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