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