make it look like kernel driver
[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 13#ifndef lint
31bb8678 14static char sccsid[] = "@(#)main.c 5.2 (Berkeley) %G%";
2a24676e 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 105 process_init();
31bb8678 106 optab_init();
00102538
ML
107 if (runfirst) {
108 if (setjmp(env) == FIRST_TIME) {
109 arginit();
110 for (i = firstarg; i < argc; i++) {
111 newarg(argv[i]);
112 }
113 run();
114 /* NOTREACHED */
115 } else {
116 runfirst = false;
117 }
118 } else {
119 init();
120 }
2fd0f574
SL
121 if (setjmp(env) != FIRST_TIME) {
122 restoretty(stdout, &ttyinfo);
123 }
00102538
ML
124 signal(SIGINT, catchintr);
125 yyparse();
126 putchar('\n');
127 quit(0);
128}
129
130/*
131 * Initialize the world, including setting initial input file
132 * if the file exists.
133 */
134
135public init()
136{
137 File f;
138 String home;
139 char buf[100];
140 extern String getenv();
141
39144fe1 142 savetty(stdout, &ttyinfo);
00102538
ML
143 enterkeywords();
144 scanner_init();
145 if (not coredump and not runfirst) {
146 start(nil, nil, nil);
147 }
39144fe1
ML
148 printf("reading symbolic information ...");
149 fflush(stdout);
00102538 150 readobj(objname);
39144fe1
ML
151 printf("\n");
152 fflush(stdout);
1c5b15ac 153 if (coredump) {
0022c355
ML
154 printf("[using memory image in %s]\n", corename);
155 if (vaddrs) {
156 coredump_getkerinfo();
157 }
2fd0f574 158 setcurfunc(whatblock(pc));
1c5b15ac 159 } else {
2fd0f574 160 setcurfunc(program);
1c5b15ac 161 }
00102538
ML
162 bpinit();
163 f = fopen(initfile, "r");
164 if (f != nil) {
165 fclose(f);
166 setinput(initfile);
167 } else {
168 home = getenv("HOME");
169 if (home != nil) {
170 sprintf(buf, "%s/%s", home, initfile);
171 f = fopen(buf, "r");
172 if (f != nil) {
173 fclose(f);
174 setinput(strdup(buf));
175 }
176 }
177 }
178 initdone = true;
179}
180
181/*
182 * Re-initialize the world, first de-allocating all storage.
183 * This is necessary when the symbol information must be re-read
184 * from the object file when it has changed.
185 *
186 * Before "forgetting" things, we save the current tracing/breakpoint
187 * information to a temp file. Then after re-creating the world,
188 * we read the temp file as commands. This isn't always the right thing;
189 * if a procedure that was being traced is deleted, an error message
190 * will be generated.
191 *
192 * If the argument vector is not nil, then this is re-initialize is being
193 * done in preparation for running the program. Since we want to process
194 * the commands in the temp file before running the program, we add the
195 * run command at the end of the temp file. In this case, reinit longjmps
196 * back to parsing rather than returning.
197 */
198
199public reinit(argv, infile, outfile)
200String *argv;
201String infile;
202String outfile;
203{
204 register Integer i;
205 String tmpfile;
206 extern String mktemp();
207
208 tmpfile = mktemp("/tmp/dbxXXXX");
209 setout(tmpfile);
210 status();
0022c355 211 alias(nil, nil, nil);
00102538
ML
212 if (argv != nil) {
213 printf("run");
214 for (i = 1; argv[i] != nil; i++) {
215 printf(" %s", argv[i]);
216 }
217 if (infile != nil) {
218 printf(" < %s", infile);
219 }
220 if (outfile != nil) {
221 printf(" > %s", outfile);
222 }
223 putchar('\n');
224 }
225 unsetout();
226 bpfree();
227 objfree();
0022c355 228 symbols_init();
00102538
ML
229 process_init();
230 enterkeywords();
231 scanner_init();
232 readobj(objname);
233 bpinit();
234 fflush(stdout);
235 setinput(tmpfile);
236 unlink(tmpfile);
237 if (argv != nil) {
238 longjmp(env, 1);
239 /* NOTREACHED */
240 }
241}
242
243/*
0022c355
ML
244 * After a non-fatal error we skip the rest of the current input line, and
245 * jump back to command parsing.
00102538
ML
246 */
247
248public erecover()
249{
250 if (initdone) {
251 gobble();
252 longjmp(env, 1);
253 }
254}
255
256/*
257 * This routine is called when an interrupt occurs.
258 */
259
260private catchintr()
261{
0022c355
ML
262 if (isredirected()) {
263 fflush(stdout);
264 unsetout();
265 }
00102538
ML
266 putchar('\n');
267 longjmp(env, 1);
268}
269
270/*
271 * Scan the argument list.
272 */
273
274private scanargs(argc, argv)
275int argc;
276String argv[];
277{
278 register int i, j;
279 register Boolean foundfile;
280 register File f;
281 char *tmp;
282
283 runfirst = false;
284 interactive = false;
285 lexdebug = false;
286 tracebpts = false;
287 traceexec = false;
288 tracesyms = false;
2fd0f574 289 traceblocks = false;
0022c355 290 vaddrs = false;
00102538
ML
291 foundfile = false;
292 corefile = nil;
293 coredump = true;
294 sourcepath = list_alloc();
295 list_append(list_item("."), nil, sourcepath);
296 i = 1;
0022c355 297 while (i < argc and (not foundfile or (coredump and corefile == nil))) {
00102538
ML
298 if (argv[i][0] == '-') {
299 if (streq(argv[i], "-I")) {
300 ++i;
301 if (i >= argc) {
302 fatal("missing directory for -I");
303 }
304 list_append(list_item(argv[i]), nil, sourcepath);
0022c355
ML
305 } else if (streq(argv[i], "-c")) {
306 ++i;
307 if (i >= argc) {
308 fatal("missing command file name for -c");
309 }
310 initfile = argv[i];
00102538
ML
311 } else {
312 for (j = 1; argv[i][j] != '\0'; j++) {
313 setoption(argv[i][j]);
314 }
315 }
316 } else if (not foundfile) {
317 objname = argv[i];
318 foundfile = true;
319 } else if (coredump and corefile == nil) {
320 corefile = fopen(argv[i], "r");
0022c355 321 corename = argv[i];
00102538
ML
322 if (corefile == nil) {
323 coredump = false;
324 }
325 }
326 ++i;
327 }
328 if (i < argc and not runfirst) {
329 fatal("extraneous argument %s", argv[i]);
330 }
331 firstarg = i;
332 if (not foundfile and isatty(0)) {
333 printf("enter object file name (default is `%s'): ", objname);
334 fflush(stdout);
335 gets(namebuf);
336 if (namebuf[0] != '\0') {
337 objname = namebuf;
338 }
339 }
340 f = fopen(objname, "r");
341 if (f == nil) {
342 fatal("can't read %s", objname);
343 } else {
344 fclose(f);
345 }
346 if (rindex(objname, '/') != nil) {
347 tmp = strdup(objname);
348 *(rindex(tmp, '/')) = '\0';
349 list_append(list_item(tmp), nil, sourcepath);
350 }
351 if (coredump and corefile == nil) {
0022c355
ML
352 if (vaddrs) {
353 corefile = fopen("/dev/mem", "r");
354 corename = "/dev/mem";
355 if (corefile == nil) {
356 panic("can't open /dev/mem");
357 }
358 } else {
359 corefile = fopen("core", "r");
360 corename = "core";
361 if (corefile == nil) {
362 coredump = false;
363 }
00102538
ML
364 }
365 }
366}
367
368/*
369 * Take appropriate action for recognized command argument.
370 */
371
372private setoption(c)
373char c;
374{
375 switch (c) {
376 case 'r': /* run program before accepting commands */
377 runfirst = true;
378 coredump = false;
379 break;
380
381 case 'i':
382 interactive = true;
383 break;
384
385 case 'b':
386 tracebpts = true;
387 break;
388
389 case 'e':
390 traceexec = true;
391 break;
392
393 case 's':
394 tracesyms = true;
395 break;
396
2fd0f574
SL
397 case 'n':
398 traceblocks = true;
399 break;
400
0022c355
ML
401 case 'k':
402 vaddrs = true;
403 break;
404
00102538 405 case 'l':
0022c355 406# ifdef LEXDEBUG
00102538 407 lexdebug = true;
0022c355
ML
408# else
409 fatal("\"-l\" only applicable when compiled with LEXDEBUG");
410# endif
00102538
ML
411 break;
412
413 default:
414 fatal("unknown option '%c'", c);
415 }
416}
417
39144fe1
ML
418/*
419 * Save/restore the state of a tty.
420 */
421
422public savetty(f, t)
423File f;
424Ttyinfo *t;
425{
d582c82a
RC
426 ioctl(fileno(f), TIOCGETP, &(t->sg));
427 ioctl(fileno(f), TIOCGETC, &(t->tc));
428 ioctl(fileno(f), TIOCGLTC, &(t->ltc));
429 ioctl(fileno(f), TIOCGETD, &(t->ldisc));
430 ioctl(fileno(f), TIOCLGET, &(t->local));
431 t->fcflags = fcntl(fileno(f), F_GETFL, 0);
39144fe1
ML
432}
433
434public restoretty(f, t)
435File f;
436Ttyinfo *t;
437{
d582c82a
RC
438 ioctl(fileno(f), TIOCSETN, &(t->sg));
439 ioctl(fileno(f), TIOCSETC, &(t->tc));
440 ioctl(fileno(f), TIOCSLTC, &(t->ltc));
441 ioctl(fileno(f), TIOCSETD, &(t->ldisc));
442 ioctl(fileno(f), TIOCLSET, &(t->local));
443 (void) fcntl(fileno(f), F_SETFL, t->fcflags);
39144fe1
ML
444}
445
00102538
ML
446/*
447 * Exit gracefully.
448 */
449
450public quit(r)
451Integer r;
452{
2fd0f574 453 pterm(process);
00102538
ML
454 exit(r);
455}