121626Sdist /* 2*38105Sbostic * Copyright (c) 1983 The Regents of the University of California. 3*38105Sbostic * All rights reserved. 4*38105Sbostic * 5*38105Sbostic * Redistribution and use in source and binary forms are permitted 6*38105Sbostic * provided that the above copyright notice and this paragraph are 7*38105Sbostic * duplicated in all such forms and that any documentation, 8*38105Sbostic * advertising materials, and other materials related to such 9*38105Sbostic * distribution and use acknowledge that the software was developed 10*38105Sbostic * by the University of California, Berkeley. The name of the 11*38105Sbostic * University may not be used to endorse or promote products derived 12*38105Sbostic * from this software without specific prior written permission. 13*38105Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*38105Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*38105Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621626Sdist */ 179681Slinton 1821626Sdist #ifndef lint 19*38105Sbostic static char sccsid[] = "@(#)tree.c 5.4 (Berkeley) 05/23/89"; 20*38105Sbostic #endif /* not lint */ 219681Slinton 229681Slinton /* 239681Slinton * Parse tree management. 249681Slinton */ 259681Slinton 269681Slinton #include "defs.h" 279681Slinton #include "tree.h" 289681Slinton #include "operators.h" 2918236Slinton #include "debug.h" 309681Slinton #include "eval.h" 319681Slinton #include "events.h" 329681Slinton #include "symbols.h" 339681Slinton #include "scanner.h" 349681Slinton #include "source.h" 359681Slinton #include "object.h" 369681Slinton #include "mappings.h" 379681Slinton #include "process.h" 389681Slinton #include "machine.h" 399681Slinton 409681Slinton #ifndef public 419681Slinton #include "lists.h" 429681Slinton 439681Slinton typedef struct Node *Node; 449681Slinton typedef Node Command; 459681Slinton typedef List Cmdlist; 469681Slinton 479681Slinton #include "operators.h" 489681Slinton #include "symbols.h" 499681Slinton #include "events.h" 509681Slinton 519681Slinton #define MAXNARGS 5 529681Slinton 539681Slinton struct Node { 549681Slinton Operator op; 559681Slinton Symbol nodetype; 569681Slinton union treevalue { 579681Slinton Symbol sym; 589681Slinton Name name; 599681Slinton long lcon; 609681Slinton double fcon; 619681Slinton String scon; 629681Slinton Node arg[MAXNARGS]; 639681Slinton struct { 649681Slinton Node cond; 659681Slinton Cmdlist actions; 669681Slinton } event; 679681Slinton struct { 689681Slinton Boolean inst; 699681Slinton Event event; 709681Slinton Cmdlist actions; 719681Slinton } trace; 729681Slinton struct { 739681Slinton Boolean source; 749681Slinton Boolean skipcalls; 759681Slinton } step; 769681Slinton struct { 779681Slinton String mode; 789681Slinton Node beginaddr; 799681Slinton Node endaddr; 809681Slinton Integer count; 819681Slinton } examine; 829681Slinton } value; 839681Slinton }; 849681Slinton 859681Slinton #define evalcmd(cmd) eval(cmd) 869681Slinton #define cmdlist_append(cmd, cl) list_append(list_item(cmd), nil, cl) 879681Slinton 889681Slinton #endif 899681Slinton 909681Slinton typedef char *Arglist; 919681Slinton 929681Slinton #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] 939681Slinton 949681Slinton /* 959681Slinton * Build a tree. 969681Slinton */ 979681Slinton 989681Slinton /* VARARGS1 */ 999681Slinton public Node build(op, args) 1009681Slinton Operator op; 1019681Slinton { 1029681Slinton register Node p, q; 1039681Slinton register Arglist ap; 1049681Slinton Integer i; 1059681Slinton 1069681Slinton p = new(Node); 1079681Slinton p->op = op; 1089681Slinton p->nodetype = nil; 1099681Slinton ap = (Arglist) &args; 1109681Slinton switch (op) { 1119681Slinton case O_NAME: 1129681Slinton p->value.name = nextarg(Name); 1139681Slinton break; 1149681Slinton 1159681Slinton case O_SYM: 1169681Slinton case O_PRINTCALL: 1179681Slinton case O_PRINTRTN: 1189681Slinton case O_PROCRTN: 1199681Slinton p->value.sym = nextarg(Symbol); 1209681Slinton break; 1219681Slinton 12212548Scsvaf case O_DEBUG: 1239681Slinton case O_LCON: 12418236Slinton case O_CCON: 12511862Slinton case O_CONT: 12618236Slinton case O_CATCH: 12718236Slinton case O_IGNORE: 1289681Slinton case O_TRACEOFF: 1299681Slinton p->value.lcon = nextarg(long); 1309681Slinton break; 1319681Slinton 1329681Slinton case O_FCON: 1339681Slinton p->value.fcon = nextarg(double); 1349681Slinton break; 1359681Slinton 1369681Slinton case O_SCON: 1379681Slinton case O_CHFILE: 1389681Slinton case O_EDIT: 1399681Slinton case O_SOURCE: 1409681Slinton p->value.scon = nextarg(String); 1419681Slinton break; 1429681Slinton 1439681Slinton case O_RVAL: 14418236Slinton case O_INDIR: 14518236Slinton p->value.arg[0] = nextarg(Node); 1469681Slinton break; 1479681Slinton 14818236Slinton case O_CALL: 1499681Slinton q = nextarg(Node); 15018236Slinton if (q->op == O_SYM and 15118236Slinton (q->value.sym->class == TYPE or q->value.sym->class == TAG) 15218236Slinton ) { 15318236Slinton p->op = O_TYPERENAME; 15418236Slinton p->value.arg[0] = nextarg(Node); 15518236Slinton p->value.arg[1] = q; 15618236Slinton q = p->value.arg[0]; 15718236Slinton if (q->value.arg[1] != nil) { 15818236Slinton error("too many arguments to type rename"); 15918236Slinton } 1609681Slinton p->value.arg[0] = q->value.arg[0]; 1619681Slinton } else { 1629681Slinton p->value.arg[0] = q; 16318236Slinton p->value.arg[1] = nextarg(Node); 1649681Slinton } 1659681Slinton break; 1669681Slinton 1679681Slinton case O_ADDEVENT: 1689681Slinton case O_ONCE: 1699681Slinton case O_IF: 1709681Slinton p->value.event.cond = nextarg(Node); 1719681Slinton p->value.event.actions = nextarg(Cmdlist); 1729681Slinton break; 1739681Slinton 1749681Slinton case O_TRACEON: 1759681Slinton p->value.trace.inst = nextarg(Boolean); 1769681Slinton p->value.trace.event = nil; 1779681Slinton p->value.trace.actions = nextarg(Cmdlist); 1789681Slinton break; 1799681Slinton 1809681Slinton case O_STEP: 1819681Slinton p->value.step.source = nextarg(Boolean); 1829681Slinton p->value.step.skipcalls = nextarg(Boolean); 1839681Slinton break; 1849681Slinton 1859681Slinton case O_EXAMINE: 1869681Slinton p->value.examine.mode = nextarg(String); 1879681Slinton p->value.examine.beginaddr = nextarg(Node); 1889681Slinton p->value.examine.endaddr = nextarg(Node); 1899681Slinton p->value.examine.count = nextarg(Integer); 1909681Slinton break; 1919681Slinton 1929681Slinton default: 1939681Slinton for (i = 0; i < nargs(op); i++) { 1949681Slinton p->value.arg[i] = nextarg(Node); 1959681Slinton } 1969681Slinton break; 1979681Slinton } 1989681Slinton check(p); 1999681Slinton assigntypes(p); 20018236Slinton if (tracetree) { 20118236Slinton printf("built %s node 0x%x with arg[0] 0x%x arg[1] 0x%x\n", 20218236Slinton opname(p->op), p, p->value.arg[0], p->value.arg[1]); 20318236Slinton fflush(stdout); 20412548Scsvaf } 2059681Slinton return p; 2069681Slinton } 2079681Slinton 2089681Slinton /* 20918236Slinton * Strip away indirection from a node, thus returning a node for 21018236Slinton * interpreting the expression as an lvalue. 2119681Slinton */ 2129681Slinton 21318236Slinton public Node unrval (exp) 21418236Slinton Node exp; 2159681Slinton { 21618236Slinton Node p; 21718236Slinton Symbol t; 2189681Slinton 21918236Slinton if (exp->op == O_RVAL) { 22018236Slinton p = exp->value.arg[0]; 22118236Slinton dispose(exp); 22218236Slinton } else if (exp->op == O_INDIR) { 22318236Slinton p = exp->value.arg[0]; 22418236Slinton if (p->op == O_RVAL) { 22518236Slinton p->op = O_INDIR; 22618236Slinton p->nodetype = exp->nodetype; 22718236Slinton } 22818236Slinton dispose(exp); 22918236Slinton } else { 23018236Slinton p = exp; 23118236Slinton } 23218236Slinton return p; 2339681Slinton } 2349681Slinton 2359681Slinton /* 23618236Slinton * Create a node for renaming a node to a pointer type. 23718236Slinton */ 23818236Slinton 23918236Slinton public Node renameptr (p, t) 24018236Slinton Node p; 24118236Slinton Node t; 24218236Slinton { 24318236Slinton t->nodetype = newSymbol(nil, 0, PTR, t->nodetype, nil); 24418236Slinton p = build(O_TYPERENAME, p, t); 24518236Slinton } 24618236Slinton 24718236Slinton /* 2489681Slinton * Return the tree for a unary ampersand operator. 2499681Slinton */ 2509681Slinton 2519681Slinton public Node amper(p) 2529681Slinton Node p; 2539681Slinton { 2549681Slinton Node r; 2559681Slinton 2569681Slinton checkref(p); 2579681Slinton switch (p->op) { 2589681Slinton case O_RVAL: 25918236Slinton case O_INDIR: 2609681Slinton r = p->value.arg[0]; 26118236Slinton r->nodetype = t_addr; 26218236Slinton dispose(p); 2639681Slinton break; 2649681Slinton 26518236Slinton case O_TYPERENAME: 26618236Slinton r = p; 26718236Slinton r->nodetype = newSymbol(nil, 0, PTR, r->nodetype, nil); 26833339Sdonn r->nodetype->language = p->nodetype->language; 2699681Slinton break; 2709681Slinton 2719681Slinton case O_SYM: 2729681Slinton if (isblock(p->value.sym)) { 2739681Slinton r = build(O_LCON, codeloc(p->value.sym)); 2749681Slinton } else { 2759681Slinton r = build(O_LCON, address(p->value.sym, nil)); 2769681Slinton } 27718236Slinton r->nodetype = t_addr; 27818236Slinton dispose(p); 2799681Slinton break; 2809681Slinton 2819681Slinton case O_DOT: 2829681Slinton r = p; 28318236Slinton r->nodetype = t_addr; 2849681Slinton break; 2859681Slinton 2869681Slinton default: 2879681Slinton beginerrmsg(); 28818236Slinton fprintf(stderr, "expected variable, found \""); 2899681Slinton prtree(stderr, p); 29018236Slinton fprintf(stderr, "\""); 2919681Slinton tfree(p); 2929681Slinton enderrmsg(); 2939681Slinton /* NOTREACHED */ 2949681Slinton } 2959681Slinton return r; 2969681Slinton } 2979681Slinton 2989681Slinton /* 2999681Slinton * Create a "concrete" version of a node. 3009681Slinton * This is necessary when the type of the node contains 3019681Slinton * an unresolved type reference. 3029681Slinton */ 3039681Slinton 3049681Slinton public Node concrete(p) 3059681Slinton Node p; 3069681Slinton { 3079681Slinton findtype(p->nodetype); 3089681Slinton return build(O_INDIR, p); 3099681Slinton } 3109681Slinton 3119681Slinton /* 31218236Slinton * Create a command list from a single command. 31318236Slinton */ 31418236Slinton 31518236Slinton public Cmdlist buildcmdlist(cmd) 31618236Slinton Command cmd; 31718236Slinton { 31818236Slinton Cmdlist cmdlist; 31918236Slinton 32018236Slinton cmdlist = list_alloc(); 32118236Slinton cmdlist_append(cmd, cmdlist); 32218236Slinton return cmdlist; 32318236Slinton } 32418236Slinton 32518236Slinton /* 3269681Slinton * Print out a command. 3279681Slinton */ 3289681Slinton 3299681Slinton public printcmd(f, cmd) 3309681Slinton File f; 3319681Slinton Command cmd; 3329681Slinton { 3339681Slinton register Integer i; 3349681Slinton register Command c; 3359681Slinton register Node p; 3369681Slinton 3379681Slinton switch (cmd->op) { 3389681Slinton case O_PRINTIFCHANGED: 3399681Slinton case O_PRINTSRCPOS: 3409681Slinton case O_STOPIFCHANGED: 3419681Slinton case O_TRACEON: 3429681Slinton break; 3439681Slinton 3449681Slinton case O_STEP: 3459681Slinton if (cmd->value.step.skipcalls) { 3469681Slinton fprintf(f, "next"); 3479681Slinton } else { 3489681Slinton fprintf(f, "step"); 3499681Slinton } 3509681Slinton if (not cmd->value.step.source) { 3519681Slinton fprintf(f, "i"); 3529681Slinton } 3539681Slinton break; 3549681Slinton 3559681Slinton default: 3569681Slinton fprintf(f, "%s", opinfo[ord(cmd->op)].opstring); 3579681Slinton if (nargs(cmd->op) != 0) { 3589681Slinton fprintf(f, " "); 3599681Slinton } 3609681Slinton break; 3619681Slinton } 3629681Slinton switch (cmd->op) { 3639681Slinton case O_PRINTCALL: 3649681Slinton case O_PRINTRTN: 3659681Slinton case O_PROCRTN: 3669681Slinton fprintf(f, "%s", symname(cmd->value.sym)); 3679681Slinton break; 3689681Slinton 3699681Slinton case O_PRINTSRCPOS: 3709681Slinton p = cmd->value.arg[0]; 3719681Slinton if (p != nil and p->op != O_QLINE) { 3729681Slinton printf("trace "); 3739681Slinton prtree(f, p); 3749681Slinton } 3759681Slinton break; 3769681Slinton 3779681Slinton case O_CHFILE: 3789681Slinton case O_EDIT: 3799681Slinton case O_SOURCE: 3809681Slinton fprintf(f, "%s", cmd->value.scon); 3819681Slinton break; 3829681Slinton 38318236Slinton case O_CATCH: 38418236Slinton case O_IGNORE: 3859681Slinton case O_TRACEOFF: 3869681Slinton fprintf(f, "%d", cmd->value.lcon); 3879681Slinton break; 3889681Slinton 3899681Slinton case O_ADDEVENT: 3909681Slinton case O_ONCE: 3919681Slinton case O_IF: 3929681Slinton fprintf(f, " "); 3939681Slinton prtree(f, cmd->value.event.cond); 3949681Slinton fprintf(f, " { "); 3959681Slinton foreach (Command, c, cmd->value.event.actions) 3969681Slinton printcmd(f, c); 3979681Slinton if (not list_islast()) { 3989681Slinton fprintf(f, ";"); 3999681Slinton } 4009681Slinton endfor 40130798Sbostic fprintf(f, "%s }", opinfo[ord(cmd->op)].opstring); 4029681Slinton break; 4039681Slinton 4049681Slinton case O_TRACEON: 4059681Slinton print_tracestop(f, cmd); 4069681Slinton break; 4079681Slinton 4089681Slinton case O_EXAMINE: 4099681Slinton prtree(f, cmd->value.examine.beginaddr); 4109681Slinton if (cmd->value.examine.endaddr != nil) { 4119681Slinton fprintf(f, ","); 4129681Slinton prtree(f, cmd->value.examine.endaddr); 4139681Slinton } 4149681Slinton fprintf(f, "/"); 4159681Slinton if (cmd->value.examine.count > 1) { 4169681Slinton fprintf(f, "%d", cmd->value.examine.count); 4179681Slinton } 4189681Slinton fprintf("%s", cmd->value.examine.mode); 4199681Slinton break; 4209681Slinton 4219681Slinton default: 4229681Slinton if (nargs(cmd->op) != 0) { 4239681Slinton i = 0; 4249681Slinton for (;;) { 4259681Slinton prtree(f, cmd->value.arg[i]); 4269681Slinton ++i; 4279681Slinton if (i >= nargs(cmd->op)) break; 4289681Slinton fprintf(f, " "); 4299681Slinton } 4309681Slinton } 4319681Slinton break; 4329681Slinton } 4339681Slinton } 4349681Slinton 4359681Slinton /* 4369681Slinton * Print out a trace/stop command name. 4379681Slinton */ 4389681Slinton 43914446Slinton #define fprintI(f, b) { if (b) fprintf(f, "i"); } 44014446Slinton 4419681Slinton private print_tracestop(f, cmd) 4429681Slinton File f; 4439681Slinton Command cmd; 4449681Slinton { 4459681Slinton register Command c, ifcmd, stopcmd; 4469681Slinton Boolean done; 4479681Slinton 4489681Slinton done = false; 4499681Slinton ifcmd = list_element(Command, list_head(cmd->value.trace.actions)); 4509681Slinton checkref(ifcmd); 4519681Slinton if (ifcmd->op == O_IF) { 4529681Slinton stopcmd = list_element(Command, list_head(ifcmd->value.event.actions)); 4539681Slinton checkref(stopcmd); 4549681Slinton if (stopcmd->op == O_STOPX) { 45514446Slinton fprintf(f, "stop"); 45614446Slinton fprintI(f, cmd->value.trace.inst); 45714446Slinton fprintf(f, " if "); 4589681Slinton prtree(f, ifcmd->value.event.cond); 4599681Slinton done = true; 4609681Slinton } 46114446Slinton } else if (ifcmd->op == O_STOPIFCHANGED) { 46214446Slinton fprintf(f, "stop"); 46314446Slinton fprintI(f, cmd->value.trace.inst); 46414446Slinton fprintf(f, " "); 46514446Slinton prtree(f, ifcmd->value.arg[0]); 46614446Slinton done = true; 4679681Slinton } 4689681Slinton if (not done) { 4699681Slinton fprintf(f, "%s ", cmd->value.trace.inst ? "tracei" : "trace"); 4709681Slinton foreach (Command, c, cmd->value.trace.actions) 4719681Slinton printcmd(f, c); 4729681Slinton if (not list_islast()) { 4739681Slinton fprintf(f, ";"); 4749681Slinton } 4759681Slinton endfor 4769681Slinton } 4779681Slinton } 4789681Slinton 4799681Slinton /* 48014446Slinton * Print out a tree. 4819681Slinton */ 4829681Slinton 4839681Slinton public prtree(f, p) 4849681Slinton File f; 4859681Slinton register Node p; 4869681Slinton { 4879681Slinton register Node q; 4889681Slinton Operator op; 4899681Slinton 4909681Slinton if (p != nil) { 4919681Slinton op = p->op; 4929681Slinton if (ord(op) > ord(O_LASTOP)) { 4939681Slinton panic("bad op %d in prtree", p->op); 4949681Slinton } 4959681Slinton switch (op) { 4969681Slinton case O_NAME: 4979681Slinton fprintf(f, "%s", ident(p->value.name)); 4989681Slinton break; 4999681Slinton 5009681Slinton case O_SYM: 5019681Slinton printname(f, p->value.sym); 5029681Slinton break; 5039681Slinton 5049681Slinton case O_QLINE: 5059681Slinton if (nlhdr.nfiles > 1) { 5069681Slinton prtree(f, p->value.arg[0]); 5079681Slinton fprintf(f, ":"); 5089681Slinton } 5099681Slinton prtree(f, p->value.arg[1]); 5109681Slinton break; 5119681Slinton 5129681Slinton case O_LCON: 51318236Slinton fprintf(f, "%d", p->value.lcon); 5149681Slinton break; 5159681Slinton 51618236Slinton case O_CCON: 51718236Slinton fprintf(f, "'%c'", p->value.lcon); 51818236Slinton break; 51918236Slinton 5209681Slinton case O_FCON: 5219681Slinton fprintf(f, "%g", p->value.fcon); 5229681Slinton break; 5239681Slinton 5249681Slinton case O_SCON: 5259681Slinton fprintf(f, "\"%s\"", p->value.scon); 5269681Slinton break; 5279681Slinton 5289681Slinton case O_INDEX: 5299681Slinton prtree(f, p->value.arg[0]); 5309681Slinton fprintf(f, "["); 5319681Slinton prtree(f, p->value.arg[1]); 5329681Slinton fprintf(f, "]"); 5339681Slinton break; 5349681Slinton 5359681Slinton case O_COMMA: 5369681Slinton prtree(f, p->value.arg[0]); 5379681Slinton if (p->value.arg[1] != nil) { 5389681Slinton fprintf(f, ", "); 5399681Slinton prtree(f, p->value.arg[1]); 5409681Slinton } 5419681Slinton break; 5429681Slinton 5439681Slinton case O_RVAL: 5449681Slinton case O_ITOF: 5459681Slinton prtree(f, p->value.arg[0]); 5469681Slinton break; 5479681Slinton 5489681Slinton case O_CALL: 5499681Slinton prtree(f, p->value.arg[0]); 5509681Slinton if (p->value.arg[1]!= nil) { 5519681Slinton fprintf(f, "("); 5529681Slinton prtree(f, p->value.arg[1]); 5539681Slinton fprintf(f, ")"); 5549681Slinton } 5559681Slinton break; 5569681Slinton 5579681Slinton case O_INDIR: 55818236Slinton prtree(f, p->value.arg[0]); 55918236Slinton fprintf(f, "^"); 5609681Slinton break; 5619681Slinton 5629681Slinton case O_DOT: 56318236Slinton prtree(f, p->value.arg[0]); 5649681Slinton fprintf(f, ".%s", symname(p->value.arg[1]->value.sym)); 5659681Slinton break; 5669681Slinton 56718236Slinton case O_TYPERENAME: 56818236Slinton prtree(f, p->value.arg[1]); 56918236Slinton fprintf(f, "("); 57018236Slinton prtree(f, p->value.arg[0]); 57118236Slinton fprintf(f, ")"); 57218236Slinton break; 57318236Slinton 5749681Slinton default: 5759681Slinton switch (degree(op)) { 5769681Slinton case BINARY: 5779681Slinton prtree(f, p->value.arg[0]); 5789681Slinton fprintf(f, "%s", opinfo[ord(op)].opstring); 5799681Slinton prtree(f, p->value.arg[1]); 5809681Slinton break; 5819681Slinton 5829681Slinton case UNARY: 5839681Slinton fprintf(f, "%s", opinfo[ord(op)].opstring); 5849681Slinton prtree(f, p->value.arg[0]); 5859681Slinton break; 5869681Slinton 5879681Slinton default: 58818236Slinton if (opinfo[ord(op)].opstring == nil) { 58918236Slinton fprintf(f, "[op %d]", ord(op)); 59018236Slinton } else { 59118236Slinton fprintf(f, "%s", opinfo[ord(op)].opstring); 59218236Slinton } 59318236Slinton break; 5949681Slinton } 5959681Slinton break; 5969681Slinton } 5979681Slinton } 5989681Slinton } 5999681Slinton 6009681Slinton /* 6019681Slinton * Free storage associated with a tree. 6029681Slinton */ 6039681Slinton 6049681Slinton public tfree(p) 6059681Slinton Node p; 6069681Slinton { 6079681Slinton Integer i; 6089681Slinton 6099681Slinton if (p == nil) { 6109681Slinton return; 6119681Slinton } 6129681Slinton switch (p->op) { 6139681Slinton case O_QLINE: 6149681Slinton dispose(p->value.arg[0]->value.scon); 6159681Slinton dispose(p->value.arg[0]); 6169681Slinton tfree(p->value.arg[1]); 6179681Slinton break; 6189681Slinton 6199681Slinton case O_SCON: 6209681Slinton unmkstring(p->nodetype); 6219681Slinton dispose(p->nodetype); 6229681Slinton dispose(p->value.scon); 6239681Slinton break; 6249681Slinton 6259681Slinton default: 6269681Slinton for (i = 0; i < nargs(p->op); i++) { 6279681Slinton tfree(p->value.arg[i]); 6289681Slinton } 6299681Slinton break; 6309681Slinton } 6319681Slinton dispose(p); 6329681Slinton } 633