19669Slinton /* Copyright (c) 1982 Regents of the University of California */ 29669Slinton 3*16613Ssam static char sccsid[] = "@(#)main.c 1.5 5/17/83"; 49669Slinton 5*16613Ssam static char rcsid[] = "$Header: main.c,v 1.3 84/03/27 10:21:40 linton Exp $"; 6*16613Ssam 79669Slinton /* 89669Slinton * Debugger main routine. 99669Slinton */ 109669Slinton 119669Slinton #include "defs.h" 129669Slinton #include <setjmp.h> 139669Slinton #include <signal.h> 149669Slinton #include <errno.h> 159669Slinton #include "main.h" 1612483Slinton #include "symbols.h" 179669Slinton #include "scanner.h" 189669Slinton #include "process.h" 19*16613Ssam #include "runtime.h" 209669Slinton #include "source.h" 219669Slinton #include "object.h" 2212483Slinton #include "mappings.h" 239669Slinton 249669Slinton #ifndef public 259669Slinton 269669Slinton #define isterm(file) (interactive or isatty(fileno(file))) 279669Slinton 2811868Slinton #include <sgtty.h> 2911868Slinton 3011868Slinton typedef struct sgttyb Ttyinfo; 3111868Slinton 329669Slinton #endif 339669Slinton 349669Slinton public Boolean coredump; /* true if using a core dump */ 359669Slinton public Boolean runfirst; /* run program immediately */ 369669Slinton public Boolean interactive; /* standard input IS a terminal */ 379669Slinton public Boolean lexdebug; /* trace yylex return values */ 389669Slinton public Boolean tracebpts; /* trace create/delete breakpoints */ 399669Slinton public Boolean traceexec; /* trace process execution */ 409669Slinton public Boolean tracesyms; /* print symbols as their read */ 41*16613Ssam public Boolean traceblocks; /* trace blocks while reading symbols */ 429669Slinton 439669Slinton public File corefile; /* File id of core dump */ 449669Slinton 459669Slinton #define FIRST_TIME 0 /* initial value setjmp returns */ 469669Slinton 479669Slinton private Boolean initdone = false; /* true if initialization done */ 489669Slinton private jmp_buf env; /* setjmp/longjmp data */ 499669Slinton private char outbuf[BUFSIZ]; /* standard output buffer */ 509669Slinton private char namebuf[512]; /* possible name of object file */ 519669Slinton private int firstarg; /* first program argument (for -r) */ 529669Slinton 5311868Slinton private Ttyinfo ttyinfo; 5411868Slinton 559669Slinton private catchintr(); 569669Slinton 579669Slinton /* 589669Slinton * Main program. 599669Slinton */ 609669Slinton 619669Slinton main(argc, argv) 629669Slinton int argc; 639669Slinton String argv[]; 649669Slinton { 65*16613Ssam register integer i; 6611868Slinton extern String date; 67*16613Ssam extern integer versionNumber; 689669Slinton 699669Slinton cmdname = argv[0]; 709669Slinton catcherrs(); 719669Slinton onsyserr(EINTR, nil); 729669Slinton setbuf(stdout, outbuf); 73*16613Ssam printf("dbx version %d of %s.\nType 'help' for help.\n", 74*16613Ssam versionNumber, date); 7511868Slinton fflush(stdout); 769669Slinton scanargs(argc, argv); 779669Slinton language_init(); 789669Slinton process_init(); 799669Slinton if (runfirst) { 809669Slinton if (setjmp(env) == FIRST_TIME) { 819669Slinton arginit(); 829669Slinton for (i = firstarg; i < argc; i++) { 839669Slinton newarg(argv[i]); 849669Slinton } 859669Slinton run(); 869669Slinton /* NOTREACHED */ 879669Slinton } else { 889669Slinton runfirst = false; 899669Slinton } 909669Slinton } else { 919669Slinton init(); 929669Slinton } 93*16613Ssam if (setjmp(env) != FIRST_TIME) { 94*16613Ssam restoretty(stdout, &ttyinfo); 95*16613Ssam } 969669Slinton signal(SIGINT, catchintr); 979669Slinton yyparse(); 989669Slinton putchar('\n'); 999669Slinton quit(0); 1009669Slinton } 1019669Slinton 1029669Slinton /* 1039669Slinton * Initialize the world, including setting initial input file 1049669Slinton * if the file exists. 1059669Slinton */ 1069669Slinton 1079669Slinton public init() 1089669Slinton { 1099669Slinton File f; 1109669Slinton String home; 1119669Slinton char buf[100]; 1129669Slinton extern String getenv(); 1139669Slinton 11411868Slinton savetty(stdout, &ttyinfo); 1159669Slinton enterkeywords(); 1169669Slinton scanner_init(); 1179669Slinton if (not coredump and not runfirst) { 1189669Slinton start(nil, nil, nil); 1199669Slinton } 12011868Slinton printf("reading symbolic information ..."); 12111868Slinton fflush(stdout); 1229669Slinton readobj(objname); 12311868Slinton printf("\n"); 12411868Slinton fflush(stdout); 12512483Slinton if (coredump) { 126*16613Ssam setcurfunc(whatblock(pc)); 12712483Slinton } else { 128*16613Ssam setcurfunc(program); 12912483Slinton } 1309669Slinton bpinit(); 1319669Slinton f = fopen(initfile, "r"); 1329669Slinton if (f != nil) { 1339669Slinton fclose(f); 1349669Slinton setinput(initfile); 1359669Slinton } else { 1369669Slinton home = getenv("HOME"); 1379669Slinton if (home != nil) { 1389669Slinton sprintf(buf, "%s/%s", home, initfile); 1399669Slinton f = fopen(buf, "r"); 1409669Slinton if (f != nil) { 1419669Slinton fclose(f); 1429669Slinton setinput(strdup(buf)); 1439669Slinton } 1449669Slinton } 1459669Slinton } 1469669Slinton initdone = true; 1479669Slinton } 1489669Slinton 1499669Slinton /* 1509669Slinton * Re-initialize the world, first de-allocating all storage. 1519669Slinton * This is necessary when the symbol information must be re-read 1529669Slinton * from the object file when it has changed. 1539669Slinton * 1549669Slinton * Before "forgetting" things, we save the current tracing/breakpoint 1559669Slinton * information to a temp file. Then after re-creating the world, 1569669Slinton * we read the temp file as commands. This isn't always the right thing; 1579669Slinton * if a procedure that was being traced is deleted, an error message 1589669Slinton * will be generated. 1599669Slinton * 1609669Slinton * If the argument vector is not nil, then this is re-initialize is being 1619669Slinton * done in preparation for running the program. Since we want to process 1629669Slinton * the commands in the temp file before running the program, we add the 1639669Slinton * run command at the end of the temp file. In this case, reinit longjmps 1649669Slinton * back to parsing rather than returning. 1659669Slinton */ 1669669Slinton 1679669Slinton public reinit(argv, infile, outfile) 1689669Slinton String *argv; 1699669Slinton String infile; 1709669Slinton String outfile; 1719669Slinton { 1729669Slinton register Integer i; 1739669Slinton String tmpfile; 1749669Slinton extern String mktemp(); 1759669Slinton 1769669Slinton tmpfile = mktemp("/tmp/dbxXXXX"); 1779669Slinton setout(tmpfile); 1789669Slinton status(); 1799669Slinton print_alias(nil); 1809669Slinton if (argv != nil) { 1819669Slinton printf("run"); 1829669Slinton for (i = 1; argv[i] != nil; i++) { 1839669Slinton printf(" %s", argv[i]); 1849669Slinton } 1859669Slinton if (infile != nil) { 1869669Slinton printf(" < %s", infile); 1879669Slinton } 1889669Slinton if (outfile != nil) { 1899669Slinton printf(" > %s", outfile); 1909669Slinton } 1919669Slinton putchar('\n'); 1929669Slinton } 1939669Slinton unsetout(); 1949669Slinton bpfree(); 1959669Slinton objfree(); 1969669Slinton process_init(); 1979669Slinton enterkeywords(); 1989669Slinton scanner_init(); 1999669Slinton readobj(objname); 2009669Slinton bpinit(); 2019669Slinton fflush(stdout); 2029669Slinton setinput(tmpfile); 2039669Slinton unlink(tmpfile); 2049669Slinton if (argv != nil) { 2059669Slinton longjmp(env, 1); 2069669Slinton /* NOTREACHED */ 2079669Slinton } 2089669Slinton } 2099669Slinton 2109669Slinton /* 2119669Slinton * After a non-fatal error we jump back to command parsing. 2129669Slinton */ 2139669Slinton 2149669Slinton public erecover() 2159669Slinton { 2169669Slinton if (initdone) { 2179669Slinton gobble(); 2189669Slinton longjmp(env, 1); 2199669Slinton } 2209669Slinton } 2219669Slinton 2229669Slinton /* 2239669Slinton * This routine is called when an interrupt occurs. 2249669Slinton */ 2259669Slinton 2269669Slinton private catchintr() 2279669Slinton { 2289669Slinton putchar('\n'); 2299669Slinton longjmp(env, 1); 2309669Slinton } 2319669Slinton 2329669Slinton /* 2339669Slinton * Scan the argument list. 2349669Slinton */ 2359669Slinton 2369669Slinton private scanargs(argc, argv) 2379669Slinton int argc; 2389669Slinton String argv[]; 2399669Slinton { 2409669Slinton register int i, j; 2419669Slinton register Boolean foundfile; 2429669Slinton register File f; 2439669Slinton char *tmp; 2449669Slinton 2459669Slinton runfirst = false; 2469669Slinton interactive = false; 2479669Slinton lexdebug = false; 2489669Slinton tracebpts = false; 2499669Slinton traceexec = false; 2509669Slinton tracesyms = false; 251*16613Ssam traceblocks = false; 2529669Slinton foundfile = false; 2539669Slinton corefile = nil; 2549669Slinton coredump = true; 2559669Slinton sourcepath = list_alloc(); 2569669Slinton list_append(list_item("."), nil, sourcepath); 2579669Slinton i = 1; 258*16613Ssam while (i < argc and (not foundfile or corefile == nil)) { 2599669Slinton if (argv[i][0] == '-') { 2609669Slinton if (streq(argv[i], "-I")) { 2619669Slinton ++i; 2629669Slinton if (i >= argc) { 2639669Slinton fatal("missing directory for -I"); 2649669Slinton } 2659669Slinton list_append(list_item(argv[i]), nil, sourcepath); 2669669Slinton } else { 2679669Slinton for (j = 1; argv[i][j] != '\0'; j++) { 2689669Slinton setoption(argv[i][j]); 2699669Slinton } 2709669Slinton } 2719669Slinton } else if (not foundfile) { 2729669Slinton objname = argv[i]; 2739669Slinton foundfile = true; 2749669Slinton } else if (coredump and corefile == nil) { 2759669Slinton corefile = fopen(argv[i], "r"); 2769669Slinton if (corefile == nil) { 2779669Slinton coredump = false; 2789669Slinton } 2799669Slinton } 2809669Slinton ++i; 2819669Slinton } 2829669Slinton if (i < argc and not runfirst) { 2839669Slinton fatal("extraneous argument %s", argv[i]); 2849669Slinton } 2859669Slinton firstarg = i; 2869669Slinton if (not foundfile and isatty(0)) { 2879669Slinton printf("enter object file name (default is `%s'): ", objname); 2889669Slinton fflush(stdout); 2899669Slinton gets(namebuf); 2909669Slinton if (namebuf[0] != '\0') { 2919669Slinton objname = namebuf; 2929669Slinton } 2939669Slinton } 2949669Slinton f = fopen(objname, "r"); 2959669Slinton if (f == nil) { 2969669Slinton fatal("can't read %s", objname); 2979669Slinton } else { 2989669Slinton fclose(f); 2999669Slinton } 3009669Slinton if (rindex(objname, '/') != nil) { 3019669Slinton tmp = strdup(objname); 3029669Slinton *(rindex(tmp, '/')) = '\0'; 3039669Slinton list_append(list_item(tmp), nil, sourcepath); 3049669Slinton } 3059669Slinton if (coredump and corefile == nil) { 3069669Slinton corefile = fopen("core", "r"); 3079669Slinton if (corefile == nil) { 3089669Slinton coredump = false; 3099669Slinton } 3109669Slinton } 3119669Slinton } 3129669Slinton 3139669Slinton /* 3149669Slinton * Take appropriate action for recognized command argument. 3159669Slinton */ 3169669Slinton 3179669Slinton private setoption(c) 3189669Slinton char c; 3199669Slinton { 3209669Slinton switch (c) { 3219669Slinton case 'r': /* run program before accepting commands */ 3229669Slinton runfirst = true; 3239669Slinton coredump = false; 3249669Slinton break; 3259669Slinton 3269669Slinton case 'i': 3279669Slinton interactive = true; 3289669Slinton break; 3299669Slinton 3309669Slinton case 'b': 3319669Slinton tracebpts = true; 3329669Slinton break; 3339669Slinton 3349669Slinton case 'e': 3359669Slinton traceexec = true; 3369669Slinton break; 3379669Slinton 3389669Slinton case 's': 3399669Slinton tracesyms = true; 3409669Slinton break; 3419669Slinton 342*16613Ssam case 'n': 343*16613Ssam traceblocks = true; 344*16613Ssam break; 345*16613Ssam 3469669Slinton case 'l': 3479669Slinton # ifdef LEXDEBUG 3489669Slinton lexdebug = true; 3499669Slinton # else 3509669Slinton fatal("\"-l\" only applicable when compiled with LEXDEBUG"); 3519669Slinton # endif 3529669Slinton break; 3539669Slinton 3549669Slinton default: 3559669Slinton fatal("unknown option '%c'", c); 3569669Slinton } 3579669Slinton } 3589669Slinton 3599669Slinton /* 36011868Slinton * Save/restore the state of a tty. 36111868Slinton */ 36211868Slinton 36311868Slinton public savetty(f, t) 36411868Slinton File f; 36511868Slinton Ttyinfo *t; 36611868Slinton { 36711868Slinton gtty(fileno(f), t); 36811868Slinton } 36911868Slinton 37011868Slinton public restoretty(f, t) 37111868Slinton File f; 37211868Slinton Ttyinfo *t; 37311868Slinton { 37411868Slinton stty(fileno(f), t); 37511868Slinton } 37611868Slinton 37711868Slinton /* 3789669Slinton * Exit gracefully. 3799669Slinton */ 3809669Slinton 3819669Slinton public quit(r) 3829669Slinton Integer r; 3839669Slinton { 384*16613Ssam pterm(process); 3859669Slinton exit(r); 3869669Slinton } 387