Annotation of 43BSDTahoe/ucb/pascal/pdx/tree/eval.c, revision 1.1.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.