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

unix.superglobalmegacorp.com

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