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

unix.superglobalmegacorp.com

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