1*48069Sbostic /*- 2*48069Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48069Sbostic * All rights reserved. 4*48069Sbostic * 5*48069Sbostic * %sccs.include.redist.c% 622559Sdist */ 75543Slinton 822559Sdist #ifndef lint 9*48069Sbostic static char sccsid[] = "@(#)eval.c 5.3 (Berkeley) 04/16/91"; 10*48069Sbostic #endif /* not lint */ 115543Slinton 125543Slinton /* 135562Slinton * Parse tree evaluation. 145543Slinton */ 155543Slinton 165543Slinton #include "defs.h" 175543Slinton #include "tree.h" 185543Slinton #include "sym.h" 195543Slinton #include "process.h" 205543Slinton #include "source.h" 215543Slinton #include "mappings.h" 225543Slinton #include "breakpoint.h" 235543Slinton #include "machine.h" 245543Slinton #include "tree.rep" 2530852Smckusick #include "process/process.rep" 2630852Smckusick #include "process/pxinfo.h" 275543Slinton 286086Slinton #define Boolean char /* underlying representation type for booleans */ 296086Slinton 305543Slinton /* 315543Slinton * Evaluate a parse tree using a stack; value is left at top. 325543Slinton */ 335543Slinton 345562Slinton #define STACKSIZE 2000 355562Slinton 365562Slinton STACK stack[STACKSIZE]; 375543Slinton STACK *sp = &stack[0]; 385543Slinton 395543Slinton eval(p) 405543Slinton register NODE *p; 415543Slinton { 425782Slinton long r0, r1; 435782Slinton double fr0, fr1; 446874Slinton FILE *fp; 455543Slinton 465782Slinton if (p == NULL) { 475782Slinton return; 485782Slinton } 495782Slinton switch(degree(p->op)) { 505782Slinton case BINARY: 515782Slinton eval(p->right); 525782Slinton if (isreal(p->op)) { 535782Slinton fr1 = pop(double); 545782Slinton } else if (isint(p->op)) { 556076Slinton r1 = popsmall(p->right->nodetype); 565782Slinton } 575782Slinton /* fall through */ 585782Slinton case UNARY: 595782Slinton eval(p->left); 605782Slinton if (isreal(p->op)) { 615782Slinton fr0 = pop(double); 625782Slinton } else if (isint(p->op)) { 636076Slinton r0 = popsmall(p->left->nodetype); 645782Slinton } 655782Slinton break; 665782Slinton 675782Slinton default: 685782Slinton /* do nothing */; 695543Slinton } 705782Slinton switch(p->op) { 715782Slinton case O_NAME: { 725782Slinton SYM *s, *f; 735543Slinton 745782Slinton s = p->nameval; 755886Slinton if (!isvariable(s)) { 765886Slinton error("cannot evaluate a %s", classname(s)); 775886Slinton } else { 785886Slinton f = container(s); 795886Slinton if (!isactive(f)) { 805886Slinton error("\"%s\" is not active", name(f)); 815886Slinton } 826086Slinton push(long, address(s, NIL)); 835782Slinton } 845782Slinton break; 855782Slinton } 865543Slinton 875782Slinton case O_LCON: 885782Slinton switch (size(p->nodetype)) { 895782Slinton case sizeof(char): 905782Slinton push(char, p->lconval); 915782Slinton break; 925543Slinton 935782Slinton case sizeof(short): 945782Slinton push(short, p->lconval); 955782Slinton break; 965543Slinton 975782Slinton case sizeof(long): 985782Slinton push(long, p->lconval); 995782Slinton break; 1005543Slinton 1015782Slinton default: 1025782Slinton panic("bad size %d for LCON", size(p->nodetype)); 1035782Slinton } 1045782Slinton break; 1055543Slinton 1065782Slinton case O_FCON: 1075782Slinton push(double, p->fconval); 1085782Slinton break; 1095543Slinton 1105782Slinton case O_SCON: { 1115782Slinton int len; 1125543Slinton 1135782Slinton len = size(p->nodetype); 1145782Slinton mov(p->sconval, sp, len); 1155782Slinton sp += len; 11630852Smckusick #ifdef tahoe 11730852Smckusick alignstack(); 11830852Smckusick #endif tahoe 1195782Slinton break; 1205782Slinton } 1215543Slinton 1225782Slinton case O_INDEX: { 12311063Slinton long n; /* base address for array */ 12411063Slinton long i; /* index - lower bound */ 12530852Smckusick long evalindex(); 1265543Slinton 1276086Slinton n = pop(long); 12811063Slinton i = evalindex(p->left->nodetype, p->right); 1296086Slinton push(long, n + i*size(p->nodetype)); 1305782Slinton break; 1315782Slinton } 1325543Slinton 1335782Slinton case O_INDIR: { 1345782Slinton ADDRESS a; 1355543Slinton 1365782Slinton a = pop(ADDRESS); 1375782Slinton if (a == 0) { 1385782Slinton error("reference through nil pointer"); 1395782Slinton } 1405782Slinton dread(sp, a, sizeof(ADDRESS)); 1415782Slinton sp += sizeof(ADDRESS); 1425782Slinton break; 1435782Slinton } 1445543Slinton 1455782Slinton /* 1465782Slinton * Get the value of the expression addressed by the top of the stack. 1476076Slinton * Push the result back on the stack. 1485782Slinton */ 1495543Slinton 1505782Slinton case O_RVAL: { 1515782Slinton ADDRESS addr, len; 1525543Slinton 1536086Slinton addr = pop(long); 1545782Slinton if (addr == 0) { 1555782Slinton error("reference through nil pointer"); 1565782Slinton } 1575782Slinton len = size(p->nodetype); 1585782Slinton if (!rpush(addr, len)) { 1595782Slinton error("expression too large to evaluate"); 1605782Slinton } 1615782Slinton break; 1625782Slinton } 1635543Slinton 1645782Slinton case O_COMMA: 1655782Slinton break; 1665543Slinton 1675782Slinton case O_ITOF: 1685782Slinton push(double, (double) r0); 1695782Slinton break; 1705543Slinton 1715782Slinton case O_ADD: 1725782Slinton push(long, r0+r1); 1735782Slinton break; 1745543Slinton 1755782Slinton case O_ADDF: 1765782Slinton push(double, fr0+fr1); 1775782Slinton break; 1785543Slinton 1795782Slinton case O_SUB: 1805782Slinton push(long, r0-r1); 1815782Slinton break; 1825543Slinton 1835782Slinton case O_SUBF: 1845782Slinton push(double, fr0-fr1); 1855782Slinton break; 1865543Slinton 1875782Slinton case O_NEG: 1885782Slinton push(long, -r0); 1895782Slinton break; 1905543Slinton 1915782Slinton case O_NEGF: 1925782Slinton push(double, -fr0); 1935782Slinton break; 1945543Slinton 1955782Slinton case O_MUL: 1965782Slinton push(long, r0*r1); 1975782Slinton break; 1985543Slinton 1995782Slinton case O_MULF: 2005782Slinton push(double, fr0*fr1); 2015782Slinton break; 2025543Slinton 2035782Slinton case O_DIVF: 2045782Slinton if (fr1 == 0) { 2055782Slinton error("error: division by 0"); 2065782Slinton } 2075782Slinton push(double, fr0/fr1); 2085782Slinton break; 2095543Slinton 2105782Slinton case O_DIV: 2115782Slinton if (r1 == 0) { 2125782Slinton error("error: div by 0"); 2135782Slinton } 2145782Slinton push(long, r0/r1); 2155782Slinton break; 2165543Slinton 2175782Slinton case O_MOD: 2185782Slinton if (r1 == 0) { 2195782Slinton error("error: mod by 0"); 2205782Slinton } 2215782Slinton push(long, r0%r1); 2225782Slinton break; 2235543Slinton 2245782Slinton case O_LT: 2256086Slinton push(Boolean, r0 < r1); 2265782Slinton break; 2275543Slinton 2285782Slinton case O_LTF: 2296086Slinton push(Boolean, fr0 < fr1); 2305782Slinton break; 2315543Slinton 2325782Slinton case O_LE: 2336086Slinton push(Boolean, r0 <= r1); 2345782Slinton break; 2355543Slinton 2365782Slinton case O_LEF: 2376086Slinton push(Boolean, fr0 <= fr1); 2385782Slinton break; 2395543Slinton 2405782Slinton case O_GT: 2416086Slinton push(Boolean, r0 > r1); 2425782Slinton break; 2435543Slinton 2445782Slinton case O_GTF: 2456086Slinton push(Boolean, fr0 > fr1); 2465782Slinton break; 2475543Slinton 2485782Slinton case O_EQ: 2496086Slinton push(Boolean, r0 == r1); 2505782Slinton break; 2515543Slinton 2525782Slinton case O_EQF: 2536086Slinton push(Boolean, fr0 == fr1); 2545782Slinton break; 2555543Slinton 2565782Slinton case O_NE: 2576086Slinton push(Boolean, r0 != r1); 2585782Slinton break; 2595543Slinton 2605782Slinton case O_NEF: 2616086Slinton push(Boolean, fr0 != fr1); 2625782Slinton break; 2635543Slinton 2645782Slinton case O_AND: 2656086Slinton push(Boolean, r0 && r1); 2665782Slinton break; 2675543Slinton 2685782Slinton case O_OR: 2696086Slinton push(Boolean, r0 || r1); 2705782Slinton break; 2715543Slinton 2725782Slinton case O_ASSIGN: 2735782Slinton assign(p->left, p->right); 2745782Slinton break; 2755543Slinton 2765782Slinton case O_CHFILE: 2775782Slinton if (p->sconval == NIL) { 2785782Slinton printf("%s\n", cursource); 2795782Slinton } else { 2806874Slinton fp = fopen(p->sconval, "r"); 2816874Slinton if (fp == NIL) { 2826874Slinton error("can't read \"%s\"", p->sconval); 2836874Slinton } else { 2846874Slinton fclose(fp); 2856874Slinton skimsource(p->sconval); 2866874Slinton } 2875782Slinton } 2885782Slinton break; 2895543Slinton 2905782Slinton case O_CONT: 2915782Slinton cont(); 2925782Slinton printnews(); 2935782Slinton break; 2945543Slinton 2955782Slinton case O_LIST: { 2965782Slinton SYM *b; 2976083Slinton ADDRESS addr; 2985543Slinton 2995782Slinton if (p->left->op == O_NAME) { 3005782Slinton b = p->left->nameval; 3015782Slinton if (!isblock(b)) { 3025782Slinton error("\"%s\" is not a procedure or function", name(b)); 3035543Slinton } 3046083Slinton addr = firstline(b); 30530852Smckusick if ((int)addr == -1) { 3066083Slinton error("\"%s\" is empty", name(b)); 3076083Slinton } 3086083Slinton skimsource(srcfilename(addr)); 3096083Slinton r0 = srcline(addr); 3105782Slinton r1 = r0 + 5; 3115782Slinton if (r1 > lastlinenum) { 3125782Slinton r1 = lastlinenum; 3135782Slinton } 3145782Slinton r0 = r0 - 5; 3155782Slinton if (r0 < 1) { 3165782Slinton r0 = 1; 3175782Slinton } 3185782Slinton } else { 3195782Slinton eval(p->left->right); 3205782Slinton eval(p->left->left); 3215782Slinton r0 = pop(long); 3225782Slinton r1 = pop(long); 3235782Slinton } 3245782Slinton printlines((LINENO) r0, (LINENO) r1); 3255782Slinton break; 3265782Slinton } 3275543Slinton 3285782Slinton case O_XI: 3295782Slinton case O_XD: 3305782Slinton { 3315782Slinton SYM *b; 3325543Slinton 3335782Slinton if (p->left->op == O_CALL) { 3345782Slinton b = p->left->left->nameval; 3355782Slinton r0 = codeloc(b); 3365782Slinton r1 = firstline(b); 3375782Slinton } else { 3385782Slinton eval(p->left->right); 3395782Slinton eval(p->left->left); 3405782Slinton r0 = pop(long); 3415782Slinton r1 = pop(long); 3425782Slinton } 3435782Slinton if (p->op == O_XI) { 3445782Slinton printinst((ADDRESS) r0, (ADDRESS) r1); 3455782Slinton } else { 3465782Slinton printdata((ADDRESS) r0, (ADDRESS) r1); 3475782Slinton } 3485782Slinton break; 3495782Slinton } 3505543Slinton 3515782Slinton case O_NEXT: 3525782Slinton next(); 3535782Slinton printnews(); 3545782Slinton break; 3555543Slinton 3565782Slinton case O_PRINT: { 3575782Slinton NODE *o; 3585543Slinton 3595782Slinton for (o = p->left; o != NIL; o = o->right) { 3605782Slinton eval(o->left); 3615782Slinton printval(o->left->nodetype); 3625782Slinton putchar(' '); 3635782Slinton } 3645782Slinton putchar('\n'); 3655782Slinton break; 3665782Slinton } 3675543Slinton 3685782Slinton case O_STEP: 3695782Slinton stepc(); 3705782Slinton printnews(); 3715782Slinton break; 3725543Slinton 3735782Slinton case O_WHATIS: 3745782Slinton if (p->left->op == O_NAME) { 3755782Slinton printdecl(p->left->nameval); 3765782Slinton } else { 3775782Slinton printdecl(p->left->nodetype); 3785782Slinton } 3795782Slinton break; 3805543Slinton 3815782Slinton case O_WHICH: 3825782Slinton printwhich(p->nameval); 3835782Slinton putchar('\n'); 3845782Slinton break; 3855543Slinton 3865782Slinton case O_WHERE: 3875782Slinton where(); 3885782Slinton break; 3895543Slinton 3905782Slinton case O_ALIAS: 3915782Slinton alias(p->left->sconval, p->right->sconval); 3925782Slinton break; 3935543Slinton 3945782Slinton case O_CALL: 3955782Slinton callproc(p->left, p->right); 3965782Slinton break; 3975543Slinton 3985782Slinton case O_EDIT: 3995782Slinton edit(p->sconval); 4005782Slinton break; 4015543Slinton 4025782Slinton case O_DUMP: 4035782Slinton dump(); 4045782Slinton break; 4055543Slinton 4065782Slinton case O_GRIPE: 4075782Slinton gripe(); 4085782Slinton break; 4095562Slinton 4105782Slinton case O_HELP: 4115782Slinton help(); 4125782Slinton break; 4135543Slinton 4145782Slinton case O_REMAKE: 4155782Slinton remake(); 4165782Slinton break; 4175543Slinton 4185782Slinton case O_RUN: 4195782Slinton run(); 4205782Slinton break; 4215543Slinton 4225782Slinton case O_SOURCE: 4235782Slinton setinput(p->sconval); 4245782Slinton break; 4255543Slinton 4265782Slinton case O_STATUS: 4275782Slinton status(); 4285782Slinton break; 4295543Slinton 4305782Slinton case O_TRACE: 4315782Slinton case O_TRACEI: 4325782Slinton trace(p->op, p->what, p->where, p->cond); 4335782Slinton if (isstdin()) { 4345782Slinton status(); 4355782Slinton } 4365782Slinton break; 4375543Slinton 4385782Slinton case O_STOP: 4395782Slinton case O_STOPI: 4405782Slinton stop(p->op, p->what, p->where, p->cond); 4415782Slinton if (isstdin()) { 4425782Slinton status(); 4435782Slinton } 4445782Slinton break; 4455543Slinton 4465782Slinton case O_DELETE: 4475782Slinton eval(p->left); 4485782Slinton delbp((unsigned int) pop(long)); 4495782Slinton break; 4505543Slinton 4515782Slinton default: 4525782Slinton panic("eval: bad op %d", p->op); 4535782Slinton } 4545543Slinton } 4555543Slinton 4565543Slinton /* 4575562Slinton * Push "len" bytes onto the expression stack from address "addr" 4585562Slinton * in the process. Normally TRUE is returned, however if there 4595562Slinton * isn't enough room on the stack, rpush returns FALSE. 4605562Slinton */ 4615562Slinton 4625562Slinton BOOLEAN rpush(addr, len) 4635562Slinton ADDRESS addr; 4645562Slinton int len; 4655562Slinton { 4665782Slinton BOOLEAN success; 46730852Smckusick #ifdef tahoe 46830852Smckusick register char *savesp = sp; 46930852Smckusick #endif 4705562Slinton 4715782Slinton if (sp + len >= &stack[STACKSIZE]) { 4725782Slinton success = FALSE; 4735782Slinton } else { 4745782Slinton dread(sp, addr, len); 4755782Slinton sp += len; 47630852Smckusick #ifdef tahoe 47730852Smckusick alignstack(); 47830852Smckusick if (sp >= &stack[STACKSIZE]) { 47930852Smckusick success = FALSE; 48030852Smckusick sp = savesp; 48130852Smckusick } else 48230852Smckusick #endif 48330852Smckusick success = TRUE; 4845782Slinton } 4855782Slinton return success; 4865562Slinton } 4875562Slinton 4885562Slinton /* 4895782Slinton * Pop an item of the given type which is assumed to be no larger 4905782Slinton * than a long and return it expanded into a long. 4915782Slinton */ 4925782Slinton 4935782Slinton long popsmall(t) 4945782Slinton SYM *t; 4955782Slinton { 4965782Slinton long r; 4975782Slinton 4985782Slinton switch (size(t)) { 4995782Slinton case sizeof(char): 5005782Slinton r = (long) pop(char); 5015782Slinton break; 5025782Slinton 5035782Slinton case sizeof(short): 5045782Slinton r = (long) pop(short); 5055782Slinton break; 5065782Slinton 5075782Slinton case sizeof(long): 5085782Slinton r = pop(long); 5095782Slinton break; 5105782Slinton 51110765Slinton /* 51210765Slinton * A bit of a kludge here. If an array element is a record, 51310765Slinton * the dot operation will be converted into an addition with 51410765Slinton * the record operand having a type whose size may be larger 51510765Slinton * than a word. Now actually this is a pointer, but the subscript 51610765Slinton * operation isn't aware of this, so it's just hacked here. 51710765Slinton * 51810765Slinton * The right thing to do is to make dot directly evaluated 51910765Slinton * instead of changing it into addition. 52010765Slinton */ 5215782Slinton default: 52210765Slinton r = pop(ADDRESS); 52310765Slinton break; 5245782Slinton } 5255782Slinton return r; 5265782Slinton } 5275782Slinton 5285782Slinton /* 5295543Slinton * evaluate a conditional expression 5305543Slinton */ 5315543Slinton 5325543Slinton BOOLEAN cond(p) 5335543Slinton NODE *p; 5345543Slinton { 5355782Slinton if (p == NIL) { 5365782Slinton return(TRUE); 5375782Slinton } 5385782Slinton eval(p); 5395782Slinton return(pop(BOOLEAN)); 5405543Slinton } 5415543Slinton 5425543Slinton /* 5435543Slinton * Return the address corresponding to a given tree. 5445543Slinton */ 5455543Slinton 5465543Slinton ADDRESS lval(p) 5475543Slinton NODE *p; 5485543Slinton { 5495782Slinton eval(p); 5505782Slinton return(pop(ADDRESS)); 5515543Slinton } 552