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