xref: /csrg-svn/old/dbx/tree.c (revision 18236)
19681Slinton /* Copyright (c) 1982 Regents of the University of California */
29681Slinton 
3*18236Slinton static	char sccsid[] = "@(#)tree.c	1.8 (Berkeley) 03/01/85";
49681Slinton 
5*18236Slinton static char rcsid[] = "$Header: tree.c,v 1.5 84/12/26 10:42:55 linton Exp $";
6*18236Slinton 
79681Slinton /*
89681Slinton  * Parse tree management.
99681Slinton  */
109681Slinton 
119681Slinton #include "defs.h"
129681Slinton #include "tree.h"
139681Slinton #include "operators.h"
14*18236Slinton #include "debug.h"
159681Slinton #include "eval.h"
169681Slinton #include "events.h"
179681Slinton #include "symbols.h"
189681Slinton #include "scanner.h"
199681Slinton #include "source.h"
209681Slinton #include "object.h"
219681Slinton #include "mappings.h"
229681Slinton #include "process.h"
239681Slinton #include "machine.h"
249681Slinton 
259681Slinton #ifndef public
269681Slinton #include "lists.h"
279681Slinton 
289681Slinton typedef struct Node *Node;
299681Slinton typedef Node Command;
309681Slinton typedef List Cmdlist;
319681Slinton 
329681Slinton #include "operators.h"
339681Slinton #include "symbols.h"
349681Slinton #include "events.h"
359681Slinton 
369681Slinton #define MAXNARGS 5
379681Slinton 
389681Slinton struct Node {
399681Slinton     Operator op;
409681Slinton     Symbol nodetype;
419681Slinton     union treevalue {
429681Slinton 	Symbol sym;
439681Slinton 	Name name;
449681Slinton 	long lcon;
459681Slinton 	double fcon;
469681Slinton 	String scon;
479681Slinton 	Node arg[MAXNARGS];
489681Slinton 	struct {
499681Slinton 	    Node cond;
509681Slinton 	    Cmdlist actions;
519681Slinton 	} event;
529681Slinton 	struct {
539681Slinton 	    Boolean inst;
549681Slinton 	    Event event;
559681Slinton 	    Cmdlist actions;
569681Slinton 	} trace;
579681Slinton 	struct {
589681Slinton 	    Boolean source;
599681Slinton 	    Boolean skipcalls;
609681Slinton 	} step;
619681Slinton 	struct {
629681Slinton 	    String mode;
639681Slinton 	    Node beginaddr;
649681Slinton 	    Node endaddr;
659681Slinton 	    Integer count;
669681Slinton 	} examine;
679681Slinton     } value;
689681Slinton };
699681Slinton 
709681Slinton #define evalcmd(cmd) eval(cmd)
719681Slinton #define cmdlist_append(cmd, cl) list_append(list_item(cmd), nil, cl)
729681Slinton 
739681Slinton #endif
749681Slinton 
759681Slinton typedef char *Arglist;
769681Slinton 
779681Slinton #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
789681Slinton 
799681Slinton /*
809681Slinton  * Build a tree.
819681Slinton  */
829681Slinton 
839681Slinton /* VARARGS1 */
849681Slinton public Node build(op, args)
859681Slinton Operator op;
869681Slinton {
879681Slinton     register Node p, q;
889681Slinton     register Arglist ap;
899681Slinton     Integer i;
909681Slinton 
919681Slinton     p = new(Node);
929681Slinton     p->op = op;
939681Slinton     p->nodetype = nil;
949681Slinton     ap = (Arglist) &args;
959681Slinton     switch (op) {
969681Slinton 	case O_NAME:
979681Slinton 	    p->value.name = nextarg(Name);
989681Slinton 	    break;
999681Slinton 
1009681Slinton 	case O_SYM:
1019681Slinton 	case O_PRINTCALL:
1029681Slinton 	case O_PRINTRTN:
1039681Slinton 	case O_PROCRTN:
1049681Slinton 	    p->value.sym = nextarg(Symbol);
1059681Slinton 	    break;
1069681Slinton 
10712548Scsvaf 	case O_DEBUG:
1089681Slinton 	case O_LCON:
109*18236Slinton 	case O_CCON:
11011862Slinton 	case O_CONT:
111*18236Slinton 	case O_CATCH:
112*18236Slinton 	case O_IGNORE:
1139681Slinton 	case O_TRACEOFF:
1149681Slinton 	    p->value.lcon = nextarg(long);
1159681Slinton 	    break;
1169681Slinton 
1179681Slinton 	case O_FCON:
1189681Slinton 	    p->value.fcon = nextarg(double);
1199681Slinton 	    break;
1209681Slinton 
1219681Slinton 	case O_SCON:
1229681Slinton 	case O_CHFILE:
1239681Slinton 	case O_EDIT:
1249681Slinton 	case O_SOURCE:
1259681Slinton 	    p->value.scon = nextarg(String);
1269681Slinton 	    break;
1279681Slinton 
1289681Slinton 	case O_RVAL:
129*18236Slinton 	case O_INDIR:
130*18236Slinton 	    p->value.arg[0] = nextarg(Node);
1319681Slinton 	    break;
1329681Slinton 
133*18236Slinton 	case O_CALL:
1349681Slinton 	    q = nextarg(Node);
135*18236Slinton 	    if (q->op == O_SYM and
136*18236Slinton 		(q->value.sym->class == TYPE or q->value.sym->class == TAG)
137*18236Slinton 	    ) {
138*18236Slinton 		p->op = O_TYPERENAME;
139*18236Slinton 		p->value.arg[0] = nextarg(Node);
140*18236Slinton 		p->value.arg[1] = q;
141*18236Slinton 		q = p->value.arg[0];
142*18236Slinton 		if (q->value.arg[1] != nil) {
143*18236Slinton 		    error("too many arguments to type rename");
144*18236Slinton 		}
1459681Slinton 		p->value.arg[0] = q->value.arg[0];
1469681Slinton 	    } else {
1479681Slinton 		p->value.arg[0] = q;
148*18236Slinton 		p->value.arg[1] = nextarg(Node);
1499681Slinton 	    }
1509681Slinton 	    break;
1519681Slinton 
1529681Slinton 	case O_ADDEVENT:
1539681Slinton 	case O_ONCE:
1549681Slinton 	case O_IF:
1559681Slinton 	    p->value.event.cond = nextarg(Node);
1569681Slinton 	    p->value.event.actions = nextarg(Cmdlist);
1579681Slinton 	    break;
1589681Slinton 
1599681Slinton 	case O_TRACEON:
1609681Slinton 	    p->value.trace.inst = nextarg(Boolean);
1619681Slinton 	    p->value.trace.event = nil;
1629681Slinton 	    p->value.trace.actions = nextarg(Cmdlist);
1639681Slinton 	    break;
1649681Slinton 
1659681Slinton 	case O_STEP:
1669681Slinton 	    p->value.step.source = nextarg(Boolean);
1679681Slinton 	    p->value.step.skipcalls = nextarg(Boolean);
1689681Slinton 	    break;
1699681Slinton 
1709681Slinton 	case O_EXAMINE:
1719681Slinton 	    p->value.examine.mode = nextarg(String);
1729681Slinton 	    p->value.examine.beginaddr = nextarg(Node);
1739681Slinton 	    p->value.examine.endaddr = nextarg(Node);
1749681Slinton 	    p->value.examine.count = nextarg(Integer);
1759681Slinton 	    break;
1769681Slinton 
1779681Slinton 	default:
1789681Slinton 	    for (i = 0; i < nargs(op); i++) {
1799681Slinton 		p->value.arg[i] = nextarg(Node);
1809681Slinton 	    }
1819681Slinton 	    break;
1829681Slinton     }
1839681Slinton     check(p);
1849681Slinton     assigntypes(p);
185*18236Slinton     if (tracetree) {
186*18236Slinton 	printf("built %s node 0x%x with arg[0] 0x%x arg[1] 0x%x\n",
187*18236Slinton 	    opname(p->op), p, p->value.arg[0], p->value.arg[1]);
188*18236Slinton 	fflush(stdout);
18912548Scsvaf     }
1909681Slinton     return p;
1919681Slinton }
1929681Slinton 
1939681Slinton /*
194*18236Slinton  * Strip away indirection from a node, thus returning a node for
195*18236Slinton  * interpreting the expression as an lvalue.
1969681Slinton  */
1979681Slinton 
198*18236Slinton public Node unrval (exp)
199*18236Slinton Node exp;
2009681Slinton {
201*18236Slinton     Node p;
202*18236Slinton     Symbol t;
2039681Slinton 
204*18236Slinton     if (exp->op == O_RVAL) {
205*18236Slinton 	p = exp->value.arg[0];
206*18236Slinton 	dispose(exp);
207*18236Slinton     } else if (exp->op == O_INDIR) {
208*18236Slinton 	p = exp->value.arg[0];
209*18236Slinton 	if (p->op == O_RVAL) {
210*18236Slinton 	    p->op = O_INDIR;
211*18236Slinton 	    p->nodetype = exp->nodetype;
212*18236Slinton 	}
213*18236Slinton 	dispose(exp);
214*18236Slinton     } else {
215*18236Slinton 	p = exp;
216*18236Slinton     }
217*18236Slinton     return p;
2189681Slinton }
2199681Slinton 
2209681Slinton /*
221*18236Slinton  * Create a node for renaming a node to a pointer type.
222*18236Slinton  */
223*18236Slinton 
224*18236Slinton public Node renameptr (p, t)
225*18236Slinton Node p;
226*18236Slinton Node t;
227*18236Slinton {
228*18236Slinton     t->nodetype = newSymbol(nil, 0, PTR, t->nodetype, nil);
229*18236Slinton     p = build(O_TYPERENAME, p, t);
230*18236Slinton }
231*18236Slinton 
232*18236Slinton /*
2339681Slinton  * Return the tree for a unary ampersand operator.
2349681Slinton  */
2359681Slinton 
2369681Slinton public Node amper(p)
2379681Slinton Node p;
2389681Slinton {
2399681Slinton     Node r;
2409681Slinton 
2419681Slinton     checkref(p);
2429681Slinton     switch (p->op) {
2439681Slinton 	case O_RVAL:
244*18236Slinton 	case O_INDIR:
2459681Slinton 	    r = p->value.arg[0];
246*18236Slinton 	    r->nodetype = t_addr;
247*18236Slinton 	    dispose(p);
2489681Slinton 	    break;
2499681Slinton 
250*18236Slinton 	case O_TYPERENAME:
251*18236Slinton 	    r = p;
252*18236Slinton 	    r->nodetype = newSymbol(nil, 0, PTR, r->nodetype, nil);
2539681Slinton 	    break;
2549681Slinton 
2559681Slinton 	case O_SYM:
2569681Slinton 	    if (isblock(p->value.sym)) {
2579681Slinton 		r = build(O_LCON, codeloc(p->value.sym));
2589681Slinton 	    } else {
2599681Slinton 		r = build(O_LCON, address(p->value.sym, nil));
2609681Slinton 	    }
261*18236Slinton 	    r->nodetype = t_addr;
262*18236Slinton 	    dispose(p);
2639681Slinton 	    break;
2649681Slinton 
2659681Slinton 	case O_DOT:
2669681Slinton 	    r = p;
267*18236Slinton 	    r->nodetype = t_addr;
2689681Slinton 	    break;
2699681Slinton 
2709681Slinton 	default:
2719681Slinton 	    beginerrmsg();
272*18236Slinton 	    fprintf(stderr, "expected variable, found \"");
2739681Slinton 	    prtree(stderr, p);
274*18236Slinton 	    fprintf(stderr, "\"");
2759681Slinton 	    tfree(p);
2769681Slinton 	    enderrmsg();
2779681Slinton 	    /* NOTREACHED */
2789681Slinton     }
2799681Slinton     return r;
2809681Slinton }
2819681Slinton 
2829681Slinton /*
2839681Slinton  * Create a "concrete" version of a node.
2849681Slinton  * This is necessary when the type of the node contains
2859681Slinton  * an unresolved type reference.
2869681Slinton  */
2879681Slinton 
2889681Slinton public Node concrete(p)
2899681Slinton Node p;
2909681Slinton {
2919681Slinton     findtype(p->nodetype);
2929681Slinton     return build(O_INDIR, p);
2939681Slinton }
2949681Slinton 
2959681Slinton /*
296*18236Slinton  * Create a command list from a single command.
297*18236Slinton  */
298*18236Slinton 
299*18236Slinton public Cmdlist buildcmdlist(cmd)
300*18236Slinton Command cmd;
301*18236Slinton {
302*18236Slinton     Cmdlist cmdlist;
303*18236Slinton 
304*18236Slinton     cmdlist = list_alloc();
305*18236Slinton     cmdlist_append(cmd, cmdlist);
306*18236Slinton     return cmdlist;
307*18236Slinton }
308*18236Slinton 
309*18236Slinton /*
3109681Slinton  * Print out a command.
3119681Slinton  */
3129681Slinton 
3139681Slinton public printcmd(f, cmd)
3149681Slinton File f;
3159681Slinton Command cmd;
3169681Slinton {
3179681Slinton     register Integer i;
3189681Slinton     register Command c;
3199681Slinton     register Node p;
3209681Slinton 
3219681Slinton     switch (cmd->op) {
3229681Slinton 	case O_PRINTIFCHANGED:
3239681Slinton 	case O_PRINTSRCPOS:
3249681Slinton 	case O_STOPIFCHANGED:
3259681Slinton 	case O_TRACEON:
3269681Slinton 	    break;
3279681Slinton 
3289681Slinton 	case O_STEP:
3299681Slinton 	    if (cmd->value.step.skipcalls) {
3309681Slinton 		fprintf(f, "next");
3319681Slinton 	    } else {
3329681Slinton 		fprintf(f, "step");
3339681Slinton 	    }
3349681Slinton 	    if (not cmd->value.step.source) {
3359681Slinton 		fprintf(f, "i");
3369681Slinton 	    }
3379681Slinton 	    break;
3389681Slinton 
3399681Slinton 	default:
3409681Slinton 	    fprintf(f, "%s", opinfo[ord(cmd->op)].opstring);
3419681Slinton 	    if (nargs(cmd->op) != 0) {
3429681Slinton 		fprintf(f, " ");
3439681Slinton 	    }
3449681Slinton 	    break;
3459681Slinton     }
3469681Slinton     switch (cmd->op) {
3479681Slinton 	case O_PRINTCALL:
3489681Slinton 	case O_PRINTRTN:
3499681Slinton 	case O_PROCRTN:
3509681Slinton 	    fprintf(f, "%s", symname(cmd->value.sym));
3519681Slinton 	    break;
3529681Slinton 
3539681Slinton 	case O_PRINTSRCPOS:
3549681Slinton 	    p = cmd->value.arg[0];
3559681Slinton 	    if (p != nil and p->op != O_QLINE) {
3569681Slinton 		printf("trace ");
3579681Slinton 		prtree(f, p);
3589681Slinton 	    }
3599681Slinton 	    break;
3609681Slinton 
3619681Slinton 	case O_CHFILE:
3629681Slinton 	case O_EDIT:
3639681Slinton 	case O_SOURCE:
3649681Slinton 	    fprintf(f, "%s", cmd->value.scon);
3659681Slinton 	    break;
3669681Slinton 
367*18236Slinton 	case O_CATCH:
368*18236Slinton 	case O_IGNORE:
3699681Slinton 	case O_TRACEOFF:
3709681Slinton 	    fprintf(f, "%d", cmd->value.lcon);
3719681Slinton 	    break;
3729681Slinton 
3739681Slinton 	case O_ADDEVENT:
3749681Slinton 	case O_ONCE:
3759681Slinton 	case O_IF:
3769681Slinton 	    fprintf(f, " ");
3779681Slinton 	    prtree(f, cmd->value.event.cond);
3789681Slinton 	    fprintf(f, " { ");
3799681Slinton 	    foreach (Command, c, cmd->value.event.actions)
3809681Slinton 		printcmd(f, c);
3819681Slinton 		if (not list_islast()) {
3829681Slinton 		    fprintf(f, ";");
3839681Slinton 		}
3849681Slinton 	    endfor
3859681Slinton 	    fprintf(f, " }", opinfo[ord(cmd->op)].opstring);
3869681Slinton 	    break;
3879681Slinton 
3889681Slinton 	case O_TRACEON:
3899681Slinton 	    print_tracestop(f, cmd);
3909681Slinton 	    break;
3919681Slinton 
3929681Slinton 	case O_EXAMINE:
3939681Slinton 	    prtree(f, cmd->value.examine.beginaddr);
3949681Slinton 	    if (cmd->value.examine.endaddr != nil) {
3959681Slinton 		fprintf(f, ",");
3969681Slinton 		prtree(f, cmd->value.examine.endaddr);
3979681Slinton 	    }
3989681Slinton 	    fprintf(f, "/");
3999681Slinton 	    if (cmd->value.examine.count > 1) {
4009681Slinton 		fprintf(f, "%d", cmd->value.examine.count);
4019681Slinton 	    }
4029681Slinton 	    fprintf("%s", cmd->value.examine.mode);
4039681Slinton 	    break;
4049681Slinton 
4059681Slinton 	default:
4069681Slinton 	    if (nargs(cmd->op) != 0) {
4079681Slinton 		i = 0;
4089681Slinton 		for (;;) {
4099681Slinton 		    prtree(f, cmd->value.arg[i]);
4109681Slinton 		    ++i;
4119681Slinton 		if (i >= nargs(cmd->op)) break;
4129681Slinton 		    fprintf(f, " ");
4139681Slinton 		}
4149681Slinton 	    }
4159681Slinton 	    break;
4169681Slinton     }
4179681Slinton }
4189681Slinton 
4199681Slinton /*
4209681Slinton  * Print out a trace/stop command name.
4219681Slinton  */
4229681Slinton 
42314446Slinton #define fprintI(f, b) { if (b) fprintf(f, "i"); }
42414446Slinton 
4259681Slinton private print_tracestop(f, cmd)
4269681Slinton File f;
4279681Slinton Command cmd;
4289681Slinton {
4299681Slinton     register Command c, ifcmd, stopcmd;
4309681Slinton     Boolean done;
4319681Slinton 
4329681Slinton     done = false;
4339681Slinton     ifcmd = list_element(Command, list_head(cmd->value.trace.actions));
4349681Slinton     checkref(ifcmd);
4359681Slinton     if (ifcmd->op == O_IF) {
4369681Slinton 	stopcmd = list_element(Command, list_head(ifcmd->value.event.actions));
4379681Slinton 	checkref(stopcmd);
4389681Slinton 	if (stopcmd->op == O_STOPX) {
43914446Slinton 	    fprintf(f, "stop");
44014446Slinton 	    fprintI(f, cmd->value.trace.inst);
44114446Slinton 	    fprintf(f, " if ");
4429681Slinton 	    prtree(f, ifcmd->value.event.cond);
4439681Slinton 	    done = true;
4449681Slinton 	}
44514446Slinton     } else if (ifcmd->op == O_STOPIFCHANGED) {
44614446Slinton 	fprintf(f, "stop");
44714446Slinton 	fprintI(f, cmd->value.trace.inst);
44814446Slinton 	fprintf(f, " ");
44914446Slinton 	prtree(f, ifcmd->value.arg[0]);
45014446Slinton 	done = true;
4519681Slinton     }
4529681Slinton     if (not done) {
4539681Slinton 	fprintf(f, "%s ", cmd->value.trace.inst ? "tracei" : "trace");
4549681Slinton 	foreach (Command, c, cmd->value.trace.actions)
4559681Slinton 	    printcmd(f, c);
4569681Slinton 	    if (not list_islast()) {
4579681Slinton 		fprintf(f, ";");
4589681Slinton 	    }
4599681Slinton 	endfor
4609681Slinton     }
4619681Slinton }
4629681Slinton 
4639681Slinton /*
46414446Slinton  * Print out a tree.
4659681Slinton  */
4669681Slinton 
4679681Slinton public prtree(f, p)
4689681Slinton File f;
4699681Slinton register Node p;
4709681Slinton {
4719681Slinton     register Node q;
4729681Slinton     Operator op;
4739681Slinton 
4749681Slinton     if (p != nil) {
4759681Slinton 	op = p->op;
4769681Slinton 	if (ord(op) > ord(O_LASTOP)) {
4779681Slinton 	    panic("bad op %d in prtree", p->op);
4789681Slinton 	}
4799681Slinton 	switch (op) {
4809681Slinton 	    case O_NAME:
4819681Slinton 		fprintf(f, "%s", ident(p->value.name));
4829681Slinton 		break;
4839681Slinton 
4849681Slinton 	    case O_SYM:
4859681Slinton 		printname(f, p->value.sym);
4869681Slinton 		break;
4879681Slinton 
4889681Slinton 	    case O_QLINE:
4899681Slinton 		if (nlhdr.nfiles > 1) {
4909681Slinton 		    prtree(f, p->value.arg[0]);
4919681Slinton 		    fprintf(f, ":");
4929681Slinton 		}
4939681Slinton 		prtree(f, p->value.arg[1]);
4949681Slinton 		break;
4959681Slinton 
4969681Slinton 	    case O_LCON:
497*18236Slinton 		fprintf(f, "%d", p->value.lcon);
4989681Slinton 		break;
4999681Slinton 
500*18236Slinton 	    case O_CCON:
501*18236Slinton 		fprintf(f, "'%c'", p->value.lcon);
502*18236Slinton 		break;
503*18236Slinton 
5049681Slinton 	    case O_FCON:
5059681Slinton 		fprintf(f, "%g", p->value.fcon);
5069681Slinton 		break;
5079681Slinton 
5089681Slinton 	    case O_SCON:
5099681Slinton 		fprintf(f, "\"%s\"", p->value.scon);
5109681Slinton 		break;
5119681Slinton 
5129681Slinton 	    case O_INDEX:
5139681Slinton 		prtree(f, p->value.arg[0]);
5149681Slinton 		fprintf(f, "[");
5159681Slinton 		prtree(f, p->value.arg[1]);
5169681Slinton 		fprintf(f, "]");
5179681Slinton 		break;
5189681Slinton 
5199681Slinton 	    case O_COMMA:
5209681Slinton 		prtree(f, p->value.arg[0]);
5219681Slinton 		if (p->value.arg[1] != nil) {
5229681Slinton 		    fprintf(f, ", ");
5239681Slinton 		    prtree(f, p->value.arg[1]);
5249681Slinton 		}
5259681Slinton 		break;
5269681Slinton 
5279681Slinton 	    case O_RVAL:
5289681Slinton 	    case O_ITOF:
5299681Slinton 		prtree(f, p->value.arg[0]);
5309681Slinton 		break;
5319681Slinton 
5329681Slinton 	    case O_CALL:
5339681Slinton 		prtree(f, p->value.arg[0]);
5349681Slinton 		if (p->value.arg[1]!= nil) {
5359681Slinton 		    fprintf(f, "(");
5369681Slinton 		    prtree(f, p->value.arg[1]);
5379681Slinton 		    fprintf(f, ")");
5389681Slinton 		}
5399681Slinton 		break;
5409681Slinton 
5419681Slinton 	    case O_INDIR:
542*18236Slinton 		prtree(f, p->value.arg[0]);
543*18236Slinton 		fprintf(f, "^");
5449681Slinton 		break;
5459681Slinton 
5469681Slinton 	    case O_DOT:
547*18236Slinton 		prtree(f, p->value.arg[0]);
5489681Slinton 		fprintf(f, ".%s", symname(p->value.arg[1]->value.sym));
5499681Slinton 		break;
5509681Slinton 
551*18236Slinton 	    case O_TYPERENAME:
552*18236Slinton 		prtree(f, p->value.arg[1]);
553*18236Slinton 		fprintf(f, "(");
554*18236Slinton 		prtree(f, p->value.arg[0]);
555*18236Slinton 		fprintf(f, ")");
556*18236Slinton 		break;
557*18236Slinton 
5589681Slinton 	    default:
5599681Slinton 		switch (degree(op)) {
5609681Slinton 		    case BINARY:
5619681Slinton 			prtree(f, p->value.arg[0]);
5629681Slinton 			fprintf(f, "%s", opinfo[ord(op)].opstring);
5639681Slinton 			prtree(f, p->value.arg[1]);
5649681Slinton 			break;
5659681Slinton 
5669681Slinton 		    case UNARY:
5679681Slinton 			fprintf(f, "%s", opinfo[ord(op)].opstring);
5689681Slinton 			prtree(f, p->value.arg[0]);
5699681Slinton 			break;
5709681Slinton 
5719681Slinton 		    default:
572*18236Slinton 			if (opinfo[ord(op)].opstring == nil) {
573*18236Slinton 			    fprintf(f, "[op %d]", ord(op));
574*18236Slinton 			} else {
575*18236Slinton 			    fprintf(f, "%s", opinfo[ord(op)].opstring);
576*18236Slinton 			}
577*18236Slinton 			break;
5789681Slinton 		}
5799681Slinton 		break;
5809681Slinton 	}
5819681Slinton     }
5829681Slinton }
5839681Slinton 
5849681Slinton /*
5859681Slinton  * Free storage associated with a tree.
5869681Slinton  */
5879681Slinton 
5889681Slinton public tfree(p)
5899681Slinton Node p;
5909681Slinton {
5919681Slinton     Integer i;
5929681Slinton 
5939681Slinton     if (p == nil) {
5949681Slinton 	return;
5959681Slinton     }
5969681Slinton     switch (p->op) {
5979681Slinton 	case O_QLINE:
5989681Slinton 	    dispose(p->value.arg[0]->value.scon);
5999681Slinton 	    dispose(p->value.arg[0]);
6009681Slinton 	    tfree(p->value.arg[1]);
6019681Slinton 	    break;
6029681Slinton 
6039681Slinton 	case O_SCON:
6049681Slinton 	    unmkstring(p->nodetype);
6059681Slinton 	    dispose(p->nodetype);
6069681Slinton 	    dispose(p->value.scon);
6079681Slinton 	    break;
6089681Slinton 
6099681Slinton 	default:
6109681Slinton 	    for (i = 0; i < nargs(p->op); i++) {
6119681Slinton 		tfree(p->value.arg[i]);
6129681Slinton 	    }
6139681Slinton 	    break;
6149681Slinton     }
6159681Slinton     dispose(p);
6169681Slinton }
617