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