19681Slinton /* Copyright (c) 1982 Regents of the University of California */ 29681Slinton 3*14446Slinton static char sccsid[] = "@(#)tree.c 1.5 08/10/83"; 49681Slinton 59681Slinton /* 69681Slinton * Parse tree management. 79681Slinton */ 89681Slinton 99681Slinton #include "defs.h" 109681Slinton #include "tree.h" 119681Slinton #include "operators.h" 129681Slinton #include "eval.h" 139681Slinton #include "events.h" 149681Slinton #include "symbols.h" 159681Slinton #include "scanner.h" 169681Slinton #include "source.h" 179681Slinton #include "object.h" 189681Slinton #include "mappings.h" 199681Slinton #include "process.h" 209681Slinton #include "machine.h" 219681Slinton 229681Slinton #ifndef public 239681Slinton #include "lists.h" 249681Slinton 259681Slinton typedef struct Node *Node; 269681Slinton typedef Node Command; 279681Slinton typedef List Cmdlist; 289681Slinton 299681Slinton #include "operators.h" 309681Slinton #include "symbols.h" 319681Slinton #include "events.h" 329681Slinton 339681Slinton #define MAXNARGS 5 349681Slinton 359681Slinton struct Node { 369681Slinton Operator op; 379681Slinton Symbol nodetype; 389681Slinton union treevalue { 399681Slinton Symbol sym; 409681Slinton Name name; 419681Slinton long lcon; 429681Slinton double fcon; 439681Slinton String scon; 449681Slinton Node arg[MAXNARGS]; 459681Slinton struct { 469681Slinton Node cond; 479681Slinton Cmdlist actions; 489681Slinton } event; 499681Slinton struct { 509681Slinton Boolean inst; 519681Slinton Event event; 529681Slinton Cmdlist actions; 539681Slinton } trace; 549681Slinton struct { 559681Slinton Boolean source; 569681Slinton Boolean skipcalls; 579681Slinton } step; 589681Slinton struct { 599681Slinton String mode; 609681Slinton Node beginaddr; 619681Slinton Node endaddr; 629681Slinton Integer count; 639681Slinton } examine; 649681Slinton } value; 659681Slinton }; 669681Slinton 679681Slinton #define evalcmd(cmd) eval(cmd) 689681Slinton #define cmdlist_append(cmd, cl) list_append(list_item(cmd), nil, cl) 699681Slinton 709681Slinton #endif 719681Slinton 729681Slinton typedef char *Arglist; 739681Slinton 749681Slinton #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 759681Slinton 769681Slinton /* 779681Slinton * Build a tree. 789681Slinton */ 799681Slinton 809681Slinton /* VARARGS1 */ 819681Slinton public Node build(op, args) 829681Slinton Operator op; 839681Slinton { 849681Slinton register Node p, q; 859681Slinton register Arglist ap; 869681Slinton Integer i; 879681Slinton 889681Slinton p = new(Node); 899681Slinton p->op = op; 909681Slinton p->nodetype = nil; 919681Slinton ap = (Arglist) &args; 929681Slinton switch (op) { 939681Slinton case O_NAME: 949681Slinton p->value.name = nextarg(Name); 959681Slinton break; 969681Slinton 979681Slinton case O_SYM: 989681Slinton case O_PRINTCALL: 999681Slinton case O_PRINTRTN: 1009681Slinton case O_PROCRTN: 1019681Slinton p->value.sym = nextarg(Symbol); 1029681Slinton break; 1039681Slinton 10412548Scsvaf case O_DEBUG: 1059681Slinton case O_LCON: 10611862Slinton case O_CONT: 1079681Slinton case O_DELETE: 1089681Slinton case O_CATCH: 1099681Slinton case O_IGNORE: 1109681Slinton case O_TRACEOFF: 1119681Slinton p->value.lcon = nextarg(long); 1129681Slinton break; 1139681Slinton 1149681Slinton case O_FCON: 1159681Slinton p->value.fcon = nextarg(double); 1169681Slinton break; 1179681Slinton 1189681Slinton case O_SCON: 1199681Slinton case O_CHFILE: 1209681Slinton case O_EDIT: 1219681Slinton case O_SOURCE: 1229681Slinton p->value.scon = nextarg(String); 1239681Slinton break; 1249681Slinton 1259681Slinton case O_RVAL: 1269681Slinton q = nextarg(Node); 1279681Slinton if (q->op == O_CALL) { 1289681Slinton *p = *q; 1299681Slinton dispose(q); 1309681Slinton } else { 1319681Slinton p->value.arg[0] = q; 1329681Slinton } 1339681Slinton break; 1349681Slinton 1359681Slinton case O_INDIR: 1369681Slinton q = nextarg(Node); 1379681Slinton if (q != nil and q->op == O_RVAL) { 1389681Slinton p->value.arg[0] = q->value.arg[0]; 1399681Slinton dispose(q); 1409681Slinton } else { 1419681Slinton p->value.arg[0] = q; 1429681Slinton } 1439681Slinton break; 1449681Slinton 1459681Slinton case O_ADDEVENT: 1469681Slinton case O_ONCE: 1479681Slinton case O_IF: 1489681Slinton p->value.event.cond = nextarg(Node); 1499681Slinton p->value.event.actions = nextarg(Cmdlist); 1509681Slinton break; 1519681Slinton 1529681Slinton case O_TRACEON: 1539681Slinton p->value.trace.inst = nextarg(Boolean); 1549681Slinton p->value.trace.event = nil; 1559681Slinton p->value.trace.actions = nextarg(Cmdlist); 1569681Slinton break; 1579681Slinton 1589681Slinton case O_STEP: 1599681Slinton p->value.step.source = nextarg(Boolean); 1609681Slinton p->value.step.skipcalls = nextarg(Boolean); 1619681Slinton break; 1629681Slinton 1639681Slinton case O_EXAMINE: 1649681Slinton p->value.examine.mode = nextarg(String); 1659681Slinton p->value.examine.beginaddr = nextarg(Node); 1669681Slinton p->value.examine.endaddr = nextarg(Node); 1679681Slinton p->value.examine.count = nextarg(Integer); 1689681Slinton break; 1699681Slinton 1709681Slinton default: 1719681Slinton for (i = 0; i < nargs(op); i++) { 1729681Slinton p->value.arg[i] = nextarg(Node); 1739681Slinton } 1749681Slinton break; 1759681Slinton } 1769681Slinton check(p); 1779681Slinton assigntypes(p); 17812548Scsvaf if(debug_flag[5]) { 17912548Scsvaf fprintf(stderr," built %s node %d with arg0 %d arg1 %d \n", 18012548Scsvaf showoperator(p->op), p, p->value.arg[0],p->value.arg[1]); 18112548Scsvaf } 1829681Slinton return p; 1839681Slinton } 1849681Slinton 1859681Slinton /* 1869681Slinton * Create a command list from a single command. 1879681Slinton */ 1889681Slinton 1899681Slinton public Cmdlist buildcmdlist(cmd) 1909681Slinton Command cmd; 1919681Slinton { 1929681Slinton Cmdlist cmdlist; 1939681Slinton 1949681Slinton cmdlist = list_alloc(); 1959681Slinton cmdlist_append(cmd, cmdlist); 1969681Slinton return cmdlist; 1979681Slinton } 1989681Slinton 1999681Slinton /* 2009681Slinton * Return the tree for a unary ampersand operator. 2019681Slinton */ 2029681Slinton 2039681Slinton public Node amper(p) 2049681Slinton Node p; 2059681Slinton { 2069681Slinton Node r; 2079681Slinton 2089681Slinton checkref(p); 2099681Slinton switch (p->op) { 2109681Slinton case O_RVAL: 2119681Slinton r = p->value.arg[0]; 2129681Slinton break; 2139681Slinton 2149681Slinton case O_CALL: 2159681Slinton r = build(O_LCON, codeloc(p->value.arg[0]->value.sym)); 2169681Slinton tfree(p); 2179681Slinton break; 2189681Slinton 2199681Slinton case O_SYM: 2209681Slinton if (isblock(p->value.sym)) { 2219681Slinton r = build(O_LCON, codeloc(p->value.sym)); 2229681Slinton } else { 2239681Slinton r = build(O_LCON, address(p->value.sym, nil)); 2249681Slinton } 2259681Slinton tfree(p); 2269681Slinton break; 2279681Slinton 2289681Slinton case O_DOT: 2299681Slinton r = p; 2309681Slinton break; 2319681Slinton 2329681Slinton case O_INDIR: 2339681Slinton r = p->value.arg[0]; 2349681Slinton dispose(p); 2359681Slinton break; 2369681Slinton 2379681Slinton default: 2389681Slinton beginerrmsg(); 2399681Slinton fprintf(stderr, "expected variable, found "); 2409681Slinton prtree(stderr, p); 2419681Slinton tfree(p); 2429681Slinton enderrmsg(); 2439681Slinton /* NOTREACHED */ 2449681Slinton } 2459681Slinton r->nodetype = t_int; 2469681Slinton return r; 2479681Slinton } 2489681Slinton 2499681Slinton /* 2509681Slinton * Create a "concrete" version of a node. 2519681Slinton * This is necessary when the type of the node contains 2529681Slinton * an unresolved type reference. 2539681Slinton */ 2549681Slinton 2559681Slinton public Node concrete(p) 2569681Slinton Node p; 2579681Slinton { 2589681Slinton findtype(p->nodetype); 2599681Slinton return build(O_INDIR, p); 2609681Slinton } 2619681Slinton 2629681Slinton /* 2639681Slinton * Print out a command. 2649681Slinton */ 2659681Slinton 2669681Slinton public printcmd(f, cmd) 2679681Slinton File f; 2689681Slinton Command cmd; 2699681Slinton { 2709681Slinton register Integer i; 2719681Slinton register Command c; 2729681Slinton register Node p; 2739681Slinton 2749681Slinton switch (cmd->op) { 2759681Slinton case O_PRINTIFCHANGED: 2769681Slinton case O_PRINTSRCPOS: 2779681Slinton case O_STOPIFCHANGED: 2789681Slinton case O_TRACEON: 2799681Slinton break; 2809681Slinton 2819681Slinton case O_STEP: 2829681Slinton if (cmd->value.step.skipcalls) { 2839681Slinton fprintf(f, "next"); 2849681Slinton } else { 2859681Slinton fprintf(f, "step"); 2869681Slinton } 2879681Slinton if (not cmd->value.step.source) { 2889681Slinton fprintf(f, "i"); 2899681Slinton } 2909681Slinton break; 2919681Slinton 2929681Slinton default: 2939681Slinton fprintf(f, "%s", opinfo[ord(cmd->op)].opstring); 2949681Slinton if (nargs(cmd->op) != 0) { 2959681Slinton fprintf(f, " "); 2969681Slinton } 2979681Slinton break; 2989681Slinton } 2999681Slinton switch (cmd->op) { 3009681Slinton case O_PRINTCALL: 3019681Slinton case O_PRINTRTN: 3029681Slinton case O_PROCRTN: 3039681Slinton fprintf(f, "%s", symname(cmd->value.sym)); 3049681Slinton break; 3059681Slinton 3069681Slinton case O_PRINTSRCPOS: 3079681Slinton p = cmd->value.arg[0]; 3089681Slinton if (p != nil and p->op != O_QLINE) { 3099681Slinton printf("trace "); 3109681Slinton prtree(f, p); 3119681Slinton } 3129681Slinton break; 3139681Slinton 3149681Slinton case O_CHFILE: 3159681Slinton case O_EDIT: 3169681Slinton case O_SOURCE: 3179681Slinton fprintf(f, "%s", cmd->value.scon); 3189681Slinton break; 3199681Slinton 3209681Slinton case O_DELETE: 3219681Slinton case O_CATCH: 3229681Slinton case O_IGNORE: 3239681Slinton case O_TRACEOFF: 3249681Slinton fprintf(f, "%d", cmd->value.lcon); 3259681Slinton break; 3269681Slinton 3279681Slinton case O_ADDEVENT: 3289681Slinton case O_ONCE: 3299681Slinton case O_IF: 3309681Slinton fprintf(f, " "); 3319681Slinton prtree(f, cmd->value.event.cond); 3329681Slinton fprintf(f, " { "); 3339681Slinton foreach (Command, c, cmd->value.event.actions) 3349681Slinton printcmd(f, c); 3359681Slinton if (not list_islast()) { 3369681Slinton fprintf(f, ";"); 3379681Slinton } 3389681Slinton endfor 3399681Slinton fprintf(f, " }", opinfo[ord(cmd->op)].opstring); 3409681Slinton break; 3419681Slinton 3429681Slinton case O_TRACEON: 3439681Slinton print_tracestop(f, cmd); 3449681Slinton break; 3459681Slinton 3469681Slinton case O_EXAMINE: 3479681Slinton prtree(f, cmd->value.examine.beginaddr); 3489681Slinton if (cmd->value.examine.endaddr != nil) { 3499681Slinton fprintf(f, ","); 3509681Slinton prtree(f, cmd->value.examine.endaddr); 3519681Slinton } 3529681Slinton fprintf(f, "/"); 3539681Slinton if (cmd->value.examine.count > 1) { 3549681Slinton fprintf(f, "%d", cmd->value.examine.count); 3559681Slinton } 3569681Slinton fprintf("%s", cmd->value.examine.mode); 3579681Slinton break; 3589681Slinton 3599681Slinton default: 3609681Slinton if (nargs(cmd->op) != 0) { 3619681Slinton i = 0; 3629681Slinton for (;;) { 3639681Slinton prtree(f, cmd->value.arg[i]); 3649681Slinton ++i; 3659681Slinton if (i >= nargs(cmd->op)) break; 3669681Slinton fprintf(f, " "); 3679681Slinton } 3689681Slinton } 3699681Slinton break; 3709681Slinton } 3719681Slinton } 3729681Slinton 3739681Slinton /* 3749681Slinton * Print out a trace/stop command name. 3759681Slinton */ 3769681Slinton 377*14446Slinton #define fprintI(f, b) { if (b) fprintf(f, "i"); } 378*14446Slinton 3799681Slinton private print_tracestop(f, cmd) 3809681Slinton File f; 3819681Slinton Command cmd; 3829681Slinton { 3839681Slinton register Command c, ifcmd, stopcmd; 3849681Slinton Boolean done; 3859681Slinton 3869681Slinton done = false; 3879681Slinton ifcmd = list_element(Command, list_head(cmd->value.trace.actions)); 3889681Slinton checkref(ifcmd); 3899681Slinton if (ifcmd->op == O_IF) { 3909681Slinton stopcmd = list_element(Command, list_head(ifcmd->value.event.actions)); 3919681Slinton checkref(stopcmd); 3929681Slinton if (stopcmd->op == O_STOPX) { 393*14446Slinton fprintf(f, "stop"); 394*14446Slinton fprintI(f, cmd->value.trace.inst); 395*14446Slinton fprintf(f, " if "); 3969681Slinton prtree(f, ifcmd->value.event.cond); 3979681Slinton done = true; 3989681Slinton } 399*14446Slinton } else if (ifcmd->op == O_STOPIFCHANGED) { 400*14446Slinton fprintf(f, "stop"); 401*14446Slinton fprintI(f, cmd->value.trace.inst); 402*14446Slinton fprintf(f, " "); 403*14446Slinton prtree(f, ifcmd->value.arg[0]); 404*14446Slinton done = true; 4059681Slinton } 4069681Slinton if (not done) { 4079681Slinton fprintf(f, "%s ", cmd->value.trace.inst ? "tracei" : "trace"); 4089681Slinton foreach (Command, c, cmd->value.trace.actions) 4099681Slinton printcmd(f, c); 4109681Slinton if (not list_islast()) { 4119681Slinton fprintf(f, ";"); 4129681Slinton } 4139681Slinton endfor 4149681Slinton } 4159681Slinton } 4169681Slinton 4179681Slinton /* 418*14446Slinton * Print out a tree. 4199681Slinton */ 4209681Slinton 4219681Slinton public prtree(f, p) 4229681Slinton File f; 4239681Slinton register Node p; 4249681Slinton { 4259681Slinton register Node q; 4269681Slinton Operator op; 4279681Slinton 4289681Slinton if (p != nil) { 4299681Slinton op = p->op; 4309681Slinton if (ord(op) > ord(O_LASTOP)) { 4319681Slinton panic("bad op %d in prtree", p->op); 4329681Slinton } 4339681Slinton switch (op) { 4349681Slinton case O_NAME: 4359681Slinton fprintf(f, "%s", ident(p->value.name)); 4369681Slinton break; 4379681Slinton 4389681Slinton case O_SYM: 4399681Slinton printname(f, p->value.sym); 4409681Slinton break; 4419681Slinton 4429681Slinton case O_QLINE: 4439681Slinton if (nlhdr.nfiles > 1) { 4449681Slinton prtree(f, p->value.arg[0]); 4459681Slinton fprintf(f, ":"); 4469681Slinton } 4479681Slinton prtree(f, p->value.arg[1]); 4489681Slinton break; 4499681Slinton 4509681Slinton case O_LCON: 4519681Slinton if (compatible(p->nodetype, t_char)) { 4529681Slinton fprintf(f, "'%c'", p->value.lcon); 4539681Slinton } else { 4549681Slinton fprintf(f, "%d", p->value.lcon); 4559681Slinton } 4569681Slinton break; 4579681Slinton 4589681Slinton case O_FCON: 4599681Slinton fprintf(f, "%g", p->value.fcon); 4609681Slinton break; 4619681Slinton 4629681Slinton case O_SCON: 4639681Slinton fprintf(f, "\"%s\"", p->value.scon); 4649681Slinton break; 4659681Slinton 4669681Slinton case O_INDEX: 4679681Slinton prtree(f, p->value.arg[0]); 4689681Slinton fprintf(f, "["); 4699681Slinton prtree(f, p->value.arg[1]); 4709681Slinton fprintf(f, "]"); 4719681Slinton break; 4729681Slinton 4739681Slinton case O_COMMA: 4749681Slinton prtree(f, p->value.arg[0]); 4759681Slinton if (p->value.arg[1] != nil) { 4769681Slinton fprintf(f, ", "); 4779681Slinton prtree(f, p->value.arg[1]); 4789681Slinton } 4799681Slinton break; 4809681Slinton 4819681Slinton case O_RVAL: 4829681Slinton if (p->value.arg[0]->op == O_SYM) { 4839681Slinton printname(f, p->value.arg[0]->value.sym); 4849681Slinton } else { 4859681Slinton prtree(f, p->value.arg[0]); 4869681Slinton } 4879681Slinton break; 4889681Slinton 4899681Slinton case O_ITOF: 4909681Slinton prtree(f, p->value.arg[0]); 4919681Slinton break; 4929681Slinton 4939681Slinton case O_CALL: 4949681Slinton prtree(f, p->value.arg[0]); 4959681Slinton if (p->value.arg[1]!= nil) { 4969681Slinton fprintf(f, "("); 4979681Slinton prtree(f, p->value.arg[1]); 4989681Slinton fprintf(f, ")"); 4999681Slinton } 5009681Slinton break; 5019681Slinton 5029681Slinton case O_INDIR: 5039681Slinton q = p->value.arg[0]; 5049681Slinton if (isvarparam(q->nodetype)) { 5059681Slinton prtree(f, q); 5069681Slinton } else { 5079681Slinton if (q->op == O_SYM or q->op == O_LCON or q->op == O_DOT) { 5089681Slinton prtree(f, q); 5099681Slinton fprintf(f, "^"); 5109681Slinton } else { 5119681Slinton fprintf(f, "*("); 5129681Slinton prtree(f, q); 5139681Slinton fprintf(f, ")"); 5149681Slinton } 5159681Slinton } 5169681Slinton break; 5179681Slinton 5189681Slinton case O_DOT: 5199681Slinton q = p->value.arg[0]; 5209681Slinton if (q->op == O_INDIR) { 5219681Slinton prtree(f, q->value.arg[0]); 5229681Slinton } else { 5239681Slinton prtree(f, q); 5249681Slinton } 5259681Slinton fprintf(f, ".%s", symname(p->value.arg[1]->value.sym)); 5269681Slinton break; 5279681Slinton 5289681Slinton default: 5299681Slinton switch (degree(op)) { 5309681Slinton case BINARY: 5319681Slinton prtree(f, p->value.arg[0]); 5329681Slinton fprintf(f, "%s", opinfo[ord(op)].opstring); 5339681Slinton prtree(f, p->value.arg[1]); 5349681Slinton break; 5359681Slinton 5369681Slinton case UNARY: 5379681Slinton fprintf(f, "%s", opinfo[ord(op)].opstring); 5389681Slinton prtree(f, p->value.arg[0]); 5399681Slinton break; 5409681Slinton 5419681Slinton default: 5429681Slinton error("internal error: bad op %d in prtree", op); 5439681Slinton } 5449681Slinton break; 5459681Slinton } 5469681Slinton } 5479681Slinton } 5489681Slinton 5499681Slinton /* 5509681Slinton * Free storage associated with a tree. 5519681Slinton */ 5529681Slinton 5539681Slinton public tfree(p) 5549681Slinton Node p; 5559681Slinton { 5569681Slinton Integer i; 5579681Slinton 5589681Slinton if (p == nil) { 5599681Slinton return; 5609681Slinton } 5619681Slinton switch (p->op) { 5629681Slinton case O_QLINE: 5639681Slinton dispose(p->value.arg[0]->value.scon); 5649681Slinton dispose(p->value.arg[0]); 5659681Slinton tfree(p->value.arg[1]); 5669681Slinton break; 5679681Slinton 5689681Slinton case O_SCON: 5699681Slinton unmkstring(p->nodetype); 5709681Slinton dispose(p->nodetype); 5719681Slinton dispose(p->value.scon); 5729681Slinton break; 5739681Slinton 5749681Slinton default: 5759681Slinton for (i = 0; i < nargs(p->op); i++) { 5769681Slinton tfree(p->value.arg[i]); 5779681Slinton } 5789681Slinton break; 5799681Slinton } 5809681Slinton dispose(p); 5819681Slinton } 5829681Slinton 5839681Slinton /* 5849681Slinton * A recursive tree search routine to test if two trees * are equivalent. 5859681Slinton */ 5869681Slinton 5879681Slinton public Boolean tr_equal(t1, t2) 5889681Slinton register Node t1; 5899681Slinton register Node t2; 5909681Slinton { 5919681Slinton register Boolean b; 5929681Slinton 5939681Slinton if (t1 == nil and t2 == nil) { 5949681Slinton b = true; 5959681Slinton } else if (t1 == nil or t2 == nil) { 5969681Slinton b = false; 5979681Slinton } else if (t1->op != t2->op or degree(t1->op) != degree(t2->op)) { 5989681Slinton b = false; 5999681Slinton } else { 6009681Slinton switch (degree(t1->op)) { 6019681Slinton case LEAF: 6029681Slinton switch (t1->op) { 6039681Slinton case O_NAME: 6049681Slinton b = (Boolean) (t1->value.name == t2->value.name); 6059681Slinton break; 6069681Slinton 6079681Slinton case O_SYM: 6089681Slinton b = (Boolean) (t1->value.sym == t2->value.sym); 6099681Slinton break; 6109681Slinton 6119681Slinton case O_LCON: 6129681Slinton b = (Boolean) (t1->value.lcon == t2->value.lcon); 6139681Slinton break; 6149681Slinton 6159681Slinton case O_FCON: 6169681Slinton b = (Boolean) (t1->value.fcon == t2->value.fcon); 6179681Slinton break; 6189681Slinton 6199681Slinton case O_SCON: 6209681Slinton b = (Boolean) (t1->value.scon == t2->value.scon); 6219681Slinton break; 6229681Slinton 6239681Slinton default: 6249681Slinton panic("tr_equal: leaf %d\n", t1->op); 6259681Slinton } 6269681Slinton /*NOTREACHED*/ 6279681Slinton 6289681Slinton case BINARY: 6299681Slinton if (not tr_equal(t1->value.arg[0], t2->value.arg[0])) { 6309681Slinton b = false; 6319681Slinton } else { 6329681Slinton b = tr_equal(t1->value.arg[1], t2->value.arg[1]); 6339681Slinton } 6349681Slinton break; 6359681Slinton 6369681Slinton case UNARY: 6379681Slinton b = tr_equal(t1->value.arg[0], t2->value.arg[0]); 6389681Slinton break; 6399681Slinton 6409681Slinton default: 6419681Slinton panic("tr_equal: bad degree for op %d\n", t1->op); 6429681Slinton } 6439681Slinton } 6449681Slinton return b; 6459681Slinton } 646