|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)tree.c 5.3 (Berkeley) 1/12/88"; ! 9: #endif not lint ! 10: ! 11: static char rcsid[] = "$Header: tree.c,v 1.3 87/07/08 21:38:59 donn Exp $"; ! 12: ! 13: /* ! 14: * Parse tree management. ! 15: */ ! 16: ! 17: #include "defs.h" ! 18: #include "tree.h" ! 19: #include "operators.h" ! 20: #include "debug.h" ! 21: #include "eval.h" ! 22: #include "events.h" ! 23: #include "symbols.h" ! 24: #include "scanner.h" ! 25: #include "source.h" ! 26: #include "object.h" ! 27: #include "mappings.h" ! 28: #include "process.h" ! 29: #include "machine.h" ! 30: ! 31: #ifndef public ! 32: #include "lists.h" ! 33: ! 34: typedef struct Node *Node; ! 35: typedef Node Command; ! 36: typedef List Cmdlist; ! 37: ! 38: #include "operators.h" ! 39: #include "symbols.h" ! 40: #include "events.h" ! 41: ! 42: #define MAXNARGS 5 ! 43: ! 44: struct Node { ! 45: Operator op; ! 46: Symbol nodetype; ! 47: union treevalue { ! 48: Symbol sym; ! 49: Name name; ! 50: long lcon; ! 51: double fcon; ! 52: String scon; ! 53: Node arg[MAXNARGS]; ! 54: struct { ! 55: Node cond; ! 56: Cmdlist actions; ! 57: } event; ! 58: struct { ! 59: Boolean inst; ! 60: Event event; ! 61: Cmdlist actions; ! 62: } trace; ! 63: struct { ! 64: Boolean source; ! 65: Boolean skipcalls; ! 66: } step; ! 67: struct { ! 68: String mode; ! 69: Node beginaddr; ! 70: Node endaddr; ! 71: Integer count; ! 72: } examine; ! 73: } value; ! 74: }; ! 75: ! 76: #define evalcmd(cmd) eval(cmd) ! 77: #define cmdlist_append(cmd, cl) list_append(list_item(cmd), nil, cl) ! 78: ! 79: #endif ! 80: ! 81: typedef char *Arglist; ! 82: ! 83: #define nextarg(type) ((type *) (ap += sizeof(type)))[-1] ! 84: ! 85: /* ! 86: * Build a tree. ! 87: */ ! 88: ! 89: /* VARARGS1 */ ! 90: public Node build(op, args) ! 91: Operator op; ! 92: { ! 93: register Node p, q; ! 94: register Arglist ap; ! 95: Integer i; ! 96: ! 97: p = new(Node); ! 98: p->op = op; ! 99: p->nodetype = nil; ! 100: ap = (Arglist) &args; ! 101: switch (op) { ! 102: case O_NAME: ! 103: p->value.name = nextarg(Name); ! 104: break; ! 105: ! 106: case O_SYM: ! 107: case O_PRINTCALL: ! 108: case O_PRINTRTN: ! 109: case O_PROCRTN: ! 110: p->value.sym = nextarg(Symbol); ! 111: break; ! 112: ! 113: case O_DEBUG: ! 114: case O_LCON: ! 115: case O_CCON: ! 116: case O_CONT: ! 117: case O_CATCH: ! 118: case O_IGNORE: ! 119: case O_TRACEOFF: ! 120: p->value.lcon = nextarg(long); ! 121: break; ! 122: ! 123: case O_FCON: ! 124: p->value.fcon = nextarg(double); ! 125: break; ! 126: ! 127: case O_SCON: ! 128: case O_CHFILE: ! 129: case O_EDIT: ! 130: case O_SOURCE: ! 131: p->value.scon = nextarg(String); ! 132: break; ! 133: ! 134: case O_RVAL: ! 135: case O_INDIR: ! 136: p->value.arg[0] = nextarg(Node); ! 137: break; ! 138: ! 139: case O_CALL: ! 140: q = nextarg(Node); ! 141: if (q->op == O_SYM and ! 142: (q->value.sym->class == TYPE or q->value.sym->class == TAG) ! 143: ) { ! 144: p->op = O_TYPERENAME; ! 145: p->value.arg[0] = nextarg(Node); ! 146: p->value.arg[1] = q; ! 147: q = p->value.arg[0]; ! 148: if (q->value.arg[1] != nil) { ! 149: error("too many arguments to type rename"); ! 150: } ! 151: p->value.arg[0] = q->value.arg[0]; ! 152: } else { ! 153: p->value.arg[0] = q; ! 154: p->value.arg[1] = nextarg(Node); ! 155: } ! 156: break; ! 157: ! 158: case O_ADDEVENT: ! 159: case O_ONCE: ! 160: case O_IF: ! 161: p->value.event.cond = nextarg(Node); ! 162: p->value.event.actions = nextarg(Cmdlist); ! 163: break; ! 164: ! 165: case O_TRACEON: ! 166: p->value.trace.inst = nextarg(Boolean); ! 167: p->value.trace.event = nil; ! 168: p->value.trace.actions = nextarg(Cmdlist); ! 169: break; ! 170: ! 171: case O_STEP: ! 172: p->value.step.source = nextarg(Boolean); ! 173: p->value.step.skipcalls = nextarg(Boolean); ! 174: break; ! 175: ! 176: case O_EXAMINE: ! 177: p->value.examine.mode = nextarg(String); ! 178: p->value.examine.beginaddr = nextarg(Node); ! 179: p->value.examine.endaddr = nextarg(Node); ! 180: p->value.examine.count = nextarg(Integer); ! 181: break; ! 182: ! 183: default: ! 184: for (i = 0; i < nargs(op); i++) { ! 185: p->value.arg[i] = nextarg(Node); ! 186: } ! 187: break; ! 188: } ! 189: check(p); ! 190: assigntypes(p); ! 191: if (tracetree) { ! 192: printf("built %s node 0x%x with arg[0] 0x%x arg[1] 0x%x\n", ! 193: opname(p->op), p, p->value.arg[0], p->value.arg[1]); ! 194: fflush(stdout); ! 195: } ! 196: return p; ! 197: } ! 198: ! 199: /* ! 200: * Strip away indirection from a node, thus returning a node for ! 201: * interpreting the expression as an lvalue. ! 202: */ ! 203: ! 204: public Node unrval (exp) ! 205: Node exp; ! 206: { ! 207: Node p; ! 208: Symbol t; ! 209: ! 210: if (exp->op == O_RVAL) { ! 211: p = exp->value.arg[0]; ! 212: dispose(exp); ! 213: } else if (exp->op == O_INDIR) { ! 214: p = exp->value.arg[0]; ! 215: if (p->op == O_RVAL) { ! 216: p->op = O_INDIR; ! 217: p->nodetype = exp->nodetype; ! 218: } ! 219: dispose(exp); ! 220: } else { ! 221: p = exp; ! 222: } ! 223: return p; ! 224: } ! 225: ! 226: /* ! 227: * Create a node for renaming a node to a pointer type. ! 228: */ ! 229: ! 230: public Node renameptr (p, t) ! 231: Node p; ! 232: Node t; ! 233: { ! 234: t->nodetype = newSymbol(nil, 0, PTR, t->nodetype, nil); ! 235: p = build(O_TYPERENAME, p, t); ! 236: } ! 237: ! 238: /* ! 239: * Return the tree for a unary ampersand operator. ! 240: */ ! 241: ! 242: public Node amper(p) ! 243: Node p; ! 244: { ! 245: Node r; ! 246: ! 247: checkref(p); ! 248: switch (p->op) { ! 249: case O_RVAL: ! 250: case O_INDIR: ! 251: r = p->value.arg[0]; ! 252: r->nodetype = t_addr; ! 253: dispose(p); ! 254: break; ! 255: ! 256: case O_TYPERENAME: ! 257: r = p; ! 258: r->nodetype = newSymbol(nil, 0, PTR, r->nodetype, nil); ! 259: r->nodetype->language = p->nodetype->language; ! 260: break; ! 261: ! 262: case O_SYM: ! 263: if (isblock(p->value.sym)) { ! 264: r = build(O_LCON, codeloc(p->value.sym)); ! 265: } else { ! 266: r = build(O_LCON, address(p->value.sym, nil)); ! 267: } ! 268: r->nodetype = t_addr; ! 269: dispose(p); ! 270: break; ! 271: ! 272: case O_DOT: ! 273: r = p; ! 274: r->nodetype = t_addr; ! 275: break; ! 276: ! 277: default: ! 278: beginerrmsg(); ! 279: fprintf(stderr, "expected variable, found \""); ! 280: prtree(stderr, p); ! 281: fprintf(stderr, "\""); ! 282: tfree(p); ! 283: enderrmsg(); ! 284: /* NOTREACHED */ ! 285: } ! 286: return r; ! 287: } ! 288: ! 289: /* ! 290: * Create a "concrete" version of a node. ! 291: * This is necessary when the type of the node contains ! 292: * an unresolved type reference. ! 293: */ ! 294: ! 295: public Node concrete(p) ! 296: Node p; ! 297: { ! 298: findtype(p->nodetype); ! 299: return build(O_INDIR, p); ! 300: } ! 301: ! 302: /* ! 303: * Create a command list from a single command. ! 304: */ ! 305: ! 306: public Cmdlist buildcmdlist(cmd) ! 307: Command cmd; ! 308: { ! 309: Cmdlist cmdlist; ! 310: ! 311: cmdlist = list_alloc(); ! 312: cmdlist_append(cmd, cmdlist); ! 313: return cmdlist; ! 314: } ! 315: ! 316: /* ! 317: * Print out a command. ! 318: */ ! 319: ! 320: public printcmd(f, cmd) ! 321: File f; ! 322: Command cmd; ! 323: { ! 324: register Integer i; ! 325: register Command c; ! 326: register Node p; ! 327: ! 328: switch (cmd->op) { ! 329: case O_PRINTIFCHANGED: ! 330: case O_PRINTSRCPOS: ! 331: case O_STOPIFCHANGED: ! 332: case O_TRACEON: ! 333: break; ! 334: ! 335: case O_STEP: ! 336: if (cmd->value.step.skipcalls) { ! 337: fprintf(f, "next"); ! 338: } else { ! 339: fprintf(f, "step"); ! 340: } ! 341: if (not cmd->value.step.source) { ! 342: fprintf(f, "i"); ! 343: } ! 344: break; ! 345: ! 346: default: ! 347: fprintf(f, "%s", opinfo[ord(cmd->op)].opstring); ! 348: if (nargs(cmd->op) != 0) { ! 349: fprintf(f, " "); ! 350: } ! 351: break; ! 352: } ! 353: switch (cmd->op) { ! 354: case O_PRINTCALL: ! 355: case O_PRINTRTN: ! 356: case O_PROCRTN: ! 357: fprintf(f, "%s", symname(cmd->value.sym)); ! 358: break; ! 359: ! 360: case O_PRINTSRCPOS: ! 361: p = cmd->value.arg[0]; ! 362: if (p != nil and p->op != O_QLINE) { ! 363: printf("trace "); ! 364: prtree(f, p); ! 365: } ! 366: break; ! 367: ! 368: case O_CHFILE: ! 369: case O_EDIT: ! 370: case O_SOURCE: ! 371: fprintf(f, "%s", cmd->value.scon); ! 372: break; ! 373: ! 374: case O_CATCH: ! 375: case O_IGNORE: ! 376: case O_TRACEOFF: ! 377: fprintf(f, "%d", cmd->value.lcon); ! 378: break; ! 379: ! 380: case O_ADDEVENT: ! 381: case O_ONCE: ! 382: case O_IF: ! 383: fprintf(f, " "); ! 384: prtree(f, cmd->value.event.cond); ! 385: fprintf(f, " { "); ! 386: foreach (Command, c, cmd->value.event.actions) ! 387: printcmd(f, c); ! 388: if (not list_islast()) { ! 389: fprintf(f, ";"); ! 390: } ! 391: endfor ! 392: fprintf(f, "%s }", opinfo[ord(cmd->op)].opstring); ! 393: break; ! 394: ! 395: case O_TRACEON: ! 396: print_tracestop(f, cmd); ! 397: break; ! 398: ! 399: case O_EXAMINE: ! 400: prtree(f, cmd->value.examine.beginaddr); ! 401: if (cmd->value.examine.endaddr != nil) { ! 402: fprintf(f, ","); ! 403: prtree(f, cmd->value.examine.endaddr); ! 404: } ! 405: fprintf(f, "/"); ! 406: if (cmd->value.examine.count > 1) { ! 407: fprintf(f, "%d", cmd->value.examine.count); ! 408: } ! 409: fprintf("%s", cmd->value.examine.mode); ! 410: break; ! 411: ! 412: default: ! 413: if (nargs(cmd->op) != 0) { ! 414: i = 0; ! 415: for (;;) { ! 416: prtree(f, cmd->value.arg[i]); ! 417: ++i; ! 418: if (i >= nargs(cmd->op)) break; ! 419: fprintf(f, " "); ! 420: } ! 421: } ! 422: break; ! 423: } ! 424: } ! 425: ! 426: /* ! 427: * Print out a trace/stop command name. ! 428: */ ! 429: ! 430: #define fprintI(f, b) { if (b) fprintf(f, "i"); } ! 431: ! 432: private print_tracestop(f, cmd) ! 433: File f; ! 434: Command cmd; ! 435: { ! 436: register Command c, ifcmd, stopcmd; ! 437: Boolean done; ! 438: ! 439: done = false; ! 440: ifcmd = list_element(Command, list_head(cmd->value.trace.actions)); ! 441: checkref(ifcmd); ! 442: if (ifcmd->op == O_IF) { ! 443: stopcmd = list_element(Command, list_head(ifcmd->value.event.actions)); ! 444: checkref(stopcmd); ! 445: if (stopcmd->op == O_STOPX) { ! 446: fprintf(f, "stop"); ! 447: fprintI(f, cmd->value.trace.inst); ! 448: fprintf(f, " if "); ! 449: prtree(f, ifcmd->value.event.cond); ! 450: done = true; ! 451: } ! 452: } else if (ifcmd->op == O_STOPIFCHANGED) { ! 453: fprintf(f, "stop"); ! 454: fprintI(f, cmd->value.trace.inst); ! 455: fprintf(f, " "); ! 456: prtree(f, ifcmd->value.arg[0]); ! 457: done = true; ! 458: } ! 459: if (not done) { ! 460: fprintf(f, "%s ", cmd->value.trace.inst ? "tracei" : "trace"); ! 461: foreach (Command, c, cmd->value.trace.actions) ! 462: printcmd(f, c); ! 463: if (not list_islast()) { ! 464: fprintf(f, ";"); ! 465: } ! 466: endfor ! 467: } ! 468: } ! 469: ! 470: /* ! 471: * Print out a tree. ! 472: */ ! 473: ! 474: public prtree(f, p) ! 475: File f; ! 476: register Node p; ! 477: { ! 478: register Node q; ! 479: Operator op; ! 480: ! 481: if (p != nil) { ! 482: op = p->op; ! 483: if (ord(op) > ord(O_LASTOP)) { ! 484: panic("bad op %d in prtree", p->op); ! 485: } ! 486: switch (op) { ! 487: case O_NAME: ! 488: fprintf(f, "%s", ident(p->value.name)); ! 489: break; ! 490: ! 491: case O_SYM: ! 492: printname(f, p->value.sym); ! 493: break; ! 494: ! 495: case O_QLINE: ! 496: if (nlhdr.nfiles > 1) { ! 497: prtree(f, p->value.arg[0]); ! 498: fprintf(f, ":"); ! 499: } ! 500: prtree(f, p->value.arg[1]); ! 501: break; ! 502: ! 503: case O_LCON: ! 504: fprintf(f, "%d", p->value.lcon); ! 505: break; ! 506: ! 507: case O_CCON: ! 508: fprintf(f, "'%c'", p->value.lcon); ! 509: break; ! 510: ! 511: case O_FCON: ! 512: fprintf(f, "%g", p->value.fcon); ! 513: break; ! 514: ! 515: case O_SCON: ! 516: fprintf(f, "\"%s\"", p->value.scon); ! 517: break; ! 518: ! 519: case O_INDEX: ! 520: prtree(f, p->value.arg[0]); ! 521: fprintf(f, "["); ! 522: prtree(f, p->value.arg[1]); ! 523: fprintf(f, "]"); ! 524: break; ! 525: ! 526: case O_COMMA: ! 527: prtree(f, p->value.arg[0]); ! 528: if (p->value.arg[1] != nil) { ! 529: fprintf(f, ", "); ! 530: prtree(f, p->value.arg[1]); ! 531: } ! 532: break; ! 533: ! 534: case O_RVAL: ! 535: case O_ITOF: ! 536: prtree(f, p->value.arg[0]); ! 537: break; ! 538: ! 539: case O_CALL: ! 540: prtree(f, p->value.arg[0]); ! 541: if (p->value.arg[1]!= nil) { ! 542: fprintf(f, "("); ! 543: prtree(f, p->value.arg[1]); ! 544: fprintf(f, ")"); ! 545: } ! 546: break; ! 547: ! 548: case O_INDIR: ! 549: prtree(f, p->value.arg[0]); ! 550: fprintf(f, "^"); ! 551: break; ! 552: ! 553: case O_DOT: ! 554: prtree(f, p->value.arg[0]); ! 555: fprintf(f, ".%s", symname(p->value.arg[1]->value.sym)); ! 556: break; ! 557: ! 558: case O_TYPERENAME: ! 559: prtree(f, p->value.arg[1]); ! 560: fprintf(f, "("); ! 561: prtree(f, p->value.arg[0]); ! 562: fprintf(f, ")"); ! 563: break; ! 564: ! 565: default: ! 566: switch (degree(op)) { ! 567: case BINARY: ! 568: prtree(f, p->value.arg[0]); ! 569: fprintf(f, "%s", opinfo[ord(op)].opstring); ! 570: prtree(f, p->value.arg[1]); ! 571: break; ! 572: ! 573: case UNARY: ! 574: fprintf(f, "%s", opinfo[ord(op)].opstring); ! 575: prtree(f, p->value.arg[0]); ! 576: break; ! 577: ! 578: default: ! 579: if (opinfo[ord(op)].opstring == nil) { ! 580: fprintf(f, "[op %d]", ord(op)); ! 581: } else { ! 582: fprintf(f, "%s", opinfo[ord(op)].opstring); ! 583: } ! 584: break; ! 585: } ! 586: break; ! 587: } ! 588: } ! 589: } ! 590: ! 591: /* ! 592: * Free storage associated with a tree. ! 593: */ ! 594: ! 595: public tfree(p) ! 596: Node p; ! 597: { ! 598: Integer i; ! 599: ! 600: if (p == nil) { ! 601: return; ! 602: } ! 603: switch (p->op) { ! 604: case O_QLINE: ! 605: dispose(p->value.arg[0]->value.scon); ! 606: dispose(p->value.arg[0]); ! 607: tfree(p->value.arg[1]); ! 608: break; ! 609: ! 610: case O_SCON: ! 611: unmkstring(p->nodetype); ! 612: dispose(p->nodetype); ! 613: dispose(p->value.scon); ! 614: break; ! 615: ! 616: default: ! 617: for (i = 0; i < nargs(p->op); i++) { ! 618: tfree(p->value.arg[i]); ! 619: } ! 620: break; ! 621: } ! 622: dispose(p); ! 623: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.