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