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: }