xref: /csrg-svn/old/dbx/main.c (revision 17194)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static	char sccsid[] = "@(#)main.c	1.9 (Berkeley) 09/17/84";
4 
5 /*
6  * Debugger main routine.
7  */
8 
9 #include "defs.h"
10 #include <setjmp.h>
11 #include <signal.h>
12 #include <errno.h>
13 #include "main.h"
14 #include "symbols.h"
15 #include "scanner.h"
16 #include "process.h"
17 #include "runtime.h"
18 #include "source.h"
19 #include "object.h"
20 #include "mappings.h"
21 
22 #ifndef public
23 
24 #define isterm(file)	(interactive or isatty(fileno(file)))
25 
26 #include <sgtty.h>
27 
28 typedef struct sgttyb Ttyinfo;
29 
30 #endif
31 
32 public Boolean coredump;		/* true if using a core dump */
33 public Boolean runfirst;		/* run program immediately */
34 public Boolean interactive;		/* standard input IS a terminal */
35 public Boolean lexdebug;		/* trace yylex return values */
36 public Boolean tracebpts;		/* trace create/delete breakpoints */
37 public Boolean traceexec;		/* trace process execution */
38 public Boolean tracesyms;		/* print symbols as their read */
39 public Boolean traceblocks;		/* trace blocks while reading symbols */
40 
41 public File corefile;			/* File id of core dump */
42 
43 #define FIRST_TIME 0			/* initial value setjmp returns */
44 
45 private Boolean initdone = false;	/* true if initialization done */
46 private jmp_buf env;			/* setjmp/longjmp data */
47 private char namebuf[512];		/* possible name of object file */
48 private int firstarg;			/* first program argument (for -r) */
49 
50 private Ttyinfo ttyinfo;
51 
52 private catchintr();
53 
54 /*
55  * Main program.
56  */
57 
58 main(argc, argv)
59 int argc;
60 String argv[];
61 {
62     register integer i;
63     extern String date;
64     extern integer versionNumber;
65 
66     cmdname = argv[0];
67     catcherrs();
68     onsyserr(EINTR, nil);
69     setlinebuf(stderr);
70     printf("dbx version %d of %s.\nType 'help' for help.\n",
71 	versionNumber, date);
72     fflush(stdout);
73     scanargs(argc, argv);
74     language_init();
75     process_init();
76     if (runfirst) {
77 	if (setjmp(env) == FIRST_TIME) {
78 	    arginit();
79 	    for (i = firstarg; i < argc; i++) {
80 		newarg(argv[i]);
81 	    }
82 	    run();
83 	    /* NOTREACHED */
84 	} else {
85 	    runfirst = false;
86 	}
87     } else {
88 	init();
89     }
90     if (setjmp(env) != FIRST_TIME) {
91 	restoretty(stdout, &ttyinfo);
92     }
93     signal(SIGINT, catchintr);
94     if (isterm(stdin)) {
95 	    printf("(%s) ", cmdname);
96 	    fflush(stdout);
97     }
98     endshellmode();		/* after an error longjmp */
99     startaliasing();
100     yyparse();
101     putchar('\n');
102     quit(0);
103 }
104 
105 /*
106  * Initialize the world, including setting initial input file
107  * if the file exists.
108  */
109 
110 public init()
111 {
112     File f;
113     String home;
114     char buf[100];
115     extern String getenv();
116 
117     savetty(stdout, &ttyinfo);
118     enterkeywords();
119     scanner_init();
120     if (not coredump and not runfirst) {
121 	start(nil, nil, nil);
122     }
123     printf("reading symbolic information ...");
124     fflush(stdout);
125     readobj(objname);
126     printf("\n");
127     fflush(stdout);
128     if (coredump) {
129 	setcurfunc(whatblock(pc));
130     } else {
131 	setcurfunc(program);
132     }
133     bpinit();
134     f = fopen(initfile, "r");
135     if (f != nil) {
136 	fclose(f);
137 	setinput(initfile);
138     } else {
139 	home = getenv("HOME");
140 	if (home != nil) {
141 	    sprintf(buf, "%s/%s", home, initfile);
142 	    f = fopen(buf, "r");
143 	    if (f != nil) {
144 		fclose(f);
145 		setinput(strdup(buf));
146 	    }
147 	}
148     }
149     initdone = true;
150 }
151 
152 /*
153  * Re-initialize the world, first de-allocating all storage.
154  * This is necessary when the symbol information must be re-read
155  * from the object file when it has changed.
156  *
157  * Before "forgetting" things, we save the current tracing/breakpoint
158  * information to a temp file.  Then after re-creating the world,
159  * we read the temp file as commands.  This isn't always the right thing;
160  * if a procedure that was being traced is deleted, an error message
161  * will be generated.
162  *
163  * If the argument vector is not nil, then this is re-initialize is being
164  * done in preparation for running the program.  Since we want to process
165  * the commands in the temp file before running the program, we add the
166  * run command at the end of the temp file.  In this case, reinit longjmps
167  * back to parsing rather than returning.
168  */
169 
170 public reinit(argv, infile, outfile)
171 String *argv;
172 String infile;
173 String outfile;
174 {
175     register Integer i;
176     String tmpfile;
177     extern String mktemp();
178 
179     tmpfile = mktemp("/tmp/dbxXXXX");
180     setout(tmpfile);
181     status();
182     print_alias(nil);
183     if (argv != nil) {
184 	printf("run");
185 	for (i = 1; argv[i] != nil; i++) {
186 	    printf(" %s", argv[i]);
187 	}
188 	if (infile != nil) {
189 	    printf(" < %s", infile);
190 	}
191 	if (outfile != nil) {
192 	    printf(" > %s", outfile);
193 	}
194 	putchar('\n');
195     }
196     unsetout();
197     bpfree();
198     objfree();
199     process_init();
200     enterkeywords();
201     scanner_init();
202     readobj(objname);
203     bpinit();
204     fflush(stdout);
205     setinput(tmpfile);
206     unlink(tmpfile);
207     if (argv != nil) {
208 	longjmp(env, 1);
209 	/* NOTREACHED */
210     }
211 }
212 
213 /*
214  * After a non-fatal error we jump back to command parsing.
215  */
216 
217 public erecover()
218 {
219     if (initdone) {
220 	gobble();
221 	longjmp(env, 1);
222     }
223 }
224 
225 /*
226  * This routine is called when an interrupt occurs.
227  */
228 
229 private catchintr()
230 {
231     putchar('\n');
232     longjmp(env, 1);
233 }
234 
235 /*
236  * Scan the argument list.
237  */
238 
239 private scanargs(argc, argv)
240 int argc;
241 String argv[];
242 {
243     register int i, j;
244     register Boolean foundfile;
245     register File f;
246     char *tmp;
247 
248     runfirst = false;
249     interactive = false;
250     lexdebug = false;
251     tracebpts = false;
252     traceexec = false;
253     tracesyms = false;
254     traceblocks = false;
255     foundfile = false;
256     corefile = nil;
257     coredump = true;
258     sourcepath = list_alloc();
259     list_append(list_item("."), nil, sourcepath);
260     i = 1;
261     while (i < argc and (not foundfile or corefile == nil)) {
262 	if (argv[i][0] == '-') {
263 	    if (streq(argv[i], "-I")) {
264 		++i;
265 		if (i >= argc) {
266 		    fatal("missing directory for -I");
267 		}
268 		list_append(list_item(argv[i]), nil, sourcepath);
269 	    } else {
270 		for (j = 1; argv[i][j] != '\0'; j++) {
271 		    setoption(argv[i][j]);
272 		}
273 	    }
274 	} else if (not foundfile) {
275 	    objname = argv[i];
276 	    foundfile = true;
277 	} else if (coredump and corefile == nil) {
278 	    corefile = fopen(argv[i], "r");
279 	    if (corefile == nil) {
280 		coredump = false;
281 	    }
282 	}
283 	++i;
284     }
285     if (i < argc and not runfirst) {
286 	fatal("extraneous argument %s", argv[i]);
287     }
288     firstarg = i;
289     if (not foundfile and isatty(0)) {
290 	printf("enter object file name (default is `%s'): ", objname);
291 	fflush(stdout);
292 	gets(namebuf);
293 	if (namebuf[0] != '\0') {
294 	    objname = namebuf;
295 	}
296     }
297     f = fopen(objname, "r");
298     if (f == nil) {
299 	fatal("can't read %s", objname);
300     } else {
301 	fclose(f);
302     }
303     if (rindex(objname, '/') != nil) {
304 	tmp = strdup(objname);
305 	*(rindex(tmp, '/')) = '\0';
306 	list_append(list_item(tmp), nil, sourcepath);
307     }
308     if (coredump and corefile == nil) {
309 	corefile = fopen("core", "r");
310 	if (corefile == nil) {
311 	    coredump = false;
312 	}
313     }
314 }
315 
316 /*
317  * Take appropriate action for recognized command argument.
318  */
319 
320 private setoption(c)
321 char c;
322 {
323     switch (c) {
324 	case 'r':   /* run program before accepting commands */
325 	    runfirst = true;
326 	    coredump = false;
327 	    break;
328 
329 	case 'i':
330 	    interactive = true;
331 	    break;
332 
333 	case 'b':
334 	    tracebpts = true;
335 	    break;
336 
337 	case 'e':
338 	    traceexec = true;
339 	    break;
340 
341 	case 's':
342 	    tracesyms = true;
343 	    break;
344 
345 	case 'n':
346 	    traceblocks = true;
347 	    break;
348 
349 	case 'l':
350 		lexdebug = true;
351 	    break;
352 
353 	default:
354 	    fatal("unknown option '%c'", c);
355     }
356 }
357 
358 /*
359  * Save/restore the state of a tty.
360  */
361 
362 public savetty(f, t)
363 File f;
364 Ttyinfo *t;
365 {
366     ioctl(fileno(f), TIOCGETP, t);
367 }
368 
369 public restoretty(f, t)
370 File f;
371 Ttyinfo *t;
372 {
373     ioctl(fileno(f), TIOCSETN, t);
374 }
375 
376 /*
377  * Exit gracefully.
378  */
379 
380 public quit(r)
381 Integer r;
382 {
383     pterm(process);
384     exit(r);
385 }
386