# 2.11BSD#431 - /usr/src/ucb/PORT/pascal/pdx/tree/eval.c

##### Functions

    cond              X
    eval              X
    lval              X
    popsmall          X
    rpush             X

##### Macros

    Boolean           X
    STACKSIZE         X

       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: }

#### Defined functions

cond defined in line 516; used 2 times

- in line 426, 434

eval defined in line 36; used 11 times

- in line 48, 56, 313-314(2), 332-333(2), 354, 441, 522, 533
- in /usr/src/ucb/PORT/pascal/pdx/tree/assign.c line 35

lval defined in line 530; used 1 times

- in /usr/src/ucb/PORT/pascal/pdx/tree/assign.c line 34

popsmall defined in line 477; used 2 times

- in line 52, 60

rpush defined in line 456; used 1 times

- in line 152

#### Defined variables

sccsid defined in line 8; never used

#### Defined macros

Boolean defined in line 25; used 12 times

- in line 219-263(12)

STACKSIZE defined in line 31; used 2 times

- in line 33, 462

Last modified: 1985-06-07 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1300 |