xref: /csrg-svn/old/dbx/printsym.c (revision 12544)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)printsym.c 1.5 05/18/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", "tag", "common", "typeref"
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 	    break;
341 
342 	case RECORD:
343 	case VARNT:
344 	    printf("size\t%d\n", s->symvalue.offset);
345 	    break;
346 
347 	case FIELD:
348 	    printf("offset\t%d\n", s->symvalue.field.offset);
349 	    printf("size\t%d\n", s->symvalue.field.length);
350 	    break;
351 
352 	case PROC:
353 	case FUNC:
354 	    printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
355 	    if (nosource(s)) {
356 		printf("does not have source information\n");
357 	    } else {
358 		printf("has source information\n");
359 	    }
360 	    break;
361 
362 	case RANGE:
363             switch(s->symvalue.rangev.lowertype) {
364 
365 	      case R_CONST :  printf("CONST");
366 		              break;
367 	      case R_ARG :    printf("ARG");
368 			      break;
369 	      case R_TEMP :   printf("TEMP");
370 			      break;
371 	      case R_ADJUST : printf("ADJUST");
372 			      break;
373             }
374 	    printf("lower\t%d\n", s->symvalue.rangev.lower);
375 
376             switch(s->symvalue.rangev.uppertype) {
377 
378 	      case R_CONST :  printf("CONST");
379 		              break;
380 	      case R_ARG :    printf("ARG");
381 			      break;
382 	      case R_TEMP :   printf("TEMP");
383 			      break;
384 	      case R_ADJUST : printf("ADJUST");
385 			      break;
386             }
387 
388 	    printf("upper\t%d\n", s->symvalue.rangev.upper);
389 	    break;
390 
391 	default:
392 	    /* do nothing */
393 	    break;
394     }
395 }
396 
397 /*
398  * Print out the value on top of the stack according to the given type.
399  */
400 
401 public printval(t)
402 Symbol t;
403 {
404     Symbol s;
405 
406     checkref(t);
407     switch (t->class) {
408 	case PROC:
409 	case FUNC:
410 	    s = pop(Symbol);
411 	    printf("%s", symname(s));
412 	    break;
413 
414 	default:
415 	    if (t->language == nil) {
416 		error("unknown language");
417 	    } else {
418 		(*language_op(t->language, L_PRINTVAL))(t);
419 	    }
420 	    break;
421     }
422 }
423 
424 /*
425  * Print out the value of a record, field by field.
426  */
427 
428 public printrecord(s)
429 Symbol s;
430 {
431     if (s->chain == nil) {
432 	error("record has no fields");
433     }
434     printf("(");
435     sp -= size(s);
436     printfield(s->chain);
437     printf(")");
438 }
439 
440 /*
441  * Print out a field, first printing out other fields.
442  * This is done because the fields are chained together backwards.
443  */
444 
445 private printfield(s)
446 Symbol s;
447 {
448     Stack *savesp;
449 
450     if (s->chain != nil) {
451 	printfield(s->chain);
452 	printf(", ");
453     }
454     printf("%s = ", symname(s));
455     savesp = sp;
456     sp += ((s->symvalue.field.offset div BITSPERBYTE) + size(s->type));
457     printval(s);
458     sp = savesp;
459 }
460 
461 /*
462  * Print out the contents of an array.
463  * Haven't quite figured out what the best format is.
464  *
465  * This is rather inefficient.
466  *
467  * The "2*elsize" is there since "printval" drops the stack by elsize.
468  */
469 
470 public printarray(a)
471 Symbol a;
472 {
473     Stack *savesp, *newsp;
474     Symbol eltype;
475     long elsize;
476     String sep;
477 
478     savesp = sp;
479     sp -= (size(a));
480     newsp = sp;
481     eltype = rtype(a->type);
482     elsize = size(eltype);
483     printf("(");
484     if (eltype->class == RECORD or eltype->class == ARRAY or
485       eltype->class == VARNT) {
486 	sep = "\n";
487 	putchar('\n');
488     } else {
489 	sep = ", ";
490     }
491     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
492 	if (sp - elsize != newsp) {
493 	    fputs(sep, stdout);
494 	}
495 	printval(eltype);
496     }
497     sp = newsp;
498     if (streq(sep, "\n")) {
499 	putchar('\n');
500     }
501     printf(")");
502 }
503 
504 /*
505  * Print out the value of a real number in Pascal notation.
506  * This is, unfortunately, different than what one gets
507  * from "%g" in printf.
508  */
509 
510 public prtreal(r)
511 double r;
512 {
513     extern char *index();
514     char buf[256];
515 
516     sprintf(buf, "%g", r);
517     if (buf[0] == '.') {
518 	printf("0%s", buf);
519     } else if (buf[0] == '-' and buf[1] == '.') {
520 	printf("-0%s", &buf[1]);
521     } else {
522 	printf("%s", buf);
523     }
524     if (index(buf, '.') == nil) {
525 	printf(".0");
526     }
527 }
528 
529 /*
530  * Print out a character using ^? notation for unprintables.
531  */
532 
533 public printchar(c)
534 char c;
535 {
536     if (c == 0) {
537 	putchar('\\');
538 	putchar('0');
539     } else if (c == '\n') {
540 	putchar('\\');
541 	putchar('n');
542     } else if (c > 0 and c < ' ') {
543 	putchar('^');
544 	putchar(c - 1 + 'A');
545     } else {
546 	putchar(c);
547     }
548 }
549