1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)printsym.c 1.13 (Berkeley) 06/23/84"; 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", "extref", "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 * If the procedure or function is internal, the argument count is 123 * not valid so we ignore it. 124 */ 125 126 public printparams(f, frame) 127 Symbol f; 128 Frame frame; 129 { 130 Symbol param; 131 int n, m, s; 132 133 n = nargspassed(frame); 134 if (isinternal(f)) { 135 n = 0; 136 } 137 param = f->chain; 138 if (param != nil or n > 0) { 139 printf("("); 140 m = n; 141 if (param != nil) { 142 for (;;) { 143 s = size(param) div sizeof(Word); 144 if (s == 0) { 145 s = 1; 146 } 147 m -= s; 148 printv(param, frame); 149 param = param->chain; 150 if (param == nil) break; 151 printf(", "); 152 } 153 } 154 if (m > 0) { 155 if (m > MAXARGSPASSED) { 156 m = MAXARGSPASSED; 157 } 158 if (f->chain != nil) { 159 printf(", "); 160 } 161 for (;;) { 162 --m; 163 printf("0x%x", argn(n - m, frame)); 164 if (m <= 0) break; 165 printf(", "); 166 } 167 } 168 printf(")"); 169 } 170 } 171 172 /* 173 * Test if a symbol should be printed. We don't print files, 174 * for example, simply because there's no good way to do it. 175 * The symbol must be within the given function. 176 */ 177 178 public Boolean should_print(s) 179 Symbol s; 180 { 181 Boolean b; 182 register Symbol t; 183 184 switch (s->class) { 185 case VAR: 186 case FVAR: 187 if (isparam(s)) { 188 b = false; 189 } else { 190 t = rtype(s->type); 191 if (t == nil) { 192 b = false; 193 } else { 194 switch (t->class) { 195 case FILET: 196 case SET: 197 case BADUSE: 198 b = false; 199 break; 200 201 default: 202 b = true; 203 break; 204 } 205 } 206 } 207 break; 208 209 default: 210 b = false; 211 break; 212 } 213 return b; 214 } 215 216 /* 217 * Print the name and value of a variable. 218 */ 219 220 public printv(s, frame) 221 Symbol s; 222 Frame frame; 223 { 224 Address addr; 225 int len; 226 Symbol t; 227 228 if (isambiguous(s) and ismodule(container(s))) { 229 printname(stdout, s); 230 printf(" = "); 231 } else { 232 printf("%s = ", symname(s)); 233 } 234 /* 235 * Not today. 236 t = rtype(s->type); 237 if (t->class == ARRAY and not istypename(t->type, "char")) { 238 printf("ARRAY"); 239 } else { 240 */ 241 if (isvarparam(s)) { 242 rpush(address(s, frame), sizeof(Address)); 243 addr = pop(Address); 244 len = size(s->type); 245 } else { 246 addr = address(s, frame); 247 len = size(s); 248 } 249 if (canpush(len)) { 250 rpush(addr, len); 251 printval(s->type); 252 } else { 253 printf("*** expression too large ***"); 254 } 255 /* 256 * Matches brace commented out above. 257 } 258 */ 259 } 260 261 /* 262 * Print out the name of a symbol. 263 */ 264 265 public printname(f, s) 266 File f; 267 Symbol s; 268 { 269 if (s == nil) { 270 fprintf(f, "(noname)"); 271 } else if (s == program) { 272 fprintf(f, "."); 273 } else if (isredirected() or isambiguous(s)) { 274 printwhich(f, s); 275 } else { 276 fprintf(f, "%s", symname(s)); 277 } 278 } 279 280 /* 281 * Print the fully specified variable that is described by the given identifer. 282 */ 283 284 public printwhich(f, s) 285 File f; 286 Symbol s; 287 { 288 printouter(f, container(s)); 289 fprintf(f, "%s", symname(s)); 290 } 291 292 /* 293 * Print the fully qualified name of each symbol that has the same name 294 * as the given symbol. 295 */ 296 297 public printwhereis(f, s) 298 File f; 299 Symbol s; 300 { 301 register Name n; 302 register Symbol t; 303 304 checkref(s); 305 n = s->name; 306 t = lookup(n); 307 printwhich(f, t); 308 t = t->next_sym; 309 while (t != nil) { 310 if (t->name == n) { 311 putc(' ', f); 312 printwhich(f, t); 313 } 314 t = t->next_sym; 315 } 316 putc('\n', f); 317 } 318 319 private printouter(f, s) 320 File f; 321 Symbol s; 322 { 323 Symbol outer; 324 325 if (s != nil) { 326 outer = container(s); 327 if (outer != nil and outer != program) { 328 printouter(f, outer); 329 } 330 fprintf(f, "%s.", symname(s)); 331 } 332 } 333 334 public printdecl(s) 335 Symbol s; 336 { 337 checkref(s); 338 (*language_op(s->language, L_PRINTDECL))(s); 339 } 340 341 /* 342 * Straight dump of symbol information. 343 */ 344 345 public psym(s) 346 Symbol s; 347 { 348 printf("name\t%s\n", symname(s)); 349 printf("lang\t%s\n", language_name(s->language)); 350 printf("level\t%d\n", s->level); 351 printf("class\t%s\n", classname(s)); 352 printf("type\t0x%x", s->type); 353 if (s->type != nil and s->type->name != nil) { 354 printf(" (%s)", symname(s->type)); 355 } 356 printf("\nchain\t0x%x", s->chain); 357 if (s->chain != nil and s->chain->name != nil) { 358 printf(" (%s)", symname(s->chain)); 359 } 360 printf("\nblock\t0x%x", s->block); 361 if (s->block->name != nil) { 362 printf(" ("); 363 printname(stdout, s->block); 364 putchar(')'); 365 } 366 putchar('\n'); 367 switch (s->class) { 368 case VAR: 369 case REF: 370 if (s->level >= 3) { 371 printf("address\t0x%x\n", s->symvalue.offset); 372 } else { 373 printf("offset\t%d\n", s->symvalue.offset); 374 } 375 printf("size\t%d\n", size(s)); 376 break; 377 378 case RECORD: 379 case VARNT: 380 printf("size\t%d\n", s->symvalue.offset); 381 break; 382 383 case FIELD: 384 printf("offset\t%d\n", s->symvalue.field.offset); 385 printf("size\t%d\n", s->symvalue.field.length); 386 break; 387 388 case PROG: 389 case PROC: 390 case FUNC: 391 printf("address\t0x%x\n", s->symvalue.funcv.beginaddr); 392 if (isinline(s)) { 393 printf("inline procedure\n"); 394 } 395 if (nosource(s)) { 396 printf("does not have source information\n"); 397 } else { 398 printf("has source information\n"); 399 } 400 break; 401 402 case RANGE: 403 prangetype(s->symvalue.rangev.lowertype); 404 printf("lower\t%d\n", s->symvalue.rangev.lower); 405 prangetype(s->symvalue.rangev.uppertype); 406 printf("upper\t%d\n", s->symvalue.rangev.upper); 407 break; 408 409 default: 410 /* do nothing */ 411 break; 412 } 413 } 414 415 private prangetype(r) 416 Rangetype r; 417 { 418 switch (r) { 419 case R_CONST: 420 printf("CONST"); 421 break; 422 423 case R_ARG: 424 printf("ARG"); 425 break; 426 427 case R_TEMP: 428 printf("TEMP"); 429 break; 430 431 case R_ADJUST: 432 printf("ADJUST"); 433 break; 434 } 435 } 436 437 /* 438 * Print out the value on top of the stack according to the given type. 439 */ 440 441 public printval(t) 442 Symbol t; 443 { 444 Symbol s; 445 446 checkref(t); 447 if (t->class == TYPEREF) { 448 resolveRef(t); 449 } 450 switch (t->class) { 451 case PROC: 452 case FUNC: 453 s = pop(Symbol); 454 printf("%s", symname(s)); 455 break; 456 457 default: 458 if (t->language == nil) { 459 error("unknown language"); 460 } else if (t->language == primlang) { 461 (*language_op(findlanguage(".c"), L_PRINTVAL))(t); 462 } else { 463 (*language_op(t->language, L_PRINTVAL))(t); 464 } 465 break; 466 } 467 } 468 469 /* 470 * Print out the value of a record, field by field. 471 */ 472 473 public printrecord(s) 474 Symbol s; 475 { 476 Symbol f; 477 478 if (s->chain == nil) { 479 error("record has no fields"); 480 } 481 printf("("); 482 sp -= size(s); 483 f = s->chain; 484 if (f != nil) { 485 for (;;) { 486 printfield(f); 487 f = f->chain; 488 if (f == nil) break; 489 printf(", "); 490 } 491 } 492 printf(")"); 493 } 494 495 /* 496 * Print out a field. 497 */ 498 499 private printfield(f) 500 Symbol f; 501 { 502 Stack *savesp; 503 register int off, len; 504 505 printf("%s = ", symname(f)); 506 savesp = sp; 507 off = f->symvalue.field.offset; 508 len = f->symvalue.field.length; 509 sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE); 510 printval(f); 511 sp = savesp; 512 } 513 514 /* 515 * Print out the contents of an array. 516 * Haven't quite figured out what the best format is. 517 * 518 * This is rather inefficient. 519 * 520 * The "2*elsize" is there since "printval" drops the stack by elsize. 521 */ 522 523 public printarray(a) 524 Symbol a; 525 { 526 Stack *savesp, *newsp; 527 Symbol eltype; 528 long elsize; 529 String sep; 530 531 savesp = sp; 532 sp -= (size(a)); 533 newsp = sp; 534 eltype = rtype(a->type); 535 elsize = size(eltype); 536 printf("("); 537 if (eltype->class == RECORD or eltype->class == ARRAY or 538 eltype->class == VARNT) { 539 sep = "\n"; 540 putchar('\n'); 541 } else { 542 sep = ", "; 543 } 544 for (sp += elsize; sp <= savesp; sp += 2*elsize) { 545 if (sp - elsize != newsp) { 546 fputs(sep, stdout); 547 } 548 printval(eltype); 549 } 550 sp = newsp; 551 if (streq(sep, "\n")) { 552 putchar('\n'); 553 } 554 printf(")"); 555 } 556 557 /* 558 * Print out the value of a real number in Pascal notation. 559 * This is, unfortunately, different than what one gets 560 * from "%g" in printf. 561 */ 562 563 public prtreal(r) 564 double r; 565 { 566 extern char *index(); 567 char buf[256]; 568 569 sprintf(buf, "%g", r); 570 if (buf[0] == '.') { 571 printf("0%s", buf); 572 } else if (buf[0] == '-' and buf[1] == '.') { 573 printf("-0%s", &buf[1]); 574 } else { 575 printf("%s", buf); 576 } 577 if (index(buf, '.') == nil) { 578 printf(".0"); 579 } 580 } 581 582 /* 583 * Print out a character using ^? notation for unprintables. 584 */ 585 586 public printchar(c) 587 char c; 588 { 589 if (c == 0) { 590 putchar('\\'); 591 putchar('0'); 592 } else if (c == '\n') { 593 putchar('\\'); 594 putchar('n'); 595 } else if (c > 0 and c < ' ') { 596 putchar('^'); 597 putchar(c - 1 + 'A'); 598 } else if (c >= ' ' && c <= '~') { 599 putchar(c); 600 } else { 601 printf("\\0%o",c); 602 } 603 } 604