122559Sdist /* 222559Sdist * Copyright (c) 1980 Regents of the University of California. 322559Sdist * All rights reserved. The Berkeley software License Agreement 422559Sdist * specifies the terms and conditions for redistribution. 522559Sdist */ 65543Slinton 722559Sdist #ifndef lint 8*30852Smckusick static char sccsid[] = "@(#)eval.c 5.2 (Berkeley) 04/07/87"; 922559Sdist #endif not lint 105543Slinton 115543Slinton /* 125562Slinton * Parse tree evaluation. 135543Slinton */ 145543Slinton 155543Slinton #include "defs.h" 165543Slinton #include "tree.h" 175543Slinton #include "sym.h" 185543Slinton #include "process.h" 195543Slinton #include "source.h" 205543Slinton #include "mappings.h" 215543Slinton #include "breakpoint.h" 225543Slinton #include "machine.h" 235543Slinton #include "tree.rep" 24*30852Smckusick #include "process/process.rep" 25*30852Smckusick #include "process/pxinfo.h" 265543Slinton 276086Slinton #define Boolean char /* underlying representation type for booleans */ 286086Slinton 295543Slinton /* 305543Slinton * Evaluate a parse tree using a stack; value is left at top. 315543Slinton */ 325543Slinton 335562Slinton #define STACKSIZE 2000 345562Slinton 355562Slinton STACK stack[STACKSIZE]; 365543Slinton STACK *sp = &stack[0]; 375543Slinton 385543Slinton eval(p) 395543Slinton register NODE *p; 405543Slinton { 415782Slinton long r0, r1; 425782Slinton double fr0, fr1; 436874Slinton FILE *fp; 445543Slinton 455782Slinton if (p == NULL) { 465782Slinton return; 475782Slinton } 485782Slinton switch(degree(p->op)) { 495782Slinton case BINARY: 505782Slinton eval(p->right); 515782Slinton if (isreal(p->op)) { 525782Slinton fr1 = pop(double); 535782Slinton } else if (isint(p->op)) { 546076Slinton r1 = popsmall(p->right->nodetype); 555782Slinton } 565782Slinton /* fall through */ 575782Slinton case UNARY: 585782Slinton eval(p->left); 595782Slinton if (isreal(p->op)) { 605782Slinton fr0 = pop(double); 615782Slinton } else if (isint(p->op)) { 626076Slinton r0 = popsmall(p->left->nodetype); 635782Slinton } 645782Slinton break; 655782Slinton 665782Slinton default: 675782Slinton /* do nothing */; 685543Slinton } 695782Slinton switch(p->op) { 705782Slinton case O_NAME: { 715782Slinton SYM *s, *f; 725543Slinton 735782Slinton s = p->nameval; 745886Slinton if (!isvariable(s)) { 755886Slinton error("cannot evaluate a %s", classname(s)); 765886Slinton } else { 775886Slinton f = container(s); 785886Slinton if (!isactive(f)) { 795886Slinton error("\"%s\" is not active", name(f)); 805886Slinton } 816086Slinton push(long, address(s, NIL)); 825782Slinton } 835782Slinton break; 845782Slinton } 855543Slinton 865782Slinton case O_LCON: 875782Slinton switch (size(p->nodetype)) { 885782Slinton case sizeof(char): 895782Slinton push(char, p->lconval); 905782Slinton break; 915543Slinton 925782Slinton case sizeof(short): 935782Slinton push(short, p->lconval); 945782Slinton break; 955543Slinton 965782Slinton case sizeof(long): 975782Slinton push(long, p->lconval); 985782Slinton break; 995543Slinton 1005782Slinton default: 1015782Slinton panic("bad size %d for LCON", size(p->nodetype)); 1025782Slinton } 1035782Slinton break; 1045543Slinton 1055782Slinton case O_FCON: 1065782Slinton push(double, p->fconval); 1075782Slinton break; 1085543Slinton 1095782Slinton case O_SCON: { 1105782Slinton int len; 1115543Slinton 1125782Slinton len = size(p->nodetype); 1135782Slinton mov(p->sconval, sp, len); 1145782Slinton sp += len; 115*30852Smckusick #ifdef tahoe 116*30852Smckusick alignstack(); 117*30852Smckusick #endif tahoe 1185782Slinton break; 1195782Slinton } 1205543Slinton 1215782Slinton case O_INDEX: { 12211063Slinton long n; /* base address for array */ 12311063Slinton long i; /* index - lower bound */ 124*30852Smckusick long evalindex(); 1255543Slinton 1266086Slinton n = pop(long); 12711063Slinton i = evalindex(p->left->nodetype, p->right); 1286086Slinton push(long, n + i*size(p->nodetype)); 1295782Slinton break; 1305782Slinton } 1315543Slinton 1325782Slinton case O_INDIR: { 1335782Slinton ADDRESS a; 1345543Slinton 1355782Slinton a = pop(ADDRESS); 1365782Slinton if (a == 0) { 1375782Slinton error("reference through nil pointer"); 1385782Slinton } 1395782Slinton dread(sp, a, sizeof(ADDRESS)); 1405782Slinton sp += sizeof(ADDRESS); 1415782Slinton break; 1425782Slinton } 1435543Slinton 1445782Slinton /* 1455782Slinton * Get the value of the expression addressed by the top of the stack. 1466076Slinton * Push the result back on the stack. 1475782Slinton */ 1485543Slinton 1495782Slinton case O_RVAL: { 1505782Slinton ADDRESS addr, len; 1515543Slinton 1526086Slinton addr = pop(long); 1535782Slinton if (addr == 0) { 1545782Slinton error("reference through nil pointer"); 1555782Slinton } 1565782Slinton len = size(p->nodetype); 1575782Slinton if (!rpush(addr, len)) { 1585782Slinton error("expression too large to evaluate"); 1595782Slinton } 1605782Slinton break; 1615782Slinton } 1625543Slinton 1635782Slinton case O_COMMA: 1645782Slinton break; 1655543Slinton 1665782Slinton case O_ITOF: 1675782Slinton push(double, (double) r0); 1685782Slinton break; 1695543Slinton 1705782Slinton case O_ADD: 1715782Slinton push(long, r0+r1); 1725782Slinton break; 1735543Slinton 1745782Slinton case O_ADDF: 1755782Slinton push(double, fr0+fr1); 1765782Slinton break; 1775543Slinton 1785782Slinton case O_SUB: 1795782Slinton push(long, r0-r1); 1805782Slinton break; 1815543Slinton 1825782Slinton case O_SUBF: 1835782Slinton push(double, fr0-fr1); 1845782Slinton break; 1855543Slinton 1865782Slinton case O_NEG: 1875782Slinton push(long, -r0); 1885782Slinton break; 1895543Slinton 1905782Slinton case O_NEGF: 1915782Slinton push(double, -fr0); 1925782Slinton break; 1935543Slinton 1945782Slinton case O_MUL: 1955782Slinton push(long, r0*r1); 1965782Slinton break; 1975543Slinton 1985782Slinton case O_MULF: 1995782Slinton push(double, fr0*fr1); 2005782Slinton break; 2015543Slinton 2025782Slinton case O_DIVF: 2035782Slinton if (fr1 == 0) { 2045782Slinton error("error: division by 0"); 2055782Slinton } 2065782Slinton push(double, fr0/fr1); 2075782Slinton break; 2085543Slinton 2095782Slinton case O_DIV: 2105782Slinton if (r1 == 0) { 2115782Slinton error("error: div by 0"); 2125782Slinton } 2135782Slinton push(long, r0/r1); 2145782Slinton break; 2155543Slinton 2165782Slinton case O_MOD: 2175782Slinton if (r1 == 0) { 2185782Slinton error("error: mod by 0"); 2195782Slinton } 2205782Slinton push(long, r0%r1); 2215782Slinton break; 2225543Slinton 2235782Slinton case O_LT: 2246086Slinton push(Boolean, r0 < r1); 2255782Slinton break; 2265543Slinton 2275782Slinton case O_LTF: 2286086Slinton push(Boolean, fr0 < fr1); 2295782Slinton break; 2305543Slinton 2315782Slinton case O_LE: 2326086Slinton push(Boolean, r0 <= r1); 2335782Slinton break; 2345543Slinton 2355782Slinton case O_LEF: 2366086Slinton push(Boolean, fr0 <= fr1); 2375782Slinton break; 2385543Slinton 2395782Slinton case O_GT: 2406086Slinton push(Boolean, r0 > r1); 2415782Slinton break; 2425543Slinton 2435782Slinton case O_GTF: 2446086Slinton push(Boolean, fr0 > fr1); 2455782Slinton break; 2465543Slinton 2475782Slinton case O_EQ: 2486086Slinton push(Boolean, r0 == r1); 2495782Slinton break; 2505543Slinton 2515782Slinton case O_EQF: 2526086Slinton push(Boolean, fr0 == fr1); 2535782Slinton break; 2545543Slinton 2555782Slinton case O_NE: 2566086Slinton push(Boolean, r0 != r1); 2575782Slinton break; 2585543Slinton 2595782Slinton case O_NEF: 2606086Slinton push(Boolean, fr0 != fr1); 2615782Slinton break; 2625543Slinton 2635782Slinton case O_AND: 2646086Slinton push(Boolean, r0 && r1); 2655782Slinton break; 2665543Slinton 2675782Slinton case O_OR: 2686086Slinton push(Boolean, r0 || r1); 2695782Slinton break; 2705543Slinton 2715782Slinton case O_ASSIGN: 2725782Slinton assign(p->left, p->right); 2735782Slinton break; 2745543Slinton 2755782Slinton case O_CHFILE: 2765782Slinton if (p->sconval == NIL) { 2775782Slinton printf("%s\n", cursource); 2785782Slinton } else { 2796874Slinton fp = fopen(p->sconval, "r"); 2806874Slinton if (fp == NIL) { 2816874Slinton error("can't read \"%s\"", p->sconval); 2826874Slinton } else { 2836874Slinton fclose(fp); 2846874Slinton skimsource(p->sconval); 2856874Slinton } 2865782Slinton } 2875782Slinton break; 2885543Slinton 2895782Slinton case O_CONT: 2905782Slinton cont(); 2915782Slinton printnews(); 2925782Slinton break; 2935543Slinton 2945782Slinton case O_LIST: { 2955782Slinton SYM *b; 2966083Slinton ADDRESS addr; 2975543Slinton 2985782Slinton if (p->left->op == O_NAME) { 2995782Slinton b = p->left->nameval; 3005782Slinton if (!isblock(b)) { 3015782Slinton error("\"%s\" is not a procedure or function", name(b)); 3025543Slinton } 3036083Slinton addr = firstline(b); 304*30852Smckusick if ((int)addr == -1) { 3056083Slinton error("\"%s\" is empty", name(b)); 3066083Slinton } 3076083Slinton skimsource(srcfilename(addr)); 3086083Slinton r0 = srcline(addr); 3095782Slinton r1 = r0 + 5; 3105782Slinton if (r1 > lastlinenum) { 3115782Slinton r1 = lastlinenum; 3125782Slinton } 3135782Slinton r0 = r0 - 5; 3145782Slinton if (r0 < 1) { 3155782Slinton r0 = 1; 3165782Slinton } 3175782Slinton } else { 3185782Slinton eval(p->left->right); 3195782Slinton eval(p->left->left); 3205782Slinton r0 = pop(long); 3215782Slinton r1 = pop(long); 3225782Slinton } 3235782Slinton printlines((LINENO) r0, (LINENO) r1); 3245782Slinton break; 3255782Slinton } 3265543Slinton 3275782Slinton case O_XI: 3285782Slinton case O_XD: 3295782Slinton { 3305782Slinton SYM *b; 3315543Slinton 3325782Slinton if (p->left->op == O_CALL) { 3335782Slinton b = p->left->left->nameval; 3345782Slinton r0 = codeloc(b); 3355782Slinton r1 = firstline(b); 3365782Slinton } else { 3375782Slinton eval(p->left->right); 3385782Slinton eval(p->left->left); 3395782Slinton r0 = pop(long); 3405782Slinton r1 = pop(long); 3415782Slinton } 3425782Slinton if (p->op == O_XI) { 3435782Slinton printinst((ADDRESS) r0, (ADDRESS) r1); 3445782Slinton } else { 3455782Slinton printdata((ADDRESS) r0, (ADDRESS) r1); 3465782Slinton } 3475782Slinton break; 3485782Slinton } 3495543Slinton 3505782Slinton case O_NEXT: 3515782Slinton next(); 3525782Slinton printnews(); 3535782Slinton break; 3545543Slinton 3555782Slinton case O_PRINT: { 3565782Slinton NODE *o; 3575543Slinton 3585782Slinton for (o = p->left; o != NIL; o = o->right) { 3595782Slinton eval(o->left); 3605782Slinton printval(o->left->nodetype); 3615782Slinton putchar(' '); 3625782Slinton } 3635782Slinton putchar('\n'); 3645782Slinton break; 3655782Slinton } 3665543Slinton 3675782Slinton case O_STEP: 3685782Slinton stepc(); 3695782Slinton printnews(); 3705782Slinton break; 3715543Slinton 3725782Slinton case O_WHATIS: 3735782Slinton if (p->left->op == O_NAME) { 3745782Slinton printdecl(p->left->nameval); 3755782Slinton } else { 3765782Slinton printdecl(p->left->nodetype); 3775782Slinton } 3785782Slinton break; 3795543Slinton 3805782Slinton case O_WHICH: 3815782Slinton printwhich(p->nameval); 3825782Slinton putchar('\n'); 3835782Slinton break; 3845543Slinton 3855782Slinton case O_WHERE: 3865782Slinton where(); 3875782Slinton break; 3885543Slinton 3895782Slinton case O_ALIAS: 3905782Slinton alias(p->left->sconval, p->right->sconval); 3915782Slinton break; 3925543Slinton 3935782Slinton case O_CALL: 3945782Slinton callproc(p->left, p->right); 3955782Slinton break; 3965543Slinton 3975782Slinton case O_EDIT: 3985782Slinton edit(p->sconval); 3995782Slinton break; 4005543Slinton 4015782Slinton case O_DUMP: 4025782Slinton dump(); 4035782Slinton break; 4045543Slinton 4055782Slinton case O_GRIPE: 4065782Slinton gripe(); 4075782Slinton break; 4085562Slinton 4095782Slinton case O_HELP: 4105782Slinton help(); 4115782Slinton break; 4125543Slinton 4135782Slinton case O_REMAKE: 4145782Slinton remake(); 4155782Slinton break; 4165543Slinton 4175782Slinton case O_RUN: 4185782Slinton run(); 4195782Slinton break; 4205543Slinton 4215782Slinton case O_SOURCE: 4225782Slinton setinput(p->sconval); 4235782Slinton break; 4245543Slinton 4255782Slinton case O_STATUS: 4265782Slinton status(); 4275782Slinton break; 4285543Slinton 4295782Slinton case O_TRACE: 4305782Slinton case O_TRACEI: 4315782Slinton trace(p->op, p->what, p->where, p->cond); 4325782Slinton if (isstdin()) { 4335782Slinton status(); 4345782Slinton } 4355782Slinton break; 4365543Slinton 4375782Slinton case O_STOP: 4385782Slinton case O_STOPI: 4395782Slinton stop(p->op, p->what, p->where, p->cond); 4405782Slinton if (isstdin()) { 4415782Slinton status(); 4425782Slinton } 4435782Slinton break; 4445543Slinton 4455782Slinton case O_DELETE: 4465782Slinton eval(p->left); 4475782Slinton delbp((unsigned int) pop(long)); 4485782Slinton break; 4495543Slinton 4505782Slinton default: 4515782Slinton panic("eval: bad op %d", p->op); 4525782Slinton } 4535543Slinton } 4545543Slinton 4555543Slinton /* 4565562Slinton * Push "len" bytes onto the expression stack from address "addr" 4575562Slinton * in the process. Normally TRUE is returned, however if there 4585562Slinton * isn't enough room on the stack, rpush returns FALSE. 4595562Slinton */ 4605562Slinton 4615562Slinton BOOLEAN rpush(addr, len) 4625562Slinton ADDRESS addr; 4635562Slinton int len; 4645562Slinton { 4655782Slinton BOOLEAN success; 466*30852Smckusick #ifdef tahoe 467*30852Smckusick register char *savesp = sp; 468*30852Smckusick #endif 4695562Slinton 4705782Slinton if (sp + len >= &stack[STACKSIZE]) { 4715782Slinton success = FALSE; 4725782Slinton } else { 4735782Slinton dread(sp, addr, len); 4745782Slinton sp += len; 475*30852Smckusick #ifdef tahoe 476*30852Smckusick alignstack(); 477*30852Smckusick if (sp >= &stack[STACKSIZE]) { 478*30852Smckusick success = FALSE; 479*30852Smckusick sp = savesp; 480*30852Smckusick } else 481*30852Smckusick #endif 482*30852Smckusick success = TRUE; 4835782Slinton } 4845782Slinton return success; 4855562Slinton } 4865562Slinton 4875562Slinton /* 4885782Slinton * Pop an item of the given type which is assumed to be no larger 4895782Slinton * than a long and return it expanded into a long. 4905782Slinton */ 4915782Slinton 4925782Slinton long popsmall(t) 4935782Slinton SYM *t; 4945782Slinton { 4955782Slinton long r; 4965782Slinton 4975782Slinton switch (size(t)) { 4985782Slinton case sizeof(char): 4995782Slinton r = (long) pop(char); 5005782Slinton break; 5015782Slinton 5025782Slinton case sizeof(short): 5035782Slinton r = (long) pop(short); 5045782Slinton break; 5055782Slinton 5065782Slinton case sizeof(long): 5075782Slinton r = pop(long); 5085782Slinton break; 5095782Slinton 51010765Slinton /* 51110765Slinton * A bit of a kludge here. If an array element is a record, 51210765Slinton * the dot operation will be converted into an addition with 51310765Slinton * the record operand having a type whose size may be larger 51410765Slinton * than a word. Now actually this is a pointer, but the subscript 51510765Slinton * operation isn't aware of this, so it's just hacked here. 51610765Slinton * 51710765Slinton * The right thing to do is to make dot directly evaluated 51810765Slinton * instead of changing it into addition. 51910765Slinton */ 5205782Slinton default: 52110765Slinton r = pop(ADDRESS); 52210765Slinton break; 5235782Slinton } 5245782Slinton return r; 5255782Slinton } 5265782Slinton 5275782Slinton /* 5285543Slinton * evaluate a conditional expression 5295543Slinton */ 5305543Slinton 5315543Slinton BOOLEAN cond(p) 5325543Slinton NODE *p; 5335543Slinton { 5345782Slinton if (p == NIL) { 5355782Slinton return(TRUE); 5365782Slinton } 5375782Slinton eval(p); 5385782Slinton return(pop(BOOLEAN)); 5395543Slinton } 5405543Slinton 5415543Slinton /* 5425543Slinton * Return the address corresponding to a given tree. 5435543Slinton */ 5445543Slinton 5455543Slinton ADDRESS lval(p) 5465543Slinton NODE *p; 5475543Slinton { 5485782Slinton eval(p); 5495782Slinton return(pop(ADDRESS)); 5505543Slinton } 551