1: /*
   2:  * Copyright (c) 1983 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: char copyright[] =
   9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  10:  All rights reserved.\n";
  11: #endif not lint
  12: 
  13: #ifndef lint
  14: static char sccsid[] = "@(#)main.c	5.1 (Berkeley) 5/31/85";
  15: #endif not lint
  16: 
  17: static char rcsid[] = "$Header: main.c,v 1.5 84/12/26 10:40:16 linton Exp $";
  18: 
  19: /*
  20:  * Debugger main routine.
  21:  */
  22: 
  23: #include "defs.h"
  24: #include <setjmp.h>
  25: #include <signal.h>
  26: #include <errno.h>
  27: #include "main.h"
  28: #include "eval.h"
  29: #include "debug.h"
  30: #include "symbols.h"
  31: #include "scanner.h"
  32: #include "keywords.h"
  33: #include "process.h"
  34: #include "runtime.h"
  35: #include "source.h"
  36: #include "object.h"
  37: #include "mappings.h"
  38: #include "coredump.h"
  39: 
  40: #ifndef public
  41: 
  42: #define isterm(file)    (interactive or isatty(fileno(file)))
  43: 
  44: #include <sgtty.h>
  45: #include <fcntl.h>
  46: 
  47: typedef struct {
  48:     struct sgttyb sg;       /* standard sgttyb structure */
  49:     struct tchars tc;       /* terminal characters */
  50:     struct ltchars ltc;     /* local special characters */
  51:     integer ldisc;      /* line discipline */
  52:     integer local;      /* TIOCLGET */
  53:     integer fcflags;        /* fcntl(2) F_GETFL, F_SETFL */
  54: } Ttyinfo;
  55: 
  56: #endif
  57: 
  58: public boolean coredump;        /* true if using a core dump */
  59: public boolean runfirst;        /* run program immediately */
  60: public boolean interactive;     /* standard input IS a terminal */
  61: public boolean lexdebug;        /* trace scanner return values */
  62: public boolean tracebpts;       /* trace create/delete breakpoints */
  63: public boolean traceexec;       /* trace execution */
  64: public boolean tracesyms;       /* print symbols are they are read */
  65: public boolean traceblocks;     /* trace blocks while reading symbols */
  66: public boolean vaddrs;          /* map addresses through page tables */
  67: 
  68: public File corefile;           /* File id of core dump */
  69: 
  70: #define FIRST_TIME 0            /* initial value setjmp returns */
  71: 
  72: private Boolean initdone = false;   /* true if initialization done */
  73: private jmp_buf env;            /* setjmp/longjmp data */
  74: private char outbuf[BUFSIZ];        /* standard output buffer */
  75: private char namebuf[512];      /* possible name of object file */
  76: private int firstarg;           /* first program argument (for -r) */
  77: 
  78: private Ttyinfo ttyinfo;
  79: private String corename;        /* name of core file */
  80: 
  81: private catchintr();
  82: 
  83: /*
  84:  * Main program.
  85:  */
  86: 
  87: main(argc, argv)
  88: int argc;
  89: String argv[];
  90: {
  91:     register integer i;
  92:     extern String date;
  93:     extern integer versionNumber;
  94: 
  95:     cmdname = argv[0];
  96:     catcherrs();
  97:     onsyserr(EINTR, nil);
  98:     setbuf(stdout, outbuf);
  99:     printf("dbx version 3.%d of %s.\nType 'help' for help.\n",
 100:     versionNumber, date);
 101:     fflush(stdout);
 102:     scanargs(argc, argv);
 103:     language_init();
 104:     symbols_init();
 105:     process_init();
 106:     if (runfirst) {
 107:     if (setjmp(env) == FIRST_TIME) {
 108:         arginit();
 109:         for (i = firstarg; i < argc; i++) {
 110:         newarg(argv[i]);
 111:         }
 112:         run();
 113:         /* NOTREACHED */
 114:     } else {
 115:         runfirst = false;
 116:     }
 117:     } else {
 118:     init();
 119:     }
 120:     if (setjmp(env) != FIRST_TIME) {
 121:     restoretty(stdout, &ttyinfo);
 122:     }
 123:     signal(SIGINT, catchintr);
 124:     yyparse();
 125:     putchar('\n');
 126:     quit(0);
 127: }
 128: 
 129: /*
 130:  * Initialize the world, including setting initial input file
 131:  * if the file exists.
 132:  */
 133: 
 134: public init()
 135: {
 136:     File f;
 137:     String home;
 138:     char buf[100];
 139:     extern String getenv();
 140: 
 141:     savetty(stdout, &ttyinfo);
 142:     enterkeywords();
 143:     scanner_init();
 144:     if (not coredump and not runfirst) {
 145:     start(nil, nil, nil);
 146:     }
 147:     printf("reading symbolic information ...");
 148:     fflush(stdout);
 149:     readobj(objname);
 150:     printf("\n");
 151:     fflush(stdout);
 152:     if (coredump) {
 153:     printf("[using memory image in %s]\n", corename);
 154:     if (vaddrs) {
 155:         coredump_getkerinfo();
 156:     }
 157:     setcurfunc(whatblock(pc));
 158:     } else {
 159:     setcurfunc(program);
 160:     }
 161:     bpinit();
 162:     f = fopen(initfile, "r");
 163:     if (f != nil) {
 164:     fclose(f);
 165:     setinput(initfile);
 166:     } else {
 167:     home = getenv("HOME");
 168:     if (home != nil) {
 169:         sprintf(buf, "%s/%s", home, initfile);
 170:         f = fopen(buf, "r");
 171:         if (f != nil) {
 172:         fclose(f);
 173:         setinput(strdup(buf));
 174:         }
 175:     }
 176:     }
 177:     initdone = true;
 178: }
 179: 
 180: /*
 181:  * Re-initialize the world, first de-allocating all storage.
 182:  * This is necessary when the symbol information must be re-read
 183:  * from the object file when it has changed.
 184:  *
 185:  * Before "forgetting" things, we save the current tracing/breakpoint
 186:  * information to a temp file.  Then after re-creating the world,
 187:  * we read the temp file as commands.  This isn't always the right thing;
 188:  * if a procedure that was being traced is deleted, an error message
 189:  * will be generated.
 190:  *
 191:  * If the argument vector is not nil, then this is re-initialize is being
 192:  * done in preparation for running the program.  Since we want to process
 193:  * the commands in the temp file before running the program, we add the
 194:  * run command at the end of the temp file.  In this case, reinit longjmps
 195:  * back to parsing rather than returning.
 196:  */
 197: 
 198: public reinit(argv, infile, outfile)
 199: String *argv;
 200: String infile;
 201: String outfile;
 202: {
 203:     register Integer i;
 204:     String tmpfile;
 205:     extern String mktemp();
 206: 
 207:     tmpfile = mktemp("/tmp/dbxXXXX");
 208:     setout(tmpfile);
 209:     status();
 210:     alias(nil, nil, nil);
 211:     if (argv != nil) {
 212:     printf("run");
 213:     for (i = 1; argv[i] != nil; i++) {
 214:         printf(" %s", argv[i]);
 215:     }
 216:     if (infile != nil) {
 217:         printf(" < %s", infile);
 218:     }
 219:     if (outfile != nil) {
 220:         printf(" > %s", outfile);
 221:     }
 222:     putchar('\n');
 223:     }
 224:     unsetout();
 225:     bpfree();
 226:     objfree();
 227:     symbols_init();
 228:     process_init();
 229:     enterkeywords();
 230:     scanner_init();
 231:     readobj(objname);
 232:     bpinit();
 233:     fflush(stdout);
 234:     setinput(tmpfile);
 235:     unlink(tmpfile);
 236:     if (argv != nil) {
 237:     longjmp(env, 1);
 238:     /* NOTREACHED */
 239:     }
 240: }
 241: 
 242: /*
 243:  * After a non-fatal error we skip the rest of the current input line, and
 244:  * jump back to command parsing.
 245:  */
 246: 
 247: public erecover()
 248: {
 249:     if (initdone) {
 250:     gobble();
 251:     longjmp(env, 1);
 252:     }
 253: }
 254: 
 255: /*
 256:  * This routine is called when an interrupt occurs.
 257:  */
 258: 
 259: private catchintr()
 260: {
 261:     if (isredirected()) {
 262:     fflush(stdout);
 263:     unsetout();
 264:     }
 265:     putchar('\n');
 266:     longjmp(env, 1);
 267: }
 268: 
 269: /*
 270:  * Scan the argument list.
 271:  */
 272: 
 273: private scanargs(argc, argv)
 274: int argc;
 275: String argv[];
 276: {
 277:     register int i, j;
 278:     register Boolean foundfile;
 279:     register File f;
 280:     char *tmp;
 281: 
 282:     runfirst = false;
 283:     interactive = false;
 284:     lexdebug = false;
 285:     tracebpts = false;
 286:     traceexec = false;
 287:     tracesyms = false;
 288:     traceblocks = false;
 289:     vaddrs = false;
 290:     foundfile = false;
 291:     corefile = nil;
 292:     coredump = true;
 293:     sourcepath = list_alloc();
 294:     list_append(list_item("."), nil, sourcepath);
 295:     i = 1;
 296:     while (i < argc and (not foundfile or (coredump and corefile == nil))) {
 297:     if (argv[i][0] == '-') {
 298:         if (streq(argv[i], "-I")) {
 299:         ++i;
 300:         if (i >= argc) {
 301:             fatal("missing directory for -I");
 302:         }
 303:         list_append(list_item(argv[i]), nil, sourcepath);
 304:         } else if (streq(argv[i], "-c")) {
 305:         ++i;
 306:         if (i >= argc) {
 307:             fatal("missing command file name for -c");
 308:         }
 309:         initfile = argv[i];
 310:         } else {
 311:         for (j = 1; argv[i][j] != '\0'; j++) {
 312:             setoption(argv[i][j]);
 313:         }
 314:         }
 315:     } else if (not foundfile) {
 316:         objname = argv[i];
 317:         foundfile = true;
 318:     } else if (coredump and corefile == nil) {
 319:         corefile = fopen(argv[i], "r");
 320:         corename = argv[i];
 321:         if (corefile == nil) {
 322:         coredump = false;
 323:         }
 324:     }
 325:     ++i;
 326:     }
 327:     if (i < argc and not runfirst) {
 328:     fatal("extraneous argument %s", argv[i]);
 329:     }
 330:     firstarg = i;
 331:     if (not foundfile and isatty(0)) {
 332:     printf("enter object file name (default is `%s'): ", objname);
 333:     fflush(stdout);
 334:     gets(namebuf);
 335:     if (namebuf[0] != '\0') {
 336:         objname = namebuf;
 337:     }
 338:     }
 339:     f = fopen(objname, "r");
 340:     if (f == nil) {
 341:     fatal("can't read %s", objname);
 342:     } else {
 343:     fclose(f);
 344:     }
 345:     if (rindex(objname, '/') != nil) {
 346:     tmp = strdup(objname);
 347:     *(rindex(tmp, '/')) = '\0';
 348:     list_append(list_item(tmp), nil, sourcepath);
 349:     }
 350:     if (coredump and corefile == nil) {
 351:     if (vaddrs) {
 352:         corefile = fopen("/dev/mem", "r");
 353:         corename = "/dev/mem";
 354:         if (corefile == nil) {
 355:         panic("can't open /dev/mem");
 356:         }
 357:     } else {
 358:         corefile = fopen("core", "r");
 359:         corename = "core";
 360:         if (corefile == nil) {
 361:         coredump = false;
 362:         }
 363:     }
 364:     }
 365: }
 366: 
 367: /*
 368:  * Take appropriate action for recognized command argument.
 369:  */
 370: 
 371: private setoption(c)
 372: char c;
 373: {
 374:     switch (c) {
 375:     case 'r':   /* run program before accepting commands */
 376:         runfirst = true;
 377:         coredump = false;
 378:         break;
 379: 
 380:     case 'i':
 381:         interactive = true;
 382:         break;
 383: 
 384:     case 'b':
 385:         tracebpts = true;
 386:         break;
 387: 
 388:     case 'e':
 389:         traceexec = true;
 390:         break;
 391: 
 392:     case 's':
 393:         tracesyms = true;
 394:         break;
 395: 
 396:     case 'n':
 397:         traceblocks = true;
 398:         break;
 399: 
 400:     case 'k':
 401:         vaddrs = true;
 402:         break;
 403: 
 404:     case 'l':
 405: #   	    ifdef LEXDEBUG
 406:         lexdebug = true;
 407: #	    else
 408:         fatal("\"-l\" only applicable when compiled with LEXDEBUG");
 409: #	    endif
 410:         break;
 411: 
 412:     default:
 413:         fatal("unknown option '%c'", c);
 414:     }
 415: }
 416: 
 417: /*
 418:  * Save/restore the state of a tty.
 419:  */
 420: 
 421: public savetty(f, t)
 422: File f;
 423: Ttyinfo *t;
 424: {
 425:     ioctl(fileno(f), TIOCGETP, &(t->sg));
 426:     ioctl(fileno(f), TIOCGETC, &(t->tc));
 427:     ioctl(fileno(f), TIOCGLTC, &(t->ltc));
 428:     ioctl(fileno(f), TIOCGETD, &(t->ldisc));
 429:     ioctl(fileno(f), TIOCLGET, &(t->local));
 430:     t->fcflags = fcntl(fileno(f), F_GETFL, 0);
 431: }
 432: 
 433: public restoretty(f, t)
 434: File f;
 435: Ttyinfo *t;
 436: {
 437:     ioctl(fileno(f), TIOCSETN, &(t->sg));
 438:     ioctl(fileno(f), TIOCSETC, &(t->tc));
 439:     ioctl(fileno(f), TIOCSLTC, &(t->ltc));
 440:     ioctl(fileno(f), TIOCSETD, &(t->ldisc));
 441:     ioctl(fileno(f), TIOCLSET, &(t->local));
 442:     (void) fcntl(fileno(f), F_SETFL, t->fcflags);
 443: }
 444: 
 445: /*
 446:  * Exit gracefully.
 447:  */
 448: 
 449: public quit(r)
 450: Integer r;
 451: {
 452:     pterm(process);
 453:     exit(r);
 454: }

Defined functions

catchintr defined in line 259; used 2 times
erecover defined in line 247; never used
init defined in line 134; used 2 times
main defined in line 87; never used
quit defined in line 449; used 1 times
reinit defined in line 198; used 1 times
restoretty defined in line 433; used 2 times
savetty defined in line 421; used 2 times
scanargs defined in line 273; used 1 times
setoption defined in line 371; used 1 times

Defined variables

copyright defined in line 8; never used
corename defined in line 79; used 4 times
env defined in line 73; used 5 times
firstarg defined in line 76; used 2 times
namebuf defined in line 75; used 3 times
outbuf defined in line 74; used 1 times
  • in line 98
rcsid defined in line 17; never used
sccsid defined in line 14; never used

Defined macros

FIRST_TIME defined in line 70; used 2 times
isterm defined in line 42; never used
Last modified: 1985-05-31
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1205
Valid CSS Valid XHTML 1.0 Strict