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