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

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