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