Annotation of 43BSDReno/pgrm/dbx/main.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.