xref: /csrg-svn/old/dbx/printsym.c (revision 16616)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)printsym.c 1.12 8/10/83";
4 
5 static char rcsid[] = "$Header: printsym.c,v 1.3 84/03/27 10:23:14 linton Exp $";
6 
7 /*
8  * Printing of symbolic information.
9  */
10 
11 #include "defs.h"
12 #include "symbols.h"
13 #include "languages.h"
14 #include "printsym.h"
15 #include "tree.h"
16 #include "eval.h"
17 #include "mappings.h"
18 #include "process.h"
19 #include "runtime.h"
20 #include "machine.h"
21 #include "names.h"
22 #include "main.h"
23 
24 #ifndef public
25 #endif
26 
27 /*
28  * Maximum number of arguments to a function.
29  * This is used as a check for the possibility that the stack has been
30  * overwritten and therefore a saved argument pointer might indicate
31  * to an absurdly large number of arguments.
32  */
33 
34 #define MAXARGSPASSED 20
35 
36 /*
37  * Return a pointer to the string for the name of the class that
38  * the given symbol belongs to.
39  */
40 
41 private String clname[] = {
42     "bad use", "constant", "type", "variable", "array", "fileptr",
43     "record", "field", "procedure", "function", "funcvar",
44     "ref", "pointer", "file", "set", "range", "label", "withptr",
45     "scalar", "string", "program", "improper", "variant",
46     "procparam", "funcparam", "module", "tag", "common", "extref", "typeref"
47 };
48 
49 public String classname(s)
50 Symbol s;
51 {
52     return clname[ord(s->class)];
53 }
54 
55 /*
56  * Note the entry of the given block, unless it's the main program.
57  */
58 
59 public printentry(s)
60 Symbol s;
61 {
62     if (s != program) {
63 	printf("\nentering %s %s\n", classname(s), symname(s));
64     }
65 }
66 
67 /*
68  * Note the exit of the given block
69  */
70 
71 public printexit(s)
72 Symbol s;
73 {
74     if (s != program) {
75 	printf("leaving %s %s\n\n", classname(s), symname(s));
76     }
77 }
78 
79 /*
80  * Note the call of s from t.
81  */
82 
83 public printcall(s, t)
84 Symbol s, t;
85 {
86     printf("calling %s", symname(s));
87     printparams(s, nil);
88     printf(" from %s %s\n", classname(t), symname(t));
89 }
90 
91 /*
92  * Note the return from s.  If s is a function, print the value
93  * it is returning.  This is somewhat painful, since the function
94  * has actually just returned.
95  */
96 
97 public printrtn(s)
98 Symbol s;
99 {
100     register Symbol t;
101     register int len;
102     Boolean isindirect;
103 
104     printf("returning ");
105     if (s->class == FUNC && (!istypename(s->type,"void"))) {
106 	len = size(s->type);
107 	if (canpush(len)) {
108 	    t = rtype(s->type);
109 	    isindirect = (Boolean) (t->class == RECORD or t->class == VARNT);
110 	    pushretval(len, isindirect);
111 	    printval(s->type);
112 	    putchar(' ');
113 	} else {
114 	    printf("(value too large) ");
115 	}
116     }
117     printf("from %s\n", symname(s));
118 }
119 
120 /*
121  * Print the values of the parameters of the given procedure or function.
122  * The frame distinguishes recursive instances of a procedure.
123  *
124  * If the procedure or function is internal, the argument count is
125  * not valid so we ignore it.
126  */
127 
128 public printparams(f, frame)
129 Symbol f;
130 Frame frame;
131 {
132     Symbol param;
133     int n, m, s;
134 
135     n = nargspassed(frame);
136     if (isinternal(f)) {
137 	n = 0;
138     }
139     param = f->chain;
140     if (param != nil or n > 0) {
141 	printf("(");
142 	m = n;
143 	if (param != nil) {
144 	    for (;;) {
145 		s = size(param) div sizeof(Word);
146 		if (s == 0) {
147 		    s = 1;
148 		}
149 		m -= s;
150 		printv(param, frame);
151 		param = param->chain;
152 	    if (param == nil) break;
153 		printf(", ");
154 	    }
155 	}
156 	if (m > 0) {
157 	    if (m > MAXARGSPASSED) {
158 		m = MAXARGSPASSED;
159 	    }
160 	    if (f->chain != nil) {
161 		printf(", ");
162 	    }
163 	    for (;;) {
164 		--m;
165 		printf("0x%x", argn(n - m, frame));
166 	    if (m <= 0) break;
167 		printf(", ");
168 	    }
169 	}
170 	printf(")");
171     }
172 }
173 
174 /*
175  * Test if a symbol should be printed.  We don't print files,
176  * for example, simply because there's no good way to do it.
177  * The symbol must be within the given function.
178  */
179 
180 public Boolean should_print(s)
181 Symbol s;
182 {
183     Boolean b;
184     register Symbol t;
185 
186     switch (s->class) {
187 	case VAR:
188 	case FVAR:
189 	    if (isparam(s)) {
190 		b = false;
191 	    } else {
192 		t = rtype(s->type);
193 		if (t == nil) {
194 		    b = false;
195 		} else {
196 		    switch (t->class) {
197 			case FILET:
198 			case SET:
199 			case BADUSE:
200 			    b = false;
201 			    break;
202 
203 			default:
204 			    b = true;
205 			    break;
206 		    }
207 		}
208 	    }
209 	    break;
210 
211 	default:
212 	    b = false;
213 	    break;
214     }
215     return b;
216 }
217 
218 /*
219  * Print the name and value of a variable.
220  */
221 
222 public printv(s, frame)
223 Symbol s;
224 Frame frame;
225 {
226     Address addr;
227     int len;
228     Symbol t;
229 
230     if (isambiguous(s) and ismodule(container(s))) {
231 	printname(stdout, s);
232 	printf(" = ");
233     } else {
234 	printf("%s = ", symname(s));
235     }
236 /*
237  * Not today.
238     t = rtype(s->type);
239     if (t->class == ARRAY and not istypename(t->type, "char")) {
240 	printf("ARRAY");
241     } else {
242  */
243        if (isvarparam(s)) {
244 	   rpush(address(s, frame), sizeof(Address));
245 	   addr = pop(Address);
246 	   len = size(s->type);
247        } else {
248 	   addr = address(s, frame);
249 	   len = size(s);
250        }
251        if (canpush(len)) {
252 	   rpush(addr, len);
253 	   printval(s->type);
254        } else {
255 	   printf("*** expression too large ***");
256        }
257 /*
258  * Matches brace commented out above.
259    }
260  */
261 }
262 
263 /*
264  * Print out the name of a symbol.
265  */
266 
267 public printname(f, s)
268 File f;
269 Symbol s;
270 {
271     if (s == nil) {
272 	fprintf(f, "(noname)");
273     } else if (s == program) {
274 	fprintf(f, ".");
275     } else if (isredirected() or isambiguous(s)) {
276 	printwhich(f, s);
277     } else {
278 	fprintf(f, "%s", symname(s));
279     }
280 }
281 
282 /*
283  * Print the fully specified variable that is described by the given identifer.
284  */
285 
286 public printwhich(f, s)
287 File f;
288 Symbol s;
289 {
290     printouter(f, container(s));
291     fprintf(f, "%s", symname(s));
292 }
293 
294 /*
295  * Print the fully qualified name of each symbol that has the same name
296  * as the given symbol.
297  */
298 
299 public printwhereis(f, s)
300 File f;
301 Symbol s;
302 {
303     register Name n;
304     register Symbol t;
305 
306     checkref(s);
307     n = s->name;
308     t = lookup(n);
309     printwhich(f, t);
310     t = t->next_sym;
311     while (t != nil) {
312 	if (t->name == n) {
313 	    putc(' ', f);
314 	    printwhich(f, t);
315 	}
316 	t = t->next_sym;
317     }
318     putc('\n', f);
319 }
320 
321 private printouter(f, s)
322 File f;
323 Symbol s;
324 {
325     Symbol outer;
326 
327     if (s != nil) {
328 	outer = container(s);
329 	if (outer != nil and outer != program) {
330 	    printouter(f, outer);
331 	}
332 	fprintf(f, "%s.", symname(s));
333     }
334 }
335 
336 public printdecl(s)
337 Symbol s;
338 {
339     checkref(s);
340     (*language_op(s->language, L_PRINTDECL))(s);
341 }
342 
343 /*
344  * Straight dump of symbol information.
345  */
346 
347 public psym(s)
348 Symbol s;
349 {
350     printf("name\t%s\n", symname(s));
351     printf("lang\t%s\n", language_name(s->language));
352     printf("level\t%d\n", s->level);
353     printf("class\t%s\n", classname(s));
354     printf("type\t0x%x", s->type);
355     if (s->type != nil and s->type->name != nil) {
356 	printf(" (%s)", symname(s->type));
357     }
358     printf("\nchain\t0x%x", s->chain);
359     if (s->chain != nil and s->chain->name != nil) {
360 	printf(" (%s)", symname(s->chain));
361     }
362     printf("\nblock\t0x%x", s->block);
363     if (s->block->name != nil) {
364 	printf(" (");
365 	printname(stdout, s->block);
366 	putchar(')');
367     }
368     putchar('\n');
369     switch (s->class) {
370 	case VAR:
371 	case REF:
372 	    if (s->level >= 3) {
373 		printf("address\t0x%x\n", s->symvalue.offset);
374 	    } else {
375 		printf("offset\t%d\n", s->symvalue.offset);
376 	    }
377 	    printf("size\t%d\n", size(s));
378 	    break;
379 
380 	case RECORD:
381 	case VARNT:
382 	    printf("size\t%d\n", s->symvalue.offset);
383 	    break;
384 
385 	case FIELD:
386 	    printf("offset\t%d\n", s->symvalue.field.offset);
387 	    printf("size\t%d\n", s->symvalue.field.length);
388 	    break;
389 
390 	case PROG:
391 	case PROC:
392 	case FUNC:
393 	    printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
394 	    if (isinline(s)) {
395 		printf("inline procedure\n");
396 	    }
397 	    if (nosource(s)) {
398 		printf("does not have source information\n");
399 	    } else {
400 		printf("has source information\n");
401 	    }
402 	    break;
403 
404 	case RANGE:
405 	    prangetype(s->symvalue.rangev.lowertype);
406 	    printf("lower\t%d\n", s->symvalue.rangev.lower);
407 	    prangetype(s->symvalue.rangev.uppertype);
408 	    printf("upper\t%d\n", s->symvalue.rangev.upper);
409 	    break;
410 
411 	default:
412 	    /* do nothing */
413 	    break;
414     }
415 }
416 
417 private prangetype(r)
418 Rangetype r;
419 {
420     switch (r) {
421 	case R_CONST:
422 	    printf("CONST");
423 	    break;
424 
425 	case R_ARG:
426 	    printf("ARG");
427 	    break;
428 
429 	case R_TEMP:
430 	    printf("TEMP");
431 	    break;
432 
433 	case R_ADJUST:
434 	    printf("ADJUST");
435 	    break;
436     }
437 }
438 
439 /*
440  * Print out the value on top of the stack according to the given type.
441  */
442 
443 public printval(t)
444 Symbol t;
445 {
446     Symbol s;
447 
448     checkref(t);
449     if (t->class == TYPEREF) {
450 	resolveRef(t);
451     }
452     switch (t->class) {
453 	case PROC:
454 	case FUNC:
455 	    s = pop(Symbol);
456 	    printf("%s", symname(s));
457 	    break;
458 
459 	default:
460 	    if (t->language == nil) {
461 		error("unknown language");
462 	    } else if (t->language == primlang) {
463 		(*language_op(findlanguage(".c"), L_PRINTVAL))(t);
464 	    } else {
465 		(*language_op(t->language, L_PRINTVAL))(t);
466 	    }
467 	    break;
468     }
469 }
470 
471 /*
472  * Print out the value of a record, field by field.
473  */
474 
475 public printrecord(s)
476 Symbol s;
477 {
478     Symbol f;
479 
480     if (s->chain == nil) {
481 	error("record has no fields");
482     }
483     printf("(");
484     sp -= size(s);
485     f = s->chain;
486     if (f != nil) {
487 	for (;;) {
488 	    printfield(f);
489 	    f = f->chain;
490 	if (f == nil) break;
491 	    printf(", ");
492 	}
493     }
494     printf(")");
495 }
496 
497 /*
498  * Print out a field.
499  */
500 
501 private printfield(f)
502 Symbol f;
503 {
504     Stack *savesp;
505     register int off, len;
506 
507     printf("%s = ", symname(f));
508     savesp = sp;
509     off = f->symvalue.field.offset;
510     len = f->symvalue.field.length;
511     sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE);
512     printval(f);
513     sp = savesp;
514 }
515 
516 /*
517  * Print out the contents of an array.
518  * Haven't quite figured out what the best format is.
519  *
520  * This is rather inefficient.
521  *
522  * The "2*elsize" is there since "printval" drops the stack by elsize.
523  */
524 
525 public printarray(a)
526 Symbol a;
527 {
528     Stack *savesp, *newsp;
529     Symbol eltype;
530     long elsize;
531     String sep;
532 
533     savesp = sp;
534     sp -= (size(a));
535     newsp = sp;
536     eltype = rtype(a->type);
537     elsize = size(eltype);
538     printf("(");
539     if (eltype->class == RECORD or eltype->class == ARRAY or
540       eltype->class == VARNT) {
541 	sep = "\n";
542 	putchar('\n');
543     } else {
544 	sep = ", ";
545     }
546     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
547 	if (sp - elsize != newsp) {
548 	    fputs(sep, stdout);
549 	}
550 	printval(eltype);
551     }
552     sp = newsp;
553     if (streq(sep, "\n")) {
554 	putchar('\n');
555     }
556     printf(")");
557 }
558 
559 /*
560  * Print out the value of a real number in Pascal notation.
561  * This is, unfortunately, different than what one gets
562  * from "%g" in printf.
563  */
564 
565 public prtreal(r)
566 double r;
567 {
568     extern char *index();
569     char buf[256];
570 
571     sprintf(buf, "%g", r);
572     if (buf[0] == '.') {
573 	printf("0%s", buf);
574     } else if (buf[0] == '-' and buf[1] == '.') {
575 	printf("-0%s", &buf[1]);
576     } else {
577 	printf("%s", buf);
578     }
579     if (index(buf, '.') == nil) {
580 	printf(".0");
581     }
582 }
583 
584 /*
585  * Print out a character using ^? notation for unprintables.
586  */
587 
588 public printchar(c)
589 char c;
590 {
591     if (c == 0) {
592 	putchar('\\');
593 	putchar('0');
594     } else if (c == '\n') {
595 	putchar('\\');
596 	putchar('n');
597     } else if (c > 0 and c < ' ') {
598 	putchar('^');
599 	putchar(c - 1 + 'A');
600     } else if (c >= ' ' && c <= '~') {
601 	putchar(c);
602     } else {
603 	printf("\\0%o",c);
604     }
605 }
606