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