Annotation of 42BSD/ucb/dbx/eval.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) 1982 Regents of the University of California */
                      2: 
                      3: static char sccsid[] = "@(#)eval.c 1.10 8/17/83";
                      4: 
                      5: /*
                      6:  * Tree evaluation.
                      7:  */
                      8: 
                      9: #include "defs.h"
                     10: #include "tree.h"
                     11: #include "operators.h"
                     12: #include "eval.h"
                     13: #include "events.h"
                     14: #include "symbols.h"
                     15: #include "scanner.h"
                     16: #include "source.h"
                     17: #include "object.h"
                     18: #include "mappings.h"
                     19: #include "process.h"
                     20: #include "machine.h"
                     21: #include <signal.h>
                     22: 
                     23: #ifndef public
                     24: 
                     25: #include "machine.h"
                     26: 
                     27: #define STACKSIZE 20000
                     28: 
                     29: typedef Char Stack;
                     30: 
                     31: #define push(type, value) { \
                     32:     ((type *) (sp += sizeof(type)))[-1] = (value); \
                     33: }
                     34: 
                     35: #define pop(type) ( \
                     36:     (*((type *) (sp -= sizeof(type)))) \
                     37: )
                     38: 
                     39: #define alignstack() { \
                     40:     sp = (Stack *) (( ((int) sp) + sizeof(int) - 1)&~(sizeof(int) - 1)); \
                     41: }
                     42: 
                     43: #endif
                     44: 
                     45: public Stack stack[STACKSIZE];
                     46: public Stack *sp = &stack[0];
                     47: public Boolean useInstLoc = false;
                     48: 
                     49: #define chksp() \
                     50: { \
                     51:     if (sp < &stack[0]) { \
                     52:        panic("stack underflow"); \
                     53:     } \
                     54: }
                     55: 
                     56: #define poparg(n, r, fr) { \
                     57:     eval(p->value.arg[n]); \
                     58:     if (isreal(p->op)) { \
                     59:        fr = pop(double); \
                     60:     } else if (isint(p->op)) { \
                     61:        r = popsmall(p->value.arg[n]->nodetype); \
                     62:     } \
                     63: }
                     64: 
                     65: #define Boolrep char   /* underlying representation type for booleans */
                     66: 
                     67: /*
                     68:  * Evaluate a parse tree leaving the value on the top of the stack.
                     69:  */
                     70: 
                     71: public eval(p)
                     72: register Node p;
                     73: {
                     74:     long r0, r1;
                     75:     double fr0, fr1;
                     76:     Address addr;
                     77:     long i, n;
                     78:     int len;
                     79:     Symbol s, f;
                     80:     Node n1, n2;
                     81:     Boolean b;
                     82:     File file;
                     83: 
                     84:     checkref(p);
                     85:     if (debug_flag[2]) {
                     86:        fprintf(stderr," evaluating %s \n",showoperator(p->op));
                     87:     }
                     88:     switch (degree(p->op)) {
                     89:        case BINARY:
                     90:            poparg(1, r1, fr1);
                     91:            poparg(0, r0, fr0);
                     92:            break;
                     93: 
                     94:        case UNARY:
                     95:            poparg(0, r0, fr0);
                     96:            break;
                     97: 
                     98:        default:
                     99:            /* do nothing */;
                    100:     }
                    101:     switch (p->op) {
                    102:        case O_SYM:
                    103:            s = p->value.sym;
                    104:            if (s == retaddrsym) {
                    105:                push(long, return_addr());
                    106:            } else {
                    107:                if (isvariable(s)) {
                    108:                    if (s != program and not isactive(container(s))) {
                    109:                        error("\"%s\" is not active", symname(s));
                    110:                    }
                    111:                    push(long, address(s, nil));
                    112:                } else if (isblock(s)) {
                    113:                    push(Symbol, s);
                    114:                } else {
                    115:                    error("can't evaluate a %s", classname(s));
                    116:                }
                    117:            }
                    118:            break;
                    119: 
                    120:        case O_LCON:
                    121:            r0 = p->value.lcon;
                    122:            pushsmall(p->nodetype, r0);
                    123:            break;
                    124: 
                    125:        case O_FCON:
                    126:            push(double, p->value.fcon);
                    127:            break;
                    128: 
                    129:        case O_SCON:
                    130:            len = size(p->nodetype);
                    131:            mov(p->value.scon, sp, len);
                    132:            sp += len;
                    133:            break;
                    134: 
                    135:        case O_INDEX:
                    136:            n = pop(long);
                    137:            i = evalindex(p->value.arg[0]->nodetype,
                    138:                popsmall(p->value.arg[1]->nodetype));
                    139:            push(long, n + i*size(p->nodetype));
                    140:            break;
                    141: 
                    142:        case O_DOT:
                    143:            s = p->value.arg[1]->value.sym;
                    144:            n = lval(p->value.arg[0]);
                    145:            push(long, n + (s->symvalue.field.offset div 8));
                    146:            break;
                    147: 
                    148:        /*
                    149:         * Get the value of the expression addressed by the top of the stack.
                    150:         * Push the result back on the stack.
                    151:         */
                    152: 
                    153:        case O_INDIR:
                    154:        case O_RVAL:
                    155:            addr = pop(long);
                    156:            if (addr == 0) {
                    157:                error("reference through nil pointer");
                    158:            }
                    159:            if (p->op == O_INDIR) {
                    160:                len = sizeof(long);
                    161:            } else {
                    162:                len = size(p->nodetype);
                    163:            }
                    164:            rpush(addr, len);
                    165:        addr = pop(long);
                    166:         push(long, addr);
                    167:            break;
                    168: 
                    169:        /*
                    170:         * Effectively, we want to pop n bytes off for the evaluated subtree
                    171:         * and push len bytes on for the new type of the same tree.
                    172:         */
                    173:        case O_TYPERENAME:
                    174:            n = size(p->value.arg[0]->nodetype);
                    175:            len = size(p->nodetype);
                    176:            sp = sp - n + len;
                    177:            break;
                    178: 
                    179:        case O_COMMA:
                    180:            break;
                    181: 
                    182:        case O_ITOF:
                    183:            push(double, (double) r0);
                    184:            break;
                    185: 
                    186:        case O_ADD:
                    187:            push(long, r0+r1);
                    188:            break;
                    189: 
                    190:        case O_ADDF:
                    191:            push(double, fr0+fr1);
                    192:            break;
                    193: 
                    194:        case O_SUB:
                    195:            push(long, r0-r1);
                    196:            break;
                    197: 
                    198:        case O_SUBF:
                    199:            push(double, fr0-fr1);
                    200:            break;
                    201: 
                    202:        case O_NEG:
                    203:            push(long, -r0);
                    204:            break;
                    205: 
                    206:        case O_NEGF:
                    207:            push(double, -fr0);
                    208:            break;
                    209: 
                    210:        case O_MUL:
                    211:            push(long, r0*r1);
                    212:            break;
                    213: 
                    214:        case O_MULF:
                    215:            push(double, fr0*fr1);
                    216:            break;
                    217: 
                    218:        case O_DIVF:
                    219:            if (fr1 == 0) {
                    220:                error("error: division by 0");
                    221:            }
                    222:            push(double, fr0 / fr1);
                    223:            break;
                    224: 
                    225:        case O_DIV:
                    226:            if (r1 == 0) {
                    227:                error("error: div by 0");
                    228:            }
                    229:            push(long, r0 div r1);
                    230:            break;
                    231: 
                    232:        case O_MOD:
                    233:            if (r1 == 0) {
                    234:                error("error: mod by 0");
                    235:            }
                    236:            push(long, r0 mod r1);
                    237:            break;
                    238: 
                    239:        case O_LT:
                    240:            push(Boolrep, r0 < r1);
                    241:            break;
                    242: 
                    243:        case O_LTF:
                    244:            push(Boolrep, fr0 < fr1);
                    245:            break;
                    246: 
                    247:        case O_LE:
                    248:            push(Boolrep, r0 <= r1);
                    249:            break;
                    250: 
                    251:        case O_LEF:
                    252:            push(Boolrep, fr0 <= fr1);
                    253:            break;
                    254: 
                    255:        case O_GT:
                    256:            push(Boolrep, r0 > r1);
                    257:            break;
                    258: 
                    259:        case O_GTF:
                    260:            push(Boolrep, fr0 > fr1);
                    261:            break;
                    262: 
                    263:        case O_EQ:
                    264:            push(Boolrep, r0 == r1);
                    265:            break;
                    266: 
                    267:        case O_EQF:
                    268:            push(Boolrep, fr0 == fr1);
                    269:            break;
                    270: 
                    271:        case O_NE:
                    272:            push(Boolrep, r0 != r1);
                    273:            break;
                    274: 
                    275:        case O_NEF:
                    276:            push(Boolrep, fr0 != fr1);
                    277:            break;
                    278: 
                    279:        case O_AND:
                    280:            push(Boolrep, r0 and r1);
                    281:            break;
                    282: 
                    283:        case O_OR:
                    284:            push(Boolrep, r0 or r1);
                    285:            break;
                    286: 
                    287:        case O_ASSIGN:
                    288:            assign(p->value.arg[0], p->value.arg[1]);
                    289:            break;
                    290: 
                    291:        case O_CHFILE:
                    292:            if (p->value.scon == nil) {
                    293:                printf("%s\n", cursource);
                    294:            } else {
                    295:                file = opensource(p->value.scon);
                    296:                if (file == nil) {
                    297:                    error("can't read \"%s\"", p->value.scon);
                    298:                } else {
                    299:                    fclose(file);
                    300:                    setsource(p->value.scon);
                    301:                }
                    302:            }
                    303:            break;
                    304: 
                    305:        case O_CONT:
                    306:            cont(p->value.lcon);
                    307:            printnews();
                    308:            break;
                    309: 
                    310:        case O_LIST:
                    311:            if (p->value.arg[0]->op == O_SYM) {
                    312:                f = p->value.arg[0]->value.sym;
                    313:                addr = firstline(f);
                    314:                if (addr == NOADDR) {
                    315:                    error("no source lines for \"%s\"", symname(f));
                    316:                }
                    317:                setsource(srcfilename(addr));
                    318:                r0 = srcline(addr) - 5;
                    319:                r1 = r0 + 10;
                    320:                if (r0 < 1) {
                    321:                    r0 = 1;
                    322:                }
                    323:            } else {
                    324:                eval(p->value.arg[0]);
                    325:                r0 = pop(long);
                    326:                eval(p->value.arg[1]);
                    327:                r1 = pop(long);
                    328:            }
                    329:            printlines((Lineno) r0, (Lineno) r1);
                    330:            break;
                    331: 
                    332:        case O_FUNC:
                    333:            if (p->value.arg[0] == nil) {
                    334:                printname(stdout, curfunc);
                    335:                putchar('\n');
                    336:            } else {
                    337:                s = p->value.arg[0]->value.sym;
                    338:                find(f, s->name) where
                    339:                    f->class == FUNC or f->class == PROC
                    340:                endfind(f);
                    341:                if (f == nil) {
                    342:                    error("%s is not a procedure or function", symname(s));
                    343:                }
                    344:                curfunc = f;
                    345:                addr = codeloc(curfunc);
                    346:                if (addr != NOADDR) {
                    347:                    setsource(srcfilename(addr));
                    348:                    cursrcline = srcline(addr) - 5;
                    349:                    if (cursrcline < 1) {
                    350:                        cursrcline = 1;
                    351:                    }
                    352:                }
                    353:            }
                    354:            break;
                    355: 
                    356:        case O_EXAMINE:
                    357:            eval(p->value.examine.beginaddr);
                    358:            r0 = pop(long);
                    359:            if (p->value.examine.endaddr == nil) {
                    360:                n = p->value.examine.count;
                    361:                if (n == 0) {
                    362:                    printvalue(r0, p->value.examine.mode);
                    363:                } else if (streq(p->value.examine.mode, "i")) {
                    364:                    printninst(n, (Address) r0);
                    365:                } else {
                    366:                    printndata(n, (Address) r0, p->value.examine.mode);
                    367:                }
                    368:            } else {
                    369:                eval(p->value.examine.endaddr);
                    370:                r1 = pop(long);
                    371:                if (streq(p->value.examine.mode, "i")) {
                    372:                    printinst((Address)r0, (Address)r1);
                    373:                } else {
                    374:                    printdata((Address)r0, (Address)r1, p->value.examine.mode);
                    375:                }
                    376:            }
                    377:            break;
                    378: 
                    379:        case O_PRINT:
                    380:            for (n1 = p->value.arg[0]; n1 != nil; n1 = n1->value.arg[1]) {
                    381:                eval(n1->value.arg[0]);
                    382:                printval(n1->value.arg[0]->nodetype);
                    383:                putchar(' ');
                    384:            }
                    385:            putchar('\n');
                    386:            break;
                    387: 
                    388:        case O_PSYM:
                    389:            if (p->value.arg[0]->op == O_SYM) {
                    390:                psym(p->value.arg[0]->value.sym);
                    391:            } else {
                    392:                psym(p->value.arg[0]->nodetype);
                    393:            }
                    394:            break;
                    395: 
                    396:        case O_QLINE:
                    397:            eval(p->value.arg[1]);
                    398:            break;
                    399: 
                    400:        case O_STEP:
                    401:            b = inst_tracing;
                    402:            inst_tracing = (Boolean) (not p->value.step.source);
                    403:            if (p->value.step.skipcalls) {
                    404:                next();
                    405:            } else {
                    406:                stepc();
                    407:            }
                    408:            inst_tracing = b;
                    409:            useInstLoc = (Boolean) (not p->value.step.source);
                    410:            printnews();
                    411:            break;
                    412: 
                    413:        case O_WHATIS:
                    414:            if (p->value.arg[0]->op == O_SYM) {
                    415:                printdecl(p->value.arg[0]->value.sym);
                    416:            } else {
                    417:                printdecl(p->value.arg[0]->nodetype);
                    418:            }
                    419:            break;
                    420: 
                    421:        case O_WHERE:
                    422:            wherecmd();
                    423:            break;
                    424: 
                    425:        case O_WHEREIS:
                    426:            if (p->value.arg[0]->op == O_SYM) {
                    427:                printwhereis(stdout,p->value.arg[0]->value.sym);
                    428:            } else {
                    429:                printwhereis(stdout,p->value.arg[0]->nodetype);
                    430:            }
                    431:            break;
                    432: 
                    433:        case O_WHICH:
                    434:            if (p->value.arg[0]->op == O_SYM) {
                    435:                printwhich(stdout,p->value.arg[0]->value.sym);
                    436:            } else {
                    437:                printwhich(stdout,p->value.arg[0]->nodetype);
                    438:            }
                    439:            putchar('\n');
                    440:            break;
                    441: 
                    442:        case O_ALIAS:
                    443:            n1 = p->value.arg[0];
                    444:            n2 = p->value.arg[1];
                    445:            if (n1 == nil) {
                    446:                print_alias(nil);
                    447:            } else if (n2 == nil) {
                    448:                print_alias(n1->value.name);
                    449:            } else {
                    450:                enter_alias(n1->value.name, n2->value.name);
                    451:            }
                    452:            break;
                    453: 
                    454:        case O_CALL:
                    455:            callproc(p->value.arg[0], p->value.arg[1]);
                    456:            break;
                    457: 
                    458:        case O_CATCH:
                    459:            psigtrace(process, p->value.lcon, true);
                    460:            break;
                    461: 
                    462:        case O_EDIT:
                    463:            edit(p->value.scon);
                    464:            break;
                    465: 
                    466:         case O_DEBUG:
                    467:             debug(p);
                    468:            break;
                    469: 
                    470:        case O_DUMP:
                    471:            dump();
                    472:            break;
                    473: 
                    474:        case O_GRIPE:
                    475:            gripe();
                    476:            break;
                    477: 
                    478:        case O_HELP:
                    479:            help();
                    480:            break;
                    481: 
                    482:        case O_IGNORE:
                    483:            psigtrace(process, p->value.lcon, false);
                    484:            break;
                    485: 
                    486:        case O_RUN:
                    487:            run();
                    488:            break;
                    489: 
                    490:        case O_SOURCE:
                    491:            setinput(p->value.scon);
                    492:            break;
                    493: 
                    494:        case O_STATUS:
                    495:            status();
                    496:            break;
                    497: 
                    498:        case O_TRACE:
                    499:        case O_TRACEI:
                    500:            trace(p);
                    501:            break;
                    502: 
                    503:        case O_STOP:
                    504:        case O_STOPI:
                    505:            stop(p);
                    506:            break;
                    507: 
                    508:        case O_ADDEVENT:
                    509:            addevent(p->value.event.cond, p->value.event.actions);
                    510:            break;
                    511: 
                    512:        case O_DELETE:
                    513:            delevent((unsigned int) p->value.lcon);
                    514:            break;
                    515: 
                    516:        case O_ENDX:
                    517:            endprogram();
                    518:            break;
                    519: 
                    520:        case O_IF:
                    521:            if (cond(p->value.event.cond)) {
                    522:                evalcmdlist(p->value.event.actions);
                    523:            }
                    524:            break;
                    525: 
                    526:        case O_ONCE:
                    527:            event_once(p->value.event.cond, p->value.event.actions);
                    528:            break;
                    529: 
                    530:        case O_PRINTCALL:
                    531:            printcall(p->value.sym, whatblock(return_addr()));
                    532:            break;
                    533: 
                    534:        case O_PRINTIFCHANGED:
                    535:            printifchanged(p->value.arg[0]);
                    536:            break;
                    537: 
                    538:        case O_PRINTRTN:
                    539:            printrtn(p->value.sym);
                    540:            break;
                    541: 
                    542:        case O_PRINTSRCPOS:
                    543:            getsrcpos();
                    544:            if (p->value.arg[0] == nil) {
                    545:                printsrcpos();
                    546:                putchar('\n');
                    547:                printlines(curline, curline);
                    548:            } else if (p->value.arg[0]->op == O_QLINE) {
                    549:                if (p->value.arg[0]->value.arg[1]->value.lcon == 0) {
                    550:                    printf("tracei: ");
                    551:                    printinst(pc, pc);
                    552:                } else {
                    553:                    printf("trace:  ");
                    554:                    printlines(curline, curline);
                    555:                }
                    556:            } else {
                    557:                printsrcpos();
                    558:                printf(": ");
                    559:                eval(p->value.arg[0]);
                    560:                prtree(stdout, p->value.arg[0]);
                    561:                printf(" = ");
                    562:                printval(p->value.arg[0]->nodetype);
                    563:                putchar('\n');
                    564:            }
                    565:            break;
                    566: 
                    567:        case O_PROCRTN:
                    568:            procreturn(p->value.sym);
                    569:            break;
                    570: 
                    571:        case O_STOPIFCHANGED:
                    572:            stopifchanged(p->value.arg[0]);
                    573:            break;
                    574: 
                    575:        case O_STOPX:
                    576:            isstopped = true;
                    577:            break;
                    578: 
                    579:        case O_TRACEON:
                    580:            traceon(p->value.trace.inst, p->value.trace.event,
                    581:                p->value.trace.actions);
                    582:            break;
                    583: 
                    584:        case O_TRACEOFF:
                    585:            traceoff(p->value.lcon);
                    586:            break;
                    587: 
                    588:        default:
                    589:            panic("eval: bad op %d", p->op);
                    590:     }
                    591:  if(debug_flag[2]) { 
                    592:        fprintf(stderr," evaluated %s \n",showoperator(p->op));
                    593:  }
                    594:            
                    595: }
                    596: 
                    597: /*
                    598:  * Evaluate a list of commands.
                    599:  */
                    600: 
                    601: public evalcmdlist(cl)
                    602: Cmdlist cl;
                    603: {
                    604:     Command c;
                    605: 
                    606:     foreach (Command, c, cl)
                    607:        evalcmd(c);
                    608:     endfor
                    609: }
                    610: 
                    611: /*
                    612:  * Push "len" bytes onto the expression stack from address "addr"
                    613:  * in the process.  If there isn't room on the stack, print an error message.
                    614:  */
                    615: 
                    616: public rpush(addr, len)
                    617: Address addr;
                    618: int len;
                    619: {
                    620:     if (not canpush(len)) {
                    621:        error("expression too large to evaluate");
                    622:     } else {
                    623:        chksp();
                    624:        dread(sp, addr, len);
                    625:        sp += len;
                    626:     }
                    627: }
                    628: 
                    629: /*
                    630:  * Check if the stack has n bytes available.
                    631:  */
                    632: 
                    633: public Boolean canpush(n)
                    634: Integer n;
                    635: {
                    636:     return (Boolean) (sp + n < &stack[STACKSIZE]);
                    637: }
                    638: 
                    639: /*
                    640:  * Push a small scalar of the given type onto the stack.
                    641:  */
                    642: 
                    643: public pushsmall(t, v)
                    644: Symbol t;
                    645: long v;
                    646: {
                    647:     register Integer s;
                    648: 
                    649:     s = size(t);
                    650:     switch (s) {
                    651:        case sizeof(char):
                    652:            push(char, v);
                    653:            break;
                    654: 
                    655:        case sizeof(short):
                    656:            push(short, v);
                    657:            break;
                    658: 
                    659:        case sizeof(long):
                    660:            push(long, v);
                    661:            break;
                    662: 
                    663:        default:
                    664:            panic("bad size %d in popsmall", s);
                    665:     }
                    666: }
                    667: 
                    668: /*
                    669:  * Pop an item of the given type which is assumed to be no larger
                    670:  * than a long and return it expanded into a long.
                    671:  */
                    672: 
                    673: public long popsmall(t)
                    674: Symbol t;
                    675: {
                    676:     long r;
                    677: 
                    678:     switch (size(t)) {
                    679:        case sizeof(char):
                    680:            r = (long) pop(char);
                    681:            break;
                    682: 
                    683:        case sizeof(short):
                    684:            r = (long) pop(short);
                    685:            break;
                    686: 
                    687:        case sizeof(long):
                    688:            r = pop(long);
                    689:            break;
                    690: 
                    691:        default:
                    692:            panic("popsmall: size is %d", size(t));
                    693:     }
                    694:     return r;
                    695: }
                    696: 
                    697: /*
                    698:  * Evaluate a conditional expression.
                    699:  */
                    700: 
                    701: public Boolean cond(p)
                    702: Node p;
                    703: {
                    704:     register Boolean b;
                    705: 
                    706:     if (p == nil) {
                    707:        b = true;
                    708:     } else {
                    709:        eval(p);
                    710:        b = (Boolean) pop(Boolrep);
                    711:     }
                    712:     return b;
                    713: }
                    714: 
                    715: /*
                    716:  * Return the address corresponding to a given tree.
                    717:  */
                    718: 
                    719: public Address lval(p)
                    720: Node p;
                    721: {
                    722:     if (p->op == O_RVAL) {
                    723:        eval(p->value.arg[0]);
                    724:     } else {
                    725:        eval(p);
                    726:     }
                    727:     return (Address) (pop(long));
                    728: }
                    729: 
                    730: /*
                    731:  * Process a trace command, translating into the appropriate events
                    732:  * and associated actions.
                    733:  */
                    734: 
                    735: public trace(p)
                    736: Node p;
                    737: {
                    738:     Node exp, place, cond;
                    739:     Node left;
                    740: 
                    741:     exp = p->value.arg[0];
                    742:     place = p->value.arg[1];
                    743:     cond = p->value.arg[2];
                    744:     if (exp == nil) {
                    745:        traceall(p->op, place, cond);
                    746:     } else if (exp->op == O_QLINE or exp->op == O_LCON) {
                    747:        traceinst(p->op, exp, cond);
                    748:     } else if (place != nil and place->op == O_QLINE) {
                    749:        traceat(p->op, exp, place, cond);
                    750:     } else {
                    751:        left = exp;
                    752:        if (left->op == O_RVAL or left->op == O_CALL) {
                    753:            left = left->value.arg[0];
                    754:        }
                    755:        if (left->op == O_SYM and isblock(left->value.sym)) {
                    756:            traceproc(p->op, left->value.sym, place, cond);
                    757:        } else {
                    758:            tracedata(p->op, exp, place, cond);
                    759:        }
                    760:     }
                    761: }
                    762: 
                    763: /*
                    764:  * Set a breakpoint that will turn on tracing.
                    765:  */
                    766: 
                    767: private traceall(op, place, cond)
                    768: Operator op;
                    769: Node place;
                    770: Node cond;
                    771: {
                    772:     Symbol s;
                    773:     Node event;
                    774:     Command action;
                    775: 
                    776:     if (place == nil) {
                    777:        s = program;
                    778:     } else {
                    779:        s = place->value.sym;
                    780:     }
                    781:     event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, s));
                    782:     action = build(O_PRINTSRCPOS,
                    783:        build(O_QLINE, nil, build(O_LCON, (op == O_TRACE) ? 1 : 0)));
                    784:     if (cond != nil) {
                    785:        action = build(O_IF, cond, buildcmdlist(action));
                    786:     }
                    787:     action = build(O_TRACEON, (op == O_TRACEI), buildcmdlist(action));
                    788:     action->value.trace.event = addevent(event, buildcmdlist(action));
                    789:     if (isstdin()) {
                    790:        printevent(action->value.trace.event);
                    791:     }
                    792: }
                    793: 
                    794: /*
                    795:  * Set up the appropriate breakpoint for tracing an instruction.
                    796:  */
                    797: 
                    798: private traceinst(op, exp, cond)
                    799: Operator op;
                    800: Node exp;
                    801: Node cond;
                    802: {
                    803:     Node event, wh;
                    804:     Command action;
                    805:     Event e;
                    806: 
                    807:     if (exp->op == O_LCON) {
                    808:        wh = build(O_QLINE, build(O_SCON, cursource), exp);
                    809:     } else {
                    810:        wh = exp;
                    811:     }
                    812:     if (op == O_TRACEI) {
                    813:        event = build(O_EQ, build(O_SYM, pcsym), wh);
                    814:     } else {
                    815:        event = build(O_EQ, build(O_SYM, linesym), wh);
                    816:     }
                    817:     action = build(O_PRINTSRCPOS, wh);
                    818:     if (cond) {
                    819:        action = build(O_IF, cond, buildcmdlist(action));
                    820:     }
                    821:     e = addevent(event, buildcmdlist(action));
                    822:     if (isstdin()) {
                    823:        printevent(e);
                    824:     }
                    825: }
                    826: 
                    827: /*
                    828:  * Set a breakpoint to print an expression at a given line or address.
                    829:  */
                    830: 
                    831: private traceat(op, exp, place, cond)
                    832: Operator op;
                    833: Node exp;
                    834: Node place;
                    835: Node cond;
                    836: {
                    837:     Node event;
                    838:     Command action;
                    839:     Event e;
                    840: 
                    841:     if (op == O_TRACEI) {
                    842:        event = build(O_EQ, build(O_SYM, pcsym), place);
                    843:     } else {
                    844:        event = build(O_EQ, build(O_SYM, linesym), place);
                    845:     }
                    846:     action = build(O_PRINTSRCPOS, exp);
                    847:     if (cond != nil) {
                    848:        action = build(O_IF, cond, buildcmdlist(action));
                    849:     }
                    850:     e = addevent(event, buildcmdlist(action));
                    851:     if (isstdin()) {
                    852:        printevent(e);
                    853:     }
                    854: }
                    855: 
                    856: /*
                    857:  * Construct event for tracing a procedure.
                    858:  *
                    859:  * What we want here is
                    860:  *
                    861:  *     when $proc = p do
                    862:  *         if <condition> then
                    863:  *             printcall;
                    864:  *             once $pc = $retaddr do
                    865:  *                 printrtn;
                    866:  *             end;
                    867:  *         end if;
                    868:  *     end;
                    869:  *
                    870:  * Note that "once" is like "when" except that the event
                    871:  * deletes itself as part of its associated action.
                    872:  */
                    873: 
                    874: private traceproc(op, p, place, cond)
                    875: Operator op;
                    876: Symbol p;
                    877: Node place;
                    878: Node cond;
                    879: {
                    880:     Node event;
                    881:     Command action;
                    882:     Cmdlist actionlist;
                    883:     Event e;
                    884: 
                    885:     action = build(O_PRINTCALL, p);
                    886:     actionlist = list_alloc();
                    887:     cmdlist_append(action, actionlist);
                    888:     event = build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym));
                    889:     action = build(O_ONCE, event, buildcmdlist(build(O_PRINTRTN, p)));
                    890:     cmdlist_append(action, actionlist);
                    891:     if (cond != nil) {
                    892:        actionlist = buildcmdlist(build(O_IF, cond, actionlist));
                    893:     }
                    894:     event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p));
                    895:     e = addevent(event, actionlist);
                    896:     if (isstdin()) {
                    897:        printevent(e);
                    898:     }
                    899: }
                    900: 
                    901: /*
                    902:  * Set up breakpoint for tracing data.
                    903:  */
                    904: 
                    905: private tracedata(op, exp, place, cond)
                    906: Operator op;
                    907: Node exp;
                    908: Node place;
                    909: Node cond;
                    910: {
                    911:     Symbol p;
                    912:     Node event;
                    913:     Command action;
                    914: 
                    915:     p = (place == nil) ? tcontainer(exp) : place->value.sym;
                    916:     if (p == nil) {
                    917:        p = program;
                    918:     }
                    919:     action = build(O_PRINTIFCHANGED, exp);
                    920:     if (cond != nil) {
                    921:        action = build(O_IF, cond, buildcmdlist(action));
                    922:     }
                    923:     action = build(O_TRACEON, (op == O_TRACEI), buildcmdlist(action));
                    924:     event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p));
                    925:     action->value.trace.event = addevent(event, buildcmdlist(action));
                    926:     if (isstdin()) {
                    927:        printevent(action->value.trace.event);
                    928:     }
                    929: }
                    930: 
                    931: /*
                    932:  * Setting and unsetting of stops.
                    933:  */
                    934: 
                    935: public stop(p)
                    936: Node p;
                    937: {
                    938:     Node exp, place, cond, t;
                    939:     Symbol s;
                    940:     Command action;
                    941:     Event e;
                    942: 
                    943:     exp = p->value.arg[0];
                    944:     place = p->value.arg[1];
                    945:     cond = p->value.arg[2];
                    946:     if (exp != nil) {
                    947:        stopvar(p->op, exp, place, cond);
                    948:     } else {
                    949:        action = build(O_STOPX);
                    950:        if (cond != nil) {
                    951:            action = build(O_IF, cond, buildcmdlist(action));
                    952:        }
                    953:        if (place != nil and place->op == O_SYM) {
                    954:            s = place->value.sym;
                    955:            t = build(O_EQ, build(O_SYM, procsym), build(O_SYM, s));
                    956:            if (cond != nil) {
                    957:                action = build(O_TRACEON, (p->op == O_STOPI),
                    958:                    buildcmdlist(action));
                    959:                e = addevent(t, buildcmdlist(action));
                    960:                action->value.trace.event = e;
                    961:            } else {
                    962:                e = addevent(t, buildcmdlist(action));
                    963:            }
                    964:            if (isstdin()) {
                    965:                printevent(e);
                    966:            }
                    967:        } else {
                    968:            stopinst(p->op, place, cond, action);
                    969:        }
                    970:     }
                    971: }
                    972: 
                    973: private stopinst(op, place, cond, action)
                    974: Operator op;
                    975: Node place;
                    976: Node cond;
                    977: Command action;
                    978: {
                    979:     Node event;
                    980:     Event e;
                    981: 
                    982:     if (op == O_STOP) {
                    983:        event = build(O_EQ, build(O_SYM, linesym), place);
                    984:     } else {
                    985:        event = build(O_EQ, build(O_SYM, pcsym), place);
                    986:     }
                    987:     e = addevent(event, buildcmdlist(action));
                    988:     if (isstdin()) {
                    989:        printevent(e);
                    990:     }
                    991: }
                    992: 
                    993: /*
                    994:  * Implement stopping on assignment to a variable by adding it to
                    995:  * the variable list.
                    996:  */
                    997: 
                    998: private stopvar(op, exp, place, cond)
                    999: Operator op;
                   1000: Node exp;
                   1001: Node place;
                   1002: Node cond;
                   1003: {
                   1004:     Symbol p;
                   1005:     Node event;
                   1006:     Command action;
                   1007: 
                   1008:     if (place == nil) {
                   1009:        if (exp->op == O_LCON) {
                   1010:            p = program;
                   1011:        } else {
                   1012:            p = tcontainer(exp);
                   1013:            if (p == nil) {
                   1014:                p = program;
                   1015:            }
                   1016:        }
                   1017:     } else {
                   1018:        p = place->value.sym;
                   1019:     }
                   1020:     action = build(O_STOPIFCHANGED, exp);
                   1021:     if (cond != nil) {
                   1022:        action = build(O_IF, cond, buildcmdlist(action));
                   1023:     }
                   1024:     action = build(O_TRACEON, (op == O_STOPI), buildcmdlist(action));
                   1025:     event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p));
                   1026:     action->value.trace.event = addevent(event, buildcmdlist(action));
                   1027:     if (isstdin()) {
                   1028:        printevent(action->value.trace.event);
                   1029:     }
                   1030: }
                   1031: 
                   1032: /*
                   1033:  * Assign the value of an expression to a variable (or term).
                   1034:  */
                   1035: 
                   1036: public assign(var, exp)
                   1037: Node var;
                   1038: Node exp;
                   1039: {
                   1040:     Address addr;
                   1041:     int varsize;
                   1042:     char cvalue;
                   1043:     short svalue;
                   1044:     long lvalue;
                   1045: 
                   1046:     if (not compatible(var->nodetype, exp->nodetype)) {
                   1047:        error("incompatible types");
                   1048:     }
                   1049:     addr = lval(var);
                   1050:     eval(exp);
                   1051:     varsize = size(var->nodetype);
                   1052:     if (varsize < sizeof(long)) {
                   1053:        lvalue = pop(long);
                   1054:        switch (varsize) {
                   1055:            case sizeof(char):
                   1056:                cvalue = lvalue;
                   1057:                dwrite(&cvalue, addr, varsize);
                   1058:                break;
                   1059: 
                   1060:            case sizeof(short):
                   1061:                svalue = lvalue;
                   1062:                dwrite(&svalue, addr, varsize);
                   1063:                break;
                   1064: 
                   1065:            default:
                   1066:                panic("bad size %d", varsize);
                   1067:        }
                   1068:     } else {
                   1069:        sp -= varsize;
                   1070:        dwrite(sp, addr, varsize);
                   1071:     }
                   1072: }
                   1073: 
                   1074: /*
                   1075:  * Send some nasty mail to the current support person.
                   1076:  */
                   1077: 
                   1078: public gripe()
                   1079: {
                   1080:     typedef Operation();
                   1081:     Operation *old;
                   1082:     int pid, status;
                   1083: 
                   1084:     char *maintainer = "linton@berkeley";
                   1085: 
                   1086:     puts("Type control-D to end your message.  Be sure to include");
                   1087:     puts("your name and the name of the file you are debugging.");
                   1088:     putchar('\n');
                   1089:     old = signal(SIGINT, SIG_DFL);
                   1090:     pid = back("Mail", stdin, stdout, "-s", "dbx gripe", maintainer, nil);
                   1091:     signal(SIGINT, SIG_IGN);
                   1092:     pwait(pid, &status);
                   1093:     signal(SIGINT, old);
                   1094:     if (status == 0) {
                   1095:        puts("Thank you.");
                   1096:     } else {
                   1097:        puts("\nMail not sent.");
                   1098:     }
                   1099: }
                   1100: 
                   1101: /*
                   1102:  * Give the user some help.
                   1103:  */
                   1104: 
                   1105: public help()
                   1106: {
                   1107:     puts("run                    - begin execution of the program");
                   1108:     puts("cont                   - continue execution");
                   1109:     puts("step                   - single step one line");
                   1110:     puts("next                   - step to next line (skip over calls)");
                   1111:     puts("trace <line#>          - trace execution of the line");
                   1112:     puts("trace <proc>           - trace calls to the procedure");
                   1113:     puts("trace <var>            - trace changes to the variable");
                   1114:     puts("trace <exp> at <line#> - print <exp> when <line> is reached");
                   1115:     puts("stop at <line>         - suspend execution at the line");
                   1116:     puts("stop in <proc>         - suspend execution when <proc> is called");
                   1117:     puts("status                 - print trace/stop's in effect");
                   1118:     puts("delete <number>        - remove trace or stop of given number");
                   1119:     puts("call <proc>            - call the procedure");
                   1120:     puts("where                  - print currently active procedures");
                   1121:     puts("print <exp>            - print the value of the expression");
                   1122:     puts("whatis <name>          - print the declaration of the name");
                   1123:     puts("list <line>, <line>    - list source lines");
                   1124:     puts("edit <proc>            - edit file containing <proc>");
                   1125:     puts("gripe                  - send mail to the person in charge of dbx");
                   1126:     puts("quit                   - exit dbx");
                   1127: }
                   1128: 
                   1129: /*
                   1130:  * Divert output to the given file name.
                   1131:  * Cannot redirect to an existing file.
                   1132:  */
                   1133: 
                   1134: private int so_fd;
                   1135: private Boolean notstdout;
                   1136: 
                   1137: public setout(filename)
                   1138: String filename;
                   1139: {
                   1140:     File f;
                   1141: 
                   1142:     f = fopen(filename, "r");
                   1143:     if (f != nil) {
                   1144:        fclose(f);
                   1145:        error("%s: file already exists", filename);
                   1146:     } else {
                   1147:        so_fd = dup(1);
                   1148:        close(1);
                   1149:        if (creat(filename, 0666) == nil) {
                   1150:            unsetout();
                   1151:            error("can't create %s", filename);
                   1152:        }
                   1153:        notstdout = true;
                   1154:     }
                   1155: }
                   1156: 
                   1157: /*
                   1158:  * Revert output to standard output.
                   1159:  */
                   1160: 
                   1161: public unsetout()
                   1162: {
                   1163:     fflush(stdout);
                   1164:     close(1);
                   1165:     if (dup(so_fd) != 1) {
                   1166:        panic("standard out dup failed");
                   1167:     }
                   1168:     close(so_fd);
                   1169:     notstdout = false;
                   1170: }
                   1171: 
                   1172: /*
                   1173:  * Determine is standard output is currently being redirected
                   1174:  * to a file (as far as we know).
                   1175:  */
                   1176: 
                   1177: public Boolean isredirected()
                   1178: {
                   1179:     return notstdout;
                   1180: }

unix.superglobalmegacorp.com

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