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