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