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