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