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