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