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