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