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