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