xref: /original-bsd/old/dbx/printsym.c (revision 6fcea464)
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.5 (Berkeley) 01/12/88";
9 #endif not lint
10 
11 static char rcsid[] = "$Header: printsym.c,v 1.4 87/04/15 00:23:35 donn 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", "array",
51     "dynarray", "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 OPENARRAY:
257 	case DYNARRAY:
258 	case SUBARRAY:
259 	    t = rtype(t->type);
260 	    if (compatible(t, t_char)) {
261 		printv(p, frame);
262 	    } else {
263 		printf("%s = (...)", symname(p));
264 	    }
265 	    break;
266 
267 	case RECORD:
268 	    printf("%s = (...)", symname(p));
269 	    break;
270 
271 	default:
272 	    printv(p, frame);
273 	    break;
274     }
275 }
276 
277 /*
278  * Print the name and value of a variable.
279  */
280 
281 public printv(s, frame)
282 Symbol s;
283 Frame frame;
284 {
285     Address addr;
286     int len;
287 
288     if (isambiguous(s) and ismodule(container(s))) {
289 	printname(stdout, s);
290 	printf(" = ");
291     } else {
292 	printf("%s = ", symname(s));
293     }
294     if (isvarparam(s) and not isopenarray(s)) {
295 	rpush(address(s, frame), sizeof(Address));
296 	addr = pop(Address);
297     } else {
298 	addr = address(s, frame);
299     }
300     len = size(s);
301     if (not canpush(len)) {
302 	printf("*** expression too large ***");
303     } else if (isreg(s)) {
304 	push(Address, addr);
305 	printval(s->type);
306     } else {
307 	rpush(addr, len);
308 	printval(s->type);
309     }
310 }
311 
312 /*
313  * Print out the name of a symbol.
314  */
315 
316 public printname(f, s)
317 File f;
318 Symbol s;
319 {
320     if (s == nil) {
321 	fprintf(f, "(noname)");
322     } else if (s == program) {
323 	fprintf(f, ".");
324     } else if (isredirected() or isambiguous(s)) {
325 	printwhich(f, s);
326     } else {
327 	fprintf(f, "%s", symname(s));
328     }
329 }
330 
331 /*
332  * Print the fully specified variable that is described by the given identifer.
333  */
334 
335 public printwhich(f, s)
336 File f;
337 Symbol s;
338 {
339     printouter(f, container(s));
340     fprintf(f, "%s", symname(s));
341 }
342 
343 /*
344  * Print the fully qualified name of each symbol that has the same name
345  * as the given symbol.
346  */
347 
348 public printwhereis(f, s)
349 File f;
350 Symbol s;
351 {
352     register Name n;
353     register Symbol t;
354 
355     checkref(s);
356     n = s->name;
357     t = lookup(n);
358     printwhich(f, t);
359     t = t->next_sym;
360     while (t != nil) {
361 	if (t->name == n) {
362 	    putc(' ', f);
363 	    printwhich(f, t);
364 	}
365 	t = t->next_sym;
366     }
367     putc('\n', f);
368 }
369 
370 private printouter(f, s)
371 File f;
372 Symbol s;
373 {
374     Symbol outer;
375 
376     if (s != nil) {
377 	outer = container(s);
378 	if (outer != nil and outer != program) {
379 	    printouter(f, outer);
380 	}
381 	fprintf(f, "%s.", symname(s));
382     }
383 }
384 
385 public printdecl(s)
386 Symbol s;
387 {
388     Language lang;
389 
390     checkref(s);
391     if (s->language == nil or s->language == primlang) {
392 	lang = findlanguage(".s");
393     } else {
394 	lang = s->language;
395     }
396     (*language_op(lang, L_PRINTDECL))(s);
397 }
398 
399 /*
400  * Straight dump of symbol information.
401  */
402 
403 public psym(s)
404 Symbol s;
405 {
406     printf("name\t%s\n", symname(s));
407     printf("lang\t%s\n", language_name(s->language));
408     printf("level\t%d\n", s->level);
409     printf("class\t%s\n", classname(s));
410     printf("type\t0x%x", s->type);
411     if (s->type != nil and s->type->name != nil) {
412 	printf(" (%s)", symname(s->type));
413     }
414     printf("\nchain\t0x%x", s->chain);
415     if (s->chain != nil and s->chain->name != nil) {
416 	printf(" (%s)", symname(s->chain));
417     }
418     printf("\nblock\t0x%x", s->block);
419     if (s->block != nil and s->block->name != nil) {
420 	printf(" (");
421 	printname(stdout, s->block);
422 	putchar(')');
423     }
424     putchar('\n');
425     switch (s->class) {
426 	case TYPE:
427 	    printf("size\t%d\n", size(s));
428 	    break;
429 
430 	case VAR:
431 	case REF:
432 	    switch (s->storage) {
433 		case INREG:
434 		    printf("reg\t%d\n", s->symvalue.offset);
435 		    break;
436 
437 		case STK:
438 		    printf("offset\t%d\n", s->symvalue.offset);
439 		    break;
440 
441 		case EXT:
442 		    printf("address\t0x%x\n", s->symvalue.offset);
443 		    break;
444 	    }
445 	    printf("size\t%d\n", size(s));
446 	    break;
447 
448 	case RECORD:
449 	case VARNT:
450 	    printf("size\t%d\n", s->symvalue.offset);
451 	    break;
452 
453 	case FIELD:
454 	    printf("offset\t%d\n", s->symvalue.field.offset);
455 	    printf("size\t%d\n", s->symvalue.field.length);
456 	    break;
457 
458 	case PROG:
459 	case PROC:
460 	case FUNC:
461 	    printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
462 	    if (isinline(s)) {
463 		printf("inline procedure\n");
464 	    }
465 	    if (nosource(s)) {
466 		printf("does not have source information\n");
467 	    } else {
468 		printf("has source information\n");
469 	    }
470 	    break;
471 
472 	case RANGE:
473 	    prangetype(s->symvalue.rangev.lowertype);
474 	    printf("lower\t%d\n", s->symvalue.rangev.lower);
475 	    prangetype(s->symvalue.rangev.uppertype);
476 	    printf("upper\t%d\n", s->symvalue.rangev.upper);
477 	    break;
478 
479 	default:
480 	    /* do nothing */
481 	    break;
482     }
483 }
484 
485 private prangetype(r)
486 Rangetype r;
487 {
488     switch (r) {
489 	case R_CONST:
490 	    printf("CONST");
491 	    break;
492 
493 	case R_ARG:
494 	    printf("ARG");
495 	    break;
496 
497 	case R_TEMP:
498 	    printf("TEMP");
499 	    break;
500 
501 	case R_ADJUST:
502 	    printf("ADJUST");
503 	    break;
504     }
505 }
506 
507 /*
508  * Print out the value on top of the stack according to the given type.
509  */
510 
511 public printval(t)
512 Symbol t;
513 {
514     Symbol s;
515 
516     checkref(t);
517     if (t->class == TYPEREF) {
518 	resolveRef(t);
519     }
520     switch (t->class) {
521 	case PROC:
522 	case FUNC:
523 	    s = pop(Symbol);
524 	    printf("%s", symname(s));
525 	    break;
526 
527 	default:
528 	    if (t->language == nil or t->language == primlang) {
529 		(*language_op(findlanguage(".c"), L_PRINTVAL))(t);
530 	    } else {
531 		(*language_op(t->language, L_PRINTVAL))(t);
532 	    }
533 	    break;
534     }
535 }
536 
537 /*
538  * Print out the value of a record, field by field.
539  */
540 
541 public printrecord(s)
542 Symbol s;
543 {
544     Symbol f;
545 
546     if (s->chain == nil) {
547 	error("record has no fields");
548     }
549     printf("(");
550     sp -= size(s);
551     f = s->chain;
552     if (f != nil) {
553 	for (;;) {
554 	    printfield(f);
555 	    f = f->chain;
556 	if (f == nil) break;
557 	    printf(", ");
558 	}
559     }
560     printf(")");
561 }
562 
563 /*
564  * Print out a field.
565  */
566 
567 private printfield(f)
568 Symbol f;
569 {
570     Stack *savesp;
571     register int off, len;
572 
573     printf("%s = ", symname(f));
574     savesp = sp;
575     off = f->symvalue.field.offset;
576     len = f->symvalue.field.length;
577     sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE);
578     printval(f);
579     sp = savesp;
580 }
581 
582 /*
583  * Print out the contents of an array.
584  * Haven't quite figured out what the best format is.
585  *
586  * This is rather inefficient.
587  *
588  * The "2*elsize" is there since "printval" drops the stack by elsize.
589  */
590 
591 public printarray(a)
592 Symbol a;
593 {
594     Stack *savesp, *newsp;
595     Symbol eltype;
596     long elsize;
597     String sep;
598 
599     savesp = sp;
600     sp -= (size(a));
601     newsp = sp;
602     eltype = rtype(a->type);
603     elsize = size(eltype);
604     printf("(");
605     if (eltype->class == RECORD or eltype->class == ARRAY or
606       eltype->class == VARNT) {
607 	sep = "\n";
608 	putchar('\n');
609     } else {
610 	sep = ", ";
611     }
612     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
613 	if (sp - elsize != newsp) {
614 	    fputs(sep, stdout);
615 	}
616 	printval(eltype);
617     }
618     sp = newsp;
619     if (streq(sep, "\n")) {
620 	putchar('\n');
621     }
622     printf(")");
623 }
624 
625 /*
626  * Print out the value of a real number in Pascal notation.
627  * This is, unfortunately, different than what one gets
628  * from "%g" in printf.
629  */
630 
631 public prtreal(r)
632 double r;
633 {
634     extern char *index();
635     char buf[256];
636 
637 #   ifdef IRIS
638 	sprintf(buf, "%lg", r);
639 #   else
640 	sprintf(buf, "%g", r);
641 #   endif
642     if (buf[0] == '.') {
643 	printf("0%s", buf);
644     } else if (buf[0] == '-' and buf[1] == '.') {
645 	printf("-0%s", &buf[1]);
646     } else {
647 	printf("%s", buf);
648     }
649     if (index(buf, '.') == nil) {
650 	printf(".0");
651     }
652 }
653 
654 /*
655  * Print out a character using ^? notation for unprintables.
656  */
657 
658 public printchar(c)
659 char c;
660 {
661     if (c == 0) {
662 	putchar('\\');
663 	putchar('0');
664     } else if (c == '\n') {
665 	putchar('\\');
666 	putchar('n');
667     } else if (c > 0 and c < ' ') {
668 	putchar('^');
669 	putchar(c - 1 + 'A');
670     } else if (c >= ' ' && c <= '~') {
671 	putchar(c);
672     } else {
673 	printf("\\0%o",c&0xff);
674     }
675 }
676 
677 /*
678  * Print out a value for a range type (integer, char, or boolean).
679  */
680 
681 public printRangeVal (val, t)
682 long val;
683 Symbol t;
684 {
685     if (t == t_boolean->type or istypename(t->type, "boolean")) {
686 	if ((boolean) val) {
687 	    printf("true");
688 	} else {
689 	    printf("false");
690 	}
691     } else if (t == t_char->type or istypename(t->type, "char")) {
692 	if (varIsSet("$hexchars")) {
693 	    printf("0x%lx", val);
694 	} else {
695 	    putchar('\'');
696 	    printchar(val);
697 	    putchar('\'');
698 	}
699     } else if (varIsSet("$hexints")) {
700 	printf("0x%lx", val);
701     } else if (t->symvalue.rangev.lower >= 0) {
702 	printf("%lu", val);
703     } else {
704 	printf("%ld", val);
705     }
706 }
707 
708 /*
709  * Print out an enumerated value by finding the corresponding
710  * name in the enumeration list.
711  */
712 
713 public printEnum (i, t)
714 integer i;
715 Symbol t;
716 {
717     register Symbol e;
718 
719     e = t->chain;
720     while (e != nil and e->symvalue.constval->value.lcon != i) {
721 	e = e->chain;
722     }
723     if (e != nil) {
724 	printf("%s", symname(e));
725     } else {
726 	printf("%d", i);
727     }
728 }
729 
730 /*
731  * Print out a null-terminated string (pointer to char)
732  * starting at the given address.
733  */
734 
735 public printString (addr, quotes)
736 Address addr;
737 boolean quotes;
738 {
739     register Address a;
740     register integer i, len;
741     register boolean endofstring;
742     register int unprintables;
743 #define	MAXGARBAGE	4
744     union {
745 	char ch[sizeof(Word)];
746 	int word;
747     } u;
748 
749     if (varIsSet("$hexstrings")) {
750 	printf("0x%x", addr);
751     } else {
752 	if (quotes) {
753 	    putchar('"');
754 	}
755 	a = addr;
756 	unprintables = 0;
757 	endofstring = false;
758 	while (not endofstring) {
759 	    dread(&u, a, sizeof(u));
760 	    i = 0;
761 	    do {
762 		if (u.ch[i] == '\0') {
763 		    endofstring = true;
764 		} else {
765 		    printchar(u.ch[i]);
766 		    if (!isascii(u.ch[i]) and ++unprintables > MAXGARBAGE) {
767 			endofstring = true;
768 			printf("...");
769 		    }
770 		}
771 		++i;
772 	    } while (i < sizeof(Word) and not endofstring);
773 	    a += sizeof(Word);
774 	}
775 	if (quotes) {
776 	    putchar('"');
777 	}
778     }
779 }
780