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