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