|
|
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.1 (Berkeley) 5/31/85"; ! 9: #endif not lint ! 10: ! 11: static char rcsid[] = "$Header: tree.c,v 1.5 84/12/26 10:42:55 linton 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: break; ! 260: ! 261: case O_SYM: ! 262: if (isblock(p->value.sym)) { ! 263: r = build(O_LCON, codeloc(p->value.sym)); ! 264: } else { ! 265: r = build(O_LCON, address(p->value.sym, nil)); ! 266: } ! 267: r->nodetype = t_addr; ! 268: dispose(p); ! 269: break; ! 270: ! 271: case O_DOT: ! 272: r = p; ! 273: r->nodetype = t_addr; ! 274: break; ! 275: ! 276: default: ! 277: beginerrmsg(); ! 278: fprintf(stderr, "expected variable, found \""); ! 279: prtree(stderr, p); ! 280: fprintf(stderr, "\""); ! 281: tfree(p); ! 282: enderrmsg(); ! 283: /* NOTREACHED */ ! 284: } ! 285: return r; ! 286: } ! 287: ! 288: /* ! 289: * Create a "concrete" version of a node. ! 290: * This is necessary when the type of the node contains ! 291: * an unresolved type reference. ! 292: */ ! 293: ! 294: public Node concrete(p) ! 295: Node p; ! 296: { ! 297: findtype(p->nodetype); ! 298: return build(O_INDIR, p); ! 299: } ! 300: ! 301: /* ! 302: * Create a command list from a single command. ! 303: */ ! 304: ! 305: public Cmdlist buildcmdlist(cmd) ! 306: Command cmd; ! 307: { ! 308: Cmdlist cmdlist; ! 309: ! 310: cmdlist = list_alloc(); ! 311: cmdlist_append(cmd, cmdlist); ! 312: return cmdlist; ! 313: } ! 314: ! 315: /* ! 316: * Print out a command. ! 317: */ ! 318: ! 319: public printcmd(f, cmd) ! 320: File f; ! 321: Command cmd; ! 322: { ! 323: register Integer i; ! 324: register Command c; ! 325: register Node p; ! 326: ! 327: switch (cmd->op) { ! 328: case O_PRINTIFCHANGED: ! 329: case O_PRINTSRCPOS: ! 330: case O_STOPIFCHANGED: ! 331: case O_TRACEON: ! 332: break; ! 333: ! 334: case O_STEP: ! 335: if (cmd->value.step.skipcalls) { ! 336: fprintf(f, "next"); ! 337: } else { ! 338: fprintf(f, "step"); ! 339: } ! 340: if (not cmd->value.step.source) { ! 341: fprintf(f, "i"); ! 342: } ! 343: break; ! 344: ! 345: default: ! 346: fprintf(f, "%s", opinfo[ord(cmd->op)].opstring); ! 347: if (nargs(cmd->op) != 0) { ! 348: fprintf(f, " "); ! 349: } ! 350: break; ! 351: } ! 352: switch (cmd->op) { ! 353: case O_PRINTCALL: ! 354: case O_PRINTRTN: ! 355: case O_PROCRTN: ! 356: fprintf(f, "%s", symname(cmd->value.sym)); ! 357: break; ! 358: ! 359: case O_PRINTSRCPOS: ! 360: p = cmd->value.arg[0]; ! 361: if (p != nil and p->op != O_QLINE) { ! 362: printf("trace "); ! 363: prtree(f, p); ! 364: } ! 365: break; ! 366: ! 367: case O_CHFILE: ! 368: case O_EDIT: ! 369: case O_SOURCE: ! 370: fprintf(f, "%s", cmd->value.scon); ! 371: break; ! 372: ! 373: case O_CATCH: ! 374: case O_IGNORE: ! 375: case O_TRACEOFF: ! 376: fprintf(f, "%d", cmd->value.lcon); ! 377: break; ! 378: ! 379: case O_ADDEVENT: ! 380: case O_ONCE: ! 381: case O_IF: ! 382: fprintf(f, " "); ! 383: prtree(f, cmd->value.event.cond); ! 384: fprintf(f, " { "); ! 385: foreach (Command, c, cmd->value.event.actions) ! 386: printcmd(f, c); ! 387: if (not list_islast()) { ! 388: fprintf(f, ";"); ! 389: } ! 390: endfor ! 391: fprintf(f, " }", opinfo[ord(cmd->op)].opstring); ! 392: break; ! 393: ! 394: case O_TRACEON: ! 395: print_tracestop(f, cmd); ! 396: break; ! 397: ! 398: case O_EXAMINE: ! 399: prtree(f, cmd->value.examine.beginaddr); ! 400: if (cmd->value.examine.endaddr != nil) { ! 401: fprintf(f, ","); ! 402: prtree(f, cmd->value.examine.endaddr); ! 403: } ! 404: fprintf(f, "/"); ! 405: if (cmd->value.examine.count > 1) { ! 406: fprintf(f, "%d", cmd->value.examine.count); ! 407: } ! 408: fprintf("%s", cmd->value.examine.mode); ! 409: break; ! 410: ! 411: default: ! 412: if (nargs(cmd->op) != 0) { ! 413: i = 0; ! 414: for (;;) { ! 415: prtree(f, cmd->value.arg[i]); ! 416: ++i; ! 417: if (i >= nargs(cmd->op)) break; ! 418: fprintf(f, " "); ! 419: } ! 420: } ! 421: break; ! 422: } ! 423: } ! 424: ! 425: /* ! 426: * Print out a trace/stop command name. ! 427: */ ! 428: ! 429: #define fprintI(f, b) { if (b) fprintf(f, "i"); } ! 430: ! 431: private print_tracestop(f, cmd) ! 432: File f; ! 433: Command cmd; ! 434: { ! 435: register Command c, ifcmd, stopcmd; ! 436: Boolean done; ! 437: ! 438: done = false; ! 439: ifcmd = list_element(Command, list_head(cmd->value.trace.actions)); ! 440: checkref(ifcmd); ! 441: if (ifcmd->op == O_IF) { ! 442: stopcmd = list_element(Command, list_head(ifcmd->value.event.actions)); ! 443: checkref(stopcmd); ! 444: if (stopcmd->op == O_STOPX) { ! 445: fprintf(f, "stop"); ! 446: fprintI(f, cmd->value.trace.inst); ! 447: fprintf(f, " if "); ! 448: prtree(f, ifcmd->value.event.cond); ! 449: done = true; ! 450: } ! 451: } else if (ifcmd->op == O_STOPIFCHANGED) { ! 452: fprintf(f, "stop"); ! 453: fprintI(f, cmd->value.trace.inst); ! 454: fprintf(f, " "); ! 455: prtree(f, ifcmd->value.arg[0]); ! 456: done = true; ! 457: } ! 458: if (not done) { ! 459: fprintf(f, "%s ", cmd->value.trace.inst ? "tracei" : "trace"); ! 460: foreach (Command, c, cmd->value.trace.actions) ! 461: printcmd(f, c); ! 462: if (not list_islast()) { ! 463: fprintf(f, ";"); ! 464: } ! 465: endfor ! 466: } ! 467: } ! 468: ! 469: /* ! 470: * Print out a tree. ! 471: */ ! 472: ! 473: public prtree(f, p) ! 474: File f; ! 475: register Node p; ! 476: { ! 477: register Node q; ! 478: Operator op; ! 479: ! 480: if (p != nil) { ! 481: op = p->op; ! 482: if (ord(op) > ord(O_LASTOP)) { ! 483: panic("bad op %d in prtree", p->op); ! 484: } ! 485: switch (op) { ! 486: case O_NAME: ! 487: fprintf(f, "%s", ident(p->value.name)); ! 488: break; ! 489: ! 490: case O_SYM: ! 491: printname(f, p->value.sym); ! 492: break; ! 493: ! 494: case O_QLINE: ! 495: if (nlhdr.nfiles > 1) { ! 496: prtree(f, p->value.arg[0]); ! 497: fprintf(f, ":"); ! 498: } ! 499: prtree(f, p->value.arg[1]); ! 500: break; ! 501: ! 502: case O_LCON: ! 503: fprintf(f, "%d", p->value.lcon); ! 504: break; ! 505: ! 506: case O_CCON: ! 507: fprintf(f, "'%c'", p->value.lcon); ! 508: break; ! 509: ! 510: case O_FCON: ! 511: fprintf(f, "%g", p->value.fcon); ! 512: break; ! 513: ! 514: case O_SCON: ! 515: fprintf(f, "\"%s\"", p->value.scon); ! 516: break; ! 517: ! 518: case O_INDEX: ! 519: prtree(f, p->value.arg[0]); ! 520: fprintf(f, "["); ! 521: prtree(f, p->value.arg[1]); ! 522: fprintf(f, "]"); ! 523: break; ! 524: ! 525: case O_COMMA: ! 526: prtree(f, p->value.arg[0]); ! 527: if (p->value.arg[1] != nil) { ! 528: fprintf(f, ", "); ! 529: prtree(f, p->value.arg[1]); ! 530: } ! 531: break; ! 532: ! 533: case O_RVAL: ! 534: case O_ITOF: ! 535: prtree(f, p->value.arg[0]); ! 536: break; ! 537: ! 538: case O_CALL: ! 539: prtree(f, p->value.arg[0]); ! 540: if (p->value.arg[1]!= nil) { ! 541: fprintf(f, "("); ! 542: prtree(f, p->value.arg[1]); ! 543: fprintf(f, ")"); ! 544: } ! 545: break; ! 546: ! 547: case O_INDIR: ! 548: prtree(f, p->value.arg[0]); ! 549: fprintf(f, "^"); ! 550: break; ! 551: ! 552: case O_DOT: ! 553: prtree(f, p->value.arg[0]); ! 554: fprintf(f, ".%s", symname(p->value.arg[1]->value.sym)); ! 555: break; ! 556: ! 557: case O_TYPERENAME: ! 558: prtree(f, p->value.arg[1]); ! 559: fprintf(f, "("); ! 560: prtree(f, p->value.arg[0]); ! 561: fprintf(f, ")"); ! 562: break; ! 563: ! 564: default: ! 565: switch (degree(op)) { ! 566: case BINARY: ! 567: prtree(f, p->value.arg[0]); ! 568: fprintf(f, "%s", opinfo[ord(op)].opstring); ! 569: prtree(f, p->value.arg[1]); ! 570: break; ! 571: ! 572: case UNARY: ! 573: fprintf(f, "%s", opinfo[ord(op)].opstring); ! 574: prtree(f, p->value.arg[0]); ! 575: break; ! 576: ! 577: default: ! 578: if (opinfo[ord(op)].opstring == nil) { ! 579: fprintf(f, "[op %d]", ord(op)); ! 580: } else { ! 581: fprintf(f, "%s", opinfo[ord(op)].opstring); ! 582: } ! 583: break; ! 584: } ! 585: break; ! 586: } ! 587: } ! 588: } ! 589: ! 590: /* ! 591: * Free storage associated with a tree. ! 592: */ ! 593: ! 594: public tfree(p) ! 595: Node p; ! 596: { ! 597: Integer i; ! 598: ! 599: if (p == nil) { ! 600: return; ! 601: } ! 602: switch (p->op) { ! 603: case O_QLINE: ! 604: dispose(p->value.arg[0]->value.scon); ! 605: dispose(p->value.arg[0]); ! 606: tfree(p->value.arg[1]); ! 607: break; ! 608: ! 609: case O_SCON: ! 610: unmkstring(p->nodetype); ! 611: dispose(p->nodetype); ! 612: dispose(p->value.scon); ! 613: break; ! 614: ! 615: default: ! 616: for (i = 0; i < nargs(p->op); i++) { ! 617: tfree(p->value.arg[i]); ! 618: } ! 619: break; ! 620: } ! 621: dispose(p); ! 622: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.