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