Annotation of 43BSD/ucb/pascal/pdx/tree/eval.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1980 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  */
        !             6: 
        !             7: #ifndef lint
        !             8: static char sccsid[] = "@(#)eval.c     5.1 (Berkeley) 6/6/85";
        !             9: #endif not lint
        !            10: 
        !            11: /*
        !            12:  * Parse tree evaluation.
        !            13:  */
        !            14: 
        !            15: #include "defs.h"
        !            16: #include "tree.h"
        !            17: #include "sym.h"
        !            18: #include "process.h"
        !            19: #include "source.h"
        !            20: #include "mappings.h"
        !            21: #include "breakpoint.h"
        !            22: #include "machine.h"
        !            23: #include "tree.rep"
        !            24: 
        !            25: #define Boolean char   /* underlying representation type for booleans */
        !            26: 
        !            27: /*
        !            28:  * Evaluate a parse tree using a stack; value is left at top.
        !            29:  */
        !            30: 
        !            31: #define STACKSIZE 2000
        !            32: 
        !            33: STACK stack[STACKSIZE];
        !            34: STACK *sp = &stack[0];
        !            35: 
        !            36: eval(p)
        !            37: register NODE *p;
        !            38: {
        !            39:     long r0, r1;
        !            40:     double fr0, fr1;
        !            41:     FILE *fp;
        !            42: 
        !            43:     if (p == NULL) {
        !            44:        return;
        !            45:     }
        !            46:     switch(degree(p->op)) {
        !            47:        case BINARY:
        !            48:            eval(p->right);
        !            49:            if (isreal(p->op)) {
        !            50:                fr1 = pop(double);
        !            51:            } else if (isint(p->op)) {
        !            52:                r1 = popsmall(p->right->nodetype);
        !            53:            }
        !            54:            /* fall through */
        !            55:        case UNARY:
        !            56:            eval(p->left);
        !            57:            if (isreal(p->op)) {
        !            58:                fr0 = pop(double);
        !            59:            } else if (isint(p->op)) {
        !            60:                r0 = popsmall(p->left->nodetype);
        !            61:            }
        !            62:            break;
        !            63: 
        !            64:        default:
        !            65:            /* do nothing */;
        !            66:        }
        !            67:     switch(p->op) {
        !            68:        case O_NAME: {
        !            69:            SYM *s, *f;
        !            70: 
        !            71:            s = p->nameval;
        !            72:            if (!isvariable(s)) {
        !            73:                error("cannot evaluate a %s", classname(s));
        !            74:            } else {
        !            75:                f = container(s);
        !            76:                if (!isactive(f)) {
        !            77:                    error("\"%s\" is not active", name(f));
        !            78:                }
        !            79:                push(long, address(s, NIL));
        !            80:            }
        !            81:            break;
        !            82:        }
        !            83: 
        !            84:        case O_LCON:
        !            85:            switch (size(p->nodetype)) {
        !            86:                case sizeof(char):
        !            87:                    push(char, p->lconval);
        !            88:                    break;
        !            89: 
        !            90:                case sizeof(short):
        !            91:                    push(short, p->lconval);
        !            92:                    break;
        !            93: 
        !            94:                case sizeof(long):
        !            95:                    push(long, p->lconval);
        !            96:                    break;
        !            97: 
        !            98:                default:
        !            99:                    panic("bad size %d for LCON", size(p->nodetype));
        !           100:            }
        !           101:            break;
        !           102: 
        !           103:        case O_FCON:
        !           104:            push(double, p->fconval);
        !           105:            break;
        !           106: 
        !           107:        case O_SCON: {
        !           108:            int len;
        !           109: 
        !           110:            len = size(p->nodetype);
        !           111:            mov(p->sconval, sp, len);
        !           112:            sp += len;
        !           113:            break;
        !           114:        }
        !           115: 
        !           116:        case O_INDEX: {
        !           117:            long n;     /* base address for array */
        !           118:            long i;     /* index - lower bound */
        !           119: 
        !           120:            n = pop(long);
        !           121:            i = evalindex(p->left->nodetype, p->right);
        !           122:            push(long, n + i*size(p->nodetype));
        !           123:            break;
        !           124:        }
        !           125: 
        !           126:        case O_INDIR: {
        !           127:            ADDRESS a;
        !           128: 
        !           129:            a = pop(ADDRESS);
        !           130:            if (a == 0) {
        !           131:                error("reference through nil pointer");
        !           132:            }
        !           133:            dread(sp, a, sizeof(ADDRESS));
        !           134:            sp += sizeof(ADDRESS);
        !           135:            break;
        !           136:        }
        !           137: 
        !           138:        /*
        !           139:         * Get the value of the expression addressed by the top of the stack.
        !           140:         * Push the result back on the stack.
        !           141:         */
        !           142: 
        !           143:        case O_RVAL: {
        !           144:            ADDRESS addr, len;
        !           145:            long i;
        !           146: 
        !           147:            addr = pop(long);
        !           148:            if (addr == 0) {
        !           149:                error("reference through nil pointer");
        !           150:            }
        !           151:            len = size(p->nodetype);
        !           152:            if (!rpush(addr, len)) {
        !           153:                error("expression too large to evaluate");
        !           154:            }
        !           155:            break;
        !           156:        }
        !           157: 
        !           158:        case O_COMMA:
        !           159:            break;
        !           160: 
        !           161:        case O_ITOF:
        !           162:            push(double, (double) r0);
        !           163:            break;
        !           164: 
        !           165:        case O_ADD:
        !           166:            push(long, r0+r1);
        !           167:            break;
        !           168: 
        !           169:        case O_ADDF:
        !           170:            push(double, fr0+fr1);
        !           171:            break;
        !           172: 
        !           173:        case O_SUB:
        !           174:            push(long, r0-r1);
        !           175:            break;
        !           176: 
        !           177:        case O_SUBF:
        !           178:            push(double, fr0-fr1);
        !           179:            break;
        !           180: 
        !           181:        case O_NEG:
        !           182:            push(long, -r0);
        !           183:            break;
        !           184: 
        !           185:        case O_NEGF:
        !           186:            push(double, -fr0);
        !           187:            break;
        !           188: 
        !           189:        case O_MUL:
        !           190:            push(long, r0*r1);
        !           191:            break;
        !           192: 
        !           193:        case O_MULF:
        !           194:            push(double, fr0*fr1);
        !           195:            break;
        !           196: 
        !           197:        case O_DIVF:
        !           198:            if (fr1 == 0) {
        !           199:                error("error: division by 0");
        !           200:            }
        !           201:            push(double, fr0/fr1);
        !           202:            break;
        !           203: 
        !           204:        case O_DIV:
        !           205:            if (r1 == 0) {
        !           206:                error("error: div by 0");
        !           207:            }
        !           208:            push(long, r0/r1);
        !           209:            break;
        !           210: 
        !           211:        case O_MOD:
        !           212:            if (r1 == 0) {
        !           213:                error("error: mod by 0");
        !           214:            }
        !           215:            push(long, r0%r1);
        !           216:            break;
        !           217: 
        !           218:        case O_LT:
        !           219:            push(Boolean, r0 < r1);
        !           220:            break;
        !           221: 
        !           222:        case O_LTF:
        !           223:            push(Boolean, fr0 < fr1);
        !           224:            break;
        !           225: 
        !           226:        case O_LE:
        !           227:            push(Boolean, r0 <= r1);
        !           228:            break;
        !           229: 
        !           230:        case O_LEF:
        !           231:            push(Boolean, fr0 <= fr1);
        !           232:            break;
        !           233: 
        !           234:        case O_GT:
        !           235:            push(Boolean, r0 > r1);
        !           236:            break;
        !           237: 
        !           238:        case O_GTF:
        !           239:            push(Boolean, fr0 > fr1);
        !           240:            break;
        !           241: 
        !           242:        case O_EQ:
        !           243:            push(Boolean, r0 == r1);
        !           244:            break;
        !           245: 
        !           246:        case O_EQF:
        !           247:            push(Boolean, fr0 == fr1);
        !           248:            break;
        !           249: 
        !           250:        case O_NE:
        !           251:            push(Boolean, r0 != r1);
        !           252:            break;
        !           253: 
        !           254:        case O_NEF:
        !           255:            push(Boolean, fr0 != fr1);
        !           256:            break;
        !           257: 
        !           258:        case O_AND:
        !           259:            push(Boolean, r0 && r1);
        !           260:            break;
        !           261: 
        !           262:        case O_OR:
        !           263:            push(Boolean, r0 || r1);
        !           264:            break;
        !           265: 
        !           266:        case O_ASSIGN:
        !           267:            assign(p->left, p->right);
        !           268:            break;
        !           269: 
        !           270:        case O_CHFILE:
        !           271:            if (p->sconval == NIL) {
        !           272:                printf("%s\n", cursource);
        !           273:            } else {
        !           274:                fp = fopen(p->sconval, "r");
        !           275:                if (fp == NIL) {
        !           276:                    error("can't read \"%s\"", p->sconval);
        !           277:                } else {
        !           278:                    fclose(fp);
        !           279:                    skimsource(p->sconval);
        !           280:                }
        !           281:            }
        !           282:            break;
        !           283: 
        !           284:        case O_CONT:
        !           285:            cont();
        !           286:            printnews();
        !           287:            break;
        !           288: 
        !           289:        case O_LIST: {
        !           290:            SYM *b;
        !           291:            ADDRESS addr;
        !           292: 
        !           293:            if (p->left->op == O_NAME) {
        !           294:                b = p->left->nameval;
        !           295:                if (!isblock(b)) {
        !           296:                    error("\"%s\" is not a procedure or function", name(b));
        !           297:                }
        !           298:                addr = firstline(b);
        !           299:                if (addr == -1) {
        !           300:                    error("\"%s\" is empty", name(b));
        !           301:                }
        !           302:                skimsource(srcfilename(addr));
        !           303:                r0 = srcline(addr);
        !           304:                r1 = r0 + 5;
        !           305:                if (r1 > lastlinenum) {
        !           306:                    r1 = lastlinenum;
        !           307:                }
        !           308:                r0 = r0 - 5;
        !           309:                if (r0 < 1) {
        !           310:                    r0 = 1;
        !           311:                }
        !           312:            } else {
        !           313:                eval(p->left->right);
        !           314:                eval(p->left->left);
        !           315:                r0 = pop(long);
        !           316:                r1 = pop(long);
        !           317:            }
        !           318:            printlines((LINENO) r0, (LINENO) r1);
        !           319:            break;
        !           320:        }
        !           321: 
        !           322:        case O_XI:
        !           323:        case O_XD:
        !           324:        {
        !           325:            SYM *b;
        !           326: 
        !           327:            if (p->left->op == O_CALL) {
        !           328:                b = p->left->left->nameval;
        !           329:                r0 = codeloc(b);
        !           330:                r1 = firstline(b);
        !           331:            } else {
        !           332:                eval(p->left->right);
        !           333:                eval(p->left->left);
        !           334:                r0 = pop(long);
        !           335:                r1 = pop(long);
        !           336:            }
        !           337:            if (p->op == O_XI)  {
        !           338:                printinst((ADDRESS) r0, (ADDRESS) r1);
        !           339:            } else {
        !           340:                printdata((ADDRESS) r0, (ADDRESS) r1);
        !           341:            }
        !           342:            break;
        !           343:        }
        !           344: 
        !           345:        case O_NEXT:
        !           346:            next();
        !           347:            printnews();
        !           348:            break;
        !           349: 
        !           350:        case O_PRINT: {
        !           351:            NODE *o;
        !           352: 
        !           353:            for (o = p->left; o != NIL; o = o->right) {
        !           354:                eval(o->left);
        !           355:                printval(o->left->nodetype);
        !           356:                putchar(' ');
        !           357:            }
        !           358:            putchar('\n');
        !           359:            break;
        !           360:        }
        !           361: 
        !           362:        case O_STEP:
        !           363:            stepc();
        !           364:            printnews();
        !           365:            break;
        !           366: 
        !           367:        case O_WHATIS:
        !           368:            if (p->left->op == O_NAME) {
        !           369:                printdecl(p->left->nameval);
        !           370:            } else {
        !           371:                printdecl(p->left->nodetype);
        !           372:            }
        !           373:            break;
        !           374: 
        !           375:        case O_WHICH:
        !           376:            printwhich(p->nameval);
        !           377:            putchar('\n');
        !           378:            break;
        !           379: 
        !           380:        case O_WHERE:
        !           381:            where();
        !           382:            break;
        !           383: 
        !           384:        case O_ALIAS:
        !           385:            alias(p->left->sconval, p->right->sconval);
        !           386:            break;
        !           387: 
        !           388:        case O_CALL:
        !           389:            callproc(p->left, p->right);
        !           390:            break;
        !           391: 
        !           392:        case O_EDIT:
        !           393:            edit(p->sconval);
        !           394:            break;
        !           395: 
        !           396:        case O_DUMP:
        !           397:            dump();
        !           398:            break;
        !           399: 
        !           400:        case O_GRIPE:
        !           401:            gripe();
        !           402:            break;
        !           403: 
        !           404:        case O_HELP:
        !           405:            help();
        !           406:            break;
        !           407: 
        !           408:        case O_REMAKE:
        !           409:            remake();
        !           410:            break;
        !           411: 
        !           412:        case O_RUN:
        !           413:            run();
        !           414:            break;
        !           415: 
        !           416:        case O_SOURCE:
        !           417:            setinput(p->sconval);
        !           418:            break;
        !           419: 
        !           420:        case O_STATUS:
        !           421:            status();
        !           422:            break;
        !           423: 
        !           424:        case O_TRACE:
        !           425:        case O_TRACEI:
        !           426:            trace(p->op, p->what, p->where, p->cond);
        !           427:            if (isstdin()) {
        !           428:                status();
        !           429:            }
        !           430:            break;
        !           431: 
        !           432:        case O_STOP:
        !           433:        case O_STOPI:
        !           434:            stop(p->op, p->what, p->where, p->cond);
        !           435:            if (isstdin()) {
        !           436:                status();
        !           437:            }
        !           438:            break;
        !           439: 
        !           440:        case O_DELETE:
        !           441:            eval(p->left);
        !           442:            delbp((unsigned int) pop(long));
        !           443:            break;
        !           444: 
        !           445:        default:
        !           446:            panic("eval: bad op %d", p->op);
        !           447:     }
        !           448: }
        !           449: 
        !           450: /*
        !           451:  * Push "len" bytes onto the expression stack from address "addr"
        !           452:  * in the process.  Normally TRUE is returned, however if there
        !           453:  * isn't enough room on the stack, rpush returns FALSE.
        !           454:  */
        !           455: 
        !           456: BOOLEAN rpush(addr, len)
        !           457: ADDRESS addr;
        !           458: int len;
        !           459: {
        !           460:     BOOLEAN success;
        !           461: 
        !           462:     if (sp + len >= &stack[STACKSIZE]) {
        !           463:        success = FALSE;
        !           464:     } else {
        !           465:        dread(sp, addr, len);
        !           466:        sp += len;
        !           467:        success = TRUE;
        !           468:     }
        !           469:     return success;
        !           470: }
        !           471: 
        !           472: /*
        !           473:  * Pop an item of the given type which is assumed to be no larger
        !           474:  * than a long and return it expanded into a long.
        !           475:  */
        !           476: 
        !           477: long popsmall(t)
        !           478: SYM *t;
        !           479: {
        !           480:     long r;
        !           481: 
        !           482:     switch (size(t)) {
        !           483:        case sizeof(char):
        !           484:            r = (long) pop(char);
        !           485:            break;
        !           486: 
        !           487:        case sizeof(short):
        !           488:            r = (long) pop(short);
        !           489:            break;
        !           490: 
        !           491:        case sizeof(long):
        !           492:            r = pop(long);
        !           493:            break;
        !           494: 
        !           495:        /*
        !           496:         * A bit of a kludge here.  If an array element is a record,
        !           497:         * the dot operation will be converted into an addition with
        !           498:         * the record operand having a type whose size may be larger
        !           499:         * than a word.  Now actually this is a pointer, but the subscript
        !           500:         * operation isn't aware of this, so it's just hacked here.
        !           501:         *
        !           502:         * The right thing to do is to make dot directly evaluated
        !           503:         * instead of changing it into addition.
        !           504:         */
        !           505:        default:
        !           506:            r = pop(ADDRESS);
        !           507:            break;
        !           508:     }
        !           509:     return r;
        !           510: }
        !           511: 
        !           512: /*
        !           513:  * evaluate a conditional expression
        !           514:  */
        !           515: 
        !           516: BOOLEAN cond(p)
        !           517: NODE *p;
        !           518: {
        !           519:     if (p == NIL) {
        !           520:        return(TRUE);
        !           521:     }
        !           522:     eval(p);
        !           523:     return(pop(BOOLEAN));
        !           524: }
        !           525: 
        !           526: /*
        !           527:  * Return the address corresponding to a given tree.
        !           528:  */
        !           529: 
        !           530: ADDRESS lval(p)
        !           531: NODE *p;
        !           532: {
        !           533:     eval(p);
        !           534:     return(pop(ADDRESS));
        !           535: }

unix.superglobalmegacorp.com

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