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