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

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

unix.superglobalmegacorp.com

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