xref: /csrg-svn/old/dbx/tree.c (revision 42688)
121626Sdist /*
238105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
338105Sbostic  * All rights reserved.
438105Sbostic  *
5*42688Sbostic  * %sccs.include.redist.c%
621626Sdist  */
79681Slinton 
821626Sdist #ifndef lint
9*42688Sbostic static char sccsid[] = "@(#)tree.c	5.5 (Berkeley) 06/01/90";
1038105Sbostic #endif /* not lint */
119681Slinton 
129681Slinton /*
139681Slinton  * Parse tree management.
149681Slinton  */
159681Slinton 
169681Slinton #include "defs.h"
179681Slinton #include "tree.h"
189681Slinton #include "operators.h"
1918236Slinton #include "debug.h"
209681Slinton #include "eval.h"
219681Slinton #include "events.h"
229681Slinton #include "symbols.h"
239681Slinton #include "scanner.h"
249681Slinton #include "source.h"
259681Slinton #include "object.h"
269681Slinton #include "mappings.h"
279681Slinton #include "process.h"
289681Slinton #include "machine.h"
299681Slinton 
309681Slinton #ifndef public
319681Slinton #include "lists.h"
329681Slinton 
339681Slinton typedef struct Node *Node;
349681Slinton typedef Node Command;
359681Slinton typedef List Cmdlist;
369681Slinton 
379681Slinton #include "operators.h"
389681Slinton #include "symbols.h"
399681Slinton #include "events.h"
409681Slinton 
419681Slinton #define MAXNARGS 5
429681Slinton 
439681Slinton struct Node {
449681Slinton     Operator op;
459681Slinton     Symbol nodetype;
469681Slinton     union treevalue {
479681Slinton 	Symbol sym;
489681Slinton 	Name name;
499681Slinton 	long lcon;
509681Slinton 	double fcon;
519681Slinton 	String scon;
529681Slinton 	Node arg[MAXNARGS];
539681Slinton 	struct {
549681Slinton 	    Node cond;
559681Slinton 	    Cmdlist actions;
569681Slinton 	} event;
579681Slinton 	struct {
589681Slinton 	    Boolean inst;
599681Slinton 	    Event event;
609681Slinton 	    Cmdlist actions;
619681Slinton 	} trace;
629681Slinton 	struct {
639681Slinton 	    Boolean source;
649681Slinton 	    Boolean skipcalls;
659681Slinton 	} step;
669681Slinton 	struct {
679681Slinton 	    String mode;
689681Slinton 	    Node beginaddr;
699681Slinton 	    Node endaddr;
709681Slinton 	    Integer count;
719681Slinton 	} examine;
729681Slinton     } value;
739681Slinton };
749681Slinton 
759681Slinton #define evalcmd(cmd) eval(cmd)
769681Slinton #define cmdlist_append(cmd, cl) list_append(list_item(cmd), nil, cl)
779681Slinton 
789681Slinton #endif
799681Slinton 
809681Slinton typedef char *Arglist;
819681Slinton 
829681Slinton #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
839681Slinton 
849681Slinton /*
859681Slinton  * Build a tree.
869681Slinton  */
879681Slinton 
889681Slinton /* VARARGS1 */
build(op,args)899681Slinton public Node build(op, args)
909681Slinton Operator op;
919681Slinton {
929681Slinton     register Node p, q;
939681Slinton     register Arglist ap;
949681Slinton     Integer i;
959681Slinton 
969681Slinton     p = new(Node);
979681Slinton     p->op = op;
989681Slinton     p->nodetype = nil;
999681Slinton     ap = (Arglist) &args;
1009681Slinton     switch (op) {
1019681Slinton 	case O_NAME:
1029681Slinton 	    p->value.name = nextarg(Name);
1039681Slinton 	    break;
1049681Slinton 
1059681Slinton 	case O_SYM:
1069681Slinton 	case O_PRINTCALL:
1079681Slinton 	case O_PRINTRTN:
1089681Slinton 	case O_PROCRTN:
1099681Slinton 	    p->value.sym = nextarg(Symbol);
1109681Slinton 	    break;
1119681Slinton 
11212548Scsvaf 	case O_DEBUG:
1139681Slinton 	case O_LCON:
11418236Slinton 	case O_CCON:
11511862Slinton 	case O_CONT:
11618236Slinton 	case O_CATCH:
11718236Slinton 	case O_IGNORE:
1189681Slinton 	case O_TRACEOFF:
1199681Slinton 	    p->value.lcon = nextarg(long);
1209681Slinton 	    break;
1219681Slinton 
1229681Slinton 	case O_FCON:
1239681Slinton 	    p->value.fcon = nextarg(double);
1249681Slinton 	    break;
1259681Slinton 
1269681Slinton 	case O_SCON:
1279681Slinton 	case O_CHFILE:
1289681Slinton 	case O_EDIT:
1299681Slinton 	case O_SOURCE:
1309681Slinton 	    p->value.scon = nextarg(String);
1319681Slinton 	    break;
1329681Slinton 
1339681Slinton 	case O_RVAL:
13418236Slinton 	case O_INDIR:
13518236Slinton 	    p->value.arg[0] = nextarg(Node);
1369681Slinton 	    break;
1379681Slinton 
13818236Slinton 	case O_CALL:
1399681Slinton 	    q = nextarg(Node);
14018236Slinton 	    if (q->op == O_SYM and
14118236Slinton 		(q->value.sym->class == TYPE or q->value.sym->class == TAG)
14218236Slinton 	    ) {
14318236Slinton 		p->op = O_TYPERENAME;
14418236Slinton 		p->value.arg[0] = nextarg(Node);
14518236Slinton 		p->value.arg[1] = q;
14618236Slinton 		q = p->value.arg[0];
14718236Slinton 		if (q->value.arg[1] != nil) {
14818236Slinton 		    error("too many arguments to type rename");
14918236Slinton 		}
1509681Slinton 		p->value.arg[0] = q->value.arg[0];
1519681Slinton 	    } else {
1529681Slinton 		p->value.arg[0] = q;
15318236Slinton 		p->value.arg[1] = nextarg(Node);
1549681Slinton 	    }
1559681Slinton 	    break;
1569681Slinton 
1579681Slinton 	case O_ADDEVENT:
1589681Slinton 	case O_ONCE:
1599681Slinton 	case O_IF:
1609681Slinton 	    p->value.event.cond = nextarg(Node);
1619681Slinton 	    p->value.event.actions = nextarg(Cmdlist);
1629681Slinton 	    break;
1639681Slinton 
1649681Slinton 	case O_TRACEON:
1659681Slinton 	    p->value.trace.inst = nextarg(Boolean);
1669681Slinton 	    p->value.trace.event = nil;
1679681Slinton 	    p->value.trace.actions = nextarg(Cmdlist);
1689681Slinton 	    break;
1699681Slinton 
1709681Slinton 	case O_STEP:
1719681Slinton 	    p->value.step.source = nextarg(Boolean);
1729681Slinton 	    p->value.step.skipcalls = nextarg(Boolean);
1739681Slinton 	    break;
1749681Slinton 
1759681Slinton 	case O_EXAMINE:
1769681Slinton 	    p->value.examine.mode = nextarg(String);
1779681Slinton 	    p->value.examine.beginaddr = nextarg(Node);
1789681Slinton 	    p->value.examine.endaddr = nextarg(Node);
1799681Slinton 	    p->value.examine.count = nextarg(Integer);
1809681Slinton 	    break;
1819681Slinton 
1829681Slinton 	default:
1839681Slinton 	    for (i = 0; i < nargs(op); i++) {
1849681Slinton 		p->value.arg[i] = nextarg(Node);
1859681Slinton 	    }
1869681Slinton 	    break;
1879681Slinton     }
1889681Slinton     check(p);
1899681Slinton     assigntypes(p);
19018236Slinton     if (tracetree) {
19118236Slinton 	printf("built %s node 0x%x with arg[0] 0x%x arg[1] 0x%x\n",
19218236Slinton 	    opname(p->op), p, p->value.arg[0], p->value.arg[1]);
19318236Slinton 	fflush(stdout);
19412548Scsvaf     }
1959681Slinton     return p;
1969681Slinton }
1979681Slinton 
1989681Slinton /*
19918236Slinton  * Strip away indirection from a node, thus returning a node for
20018236Slinton  * interpreting the expression as an lvalue.
2019681Slinton  */
2029681Slinton 
unrval(exp)20318236Slinton public Node unrval (exp)
20418236Slinton Node exp;
2059681Slinton {
20618236Slinton     Node p;
20718236Slinton     Symbol t;
2089681Slinton 
20918236Slinton     if (exp->op == O_RVAL) {
21018236Slinton 	p = exp->value.arg[0];
21118236Slinton 	dispose(exp);
21218236Slinton     } else if (exp->op == O_INDIR) {
21318236Slinton 	p = exp->value.arg[0];
21418236Slinton 	if (p->op == O_RVAL) {
21518236Slinton 	    p->op = O_INDIR;
21618236Slinton 	    p->nodetype = exp->nodetype;
21718236Slinton 	}
21818236Slinton 	dispose(exp);
21918236Slinton     } else {
22018236Slinton 	p = exp;
22118236Slinton     }
22218236Slinton     return p;
2239681Slinton }
2249681Slinton 
2259681Slinton /*
22618236Slinton  * Create a node for renaming a node to a pointer type.
22718236Slinton  */
22818236Slinton 
renameptr(p,t)22918236Slinton public Node renameptr (p, t)
23018236Slinton Node p;
23118236Slinton Node t;
23218236Slinton {
23318236Slinton     t->nodetype = newSymbol(nil, 0, PTR, t->nodetype, nil);
23418236Slinton     p = build(O_TYPERENAME, p, t);
23518236Slinton }
23618236Slinton 
23718236Slinton /*
2389681Slinton  * Return the tree for a unary ampersand operator.
2399681Slinton  */
2409681Slinton 
amper(p)2419681Slinton public Node amper(p)
2429681Slinton Node p;
2439681Slinton {
2449681Slinton     Node r;
2459681Slinton 
2469681Slinton     checkref(p);
2479681Slinton     switch (p->op) {
2489681Slinton 	case O_RVAL:
24918236Slinton 	case O_INDIR:
2509681Slinton 	    r = p->value.arg[0];
25118236Slinton 	    r->nodetype = t_addr;
25218236Slinton 	    dispose(p);
2539681Slinton 	    break;
2549681Slinton 
25518236Slinton 	case O_TYPERENAME:
25618236Slinton 	    r = p;
25718236Slinton 	    r->nodetype = newSymbol(nil, 0, PTR, r->nodetype, nil);
25833339Sdonn 	    r->nodetype->language = p->nodetype->language;
2599681Slinton 	    break;
2609681Slinton 
2619681Slinton 	case O_SYM:
2629681Slinton 	    if (isblock(p->value.sym)) {
2639681Slinton 		r = build(O_LCON, codeloc(p->value.sym));
2649681Slinton 	    } else {
2659681Slinton 		r = build(O_LCON, address(p->value.sym, nil));
2669681Slinton 	    }
26718236Slinton 	    r->nodetype = t_addr;
26818236Slinton 	    dispose(p);
2699681Slinton 	    break;
2709681Slinton 
2719681Slinton 	case O_DOT:
2729681Slinton 	    r = p;
27318236Slinton 	    r->nodetype = t_addr;
2749681Slinton 	    break;
2759681Slinton 
2769681Slinton 	default:
2779681Slinton 	    beginerrmsg();
27818236Slinton 	    fprintf(stderr, "expected variable, found \"");
2799681Slinton 	    prtree(stderr, p);
28018236Slinton 	    fprintf(stderr, "\"");
2819681Slinton 	    tfree(p);
2829681Slinton 	    enderrmsg();
2839681Slinton 	    /* NOTREACHED */
2849681Slinton     }
2859681Slinton     return r;
2869681Slinton }
2879681Slinton 
2889681Slinton /*
2899681Slinton  * Create a "concrete" version of a node.
2909681Slinton  * This is necessary when the type of the node contains
2919681Slinton  * an unresolved type reference.
2929681Slinton  */
2939681Slinton 
concrete(p)2949681Slinton public Node concrete(p)
2959681Slinton Node p;
2969681Slinton {
2979681Slinton     findtype(p->nodetype);
2989681Slinton     return build(O_INDIR, p);
2999681Slinton }
3009681Slinton 
3019681Slinton /*
30218236Slinton  * Create a command list from a single command.
30318236Slinton  */
30418236Slinton 
buildcmdlist(cmd)30518236Slinton public Cmdlist buildcmdlist(cmd)
30618236Slinton Command cmd;
30718236Slinton {
30818236Slinton     Cmdlist cmdlist;
30918236Slinton 
31018236Slinton     cmdlist = list_alloc();
31118236Slinton     cmdlist_append(cmd, cmdlist);
31218236Slinton     return cmdlist;
31318236Slinton }
31418236Slinton 
31518236Slinton /*
3169681Slinton  * Print out a command.
3179681Slinton  */
3189681Slinton 
printcmd(f,cmd)3199681Slinton public printcmd(f, cmd)
3209681Slinton File f;
3219681Slinton Command cmd;
3229681Slinton {
3239681Slinton     register Integer i;
3249681Slinton     register Command c;
3259681Slinton     register Node p;
3269681Slinton 
3279681Slinton     switch (cmd->op) {
3289681Slinton 	case O_PRINTIFCHANGED:
3299681Slinton 	case O_PRINTSRCPOS:
3309681Slinton 	case O_STOPIFCHANGED:
3319681Slinton 	case O_TRACEON:
3329681Slinton 	    break;
3339681Slinton 
3349681Slinton 	case O_STEP:
3359681Slinton 	    if (cmd->value.step.skipcalls) {
3369681Slinton 		fprintf(f, "next");
3379681Slinton 	    } else {
3389681Slinton 		fprintf(f, "step");
3399681Slinton 	    }
3409681Slinton 	    if (not cmd->value.step.source) {
3419681Slinton 		fprintf(f, "i");
3429681Slinton 	    }
3439681Slinton 	    break;
3449681Slinton 
3459681Slinton 	default:
3469681Slinton 	    fprintf(f, "%s", opinfo[ord(cmd->op)].opstring);
3479681Slinton 	    if (nargs(cmd->op) != 0) {
3489681Slinton 		fprintf(f, " ");
3499681Slinton 	    }
3509681Slinton 	    break;
3519681Slinton     }
3529681Slinton     switch (cmd->op) {
3539681Slinton 	case O_PRINTCALL:
3549681Slinton 	case O_PRINTRTN:
3559681Slinton 	case O_PROCRTN:
3569681Slinton 	    fprintf(f, "%s", symname(cmd->value.sym));
3579681Slinton 	    break;
3589681Slinton 
3599681Slinton 	case O_PRINTSRCPOS:
3609681Slinton 	    p = cmd->value.arg[0];
3619681Slinton 	    if (p != nil and p->op != O_QLINE) {
3629681Slinton 		printf("trace ");
3639681Slinton 		prtree(f, p);
3649681Slinton 	    }
3659681Slinton 	    break;
3669681Slinton 
3679681Slinton 	case O_CHFILE:
3689681Slinton 	case O_EDIT:
3699681Slinton 	case O_SOURCE:
3709681Slinton 	    fprintf(f, "%s", cmd->value.scon);
3719681Slinton 	    break;
3729681Slinton 
37318236Slinton 	case O_CATCH:
37418236Slinton 	case O_IGNORE:
3759681Slinton 	case O_TRACEOFF:
3769681Slinton 	    fprintf(f, "%d", cmd->value.lcon);
3779681Slinton 	    break;
3789681Slinton 
3799681Slinton 	case O_ADDEVENT:
3809681Slinton 	case O_ONCE:
3819681Slinton 	case O_IF:
3829681Slinton 	    fprintf(f, " ");
3839681Slinton 	    prtree(f, cmd->value.event.cond);
3849681Slinton 	    fprintf(f, " { ");
3859681Slinton 	    foreach (Command, c, cmd->value.event.actions)
3869681Slinton 		printcmd(f, c);
3879681Slinton 		if (not list_islast()) {
3889681Slinton 		    fprintf(f, ";");
3899681Slinton 		}
3909681Slinton 	    endfor
39130798Sbostic 	    fprintf(f, "%s }", opinfo[ord(cmd->op)].opstring);
3929681Slinton 	    break;
3939681Slinton 
3949681Slinton 	case O_TRACEON:
3959681Slinton 	    print_tracestop(f, cmd);
3969681Slinton 	    break;
3979681Slinton 
3989681Slinton 	case O_EXAMINE:
3999681Slinton 	    prtree(f, cmd->value.examine.beginaddr);
4009681Slinton 	    if (cmd->value.examine.endaddr != nil) {
4019681Slinton 		fprintf(f, ",");
4029681Slinton 		prtree(f, cmd->value.examine.endaddr);
4039681Slinton 	    }
4049681Slinton 	    fprintf(f, "/");
4059681Slinton 	    if (cmd->value.examine.count > 1) {
4069681Slinton 		fprintf(f, "%d", cmd->value.examine.count);
4079681Slinton 	    }
4089681Slinton 	    fprintf("%s", cmd->value.examine.mode);
4099681Slinton 	    break;
4109681Slinton 
4119681Slinton 	default:
4129681Slinton 	    if (nargs(cmd->op) != 0) {
4139681Slinton 		i = 0;
4149681Slinton 		for (;;) {
4159681Slinton 		    prtree(f, cmd->value.arg[i]);
4169681Slinton 		    ++i;
4179681Slinton 		if (i >= nargs(cmd->op)) break;
4189681Slinton 		    fprintf(f, " ");
4199681Slinton 		}
4209681Slinton 	    }
4219681Slinton 	    break;
4229681Slinton     }
4239681Slinton }
4249681Slinton 
4259681Slinton /*
4269681Slinton  * Print out a trace/stop command name.
4279681Slinton  */
4289681Slinton 
42914446Slinton #define fprintI(f, b) { if (b) fprintf(f, "i"); }
43014446Slinton 
print_tracestop(f,cmd)4319681Slinton private print_tracestop(f, cmd)
4329681Slinton File f;
4339681Slinton Command cmd;
4349681Slinton {
4359681Slinton     register Command c, ifcmd, stopcmd;
4369681Slinton     Boolean done;
4379681Slinton 
4389681Slinton     done = false;
4399681Slinton     ifcmd = list_element(Command, list_head(cmd->value.trace.actions));
4409681Slinton     checkref(ifcmd);
4419681Slinton     if (ifcmd->op == O_IF) {
4429681Slinton 	stopcmd = list_element(Command, list_head(ifcmd->value.event.actions));
4439681Slinton 	checkref(stopcmd);
4449681Slinton 	if (stopcmd->op == O_STOPX) {
44514446Slinton 	    fprintf(f, "stop");
44614446Slinton 	    fprintI(f, cmd->value.trace.inst);
44714446Slinton 	    fprintf(f, " if ");
4489681Slinton 	    prtree(f, ifcmd->value.event.cond);
4499681Slinton 	    done = true;
4509681Slinton 	}
45114446Slinton     } else if (ifcmd->op == O_STOPIFCHANGED) {
45214446Slinton 	fprintf(f, "stop");
45314446Slinton 	fprintI(f, cmd->value.trace.inst);
45414446Slinton 	fprintf(f, " ");
45514446Slinton 	prtree(f, ifcmd->value.arg[0]);
45614446Slinton 	done = true;
4579681Slinton     }
4589681Slinton     if (not done) {
4599681Slinton 	fprintf(f, "%s ", cmd->value.trace.inst ? "tracei" : "trace");
4609681Slinton 	foreach (Command, c, cmd->value.trace.actions)
4619681Slinton 	    printcmd(f, c);
4629681Slinton 	    if (not list_islast()) {
4639681Slinton 		fprintf(f, ";");
4649681Slinton 	    }
4659681Slinton 	endfor
4669681Slinton     }
4679681Slinton }
4689681Slinton 
4699681Slinton /*
47014446Slinton  * Print out a tree.
4719681Slinton  */
4729681Slinton 
prtree(f,p)4739681Slinton public prtree(f, p)
4749681Slinton File f;
4759681Slinton register Node p;
4769681Slinton {
4779681Slinton     register Node q;
4789681Slinton     Operator op;
4799681Slinton 
4809681Slinton     if (p != nil) {
4819681Slinton 	op = p->op;
4829681Slinton 	if (ord(op) > ord(O_LASTOP)) {
4839681Slinton 	    panic("bad op %d in prtree", p->op);
4849681Slinton 	}
4859681Slinton 	switch (op) {
4869681Slinton 	    case O_NAME:
4879681Slinton 		fprintf(f, "%s", ident(p->value.name));
4889681Slinton 		break;
4899681Slinton 
4909681Slinton 	    case O_SYM:
4919681Slinton 		printname(f, p->value.sym);
4929681Slinton 		break;
4939681Slinton 
4949681Slinton 	    case O_QLINE:
4959681Slinton 		if (nlhdr.nfiles > 1) {
4969681Slinton 		    prtree(f, p->value.arg[0]);
4979681Slinton 		    fprintf(f, ":");
4989681Slinton 		}
4999681Slinton 		prtree(f, p->value.arg[1]);
5009681Slinton 		break;
5019681Slinton 
5029681Slinton 	    case O_LCON:
50318236Slinton 		fprintf(f, "%d", p->value.lcon);
5049681Slinton 		break;
5059681Slinton 
50618236Slinton 	    case O_CCON:
50718236Slinton 		fprintf(f, "'%c'", p->value.lcon);
50818236Slinton 		break;
50918236Slinton 
5109681Slinton 	    case O_FCON:
5119681Slinton 		fprintf(f, "%g", p->value.fcon);
5129681Slinton 		break;
5139681Slinton 
5149681Slinton 	    case O_SCON:
5159681Slinton 		fprintf(f, "\"%s\"", p->value.scon);
5169681Slinton 		break;
5179681Slinton 
5189681Slinton 	    case O_INDEX:
5199681Slinton 		prtree(f, p->value.arg[0]);
5209681Slinton 		fprintf(f, "[");
5219681Slinton 		prtree(f, p->value.arg[1]);
5229681Slinton 		fprintf(f, "]");
5239681Slinton 		break;
5249681Slinton 
5259681Slinton 	    case O_COMMA:
5269681Slinton 		prtree(f, p->value.arg[0]);
5279681Slinton 		if (p->value.arg[1] != nil) {
5289681Slinton 		    fprintf(f, ", ");
5299681Slinton 		    prtree(f, p->value.arg[1]);
5309681Slinton 		}
5319681Slinton 		break;
5329681Slinton 
5339681Slinton 	    case O_RVAL:
5349681Slinton 	    case O_ITOF:
5359681Slinton 		prtree(f, p->value.arg[0]);
5369681Slinton 		break;
5379681Slinton 
5389681Slinton 	    case O_CALL:
5399681Slinton 		prtree(f, p->value.arg[0]);
5409681Slinton 		if (p->value.arg[1]!= nil) {
5419681Slinton 		    fprintf(f, "(");
5429681Slinton 		    prtree(f, p->value.arg[1]);
5439681Slinton 		    fprintf(f, ")");
5449681Slinton 		}
5459681Slinton 		break;
5469681Slinton 
5479681Slinton 	    case O_INDIR:
54818236Slinton 		prtree(f, p->value.arg[0]);
54918236Slinton 		fprintf(f, "^");
5509681Slinton 		break;
5519681Slinton 
5529681Slinton 	    case O_DOT:
55318236Slinton 		prtree(f, p->value.arg[0]);
5549681Slinton 		fprintf(f, ".%s", symname(p->value.arg[1]->value.sym));
5559681Slinton 		break;
5569681Slinton 
55718236Slinton 	    case O_TYPERENAME:
55818236Slinton 		prtree(f, p->value.arg[1]);
55918236Slinton 		fprintf(f, "(");
56018236Slinton 		prtree(f, p->value.arg[0]);
56118236Slinton 		fprintf(f, ")");
56218236Slinton 		break;
56318236Slinton 
5649681Slinton 	    default:
5659681Slinton 		switch (degree(op)) {
5669681Slinton 		    case BINARY:
5679681Slinton 			prtree(f, p->value.arg[0]);
5689681Slinton 			fprintf(f, "%s", opinfo[ord(op)].opstring);
5699681Slinton 			prtree(f, p->value.arg[1]);
5709681Slinton 			break;
5719681Slinton 
5729681Slinton 		    case UNARY:
5739681Slinton 			fprintf(f, "%s", opinfo[ord(op)].opstring);
5749681Slinton 			prtree(f, p->value.arg[0]);
5759681Slinton 			break;
5769681Slinton 
5779681Slinton 		    default:
57818236Slinton 			if (opinfo[ord(op)].opstring == nil) {
57918236Slinton 			    fprintf(f, "[op %d]", ord(op));
58018236Slinton 			} else {
58118236Slinton 			    fprintf(f, "%s", opinfo[ord(op)].opstring);
58218236Slinton 			}
58318236Slinton 			break;
5849681Slinton 		}
5859681Slinton 		break;
5869681Slinton 	}
5879681Slinton     }
5889681Slinton }
5899681Slinton 
5909681Slinton /*
5919681Slinton  * Free storage associated with a tree.
5929681Slinton  */
5939681Slinton 
tfree(p)5949681Slinton public tfree(p)
5959681Slinton Node p;
5969681Slinton {
5979681Slinton     Integer i;
5989681Slinton 
5999681Slinton     if (p == nil) {
6009681Slinton 	return;
6019681Slinton     }
6029681Slinton     switch (p->op) {
6039681Slinton 	case O_QLINE:
6049681Slinton 	    dispose(p->value.arg[0]->value.scon);
6059681Slinton 	    dispose(p->value.arg[0]);
6069681Slinton 	    tfree(p->value.arg[1]);
6079681Slinton 	    break;
6089681Slinton 
6099681Slinton 	case O_SCON:
6109681Slinton 	    unmkstring(p->nodetype);
6119681Slinton 	    dispose(p->nodetype);
6129681Slinton 	    dispose(p->value.scon);
6139681Slinton 	    break;
6149681Slinton 
6159681Slinton 	default:
6169681Slinton 	    for (i = 0; i < nargs(p->op); i++) {
6179681Slinton 		tfree(p->value.arg[i]);
6189681Slinton 	    }
6199681Slinton 	    break;
6209681Slinton     }
6219681Slinton     dispose(p);
6229681Slinton }
623