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
eval(p)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
rpush(addr,len)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
popsmall(t)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
cond(p)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
lval(p)546 ADDRESS lval(p)
547 NODE *p;
548 {
549 eval(p);
550 return(pop(ADDRESS));
551 }
552