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