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