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