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

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

unix.superglobalmegacorp.com

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