xref: /csrg-svn/old/dbx/main.c (revision 17530)
19669Slinton /* Copyright (c) 1982 Regents of the University of California */
29669Slinton 
3*17530Sralph static	char sccsid[] = "@(#)main.c	1.10 (Berkeley) 12/18/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>
27*17530Sralph #include <fcntl.h>
2811868Slinton 
29*17530Sralph typedef struct {
30*17530Sralph 	struct sgttyb	sg;		/* standard sgttyb structure */
31*17530Sralph 	struct tchars	tc;		/* terminal characters */
32*17530Sralph 	struct ltchars	ltc;		/* local special characters */
33*17530Sralph 	int		ldisc;		/* line discipline */
34*17530Sralph 	int		local;		/* TIOCLGET */
35*17530Sralph 	int		fcflags;	/* fcntl(2) F_GETFL, F_SETFL */
36*17530Sralph } Ttyinfo;
3711868Slinton 
389669Slinton #endif
399669Slinton 
409669Slinton public Boolean coredump;		/* true if using a core dump */
419669Slinton public Boolean runfirst;		/* run program immediately */
429669Slinton public Boolean interactive;		/* standard input IS a terminal */
439669Slinton public Boolean lexdebug;		/* trace yylex return values */
449669Slinton public Boolean tracebpts;		/* trace create/delete breakpoints */
459669Slinton public Boolean traceexec;		/* trace process execution */
469669Slinton public Boolean tracesyms;		/* print symbols as their read */
4716613Ssam public Boolean traceblocks;		/* trace blocks while reading symbols */
489669Slinton 
499669Slinton public File corefile;			/* File id of core dump */
509669Slinton 
519669Slinton #define FIRST_TIME 0			/* initial value setjmp returns */
529669Slinton 
539669Slinton private Boolean initdone = false;	/* true if initialization done */
549669Slinton private jmp_buf env;			/* setjmp/longjmp data */
559669Slinton private char namebuf[512];		/* possible name of object file */
569669Slinton private int firstarg;			/* first program argument (for -r) */
579669Slinton 
5811868Slinton private Ttyinfo ttyinfo;
5911868Slinton 
609669Slinton private catchintr();
619669Slinton 
629669Slinton /*
639669Slinton  * Main program.
649669Slinton  */
659669Slinton 
669669Slinton main(argc, argv)
679669Slinton int argc;
689669Slinton String argv[];
699669Slinton {
7016613Ssam     register integer i;
7111868Slinton     extern String date;
7216613Ssam     extern integer versionNumber;
739669Slinton 
749669Slinton     cmdname = argv[0];
759669Slinton     catcherrs();
769669Slinton     onsyserr(EINTR, nil);
7716925Ssam     setlinebuf(stderr);
7816613Ssam     printf("dbx version %d of %s.\nType 'help' for help.\n",
7916613Ssam 	versionNumber, date);
8011868Slinton     fflush(stdout);
819669Slinton     scanargs(argc, argv);
829669Slinton     language_init();
839669Slinton     process_init();
849669Slinton     if (runfirst) {
859669Slinton 	if (setjmp(env) == FIRST_TIME) {
869669Slinton 	    arginit();
879669Slinton 	    for (i = firstarg; i < argc; i++) {
889669Slinton 		newarg(argv[i]);
899669Slinton 	    }
909669Slinton 	    run();
919669Slinton 	    /* NOTREACHED */
929669Slinton 	} else {
939669Slinton 	    runfirst = false;
949669Slinton 	}
959669Slinton     } else {
969669Slinton 	init();
979669Slinton     }
9816613Ssam     if (setjmp(env) != FIRST_TIME) {
9916613Ssam 	restoretty(stdout, &ttyinfo);
10016613Ssam     }
1019669Slinton     signal(SIGINT, catchintr);
10216925Ssam     if (isterm(stdin)) {
10316925Ssam 	    printf("(%s) ", cmdname);
10416925Ssam 	    fflush(stdout);
10516925Ssam     }
10616925Ssam     endshellmode();		/* after an error longjmp */
10716925Ssam     startaliasing();
1089669Slinton     yyparse();
1099669Slinton     putchar('\n');
1109669Slinton     quit(0);
1119669Slinton }
1129669Slinton 
1139669Slinton /*
1149669Slinton  * Initialize the world, including setting initial input file
1159669Slinton  * if the file exists.
1169669Slinton  */
1179669Slinton 
1189669Slinton public init()
1199669Slinton {
1209669Slinton     File f;
1219669Slinton     String home;
1229669Slinton     char buf[100];
1239669Slinton     extern String getenv();
1249669Slinton 
12511868Slinton     savetty(stdout, &ttyinfo);
1269669Slinton     enterkeywords();
1279669Slinton     scanner_init();
1289669Slinton     if (not coredump and not runfirst) {
1299669Slinton 	start(nil, nil, nil);
1309669Slinton     }
13111868Slinton     printf("reading symbolic information ...");
13211868Slinton     fflush(stdout);
1339669Slinton     readobj(objname);
13411868Slinton     printf("\n");
13511868Slinton     fflush(stdout);
13612483Slinton     if (coredump) {
13716613Ssam 	setcurfunc(whatblock(pc));
13812483Slinton     } else {
13916613Ssam 	setcurfunc(program);
14012483Slinton     }
1419669Slinton     bpinit();
1429669Slinton     f = fopen(initfile, "r");
1439669Slinton     if (f != nil) {
1449669Slinton 	fclose(f);
1459669Slinton 	setinput(initfile);
1469669Slinton     } else {
1479669Slinton 	home = getenv("HOME");
1489669Slinton 	if (home != nil) {
1499669Slinton 	    sprintf(buf, "%s/%s", home, initfile);
1509669Slinton 	    f = fopen(buf, "r");
1519669Slinton 	    if (f != nil) {
1529669Slinton 		fclose(f);
1539669Slinton 		setinput(strdup(buf));
1549669Slinton 	    }
1559669Slinton 	}
1569669Slinton     }
1579669Slinton     initdone = true;
1589669Slinton }
1599669Slinton 
1609669Slinton /*
1619669Slinton  * Re-initialize the world, first de-allocating all storage.
1629669Slinton  * This is necessary when the symbol information must be re-read
1639669Slinton  * from the object file when it has changed.
1649669Slinton  *
1659669Slinton  * Before "forgetting" things, we save the current tracing/breakpoint
1669669Slinton  * information to a temp file.  Then after re-creating the world,
1679669Slinton  * we read the temp file as commands.  This isn't always the right thing;
1689669Slinton  * if a procedure that was being traced is deleted, an error message
1699669Slinton  * will be generated.
1709669Slinton  *
1719669Slinton  * If the argument vector is not nil, then this is re-initialize is being
1729669Slinton  * done in preparation for running the program.  Since we want to process
1739669Slinton  * the commands in the temp file before running the program, we add the
1749669Slinton  * run command at the end of the temp file.  In this case, reinit longjmps
1759669Slinton  * back to parsing rather than returning.
1769669Slinton  */
1779669Slinton 
1789669Slinton public reinit(argv, infile, outfile)
1799669Slinton String *argv;
1809669Slinton String infile;
1819669Slinton String outfile;
1829669Slinton {
1839669Slinton     register Integer i;
1849669Slinton     String tmpfile;
1859669Slinton     extern String mktemp();
1869669Slinton 
1879669Slinton     tmpfile = mktemp("/tmp/dbxXXXX");
1889669Slinton     setout(tmpfile);
1899669Slinton     status();
1909669Slinton     print_alias(nil);
1919669Slinton     if (argv != nil) {
1929669Slinton 	printf("run");
1939669Slinton 	for (i = 1; argv[i] != nil; i++) {
1949669Slinton 	    printf(" %s", argv[i]);
1959669Slinton 	}
1969669Slinton 	if (infile != nil) {
1979669Slinton 	    printf(" < %s", infile);
1989669Slinton 	}
1999669Slinton 	if (outfile != nil) {
2009669Slinton 	    printf(" > %s", outfile);
2019669Slinton 	}
2029669Slinton 	putchar('\n');
2039669Slinton     }
2049669Slinton     unsetout();
2059669Slinton     bpfree();
2069669Slinton     objfree();
2079669Slinton     process_init();
2089669Slinton     enterkeywords();
2099669Slinton     scanner_init();
2109669Slinton     readobj(objname);
2119669Slinton     bpinit();
2129669Slinton     fflush(stdout);
2139669Slinton     setinput(tmpfile);
2149669Slinton     unlink(tmpfile);
2159669Slinton     if (argv != nil) {
2169669Slinton 	longjmp(env, 1);
2179669Slinton 	/* NOTREACHED */
2189669Slinton     }
2199669Slinton }
2209669Slinton 
2219669Slinton /*
2229669Slinton  * After a non-fatal error we jump back to command parsing.
2239669Slinton  */
2249669Slinton 
2259669Slinton public erecover()
2269669Slinton {
2279669Slinton     if (initdone) {
2289669Slinton 	gobble();
2299669Slinton 	longjmp(env, 1);
2309669Slinton     }
2319669Slinton }
2329669Slinton 
2339669Slinton /*
2349669Slinton  * This routine is called when an interrupt occurs.
2359669Slinton  */
2369669Slinton 
2379669Slinton private catchintr()
2389669Slinton {
2399669Slinton     putchar('\n');
2409669Slinton     longjmp(env, 1);
2419669Slinton }
2429669Slinton 
2439669Slinton /*
2449669Slinton  * Scan the argument list.
2459669Slinton  */
2469669Slinton 
2479669Slinton private scanargs(argc, argv)
2489669Slinton int argc;
2499669Slinton String argv[];
2509669Slinton {
2519669Slinton     register int i, j;
2529669Slinton     register Boolean foundfile;
2539669Slinton     register File f;
2549669Slinton     char *tmp;
2559669Slinton 
2569669Slinton     runfirst = false;
2579669Slinton     interactive = false;
2589669Slinton     lexdebug = false;
2599669Slinton     tracebpts = false;
2609669Slinton     traceexec = false;
2619669Slinton     tracesyms = false;
26216613Ssam     traceblocks = false;
2639669Slinton     foundfile = false;
2649669Slinton     corefile = nil;
2659669Slinton     coredump = true;
2669669Slinton     sourcepath = list_alloc();
2679669Slinton     list_append(list_item("."), nil, sourcepath);
2689669Slinton     i = 1;
26916613Ssam     while (i < argc and (not foundfile or corefile == nil)) {
2709669Slinton 	if (argv[i][0] == '-') {
2719669Slinton 	    if (streq(argv[i], "-I")) {
2729669Slinton 		++i;
2739669Slinton 		if (i >= argc) {
2749669Slinton 		    fatal("missing directory for -I");
2759669Slinton 		}
2769669Slinton 		list_append(list_item(argv[i]), nil, sourcepath);
2779669Slinton 	    } else {
2789669Slinton 		for (j = 1; argv[i][j] != '\0'; j++) {
2799669Slinton 		    setoption(argv[i][j]);
2809669Slinton 		}
2819669Slinton 	    }
2829669Slinton 	} else if (not foundfile) {
2839669Slinton 	    objname = argv[i];
2849669Slinton 	    foundfile = true;
2859669Slinton 	} else if (coredump and corefile == nil) {
2869669Slinton 	    corefile = fopen(argv[i], "r");
2879669Slinton 	    if (corefile == nil) {
2889669Slinton 		coredump = false;
2899669Slinton 	    }
2909669Slinton 	}
2919669Slinton 	++i;
2929669Slinton     }
2939669Slinton     if (i < argc and not runfirst) {
2949669Slinton 	fatal("extraneous argument %s", argv[i]);
2959669Slinton     }
2969669Slinton     firstarg = i;
2979669Slinton     if (not foundfile and isatty(0)) {
2989669Slinton 	printf("enter object file name (default is `%s'): ", objname);
2999669Slinton 	fflush(stdout);
3009669Slinton 	gets(namebuf);
3019669Slinton 	if (namebuf[0] != '\0') {
3029669Slinton 	    objname = namebuf;
3039669Slinton 	}
3049669Slinton     }
3059669Slinton     f = fopen(objname, "r");
3069669Slinton     if (f == nil) {
3079669Slinton 	fatal("can't read %s", objname);
3089669Slinton     } else {
3099669Slinton 	fclose(f);
3109669Slinton     }
3119669Slinton     if (rindex(objname, '/') != nil) {
3129669Slinton 	tmp = strdup(objname);
3139669Slinton 	*(rindex(tmp, '/')) = '\0';
3149669Slinton 	list_append(list_item(tmp), nil, sourcepath);
3159669Slinton     }
3169669Slinton     if (coredump and corefile == nil) {
3179669Slinton 	corefile = fopen("core", "r");
3189669Slinton 	if (corefile == nil) {
3199669Slinton 	    coredump = false;
3209669Slinton 	}
3219669Slinton     }
3229669Slinton }
3239669Slinton 
3249669Slinton /*
3259669Slinton  * Take appropriate action for recognized command argument.
3269669Slinton  */
3279669Slinton 
3289669Slinton private setoption(c)
3299669Slinton char c;
3309669Slinton {
3319669Slinton     switch (c) {
3329669Slinton 	case 'r':   /* run program before accepting commands */
3339669Slinton 	    runfirst = true;
3349669Slinton 	    coredump = false;
3359669Slinton 	    break;
3369669Slinton 
3379669Slinton 	case 'i':
3389669Slinton 	    interactive = true;
3399669Slinton 	    break;
3409669Slinton 
3419669Slinton 	case 'b':
3429669Slinton 	    tracebpts = true;
3439669Slinton 	    break;
3449669Slinton 
3459669Slinton 	case 'e':
3469669Slinton 	    traceexec = true;
3479669Slinton 	    break;
3489669Slinton 
3499669Slinton 	case 's':
3509669Slinton 	    tracesyms = true;
3519669Slinton 	    break;
3529669Slinton 
35316613Ssam 	case 'n':
35416613Ssam 	    traceblocks = true;
35516613Ssam 	    break;
35616613Ssam 
3579669Slinton 	case 'l':
3589669Slinton 		lexdebug = true;
3599669Slinton 	    break;
3609669Slinton 
3619669Slinton 	default:
3629669Slinton 	    fatal("unknown option '%c'", c);
3639669Slinton     }
3649669Slinton }
3659669Slinton 
3669669Slinton /*
36711868Slinton  * Save/restore the state of a tty.
36811868Slinton  */
36911868Slinton 
37011868Slinton public savetty(f, t)
37111868Slinton File f;
37211868Slinton Ttyinfo *t;
37311868Slinton {
374*17530Sralph     ioctl(fileno(f), TIOCGETP, &(t->sg));
375*17530Sralph     ioctl(fileno(f), TIOCGETC, &(t->tc));
376*17530Sralph     ioctl(fileno(f), TIOCGLTC, &(t->ltc));
377*17530Sralph     ioctl(fileno(f), TIOCGETD, &(t->ldisc));
378*17530Sralph     ioctl(fileno(f), TIOCLGET, &(t->local));
379*17530Sralph     t->fcflags = fcntl(fileno(f), F_GETFL, 0);
38011868Slinton }
38111868Slinton 
38211868Slinton public restoretty(f, t)
38311868Slinton File f;
38411868Slinton Ttyinfo *t;
38511868Slinton {
386*17530Sralph     ioctl(fileno(f), TIOCSETN, &(t->sg));
387*17530Sralph     ioctl(fileno(f), TIOCSETC, &(t->tc));
388*17530Sralph     ioctl(fileno(f), TIOCSLTC, &(t->ltc));
389*17530Sralph     ioctl(fileno(f), TIOCSETD, &(t->ldisc));
390*17530Sralph     ioctl(fileno(f), TIOCLSET, &(t->local));
391*17530Sralph     (void) fcntl(fileno(f), F_SETFL, t->fcflags);
39211868Slinton }
39311868Slinton 
39411868Slinton /*
3959669Slinton  * Exit gracefully.
3969669Slinton  */
3979669Slinton 
3989669Slinton public quit(r)
3999669Slinton Integer r;
4009669Slinton {
40116613Ssam     pterm(process);
4029669Slinton     exit(r);
4039669Slinton }
404