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