1 /*- 2 * Copyright (c) 1980, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)eval.c 8.1 (Berkeley) 06/06/93"; 10 #endif /* not lint */ 11 12 /* 13 * Parse tree evaluation. 14 */ 15 16 #include "defs.h" 17 #include "tree.h" 18 #include "sym.h" 19 #include "process.h" 20 #include "source.h" 21 #include "mappings.h" 22 #include "breakpoint.h" 23 #include "machine.h" 24 #include "tree.rep" 25 #include "process/process.rep" 26 #include "process/pxinfo.h" 27 28 #define Boolean char /* underlying representation type for booleans */ 29 30 /* 31 * Evaluate a parse tree using a stack; value is left at top. 32 */ 33 34 #define STACKSIZE 2000 35 36 STACK stack[STACKSIZE]; 37 STACK *sp = &stack[0]; 38 39 eval(p) 40 register NODE *p; 41 { 42 long r0, r1; 43 double fr0, fr1; 44 FILE *fp; 45 46 if (p == NULL) { 47 return; 48 } 49 switch(degree(p->op)) { 50 case BINARY: 51 eval(p->right); 52 if (isreal(p->op)) { 53 fr1 = pop(double); 54 } else if (isint(p->op)) { 55 r1 = popsmall(p->right->nodetype); 56 } 57 /* fall through */ 58 case UNARY: 59 eval(p->left); 60 if (isreal(p->op)) { 61 fr0 = pop(double); 62 } else if (isint(p->op)) { 63 r0 = popsmall(p->left->nodetype); 64 } 65 break; 66 67 default: 68 /* do nothing */; 69 } 70 switch(p->op) { 71 case O_NAME: { 72 SYM *s, *f; 73 74 s = p->nameval; 75 if (!isvariable(s)) { 76 error("cannot evaluate a %s", classname(s)); 77 } else { 78 f = container(s); 79 if (!isactive(f)) { 80 error("\"%s\" is not active", name(f)); 81 } 82 push(long, address(s, NIL)); 83 } 84 break; 85 } 86 87 case O_LCON: 88 switch (size(p->nodetype)) { 89 case sizeof(char): 90 push(char, p->lconval); 91 break; 92 93 case sizeof(short): 94 push(short, p->lconval); 95 break; 96 97 case sizeof(long): 98 push(long, p->lconval); 99 break; 100 101 default: 102 panic("bad size %d for LCON", size(p->nodetype)); 103 } 104 break; 105 106 case O_FCON: 107 push(double, p->fconval); 108 break; 109 110 case O_SCON: { 111 int len; 112 113 len = size(p->nodetype); 114 mov(p->sconval, sp, len); 115 sp += len; 116 #ifdef tahoe 117 alignstack(); 118 #endif tahoe 119 break; 120 } 121 122 case O_INDEX: { 123 long n; /* base address for array */ 124 long i; /* index - lower bound */ 125 long evalindex(); 126 127 n = pop(long); 128 i = evalindex(p->left->nodetype, p->right); 129 push(long, n + i*size(p->nodetype)); 130 break; 131 } 132 133 case O_INDIR: { 134 ADDRESS a; 135 136 a = pop(ADDRESS); 137 if (a == 0) { 138 error("reference through nil pointer"); 139 } 140 dread(sp, a, sizeof(ADDRESS)); 141 sp += sizeof(ADDRESS); 142 break; 143 } 144 145 /* 146 * Get the value of the expression addressed by the top of the stack. 147 * Push the result back on the stack. 148 */ 149 150 case O_RVAL: { 151 ADDRESS addr, len; 152 153 addr = pop(long); 154 if (addr == 0) { 155 error("reference through nil pointer"); 156 } 157 len = size(p->nodetype); 158 if (!rpush(addr, len)) { 159 error("expression too large to evaluate"); 160 } 161 break; 162 } 163 164 case O_COMMA: 165 break; 166 167 case O_ITOF: 168 push(double, (double) r0); 169 break; 170 171 case O_ADD: 172 push(long, r0+r1); 173 break; 174 175 case O_ADDF: 176 push(double, fr0+fr1); 177 break; 178 179 case O_SUB: 180 push(long, r0-r1); 181 break; 182 183 case O_SUBF: 184 push(double, fr0-fr1); 185 break; 186 187 case O_NEG: 188 push(long, -r0); 189 break; 190 191 case O_NEGF: 192 push(double, -fr0); 193 break; 194 195 case O_MUL: 196 push(long, r0*r1); 197 break; 198 199 case O_MULF: 200 push(double, fr0*fr1); 201 break; 202 203 case O_DIVF: 204 if (fr1 == 0) { 205 error("error: division by 0"); 206 } 207 push(double, fr0/fr1); 208 break; 209 210 case O_DIV: 211 if (r1 == 0) { 212 error("error: div by 0"); 213 } 214 push(long, r0/r1); 215 break; 216 217 case O_MOD: 218 if (r1 == 0) { 219 error("error: mod by 0"); 220 } 221 push(long, r0%r1); 222 break; 223 224 case O_LT: 225 push(Boolean, r0 < r1); 226 break; 227 228 case O_LTF: 229 push(Boolean, fr0 < fr1); 230 break; 231 232 case O_LE: 233 push(Boolean, r0 <= r1); 234 break; 235 236 case O_LEF: 237 push(Boolean, fr0 <= fr1); 238 break; 239 240 case O_GT: 241 push(Boolean, r0 > r1); 242 break; 243 244 case O_GTF: 245 push(Boolean, fr0 > fr1); 246 break; 247 248 case O_EQ: 249 push(Boolean, r0 == r1); 250 break; 251 252 case O_EQF: 253 push(Boolean, fr0 == fr1); 254 break; 255 256 case O_NE: 257 push(Boolean, r0 != r1); 258 break; 259 260 case O_NEF: 261 push(Boolean, fr0 != fr1); 262 break; 263 264 case O_AND: 265 push(Boolean, r0 && r1); 266 break; 267 268 case O_OR: 269 push(Boolean, r0 || r1); 270 break; 271 272 case O_ASSIGN: 273 assign(p->left, p->right); 274 break; 275 276 case O_CHFILE: 277 if (p->sconval == NIL) { 278 printf("%s\n", cursource); 279 } else { 280 fp = fopen(p->sconval, "r"); 281 if (fp == NIL) { 282 error("can't read \"%s\"", p->sconval); 283 } else { 284 fclose(fp); 285 skimsource(p->sconval); 286 } 287 } 288 break; 289 290 case O_CONT: 291 cont(); 292 printnews(); 293 break; 294 295 case O_LIST: { 296 SYM *b; 297 ADDRESS addr; 298 299 if (p->left->op == O_NAME) { 300 b = p->left->nameval; 301 if (!isblock(b)) { 302 error("\"%s\" is not a procedure or function", name(b)); 303 } 304 addr = firstline(b); 305 if ((int)addr == -1) { 306 error("\"%s\" is empty", name(b)); 307 } 308 skimsource(srcfilename(addr)); 309 r0 = srcline(addr); 310 r1 = r0 + 5; 311 if (r1 > lastlinenum) { 312 r1 = lastlinenum; 313 } 314 r0 = r0 - 5; 315 if (r0 < 1) { 316 r0 = 1; 317 } 318 } else { 319 eval(p->left->right); 320 eval(p->left->left); 321 r0 = pop(long); 322 r1 = pop(long); 323 } 324 printlines((LINENO) r0, (LINENO) r1); 325 break; 326 } 327 328 case O_XI: 329 case O_XD: 330 { 331 SYM *b; 332 333 if (p->left->op == O_CALL) { 334 b = p->left->left->nameval; 335 r0 = codeloc(b); 336 r1 = firstline(b); 337 } else { 338 eval(p->left->right); 339 eval(p->left->left); 340 r0 = pop(long); 341 r1 = pop(long); 342 } 343 if (p->op == O_XI) { 344 printinst((ADDRESS) r0, (ADDRESS) r1); 345 } else { 346 printdata((ADDRESS) r0, (ADDRESS) r1); 347 } 348 break; 349 } 350 351 case O_NEXT: 352 next(); 353 printnews(); 354 break; 355 356 case O_PRINT: { 357 NODE *o; 358 359 for (o = p->left; o != NIL; o = o->right) { 360 eval(o->left); 361 printval(o->left->nodetype); 362 putchar(' '); 363 } 364 putchar('\n'); 365 break; 366 } 367 368 case O_STEP: 369 stepc(); 370 printnews(); 371 break; 372 373 case O_WHATIS: 374 if (p->left->op == O_NAME) { 375 printdecl(p->left->nameval); 376 } else { 377 printdecl(p->left->nodetype); 378 } 379 break; 380 381 case O_WHICH: 382 printwhich(p->nameval); 383 putchar('\n'); 384 break; 385 386 case O_WHERE: 387 where(); 388 break; 389 390 case O_ALIAS: 391 alias(p->left->sconval, p->right->sconval); 392 break; 393 394 case O_CALL: 395 callproc(p->left, p->right); 396 break; 397 398 case O_EDIT: 399 edit(p->sconval); 400 break; 401 402 case O_DUMP: 403 dump(); 404 break; 405 406 case O_GRIPE: 407 gripe(); 408 break; 409 410 case O_HELP: 411 help(); 412 break; 413 414 case O_REMAKE: 415 remake(); 416 break; 417 418 case O_RUN: 419 run(); 420 break; 421 422 case O_SOURCE: 423 setinput(p->sconval); 424 break; 425 426 case O_STATUS: 427 status(); 428 break; 429 430 case O_TRACE: 431 case O_TRACEI: 432 trace(p->op, p->what, p->where, p->cond); 433 if (isstdin()) { 434 status(); 435 } 436 break; 437 438 case O_STOP: 439 case O_STOPI: 440 stop(p->op, p->what, p->where, p->cond); 441 if (isstdin()) { 442 status(); 443 } 444 break; 445 446 case O_DELETE: 447 eval(p->left); 448 delbp((unsigned int) pop(long)); 449 break; 450 451 default: 452 panic("eval: bad op %d", p->op); 453 } 454 } 455 456 /* 457 * Push "len" bytes onto the expression stack from address "addr" 458 * in the process. Normally TRUE is returned, however if there 459 * isn't enough room on the stack, rpush returns FALSE. 460 */ 461 462 BOOLEAN rpush(addr, len) 463 ADDRESS addr; 464 int len; 465 { 466 BOOLEAN success; 467 #ifdef tahoe 468 register char *savesp = sp; 469 #endif 470 471 if (sp + len >= &stack[STACKSIZE]) { 472 success = FALSE; 473 } else { 474 dread(sp, addr, len); 475 sp += len; 476 #ifdef tahoe 477 alignstack(); 478 if (sp >= &stack[STACKSIZE]) { 479 success = FALSE; 480 sp = savesp; 481 } else 482 #endif 483 success = TRUE; 484 } 485 return success; 486 } 487 488 /* 489 * Pop an item of the given type which is assumed to be no larger 490 * than a long and return it expanded into a long. 491 */ 492 493 long popsmall(t) 494 SYM *t; 495 { 496 long r; 497 498 switch (size(t)) { 499 case sizeof(char): 500 r = (long) pop(char); 501 break; 502 503 case sizeof(short): 504 r = (long) pop(short); 505 break; 506 507 case sizeof(long): 508 r = pop(long); 509 break; 510 511 /* 512 * A bit of a kludge here. If an array element is a record, 513 * the dot operation will be converted into an addition with 514 * the record operand having a type whose size may be larger 515 * than a word. Now actually this is a pointer, but the subscript 516 * operation isn't aware of this, so it's just hacked here. 517 * 518 * The right thing to do is to make dot directly evaluated 519 * instead of changing it into addition. 520 */ 521 default: 522 r = pop(ADDRESS); 523 break; 524 } 525 return r; 526 } 527 528 /* 529 * evaluate a conditional expression 530 */ 531 532 BOOLEAN cond(p) 533 NODE *p; 534 { 535 if (p == NIL) { 536 return(TRUE); 537 } 538 eval(p); 539 return(pop(BOOLEAN)); 540 } 541 542 /* 543 * Return the address corresponding to a given tree. 544 */ 545 546 ADDRESS lval(p) 547 NODE *p; 548 { 549 eval(p); 550 return(pop(ADDRESS)); 551 } 552