15543Slinton /* Copyright (c) 1982 Regents of the University of California */ 25543Slinton 3*6083Slinton static char sccsid[] = "@(#)eval.c 1.6 03/08/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 195543Slinton /* 205543Slinton * Evaluate a parse tree using a stack; value is left at top. 215543Slinton */ 225543Slinton 235562Slinton #define STACKSIZE 2000 245562Slinton 255562Slinton STACK stack[STACKSIZE]; 265543Slinton STACK *sp = &stack[0]; 275543Slinton 285543Slinton eval(p) 295543Slinton register NODE *p; 305543Slinton { 315782Slinton long r0, r1; 325782Slinton double fr0, fr1; 335543Slinton 345782Slinton if (p == NULL) { 355782Slinton return; 365782Slinton } 375782Slinton switch(degree(p->op)) { 385782Slinton case BINARY: 395782Slinton eval(p->right); 405782Slinton if (isreal(p->op)) { 415782Slinton fr1 = pop(double); 425782Slinton } else if (isint(p->op)) { 436076Slinton r1 = popsmall(p->right->nodetype); 445782Slinton } 455782Slinton /* fall through */ 465782Slinton case UNARY: 475782Slinton eval(p->left); 485782Slinton if (isreal(p->op)) { 495782Slinton fr0 = pop(double); 505782Slinton } else if (isint(p->op)) { 516076Slinton r0 = popsmall(p->left->nodetype); 525782Slinton } 535782Slinton break; 545782Slinton 555782Slinton default: 565782Slinton /* do nothing */; 575543Slinton } 585782Slinton switch(p->op) { 595782Slinton case O_NAME: { 605782Slinton SYM *s, *f; 615543Slinton 625782Slinton s = p->nameval; 635886Slinton if (!isvariable(s)) { 645886Slinton error("cannot evaluate a %s", classname(s)); 655886Slinton } else { 665886Slinton f = container(s); 675886Slinton if (!isactive(f)) { 685886Slinton error("\"%s\" is not active", name(f)); 695886Slinton } 705886Slinton push(int, address(s, NIL)); 715782Slinton } 725782Slinton break; 735782Slinton } 745543Slinton 755782Slinton case O_LCON: 765782Slinton switch (size(p->nodetype)) { 775782Slinton case sizeof(char): 785782Slinton push(char, p->lconval); 795782Slinton break; 805543Slinton 815782Slinton case sizeof(short): 825782Slinton push(short, p->lconval); 835782Slinton break; 845543Slinton 855782Slinton case sizeof(long): 865782Slinton push(long, p->lconval); 875782Slinton break; 885543Slinton 895782Slinton default: 905782Slinton panic("bad size %d for LCON", size(p->nodetype)); 915782Slinton } 925782Slinton break; 935543Slinton 945782Slinton case O_FCON: 955782Slinton push(double, p->fconval); 965782Slinton break; 975543Slinton 985782Slinton case O_SCON: { 995782Slinton int len; 1005543Slinton 1015782Slinton len = size(p->nodetype); 1025782Slinton mov(p->sconval, sp, len); 1035782Slinton sp += len; 1045782Slinton break; 1055782Slinton } 1065543Slinton 1075782Slinton case O_INDEX: { 1085782Slinton int n; 1095782Slinton long i; 1105543Slinton 1115782Slinton n = pop(int); 1125782Slinton i = evalindex(p->left->nodetype, popsmall(p->right->nodetype)); 1135782Slinton push(int, n + i*size(p->nodetype)); 1145782Slinton break; 1155782Slinton } 1165543Slinton 1175782Slinton case O_INDIR: { 1185782Slinton ADDRESS a; 1195543Slinton 1205782Slinton a = pop(ADDRESS); 1215782Slinton if (a == 0) { 1225782Slinton error("reference through nil pointer"); 1235782Slinton } 1245782Slinton dread(sp, a, sizeof(ADDRESS)); 1255782Slinton sp += sizeof(ADDRESS); 1265782Slinton break; 1275782Slinton } 1285543Slinton 1295782Slinton /* 1305782Slinton * Get the value of the expression addressed by the top of the stack. 1316076Slinton * Push the result back on the stack. 1325782Slinton */ 1335543Slinton 1345782Slinton case O_RVAL: { 1355782Slinton ADDRESS addr, len; 1365782Slinton long i; 1375543Slinton 1385782Slinton addr = pop(int); 1395782Slinton if (addr == 0) { 1405782Slinton error("reference through nil pointer"); 1415782Slinton } 1425782Slinton len = size(p->nodetype); 1435782Slinton if (!rpush(addr, len)) { 1445782Slinton error("expression too large to evaluate"); 1455782Slinton } 1465782Slinton break; 1475782Slinton } 1485543Slinton 1495782Slinton case O_COMMA: 1505782Slinton break; 1515543Slinton 1525782Slinton case O_ITOF: 1535782Slinton push(double, (double) r0); 1545782Slinton break; 1555543Slinton 1565782Slinton case O_ADD: 1575782Slinton push(long, r0+r1); 1585782Slinton break; 1595543Slinton 1605782Slinton case O_ADDF: 1615782Slinton push(double, fr0+fr1); 1625782Slinton break; 1635543Slinton 1645782Slinton case O_SUB: 1655782Slinton push(long, r0-r1); 1665782Slinton break; 1675543Slinton 1685782Slinton case O_SUBF: 1695782Slinton push(double, fr0-fr1); 1705782Slinton break; 1715543Slinton 1725782Slinton case O_NEG: 1735782Slinton push(long, -r0); 1745782Slinton break; 1755543Slinton 1765782Slinton case O_NEGF: 1775782Slinton push(double, -fr0); 1785782Slinton break; 1795543Slinton 1805782Slinton case O_MUL: 1815782Slinton push(long, r0*r1); 1825782Slinton break; 1835543Slinton 1845782Slinton case O_MULF: 1855782Slinton push(double, fr0*fr1); 1865782Slinton break; 1875543Slinton 1885782Slinton case O_DIVF: 1895782Slinton if (fr1 == 0) { 1905782Slinton error("error: division by 0"); 1915782Slinton } 1925782Slinton push(double, fr0/fr1); 1935782Slinton break; 1945543Slinton 1955782Slinton case O_DIV: 1965782Slinton if (r1 == 0) { 1975782Slinton error("error: div by 0"); 1985782Slinton } 1995782Slinton push(long, r0/r1); 2005782Slinton break; 2015543Slinton 2025782Slinton case O_MOD: 2035782Slinton if (r1 == 0) { 2045782Slinton error("error: mod by 0"); 2055782Slinton } 2065782Slinton push(long, r0%r1); 2075782Slinton break; 2085543Slinton 2095782Slinton case O_LT: 2105782Slinton push(BOOLEAN, r0 < r1); 2115782Slinton break; 2125543Slinton 2135782Slinton case O_LTF: 2145782Slinton push(BOOLEAN, fr0 < fr1); 2155782Slinton break; 2165543Slinton 2175782Slinton case O_LE: 2185782Slinton push(BOOLEAN, r0 <= r1); 2195782Slinton break; 2205543Slinton 2215782Slinton case O_LEF: 2225782Slinton push(BOOLEAN, fr0 <= fr1); 2235782Slinton break; 2245543Slinton 2255782Slinton case O_GT: 2265782Slinton push(BOOLEAN, r0 > r1); 2275782Slinton break; 2285543Slinton 2295782Slinton case O_GTF: 2305782Slinton push(BOOLEAN, fr0 > fr1); 2315782Slinton break; 2325543Slinton 2335782Slinton case O_EQ: 2345782Slinton push(BOOLEAN, r0 == r1); 2355782Slinton break; 2365543Slinton 2375782Slinton case O_EQF: 2385782Slinton push(BOOLEAN, fr0 == fr1); 2395782Slinton break; 2405543Slinton 2415782Slinton case O_NE: 2425782Slinton push(BOOLEAN, r0 != r1); 2435782Slinton break; 2445543Slinton 2455782Slinton case O_NEF: 2465782Slinton push(BOOLEAN, fr0 != fr1); 2475782Slinton break; 2485543Slinton 2495782Slinton case O_AND: 2505782Slinton push(BOOLEAN, r0 && r1); 2515782Slinton break; 2525543Slinton 2535782Slinton case O_OR: 2545782Slinton push(BOOLEAN, r0 || r1); 2555782Slinton break; 2565543Slinton 2575782Slinton case O_ASSIGN: 2585782Slinton assign(p->left, p->right); 2595782Slinton break; 2605543Slinton 2615782Slinton case O_CHFILE: 2625782Slinton if (p->sconval == NIL) { 2635782Slinton printf("%s\n", cursource); 2645782Slinton } else { 2655782Slinton skimsource(p->sconval); 2665782Slinton } 2675782Slinton break; 2685543Slinton 2695782Slinton case O_CONT: 2705782Slinton cont(); 2715782Slinton printnews(); 2725782Slinton break; 2735543Slinton 2745782Slinton case O_LIST: { 2755782Slinton SYM *b; 276*6083Slinton ADDRESS addr; 2775543Slinton 2785782Slinton if (p->left->op == O_NAME) { 2795782Slinton b = p->left->nameval; 2805782Slinton if (!isblock(b)) { 2815782Slinton error("\"%s\" is not a procedure or function", name(b)); 2825543Slinton } 283*6083Slinton addr = firstline(b); 284*6083Slinton if (addr == -1) { 285*6083Slinton error("\"%s\" is empty", name(b)); 286*6083Slinton } 287*6083Slinton skimsource(srcfilename(addr)); 288*6083Slinton r0 = srcline(addr); 2895782Slinton r1 = r0 + 5; 2905782Slinton if (r1 > lastlinenum) { 2915782Slinton r1 = lastlinenum; 2925782Slinton } 2935782Slinton r0 = r0 - 5; 2945782Slinton if (r0 < 1) { 2955782Slinton r0 = 1; 2965782Slinton } 2975782Slinton } else { 2985782Slinton eval(p->left->right); 2995782Slinton eval(p->left->left); 3005782Slinton r0 = pop(long); 3015782Slinton r1 = pop(long); 3025782Slinton } 3035782Slinton printlines((LINENO) r0, (LINENO) r1); 3045782Slinton break; 3055782Slinton } 3065543Slinton 3075782Slinton case O_XI: 3085782Slinton case O_XD: 3095782Slinton { 3105782Slinton SYM *b; 3115543Slinton 3125782Slinton if (p->left->op == O_CALL) { 3135782Slinton b = p->left->left->nameval; 3145782Slinton r0 = codeloc(b); 3155782Slinton r1 = firstline(b); 3165782Slinton } else { 3175782Slinton eval(p->left->right); 3185782Slinton eval(p->left->left); 3195782Slinton r0 = pop(long); 3205782Slinton r1 = pop(long); 3215782Slinton } 3225782Slinton if (p->op == O_XI) { 3235782Slinton printinst((ADDRESS) r0, (ADDRESS) r1); 3245782Slinton } else { 3255782Slinton printdata((ADDRESS) r0, (ADDRESS) r1); 3265782Slinton } 3275782Slinton break; 3285782Slinton } 3295543Slinton 3305782Slinton case O_NEXT: 3315782Slinton next(); 3325782Slinton printnews(); 3335782Slinton break; 3345543Slinton 3355782Slinton case O_PRINT: { 3365782Slinton NODE *o; 3375543Slinton 3385782Slinton for (o = p->left; o != NIL; o = o->right) { 3395782Slinton eval(o->left); 3405782Slinton printval(o->left->nodetype); 3415782Slinton putchar(' '); 3425782Slinton } 3435782Slinton putchar('\n'); 3445782Slinton break; 3455782Slinton } 3465543Slinton 3475782Slinton case O_STEP: 3485782Slinton stepc(); 3495782Slinton printnews(); 3505782Slinton break; 3515543Slinton 3525782Slinton case O_WHATIS: 3535782Slinton if (p->left->op == O_NAME) { 3545782Slinton printdecl(p->left->nameval); 3555782Slinton } else { 3565782Slinton printdecl(p->left->nodetype); 3575782Slinton } 3585782Slinton break; 3595543Slinton 3605782Slinton case O_WHICH: 3615782Slinton printwhich(p->nameval); 3625782Slinton putchar('\n'); 3635782Slinton break; 3645543Slinton 3655782Slinton case O_WHERE: 3665782Slinton where(); 3675782Slinton break; 3685543Slinton 3695782Slinton case O_ALIAS: 3705782Slinton alias(p->left->sconval, p->right->sconval); 3715782Slinton break; 3725543Slinton 3735782Slinton case O_CALL: 3745782Slinton callproc(p->left, p->right); 3755782Slinton break; 3765543Slinton 3775782Slinton case O_EDIT: 3785782Slinton edit(p->sconval); 3795782Slinton break; 3805543Slinton 3815782Slinton case O_DUMP: 3825782Slinton dump(); 3835782Slinton break; 3845543Slinton 3855782Slinton case O_GRIPE: 3865782Slinton gripe(); 3875782Slinton break; 3885562Slinton 3895782Slinton case O_HELP: 3905782Slinton help(); 3915782Slinton break; 3925543Slinton 3935782Slinton case O_REMAKE: 3945782Slinton remake(); 3955782Slinton break; 3965543Slinton 3975782Slinton case O_RUN: 3985782Slinton run(); 3995782Slinton break; 4005543Slinton 4015782Slinton case O_SOURCE: 4025782Slinton setinput(p->sconval); 4035782Slinton break; 4045543Slinton 4055782Slinton case O_STATUS: 4065782Slinton status(); 4075782Slinton break; 4085543Slinton 4095782Slinton case O_TRACE: 4105782Slinton case O_TRACEI: 4115782Slinton trace(p->op, p->what, p->where, p->cond); 4125782Slinton if (isstdin()) { 4135782Slinton status(); 4145782Slinton } 4155782Slinton break; 4165543Slinton 4175782Slinton case O_STOP: 4185782Slinton case O_STOPI: 4195782Slinton stop(p->op, p->what, p->where, p->cond); 4205782Slinton if (isstdin()) { 4215782Slinton status(); 4225782Slinton } 4235782Slinton break; 4245543Slinton 4255782Slinton case O_DELETE: 4265782Slinton eval(p->left); 4275782Slinton delbp((unsigned int) pop(long)); 4285782Slinton break; 4295543Slinton 4305782Slinton default: 4315782Slinton panic("eval: bad op %d", p->op); 4325782Slinton } 4335543Slinton } 4345543Slinton 4355543Slinton /* 4365562Slinton * Push "len" bytes onto the expression stack from address "addr" 4375562Slinton * in the process. Normally TRUE is returned, however if there 4385562Slinton * isn't enough room on the stack, rpush returns FALSE. 4395562Slinton */ 4405562Slinton 4415562Slinton BOOLEAN rpush(addr, len) 4425562Slinton ADDRESS addr; 4435562Slinton int len; 4445562Slinton { 4455782Slinton BOOLEAN success; 4465562Slinton 4475782Slinton if (sp + len >= &stack[STACKSIZE]) { 4485782Slinton success = FALSE; 4495782Slinton } else { 4505782Slinton dread(sp, addr, len); 4515782Slinton sp += len; 4525782Slinton success = TRUE; 4535782Slinton } 4545782Slinton return success; 4555562Slinton } 4565562Slinton 4575562Slinton /* 4585782Slinton * Pop an item of the given type which is assumed to be no larger 4595782Slinton * than a long and return it expanded into a long. 4605782Slinton */ 4615782Slinton 4625782Slinton long popsmall(t) 4635782Slinton SYM *t; 4645782Slinton { 4655782Slinton long r; 4665782Slinton 4675782Slinton switch (size(t)) { 4685782Slinton case sizeof(char): 4695782Slinton r = (long) pop(char); 4705782Slinton break; 4715782Slinton 4725782Slinton case sizeof(short): 4735782Slinton r = (long) pop(short); 4745782Slinton break; 4755782Slinton 4765782Slinton case sizeof(long): 4775782Slinton r = pop(long); 4785782Slinton break; 4795782Slinton 4805782Slinton default: 4815782Slinton panic("popsmall: size is %d", size(t)); 4825782Slinton } 4835782Slinton return r; 4845782Slinton } 4855782Slinton 4865782Slinton /* 4875543Slinton * evaluate a conditional expression 4885543Slinton */ 4895543Slinton 4905543Slinton BOOLEAN cond(p) 4915543Slinton NODE *p; 4925543Slinton { 4935782Slinton if (p == NIL) { 4945782Slinton return(TRUE); 4955782Slinton } 4965782Slinton eval(p); 4975782Slinton return(pop(BOOLEAN)); 4985543Slinton } 4995543Slinton 5005543Slinton /* 5015543Slinton * Return the address corresponding to a given tree. 5025543Slinton */ 5035543Slinton 5045543Slinton ADDRESS lval(p) 5055543Slinton NODE *p; 5065543Slinton { 5075782Slinton eval(p); 5085782Slinton return(pop(ADDRESS)); 5095543Slinton } 510