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