Annotation of 42BSD/ucb/pascal/pdx/tree/eval.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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