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