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