xref: /original-bsd/old/dbx/printsym.c (revision 4b05c5c5)
1 /*
2  * Copyright (c) 1983 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)printsym.c	5.7 (Berkeley) 06/01/90";
10 #endif /* not lint */
11 
12 /*
13  * Printing of symbolic information.
14  */
15 
16 #include "defs.h"
17 #include "symbols.h"
18 #include "languages.h"
19 #include "printsym.h"
20 #include "tree.h"
21 #include "eval.h"
22 #include "mappings.h"
23 #include "process.h"
24 #include "runtime.h"
25 #include "machine.h"
26 #include "names.h"
27 #include "keywords.h"
28 #include "main.h"
29 #include <ctype.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", "array",
50     "dynarray", "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 OPENARRAY:
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 != nil and 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 	    switch (s->storage) {
432 		case INREG:
433 		    printf("reg\t%d\n", s->symvalue.offset);
434 		    break;
435 
436 		case STK:
437 		    printf("offset\t%d\n", s->symvalue.offset);
438 		    break;
439 
440 		case EXT:
441 		    printf("address\t0x%x\n", s->symvalue.offset);
442 		    break;
443 	    }
444 	    printf("size\t%d\n", size(s));
445 	    break;
446 
447 	case RECORD:
448 	case VARNT:
449 	    printf("size\t%d\n", s->symvalue.offset);
450 	    break;
451 
452 	case FIELD:
453 	    printf("offset\t%d\n", s->symvalue.field.offset);
454 	    printf("size\t%d\n", s->symvalue.field.length);
455 	    break;
456 
457 	case PROG:
458 	case PROC:
459 	case FUNC:
460 	    printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
461 	    if (isinline(s)) {
462 		printf("inline procedure\n");
463 	    }
464 	    if (nosource(s)) {
465 		printf("does not have source information\n");
466 	    } else {
467 		printf("has source information\n");
468 	    }
469 	    break;
470 
471 	case RANGE:
472 	    prangetype(s->symvalue.rangev.lowertype);
473 	    printf("lower\t%d\n", s->symvalue.rangev.lower);
474 	    prangetype(s->symvalue.rangev.uppertype);
475 	    printf("upper\t%d\n", s->symvalue.rangev.upper);
476 	    break;
477 
478 	default:
479 	    /* do nothing */
480 	    break;
481     }
482 }
483 
484 private prangetype(r)
485 Rangetype r;
486 {
487     switch (r) {
488 	case R_CONST:
489 	    printf("CONST");
490 	    break;
491 
492 	case R_ARG:
493 	    printf("ARG");
494 	    break;
495 
496 	case R_TEMP:
497 	    printf("TEMP");
498 	    break;
499 
500 	case R_ADJUST:
501 	    printf("ADJUST");
502 	    break;
503     }
504 }
505 
506 /*
507  * Print out the value on top of the stack according to the given type.
508  */
509 
510 public printval(t)
511 Symbol t;
512 {
513     Symbol s;
514 
515     checkref(t);
516     if (t->class == TYPEREF) {
517 	resolveRef(t);
518     }
519     switch (t->class) {
520 	case PROC:
521 	case FUNC:
522 	    s = pop(Symbol);
523 	    printf("%s", symname(s));
524 	    break;
525 
526 	default:
527 	    if (t->language == nil or t->language == primlang) {
528 		(*language_op(findlanguage(".c"), L_PRINTVAL))(t);
529 	    } else {
530 		(*language_op(t->language, L_PRINTVAL))(t);
531 	    }
532 	    break;
533     }
534 }
535 
536 /*
537  * Print out the value of a record, field by field.
538  */
539 
540 public printrecord(s)
541 Symbol s;
542 {
543     Symbol f;
544 
545     if (s->chain == nil) {
546 	error("record has no fields");
547     }
548     printf("(");
549     sp -= size(s);
550     f = s->chain;
551     if (f != nil) {
552 	for (;;) {
553 	    printfield(f);
554 	    f = f->chain;
555 	if (f == nil) break;
556 	    printf(", ");
557 	}
558     }
559     printf(")");
560 }
561 
562 /*
563  * Print out a field.
564  */
565 
566 private printfield(f)
567 Symbol f;
568 {
569     Stack *savesp;
570     register int off, len;
571 
572     printf("%s = ", symname(f));
573     savesp = sp;
574     off = f->symvalue.field.offset;
575     len = f->symvalue.field.length;
576     sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE);
577     printval(f);
578     sp = savesp;
579 }
580 
581 /*
582  * Print out the contents of an array.
583  * Haven't quite figured out what the best format is.
584  *
585  * This is rather inefficient.
586  *
587  * The "2*elsize" is there since "printval" drops the stack by elsize.
588  */
589 
590 public printarray(a)
591 Symbol a;
592 {
593     Stack *savesp, *newsp;
594     Symbol eltype;
595     long elsize;
596     String sep;
597 
598     savesp = sp;
599     sp -= (size(a));
600     newsp = sp;
601     eltype = rtype(a->type);
602     elsize = size(eltype);
603     printf("(");
604     if (eltype->class == RECORD or eltype->class == ARRAY or
605       eltype->class == VARNT) {
606 	sep = "\n";
607 	putchar('\n');
608     } else {
609 	sep = ", ";
610     }
611     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
612 	if (sp - elsize != newsp) {
613 	    fputs(sep, stdout);
614 	}
615 	printval(eltype);
616     }
617     sp = newsp;
618     if (streq(sep, "\n")) {
619 	putchar('\n');
620     }
621     printf(")");
622 }
623 
624 /*
625  * Print out the value of a real number in Pascal notation.
626  * This is, unfortunately, different than what one gets
627  * from "%g" in printf.
628  */
629 
630 public prtreal(r)
631 double r;
632 {
633     extern char *index();
634     char buf[256];
635 
636 #   ifdef IRIS
637 	sprintf(buf, "%lg", r);
638 #   else
639 	sprintf(buf, "%g", r);
640 #   endif
641     if (buf[0] == '.') {
642 	printf("0%s", buf);
643     } else if (buf[0] == '-' and buf[1] == '.') {
644 	printf("-0%s", &buf[1]);
645     } else {
646 	printf("%s", buf);
647     }
648     if (index(buf, '.') == nil) {
649 	printf(".0");
650     }
651 }
652 
653 /*
654  * Print out a character using ^? notation for unprintables.
655  */
656 
657 public printchar(c)
658 char c;
659 {
660     if (c == 0) {
661 	putchar('\\');
662 	putchar('0');
663     } else if (c == '\n') {
664 	putchar('\\');
665 	putchar('n');
666     } else if (c > 0 and c < ' ') {
667 	putchar('^');
668 	putchar(c - 1 + 'A');
669     } else if (c >= ' ' && c <= '~') {
670 	putchar(c);
671     } else {
672 	printf("\\0%o",c&0xff);
673     }
674 }
675 
676 /*
677  * Print out a value for a range type (integer, char, or boolean).
678  */
679 
680 public printRangeVal (val, t)
681 long val;
682 Symbol t;
683 {
684     if (t == t_boolean->type or istypename(t->type, "boolean")) {
685 	if ((boolean) val) {
686 	    printf("true");
687 	} else {
688 	    printf("false");
689 	}
690     } else if (t == t_char->type or istypename(t->type, "char")) {
691 	if (varIsSet("$hexchars")) {
692 	    printf("0x%lx", val);
693 	} else {
694 	    putchar('\'');
695 	    printchar(val);
696 	    putchar('\'');
697 	}
698     } else if (varIsSet("$hexints")) {
699 	printf("0x%lx", val);
700     } else if (t->symvalue.rangev.lower >= 0) {
701 	printf("%lu", val);
702     } else {
703 	printf("%ld", val);
704     }
705 }
706 
707 /*
708  * Print out an enumerated value by finding the corresponding
709  * name in the enumeration list.
710  */
711 
712 public printEnum (i, t)
713 integer i;
714 Symbol t;
715 {
716     register Symbol e;
717 
718     e = t->chain;
719     while (e != nil and e->symvalue.constval->value.lcon != i) {
720 	e = e->chain;
721     }
722     if (e != nil) {
723 	printf("%s", symname(e));
724     } else {
725 	printf("%d", i);
726     }
727 }
728 
729 /*
730  * Print out a null-terminated string (pointer to char)
731  * starting at the given address.
732  */
733 
734 public printString (addr, quotes)
735 Address addr;
736 boolean quotes;
737 {
738     register Address a;
739     register integer i, len;
740     register boolean endofstring;
741     register int unprintables;
742 #define	MAXGARBAGE	4
743     union {
744 	char ch[sizeof(Word)];
745 	int word;
746     } u;
747 
748     if (varIsSet("$hexstrings")) {
749 	printf("0x%x", addr);
750     } else {
751 	if (quotes) {
752 	    putchar('"');
753 	}
754 	a = addr;
755 	unprintables = 0;
756 	endofstring = false;
757 	while (not endofstring) {
758 	    dread(&u, a, sizeof(u));
759 	    i = 0;
760 	    do {
761 		if (u.ch[i] == '\0') {
762 		    endofstring = true;
763 		} else {
764 		    printchar(u.ch[i]);
765 		    if (!isascii(u.ch[i]) and ++unprintables > MAXGARBAGE) {
766 			endofstring = true;
767 			printf("...");
768 		    }
769 		}
770 		++i;
771 	    } while (i < sizeof(Word) and not endofstring);
772 	    a += sizeof(Word);
773 	}
774 	if (quotes) {
775 	    putchar('"');
776 	}
777     }
778 }
779