xref: /csrg-svn/old/dbx/main.c (revision 16613)
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