xref: /csrg-svn/old/dbx/tree.c (revision 14446)
19681Slinton /* Copyright (c) 1982 Regents of the University of California */
29681Slinton 
3*14446Slinton static char sccsid[] = "@(#)tree.c 1.5 08/10/83";
49681Slinton 
59681Slinton /*
69681Slinton  * Parse tree management.
79681Slinton  */
89681Slinton 
99681Slinton #include "defs.h"
109681Slinton #include "tree.h"
119681Slinton #include "operators.h"
129681Slinton #include "eval.h"
139681Slinton #include "events.h"
149681Slinton #include "symbols.h"
159681Slinton #include "scanner.h"
169681Slinton #include "source.h"
179681Slinton #include "object.h"
189681Slinton #include "mappings.h"
199681Slinton #include "process.h"
209681Slinton #include "machine.h"
219681Slinton 
229681Slinton #ifndef public
239681Slinton #include "lists.h"
249681Slinton 
259681Slinton typedef struct Node *Node;
269681Slinton typedef Node Command;
279681Slinton typedef List Cmdlist;
289681Slinton 
299681Slinton #include "operators.h"
309681Slinton #include "symbols.h"
319681Slinton #include "events.h"
329681Slinton 
339681Slinton #define MAXNARGS 5
349681Slinton 
359681Slinton struct Node {
369681Slinton     Operator op;
379681Slinton     Symbol nodetype;
389681Slinton     union treevalue {
399681Slinton 	Symbol sym;
409681Slinton 	Name name;
419681Slinton 	long lcon;
429681Slinton 	double fcon;
439681Slinton 	String scon;
449681Slinton 	Node arg[MAXNARGS];
459681Slinton 	struct {
469681Slinton 	    Node cond;
479681Slinton 	    Cmdlist actions;
489681Slinton 	} event;
499681Slinton 	struct {
509681Slinton 	    Boolean inst;
519681Slinton 	    Event event;
529681Slinton 	    Cmdlist actions;
539681Slinton 	} trace;
549681Slinton 	struct {
559681Slinton 	    Boolean source;
569681Slinton 	    Boolean skipcalls;
579681Slinton 	} step;
589681Slinton 	struct {
599681Slinton 	    String mode;
609681Slinton 	    Node beginaddr;
619681Slinton 	    Node endaddr;
629681Slinton 	    Integer count;
639681Slinton 	} examine;
649681Slinton     } value;
659681Slinton };
669681Slinton 
679681Slinton #define evalcmd(cmd) eval(cmd)
689681Slinton #define cmdlist_append(cmd, cl) list_append(list_item(cmd), nil, cl)
699681Slinton 
709681Slinton #endif
719681Slinton 
729681Slinton typedef char *Arglist;
739681Slinton 
749681Slinton #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
759681Slinton 
769681Slinton /*
779681Slinton  * Build a tree.
789681Slinton  */
799681Slinton 
809681Slinton /* VARARGS1 */
819681Slinton public Node build(op, args)
829681Slinton Operator op;
839681Slinton {
849681Slinton     register Node p, q;
859681Slinton     register Arglist ap;
869681Slinton     Integer i;
879681Slinton 
889681Slinton     p = new(Node);
899681Slinton     p->op = op;
909681Slinton     p->nodetype = nil;
919681Slinton     ap = (Arglist) &args;
929681Slinton     switch (op) {
939681Slinton 	case O_NAME:
949681Slinton 	    p->value.name = nextarg(Name);
959681Slinton 	    break;
969681Slinton 
979681Slinton 	case O_SYM:
989681Slinton 	case O_PRINTCALL:
999681Slinton 	case O_PRINTRTN:
1009681Slinton 	case O_PROCRTN:
1019681Slinton 	    p->value.sym = nextarg(Symbol);
1029681Slinton 	    break;
1039681Slinton 
10412548Scsvaf 	case O_DEBUG:
1059681Slinton 	case O_LCON:
10611862Slinton 	case O_CONT:
1079681Slinton 	case O_DELETE:
1089681Slinton 	case O_CATCH:
1099681Slinton 	case O_IGNORE:
1109681Slinton 	case O_TRACEOFF:
1119681Slinton 	    p->value.lcon = nextarg(long);
1129681Slinton 	    break;
1139681Slinton 
1149681Slinton 	case O_FCON:
1159681Slinton 	    p->value.fcon = nextarg(double);
1169681Slinton 	    break;
1179681Slinton 
1189681Slinton 	case O_SCON:
1199681Slinton 	case O_CHFILE:
1209681Slinton 	case O_EDIT:
1219681Slinton 	case O_SOURCE:
1229681Slinton 	    p->value.scon = nextarg(String);
1239681Slinton 	    break;
1249681Slinton 
1259681Slinton 	case O_RVAL:
1269681Slinton 	    q = nextarg(Node);
1279681Slinton 	    if (q->op == O_CALL) {
1289681Slinton 		*p = *q;
1299681Slinton 		dispose(q);
1309681Slinton 	    } else {
1319681Slinton 		p->value.arg[0] = q;
1329681Slinton 	    }
1339681Slinton 	    break;
1349681Slinton 
1359681Slinton 	case O_INDIR:
1369681Slinton 	    q = nextarg(Node);
1379681Slinton 	    if (q != nil and q->op == O_RVAL) {
1389681Slinton 		p->value.arg[0] = q->value.arg[0];
1399681Slinton 		dispose(q);
1409681Slinton 	    } else {
1419681Slinton 		p->value.arg[0] = q;
1429681Slinton 	    }
1439681Slinton 	    break;
1449681Slinton 
1459681Slinton 	case O_ADDEVENT:
1469681Slinton 	case O_ONCE:
1479681Slinton 	case O_IF:
1489681Slinton 	    p->value.event.cond = nextarg(Node);
1499681Slinton 	    p->value.event.actions = nextarg(Cmdlist);
1509681Slinton 	    break;
1519681Slinton 
1529681Slinton 	case O_TRACEON:
1539681Slinton 	    p->value.trace.inst = nextarg(Boolean);
1549681Slinton 	    p->value.trace.event = nil;
1559681Slinton 	    p->value.trace.actions = nextarg(Cmdlist);
1569681Slinton 	    break;
1579681Slinton 
1589681Slinton 	case O_STEP:
1599681Slinton 	    p->value.step.source = nextarg(Boolean);
1609681Slinton 	    p->value.step.skipcalls = nextarg(Boolean);
1619681Slinton 	    break;
1629681Slinton 
1639681Slinton 	case O_EXAMINE:
1649681Slinton 	    p->value.examine.mode = nextarg(String);
1659681Slinton 	    p->value.examine.beginaddr = nextarg(Node);
1669681Slinton 	    p->value.examine.endaddr = nextarg(Node);
1679681Slinton 	    p->value.examine.count = nextarg(Integer);
1689681Slinton 	    break;
1699681Slinton 
1709681Slinton 	default:
1719681Slinton 	    for (i = 0; i < nargs(op); i++) {
1729681Slinton 		p->value.arg[i] = nextarg(Node);
1739681Slinton 	    }
1749681Slinton 	    break;
1759681Slinton     }
1769681Slinton     check(p);
1779681Slinton     assigntypes(p);
17812548Scsvaf     if(debug_flag[5]) {
17912548Scsvaf   	fprintf(stderr," built %s node %d with arg0 %d arg1 %d \n",
18012548Scsvaf   	        showoperator(p->op), p, p->value.arg[0],p->value.arg[1]);
18112548Scsvaf     }
1829681Slinton     return p;
1839681Slinton }
1849681Slinton 
1859681Slinton /*
1869681Slinton  * Create a command list from a single command.
1879681Slinton  */
1889681Slinton 
1899681Slinton public Cmdlist buildcmdlist(cmd)
1909681Slinton Command cmd;
1919681Slinton {
1929681Slinton     Cmdlist cmdlist;
1939681Slinton 
1949681Slinton     cmdlist = list_alloc();
1959681Slinton     cmdlist_append(cmd, cmdlist);
1969681Slinton     return cmdlist;
1979681Slinton }
1989681Slinton 
1999681Slinton /*
2009681Slinton  * Return the tree for a unary ampersand operator.
2019681Slinton  */
2029681Slinton 
2039681Slinton public Node amper(p)
2049681Slinton Node p;
2059681Slinton {
2069681Slinton     Node r;
2079681Slinton 
2089681Slinton     checkref(p);
2099681Slinton     switch (p->op) {
2109681Slinton 	case O_RVAL:
2119681Slinton 	    r = p->value.arg[0];
2129681Slinton 	    break;
2139681Slinton 
2149681Slinton 	case O_CALL:
2159681Slinton 	    r = build(O_LCON, codeloc(p->value.arg[0]->value.sym));
2169681Slinton 	    tfree(p);
2179681Slinton 	    break;
2189681Slinton 
2199681Slinton 	case O_SYM:
2209681Slinton 	    if (isblock(p->value.sym)) {
2219681Slinton 		r = build(O_LCON, codeloc(p->value.sym));
2229681Slinton 	    } else {
2239681Slinton 		r = build(O_LCON, address(p->value.sym, nil));
2249681Slinton 	    }
2259681Slinton 	    tfree(p);
2269681Slinton 	    break;
2279681Slinton 
2289681Slinton 	case O_DOT:
2299681Slinton 	    r = p;
2309681Slinton 	    break;
2319681Slinton 
2329681Slinton 	case O_INDIR:
2339681Slinton 	    r = p->value.arg[0];
2349681Slinton 	    dispose(p);
2359681Slinton 	    break;
2369681Slinton 
2379681Slinton 	default:
2389681Slinton 	    beginerrmsg();
2399681Slinton 	    fprintf(stderr, "expected variable, found ");
2409681Slinton 	    prtree(stderr, p);
2419681Slinton 	    tfree(p);
2429681Slinton 	    enderrmsg();
2439681Slinton 	    /* NOTREACHED */
2449681Slinton     }
2459681Slinton     r->nodetype = t_int;
2469681Slinton     return r;
2479681Slinton }
2489681Slinton 
2499681Slinton /*
2509681Slinton  * Create a "concrete" version of a node.
2519681Slinton  * This is necessary when the type of the node contains
2529681Slinton  * an unresolved type reference.
2539681Slinton  */
2549681Slinton 
2559681Slinton public Node concrete(p)
2569681Slinton Node p;
2579681Slinton {
2589681Slinton     findtype(p->nodetype);
2599681Slinton     return build(O_INDIR, p);
2609681Slinton }
2619681Slinton 
2629681Slinton /*
2639681Slinton  * Print out a command.
2649681Slinton  */
2659681Slinton 
2669681Slinton public printcmd(f, cmd)
2679681Slinton File f;
2689681Slinton Command cmd;
2699681Slinton {
2709681Slinton     register Integer i;
2719681Slinton     register Command c;
2729681Slinton     register Node p;
2739681Slinton 
2749681Slinton     switch (cmd->op) {
2759681Slinton 	case O_PRINTIFCHANGED:
2769681Slinton 	case O_PRINTSRCPOS:
2779681Slinton 	case O_STOPIFCHANGED:
2789681Slinton 	case O_TRACEON:
2799681Slinton 	    break;
2809681Slinton 
2819681Slinton 	case O_STEP:
2829681Slinton 	    if (cmd->value.step.skipcalls) {
2839681Slinton 		fprintf(f, "next");
2849681Slinton 	    } else {
2859681Slinton 		fprintf(f, "step");
2869681Slinton 	    }
2879681Slinton 	    if (not cmd->value.step.source) {
2889681Slinton 		fprintf(f, "i");
2899681Slinton 	    }
2909681Slinton 	    break;
2919681Slinton 
2929681Slinton 	default:
2939681Slinton 	    fprintf(f, "%s", opinfo[ord(cmd->op)].opstring);
2949681Slinton 	    if (nargs(cmd->op) != 0) {
2959681Slinton 		fprintf(f, " ");
2969681Slinton 	    }
2979681Slinton 	    break;
2989681Slinton     }
2999681Slinton     switch (cmd->op) {
3009681Slinton 	case O_PRINTCALL:
3019681Slinton 	case O_PRINTRTN:
3029681Slinton 	case O_PROCRTN:
3039681Slinton 	    fprintf(f, "%s", symname(cmd->value.sym));
3049681Slinton 	    break;
3059681Slinton 
3069681Slinton 	case O_PRINTSRCPOS:
3079681Slinton 	    p = cmd->value.arg[0];
3089681Slinton 	    if (p != nil and p->op != O_QLINE) {
3099681Slinton 		printf("trace ");
3109681Slinton 		prtree(f, p);
3119681Slinton 	    }
3129681Slinton 	    break;
3139681Slinton 
3149681Slinton 	case O_CHFILE:
3159681Slinton 	case O_EDIT:
3169681Slinton 	case O_SOURCE:
3179681Slinton 	    fprintf(f, "%s", cmd->value.scon);
3189681Slinton 	    break;
3199681Slinton 
3209681Slinton 	case O_DELETE:
3219681Slinton 	case O_CATCH:
3229681Slinton 	case O_IGNORE:
3239681Slinton 	case O_TRACEOFF:
3249681Slinton 	    fprintf(f, "%d", cmd->value.lcon);
3259681Slinton 	    break;
3269681Slinton 
3279681Slinton 	case O_ADDEVENT:
3289681Slinton 	case O_ONCE:
3299681Slinton 	case O_IF:
3309681Slinton 	    fprintf(f, " ");
3319681Slinton 	    prtree(f, cmd->value.event.cond);
3329681Slinton 	    fprintf(f, " { ");
3339681Slinton 	    foreach (Command, c, cmd->value.event.actions)
3349681Slinton 		printcmd(f, c);
3359681Slinton 		if (not list_islast()) {
3369681Slinton 		    fprintf(f, ";");
3379681Slinton 		}
3389681Slinton 	    endfor
3399681Slinton 	    fprintf(f, " }", opinfo[ord(cmd->op)].opstring);
3409681Slinton 	    break;
3419681Slinton 
3429681Slinton 	case O_TRACEON:
3439681Slinton 	    print_tracestop(f, cmd);
3449681Slinton 	    break;
3459681Slinton 
3469681Slinton 	case O_EXAMINE:
3479681Slinton 	    prtree(f, cmd->value.examine.beginaddr);
3489681Slinton 	    if (cmd->value.examine.endaddr != nil) {
3499681Slinton 		fprintf(f, ",");
3509681Slinton 		prtree(f, cmd->value.examine.endaddr);
3519681Slinton 	    }
3529681Slinton 	    fprintf(f, "/");
3539681Slinton 	    if (cmd->value.examine.count > 1) {
3549681Slinton 		fprintf(f, "%d", cmd->value.examine.count);
3559681Slinton 	    }
3569681Slinton 	    fprintf("%s", cmd->value.examine.mode);
3579681Slinton 	    break;
3589681Slinton 
3599681Slinton 	default:
3609681Slinton 	    if (nargs(cmd->op) != 0) {
3619681Slinton 		i = 0;
3629681Slinton 		for (;;) {
3639681Slinton 		    prtree(f, cmd->value.arg[i]);
3649681Slinton 		    ++i;
3659681Slinton 		if (i >= nargs(cmd->op)) break;
3669681Slinton 		    fprintf(f, " ");
3679681Slinton 		}
3689681Slinton 	    }
3699681Slinton 	    break;
3709681Slinton     }
3719681Slinton }
3729681Slinton 
3739681Slinton /*
3749681Slinton  * Print out a trace/stop command name.
3759681Slinton  */
3769681Slinton 
377*14446Slinton #define fprintI(f, b) { if (b) fprintf(f, "i"); }
378*14446Slinton 
3799681Slinton private print_tracestop(f, cmd)
3809681Slinton File f;
3819681Slinton Command cmd;
3829681Slinton {
3839681Slinton     register Command c, ifcmd, stopcmd;
3849681Slinton     Boolean done;
3859681Slinton 
3869681Slinton     done = false;
3879681Slinton     ifcmd = list_element(Command, list_head(cmd->value.trace.actions));
3889681Slinton     checkref(ifcmd);
3899681Slinton     if (ifcmd->op == O_IF) {
3909681Slinton 	stopcmd = list_element(Command, list_head(ifcmd->value.event.actions));
3919681Slinton 	checkref(stopcmd);
3929681Slinton 	if (stopcmd->op == O_STOPX) {
393*14446Slinton 	    fprintf(f, "stop");
394*14446Slinton 	    fprintI(f, cmd->value.trace.inst);
395*14446Slinton 	    fprintf(f, " if ");
3969681Slinton 	    prtree(f, ifcmd->value.event.cond);
3979681Slinton 	    done = true;
3989681Slinton 	}
399*14446Slinton     } else if (ifcmd->op == O_STOPIFCHANGED) {
400*14446Slinton 	fprintf(f, "stop");
401*14446Slinton 	fprintI(f, cmd->value.trace.inst);
402*14446Slinton 	fprintf(f, " ");
403*14446Slinton 	prtree(f, ifcmd->value.arg[0]);
404*14446Slinton 	done = true;
4059681Slinton     }
4069681Slinton     if (not done) {
4079681Slinton 	fprintf(f, "%s ", cmd->value.trace.inst ? "tracei" : "trace");
4089681Slinton 	foreach (Command, c, cmd->value.trace.actions)
4099681Slinton 	    printcmd(f, c);
4109681Slinton 	    if (not list_islast()) {
4119681Slinton 		fprintf(f, ";");
4129681Slinton 	    }
4139681Slinton 	endfor
4149681Slinton     }
4159681Slinton }
4169681Slinton 
4179681Slinton /*
418*14446Slinton  * Print out a tree.
4199681Slinton  */
4209681Slinton 
4219681Slinton public prtree(f, p)
4229681Slinton File f;
4239681Slinton register Node p;
4249681Slinton {
4259681Slinton     register Node q;
4269681Slinton     Operator op;
4279681Slinton 
4289681Slinton     if (p != nil) {
4299681Slinton 	op = p->op;
4309681Slinton 	if (ord(op) > ord(O_LASTOP)) {
4319681Slinton 	    panic("bad op %d in prtree", p->op);
4329681Slinton 	}
4339681Slinton 	switch (op) {
4349681Slinton 	    case O_NAME:
4359681Slinton 		fprintf(f, "%s", ident(p->value.name));
4369681Slinton 		break;
4379681Slinton 
4389681Slinton 	    case O_SYM:
4399681Slinton 		printname(f, p->value.sym);
4409681Slinton 		break;
4419681Slinton 
4429681Slinton 	    case O_QLINE:
4439681Slinton 		if (nlhdr.nfiles > 1) {
4449681Slinton 		    prtree(f, p->value.arg[0]);
4459681Slinton 		    fprintf(f, ":");
4469681Slinton 		}
4479681Slinton 		prtree(f, p->value.arg[1]);
4489681Slinton 		break;
4499681Slinton 
4509681Slinton 	    case O_LCON:
4519681Slinton 		if (compatible(p->nodetype, t_char)) {
4529681Slinton 		    fprintf(f, "'%c'", p->value.lcon);
4539681Slinton 		} else {
4549681Slinton 		    fprintf(f, "%d", p->value.lcon);
4559681Slinton 		}
4569681Slinton 		break;
4579681Slinton 
4589681Slinton 	    case O_FCON:
4599681Slinton 		fprintf(f, "%g", p->value.fcon);
4609681Slinton 		break;
4619681Slinton 
4629681Slinton 	    case O_SCON:
4639681Slinton 		fprintf(f, "\"%s\"", p->value.scon);
4649681Slinton 		break;
4659681Slinton 
4669681Slinton 	    case O_INDEX:
4679681Slinton 		prtree(f, p->value.arg[0]);
4689681Slinton 		fprintf(f, "[");
4699681Slinton 		prtree(f, p->value.arg[1]);
4709681Slinton 		fprintf(f, "]");
4719681Slinton 		break;
4729681Slinton 
4739681Slinton 	    case O_COMMA:
4749681Slinton 		prtree(f, p->value.arg[0]);
4759681Slinton 		if (p->value.arg[1] != nil) {
4769681Slinton 		    fprintf(f, ", ");
4779681Slinton 		    prtree(f, p->value.arg[1]);
4789681Slinton 		}
4799681Slinton 		break;
4809681Slinton 
4819681Slinton 	    case O_RVAL:
4829681Slinton 		if (p->value.arg[0]->op == O_SYM) {
4839681Slinton 		    printname(f, p->value.arg[0]->value.sym);
4849681Slinton 		} else {
4859681Slinton 		    prtree(f, p->value.arg[0]);
4869681Slinton 		}
4879681Slinton 		break;
4889681Slinton 
4899681Slinton 	    case O_ITOF:
4909681Slinton 		prtree(f, p->value.arg[0]);
4919681Slinton 		break;
4929681Slinton 
4939681Slinton 	    case O_CALL:
4949681Slinton 		prtree(f, p->value.arg[0]);
4959681Slinton 		if (p->value.arg[1]!= nil) {
4969681Slinton 		    fprintf(f, "(");
4979681Slinton 		    prtree(f, p->value.arg[1]);
4989681Slinton 		    fprintf(f, ")");
4999681Slinton 		}
5009681Slinton 		break;
5019681Slinton 
5029681Slinton 	    case O_INDIR:
5039681Slinton 		q = p->value.arg[0];
5049681Slinton 		if (isvarparam(q->nodetype)) {
5059681Slinton 		    prtree(f, q);
5069681Slinton 		} else {
5079681Slinton 		    if (q->op == O_SYM or q->op == O_LCON or q->op == O_DOT) {
5089681Slinton 			prtree(f, q);
5099681Slinton 			fprintf(f, "^");
5109681Slinton 		    } else {
5119681Slinton 			fprintf(f, "*(");
5129681Slinton 			prtree(f, q);
5139681Slinton 			fprintf(f, ")");
5149681Slinton 		    }
5159681Slinton 		}
5169681Slinton 		break;
5179681Slinton 
5189681Slinton 	    case O_DOT:
5199681Slinton 		q = p->value.arg[0];
5209681Slinton 		if (q->op == O_INDIR) {
5219681Slinton 		    prtree(f, q->value.arg[0]);
5229681Slinton 		} else {
5239681Slinton 		    prtree(f, q);
5249681Slinton 		}
5259681Slinton 		fprintf(f, ".%s", symname(p->value.arg[1]->value.sym));
5269681Slinton 		break;
5279681Slinton 
5289681Slinton 	    default:
5299681Slinton 		switch (degree(op)) {
5309681Slinton 		    case BINARY:
5319681Slinton 			prtree(f, p->value.arg[0]);
5329681Slinton 			fprintf(f, "%s", opinfo[ord(op)].opstring);
5339681Slinton 			prtree(f, p->value.arg[1]);
5349681Slinton 			break;
5359681Slinton 
5369681Slinton 		    case UNARY:
5379681Slinton 			fprintf(f, "%s", opinfo[ord(op)].opstring);
5389681Slinton 			prtree(f, p->value.arg[0]);
5399681Slinton 			break;
5409681Slinton 
5419681Slinton 		    default:
5429681Slinton 			error("internal error: bad op %d in prtree", op);
5439681Slinton 		}
5449681Slinton 		break;
5459681Slinton 	}
5469681Slinton     }
5479681Slinton }
5489681Slinton 
5499681Slinton /*
5509681Slinton  * Free storage associated with a tree.
5519681Slinton  */
5529681Slinton 
5539681Slinton public tfree(p)
5549681Slinton Node p;
5559681Slinton {
5569681Slinton     Integer i;
5579681Slinton 
5589681Slinton     if (p == nil) {
5599681Slinton 	return;
5609681Slinton     }
5619681Slinton     switch (p->op) {
5629681Slinton 	case O_QLINE:
5639681Slinton 	    dispose(p->value.arg[0]->value.scon);
5649681Slinton 	    dispose(p->value.arg[0]);
5659681Slinton 	    tfree(p->value.arg[1]);
5669681Slinton 	    break;
5679681Slinton 
5689681Slinton 	case O_SCON:
5699681Slinton 	    unmkstring(p->nodetype);
5709681Slinton 	    dispose(p->nodetype);
5719681Slinton 	    dispose(p->value.scon);
5729681Slinton 	    break;
5739681Slinton 
5749681Slinton 	default:
5759681Slinton 	    for (i = 0; i < nargs(p->op); i++) {
5769681Slinton 		tfree(p->value.arg[i]);
5779681Slinton 	    }
5789681Slinton 	    break;
5799681Slinton     }
5809681Slinton     dispose(p);
5819681Slinton }
5829681Slinton 
5839681Slinton /*
5849681Slinton  * A recursive tree search routine to test if two trees * are equivalent.
5859681Slinton  */
5869681Slinton 
5879681Slinton public Boolean tr_equal(t1, t2)
5889681Slinton register Node t1;
5899681Slinton register Node t2;
5909681Slinton {
5919681Slinton     register Boolean b;
5929681Slinton 
5939681Slinton     if (t1 == nil and t2 == nil) {
5949681Slinton 	b = true;
5959681Slinton     } else if (t1 == nil or t2 == nil) {
5969681Slinton 	b = false;
5979681Slinton     } else if (t1->op != t2->op or degree(t1->op) != degree(t2->op)) {
5989681Slinton 	b = false;
5999681Slinton     } else {
6009681Slinton 	switch (degree(t1->op)) {
6019681Slinton 	    case LEAF:
6029681Slinton 		switch (t1->op) {
6039681Slinton 		    case O_NAME:
6049681Slinton 			b = (Boolean) (t1->value.name == t2->value.name);
6059681Slinton 			break;
6069681Slinton 
6079681Slinton 		    case O_SYM:
6089681Slinton 			b = (Boolean) (t1->value.sym == t2->value.sym);
6099681Slinton 			break;
6109681Slinton 
6119681Slinton 		    case O_LCON:
6129681Slinton 			b = (Boolean) (t1->value.lcon == t2->value.lcon);
6139681Slinton 			break;
6149681Slinton 
6159681Slinton 		    case O_FCON:
6169681Slinton 			b = (Boolean) (t1->value.fcon == t2->value.fcon);
6179681Slinton 			break;
6189681Slinton 
6199681Slinton 		    case O_SCON:
6209681Slinton 			b = (Boolean) (t1->value.scon == t2->value.scon);
6219681Slinton 			break;
6229681Slinton 
6239681Slinton 		    default:
6249681Slinton 			panic("tr_equal: leaf %d\n", t1->op);
6259681Slinton 		}
6269681Slinton 		/*NOTREACHED*/
6279681Slinton 
6289681Slinton 	    case BINARY:
6299681Slinton 		if (not tr_equal(t1->value.arg[0], t2->value.arg[0])) {
6309681Slinton 		    b = false;
6319681Slinton 		} else {
6329681Slinton 		    b = tr_equal(t1->value.arg[1], t2->value.arg[1]);
6339681Slinton 		}
6349681Slinton 		break;
6359681Slinton 
6369681Slinton 	    case UNARY:
6379681Slinton 		b = tr_equal(t1->value.arg[0], t2->value.arg[0]);
6389681Slinton 		break;
6399681Slinton 
6409681Slinton 	    default:
6419681Slinton 		panic("tr_equal: bad degree for op %d\n", t1->op);
6429681Slinton 	}
6439681Slinton     }
6449681Slinton     return b;
6459681Slinton }
646