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