|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.