xref: /csrg-svn/old/dbx/main.c (revision 12483)
19669Slinton /* Copyright (c) 1982 Regents of the University of California */
29669Slinton 
3*12483Slinton static char sccsid[] = "@(#)main.c 1.5 05/17/83";
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"
14*12483Slinton #include "symbols.h"
159669Slinton #include "scanner.h"
169669Slinton #include "process.h"
179669Slinton #include "source.h"
189669Slinton #include "object.h"
19*12483Slinton #include "mappings.h"
209669Slinton 
219669Slinton #ifndef public
229669Slinton 
239669Slinton #define isterm(file)	(interactive or isatty(fileno(file)))
249669Slinton 
2511868Slinton #include <sgtty.h>
2611868Slinton 
2711868Slinton typedef struct sgttyb Ttyinfo;
2811868Slinton 
299669Slinton #endif
309669Slinton 
319669Slinton public Boolean coredump;		/* true if using a core dump */
329669Slinton public Boolean runfirst;		/* run program immediately */
339669Slinton public Boolean interactive;		/* standard input IS a terminal */
349669Slinton public Boolean lexdebug;		/* trace yylex return values */
359669Slinton public Boolean tracebpts;		/* trace create/delete breakpoints */
369669Slinton public Boolean traceexec;		/* trace process execution */
379669Slinton public Boolean tracesyms;		/* print symbols as their read */
389669Slinton 
399669Slinton public File corefile;			/* File id of core dump */
409669Slinton 
419669Slinton #define FIRST_TIME 0			/* initial value setjmp returns */
429669Slinton 
439669Slinton private Boolean initdone = false;	/* true if initialization done */
449669Slinton private jmp_buf env;			/* setjmp/longjmp data */
459669Slinton private char outbuf[BUFSIZ];		/* standard output buffer */
469669Slinton private char namebuf[512];		/* possible name of object file */
479669Slinton private int firstarg;			/* first program argument (for -r) */
489669Slinton 
4911868Slinton private Ttyinfo ttyinfo;
5011868Slinton 
519669Slinton private catchintr();
529669Slinton 
539669Slinton /*
549669Slinton  * Main program.
559669Slinton  */
569669Slinton 
579669Slinton main(argc, argv)
589669Slinton int argc;
599669Slinton String argv[];
609669Slinton {
619669Slinton     register Integer i;
6211868Slinton     extern String date;
639669Slinton 
649669Slinton     cmdname = argv[0];
659669Slinton     catcherrs();
669669Slinton     onsyserr(EINTR, nil);
679669Slinton     setbuf(stdout, outbuf);
6811868Slinton     printf("dbx version of %s.\nType 'help' for help.\n", date);
6911868Slinton     fflush(stdout);
709669Slinton     scanargs(argc, argv);
719669Slinton     language_init();
729669Slinton     process_init();
739669Slinton     if (runfirst) {
749669Slinton 	if (setjmp(env) == FIRST_TIME) {
759669Slinton 	    arginit();
769669Slinton 	    for (i = firstarg; i < argc; i++) {
779669Slinton 		newarg(argv[i]);
789669Slinton 	    }
799669Slinton 	    run();
809669Slinton 	    /* NOTREACHED */
819669Slinton 	} else {
829669Slinton 	    runfirst = false;
839669Slinton 	}
849669Slinton     } else {
859669Slinton 	init();
869669Slinton     }
879669Slinton     setjmp(env);
8811868Slinton     restoretty(stdout, &ttyinfo);
899669Slinton     signal(SIGINT, catchintr);
909669Slinton     yyparse();
919669Slinton     putchar('\n');
929669Slinton     quit(0);
939669Slinton }
949669Slinton 
959669Slinton /*
969669Slinton  * Initialize the world, including setting initial input file
979669Slinton  * if the file exists.
989669Slinton  */
999669Slinton 
1009669Slinton public init()
1019669Slinton {
1029669Slinton     File f;
1039669Slinton     String home;
1049669Slinton     char buf[100];
1059669Slinton     extern String getenv();
1069669Slinton 
10711868Slinton     savetty(stdout, &ttyinfo);
1089669Slinton     enterkeywords();
1099669Slinton     scanner_init();
1109669Slinton     if (not coredump and not runfirst) {
1119669Slinton 	start(nil, nil, nil);
1129669Slinton     }
11311868Slinton     printf("reading symbolic information ...");
11411868Slinton     fflush(stdout);
1159669Slinton     readobj(objname);
11611868Slinton     printf("\n");
11711868Slinton     fflush(stdout);
118*12483Slinton     if (coredump) {
119*12483Slinton 	curfunc = whatblock(pc);
120*12483Slinton     } else {
121*12483Slinton 	curfunc = program;
122*12483Slinton     }
1239669Slinton     bpinit();
1249669Slinton     f = fopen(initfile, "r");
1259669Slinton     if (f != nil) {
1269669Slinton 	fclose(f);
1279669Slinton 	setinput(initfile);
1289669Slinton     } else {
1299669Slinton 	home = getenv("HOME");
1309669Slinton 	if (home != nil) {
1319669Slinton 	    sprintf(buf, "%s/%s", home, initfile);
1329669Slinton 	    f = fopen(buf, "r");
1339669Slinton 	    if (f != nil) {
1349669Slinton 		fclose(f);
1359669Slinton 		setinput(strdup(buf));
1369669Slinton 	    }
1379669Slinton 	}
1389669Slinton     }
1399669Slinton     initdone = true;
1409669Slinton }
1419669Slinton 
1429669Slinton /*
1439669Slinton  * Re-initialize the world, first de-allocating all storage.
1449669Slinton  * This is necessary when the symbol information must be re-read
1459669Slinton  * from the object file when it has changed.
1469669Slinton  *
1479669Slinton  * Before "forgetting" things, we save the current tracing/breakpoint
1489669Slinton  * information to a temp file.  Then after re-creating the world,
1499669Slinton  * we read the temp file as commands.  This isn't always the right thing;
1509669Slinton  * if a procedure that was being traced is deleted, an error message
1519669Slinton  * will be generated.
1529669Slinton  *
1539669Slinton  * If the argument vector is not nil, then this is re-initialize is being
1549669Slinton  * done in preparation for running the program.  Since we want to process
1559669Slinton  * the commands in the temp file before running the program, we add the
1569669Slinton  * run command at the end of the temp file.  In this case, reinit longjmps
1579669Slinton  * back to parsing rather than returning.
1589669Slinton  */
1599669Slinton 
1609669Slinton public reinit(argv, infile, outfile)
1619669Slinton String *argv;
1629669Slinton String infile;
1639669Slinton String outfile;
1649669Slinton {
1659669Slinton     register Integer i;
1669669Slinton     String tmpfile;
1679669Slinton     extern String mktemp();
1689669Slinton 
1699669Slinton     tmpfile = mktemp("/tmp/dbxXXXX");
1709669Slinton     setout(tmpfile);
1719669Slinton     status();
1729669Slinton     print_alias(nil);
1739669Slinton     if (argv != nil) {
1749669Slinton 	printf("run");
1759669Slinton 	for (i = 1; argv[i] != nil; i++) {
1769669Slinton 	    printf(" %s", argv[i]);
1779669Slinton 	}
1789669Slinton 	if (infile != nil) {
1799669Slinton 	    printf(" < %s", infile);
1809669Slinton 	}
1819669Slinton 	if (outfile != nil) {
1829669Slinton 	    printf(" > %s", outfile);
1839669Slinton 	}
1849669Slinton 	putchar('\n');
1859669Slinton     }
1869669Slinton     unsetout();
1879669Slinton     bpfree();
1889669Slinton     objfree();
1899669Slinton     process_init();
1909669Slinton     enterkeywords();
1919669Slinton     scanner_init();
1929669Slinton     readobj(objname);
1939669Slinton     bpinit();
1949669Slinton     fflush(stdout);
1959669Slinton     setinput(tmpfile);
1969669Slinton     unlink(tmpfile);
1979669Slinton     if (argv != nil) {
1989669Slinton 	longjmp(env, 1);
1999669Slinton 	/* NOTREACHED */
2009669Slinton     }
2019669Slinton }
2029669Slinton 
2039669Slinton /*
2049669Slinton  * After a non-fatal error we jump back to command parsing.
2059669Slinton  */
2069669Slinton 
2079669Slinton public erecover()
2089669Slinton {
2099669Slinton     if (initdone) {
2109669Slinton 	gobble();
2119669Slinton 	longjmp(env, 1);
2129669Slinton     }
2139669Slinton }
2149669Slinton 
2159669Slinton /*
2169669Slinton  * This routine is called when an interrupt occurs.
2179669Slinton  */
2189669Slinton 
2199669Slinton private catchintr()
2209669Slinton {
2219669Slinton     putchar('\n');
2229669Slinton     longjmp(env, 1);
2239669Slinton }
2249669Slinton 
2259669Slinton /*
2269669Slinton  * Scan the argument list.
2279669Slinton  */
2289669Slinton 
2299669Slinton private scanargs(argc, argv)
2309669Slinton int argc;
2319669Slinton String argv[];
2329669Slinton {
2339669Slinton     register int i, j;
2349669Slinton     register Boolean foundfile;
2359669Slinton     register File f;
2369669Slinton     char *tmp;
2379669Slinton 
2389669Slinton     runfirst = false;
2399669Slinton     interactive = false;
2409669Slinton     lexdebug = false;
2419669Slinton     tracebpts = false;
2429669Slinton     traceexec = false;
2439669Slinton     tracesyms = false;
2449669Slinton     foundfile = false;
2459669Slinton     corefile = nil;
2469669Slinton     coredump = true;
2479669Slinton     sourcepath = list_alloc();
2489669Slinton     list_append(list_item("."), nil, sourcepath);
2499669Slinton     i = 1;
25010607Slinton     while (i < argc and (not foundfile or corefile == nil)) {
2519669Slinton 	if (argv[i][0] == '-') {
2529669Slinton 	    if (streq(argv[i], "-I")) {
2539669Slinton 		++i;
2549669Slinton 		if (i >= argc) {
2559669Slinton 		    fatal("missing directory for -I");
2569669Slinton 		}
2579669Slinton 		list_append(list_item(argv[i]), nil, sourcepath);
2589669Slinton 	    } else {
2599669Slinton 		for (j = 1; argv[i][j] != '\0'; j++) {
2609669Slinton 		    setoption(argv[i][j]);
2619669Slinton 		}
2629669Slinton 	    }
2639669Slinton 	} else if (not foundfile) {
2649669Slinton 	    objname = argv[i];
2659669Slinton 	    foundfile = true;
2669669Slinton 	} else if (coredump and corefile == nil) {
2679669Slinton 	    corefile = fopen(argv[i], "r");
2689669Slinton 	    if (corefile == nil) {
2699669Slinton 		coredump = false;
2709669Slinton 	    }
2719669Slinton 	}
2729669Slinton 	++i;
2739669Slinton     }
2749669Slinton     if (i < argc and not runfirst) {
2759669Slinton 	fatal("extraneous argument %s", argv[i]);
2769669Slinton     }
2779669Slinton     firstarg = i;
2789669Slinton     if (not foundfile and isatty(0)) {
2799669Slinton 	printf("enter object file name (default is `%s'): ", objname);
2809669Slinton 	fflush(stdout);
2819669Slinton 	gets(namebuf);
2829669Slinton 	if (namebuf[0] != '\0') {
2839669Slinton 	    objname = namebuf;
2849669Slinton 	}
2859669Slinton     }
2869669Slinton     f = fopen(objname, "r");
2879669Slinton     if (f == nil) {
2889669Slinton 	fatal("can't read %s", objname);
2899669Slinton     } else {
2909669Slinton 	fclose(f);
2919669Slinton     }
2929669Slinton     if (rindex(objname, '/') != nil) {
2939669Slinton 	tmp = strdup(objname);
2949669Slinton 	*(rindex(tmp, '/')) = '\0';
2959669Slinton 	list_append(list_item(tmp), nil, sourcepath);
2969669Slinton     }
2979669Slinton     if (coredump and corefile == nil) {
2989669Slinton 	corefile = fopen("core", "r");
2999669Slinton 	if (corefile == nil) {
3009669Slinton 	    coredump = false;
3019669Slinton 	}
3029669Slinton     }
3039669Slinton }
3049669Slinton 
3059669Slinton /*
3069669Slinton  * Take appropriate action for recognized command argument.
3079669Slinton  */
3089669Slinton 
3099669Slinton private setoption(c)
3109669Slinton char c;
3119669Slinton {
3129669Slinton     switch (c) {
3139669Slinton 	case 'r':   /* run program before accepting commands */
3149669Slinton 	    runfirst = true;
3159669Slinton 	    coredump = false;
3169669Slinton 	    break;
3179669Slinton 
3189669Slinton 	case 'i':
3199669Slinton 	    interactive = true;
3209669Slinton 	    break;
3219669Slinton 
3229669Slinton 	case 'b':
3239669Slinton 	    tracebpts = true;
3249669Slinton 	    break;
3259669Slinton 
3269669Slinton 	case 'e':
3279669Slinton 	    traceexec = true;
3289669Slinton 	    break;
3299669Slinton 
3309669Slinton 	case 's':
3319669Slinton 	    tracesyms = true;
3329669Slinton 	    break;
3339669Slinton 
3349669Slinton 	case 'l':
3359669Slinton #   	    ifdef LEXDEBUG
3369669Slinton 		lexdebug = true;
3379669Slinton #	    else
3389669Slinton 		fatal("\"-l\" only applicable when compiled with LEXDEBUG");
3399669Slinton #	    endif
3409669Slinton 	    break;
3419669Slinton 
3429669Slinton 	default:
3439669Slinton 	    fatal("unknown option '%c'", c);
3449669Slinton     }
3459669Slinton }
3469669Slinton 
3479669Slinton /*
34811868Slinton  * Save/restore the state of a tty.
34911868Slinton  */
35011868Slinton 
35111868Slinton public savetty(f, t)
35211868Slinton File f;
35311868Slinton Ttyinfo *t;
35411868Slinton {
35511868Slinton     gtty(fileno(f), t);
35611868Slinton }
35711868Slinton 
35811868Slinton public restoretty(f, t)
35911868Slinton File f;
36011868Slinton Ttyinfo *t;
36111868Slinton {
36211868Slinton     stty(fileno(f), t);
36311868Slinton }
36411868Slinton 
36511868Slinton /*
3669669Slinton  * Exit gracefully.
3679669Slinton  */
3689669Slinton 
3699669Slinton public quit(r)
3709669Slinton Integer r;
3719669Slinton {
3729669Slinton     exit(r);
3739669Slinton }
374