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