new doc makefiles
[unix-history] / usr / src / old / dbx / main.c
CommitLineData
2a24676e 1/*
8a90f3aa
KB
2 * Copyright (c) 1983 The Regents of the University of California.
3 * All rights reserved.
4 *
6ecf3d85 5 * %sccs.include.redist.c%
2a24676e
DF
6 */
7
8#ifndef lint
9char copyright[] =
8a90f3aa 10"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
2a24676e 11 All rights reserved.\n";
8a90f3aa 12#endif /* not lint */
00102538 13
2a24676e 14#ifndef lint
6ecf3d85 15static char sccsid[] = "@(#)main.c 5.7 (Berkeley) %G%";
8a90f3aa 16#endif /* not lint */
00102538
ML
17
18/*
19 * Debugger main routine.
20 */
21
22#include "defs.h"
23#include <setjmp.h>
24#include <signal.h>
25#include <errno.h>
26#include "main.h"
9606e7b9 27#include "tree.h"
0022c355
ML
28#include "eval.h"
29#include "debug.h"
1c5b15ac 30#include "symbols.h"
00102538 31#include "scanner.h"
0022c355 32#include "keywords.h"
00102538 33#include "process.h"
2fd0f574 34#include "runtime.h"
00102538
ML
35#include "source.h"
36#include "object.h"
1c5b15ac 37#include "mappings.h"
0022c355 38#include "coredump.h"
dc0e9d50 39#include "pathnames.h"
00102538
ML
40
41#ifndef public
42
43#define isterm(file) (interactive or isatty(fileno(file)))
44
9606e7b9
DS
45#ifdef IRIS
46# include <termio.h>
39144fe1 47
9606e7b9
DS
48 typedef struct termio Ttyinfo;
49#else
50# include <sgtty.h>
51# include <fcntl.h>
52
53 typedef struct {
54 struct sgttyb sg; /* standard sgttyb structure */
55 struct tchars tc; /* terminal characters */
56 struct ltchars ltc; /* local special characters */
57 integer ldisc; /* line discipline */
58 integer local; /* TIOCLGET */
59 integer fcflags; /* fcntl(2) F_GETFL, F_SETFL */
60 } Ttyinfo;
61#endif
39144fe1 62
00102538
ML
63#endif
64
0022c355
ML
65public boolean coredump; /* true if using a core dump */
66public boolean runfirst; /* run program immediately */
67public boolean interactive; /* standard input IS a terminal */
68public boolean lexdebug; /* trace scanner return values */
69public boolean tracebpts; /* trace create/delete breakpoints */
70public boolean traceexec; /* trace execution */
71public boolean tracesyms; /* print symbols are they are read */
72public boolean traceblocks; /* trace blocks while reading symbols */
73public boolean vaddrs; /* map addresses through page tables */
9606e7b9
DS
74public boolean quiet; /* don't print heading */
75public boolean autostrip; /* strip C++ prefixes */
00102538
ML
76
77public File corefile; /* File id of core dump */
78
9606e7b9
DS
79public integer versionNumber = 4;
80
00102538
ML
81#define FIRST_TIME 0 /* initial value setjmp returns */
82
83private Boolean initdone = false; /* true if initialization done */
84private jmp_buf env; /* setjmp/longjmp data */
0022c355 85private char outbuf[BUFSIZ]; /* standard output buffer */
00102538 86private char namebuf[512]; /* possible name of object file */
00102538 87
39144fe1 88private Ttyinfo ttyinfo;
0022c355 89private String corename; /* name of core file */
39144fe1 90
00102538 91private catchintr();
9606e7b9 92private char **scanargs();
00102538
ML
93
94/*
95 * Main program.
96 */
97
98main(argc, argv)
99int argc;
100String argv[];
101{
2fd0f574 102 extern integer versionNumber;
ef9fed8e
KB
103 char **scanargs();
104
105 if (!(cmdname = rindex(*argv, '/')))
106 cmdname = *argv;
107 else
108 ++cmdname;
00102538 109
00102538
ML
110 catcherrs();
111 onsyserr(EINTR, nil);
9606e7b9
DS
112 onsyserr(EADDRINUSE, nil);
113 onsyserr(ENXIO, nil);
0022c355 114 setbuf(stdout, outbuf);
ef9fed8e 115 argv = scanargs(argc, argv);
9606e7b9
DS
116 if (not runfirst and not quiet) {
117 printheading();
118 }
119 openfiles();
00102538 120 language_init();
0022c355 121 symbols_init();
00102538 122 process_init();
31bb8678 123 optab_init();
00102538
ML
124 if (runfirst) {
125 if (setjmp(env) == FIRST_TIME) {
126 arginit();
ef9fed8e
KB
127 while (*argv)
128 newarg(*argv++);
00102538
ML
129 run();
130 /* NOTREACHED */
131 } else {
132 runfirst = false;
133 }
134 } else {
135 init();
136 }
2fd0f574
SL
137 if (setjmp(env) != FIRST_TIME) {
138 restoretty(stdout, &ttyinfo);
139 }
00102538
ML
140 signal(SIGINT, catchintr);
141 yyparse();
142 putchar('\n');
143 quit(0);
144}
145
9606e7b9
DS
146public printheading ()
147{
148 extern String date;
149
150 printf("dbx version 3.%d of %s.\nType 'help' for help.\n",
151 versionNumber, date
152 );
153 fflush(stdout);
154}
155
00102538
ML
156/*
157 * Initialize the world, including setting initial input file
158 * if the file exists.
159 */
160
161public init()
162{
163 File f;
164 String home;
165 char buf[100];
166 extern String getenv();
167
39144fe1 168 savetty(stdout, &ttyinfo);
00102538
ML
169 enterkeywords();
170 scanner_init();
171 if (not coredump and not runfirst) {
172 start(nil, nil, nil);
173 }
39144fe1
ML
174 printf("reading symbolic information ...");
175 fflush(stdout);
00102538 176 readobj(objname);
39144fe1
ML
177 printf("\n");
178 fflush(stdout);
1c5b15ac 179 if (coredump) {
0022c355
ML
180 printf("[using memory image in %s]\n", corename);
181 if (vaddrs) {
182 coredump_getkerinfo();
183 }
9606e7b9 184 getsrcpos();
2fd0f574 185 setcurfunc(whatblock(pc));
1c5b15ac 186 } else {
2fd0f574 187 setcurfunc(program);
1c5b15ac 188 }
00102538
ML
189 bpinit();
190 f = fopen(initfile, "r");
191 if (f != nil) {
192 fclose(f);
193 setinput(initfile);
194 } else {
195 home = getenv("HOME");
196 if (home != nil) {
197 sprintf(buf, "%s/%s", home, initfile);
198 f = fopen(buf, "r");
199 if (f != nil) {
200 fclose(f);
201 setinput(strdup(buf));
202 }
203 }
204 }
205 initdone = true;
206}
207
208/*
209 * Re-initialize the world, first de-allocating all storage.
210 * This is necessary when the symbol information must be re-read
211 * from the object file when it has changed.
212 *
213 * Before "forgetting" things, we save the current tracing/breakpoint
214 * information to a temp file. Then after re-creating the world,
215 * we read the temp file as commands. This isn't always the right thing;
216 * if a procedure that was being traced is deleted, an error message
217 * will be generated.
218 *
219 * If the argument vector is not nil, then this is re-initialize is being
220 * done in preparation for running the program. Since we want to process
221 * the commands in the temp file before running the program, we add the
222 * run command at the end of the temp file. In this case, reinit longjmps
223 * back to parsing rather than returning.
224 */
225
226public reinit(argv, infile, outfile)
227String *argv;
228String infile;
229String outfile;
230{
231 register Integer i;
232 String tmpfile;
233 extern String mktemp();
234
dc0e9d50 235 tmpfile = mktemp(_PATH_TMP);
00102538
ML
236 setout(tmpfile);
237 status();
0022c355 238 alias(nil, nil, nil);
00102538
ML
239 if (argv != nil) {
240 printf("run");
241 for (i = 1; argv[i] != nil; i++) {
242 printf(" %s", argv[i]);
243 }
244 if (infile != nil) {
245 printf(" < %s", infile);
246 }
247 if (outfile != nil) {
248 printf(" > %s", outfile);
249 }
250 putchar('\n');
251 }
252 unsetout();
253 bpfree();
254 objfree();
0022c355 255 symbols_init();
00102538
ML
256 process_init();
257 enterkeywords();
258 scanner_init();
259 readobj(objname);
260 bpinit();
261 fflush(stdout);
262 setinput(tmpfile);
263 unlink(tmpfile);
264 if (argv != nil) {
265 longjmp(env, 1);
266 /* NOTREACHED */
267 }
268}
269
270/*
0022c355
ML
271 * After a non-fatal error we skip the rest of the current input line, and
272 * jump back to command parsing.
00102538
ML
273 */
274
275public erecover()
276{
277 if (initdone) {
278 gobble();
279 longjmp(env, 1);
280 }
281}
282
283/*
284 * This routine is called when an interrupt occurs.
285 */
286
287private catchintr()
288{
0022c355
ML
289 if (isredirected()) {
290 fflush(stdout);
291 unsetout();
292 }
00102538
ML
293 putchar('\n');
294 longjmp(env, 1);
295}
296
297/*
298 * Scan the argument list.
299 */
300
9606e7b9 301private char **scanargs (argc, argv)
00102538
ML
302int argc;
303String argv[];
304{
ef9fed8e 305 extern char *optarg;
9606e7b9
DS
306 extern integer optind;
307 integer ch;
00102538
ML
308
309 runfirst = false;
310 interactive = false;
311 lexdebug = false;
312 tracebpts = false;
313 traceexec = false;
314 tracesyms = false;
2fd0f574 315 traceblocks = false;
0022c355 316 vaddrs = false;
9606e7b9
DS
317 quiet = false;
318 autostrip = true;
00102538
ML
319 corefile = nil;
320 coredump = true;
321 sourcepath = list_alloc();
322 list_append(list_item("."), nil, sourcepath);
ef9fed8e 323
9606e7b9 324 while ((ch = getopt(argc, argv, "I:abc:eiklnqrs")) != EOF)
ef9fed8e
KB
325 switch((char)ch) {
326 case 'I':
327 list_append(list_item(optarg), nil, sourcepath);
328 break;
9606e7b9
DS
329 case 'a':
330 autostrip = false;
331 break;
ef9fed8e
KB
332 case 'b':
333 tracebpts = true;
334 break;
335 case 'c':
336 initfile = optarg;
337 break;
338 case 'e':
339 traceexec = true;
340 break;
341 case 'i':
342 interactive = true;
343 break;
344 case 'k':
345 vaddrs = true;
346 break;
347 case 'l':
348#ifdef LEXDEBUG
349 lexdebug = true;
350#else
351 fatal("\"-l\" only applicable when compiled with LEXDEBUG");
352#endif
353 break;
354 case 'n':
355 traceblocks = true;
356 break;
9606e7b9
DS
357 case 'q':
358 quiet = true;
359 break;
ef9fed8e
KB
360 case 'r': /* run program before accepting commands */
361 runfirst = true;
00102538 362 coredump = false;
ef9fed8e
KB
363 break;
364 case 's':
365 tracesyms = true;
366 break;
367 case '?':
368 default:
369 fatal("unknown option");
00102538 370 }
ef9fed8e
KB
371 argv += optind;
372 if (*argv) {
373 objname = *argv;
ef9fed8e
KB
374 if (*++argv && coredump) {
375 corename = *argv;
376 corefile = fopen(*argv, "r");
377 if (corefile == nil)
378 coredump = false;
379 ++argv;
380 }
00102538 381 }
9606e7b9 382 if (*argv and not runfirst) {
ef9fed8e 383 fatal("extraneous argument %s", *argv);
9606e7b9
DS
384 }
385 return argv;
386}
387
388private openfiles ()
389{
390 File f;
391 char *tmp;
392
393 if (objname == nil and isatty(0)) {
00102538
ML
394 printf("enter object file name (default is `%s'): ", objname);
395 fflush(stdout);
396 gets(namebuf);
397 if (namebuf[0] != '\0') {
398 objname = namebuf;
399 }
400 }
401 f = fopen(objname, "r");
402 if (f == nil) {
403 fatal("can't read %s", objname);
404 } else {
405 fclose(f);
406 }
407 if (rindex(objname, '/') != nil) {
408 tmp = strdup(objname);
409 *(rindex(tmp, '/')) = '\0';
410 list_append(list_item(tmp), nil, sourcepath);
411 }
412 if (coredump and corefile == nil) {
0022c355 413 if (vaddrs) {
dc0e9d50 414 corename = _PATH_MEM;
ef9fed8e 415 corefile = fopen(corename, "r");
0022c355 416 if (corefile == nil) {
dc0e9d50 417 panic("can't open %s", _PATH_MEM);
0022c355
ML
418 }
419 } else {
0022c355 420 corename = "core";
ef9fed8e 421 corefile = fopen(corename, "r");
0022c355
ML
422 if (corefile == nil) {
423 coredump = false;
424 }
00102538
ML
425 }
426 }
00102538
ML
427}
428
39144fe1
ML
429/*
430 * Save/restore the state of a tty.
431 */
432
433public savetty(f, t)
434File f;
435Ttyinfo *t;
436{
9606e7b9
DS
437# ifdef IRIS
438 ioctl(fileno(f), TCGETA, t);
439# else
440 ioctl(fileno(f), TIOCGETP, &(t->sg));
441 ioctl(fileno(f), TIOCGETC, &(t->tc));
442 ioctl(fileno(f), TIOCGLTC, &(t->ltc));
443 ioctl(fileno(f), TIOCGETD, &(t->ldisc));
444 ioctl(fileno(f), TIOCLGET, &(t->local));
445 t->fcflags = fcntl(fileno(f), F_GETFL, 0);
446 if ((t->fcflags&FASYNC) != 0) {
447 /* fprintf(stderr, "[async i/o found set -- reset]\n"); */
448 t->fcflags &= ~FASYNC;
449 }
450# endif
39144fe1
ML
451}
452
453public restoretty(f, t)
454File f;
455Ttyinfo *t;
456{
9606e7b9
DS
457# ifdef IRIS
458 ioctl(fileno(f), TCSETA, t);
459# else
460 ioctl(fileno(f), TIOCSETN, &(t->sg));
461 ioctl(fileno(f), TIOCSETC, &(t->tc));
462 ioctl(fileno(f), TIOCSLTC, &(t->ltc));
463 ioctl(fileno(f), TIOCSETD, &(t->ldisc));
464 ioctl(fileno(f), TIOCLSET, &(t->local));
465 if ((t->fcflags&FASYNC) != 0) {
466 /* fprintf(stderr, "[async i/o not set]\n"); */
467 t->fcflags &= ~FASYNC;
468 }
469 (void) fcntl(fileno(f), F_SETFL, t->fcflags);
470# endif
39144fe1
ML
471}
472
00102538
ML
473/*
474 * Exit gracefully.
475 */
476
477public quit(r)
478Integer r;
479{
2fd0f574 480 pterm(process);
00102538
ML
481 exit(r);
482}