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