15543Slinton /* Copyright (c) 1982 Regents of the University of California */ 25543Slinton 3*6874Slinton static char sccsid[] = "@(#)eval.c 1.8 05/19/82"; 45543Slinton 55543Slinton /* 65562Slinton * Parse tree evaluation. 75543Slinton */ 85543Slinton 95543Slinton #include "defs.h" 105543Slinton #include "tree.h" 115543Slinton #include "sym.h" 125543Slinton #include "process.h" 135543Slinton #include "source.h" 145543Slinton #include "mappings.h" 155543Slinton #include "breakpoint.h" 165543Slinton #include "machine.h" 175543Slinton #include "tree.rep" 185543Slinton 196086Slinton #define Boolean char /* underlying representation type for booleans */ 206086Slinton 215543Slinton /* 225543Slinton * Evaluate a parse tree using a stack; value is left at top. 235543Slinton */ 245543Slinton 255562Slinton #define STACKSIZE 2000 265562Slinton 275562Slinton STACK stack[STACKSIZE]; 285543Slinton STACK *sp = &stack[0]; 295543Slinton 305543Slinton eval(p) 315543Slinton register NODE *p; 325543Slinton { 335782Slinton long r0, r1; 345782Slinton double fr0, fr1; 35*6874Slinton FILE *fp; 365543Slinton 375782Slinton if (p == NULL) { 385782Slinton return; 395782Slinton } 405782Slinton switch(degree(p->op)) { 415782Slinton case BINARY: 425782Slinton eval(p->right); 435782Slinton if (isreal(p->op)) { 445782Slinton fr1 = pop(double); 455782Slinton } else if (isint(p->op)) { 466076Slinton r1 = popsmall(p->right->nodetype); 475782Slinton } 485782Slinton /* fall through */ 495782Slinton case UNARY: 505782Slinton eval(p->left); 515782Slinton if (isreal(p->op)) { 525782Slinton fr0 = pop(double); 535782Slinton } else if (isint(p->op)) { 546076Slinton r0 = popsmall(p->left->nodetype); 555782Slinton } 565782Slinton break; 575782Slinton 585782Slinton default: 595782Slinton /* do nothing */; 605543Slinton } 615782Slinton switch(p->op) { 625782Slinton case O_NAME: { 635782Slinton SYM *s, *f; 645543Slinton 655782Slinton s = p->nameval; 665886Slinton if (!isvariable(s)) { 675886Slinton error("cannot evaluate a %s", classname(s)); 685886Slinton } else { 695886Slinton f = container(s); 705886Slinton if (!isactive(f)) { 715886Slinton error("\"%s\" is not active", name(f)); 725886Slinton } 736086Slinton push(long, address(s, NIL)); 745782Slinton } 755782Slinton break; 765782Slinton } 775543Slinton 785782Slinton case O_LCON: 795782Slinton switch (size(p->nodetype)) { 805782Slinton case sizeof(char): 815782Slinton push(char, p->lconval); 825782Slinton break; 835543Slinton 845782Slinton case sizeof(short): 855782Slinton push(short, p->lconval); 865782Slinton break; 875543Slinton 885782Slinton case sizeof(long): 895782Slinton push(long, p->lconval); 905782Slinton break; 915543Slinton 925782Slinton default: 935782Slinton panic("bad size %d for LCON", size(p->nodetype)); 945782Slinton } 955782Slinton break; 965543Slinton 975782Slinton case O_FCON: 985782Slinton push(double, p->fconval); 995782Slinton break; 1005543Slinton 1015782Slinton case O_SCON: { 1025782Slinton int len; 1035543Slinton 1045782Slinton len = size(p->nodetype); 1055782Slinton mov(p->sconval, sp, len); 1065782Slinton sp += len; 1075782Slinton break; 1085782Slinton } 1095543Slinton 1105782Slinton case O_INDEX: { 1115782Slinton int n; 1125782Slinton long i; 1135543Slinton 1146086Slinton n = pop(long); 1155782Slinton i = evalindex(p->left->nodetype, popsmall(p->right->nodetype)); 1166086Slinton push(long, n + i*size(p->nodetype)); 1175782Slinton break; 1185782Slinton } 1195543Slinton 1205782Slinton case O_INDIR: { 1215782Slinton ADDRESS a; 1225543Slinton 1235782Slinton a = pop(ADDRESS); 1245782Slinton if (a == 0) { 1255782Slinton error("reference through nil pointer"); 1265782Slinton } 1275782Slinton dread(sp, a, sizeof(ADDRESS)); 1285782Slinton sp += sizeof(ADDRESS); 1295782Slinton break; 1305782Slinton } 1315543Slinton 1325782Slinton /* 1335782Slinton * Get the value of the expression addressed by the top of the stack. 1346076Slinton * Push the result back on the stack. 1355782Slinton */ 1365543Slinton 1375782Slinton case O_RVAL: { 1385782Slinton ADDRESS addr, len; 1395782Slinton long i; 1405543Slinton 1416086Slinton addr = pop(long); 1425782Slinton if (addr == 0) { 1435782Slinton error("reference through nil pointer"); 1445782Slinton } 1455782Slinton len = size(p->nodetype); 1465782Slinton if (!rpush(addr, len)) { 1475782Slinton error("expression too large to evaluate"); 1485782Slinton } 1495782Slinton break; 1505782Slinton } 1515543Slinton 1525782Slinton case O_COMMA: 1535782Slinton break; 1545543Slinton 1555782Slinton case O_ITOF: 1565782Slinton push(double, (double) r0); 1575782Slinton break; 1585543Slinton 1595782Slinton case O_ADD: 1605782Slinton push(long, r0+r1); 1615782Slinton break; 1625543Slinton 1635782Slinton case O_ADDF: 1645782Slinton push(double, fr0+fr1); 1655782Slinton break; 1665543Slinton 1675782Slinton case O_SUB: 1685782Slinton push(long, r0-r1); 1695782Slinton break; 1705543Slinton 1715782Slinton case O_SUBF: 1725782Slinton push(double, fr0-fr1); 1735782Slinton break; 1745543Slinton 1755782Slinton case O_NEG: 1765782Slinton push(long, -r0); 1775782Slinton break; 1785543Slinton 1795782Slinton case O_NEGF: 1805782Slinton push(double, -fr0); 1815782Slinton break; 1825543Slinton 1835782Slinton case O_MUL: 1845782Slinton push(long, r0*r1); 1855782Slinton break; 1865543Slinton 1875782Slinton case O_MULF: 1885782Slinton push(double, fr0*fr1); 1895782Slinton break; 1905543Slinton 1915782Slinton case O_DIVF: 1925782Slinton if (fr1 == 0) { 1935782Slinton error("error: division by 0"); 1945782Slinton } 1955782Slinton push(double, fr0/fr1); 1965782Slinton break; 1975543Slinton 1985782Slinton case O_DIV: 1995782Slinton if (r1 == 0) { 2005782Slinton error("error: div by 0"); 2015782Slinton } 2025782Slinton push(long, r0/r1); 2035782Slinton break; 2045543Slinton 2055782Slinton case O_MOD: 2065782Slinton if (r1 == 0) { 2075782Slinton error("error: mod by 0"); 2085782Slinton } 2095782Slinton push(long, r0%r1); 2105782Slinton break; 2115543Slinton 2125782Slinton case O_LT: 2136086Slinton push(Boolean, r0 < r1); 2145782Slinton break; 2155543Slinton 2165782Slinton case O_LTF: 2176086Slinton push(Boolean, fr0 < fr1); 2185782Slinton break; 2195543Slinton 2205782Slinton case O_LE: 2216086Slinton push(Boolean, r0 <= r1); 2225782Slinton break; 2235543Slinton 2245782Slinton case O_LEF: 2256086Slinton push(Boolean, fr0 <= fr1); 2265782Slinton break; 2275543Slinton 2285782Slinton case O_GT: 2296086Slinton push(Boolean, r0 > r1); 2305782Slinton break; 2315543Slinton 2325782Slinton case O_GTF: 2336086Slinton push(Boolean, fr0 > fr1); 2345782Slinton break; 2355543Slinton 2365782Slinton case O_EQ: 2376086Slinton push(Boolean, r0 == r1); 2385782Slinton break; 2395543Slinton 2405782Slinton case O_EQF: 2416086Slinton push(Boolean, fr0 == fr1); 2425782Slinton break; 2435543Slinton 2445782Slinton case O_NE: 2456086Slinton push(Boolean, r0 != r1); 2465782Slinton break; 2475543Slinton 2485782Slinton case O_NEF: 2496086Slinton push(Boolean, fr0 != fr1); 2505782Slinton break; 2515543Slinton 2525782Slinton case O_AND: 2536086Slinton push(Boolean, r0 && r1); 2545782Slinton break; 2555543Slinton 2565782Slinton case O_OR: 2576086Slinton push(Boolean, r0 || r1); 2585782Slinton break; 2595543Slinton 2605782Slinton case O_ASSIGN: 2615782Slinton assign(p->left, p->right); 2625782Slinton break; 2635543Slinton 2645782Slinton case O_CHFILE: 2655782Slinton if (p->sconval == NIL) { 2665782Slinton printf("%s\n", cursource); 2675782Slinton } else { 268*6874Slinton fp = fopen(p->sconval, "r"); 269*6874Slinton if (fp == NIL) { 270*6874Slinton error("can't read \"%s\"", p->sconval); 271*6874Slinton } else { 272*6874Slinton fclose(fp); 273*6874Slinton skimsource(p->sconval); 274*6874Slinton } 2755782Slinton } 2765782Slinton break; 2775543Slinton 2785782Slinton case O_CONT: 2795782Slinton cont(); 2805782Slinton printnews(); 2815782Slinton break; 2825543Slinton 2835782Slinton case O_LIST: { 2845782Slinton SYM *b; 2856083Slinton ADDRESS addr; 2865543Slinton 2875782Slinton if (p->left->op == O_NAME) { 2885782Slinton b = p->left->nameval; 2895782Slinton if (!isblock(b)) { 2905782Slinton error("\"%s\" is not a procedure or function", name(b)); 2915543Slinton } 2926083Slinton addr = firstline(b); 2936083Slinton if (addr == -1) { 2946083Slinton error("\"%s\" is empty", name(b)); 2956083Slinton } 2966083Slinton skimsource(srcfilename(addr)); 2976083Slinton r0 = srcline(addr); 2985782Slinton r1 = r0 + 5; 2995782Slinton if (r1 > lastlinenum) { 3005782Slinton r1 = lastlinenum; 3015782Slinton } 3025782Slinton r0 = r0 - 5; 3035782Slinton if (r0 < 1) { 3045782Slinton r0 = 1; 3055782Slinton } 3065782Slinton } else { 3075782Slinton eval(p->left->right); 3085782Slinton eval(p->left->left); 3095782Slinton r0 = pop(long); 3105782Slinton r1 = pop(long); 3115782Slinton } 3125782Slinton printlines((LINENO) r0, (LINENO) r1); 3135782Slinton break; 3145782Slinton } 3155543Slinton 3165782Slinton case O_XI: 3175782Slinton case O_XD: 3185782Slinton { 3195782Slinton SYM *b; 3205543Slinton 3215782Slinton if (p->left->op == O_CALL) { 3225782Slinton b = p->left->left->nameval; 3235782Slinton r0 = codeloc(b); 3245782Slinton r1 = firstline(b); 3255782Slinton } else { 3265782Slinton eval(p->left->right); 3275782Slinton eval(p->left->left); 3285782Slinton r0 = pop(long); 3295782Slinton r1 = pop(long); 3305782Slinton } 3315782Slinton if (p->op == O_XI) { 3325782Slinton printinst((ADDRESS) r0, (ADDRESS) r1); 3335782Slinton } else { 3345782Slinton printdata((ADDRESS) r0, (ADDRESS) r1); 3355782Slinton } 3365782Slinton break; 3375782Slinton } 3385543Slinton 3395782Slinton case O_NEXT: 3405782Slinton next(); 3415782Slinton printnews(); 3425782Slinton break; 3435543Slinton 3445782Slinton case O_PRINT: { 3455782Slinton NODE *o; 3465543Slinton 3475782Slinton for (o = p->left; o != NIL; o = o->right) { 3485782Slinton eval(o->left); 3495782Slinton printval(o->left->nodetype); 3505782Slinton putchar(' '); 3515782Slinton } 3525782Slinton putchar('\n'); 3535782Slinton break; 3545782Slinton } 3555543Slinton 3565782Slinton case O_STEP: 3575782Slinton stepc(); 3585782Slinton printnews(); 3595782Slinton break; 3605543Slinton 3615782Slinton case O_WHATIS: 3625782Slinton if (p->left->op == O_NAME) { 3635782Slinton printdecl(p->left->nameval); 3645782Slinton } else { 3655782Slinton printdecl(p->left->nodetype); 3665782Slinton } 3675782Slinton break; 3685543Slinton 3695782Slinton case O_WHICH: 3705782Slinton printwhich(p->nameval); 3715782Slinton putchar('\n'); 3725782Slinton break; 3735543Slinton 3745782Slinton case O_WHERE: 3755782Slinton where(); 3765782Slinton break; 3775543Slinton 3785782Slinton case O_ALIAS: 3795782Slinton alias(p->left->sconval, p->right->sconval); 3805782Slinton break; 3815543Slinton 3825782Slinton case O_CALL: 3835782Slinton callproc(p->left, p->right); 3845782Slinton break; 3855543Slinton 3865782Slinton case O_EDIT: 3875782Slinton edit(p->sconval); 3885782Slinton break; 3895543Slinton 3905782Slinton case O_DUMP: 3915782Slinton dump(); 3925782Slinton break; 3935543Slinton 3945782Slinton case O_GRIPE: 3955782Slinton gripe(); 3965782Slinton break; 3975562Slinton 3985782Slinton case O_HELP: 3995782Slinton help(); 4005782Slinton break; 4015543Slinton 4025782Slinton case O_REMAKE: 4035782Slinton remake(); 4045782Slinton break; 4055543Slinton 4065782Slinton case O_RUN: 4075782Slinton run(); 4085782Slinton break; 4095543Slinton 4105782Slinton case O_SOURCE: 4115782Slinton setinput(p->sconval); 4125782Slinton break; 4135543Slinton 4145782Slinton case O_STATUS: 4155782Slinton status(); 4165782Slinton break; 4175543Slinton 4185782Slinton case O_TRACE: 4195782Slinton case O_TRACEI: 4205782Slinton trace(p->op, p->what, p->where, p->cond); 4215782Slinton if (isstdin()) { 4225782Slinton status(); 4235782Slinton } 4245782Slinton break; 4255543Slinton 4265782Slinton case O_STOP: 4275782Slinton case O_STOPI: 4285782Slinton stop(p->op, p->what, p->where, p->cond); 4295782Slinton if (isstdin()) { 4305782Slinton status(); 4315782Slinton } 4325782Slinton break; 4335543Slinton 4345782Slinton case O_DELETE: 4355782Slinton eval(p->left); 4365782Slinton delbp((unsigned int) pop(long)); 4375782Slinton break; 4385543Slinton 4395782Slinton default: 4405782Slinton panic("eval: bad op %d", p->op); 4415782Slinton } 4425543Slinton } 4435543Slinton 4445543Slinton /* 4455562Slinton * Push "len" bytes onto the expression stack from address "addr" 4465562Slinton * in the process. Normally TRUE is returned, however if there 4475562Slinton * isn't enough room on the stack, rpush returns FALSE. 4485562Slinton */ 4495562Slinton 4505562Slinton BOOLEAN rpush(addr, len) 4515562Slinton ADDRESS addr; 4525562Slinton int len; 4535562Slinton { 4545782Slinton BOOLEAN success; 4555562Slinton 4565782Slinton if (sp + len >= &stack[STACKSIZE]) { 4575782Slinton success = FALSE; 4585782Slinton } else { 4595782Slinton dread(sp, addr, len); 4605782Slinton sp += len; 4615782Slinton success = TRUE; 4625782Slinton } 4635782Slinton return success; 4645562Slinton } 4655562Slinton 4665562Slinton /* 4675782Slinton * Pop an item of the given type which is assumed to be no larger 4685782Slinton * than a long and return it expanded into a long. 4695782Slinton */ 4705782Slinton 4715782Slinton long popsmall(t) 4725782Slinton SYM *t; 4735782Slinton { 4745782Slinton long r; 4755782Slinton 4765782Slinton switch (size(t)) { 4775782Slinton case sizeof(char): 4785782Slinton r = (long) pop(char); 4795782Slinton break; 4805782Slinton 4815782Slinton case sizeof(short): 4825782Slinton r = (long) pop(short); 4835782Slinton break; 4845782Slinton 4855782Slinton case sizeof(long): 4865782Slinton r = pop(long); 4875782Slinton break; 4885782Slinton 4895782Slinton default: 4905782Slinton panic("popsmall: size is %d", size(t)); 4915782Slinton } 4925782Slinton return r; 4935782Slinton } 4945782Slinton 4955782Slinton /* 4965543Slinton * evaluate a conditional expression 4975543Slinton */ 4985543Slinton 4995543Slinton BOOLEAN cond(p) 5005543Slinton NODE *p; 5015543Slinton { 5025782Slinton if (p == NIL) { 5035782Slinton return(TRUE); 5045782Slinton } 5055782Slinton eval(p); 5065782Slinton return(pop(BOOLEAN)); 5075543Slinton } 5085543Slinton 5095543Slinton /* 5105543Slinton * Return the address corresponding to a given tree. 5115543Slinton */ 5125543Slinton 5135543Slinton ADDRESS lval(p) 5145543Slinton NODE *p; 5155543Slinton { 5165782Slinton eval(p); 5175782Slinton return(pop(ADDRESS)); 5185543Slinton } 519