xref: /csrg-svn/old/dbx/tree.c (revision 9681)
1*9681Slinton /* Copyright (c) 1982 Regents of the University of California */
2*9681Slinton 
3*9681Slinton static char sccsid[] = "@(#)@(#)tree.c 1.1 12/15/82";
4*9681Slinton 
5*9681Slinton /*
6*9681Slinton  * Parse tree management.
7*9681Slinton  */
8*9681Slinton 
9*9681Slinton #include "defs.h"
10*9681Slinton #include "tree.h"
11*9681Slinton #include "operators.h"
12*9681Slinton #include "eval.h"
13*9681Slinton #include "events.h"
14*9681Slinton #include "symbols.h"
15*9681Slinton #include "scanner.h"
16*9681Slinton #include "source.h"
17*9681Slinton #include "object.h"
18*9681Slinton #include "mappings.h"
19*9681Slinton #include "process.h"
20*9681Slinton #include "machine.h"
21*9681Slinton 
22*9681Slinton #ifndef public
23*9681Slinton #include "lists.h"
24*9681Slinton 
25*9681Slinton typedef struct Node *Node;
26*9681Slinton typedef Node Command;
27*9681Slinton typedef List Cmdlist;
28*9681Slinton 
29*9681Slinton #include "operators.h"
30*9681Slinton #include "symbols.h"
31*9681Slinton #include "events.h"
32*9681Slinton 
33*9681Slinton #define MAXNARGS 5
34*9681Slinton 
35*9681Slinton struct Node {
36*9681Slinton     Operator op;
37*9681Slinton     Symbol nodetype;
38*9681Slinton     union treevalue {
39*9681Slinton 	Symbol sym;
40*9681Slinton 	Name name;
41*9681Slinton 	long lcon;
42*9681Slinton 	double fcon;
43*9681Slinton 	String scon;
44*9681Slinton 	Node arg[MAXNARGS];
45*9681Slinton 	struct {
46*9681Slinton 	    Node cond;
47*9681Slinton 	    Cmdlist actions;
48*9681Slinton 	} event;
49*9681Slinton 	struct {
50*9681Slinton 	    Boolean inst;
51*9681Slinton 	    Event event;
52*9681Slinton 	    Cmdlist actions;
53*9681Slinton 	} trace;
54*9681Slinton 	struct {
55*9681Slinton 	    Boolean source;
56*9681Slinton 	    Boolean skipcalls;
57*9681Slinton 	} step;
58*9681Slinton 	struct {
59*9681Slinton 	    String mode;
60*9681Slinton 	    Node beginaddr;
61*9681Slinton 	    Node endaddr;
62*9681Slinton 	    Integer count;
63*9681Slinton 	} examine;
64*9681Slinton     } value;
65*9681Slinton };
66*9681Slinton 
67*9681Slinton #define evalcmd(cmd) eval(cmd)
68*9681Slinton #define cmdlist_append(cmd, cl) list_append(list_item(cmd), nil, cl)
69*9681Slinton 
70*9681Slinton #endif
71*9681Slinton 
72*9681Slinton typedef char *Arglist;
73*9681Slinton 
74*9681Slinton #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
75*9681Slinton 
76*9681Slinton /*
77*9681Slinton  * Build a tree.
78*9681Slinton  */
79*9681Slinton 
80*9681Slinton /* VARARGS1 */
81*9681Slinton public Node build(op, args)
82*9681Slinton Operator op;
83*9681Slinton {
84*9681Slinton     register Node p, q;
85*9681Slinton     register Arglist ap;
86*9681Slinton     Integer i;
87*9681Slinton 
88*9681Slinton     p = new(Node);
89*9681Slinton     p->op = op;
90*9681Slinton     p->nodetype = nil;
91*9681Slinton     ap = (Arglist) &args;
92*9681Slinton     switch (op) {
93*9681Slinton 	case O_NAME:
94*9681Slinton 	    p->value.name = nextarg(Name);
95*9681Slinton 	    break;
96*9681Slinton 
97*9681Slinton 	case O_SYM:
98*9681Slinton 	case O_PRINTCALL:
99*9681Slinton 	case O_PRINTRTN:
100*9681Slinton 	case O_PROCRTN:
101*9681Slinton 	    p->value.sym = nextarg(Symbol);
102*9681Slinton 	    break;
103*9681Slinton 
104*9681Slinton 	case O_LCON:
105*9681Slinton 	case O_DELETE:
106*9681Slinton 	case O_CATCH:
107*9681Slinton 	case O_IGNORE:
108*9681Slinton 	case O_TRACEOFF:
109*9681Slinton 	    p->value.lcon = nextarg(long);
110*9681Slinton 	    break;
111*9681Slinton 
112*9681Slinton 	case O_FCON:
113*9681Slinton 	    p->value.fcon = nextarg(double);
114*9681Slinton 	    break;
115*9681Slinton 
116*9681Slinton 	case O_SCON:
117*9681Slinton 	case O_CHFILE:
118*9681Slinton 	case O_EDIT:
119*9681Slinton 	case O_SOURCE:
120*9681Slinton 	    p->value.scon = nextarg(String);
121*9681Slinton 	    break;
122*9681Slinton 
123*9681Slinton 	case O_RVAL:
124*9681Slinton 	    q = nextarg(Node);
125*9681Slinton 	    if (q->op == O_CALL) {
126*9681Slinton 		*p = *q;
127*9681Slinton 		dispose(q);
128*9681Slinton 	    } else {
129*9681Slinton 		p->value.arg[0] = q;
130*9681Slinton 	    }
131*9681Slinton 	    break;
132*9681Slinton 
133*9681Slinton 	case O_INDIR:
134*9681Slinton 	    q = nextarg(Node);
135*9681Slinton 	    if (q != nil and q->op == O_RVAL) {
136*9681Slinton 		p->value.arg[0] = q->value.arg[0];
137*9681Slinton 		dispose(q);
138*9681Slinton 	    } else {
139*9681Slinton 		p->value.arg[0] = q;
140*9681Slinton 	    }
141*9681Slinton 	    break;
142*9681Slinton 
143*9681Slinton 	case O_ADDEVENT:
144*9681Slinton 	case O_ONCE:
145*9681Slinton 	case O_IF:
146*9681Slinton 	    p->value.event.cond = nextarg(Node);
147*9681Slinton 	    p->value.event.actions = nextarg(Cmdlist);
148*9681Slinton 	    break;
149*9681Slinton 
150*9681Slinton 	case O_TRACEON:
151*9681Slinton 	    p->value.trace.inst = nextarg(Boolean);
152*9681Slinton 	    p->value.trace.event = nil;
153*9681Slinton 	    p->value.trace.actions = nextarg(Cmdlist);
154*9681Slinton 	    break;
155*9681Slinton 
156*9681Slinton 	case O_STEP:
157*9681Slinton 	    p->value.step.source = nextarg(Boolean);
158*9681Slinton 	    p->value.step.skipcalls = nextarg(Boolean);
159*9681Slinton 	    break;
160*9681Slinton 
161*9681Slinton 	case O_EXAMINE:
162*9681Slinton 	    p->value.examine.mode = nextarg(String);
163*9681Slinton 	    p->value.examine.beginaddr = nextarg(Node);
164*9681Slinton 	    p->value.examine.endaddr = nextarg(Node);
165*9681Slinton 	    p->value.examine.count = nextarg(Integer);
166*9681Slinton 	    break;
167*9681Slinton 
168*9681Slinton 	default:
169*9681Slinton 	    for (i = 0; i < nargs(op); i++) {
170*9681Slinton 		p->value.arg[i] = nextarg(Node);
171*9681Slinton 	    }
172*9681Slinton 	    break;
173*9681Slinton     }
174*9681Slinton     check(p);
175*9681Slinton     assigntypes(p);
176*9681Slinton     return p;
177*9681Slinton }
178*9681Slinton 
179*9681Slinton /*
180*9681Slinton  * Create a command list from a single command.
181*9681Slinton  */
182*9681Slinton 
183*9681Slinton public Cmdlist buildcmdlist(cmd)
184*9681Slinton Command cmd;
185*9681Slinton {
186*9681Slinton     Cmdlist cmdlist;
187*9681Slinton 
188*9681Slinton     cmdlist = list_alloc();
189*9681Slinton     cmdlist_append(cmd, cmdlist);
190*9681Slinton     return cmdlist;
191*9681Slinton }
192*9681Slinton 
193*9681Slinton /*
194*9681Slinton  * Return the tree for a unary ampersand operator.
195*9681Slinton  */
196*9681Slinton 
197*9681Slinton public Node amper(p)
198*9681Slinton Node p;
199*9681Slinton {
200*9681Slinton     Node r;
201*9681Slinton 
202*9681Slinton     checkref(p);
203*9681Slinton     switch (p->op) {
204*9681Slinton 	case O_RVAL:
205*9681Slinton 	    r = p->value.arg[0];
206*9681Slinton 	    break;
207*9681Slinton 
208*9681Slinton 	case O_CALL:
209*9681Slinton 	    r = build(O_LCON, codeloc(p->value.arg[0]->value.sym));
210*9681Slinton 	    tfree(p);
211*9681Slinton 	    break;
212*9681Slinton 
213*9681Slinton 	case O_SYM:
214*9681Slinton 	    if (isblock(p->value.sym)) {
215*9681Slinton 		r = build(O_LCON, codeloc(p->value.sym));
216*9681Slinton 	    } else {
217*9681Slinton 		r = build(O_LCON, address(p->value.sym, nil));
218*9681Slinton 	    }
219*9681Slinton 	    tfree(p);
220*9681Slinton 	    break;
221*9681Slinton 
222*9681Slinton 	case O_DOT:
223*9681Slinton 	    r = p;
224*9681Slinton 	    break;
225*9681Slinton 
226*9681Slinton 	case O_INDIR:
227*9681Slinton 	    r = p->value.arg[0];
228*9681Slinton 	    dispose(p);
229*9681Slinton 	    break;
230*9681Slinton 
231*9681Slinton 	default:
232*9681Slinton 	    beginerrmsg();
233*9681Slinton 	    fprintf(stderr, "expected variable, found ");
234*9681Slinton 	    prtree(stderr, p);
235*9681Slinton 	    tfree(p);
236*9681Slinton 	    enderrmsg();
237*9681Slinton 	    /* NOTREACHED */
238*9681Slinton     }
239*9681Slinton     r->nodetype = t_int;
240*9681Slinton     return r;
241*9681Slinton }
242*9681Slinton 
243*9681Slinton /*
244*9681Slinton  * Create a "concrete" version of a node.
245*9681Slinton  * This is necessary when the type of the node contains
246*9681Slinton  * an unresolved type reference.
247*9681Slinton  */
248*9681Slinton 
249*9681Slinton public Node concrete(p)
250*9681Slinton Node p;
251*9681Slinton {
252*9681Slinton     findtype(p->nodetype);
253*9681Slinton     return build(O_INDIR, p);
254*9681Slinton }
255*9681Slinton 
256*9681Slinton /*
257*9681Slinton  * Print out a command.
258*9681Slinton  */
259*9681Slinton 
260*9681Slinton public printcmd(f, cmd)
261*9681Slinton File f;
262*9681Slinton Command cmd;
263*9681Slinton {
264*9681Slinton     register Integer i;
265*9681Slinton     register Command c;
266*9681Slinton     register Node p;
267*9681Slinton 
268*9681Slinton     switch (cmd->op) {
269*9681Slinton 	case O_PRINTIFCHANGED:
270*9681Slinton 	case O_PRINTSRCPOS:
271*9681Slinton 	case O_STOPIFCHANGED:
272*9681Slinton 	case O_TRACEON:
273*9681Slinton 	    break;
274*9681Slinton 
275*9681Slinton 	case O_STEP:
276*9681Slinton 	    if (cmd->value.step.skipcalls) {
277*9681Slinton 		fprintf(f, "next");
278*9681Slinton 	    } else {
279*9681Slinton 		fprintf(f, "step");
280*9681Slinton 	    }
281*9681Slinton 	    if (not cmd->value.step.source) {
282*9681Slinton 		fprintf(f, "i");
283*9681Slinton 	    }
284*9681Slinton 	    break;
285*9681Slinton 
286*9681Slinton 	default:
287*9681Slinton 	    fprintf(f, "%s", opinfo[ord(cmd->op)].opstring);
288*9681Slinton 	    if (nargs(cmd->op) != 0) {
289*9681Slinton 		fprintf(f, " ");
290*9681Slinton 	    }
291*9681Slinton 	    break;
292*9681Slinton     }
293*9681Slinton     switch (cmd->op) {
294*9681Slinton 	case O_PRINTCALL:
295*9681Slinton 	case O_PRINTRTN:
296*9681Slinton 	case O_PROCRTN:
297*9681Slinton 	    fprintf(f, "%s", symname(cmd->value.sym));
298*9681Slinton 	    break;
299*9681Slinton 
300*9681Slinton 	case O_PRINTSRCPOS:
301*9681Slinton 	    p = cmd->value.arg[0];
302*9681Slinton 	    if (p != nil and p->op != O_QLINE) {
303*9681Slinton 		printf("trace ");
304*9681Slinton 		prtree(f, p);
305*9681Slinton 	    }
306*9681Slinton 	    break;
307*9681Slinton 
308*9681Slinton 	case O_CHFILE:
309*9681Slinton 	case O_EDIT:
310*9681Slinton 	case O_SOURCE:
311*9681Slinton 	    fprintf(f, "%s", cmd->value.scon);
312*9681Slinton 	    break;
313*9681Slinton 
314*9681Slinton 	case O_DELETE:
315*9681Slinton 	case O_CATCH:
316*9681Slinton 	case O_IGNORE:
317*9681Slinton 	case O_TRACEOFF:
318*9681Slinton 	    fprintf(f, "%d", cmd->value.lcon);
319*9681Slinton 	    break;
320*9681Slinton 
321*9681Slinton 	case O_ADDEVENT:
322*9681Slinton 	case O_ONCE:
323*9681Slinton 	case O_IF:
324*9681Slinton 	    fprintf(f, " ");
325*9681Slinton 	    prtree(f, cmd->value.event.cond);
326*9681Slinton 	    fprintf(f, " { ");
327*9681Slinton 	    foreach (Command, c, cmd->value.event.actions)
328*9681Slinton 		printcmd(f, c);
329*9681Slinton 		if (not list_islast()) {
330*9681Slinton 		    fprintf(f, ";");
331*9681Slinton 		}
332*9681Slinton 	    endfor
333*9681Slinton 	    fprintf(f, " }", opinfo[ord(cmd->op)].opstring);
334*9681Slinton 	    break;
335*9681Slinton 
336*9681Slinton 	case O_TRACEON:
337*9681Slinton 	    print_tracestop(f, cmd);
338*9681Slinton 	    break;
339*9681Slinton 
340*9681Slinton 	case O_EXAMINE:
341*9681Slinton 	    prtree(f, cmd->value.examine.beginaddr);
342*9681Slinton 	    if (cmd->value.examine.endaddr != nil) {
343*9681Slinton 		fprintf(f, ",");
344*9681Slinton 		prtree(f, cmd->value.examine.endaddr);
345*9681Slinton 	    }
346*9681Slinton 	    fprintf(f, "/");
347*9681Slinton 	    if (cmd->value.examine.count > 1) {
348*9681Slinton 		fprintf(f, "%d", cmd->value.examine.count);
349*9681Slinton 	    }
350*9681Slinton 	    fprintf("%s", cmd->value.examine.mode);
351*9681Slinton 	    break;
352*9681Slinton 
353*9681Slinton 	default:
354*9681Slinton 	    if (nargs(cmd->op) != 0) {
355*9681Slinton 		i = 0;
356*9681Slinton 		for (;;) {
357*9681Slinton 		    prtree(f, cmd->value.arg[i]);
358*9681Slinton 		    ++i;
359*9681Slinton 		if (i >= nargs(cmd->op)) break;
360*9681Slinton 		    fprintf(f, " ");
361*9681Slinton 		}
362*9681Slinton 	    }
363*9681Slinton 	    break;
364*9681Slinton     }
365*9681Slinton }
366*9681Slinton 
367*9681Slinton /*
368*9681Slinton  * Print out a trace/stop command name.
369*9681Slinton  */
370*9681Slinton 
371*9681Slinton private print_tracestop(f, cmd)
372*9681Slinton File f;
373*9681Slinton Command cmd;
374*9681Slinton {
375*9681Slinton     register Command c, ifcmd, stopcmd;
376*9681Slinton     Boolean done;
377*9681Slinton 
378*9681Slinton     done = false;
379*9681Slinton     ifcmd = list_element(Command, list_head(cmd->value.trace.actions));
380*9681Slinton     checkref(ifcmd);
381*9681Slinton     if (ifcmd->op == O_IF) {
382*9681Slinton 	stopcmd = list_element(Command, list_head(ifcmd->value.event.actions));
383*9681Slinton 	checkref(stopcmd);
384*9681Slinton 	if (stopcmd->op == O_STOPX) {
385*9681Slinton 	    fprintf(f, "%s if ", cmd->value.trace.inst ? "stopi" : "stop");
386*9681Slinton 	    prtree(f, ifcmd->value.event.cond);
387*9681Slinton 	    done = true;
388*9681Slinton 	}
389*9681Slinton     }
390*9681Slinton     if (not done) {
391*9681Slinton 	fprintf(f, "%s ", cmd->value.trace.inst ? "tracei" : "trace");
392*9681Slinton 	foreach (Command, c, cmd->value.trace.actions)
393*9681Slinton 	    printcmd(f, c);
394*9681Slinton 	    if (not list_islast()) {
395*9681Slinton 		fprintf(f, ";");
396*9681Slinton 	    }
397*9681Slinton 	endfor
398*9681Slinton     }
399*9681Slinton }
400*9681Slinton 
401*9681Slinton /*
402*9681Slinton  * Print a tree back out in Pascal form.
403*9681Slinton  */
404*9681Slinton 
405*9681Slinton public prtree(f, p)
406*9681Slinton File f;
407*9681Slinton register Node p;
408*9681Slinton {
409*9681Slinton     register Node q;
410*9681Slinton     Operator op;
411*9681Slinton 
412*9681Slinton     if (p != nil) {
413*9681Slinton 	op = p->op;
414*9681Slinton 	if (ord(op) > ord(O_LASTOP)) {
415*9681Slinton 	    panic("bad op %d in prtree", p->op);
416*9681Slinton 	}
417*9681Slinton 	switch (op) {
418*9681Slinton 	    case O_NAME:
419*9681Slinton 		fprintf(f, "%s", ident(p->value.name));
420*9681Slinton 		break;
421*9681Slinton 
422*9681Slinton 	    case O_SYM:
423*9681Slinton 		printname(f, p->value.sym);
424*9681Slinton 		break;
425*9681Slinton 
426*9681Slinton 	    case O_QLINE:
427*9681Slinton 		if (nlhdr.nfiles > 1) {
428*9681Slinton 		    prtree(f, p->value.arg[0]);
429*9681Slinton 		    fprintf(f, ":");
430*9681Slinton 		}
431*9681Slinton 		prtree(f, p->value.arg[1]);
432*9681Slinton 		break;
433*9681Slinton 
434*9681Slinton 	    case O_LCON:
435*9681Slinton 		if (compatible(p->nodetype, t_char)) {
436*9681Slinton 		    fprintf(f, "'%c'", p->value.lcon);
437*9681Slinton 		} else {
438*9681Slinton 		    fprintf(f, "%d", p->value.lcon);
439*9681Slinton 		}
440*9681Slinton 		break;
441*9681Slinton 
442*9681Slinton 	    case O_FCON:
443*9681Slinton 		fprintf(f, "%g", p->value.fcon);
444*9681Slinton 		break;
445*9681Slinton 
446*9681Slinton 	    case O_SCON:
447*9681Slinton 		fprintf(f, "\"%s\"", p->value.scon);
448*9681Slinton 		break;
449*9681Slinton 
450*9681Slinton 	    case O_INDEX:
451*9681Slinton 		prtree(f, p->value.arg[0]);
452*9681Slinton 		fprintf(f, "[");
453*9681Slinton 		prtree(f, p->value.arg[1]);
454*9681Slinton 		fprintf(f, "]");
455*9681Slinton 		break;
456*9681Slinton 
457*9681Slinton 	    case O_COMMA:
458*9681Slinton 		prtree(f, p->value.arg[0]);
459*9681Slinton 		if (p->value.arg[1] != nil) {
460*9681Slinton 		    fprintf(f, ", ");
461*9681Slinton 		    prtree(f, p->value.arg[1]);
462*9681Slinton 		}
463*9681Slinton 		break;
464*9681Slinton 
465*9681Slinton 	    case O_RVAL:
466*9681Slinton 		if (p->value.arg[0]->op == O_SYM) {
467*9681Slinton 		    printname(f, p->value.arg[0]->value.sym);
468*9681Slinton 		} else {
469*9681Slinton 		    prtree(f, p->value.arg[0]);
470*9681Slinton 		}
471*9681Slinton 		break;
472*9681Slinton 
473*9681Slinton 	    case O_ITOF:
474*9681Slinton 		prtree(f, p->value.arg[0]);
475*9681Slinton 		break;
476*9681Slinton 
477*9681Slinton 	    case O_CALL:
478*9681Slinton 		prtree(f, p->value.arg[0]);
479*9681Slinton 		if (p->value.arg[1]!= nil) {
480*9681Slinton 		    fprintf(f, "(");
481*9681Slinton 		    prtree(f, p->value.arg[1]);
482*9681Slinton 		    fprintf(f, ")");
483*9681Slinton 		}
484*9681Slinton 		break;
485*9681Slinton 
486*9681Slinton 	    case O_INDIR:
487*9681Slinton 		q = p->value.arg[0];
488*9681Slinton 		if (isvarparam(q->nodetype)) {
489*9681Slinton 		    prtree(f, q);
490*9681Slinton 		} else {
491*9681Slinton 		    if (q->op == O_SYM or q->op == O_LCON or q->op == O_DOT) {
492*9681Slinton 			prtree(f, q);
493*9681Slinton 			fprintf(f, "^");
494*9681Slinton 		    } else {
495*9681Slinton 			fprintf(f, "*(");
496*9681Slinton 			prtree(f, q);
497*9681Slinton 			fprintf(f, ")");
498*9681Slinton 		    }
499*9681Slinton 		}
500*9681Slinton 		break;
501*9681Slinton 
502*9681Slinton 	    case O_DOT:
503*9681Slinton 		q = p->value.arg[0];
504*9681Slinton 		if (q->op == O_INDIR) {
505*9681Slinton 		    prtree(f, q->value.arg[0]);
506*9681Slinton 		} else {
507*9681Slinton 		    prtree(f, q);
508*9681Slinton 		}
509*9681Slinton 		fprintf(f, ".%s", symname(p->value.arg[1]->value.sym));
510*9681Slinton 		break;
511*9681Slinton 
512*9681Slinton 	    default:
513*9681Slinton 		switch (degree(op)) {
514*9681Slinton 		    case BINARY:
515*9681Slinton 			prtree(f, p->value.arg[0]);
516*9681Slinton 			fprintf(f, "%s", opinfo[ord(op)].opstring);
517*9681Slinton 			prtree(f, p->value.arg[1]);
518*9681Slinton 			break;
519*9681Slinton 
520*9681Slinton 		    case UNARY:
521*9681Slinton 			fprintf(f, "%s", opinfo[ord(op)].opstring);
522*9681Slinton 			prtree(f, p->value.arg[0]);
523*9681Slinton 			break;
524*9681Slinton 
525*9681Slinton 		    default:
526*9681Slinton 			error("internal error: bad op %d in prtree", op);
527*9681Slinton 		}
528*9681Slinton 		break;
529*9681Slinton 	}
530*9681Slinton     }
531*9681Slinton }
532*9681Slinton 
533*9681Slinton /*
534*9681Slinton  * Free storage associated with a tree.
535*9681Slinton  */
536*9681Slinton 
537*9681Slinton public tfree(p)
538*9681Slinton Node p;
539*9681Slinton {
540*9681Slinton     Integer i;
541*9681Slinton 
542*9681Slinton     if (p == nil) {
543*9681Slinton 	return;
544*9681Slinton     }
545*9681Slinton     switch (p->op) {
546*9681Slinton 	case O_QLINE:
547*9681Slinton 	    dispose(p->value.arg[0]->value.scon);
548*9681Slinton 	    dispose(p->value.arg[0]);
549*9681Slinton 	    tfree(p->value.arg[1]);
550*9681Slinton 	    break;
551*9681Slinton 
552*9681Slinton 	case O_SCON:
553*9681Slinton 	    unmkstring(p->nodetype);
554*9681Slinton 	    dispose(p->nodetype);
555*9681Slinton 	    dispose(p->value.scon);
556*9681Slinton 	    break;
557*9681Slinton 
558*9681Slinton 	default:
559*9681Slinton 	    for (i = 0; i < nargs(p->op); i++) {
560*9681Slinton 		tfree(p->value.arg[i]);
561*9681Slinton 	    }
562*9681Slinton 	    break;
563*9681Slinton     }
564*9681Slinton     dispose(p);
565*9681Slinton }
566*9681Slinton 
567*9681Slinton /*
568*9681Slinton  * A recursive tree search routine to test if two trees * are equivalent.
569*9681Slinton  */
570*9681Slinton 
571*9681Slinton public Boolean tr_equal(t1, t2)
572*9681Slinton register Node t1;
573*9681Slinton register Node t2;
574*9681Slinton {
575*9681Slinton     register Boolean b;
576*9681Slinton 
577*9681Slinton     if (t1 == nil and t2 == nil) {
578*9681Slinton 	b = true;
579*9681Slinton     } else if (t1 == nil or t2 == nil) {
580*9681Slinton 	b = false;
581*9681Slinton     } else if (t1->op != t2->op or degree(t1->op) != degree(t2->op)) {
582*9681Slinton 	b = false;
583*9681Slinton     } else {
584*9681Slinton 	switch (degree(t1->op)) {
585*9681Slinton 	    case LEAF:
586*9681Slinton 		switch (t1->op) {
587*9681Slinton 		    case O_NAME:
588*9681Slinton 			b = (Boolean) (t1->value.name == t2->value.name);
589*9681Slinton 			break;
590*9681Slinton 
591*9681Slinton 		    case O_SYM:
592*9681Slinton 			b = (Boolean) (t1->value.sym == t2->value.sym);
593*9681Slinton 			break;
594*9681Slinton 
595*9681Slinton 		    case O_LCON:
596*9681Slinton 			b = (Boolean) (t1->value.lcon == t2->value.lcon);
597*9681Slinton 			break;
598*9681Slinton 
599*9681Slinton 		    case O_FCON:
600*9681Slinton 			b = (Boolean) (t1->value.fcon == t2->value.fcon);
601*9681Slinton 			break;
602*9681Slinton 
603*9681Slinton 		    case O_SCON:
604*9681Slinton 			b = (Boolean) (t1->value.scon == t2->value.scon);
605*9681Slinton 			break;
606*9681Slinton 
607*9681Slinton 		    default:
608*9681Slinton 			panic("tr_equal: leaf %d\n", t1->op);
609*9681Slinton 		}
610*9681Slinton 		/*NOTREACHED*/
611*9681Slinton 
612*9681Slinton 	    case BINARY:
613*9681Slinton 		if (not tr_equal(t1->value.arg[0], t2->value.arg[0])) {
614*9681Slinton 		    b = false;
615*9681Slinton 		} else {
616*9681Slinton 		    b = tr_equal(t1->value.arg[1], t2->value.arg[1]);
617*9681Slinton 		}
618*9681Slinton 		break;
619*9681Slinton 
620*9681Slinton 	    case UNARY:
621*9681Slinton 		b = tr_equal(t1->value.arg[0], t2->value.arg[0]);
622*9681Slinton 		break;
623*9681Slinton 
624*9681Slinton 	    default:
625*9681Slinton 		panic("tr_equal: bad degree for op %d\n", t1->op);
626*9681Slinton 	}
627*9681Slinton     }
628*9681Slinton     return b;
629*9681Slinton }
630