148069Sbostic /*-
2*62161Sbostic * Copyright (c) 1980, 1993
3*62161Sbostic * The Regents of the University of California. All rights reserved.
448069Sbostic *
548069Sbostic * %sccs.include.redist.c%
622559Sdist */
75543Slinton
822559Sdist #ifndef lint
9*62161Sbostic static char sccsid[] = "@(#)eval.c 8.1 (Berkeley) 06/06/93";
1048069Sbostic #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
eval(p)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
rpush(addr,len)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
popsmall(t)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
cond(p)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
lval(p)5465543Slinton ADDRESS lval(p)
5475543Slinton NODE *p;
5485543Slinton {
5495782Slinton eval(p);
5505782Slinton return(pop(ADDRESS));
5515543Slinton }
552