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
eval defined in line 36; used 11 times
lval defined in line 530; used 1 times
popsmall defined in line 477; used 2 times
rpush defined in line 456; used 1 times

Defined variables

sccsid defined in line 8; never used

Defined macros

Boolean defined in line 25; used 12 times
STACKSIZE defined in line 31; used 2 times
Last modified: 1985-06-07
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2871
Valid CSS Valid XHTML 1.0 Strict