1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)printsym.c 1.6 05/18/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) { 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 t = rtype(s->type); 182 b = (Boolean) ( 183 not isparam(s) and 184 t != nil and t->class != FILET and t->class != SET 185 ); 186 break; 187 188 default: 189 b = false; 190 break; 191 } 192 return b; 193 } 194 195 /* 196 * Print the name and value of a variable. 197 */ 198 199 public printv(s, frame) 200 Symbol s; 201 Frame frame; 202 { 203 Address addr; 204 int len; 205 206 if (isambiguous(s) and ismodule(container(s))) { 207 printname(stdout, s); 208 printf(" = "); 209 } else { 210 printf("%s = ", symname(s)); 211 } 212 if (isvarparam(s)) { 213 rpush(address(s, frame), sizeof(Address)); 214 addr = pop(Address); 215 len = size(s->type); 216 } else { 217 addr = address(s, frame); 218 len = size(s); 219 } 220 if (canpush(len)) { 221 rpush(addr, len); 222 printval(s->type); 223 } else { 224 printf("*** expression too large ***"); 225 } 226 } 227 228 /* 229 * Print out the name of a symbol. 230 */ 231 232 public printname(f, s) 233 File f; 234 Symbol s; 235 { 236 if (s == nil) { 237 fprintf(f, "(noname)"); 238 } else if (isredirected() or isambiguous(s)) { 239 printwhich(f, s); 240 } else { 241 fprintf(f, "%s", symname(s)); 242 } 243 } 244 245 /* 246 * Print the fully specified variable that is described by the given identifer. 247 */ 248 249 public printwhich(f, s) 250 File f; 251 Symbol s; 252 { 253 printouter(f, container(s)); 254 fprintf(f, "%s", symname(s)); 255 } 256 257 /* 258 * Print the fully qualified name of each symbol that has the same name 259 * as the given symbol. 260 */ 261 262 public printwhereis(f, s) 263 File f; 264 Symbol s; 265 { 266 register Name n; 267 register Symbol t; 268 269 checkref(s); 270 n = s->name; 271 t = lookup(n); 272 printwhich(f, t); 273 t = t->next_sym; 274 while (t != nil) { 275 if (t->name == n) { 276 putc(' ', f); 277 printwhich(f, t); 278 } 279 t = t->next_sym; 280 } 281 putc('\n', f); 282 } 283 284 private printouter(f, s) 285 File f; 286 Symbol s; 287 { 288 Symbol outer; 289 290 if (s != nil) { 291 outer = container(s); 292 if (outer != nil and outer != program) { 293 printouter(f, outer); 294 } 295 fprintf(f, "%s.", symname(s)); 296 } 297 } 298 299 public printdecl(s) 300 Symbol s; 301 { 302 checkref(s); 303 (*language_op(s->language, L_PRINTDECL))(s); 304 } 305 306 /* 307 * Straight dump of symbol information. 308 */ 309 310 public psym(s) 311 Symbol s; 312 { 313 printf("name\t%s\n", symname(s)); 314 printf("lang\t%s\n", language_name(s->language)); 315 printf("level\t%d\n", s->level); 316 printf("class\t%s\n", classname(s)); 317 printf("type\t0x%x", s->type); 318 if (s->type != nil and s->type->name != nil) { 319 printf(" (%s)", symname(s->type)); 320 } 321 printf("\nchain\t0x%x", s->chain); 322 if (s->chain != nil and s->chain->name != nil) { 323 printf(" (%s)", symname(s->chain)); 324 } 325 printf("\nblock\t0x%x", s->block); 326 if (s->block->name != nil) { 327 printf(" ("); 328 printname(stdout, s->block); 329 putchar(')'); 330 } 331 putchar('\n'); 332 switch (s->class) { 333 case VAR: 334 case REF: 335 if (s->level >= 3) { 336 printf("address\t0x%x\n", s->symvalue.offset); 337 } else { 338 printf("offset\t%d\n", s->symvalue.offset); 339 } 340 printf("size\t%d\n", size(s)); 341 break; 342 343 case RECORD: 344 case VARNT: 345 printf("size\t%d\n", s->symvalue.offset); 346 break; 347 348 case FIELD: 349 printf("offset\t%d\n", s->symvalue.field.offset); 350 printf("size\t%d\n", s->symvalue.field.length); 351 break; 352 353 case PROC: 354 case FUNC: 355 printf("address\t0x%x\n", s->symvalue.funcv.beginaddr); 356 if (nosource(s)) { 357 printf("does not have source information\n"); 358 } else { 359 printf("has source information\n"); 360 } 361 break; 362 363 case RANGE: 364 switch(s->symvalue.rangev.lowertype) { 365 366 case R_CONST : printf("CONST"); 367 break; 368 case R_ARG : printf("ARG"); 369 break; 370 case R_TEMP : printf("TEMP"); 371 break; 372 case R_ADJUST : printf("ADJUST"); 373 break; 374 } 375 printf("lower\t%d\n", s->symvalue.rangev.lower); 376 377 switch(s->symvalue.rangev.uppertype) { 378 379 case R_CONST : printf("CONST"); 380 break; 381 case R_ARG : printf("ARG"); 382 break; 383 case R_TEMP : printf("TEMP"); 384 break; 385 case R_ADJUST : printf("ADJUST"); 386 break; 387 } 388 389 printf("upper\t%d\n", s->symvalue.rangev.upper); 390 break; 391 392 default: 393 /* do nothing */ 394 break; 395 } 396 } 397 398 /* 399 * Print out the value on top of the stack according to the given type. 400 */ 401 402 public printval(t) 403 Symbol t; 404 { 405 Symbol s; 406 407 checkref(t); 408 switch (t->class) { 409 case PROC: 410 case FUNC: 411 s = pop(Symbol); 412 printf("%s", symname(s)); 413 break; 414 415 default: 416 if (t->language == nil) { 417 error("unknown language"); 418 } else { 419 (*language_op(t->language, L_PRINTVAL))(t); 420 } 421 break; 422 } 423 } 424 425 /* 426 * Print out the value of a record, field by field. 427 */ 428 429 public printrecord(s) 430 Symbol s; 431 { 432 if (s->chain == nil) { 433 error("record has no fields"); 434 } 435 printf("("); 436 sp -= size(s); 437 printfield(s->chain); 438 printf(")"); 439 } 440 441 /* 442 * Print out a field, first printing out other fields. 443 * This is done because the fields are chained together backwards. 444 */ 445 446 private printfield(s) 447 Symbol s; 448 { 449 Stack *savesp; 450 451 if (s->chain != nil) { 452 printfield(s->chain); 453 printf(", "); 454 } 455 printf("%s = ", symname(s)); 456 savesp = sp; 457 sp += ((s->symvalue.field.offset div BITSPERBYTE) + size(s->type)); 458 printval(s); 459 sp = savesp; 460 } 461 462 /* 463 * Print out the contents of an array. 464 * Haven't quite figured out what the best format is. 465 * 466 * This is rather inefficient. 467 * 468 * The "2*elsize" is there since "printval" drops the stack by elsize. 469 */ 470 471 public printarray(a) 472 Symbol a; 473 { 474 Stack *savesp, *newsp; 475 Symbol eltype; 476 long elsize; 477 String sep; 478 479 savesp = sp; 480 sp -= (size(a)); 481 newsp = sp; 482 eltype = rtype(a->type); 483 elsize = size(eltype); 484 printf("("); 485 if (eltype->class == RECORD or eltype->class == ARRAY or 486 eltype->class == VARNT) { 487 sep = "\n"; 488 putchar('\n'); 489 } else { 490 sep = ", "; 491 } 492 for (sp += elsize; sp <= savesp; sp += 2*elsize) { 493 if (sp - elsize != newsp) { 494 fputs(sep, stdout); 495 } 496 printval(eltype); 497 } 498 sp = newsp; 499 if (streq(sep, "\n")) { 500 putchar('\n'); 501 } 502 printf(")"); 503 } 504 505 /* 506 * Print out the value of a real number in Pascal notation. 507 * This is, unfortunately, different than what one gets 508 * from "%g" in printf. 509 */ 510 511 public prtreal(r) 512 double r; 513 { 514 extern char *index(); 515 char buf[256]; 516 517 sprintf(buf, "%g", r); 518 if (buf[0] == '.') { 519 printf("0%s", buf); 520 } else if (buf[0] == '-' and buf[1] == '.') { 521 printf("-0%s", &buf[1]); 522 } else { 523 printf("%s", buf); 524 } 525 if (index(buf, '.') == nil) { 526 printf(".0"); 527 } 528 } 529 530 /* 531 * Print out a character using ^? notation for unprintables. 532 */ 533 534 public printchar(c) 535 char c; 536 { 537 if (c == 0) { 538 putchar('\\'); 539 putchar('0'); 540 } else if (c == '\n') { 541 putchar('\\'); 542 putchar('n'); 543 } else if (c > 0 and c < ' ') { 544 putchar('^'); 545 putchar(c - 1 + 'A'); 546 } else { 547 putchar(c); 548 } 549 } 550