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