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