1*5543Slinton /* Copyright (c) 1982 Regents of the University of California */ 2*5543Slinton 3*5543Slinton static char sccsid[] = "@(#)eval.c 1.1 01/18/82"; 4*5543Slinton 5*5543Slinton /* 6*5543Slinton * parse tree evaluation 7*5543Slinton */ 8*5543Slinton 9*5543Slinton #include "defs.h" 10*5543Slinton #include "tree.h" 11*5543Slinton #include "sym.h" 12*5543Slinton #include "process.h" 13*5543Slinton #include "source.h" 14*5543Slinton #include "mappings.h" 15*5543Slinton #include "breakpoint.h" 16*5543Slinton #include "machine.h" 17*5543Slinton #include "tree.rep" 18*5543Slinton 19*5543Slinton /* 20*5543Slinton * Evaluate a parse tree using a stack; value is left at top. 21*5543Slinton */ 22*5543Slinton 23*5543Slinton STACK *sp = &stack[0]; 24*5543Slinton 25*5543Slinton eval(p) 26*5543Slinton register NODE *p; 27*5543Slinton { 28*5543Slinton long r0, r1; 29*5543Slinton double fr0, fr1; 30*5543Slinton 31*5543Slinton if (p == NULL) { 32*5543Slinton return; 33*5543Slinton } 34*5543Slinton switch(degree(p->op)) { 35*5543Slinton case BINARY: 36*5543Slinton eval(p->right); 37*5543Slinton if (isreal(p->op)) { 38*5543Slinton fr1 = pop(double); 39*5543Slinton } else if (isint(p->op)) { 40*5543Slinton r1 = pop(long); 41*5543Slinton } 42*5543Slinton /* fall through */ 43*5543Slinton case UNARY: 44*5543Slinton eval(p->left); 45*5543Slinton if (isreal(p->op)) { 46*5543Slinton fr0 = pop(double); 47*5543Slinton } else if (isint(p->op)) { 48*5543Slinton r0 = pop(long); 49*5543Slinton } 50*5543Slinton break; 51*5543Slinton 52*5543Slinton default: 53*5543Slinton /* do nothing */; 54*5543Slinton } 55*5543Slinton switch(p->op) { 56*5543Slinton case O_NAME: { 57*5543Slinton SYM *s, *f; 58*5543Slinton 59*5543Slinton s = p->nameval; 60*5543Slinton f = container(s); 61*5543Slinton if (!isactive(f)) { 62*5543Slinton error("\"%s\" is not active", name(f)); 63*5543Slinton } 64*5543Slinton push(int, address(s, NIL)); 65*5543Slinton break; 66*5543Slinton } 67*5543Slinton 68*5543Slinton case O_LCON: 69*5543Slinton push(long, p->lconval); 70*5543Slinton break; 71*5543Slinton 72*5543Slinton case O_FCON: 73*5543Slinton push(double, p->fconval); 74*5543Slinton break; 75*5543Slinton 76*5543Slinton case O_SCON: { 77*5543Slinton int len; 78*5543Slinton 79*5543Slinton len = size(p->nodetype); 80*5543Slinton mov(p->sconval, sp, len); 81*5543Slinton sp += len; 82*5543Slinton break; 83*5543Slinton } 84*5543Slinton 85*5543Slinton case O_INDEX: { 86*5543Slinton int n; 87*5543Slinton long i; 88*5543Slinton 89*5543Slinton n = pop(int); 90*5543Slinton i = evalindex(p->left->nodetype); 91*5543Slinton push(int, n + i*size(p->nodetype)); 92*5543Slinton break; 93*5543Slinton } 94*5543Slinton 95*5543Slinton case O_INDIR: { 96*5543Slinton ADDRESS a; 97*5543Slinton 98*5543Slinton a = pop(ADDRESS); 99*5543Slinton if (a == 0) { 100*5543Slinton error("reference through nil pointer"); 101*5543Slinton } 102*5543Slinton dread(sp, a, sizeof(ADDRESS)); 103*5543Slinton sp += sizeof(ADDRESS); 104*5543Slinton break; 105*5543Slinton } 106*5543Slinton 107*5543Slinton /* 108*5543Slinton * Get the value of the expression addressed by the top of the stack. 109*5543Slinton * Push the result back on the stack. Never push less than a long. 110*5543Slinton */ 111*5543Slinton 112*5543Slinton case O_RVAL: { 113*5543Slinton ADDRESS addr, len; 114*5543Slinton long i; 115*5543Slinton 116*5543Slinton addr = pop(int); 117*5543Slinton if (addr == 0) { 118*5543Slinton error("reference through nil pointer"); 119*5543Slinton } 120*5543Slinton len = size(p->nodetype); 121*5543Slinton dread(sp, addr, len); 122*5543Slinton sp += len; 123*5543Slinton if (len < sizeof(long)) { 124*5543Slinton switch (len) { 125*5543Slinton case sizeof(char): 126*5543Slinton i = pop(char); 127*5543Slinton break; 128*5543Slinton 129*5543Slinton case sizeof(short): 130*5543Slinton i = pop(short); 131*5543Slinton break; 132*5543Slinton 133*5543Slinton default: 134*5543Slinton panic("bad size in RVAL"); 135*5543Slinton } 136*5543Slinton push(long, i); 137*5543Slinton } 138*5543Slinton break; 139*5543Slinton } 140*5543Slinton 141*5543Slinton case O_COMMA: 142*5543Slinton break; 143*5543Slinton 144*5543Slinton case O_ITOF: 145*5543Slinton push(double, (double) r0); 146*5543Slinton break; 147*5543Slinton 148*5543Slinton case O_ADD: 149*5543Slinton push(long, r0+r1); 150*5543Slinton break; 151*5543Slinton 152*5543Slinton case O_ADDF: 153*5543Slinton push(double, fr0+fr1); 154*5543Slinton break; 155*5543Slinton 156*5543Slinton case O_SUB: 157*5543Slinton push(long, r0-r1); 158*5543Slinton break; 159*5543Slinton 160*5543Slinton case O_SUBF: 161*5543Slinton push(double, fr0-fr1); 162*5543Slinton break; 163*5543Slinton 164*5543Slinton case O_NEG: 165*5543Slinton push(long, -r0); 166*5543Slinton break; 167*5543Slinton 168*5543Slinton case O_NEGF: 169*5543Slinton push(double, -fr0); 170*5543Slinton break; 171*5543Slinton 172*5543Slinton case O_MUL: 173*5543Slinton push(long, r0*r1); 174*5543Slinton break; 175*5543Slinton 176*5543Slinton case O_MULF: 177*5543Slinton push(double, fr0*fr1); 178*5543Slinton break; 179*5543Slinton 180*5543Slinton case O_DIVF: 181*5543Slinton if (fr1 == 0) { 182*5543Slinton error("error: division by 0"); 183*5543Slinton } 184*5543Slinton push(double, fr0/fr1); 185*5543Slinton break; 186*5543Slinton 187*5543Slinton case O_DIV: 188*5543Slinton if (r1 == 0) { 189*5543Slinton error("error: div by 0"); 190*5543Slinton } 191*5543Slinton push(long, r0/r1); 192*5543Slinton break; 193*5543Slinton 194*5543Slinton case O_MOD: 195*5543Slinton if (r1 == 0) { 196*5543Slinton error("error: mod by 0"); 197*5543Slinton } 198*5543Slinton push(long, r0%r1); 199*5543Slinton break; 200*5543Slinton 201*5543Slinton case O_LT: 202*5543Slinton push(BOOLEAN, r0 < r1); 203*5543Slinton break; 204*5543Slinton 205*5543Slinton case O_LTF: 206*5543Slinton push(BOOLEAN, fr0 < fr1); 207*5543Slinton break; 208*5543Slinton 209*5543Slinton case O_LE: 210*5543Slinton push(BOOLEAN, r0 <= r1); 211*5543Slinton break; 212*5543Slinton 213*5543Slinton case O_LEF: 214*5543Slinton push(BOOLEAN, fr0 <= fr1); 215*5543Slinton break; 216*5543Slinton 217*5543Slinton case O_GT: 218*5543Slinton push(BOOLEAN, r0 > r1); 219*5543Slinton break; 220*5543Slinton 221*5543Slinton case O_GTF: 222*5543Slinton push(BOOLEAN, fr0 > fr1); 223*5543Slinton break; 224*5543Slinton 225*5543Slinton case O_EQ: 226*5543Slinton push(BOOLEAN, r0 == r1); 227*5543Slinton break; 228*5543Slinton 229*5543Slinton case O_EQF: 230*5543Slinton push(BOOLEAN, fr0 == fr1); 231*5543Slinton break; 232*5543Slinton 233*5543Slinton case O_NE: 234*5543Slinton push(BOOLEAN, r0 != r1); 235*5543Slinton break; 236*5543Slinton 237*5543Slinton case O_NEF: 238*5543Slinton push(BOOLEAN, fr0 != fr1); 239*5543Slinton break; 240*5543Slinton 241*5543Slinton case O_AND: 242*5543Slinton push(BOOLEAN, r0 && r1); 243*5543Slinton break; 244*5543Slinton 245*5543Slinton case O_OR: 246*5543Slinton push(BOOLEAN, r0 || r1); 247*5543Slinton break; 248*5543Slinton 249*5543Slinton case O_ASSIGN: 250*5543Slinton assign(p->left, p->right); 251*5543Slinton break; 252*5543Slinton 253*5543Slinton case O_CHFILE: 254*5543Slinton if (p->sconval == NIL) { 255*5543Slinton printf("%s\n", cursource); 256*5543Slinton } else { 257*5543Slinton skimsource(p->sconval); 258*5543Slinton } 259*5543Slinton break; 260*5543Slinton 261*5543Slinton case O_CONT: 262*5543Slinton cont(); 263*5543Slinton printnews(); 264*5543Slinton break; 265*5543Slinton 266*5543Slinton case O_LIST: { 267*5543Slinton SYM *b; 268*5543Slinton 269*5543Slinton if (p->left->op == O_NAME) { 270*5543Slinton b = p->left->nameval; 271*5543Slinton if (!isblock(b)) { 272*5543Slinton error("\"%s\" is not a procedure or function", name(b)); 273*5543Slinton } 274*5543Slinton r0 = srcline(firstline(b)); 275*5543Slinton r1 = r0 + 5; 276*5543Slinton if (r1 > lastlinenum) { 277*5543Slinton r1 = lastlinenum; 278*5543Slinton } 279*5543Slinton r0 = r0 - 5; 280*5543Slinton if (r0 < 1) { 281*5543Slinton r0 = 1; 282*5543Slinton } 283*5543Slinton } else { 284*5543Slinton eval(p->left->right); 285*5543Slinton eval(p->left->left); 286*5543Slinton r0 = pop(long); 287*5543Slinton r1 = pop(long); 288*5543Slinton } 289*5543Slinton printlines((LINENO) r0, (LINENO) r1); 290*5543Slinton break; 291*5543Slinton } 292*5543Slinton 293*5543Slinton case O_XI: 294*5543Slinton case O_XD: 295*5543Slinton { 296*5543Slinton SYM *b; 297*5543Slinton 298*5543Slinton if (p->left->op == O_CALL) { 299*5543Slinton b = p->left->left->nameval; 300*5543Slinton r0 = codeloc(b); 301*5543Slinton r1 = firstline(b); 302*5543Slinton } else { 303*5543Slinton eval(p->left->right); 304*5543Slinton eval(p->left->left); 305*5543Slinton r0 = pop(long); 306*5543Slinton r1 = pop(long); 307*5543Slinton } 308*5543Slinton if (p->op == O_XI) { 309*5543Slinton printinst((ADDRESS) r0, (ADDRESS) r1); 310*5543Slinton } else { 311*5543Slinton printdata((ADDRESS) r0, (ADDRESS) r1); 312*5543Slinton } 313*5543Slinton break; 314*5543Slinton } 315*5543Slinton 316*5543Slinton case O_NEXT: 317*5543Slinton next(); 318*5543Slinton printnews(); 319*5543Slinton break; 320*5543Slinton 321*5543Slinton case O_PRINT: { 322*5543Slinton NODE *o; 323*5543Slinton 324*5543Slinton for (o = p->left; o != NIL; o = o->right) { 325*5543Slinton eval(o->left); 326*5543Slinton printval(o->left->nodetype); 327*5543Slinton putchar(' '); 328*5543Slinton } 329*5543Slinton putchar('\n'); 330*5543Slinton break; 331*5543Slinton } 332*5543Slinton 333*5543Slinton case O_STEP: 334*5543Slinton stepc(); 335*5543Slinton printnews(); 336*5543Slinton break; 337*5543Slinton 338*5543Slinton case O_WHATIS: 339*5543Slinton if (p->left->op == O_NAME) { 340*5543Slinton printdecl(p->left->nameval); 341*5543Slinton } else { 342*5543Slinton printdecl(p->left->nodetype); 343*5543Slinton } 344*5543Slinton break; 345*5543Slinton 346*5543Slinton case O_WHICH: 347*5543Slinton printwhich(p->nameval); 348*5543Slinton putchar('\n'); 349*5543Slinton break; 350*5543Slinton 351*5543Slinton case O_WHERE: 352*5543Slinton where(); 353*5543Slinton break; 354*5543Slinton 355*5543Slinton case O_ALIAS: 356*5543Slinton alias(p->left->sconval, p->right->sconval); 357*5543Slinton break; 358*5543Slinton 359*5543Slinton case O_CALL: 360*5543Slinton callproc(p->left, p->right); 361*5543Slinton break; 362*5543Slinton 363*5543Slinton case O_EDIT: 364*5543Slinton edit(p->sconval); 365*5543Slinton break; 366*5543Slinton 367*5543Slinton case O_DUMP: 368*5543Slinton dump(); 369*5543Slinton break; 370*5543Slinton 371*5543Slinton case O_HELP: 372*5543Slinton help(); 373*5543Slinton break; 374*5543Slinton 375*5543Slinton case O_REMAKE: 376*5543Slinton remake(); 377*5543Slinton break; 378*5543Slinton 379*5543Slinton case O_RUN: 380*5543Slinton run(); 381*5543Slinton break; 382*5543Slinton 383*5543Slinton case O_SOURCE: 384*5543Slinton setinput(p->sconval); 385*5543Slinton break; 386*5543Slinton 387*5543Slinton case O_STATUS: 388*5543Slinton status(); 389*5543Slinton break; 390*5543Slinton 391*5543Slinton case O_TRACE: 392*5543Slinton case O_TRACEI: 393*5543Slinton trace(p->op, p->what, p->where, p->cond); 394*5543Slinton if (isstdin()) { 395*5543Slinton status(); 396*5543Slinton } 397*5543Slinton break; 398*5543Slinton 399*5543Slinton case O_STOP: 400*5543Slinton case O_STOPI: 401*5543Slinton stop(p->op, p->what, p->where, p->cond); 402*5543Slinton if (isstdin()) { 403*5543Slinton status(); 404*5543Slinton } 405*5543Slinton break; 406*5543Slinton 407*5543Slinton case O_DELETE: 408*5543Slinton eval(p->left); 409*5543Slinton delbp((unsigned int) pop(long)); 410*5543Slinton break; 411*5543Slinton 412*5543Slinton default: 413*5543Slinton panic("eval: bad op %d", p->op); 414*5543Slinton } 415*5543Slinton } 416*5543Slinton 417*5543Slinton /* 418*5543Slinton * evaluate a conditional expression 419*5543Slinton */ 420*5543Slinton 421*5543Slinton BOOLEAN cond(p) 422*5543Slinton NODE *p; 423*5543Slinton { 424*5543Slinton if (p == NIL) { 425*5543Slinton return(TRUE); 426*5543Slinton } 427*5543Slinton eval(p); 428*5543Slinton return(pop(BOOLEAN)); 429*5543Slinton } 430*5543Slinton 431*5543Slinton /* 432*5543Slinton * Return the address corresponding to a given tree. 433*5543Slinton */ 434*5543Slinton 435*5543Slinton ADDRESS lval(p) 436*5543Slinton NODE *p; 437*5543Slinton { 438*5543Slinton eval(p); 439*5543Slinton return(pop(ADDRESS)); 440*5543Slinton } 441