19669Slinton /* Copyright (c) 1982 Regents of the University of California */ 29669Slinton 3*16925Ssam static char sccsid[] = "@(#)main.c 1.8 (Berkeley) 08/12/84"; 49669Slinton 59669Slinton /* 69669Slinton * Debugger main routine. 79669Slinton */ 89669Slinton 99669Slinton #include "defs.h" 109669Slinton #include <setjmp.h> 119669Slinton #include <signal.h> 129669Slinton #include <errno.h> 139669Slinton #include "main.h" 1412483Slinton #include "symbols.h" 159669Slinton #include "scanner.h" 169669Slinton #include "process.h" 1716613Ssam #include "runtime.h" 189669Slinton #include "source.h" 199669Slinton #include "object.h" 2012483Slinton #include "mappings.h" 219669Slinton 229669Slinton #ifndef public 239669Slinton 249669Slinton #define isterm(file) (interactive or isatty(fileno(file))) 259669Slinton 2611868Slinton #include <sgtty.h> 2711868Slinton 2811868Slinton typedef struct sgttyb Ttyinfo; 2911868Slinton 309669Slinton #endif 319669Slinton 329669Slinton public Boolean coredump; /* true if using a core dump */ 339669Slinton public Boolean runfirst; /* run program immediately */ 349669Slinton public Boolean interactive; /* standard input IS a terminal */ 359669Slinton public Boolean lexdebug; /* trace yylex return values */ 369669Slinton public Boolean tracebpts; /* trace create/delete breakpoints */ 379669Slinton public Boolean traceexec; /* trace process execution */ 389669Slinton public Boolean tracesyms; /* print symbols as their read */ 3916613Ssam public Boolean traceblocks; /* trace blocks while reading symbols */ 409669Slinton 419669Slinton public File corefile; /* File id of core dump */ 429669Slinton 439669Slinton #define FIRST_TIME 0 /* initial value setjmp returns */ 449669Slinton 459669Slinton private Boolean initdone = false; /* true if initialization done */ 469669Slinton private jmp_buf env; /* setjmp/longjmp data */ 479669Slinton private char outbuf[BUFSIZ]; /* standard output buffer */ 489669Slinton private char namebuf[512]; /* possible name of object file */ 499669Slinton private int firstarg; /* first program argument (for -r) */ 509669Slinton 5111868Slinton private Ttyinfo ttyinfo; 5211868Slinton 539669Slinton private catchintr(); 549669Slinton 559669Slinton /* 569669Slinton * Main program. 579669Slinton */ 589669Slinton 599669Slinton main(argc, argv) 609669Slinton int argc; 619669Slinton String argv[]; 629669Slinton { 6316613Ssam register integer i; 6411868Slinton extern String date; 6516613Ssam extern integer versionNumber; 669669Slinton 679669Slinton cmdname = argv[0]; 689669Slinton catcherrs(); 699669Slinton onsyserr(EINTR, nil); 709669Slinton setbuf(stdout, outbuf); 71*16925Ssam setlinebuf(stderr); 7216613Ssam printf("dbx version %d of %s.\nType 'help' for help.\n", 7316613Ssam versionNumber, date); 7411868Slinton fflush(stdout); 759669Slinton scanargs(argc, argv); 769669Slinton language_init(); 779669Slinton process_init(); 789669Slinton if (runfirst) { 799669Slinton if (setjmp(env) == FIRST_TIME) { 809669Slinton arginit(); 819669Slinton for (i = firstarg; i < argc; i++) { 829669Slinton newarg(argv[i]); 839669Slinton } 849669Slinton run(); 859669Slinton /* NOTREACHED */ 869669Slinton } else { 879669Slinton runfirst = false; 889669Slinton } 899669Slinton } else { 909669Slinton init(); 919669Slinton } 9216613Ssam if (setjmp(env) != FIRST_TIME) { 9316613Ssam restoretty(stdout, &ttyinfo); 9416613Ssam } 959669Slinton signal(SIGINT, catchintr); 96*16925Ssam if (isterm(stdin)) { 97*16925Ssam printf("(%s) ", cmdname); 98*16925Ssam fflush(stdout); 99*16925Ssam } 100*16925Ssam endshellmode(); /* after an error longjmp */ 101*16925Ssam startaliasing(); 1029669Slinton yyparse(); 1039669Slinton putchar('\n'); 1049669Slinton quit(0); 1059669Slinton } 1069669Slinton 1079669Slinton /* 1089669Slinton * Initialize the world, including setting initial input file 1099669Slinton * if the file exists. 1109669Slinton */ 1119669Slinton 1129669Slinton public init() 1139669Slinton { 1149669Slinton File f; 1159669Slinton String home; 1169669Slinton char buf[100]; 1179669Slinton extern String getenv(); 1189669Slinton 11911868Slinton savetty(stdout, &ttyinfo); 1209669Slinton enterkeywords(); 1219669Slinton scanner_init(); 1229669Slinton if (not coredump and not runfirst) { 1239669Slinton start(nil, nil, nil); 1249669Slinton } 12511868Slinton printf("reading symbolic information ..."); 12611868Slinton fflush(stdout); 1279669Slinton readobj(objname); 12811868Slinton printf("\n"); 12911868Slinton fflush(stdout); 13012483Slinton if (coredump) { 13116613Ssam setcurfunc(whatblock(pc)); 13212483Slinton } else { 13316613Ssam setcurfunc(program); 13412483Slinton } 1359669Slinton bpinit(); 1369669Slinton f = fopen(initfile, "r"); 1379669Slinton if (f != nil) { 1389669Slinton fclose(f); 1399669Slinton setinput(initfile); 1409669Slinton } else { 1419669Slinton home = getenv("HOME"); 1429669Slinton if (home != nil) { 1439669Slinton sprintf(buf, "%s/%s", home, initfile); 1449669Slinton f = fopen(buf, "r"); 1459669Slinton if (f != nil) { 1469669Slinton fclose(f); 1479669Slinton setinput(strdup(buf)); 1489669Slinton } 1499669Slinton } 1509669Slinton } 1519669Slinton initdone = true; 1529669Slinton } 1539669Slinton 1549669Slinton /* 1559669Slinton * Re-initialize the world, first de-allocating all storage. 1569669Slinton * This is necessary when the symbol information must be re-read 1579669Slinton * from the object file when it has changed. 1589669Slinton * 1599669Slinton * Before "forgetting" things, we save the current tracing/breakpoint 1609669Slinton * information to a temp file. Then after re-creating the world, 1619669Slinton * we read the temp file as commands. This isn't always the right thing; 1629669Slinton * if a procedure that was being traced is deleted, an error message 1639669Slinton * will be generated. 1649669Slinton * 1659669Slinton * If the argument vector is not nil, then this is re-initialize is being 1669669Slinton * done in preparation for running the program. Since we want to process 1679669Slinton * the commands in the temp file before running the program, we add the 1689669Slinton * run command at the end of the temp file. In this case, reinit longjmps 1699669Slinton * back to parsing rather than returning. 1709669Slinton */ 1719669Slinton 1729669Slinton public reinit(argv, infile, outfile) 1739669Slinton String *argv; 1749669Slinton String infile; 1759669Slinton String outfile; 1769669Slinton { 1779669Slinton register Integer i; 1789669Slinton String tmpfile; 1799669Slinton extern String mktemp(); 1809669Slinton 1819669Slinton tmpfile = mktemp("/tmp/dbxXXXX"); 1829669Slinton setout(tmpfile); 1839669Slinton status(); 1849669Slinton print_alias(nil); 1859669Slinton if (argv != nil) { 1869669Slinton printf("run"); 1879669Slinton for (i = 1; argv[i] != nil; i++) { 1889669Slinton printf(" %s", argv[i]); 1899669Slinton } 1909669Slinton if (infile != nil) { 1919669Slinton printf(" < %s", infile); 1929669Slinton } 1939669Slinton if (outfile != nil) { 1949669Slinton printf(" > %s", outfile); 1959669Slinton } 1969669Slinton putchar('\n'); 1979669Slinton } 1989669Slinton unsetout(); 1999669Slinton bpfree(); 2009669Slinton objfree(); 2019669Slinton process_init(); 2029669Slinton enterkeywords(); 2039669Slinton scanner_init(); 2049669Slinton readobj(objname); 2059669Slinton bpinit(); 2069669Slinton fflush(stdout); 2079669Slinton setinput(tmpfile); 2089669Slinton unlink(tmpfile); 2099669Slinton if (argv != nil) { 2109669Slinton longjmp(env, 1); 2119669Slinton /* NOTREACHED */ 2129669Slinton } 2139669Slinton } 2149669Slinton 2159669Slinton /* 2169669Slinton * After a non-fatal error we jump back to command parsing. 2179669Slinton */ 2189669Slinton 2199669Slinton public erecover() 2209669Slinton { 2219669Slinton if (initdone) { 2229669Slinton gobble(); 2239669Slinton longjmp(env, 1); 2249669Slinton } 2259669Slinton } 2269669Slinton 2279669Slinton /* 2289669Slinton * This routine is called when an interrupt occurs. 2299669Slinton */ 2309669Slinton 2319669Slinton private catchintr() 2329669Slinton { 2339669Slinton putchar('\n'); 2349669Slinton longjmp(env, 1); 2359669Slinton } 2369669Slinton 2379669Slinton /* 2389669Slinton * Scan the argument list. 2399669Slinton */ 2409669Slinton 2419669Slinton private scanargs(argc, argv) 2429669Slinton int argc; 2439669Slinton String argv[]; 2449669Slinton { 2459669Slinton register int i, j; 2469669Slinton register Boolean foundfile; 2479669Slinton register File f; 2489669Slinton char *tmp; 2499669Slinton 2509669Slinton runfirst = false; 2519669Slinton interactive = false; 2529669Slinton lexdebug = false; 2539669Slinton tracebpts = false; 2549669Slinton traceexec = false; 2559669Slinton tracesyms = false; 25616613Ssam traceblocks = false; 2579669Slinton foundfile = false; 2589669Slinton corefile = nil; 2599669Slinton coredump = true; 2609669Slinton sourcepath = list_alloc(); 2619669Slinton list_append(list_item("."), nil, sourcepath); 2629669Slinton i = 1; 26316613Ssam while (i < argc and (not foundfile or corefile == nil)) { 2649669Slinton if (argv[i][0] == '-') { 2659669Slinton if (streq(argv[i], "-I")) { 2669669Slinton ++i; 2679669Slinton if (i >= argc) { 2689669Slinton fatal("missing directory for -I"); 2699669Slinton } 2709669Slinton list_append(list_item(argv[i]), nil, sourcepath); 2719669Slinton } else { 2729669Slinton for (j = 1; argv[i][j] != '\0'; j++) { 2739669Slinton setoption(argv[i][j]); 2749669Slinton } 2759669Slinton } 2769669Slinton } else if (not foundfile) { 2779669Slinton objname = argv[i]; 2789669Slinton foundfile = true; 2799669Slinton } else if (coredump and corefile == nil) { 2809669Slinton corefile = fopen(argv[i], "r"); 2819669Slinton if (corefile == nil) { 2829669Slinton coredump = false; 2839669Slinton } 2849669Slinton } 2859669Slinton ++i; 2869669Slinton } 2879669Slinton if (i < argc and not runfirst) { 2889669Slinton fatal("extraneous argument %s", argv[i]); 2899669Slinton } 2909669Slinton firstarg = i; 2919669Slinton if (not foundfile and isatty(0)) { 2929669Slinton printf("enter object file name (default is `%s'): ", objname); 2939669Slinton fflush(stdout); 2949669Slinton gets(namebuf); 2959669Slinton if (namebuf[0] != '\0') { 2969669Slinton objname = namebuf; 2979669Slinton } 2989669Slinton } 2999669Slinton f = fopen(objname, "r"); 3009669Slinton if (f == nil) { 3019669Slinton fatal("can't read %s", objname); 3029669Slinton } else { 3039669Slinton fclose(f); 3049669Slinton } 3059669Slinton if (rindex(objname, '/') != nil) { 3069669Slinton tmp = strdup(objname); 3079669Slinton *(rindex(tmp, '/')) = '\0'; 3089669Slinton list_append(list_item(tmp), nil, sourcepath); 3099669Slinton } 3109669Slinton if (coredump and corefile == nil) { 3119669Slinton corefile = fopen("core", "r"); 3129669Slinton if (corefile == nil) { 3139669Slinton coredump = false; 3149669Slinton } 3159669Slinton } 3169669Slinton } 3179669Slinton 3189669Slinton /* 3199669Slinton * Take appropriate action for recognized command argument. 3209669Slinton */ 3219669Slinton 3229669Slinton private setoption(c) 3239669Slinton char c; 3249669Slinton { 3259669Slinton switch (c) { 3269669Slinton case 'r': /* run program before accepting commands */ 3279669Slinton runfirst = true; 3289669Slinton coredump = false; 3299669Slinton break; 3309669Slinton 3319669Slinton case 'i': 3329669Slinton interactive = true; 3339669Slinton break; 3349669Slinton 3359669Slinton case 'b': 3369669Slinton tracebpts = true; 3379669Slinton break; 3389669Slinton 3399669Slinton case 'e': 3409669Slinton traceexec = true; 3419669Slinton break; 3429669Slinton 3439669Slinton case 's': 3449669Slinton tracesyms = true; 3459669Slinton break; 3469669Slinton 34716613Ssam case 'n': 34816613Ssam traceblocks = true; 34916613Ssam break; 35016613Ssam 3519669Slinton case 'l': 3529669Slinton lexdebug = true; 3539669Slinton break; 3549669Slinton 3559669Slinton default: 3569669Slinton fatal("unknown option '%c'", c); 3579669Slinton } 3589669Slinton } 3599669Slinton 3609669Slinton /* 36111868Slinton * Save/restore the state of a tty. 36211868Slinton */ 36311868Slinton 36411868Slinton public savetty(f, t) 36511868Slinton File f; 36611868Slinton Ttyinfo *t; 36711868Slinton { 368*16925Ssam ioctl(fileno(f), TIOCGETP, t); 36911868Slinton } 37011868Slinton 37111868Slinton public restoretty(f, t) 37211868Slinton File f; 37311868Slinton Ttyinfo *t; 37411868Slinton { 375*16925Ssam ioctl(fileno(f), TIOCSETN, t); 37611868Slinton } 37711868Slinton 37811868Slinton /* 3799669Slinton * Exit gracefully. 3809669Slinton */ 3819669Slinton 3829669Slinton public quit(r) 3839669Slinton Integer r; 3849669Slinton { 38516613Ssam pterm(process); 3869669Slinton exit(r); 3879669Slinton } 388