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