|
|
1.1 ! root 1: /* Copyright (c) 1982 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)printsym.c 1.12 8/10/83"; ! 4: ! 5: /* ! 6: * Printing of symbolic information. ! 7: */ ! 8: ! 9: #include "defs.h" ! 10: #include "symbols.h" ! 11: #include "languages.h" ! 12: #include "printsym.h" ! 13: #include "tree.h" ! 14: #include "eval.h" ! 15: #include "mappings.h" ! 16: #include "process.h" ! 17: #include "runtime.h" ! 18: #include "machine.h" ! 19: #include "names.h" ! 20: #include "main.h" ! 21: ! 22: #ifndef public ! 23: #endif ! 24: ! 25: /* ! 26: * Maximum number of arguments to a function. ! 27: * This is used as a check for the possibility that the stack has been ! 28: * overwritten and therefore a saved argument pointer might indicate ! 29: * to an absurdly large number of arguments. ! 30: */ ! 31: ! 32: #define MAXARGSPASSED 20 ! 33: ! 34: /* ! 35: * Return a pointer to the string for the name of the class that ! 36: * the given symbol belongs to. ! 37: */ ! 38: ! 39: private String clname[] = { ! 40: "bad use", "constant", "type", "variable", "array", "fileptr", ! 41: "record", "field", "procedure", "function", "funcvar", ! 42: "ref", "pointer", "file", "set", "range", "label", "withptr", ! 43: "scalar", "string", "program", "improper", "variant", ! 44: "procparam", "funcparam", "module", "tag", "common", "typeref" ! 45: }; ! 46: ! 47: public String classname(s) ! 48: Symbol s; ! 49: { ! 50: return clname[ord(s->class)]; ! 51: } ! 52: ! 53: /* ! 54: * Note the entry of the given block, unless it's the main program. ! 55: */ ! 56: ! 57: public printentry(s) ! 58: Symbol s; ! 59: { ! 60: if (s != program) { ! 61: printf("\nentering %s %s\n", classname(s), symname(s)); ! 62: } ! 63: } ! 64: ! 65: /* ! 66: * Note the exit of the given block ! 67: */ ! 68: ! 69: public printexit(s) ! 70: Symbol s; ! 71: { ! 72: if (s != program) { ! 73: printf("leaving %s %s\n\n", classname(s), symname(s)); ! 74: } ! 75: } ! 76: ! 77: /* ! 78: * Note the call of s from t. ! 79: */ ! 80: ! 81: public printcall(s, t) ! 82: Symbol s, t; ! 83: { ! 84: printf("calling %s", symname(s)); ! 85: printparams(s, nil); ! 86: printf(" from %s %s\n", classname(t), symname(t)); ! 87: } ! 88: ! 89: /* ! 90: * Note the return from s. If s is a function, print the value ! 91: * it is returning. This is somewhat painful, since the function ! 92: * has actually just returned. ! 93: */ ! 94: ! 95: public printrtn(s) ! 96: Symbol s; ! 97: { ! 98: register Symbol t; ! 99: register int len; ! 100: Boolean isindirect; ! 101: ! 102: printf("returning "); ! 103: if (s->class == FUNC && (!istypename(s->type,"void"))) { ! 104: len = size(s->type); ! 105: if (canpush(len)) { ! 106: t = rtype(s->type); ! 107: isindirect = (Boolean) (t->class == RECORD or t->class == VARNT); ! 108: pushretval(len, isindirect); ! 109: printval(s->type); ! 110: putchar(' '); ! 111: } else { ! 112: printf("(value too large) "); ! 113: } ! 114: } ! 115: printf("from %s\n", symname(s)); ! 116: } ! 117: ! 118: /* ! 119: * Print the values of the parameters of the given procedure or function. ! 120: * The frame distinguishes recursive instances of a procedure. ! 121: */ ! 122: ! 123: public printparams(f, frame) ! 124: Symbol f; ! 125: Frame frame; ! 126: { ! 127: Symbol param; ! 128: int n, m, s; ! 129: ! 130: n = nargspassed(frame); ! 131: param = f->chain; ! 132: if (param != nil or n > 0) { ! 133: printf("("); ! 134: m = n; ! 135: if (param != nil) { ! 136: for (;;) { ! 137: s = size(param) div sizeof(Word); ! 138: if (s == 0) { ! 139: s = 1; ! 140: } ! 141: m -= s; ! 142: printv(param, frame); ! 143: param = param->chain; ! 144: if (param == nil) break; ! 145: printf(", "); ! 146: } ! 147: } ! 148: if (m > 0) { ! 149: if (m > MAXARGSPASSED) { ! 150: m = MAXARGSPASSED; ! 151: } ! 152: if (f->chain != nil) { ! 153: printf(", "); ! 154: } ! 155: for (;;) { ! 156: --m; ! 157: printf("0x%x", argn(n - m, frame)); ! 158: if (m <= 0) break; ! 159: printf(", "); ! 160: } ! 161: } ! 162: printf(")"); ! 163: } ! 164: } ! 165: ! 166: /* ! 167: * Test if a symbol should be printed. We don't print files, ! 168: * for example, simply because there's no good way to do it. ! 169: * The symbol must be within the given function. ! 170: */ ! 171: ! 172: public Boolean should_print(s) ! 173: Symbol s; ! 174: { ! 175: Boolean b; ! 176: register Symbol t; ! 177: ! 178: switch (s->class) { ! 179: case VAR: ! 180: case FVAR: ! 181: if (isparam(s)) { ! 182: b = false; ! 183: } else { ! 184: t = rtype(s->type); ! 185: if (t == nil) { ! 186: b = false; ! 187: } else { ! 188: switch (t->class) { ! 189: case FILET: ! 190: case SET: ! 191: case BADUSE: ! 192: b = false; ! 193: break; ! 194: ! 195: default: ! 196: b = true; ! 197: break; ! 198: } ! 199: } ! 200: } ! 201: break; ! 202: ! 203: default: ! 204: b = false; ! 205: break; ! 206: } ! 207: return b; ! 208: } ! 209: ! 210: /* ! 211: * Print the name and value of a variable. ! 212: */ ! 213: ! 214: public printv(s, frame) ! 215: Symbol s; ! 216: Frame frame; ! 217: { ! 218: Address addr; ! 219: int len; ! 220: ! 221: if (isambiguous(s) and ismodule(container(s))) { ! 222: printname(stdout, s); ! 223: printf(" = "); ! 224: } else { ! 225: printf("%s = ", symname(s)); ! 226: } ! 227: if(s->type->class == ARRAY && (! istypename(s->type->type,"char")) ) { ! 228: printf(" ARRAY "); ! 229: } else { ! 230: if (isvarparam(s)) { ! 231: rpush(address(s, frame), sizeof(Address)); ! 232: addr = pop(Address); ! 233: len = size(s->type); ! 234: } else { ! 235: addr = address(s, frame); ! 236: len = size(s); ! 237: } ! 238: if (canpush(len)) { ! 239: rpush(addr, len); ! 240: printval(s->type); ! 241: } else { ! 242: printf("*** expression too large ***"); ! 243: } ! 244: } ! 245: } ! 246: ! 247: /* ! 248: * Print out the name of a symbol. ! 249: */ ! 250: ! 251: public printname(f, s) ! 252: File f; ! 253: Symbol s; ! 254: { ! 255: if (s == nil) { ! 256: fprintf(f, "(noname)"); ! 257: } else if (isredirected() or isambiguous(s)) { ! 258: printwhich(f, s); ! 259: } else { ! 260: fprintf(f, "%s", symname(s)); ! 261: } ! 262: } ! 263: ! 264: /* ! 265: * Print the fully specified variable that is described by the given identifer. ! 266: */ ! 267: ! 268: public printwhich(f, s) ! 269: File f; ! 270: Symbol s; ! 271: { ! 272: printouter(f, container(s)); ! 273: fprintf(f, "%s", symname(s)); ! 274: } ! 275: ! 276: /* ! 277: * Print the fully qualified name of each symbol that has the same name ! 278: * as the given symbol. ! 279: */ ! 280: ! 281: public printwhereis(f, s) ! 282: File f; ! 283: Symbol s; ! 284: { ! 285: register Name n; ! 286: register Symbol t; ! 287: ! 288: checkref(s); ! 289: n = s->name; ! 290: t = lookup(n); ! 291: printwhich(f, t); ! 292: t = t->next_sym; ! 293: while (t != nil) { ! 294: if (t->name == n) { ! 295: putc(' ', f); ! 296: printwhich(f, t); ! 297: } ! 298: t = t->next_sym; ! 299: } ! 300: putc('\n', f); ! 301: } ! 302: ! 303: private printouter(f, s) ! 304: File f; ! 305: Symbol s; ! 306: { ! 307: Symbol outer; ! 308: ! 309: if (s != nil) { ! 310: outer = container(s); ! 311: if (outer != nil and outer != program) { ! 312: printouter(f, outer); ! 313: } ! 314: fprintf(f, "%s.", symname(s)); ! 315: } ! 316: } ! 317: ! 318: public printdecl(s) ! 319: Symbol s; ! 320: { ! 321: checkref(s); ! 322: (*language_op(s->language, L_PRINTDECL))(s); ! 323: } ! 324: ! 325: /* ! 326: * Straight dump of symbol information. ! 327: */ ! 328: ! 329: public psym(s) ! 330: Symbol s; ! 331: { ! 332: printf("name\t%s\n", symname(s)); ! 333: printf("lang\t%s\n", language_name(s->language)); ! 334: printf("level\t%d\n", s->level); ! 335: printf("class\t%s\n", classname(s)); ! 336: printf("type\t0x%x", s->type); ! 337: if (s->type != nil and s->type->name != nil) { ! 338: printf(" (%s)", symname(s->type)); ! 339: } ! 340: printf("\nchain\t0x%x", s->chain); ! 341: if (s->chain != nil and s->chain->name != nil) { ! 342: printf(" (%s)", symname(s->chain)); ! 343: } ! 344: printf("\nblock\t0x%x", s->block); ! 345: if (s->block->name != nil) { ! 346: printf(" ("); ! 347: printname(stdout, s->block); ! 348: putchar(')'); ! 349: } ! 350: putchar('\n'); ! 351: switch (s->class) { ! 352: case VAR: ! 353: case REF: ! 354: if (s->level >= 3) { ! 355: printf("address\t0x%x\n", s->symvalue.offset); ! 356: } else { ! 357: printf("offset\t%d\n", s->symvalue.offset); ! 358: } ! 359: printf("size\t%d\n", size(s)); ! 360: break; ! 361: ! 362: case RECORD: ! 363: case VARNT: ! 364: printf("size\t%d\n", s->symvalue.offset); ! 365: break; ! 366: ! 367: case FIELD: ! 368: printf("offset\t%d\n", s->symvalue.field.offset); ! 369: printf("size\t%d\n", s->symvalue.field.length); ! 370: break; ! 371: ! 372: case PROG: ! 373: case PROC: ! 374: case FUNC: ! 375: printf("address\t0x%x\n", s->symvalue.funcv.beginaddr); ! 376: if (isinline(s)) { ! 377: printf("inline procedure\n"); ! 378: } ! 379: if (nosource(s)) { ! 380: printf("does not have source information\n"); ! 381: } else { ! 382: printf("has source information\n"); ! 383: } ! 384: break; ! 385: ! 386: case RANGE: ! 387: ! 388: prangetype(s->symvalue.rangev.lowertype); ! 389: printf("lower\t%d\n", s->symvalue.rangev.lower); ! 390: prangetype(s->symvalue.rangev.uppertype); ! 391: printf("upper\t%d\n", s->symvalue.rangev.upper); ! 392: break; ! 393: ! 394: default: ! 395: /* do nothing */ ! 396: break; ! 397: } ! 398: } ! 399: ! 400: private prangetype(r) ! 401: Rangetype r; ! 402: { ! 403: switch (r) { ! 404: case R_CONST: ! 405: printf("CONST"); ! 406: break; ! 407: ! 408: case R_ARG: ! 409: printf("ARG"); ! 410: break; ! 411: ! 412: case R_TEMP: ! 413: printf("TEMP"); ! 414: break; ! 415: ! 416: case R_ADJUST: ! 417: printf("ADJUST"); ! 418: break; ! 419: } ! 420: } ! 421: ! 422: /* ! 423: * Print out the value on top of the stack according to the given type. ! 424: */ ! 425: ! 426: public printval(t) ! 427: Symbol t; ! 428: { ! 429: Symbol s; ! 430: ! 431: checkref(t); ! 432: switch (t->class) { ! 433: case PROC: ! 434: case FUNC: ! 435: s = pop(Symbol); ! 436: printf("%s", symname(s)); ! 437: break; ! 438: ! 439: default: ! 440: if (t->language == nil) { ! 441: error("unknown language"); ! 442: } else { ! 443: (*language_op(t->language, L_PRINTVAL))(t); ! 444: } ! 445: break; ! 446: } ! 447: } ! 448: ! 449: /* ! 450: * Print out the value of a record, field by field. ! 451: */ ! 452: ! 453: public printrecord(s) ! 454: Symbol s; ! 455: { ! 456: if (s->chain == nil) { ! 457: error("record has no fields"); ! 458: } ! 459: printf("("); ! 460: sp -= size(s); ! 461: printfield(s->chain); ! 462: printf(")"); ! 463: } ! 464: ! 465: /* ! 466: * Print out a field, first printing out other fields. ! 467: * This is done because the fields are chained together backwards. ! 468: */ ! 469: ! 470: private printfield(s) ! 471: Symbol s; ! 472: { ! 473: Stack *savesp; ! 474: ! 475: if (s->chain != nil) { ! 476: printfield(s->chain); ! 477: printf(", "); ! 478: } ! 479: printf("%s = ", symname(s)); ! 480: savesp = sp; ! 481: sp += ((s->symvalue.field.offset div BITSPERBYTE) + size(s->type)); ! 482: printval(s); ! 483: sp = savesp; ! 484: } ! 485: ! 486: /* ! 487: * Print out the contents of an array. ! 488: * Haven't quite figured out what the best format is. ! 489: * ! 490: * This is rather inefficient. ! 491: * ! 492: * The "2*elsize" is there since "printval" drops the stack by elsize. ! 493: */ ! 494: ! 495: public printarray(a) ! 496: Symbol a; ! 497: { ! 498: Stack *savesp, *newsp; ! 499: Symbol eltype; ! 500: long elsize; ! 501: String sep; ! 502: ! 503: savesp = sp; ! 504: sp -= (size(a)); ! 505: newsp = sp; ! 506: eltype = rtype(a->type); ! 507: elsize = size(eltype); ! 508: printf("("); ! 509: if (eltype->class == RECORD or eltype->class == ARRAY or ! 510: eltype->class == VARNT) { ! 511: sep = "\n"; ! 512: putchar('\n'); ! 513: } else { ! 514: sep = ", "; ! 515: } ! 516: for (sp += elsize; sp <= savesp; sp += 2*elsize) { ! 517: if (sp - elsize != newsp) { ! 518: fputs(sep, stdout); ! 519: } ! 520: printval(eltype); ! 521: } ! 522: sp = newsp; ! 523: if (streq(sep, "\n")) { ! 524: putchar('\n'); ! 525: } ! 526: printf(")"); ! 527: } ! 528: ! 529: /* ! 530: * Print out the value of a real number in Pascal notation. ! 531: * This is, unfortunately, different than what one gets ! 532: * from "%g" in printf. ! 533: */ ! 534: ! 535: public prtreal(r) ! 536: double r; ! 537: { ! 538: extern char *index(); ! 539: char buf[256]; ! 540: ! 541: sprintf(buf, "%g", r); ! 542: if (buf[0] == '.') { ! 543: printf("0%s", buf); ! 544: } else if (buf[0] == '-' and buf[1] == '.') { ! 545: printf("-0%s", &buf[1]); ! 546: } else { ! 547: printf("%s", buf); ! 548: } ! 549: if (index(buf, '.') == nil) { ! 550: printf(".0"); ! 551: } ! 552: } ! 553: ! 554: /* ! 555: * Print out a character using ^? notation for unprintables. ! 556: */ ! 557: ! 558: public printchar(c) ! 559: char c; ! 560: { ! 561: if (c == 0) { ! 562: putchar('\\'); ! 563: putchar('0'); ! 564: } else if (c == '\n') { ! 565: putchar('\\'); ! 566: putchar('n'); ! 567: } else if (c > 0 and c < ' ') { ! 568: putchar('^'); ! 569: putchar(c - 1 + 'A'); ! 570: } else { ! 571: putchar(c); ! 572: } ! 573: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.