|
|
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[] = "@(#)printsym.c 5.5 (Berkeley) 1/12/88"; ! 9: #endif not lint ! 10: ! 11: static char rcsid[] = "$Header: printsym.c,v 1.4 87/04/15 00:23:35 donn Exp $"; ! 12: ! 13: /* ! 14: * Printing of symbolic information. ! 15: */ ! 16: ! 17: #include "defs.h" ! 18: #include "symbols.h" ! 19: #include "languages.h" ! 20: #include "printsym.h" ! 21: #include "tree.h" ! 22: #include "eval.h" ! 23: #include "mappings.h" ! 24: #include "process.h" ! 25: #include "runtime.h" ! 26: #include "machine.h" ! 27: #include "names.h" ! 28: #include "keywords.h" ! 29: #include "main.h" ! 30: #include <ctype.h> ! 31: ! 32: #ifndef public ! 33: #endif ! 34: ! 35: /* ! 36: * Maximum number of arguments to a function. ! 37: * This is used as a check for the possibility that the stack has been ! 38: * overwritten and therefore a saved argument pointer might indicate ! 39: * to an absurdly large number of arguments. ! 40: */ ! 41: ! 42: #define MAXARGSPASSED 20 ! 43: ! 44: /* ! 45: * Return a pointer to the string for the name of the class that ! 46: * the given symbol belongs to. ! 47: */ ! 48: ! 49: private String clname[] = { ! 50: "bad use", "constant", "type", "variable", "array", "array", ! 51: "dynarray", "subarray", "fileptr", "record", "field", ! 52: "procedure", "function", "funcvar", ! 53: "ref", "pointer", "file", "set", "range", "label", "withptr", ! 54: "scalar", "string", "program", "improper", "variant", ! 55: "procparam", "funcparam", "module", "tag", "common", "extref", "typeref" ! 56: }; ! 57: ! 58: public String classname(s) ! 59: Symbol s; ! 60: { ! 61: return clname[ord(s->class)]; ! 62: } ! 63: ! 64: /* ! 65: * Note the entry of the given block, unless it's the main program. ! 66: */ ! 67: ! 68: public printentry(s) ! 69: Symbol s; ! 70: { ! 71: if (s != program) { ! 72: printf("\nentering %s ", classname(s)); ! 73: printname(stdout, s); ! 74: printf("\n"); ! 75: } ! 76: } ! 77: ! 78: /* ! 79: * Note the exit of the given block ! 80: */ ! 81: ! 82: public printexit(s) ! 83: Symbol s; ! 84: { ! 85: if (s != program) { ! 86: printf("leaving %s ", classname(s)); ! 87: printname(stdout, s); ! 88: printf("\n\n"); ! 89: } ! 90: } ! 91: ! 92: /* ! 93: * Note the call of s from t. ! 94: */ ! 95: ! 96: public printcall(s, t) ! 97: Symbol s, t; ! 98: { ! 99: printf("calling "); ! 100: printname(stdout, s); ! 101: printparams(s, nil); ! 102: printf(" from %s ", classname(t)); ! 103: printname(stdout, t); ! 104: printf("\n"); ! 105: } ! 106: ! 107: /* ! 108: * Note the return from s. If s is a function, print the value ! 109: * it is returning. This is somewhat painful, since the function ! 110: * has actually just returned. ! 111: */ ! 112: ! 113: public printrtn(s) ! 114: Symbol s; ! 115: { ! 116: register Symbol t; ! 117: register int len; ! 118: Boolean isindirect; ! 119: ! 120: printf("returning "); ! 121: if (s->class == FUNC && (!istypename(s->type,"void"))) { ! 122: len = size(s->type); ! 123: if (canpush(len)) { ! 124: t = rtype(s->type); ! 125: isindirect = (Boolean) (t->class == RECORD or t->class == VARNT); ! 126: pushretval(len, isindirect); ! 127: printval(s->type); ! 128: putchar(' '); ! 129: } else { ! 130: printf("(value too large) "); ! 131: } ! 132: } ! 133: printf("from "); ! 134: printname(stdout, s); ! 135: printf("\n"); ! 136: } ! 137: ! 138: /* ! 139: * Print the values of the parameters of the given procedure or function. ! 140: * The frame distinguishes recursive instances of a procedure. ! 141: * ! 142: * If the procedure or function is internal, the argument count is ! 143: * not valid so we ignore it. ! 144: */ ! 145: ! 146: public printparams(f, frame) ! 147: Symbol f; ! 148: Frame frame; ! 149: { ! 150: Symbol param; ! 151: int n, m, s; ! 152: ! 153: n = nargspassed(frame); ! 154: if (isinternal(f)) { ! 155: n = 0; ! 156: } ! 157: printf("("); ! 158: param = f->chain; ! 159: if (param != nil or n > 0) { ! 160: m = n; ! 161: if (param != nil) { ! 162: for (;;) { ! 163: s = psize(param) div sizeof(Word); ! 164: if (s == 0) { ! 165: s = 1; ! 166: } ! 167: m -= s; ! 168: if (showaggrs) { ! 169: printv(param, frame); ! 170: } else { ! 171: printparamv(param, frame); ! 172: } ! 173: param = param->chain; ! 174: if (param == nil) break; ! 175: printf(", "); ! 176: } ! 177: } ! 178: if (m > 0) { ! 179: if (m > MAXARGSPASSED) { ! 180: m = MAXARGSPASSED; ! 181: } ! 182: if (f->chain != nil) { ! 183: printf(", "); ! 184: } ! 185: for (;;) { ! 186: --m; ! 187: printf("0x%x", argn(n - m, frame)); ! 188: if (m <= 0) break; ! 189: printf(", "); ! 190: } ! 191: } ! 192: } ! 193: printf(")"); ! 194: } ! 195: ! 196: /* ! 197: * Test if a symbol should be printed. We don't print files, ! 198: * for example, simply because there's no good way to do it. ! 199: * The symbol must be within the given function. ! 200: */ ! 201: ! 202: public Boolean should_print(s) ! 203: Symbol s; ! 204: { ! 205: Boolean b; ! 206: register Symbol t; ! 207: ! 208: switch (s->class) { ! 209: case VAR: ! 210: case FVAR: ! 211: if (isparam(s)) { ! 212: b = false; ! 213: } else { ! 214: t = rtype(s->type); ! 215: if (t == nil) { ! 216: b = false; ! 217: } else { ! 218: switch (t->class) { ! 219: case FILET: ! 220: case SET: ! 221: case BADUSE: ! 222: b = false; ! 223: break; ! 224: ! 225: default: ! 226: b = true; ! 227: break; ! 228: } ! 229: } ! 230: } ! 231: break; ! 232: ! 233: default: ! 234: b = false; ! 235: break; ! 236: } ! 237: return b; ! 238: } ! 239: ! 240: /* ! 241: * Print out a parameter value. ! 242: * ! 243: * Since this is intended to be printed on a single line with other information ! 244: * aggregate values are not printed. ! 245: */ ! 246: ! 247: public printparamv (p, frame) ! 248: Symbol p; ! 249: Frame frame; ! 250: { ! 251: Symbol t; ! 252: ! 253: t = rtype(p->type); ! 254: switch (t->class) { ! 255: case ARRAY: ! 256: case OPENARRAY: ! 257: case DYNARRAY: ! 258: case SUBARRAY: ! 259: t = rtype(t->type); ! 260: if (compatible(t, t_char)) { ! 261: printv(p, frame); ! 262: } else { ! 263: printf("%s = (...)", symname(p)); ! 264: } ! 265: break; ! 266: ! 267: case RECORD: ! 268: printf("%s = (...)", symname(p)); ! 269: break; ! 270: ! 271: default: ! 272: printv(p, frame); ! 273: break; ! 274: } ! 275: } ! 276: ! 277: /* ! 278: * Print the name and value of a variable. ! 279: */ ! 280: ! 281: public printv(s, frame) ! 282: Symbol s; ! 283: Frame frame; ! 284: { ! 285: Address addr; ! 286: int len; ! 287: ! 288: if (isambiguous(s) and ismodule(container(s))) { ! 289: printname(stdout, s); ! 290: printf(" = "); ! 291: } else { ! 292: printf("%s = ", symname(s)); ! 293: } ! 294: if (isvarparam(s) and not isopenarray(s)) { ! 295: rpush(address(s, frame), sizeof(Address)); ! 296: addr = pop(Address); ! 297: } else { ! 298: addr = address(s, frame); ! 299: } ! 300: len = size(s); ! 301: if (not canpush(len)) { ! 302: printf("*** expression too large ***"); ! 303: } else if (isreg(s)) { ! 304: push(Address, addr); ! 305: printval(s->type); ! 306: } else { ! 307: rpush(addr, len); ! 308: printval(s->type); ! 309: } ! 310: } ! 311: ! 312: /* ! 313: * Print out the name of a symbol. ! 314: */ ! 315: ! 316: public printname(f, s) ! 317: File f; ! 318: Symbol s; ! 319: { ! 320: if (s == nil) { ! 321: fprintf(f, "(noname)"); ! 322: } else if (s == program) { ! 323: fprintf(f, "."); ! 324: } else if (isredirected() or isambiguous(s)) { ! 325: printwhich(f, s); ! 326: } else { ! 327: fprintf(f, "%s", symname(s)); ! 328: } ! 329: } ! 330: ! 331: /* ! 332: * Print the fully specified variable that is described by the given identifer. ! 333: */ ! 334: ! 335: public printwhich(f, s) ! 336: File f; ! 337: Symbol s; ! 338: { ! 339: printouter(f, container(s)); ! 340: fprintf(f, "%s", symname(s)); ! 341: } ! 342: ! 343: /* ! 344: * Print the fully qualified name of each symbol that has the same name ! 345: * as the given symbol. ! 346: */ ! 347: ! 348: public printwhereis(f, s) ! 349: File f; ! 350: Symbol s; ! 351: { ! 352: register Name n; ! 353: register Symbol t; ! 354: ! 355: checkref(s); ! 356: n = s->name; ! 357: t = lookup(n); ! 358: printwhich(f, t); ! 359: t = t->next_sym; ! 360: while (t != nil) { ! 361: if (t->name == n) { ! 362: putc(' ', f); ! 363: printwhich(f, t); ! 364: } ! 365: t = t->next_sym; ! 366: } ! 367: putc('\n', f); ! 368: } ! 369: ! 370: private printouter(f, s) ! 371: File f; ! 372: Symbol s; ! 373: { ! 374: Symbol outer; ! 375: ! 376: if (s != nil) { ! 377: outer = container(s); ! 378: if (outer != nil and outer != program) { ! 379: printouter(f, outer); ! 380: } ! 381: fprintf(f, "%s.", symname(s)); ! 382: } ! 383: } ! 384: ! 385: public printdecl(s) ! 386: Symbol s; ! 387: { ! 388: Language lang; ! 389: ! 390: checkref(s); ! 391: if (s->language == nil or s->language == primlang) { ! 392: lang = findlanguage(".s"); ! 393: } else { ! 394: lang = s->language; ! 395: } ! 396: (*language_op(lang, L_PRINTDECL))(s); ! 397: } ! 398: ! 399: /* ! 400: * Straight dump of symbol information. ! 401: */ ! 402: ! 403: public psym(s) ! 404: Symbol s; ! 405: { ! 406: printf("name\t%s\n", symname(s)); ! 407: printf("lang\t%s\n", language_name(s->language)); ! 408: printf("level\t%d\n", s->level); ! 409: printf("class\t%s\n", classname(s)); ! 410: printf("type\t0x%x", s->type); ! 411: if (s->type != nil and s->type->name != nil) { ! 412: printf(" (%s)", symname(s->type)); ! 413: } ! 414: printf("\nchain\t0x%x", s->chain); ! 415: if (s->chain != nil and s->chain->name != nil) { ! 416: printf(" (%s)", symname(s->chain)); ! 417: } ! 418: printf("\nblock\t0x%x", s->block); ! 419: if (s->block != nil and s->block->name != nil) { ! 420: printf(" ("); ! 421: printname(stdout, s->block); ! 422: putchar(')'); ! 423: } ! 424: putchar('\n'); ! 425: switch (s->class) { ! 426: case TYPE: ! 427: printf("size\t%d\n", size(s)); ! 428: break; ! 429: ! 430: case VAR: ! 431: case REF: ! 432: switch (s->storage) { ! 433: case INREG: ! 434: printf("reg\t%d\n", s->symvalue.offset); ! 435: break; ! 436: ! 437: case STK: ! 438: printf("offset\t%d\n", s->symvalue.offset); ! 439: break; ! 440: ! 441: case EXT: ! 442: printf("address\t0x%x\n", s->symvalue.offset); ! 443: break; ! 444: } ! 445: printf("size\t%d\n", size(s)); ! 446: break; ! 447: ! 448: case RECORD: ! 449: case VARNT: ! 450: printf("size\t%d\n", s->symvalue.offset); ! 451: break; ! 452: ! 453: case FIELD: ! 454: printf("offset\t%d\n", s->symvalue.field.offset); ! 455: printf("size\t%d\n", s->symvalue.field.length); ! 456: break; ! 457: ! 458: case PROG: ! 459: case PROC: ! 460: case FUNC: ! 461: printf("address\t0x%x\n", s->symvalue.funcv.beginaddr); ! 462: if (isinline(s)) { ! 463: printf("inline procedure\n"); ! 464: } ! 465: if (nosource(s)) { ! 466: printf("does not have source information\n"); ! 467: } else { ! 468: printf("has source information\n"); ! 469: } ! 470: break; ! 471: ! 472: case RANGE: ! 473: prangetype(s->symvalue.rangev.lowertype); ! 474: printf("lower\t%d\n", s->symvalue.rangev.lower); ! 475: prangetype(s->symvalue.rangev.uppertype); ! 476: printf("upper\t%d\n", s->symvalue.rangev.upper); ! 477: break; ! 478: ! 479: default: ! 480: /* do nothing */ ! 481: break; ! 482: } ! 483: } ! 484: ! 485: private prangetype(r) ! 486: Rangetype r; ! 487: { ! 488: switch (r) { ! 489: case R_CONST: ! 490: printf("CONST"); ! 491: break; ! 492: ! 493: case R_ARG: ! 494: printf("ARG"); ! 495: break; ! 496: ! 497: case R_TEMP: ! 498: printf("TEMP"); ! 499: break; ! 500: ! 501: case R_ADJUST: ! 502: printf("ADJUST"); ! 503: break; ! 504: } ! 505: } ! 506: ! 507: /* ! 508: * Print out the value on top of the stack according to the given type. ! 509: */ ! 510: ! 511: public printval(t) ! 512: Symbol t; ! 513: { ! 514: Symbol s; ! 515: ! 516: checkref(t); ! 517: if (t->class == TYPEREF) { ! 518: resolveRef(t); ! 519: } ! 520: switch (t->class) { ! 521: case PROC: ! 522: case FUNC: ! 523: s = pop(Symbol); ! 524: printf("%s", symname(s)); ! 525: break; ! 526: ! 527: default: ! 528: if (t->language == nil or t->language == primlang) { ! 529: (*language_op(findlanguage(".c"), L_PRINTVAL))(t); ! 530: } else { ! 531: (*language_op(t->language, L_PRINTVAL))(t); ! 532: } ! 533: break; ! 534: } ! 535: } ! 536: ! 537: /* ! 538: * Print out the value of a record, field by field. ! 539: */ ! 540: ! 541: public printrecord(s) ! 542: Symbol s; ! 543: { ! 544: Symbol f; ! 545: ! 546: if (s->chain == nil) { ! 547: error("record has no fields"); ! 548: } ! 549: printf("("); ! 550: sp -= size(s); ! 551: f = s->chain; ! 552: if (f != nil) { ! 553: for (;;) { ! 554: printfield(f); ! 555: f = f->chain; ! 556: if (f == nil) break; ! 557: printf(", "); ! 558: } ! 559: } ! 560: printf(")"); ! 561: } ! 562: ! 563: /* ! 564: * Print out a field. ! 565: */ ! 566: ! 567: private printfield(f) ! 568: Symbol f; ! 569: { ! 570: Stack *savesp; ! 571: register int off, len; ! 572: ! 573: printf("%s = ", symname(f)); ! 574: savesp = sp; ! 575: off = f->symvalue.field.offset; ! 576: len = f->symvalue.field.length; ! 577: sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE); ! 578: printval(f); ! 579: sp = savesp; ! 580: } ! 581: ! 582: /* ! 583: * Print out the contents of an array. ! 584: * Haven't quite figured out what the best format is. ! 585: * ! 586: * This is rather inefficient. ! 587: * ! 588: * The "2*elsize" is there since "printval" drops the stack by elsize. ! 589: */ ! 590: ! 591: public printarray(a) ! 592: Symbol a; ! 593: { ! 594: Stack *savesp, *newsp; ! 595: Symbol eltype; ! 596: long elsize; ! 597: String sep; ! 598: ! 599: savesp = sp; ! 600: sp -= (size(a)); ! 601: newsp = sp; ! 602: eltype = rtype(a->type); ! 603: elsize = size(eltype); ! 604: printf("("); ! 605: if (eltype->class == RECORD or eltype->class == ARRAY or ! 606: eltype->class == VARNT) { ! 607: sep = "\n"; ! 608: putchar('\n'); ! 609: } else { ! 610: sep = ", "; ! 611: } ! 612: for (sp += elsize; sp <= savesp; sp += 2*elsize) { ! 613: if (sp - elsize != newsp) { ! 614: fputs(sep, stdout); ! 615: } ! 616: printval(eltype); ! 617: } ! 618: sp = newsp; ! 619: if (streq(sep, "\n")) { ! 620: putchar('\n'); ! 621: } ! 622: printf(")"); ! 623: } ! 624: ! 625: /* ! 626: * Print out the value of a real number in Pascal notation. ! 627: * This is, unfortunately, different than what one gets ! 628: * from "%g" in printf. ! 629: */ ! 630: ! 631: public prtreal(r) ! 632: double r; ! 633: { ! 634: extern char *index(); ! 635: char buf[256]; ! 636: ! 637: # ifdef IRIS ! 638: sprintf(buf, "%lg", r); ! 639: # else ! 640: sprintf(buf, "%g", r); ! 641: # endif ! 642: if (buf[0] == '.') { ! 643: printf("0%s", buf); ! 644: } else if (buf[0] == '-' and buf[1] == '.') { ! 645: printf("-0%s", &buf[1]); ! 646: } else { ! 647: printf("%s", buf); ! 648: } ! 649: if (index(buf, '.') == nil) { ! 650: printf(".0"); ! 651: } ! 652: } ! 653: ! 654: /* ! 655: * Print out a character using ^? notation for unprintables. ! 656: */ ! 657: ! 658: public printchar(c) ! 659: char c; ! 660: { ! 661: if (c == 0) { ! 662: putchar('\\'); ! 663: putchar('0'); ! 664: } else if (c == '\n') { ! 665: putchar('\\'); ! 666: putchar('n'); ! 667: } else if (c > 0 and c < ' ') { ! 668: putchar('^'); ! 669: putchar(c - 1 + 'A'); ! 670: } else if (c >= ' ' && c <= '~') { ! 671: putchar(c); ! 672: } else { ! 673: printf("\\0%o",c&0xff); ! 674: } ! 675: } ! 676: ! 677: /* ! 678: * Print out a value for a range type (integer, char, or boolean). ! 679: */ ! 680: ! 681: public printRangeVal (val, t) ! 682: long val; ! 683: Symbol t; ! 684: { ! 685: if (t == t_boolean->type or istypename(t->type, "boolean")) { ! 686: if ((boolean) val) { ! 687: printf("true"); ! 688: } else { ! 689: printf("false"); ! 690: } ! 691: } else if (t == t_char->type or istypename(t->type, "char")) { ! 692: if (varIsSet("$hexchars")) { ! 693: printf("0x%lx", val); ! 694: } else { ! 695: putchar('\''); ! 696: printchar(val); ! 697: putchar('\''); ! 698: } ! 699: } else if (varIsSet("$hexints")) { ! 700: printf("0x%lx", val); ! 701: } else if (t->symvalue.rangev.lower >= 0) { ! 702: printf("%lu", val); ! 703: } else { ! 704: printf("%ld", val); ! 705: } ! 706: } ! 707: ! 708: /* ! 709: * Print out an enumerated value by finding the corresponding ! 710: * name in the enumeration list. ! 711: */ ! 712: ! 713: public printEnum (i, t) ! 714: integer i; ! 715: Symbol t; ! 716: { ! 717: register Symbol e; ! 718: ! 719: e = t->chain; ! 720: while (e != nil and e->symvalue.constval->value.lcon != i) { ! 721: e = e->chain; ! 722: } ! 723: if (e != nil) { ! 724: printf("%s", symname(e)); ! 725: } else { ! 726: printf("%d", i); ! 727: } ! 728: } ! 729: ! 730: /* ! 731: * Print out a null-terminated string (pointer to char) ! 732: * starting at the given address. ! 733: */ ! 734: ! 735: public printString (addr, quotes) ! 736: Address addr; ! 737: boolean quotes; ! 738: { ! 739: register Address a; ! 740: register integer i, len; ! 741: register boolean endofstring; ! 742: register int unprintables; ! 743: #define MAXGARBAGE 4 ! 744: union { ! 745: char ch[sizeof(Word)]; ! 746: int word; ! 747: } u; ! 748: ! 749: if (varIsSet("$hexstrings")) { ! 750: printf("0x%x", addr); ! 751: } else { ! 752: if (quotes) { ! 753: putchar('"'); ! 754: } ! 755: a = addr; ! 756: unprintables = 0; ! 757: endofstring = false; ! 758: while (not endofstring) { ! 759: dread(&u, a, sizeof(u)); ! 760: i = 0; ! 761: do { ! 762: if (u.ch[i] == '\0') { ! 763: endofstring = true; ! 764: } else { ! 765: printchar(u.ch[i]); ! 766: if (!isascii(u.ch[i]) and ++unprintables > MAXGARBAGE) { ! 767: endofstring = true; ! 768: printf("..."); ! 769: } ! 770: } ! 771: ++i; ! 772: } while (i < sizeof(Word) and not endofstring); ! 773: a += sizeof(Word); ! 774: } ! 775: if (quotes) { ! 776: putchar('"'); ! 777: } ! 778: } ! 779: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.