15543Slinton /* Copyright (c) 1982 Regents of the University of California */ 25543Slinton 3*5782Slinton static char sccsid[] = "@(#)eval.c 1.3 02/13/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 { 31*5782Slinton long r0, r1; 32*5782Slinton double fr0, fr1; 335543Slinton 34*5782Slinton if (p == NULL) { 35*5782Slinton return; 36*5782Slinton } 37*5782Slinton switch(degree(p->op)) { 38*5782Slinton case BINARY: 39*5782Slinton eval(p->right); 40*5782Slinton if (isreal(p->op)) { 41*5782Slinton fr1 = pop(double); 42*5782Slinton } else if (isint(p->op)) { 43*5782Slinton r1 = pop(long); 44*5782Slinton } 45*5782Slinton /* fall through */ 46*5782Slinton case UNARY: 47*5782Slinton eval(p->left); 48*5782Slinton if (isreal(p->op)) { 49*5782Slinton fr0 = pop(double); 50*5782Slinton } else if (isint(p->op)) { 51*5782Slinton r0 = pop(long); 52*5782Slinton } 53*5782Slinton break; 54*5782Slinton 55*5782Slinton default: 56*5782Slinton /* do nothing */; 575543Slinton } 58*5782Slinton switch(p->op) { 59*5782Slinton case O_NAME: { 60*5782Slinton SYM *s, *f; 615543Slinton 62*5782Slinton s = p->nameval; 63*5782Slinton f = container(s); 64*5782Slinton if (!isactive(f)) { 65*5782Slinton error("\"%s\" is not active", name(f)); 66*5782Slinton } 67*5782Slinton push(int, address(s, NIL)); 68*5782Slinton break; 69*5782Slinton } 705543Slinton 71*5782Slinton case O_LCON: 72*5782Slinton switch (size(p->nodetype)) { 73*5782Slinton case sizeof(char): 74*5782Slinton push(char, p->lconval); 75*5782Slinton break; 765543Slinton 77*5782Slinton case sizeof(short): 78*5782Slinton push(short, p->lconval); 79*5782Slinton break; 805543Slinton 81*5782Slinton case sizeof(long): 82*5782Slinton push(long, p->lconval); 83*5782Slinton break; 845543Slinton 85*5782Slinton default: 86*5782Slinton panic("bad size %d for LCON", size(p->nodetype)); 87*5782Slinton } 88*5782Slinton break; 895543Slinton 90*5782Slinton case O_FCON: 91*5782Slinton push(double, p->fconval); 92*5782Slinton break; 935543Slinton 94*5782Slinton case O_SCON: { 95*5782Slinton int len; 965543Slinton 97*5782Slinton len = size(p->nodetype); 98*5782Slinton mov(p->sconval, sp, len); 99*5782Slinton sp += len; 100*5782Slinton break; 101*5782Slinton } 1025543Slinton 103*5782Slinton case O_INDEX: { 104*5782Slinton int n; 105*5782Slinton long i; 1065543Slinton 107*5782Slinton n = pop(int); 108*5782Slinton i = evalindex(p->left->nodetype, popsmall(p->right->nodetype)); 109*5782Slinton push(int, n + i*size(p->nodetype)); 110*5782Slinton break; 111*5782Slinton } 1125543Slinton 113*5782Slinton case O_INDIR: { 114*5782Slinton ADDRESS a; 1155543Slinton 116*5782Slinton a = pop(ADDRESS); 117*5782Slinton if (a == 0) { 118*5782Slinton error("reference through nil pointer"); 119*5782Slinton } 120*5782Slinton dread(sp, a, sizeof(ADDRESS)); 121*5782Slinton sp += sizeof(ADDRESS); 122*5782Slinton break; 123*5782Slinton } 1245543Slinton 125*5782Slinton /* 126*5782Slinton * Get the value of the expression addressed by the top of the stack. 127*5782Slinton * Push the result back on the stack. Never push less than a long. 128*5782Slinton */ 1295543Slinton 130*5782Slinton case O_RVAL: { 131*5782Slinton ADDRESS addr, len; 132*5782Slinton long i; 1335543Slinton 134*5782Slinton addr = pop(int); 135*5782Slinton if (addr == 0) { 136*5782Slinton error("reference through nil pointer"); 137*5782Slinton } 138*5782Slinton len = size(p->nodetype); 139*5782Slinton if (!rpush(addr, len)) { 140*5782Slinton error("expression too large to evaluate"); 141*5782Slinton } 142*5782Slinton break; 143*5782Slinton } 1445543Slinton 145*5782Slinton case O_COMMA: 146*5782Slinton break; 1475543Slinton 148*5782Slinton case O_ITOF: 149*5782Slinton push(double, (double) r0); 150*5782Slinton break; 1515543Slinton 152*5782Slinton case O_ADD: 153*5782Slinton push(long, r0+r1); 154*5782Slinton break; 1555543Slinton 156*5782Slinton case O_ADDF: 157*5782Slinton push(double, fr0+fr1); 158*5782Slinton break; 1595543Slinton 160*5782Slinton case O_SUB: 161*5782Slinton push(long, r0-r1); 162*5782Slinton break; 1635543Slinton 164*5782Slinton case O_SUBF: 165*5782Slinton push(double, fr0-fr1); 166*5782Slinton break; 1675543Slinton 168*5782Slinton case O_NEG: 169*5782Slinton push(long, -r0); 170*5782Slinton break; 1715543Slinton 172*5782Slinton case O_NEGF: 173*5782Slinton push(double, -fr0); 174*5782Slinton break; 1755543Slinton 176*5782Slinton case O_MUL: 177*5782Slinton push(long, r0*r1); 178*5782Slinton break; 1795543Slinton 180*5782Slinton case O_MULF: 181*5782Slinton push(double, fr0*fr1); 182*5782Slinton break; 1835543Slinton 184*5782Slinton case O_DIVF: 185*5782Slinton if (fr1 == 0) { 186*5782Slinton error("error: division by 0"); 187*5782Slinton } 188*5782Slinton push(double, fr0/fr1); 189*5782Slinton break; 1905543Slinton 191*5782Slinton case O_DIV: 192*5782Slinton if (r1 == 0) { 193*5782Slinton error("error: div by 0"); 194*5782Slinton } 195*5782Slinton push(long, r0/r1); 196*5782Slinton break; 1975543Slinton 198*5782Slinton case O_MOD: 199*5782Slinton if (r1 == 0) { 200*5782Slinton error("error: mod by 0"); 201*5782Slinton } 202*5782Slinton push(long, r0%r1); 203*5782Slinton break; 2045543Slinton 205*5782Slinton case O_LT: 206*5782Slinton push(BOOLEAN, r0 < r1); 207*5782Slinton break; 2085543Slinton 209*5782Slinton case O_LTF: 210*5782Slinton push(BOOLEAN, fr0 < fr1); 211*5782Slinton break; 2125543Slinton 213*5782Slinton case O_LE: 214*5782Slinton push(BOOLEAN, r0 <= r1); 215*5782Slinton break; 2165543Slinton 217*5782Slinton case O_LEF: 218*5782Slinton push(BOOLEAN, fr0 <= fr1); 219*5782Slinton break; 2205543Slinton 221*5782Slinton case O_GT: 222*5782Slinton push(BOOLEAN, r0 > r1); 223*5782Slinton break; 2245543Slinton 225*5782Slinton case O_GTF: 226*5782Slinton push(BOOLEAN, fr0 > fr1); 227*5782Slinton break; 2285543Slinton 229*5782Slinton case O_EQ: 230*5782Slinton push(BOOLEAN, r0 == r1); 231*5782Slinton break; 2325543Slinton 233*5782Slinton case O_EQF: 234*5782Slinton push(BOOLEAN, fr0 == fr1); 235*5782Slinton break; 2365543Slinton 237*5782Slinton case O_NE: 238*5782Slinton push(BOOLEAN, r0 != r1); 239*5782Slinton break; 2405543Slinton 241*5782Slinton case O_NEF: 242*5782Slinton push(BOOLEAN, fr0 != fr1); 243*5782Slinton break; 2445543Slinton 245*5782Slinton case O_AND: 246*5782Slinton push(BOOLEAN, r0 && r1); 247*5782Slinton break; 2485543Slinton 249*5782Slinton case O_OR: 250*5782Slinton push(BOOLEAN, r0 || r1); 251*5782Slinton break; 2525543Slinton 253*5782Slinton case O_ASSIGN: 254*5782Slinton assign(p->left, p->right); 255*5782Slinton break; 2565543Slinton 257*5782Slinton case O_CHFILE: 258*5782Slinton if (p->sconval == NIL) { 259*5782Slinton printf("%s\n", cursource); 260*5782Slinton } else { 261*5782Slinton skimsource(p->sconval); 262*5782Slinton } 263*5782Slinton break; 2645543Slinton 265*5782Slinton case O_CONT: 266*5782Slinton cont(); 267*5782Slinton printnews(); 268*5782Slinton break; 2695543Slinton 270*5782Slinton case O_LIST: { 271*5782Slinton SYM *b; 2725543Slinton 273*5782Slinton if (p->left->op == O_NAME) { 274*5782Slinton b = p->left->nameval; 275*5782Slinton if (!isblock(b)) { 276*5782Slinton error("\"%s\" is not a procedure or function", name(b)); 2775543Slinton } 278*5782Slinton r0 = srcline(firstline(b)); 279*5782Slinton r1 = r0 + 5; 280*5782Slinton if (r1 > lastlinenum) { 281*5782Slinton r1 = lastlinenum; 282*5782Slinton } 283*5782Slinton r0 = r0 - 5; 284*5782Slinton if (r0 < 1) { 285*5782Slinton r0 = 1; 286*5782Slinton } 287*5782Slinton } else { 288*5782Slinton eval(p->left->right); 289*5782Slinton eval(p->left->left); 290*5782Slinton r0 = pop(long); 291*5782Slinton r1 = pop(long); 292*5782Slinton } 293*5782Slinton printlines((LINENO) r0, (LINENO) r1); 294*5782Slinton break; 295*5782Slinton } 2965543Slinton 297*5782Slinton case O_XI: 298*5782Slinton case O_XD: 299*5782Slinton { 300*5782Slinton SYM *b; 3015543Slinton 302*5782Slinton if (p->left->op == O_CALL) { 303*5782Slinton b = p->left->left->nameval; 304*5782Slinton r0 = codeloc(b); 305*5782Slinton r1 = firstline(b); 306*5782Slinton } else { 307*5782Slinton eval(p->left->right); 308*5782Slinton eval(p->left->left); 309*5782Slinton r0 = pop(long); 310*5782Slinton r1 = pop(long); 311*5782Slinton } 312*5782Slinton if (p->op == O_XI) { 313*5782Slinton printinst((ADDRESS) r0, (ADDRESS) r1); 314*5782Slinton } else { 315*5782Slinton printdata((ADDRESS) r0, (ADDRESS) r1); 316*5782Slinton } 317*5782Slinton break; 318*5782Slinton } 3195543Slinton 320*5782Slinton case O_NEXT: 321*5782Slinton next(); 322*5782Slinton printnews(); 323*5782Slinton break; 3245543Slinton 325*5782Slinton case O_PRINT: { 326*5782Slinton NODE *o; 3275543Slinton 328*5782Slinton for (o = p->left; o != NIL; o = o->right) { 329*5782Slinton eval(o->left); 330*5782Slinton printval(o->left->nodetype); 331*5782Slinton putchar(' '); 332*5782Slinton } 333*5782Slinton putchar('\n'); 334*5782Slinton break; 335*5782Slinton } 3365543Slinton 337*5782Slinton case O_STEP: 338*5782Slinton stepc(); 339*5782Slinton printnews(); 340*5782Slinton break; 3415543Slinton 342*5782Slinton case O_WHATIS: 343*5782Slinton if (p->left->op == O_NAME) { 344*5782Slinton printdecl(p->left->nameval); 345*5782Slinton } else { 346*5782Slinton printdecl(p->left->nodetype); 347*5782Slinton } 348*5782Slinton break; 3495543Slinton 350*5782Slinton case O_WHICH: 351*5782Slinton printwhich(p->nameval); 352*5782Slinton putchar('\n'); 353*5782Slinton break; 3545543Slinton 355*5782Slinton case O_WHERE: 356*5782Slinton where(); 357*5782Slinton break; 3585543Slinton 359*5782Slinton case O_ALIAS: 360*5782Slinton alias(p->left->sconval, p->right->sconval); 361*5782Slinton break; 3625543Slinton 363*5782Slinton case O_CALL: 364*5782Slinton callproc(p->left, p->right); 365*5782Slinton break; 3665543Slinton 367*5782Slinton case O_EDIT: 368*5782Slinton edit(p->sconval); 369*5782Slinton break; 3705543Slinton 371*5782Slinton case O_DUMP: 372*5782Slinton dump(); 373*5782Slinton break; 3745543Slinton 375*5782Slinton case O_GRIPE: 376*5782Slinton gripe(); 377*5782Slinton break; 3785562Slinton 379*5782Slinton case O_HELP: 380*5782Slinton help(); 381*5782Slinton break; 3825543Slinton 383*5782Slinton case O_REMAKE: 384*5782Slinton remake(); 385*5782Slinton break; 3865543Slinton 387*5782Slinton case O_RUN: 388*5782Slinton run(); 389*5782Slinton break; 3905543Slinton 391*5782Slinton case O_SOURCE: 392*5782Slinton setinput(p->sconval); 393*5782Slinton break; 3945543Slinton 395*5782Slinton case O_STATUS: 396*5782Slinton status(); 397*5782Slinton break; 3985543Slinton 399*5782Slinton case O_TRACE: 400*5782Slinton case O_TRACEI: 401*5782Slinton trace(p->op, p->what, p->where, p->cond); 402*5782Slinton if (isstdin()) { 403*5782Slinton status(); 404*5782Slinton } 405*5782Slinton break; 4065543Slinton 407*5782Slinton case O_STOP: 408*5782Slinton case O_STOPI: 409*5782Slinton stop(p->op, p->what, p->where, p->cond); 410*5782Slinton if (isstdin()) { 411*5782Slinton status(); 412*5782Slinton } 413*5782Slinton break; 4145543Slinton 415*5782Slinton case O_DELETE: 416*5782Slinton eval(p->left); 417*5782Slinton delbp((unsigned int) pop(long)); 418*5782Slinton break; 4195543Slinton 420*5782Slinton default: 421*5782Slinton panic("eval: bad op %d", p->op); 422*5782Slinton } 4235543Slinton } 4245543Slinton 4255543Slinton /* 4265562Slinton * Push "len" bytes onto the expression stack from address "addr" 4275562Slinton * in the process. Normally TRUE is returned, however if there 4285562Slinton * isn't enough room on the stack, rpush returns FALSE. 4295562Slinton */ 4305562Slinton 4315562Slinton BOOLEAN rpush(addr, len) 4325562Slinton ADDRESS addr; 4335562Slinton int len; 4345562Slinton { 435*5782Slinton BOOLEAN success; 4365562Slinton 437*5782Slinton if (sp + len >= &stack[STACKSIZE]) { 438*5782Slinton success = FALSE; 439*5782Slinton } else { 440*5782Slinton dread(sp, addr, len); 441*5782Slinton sp += len; 442*5782Slinton success = TRUE; 443*5782Slinton } 444*5782Slinton return success; 4455562Slinton } 4465562Slinton 4475562Slinton /* 448*5782Slinton * Pop an item of the given type which is assumed to be no larger 449*5782Slinton * than a long and return it expanded into a long. 450*5782Slinton */ 451*5782Slinton 452*5782Slinton long popsmall(t) 453*5782Slinton SYM *t; 454*5782Slinton { 455*5782Slinton long r; 456*5782Slinton 457*5782Slinton switch (size(t)) { 458*5782Slinton case sizeof(char): 459*5782Slinton r = (long) pop(char); 460*5782Slinton break; 461*5782Slinton 462*5782Slinton case sizeof(short): 463*5782Slinton r = (long) pop(short); 464*5782Slinton break; 465*5782Slinton 466*5782Slinton case sizeof(long): 467*5782Slinton r = pop(long); 468*5782Slinton break; 469*5782Slinton 470*5782Slinton default: 471*5782Slinton panic("popsmall: size is %d", size(t)); 472*5782Slinton } 473*5782Slinton return r; 474*5782Slinton } 475*5782Slinton 476*5782Slinton /* 4775543Slinton * evaluate a conditional expression 4785543Slinton */ 4795543Slinton 4805543Slinton BOOLEAN cond(p) 4815543Slinton NODE *p; 4825543Slinton { 483*5782Slinton if (p == NIL) { 484*5782Slinton return(TRUE); 485*5782Slinton } 486*5782Slinton eval(p); 487*5782Slinton return(pop(BOOLEAN)); 4885543Slinton } 4895543Slinton 4905543Slinton /* 4915543Slinton * Return the address corresponding to a given tree. 4925543Slinton */ 4935543Slinton 4945543Slinton ADDRESS lval(p) 4955543Slinton NODE *p; 4965543Slinton { 497*5782Slinton eval(p); 498*5782Slinton return(pop(ADDRESS)); 4995543Slinton } 500