xref: /csrg-svn/old/dbx/printsym.c (revision 14381)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)printsym.c 1.10 08/05/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 && (!istypename(s->type,"void"))) {
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 	    if (isparam(s)) {
182 		b = false;
183 	    } else {
184 		t = rtype(s->type);
185 		if (t == nil) {
186 		    b = false;
187 		} else {
188 		    switch (t->class) {
189 			case FILET:
190 			case SET:
191 			case BADUSE:
192 			    b = false;
193 			    break;
194 
195 			default:
196 			    b = true;
197 			    break;
198 		    }
199 		}
200 	    }
201 	    break;
202 
203 	default:
204 	    b = false;
205 	    break;
206     }
207     return b;
208 }
209 
210 /*
211  * Print the name and value of a variable.
212  */
213 
214 public printv(s, frame)
215 Symbol s;
216 Frame frame;
217 {
218     Address addr;
219     int len;
220 
221     if (isambiguous(s) and ismodule(container(s))) {
222 	printname(stdout, s);
223 	printf(" = ");
224     } else {
225 	printf("%s = ", symname(s));
226     }
227     if(s->type->class == ARRAY && (! istypename(s->type->type,"char")) ) {
228 	printf(" ARRAY ");
229     } else {
230        if (isvarparam(s)) {
231 	   rpush(address(s, frame), sizeof(Address));
232 	   addr = pop(Address);
233 	   len = size(s->type);
234        } else {
235 	   addr = address(s, frame);
236 	   len = size(s);
237        }
238        if (canpush(len)) {
239 	   rpush(addr, len);
240 	   printval(s->type);
241        } else {
242 	   printf("*** expression too large ***");
243        }
244    }
245 }
246 
247 /*
248  * Print out the name of a symbol.
249  */
250 
251 public printname(f, s)
252 File f;
253 Symbol s;
254 {
255     if (s == nil) {
256 	fprintf(f, "(noname)");
257     } else if (isredirected() or isambiguous(s)) {
258 	printwhich(f, s);
259     } else {
260 	fprintf(f, "%s", symname(s));
261     }
262 }
263 
264 /*
265  * Print the fully specified variable that is described by the given identifer.
266  */
267 
268 public printwhich(f, s)
269 File f;
270 Symbol s;
271 {
272     printouter(f, container(s));
273     fprintf(f, "%s", symname(s));
274 }
275 
276 /*
277  * Print the fully qualified name of each symbol that has the same name
278  * as the given symbol.
279  */
280 
281 public printwhereis(f, s)
282 File f;
283 Symbol s;
284 {
285     register Name n;
286     register Symbol t;
287 
288     checkref(s);
289     n = s->name;
290     t = lookup(n);
291     printwhich(f, t);
292     t = t->next_sym;
293     while (t != nil) {
294 	if (t->name == n) {
295 	    putc(' ', f);
296 	    printwhich(f, t);
297 	}
298 	t = t->next_sym;
299     }
300     putc('\n', f);
301 }
302 
303 private printouter(f, s)
304 File f;
305 Symbol s;
306 {
307     Symbol outer;
308 
309     if (s != nil) {
310 	outer = container(s);
311 	if (outer != nil and outer != program) {
312 	    printouter(f, outer);
313 	}
314 	fprintf(f, "%s.", symname(s));
315     }
316 }
317 
318 public printdecl(s)
319 Symbol s;
320 {
321     checkref(s);
322     (*language_op(s->language, L_PRINTDECL))(s);
323 }
324 
325 /*
326  * Straight dump of symbol information.
327  */
328 
329 public psym(s)
330 Symbol s;
331 {
332     printf("name\t%s\n", symname(s));
333     printf("lang\t%s\n", language_name(s->language));
334     printf("level\t%d\n", s->level);
335     printf("class\t%s\n", classname(s));
336     printf("type\t0x%x", s->type);
337     if (s->type != nil and s->type->name != nil) {
338 	printf(" (%s)", symname(s->type));
339     }
340     printf("\nchain\t0x%x", s->chain);
341     if (s->chain != nil and s->chain->name != nil) {
342 	printf(" (%s)", symname(s->chain));
343     }
344     printf("\nblock\t0x%x", s->block);
345     if (s->block->name != nil) {
346 	printf(" (");
347 	printname(stdout, s->block);
348 	putchar(')');
349     }
350     putchar('\n');
351     switch (s->class) {
352 	case VAR:
353 	case REF:
354 	    if (s->level >= 3) {
355 		printf("address\t0x%x\n", s->symvalue.offset);
356 	    } else {
357 		printf("offset\t%d\n", s->symvalue.offset);
358 	    }
359 	    printf("size\t%d\n", size(s));
360 	    break;
361 
362 	case RECORD:
363 	case VARNT:
364 	    printf("size\t%d\n", s->symvalue.offset);
365 	    break;
366 
367 	case FIELD:
368 	    printf("offset\t%d\n", s->symvalue.field.offset);
369 	    printf("size\t%d\n", s->symvalue.field.length);
370 	    break;
371 
372 	case PROG:
373 	case PROC:
374 	case FUNC:
375 	    printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
376 	    if (nosource(s)) {
377 		printf("does not have source information\n");
378 	    } else {
379 		printf("has source information\n");
380 	    }
381 	    break;
382 
383 	case RANGE:
384 
385 	    prangetype(s->symvalue.rangev.lowertype);
386 	    printf("lower\t%d\n", s->symvalue.rangev.lower);
387 	    prangetype(s->symvalue.rangev.uppertype);
388 	    printf("upper\t%d\n", s->symvalue.rangev.upper);
389 	    break;
390 
391 	default:
392 	    /* do nothing */
393 	    break;
394     }
395 }
396 
397 private prangetype(r)
398 Rangetype r;
399 {
400     switch (r) {
401 	case R_CONST:
402 	    printf("CONST");
403 	    break;
404 
405 	case R_ARG:
406 	    printf("ARG");
407 	    break;
408 
409 	case R_TEMP:
410 	    printf("TEMP");
411 	    break;
412 
413 	case R_ADJUST:
414 	    printf("ADJUST");
415 	    break;
416     }
417 }
418 
419 /*
420  * Print out the value on top of the stack according to the given type.
421  */
422 
423 public printval(t)
424 Symbol t;
425 {
426     Symbol s;
427 
428     checkref(t);
429     switch (t->class) {
430 	case PROC:
431 	case FUNC:
432 	    s = pop(Symbol);
433 	    printf("%s", symname(s));
434 	    break;
435 
436 	default:
437 	    if (t->language == nil) {
438 		error("unknown language");
439 	    } else {
440 		(*language_op(t->language, L_PRINTVAL))(t);
441 	    }
442 	    break;
443     }
444 }
445 
446 /*
447  * Print out the value of a record, field by field.
448  */
449 
450 public printrecord(s)
451 Symbol s;
452 {
453     if (s->chain == nil) {
454 	error("record has no fields");
455     }
456     printf("(");
457     sp -= size(s);
458     printfield(s->chain);
459     printf(")");
460 }
461 
462 /*
463  * Print out a field, first printing out other fields.
464  * This is done because the fields are chained together backwards.
465  */
466 
467 private printfield(s)
468 Symbol s;
469 {
470     Stack *savesp;
471 
472     if (s->chain != nil) {
473 	printfield(s->chain);
474 	printf(", ");
475     }
476     printf("%s = ", symname(s));
477     savesp = sp;
478     sp += ((s->symvalue.field.offset div BITSPERBYTE) + size(s->type));
479     printval(s);
480     sp = savesp;
481 }
482 
483 /*
484  * Print out the contents of an array.
485  * Haven't quite figured out what the best format is.
486  *
487  * This is rather inefficient.
488  *
489  * The "2*elsize" is there since "printval" drops the stack by elsize.
490  */
491 
492 public printarray(a)
493 Symbol a;
494 {
495     Stack *savesp, *newsp;
496     Symbol eltype;
497     long elsize;
498     String sep;
499 
500     savesp = sp;
501     sp -= (size(a));
502     newsp = sp;
503     eltype = rtype(a->type);
504     elsize = size(eltype);
505     printf("(");
506     if (eltype->class == RECORD or eltype->class == ARRAY or
507       eltype->class == VARNT) {
508 	sep = "\n";
509 	putchar('\n');
510     } else {
511 	sep = ", ";
512     }
513     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
514 	if (sp - elsize != newsp) {
515 	    fputs(sep, stdout);
516 	}
517 	printval(eltype);
518     }
519     sp = newsp;
520     if (streq(sep, "\n")) {
521 	putchar('\n');
522     }
523     printf(")");
524 }
525 
526 /*
527  * Print out the value of a real number in Pascal notation.
528  * This is, unfortunately, different than what one gets
529  * from "%g" in printf.
530  */
531 
532 public prtreal(r)
533 double r;
534 {
535     extern char *index();
536     char buf[256];
537 
538     sprintf(buf, "%g", r);
539     if (buf[0] == '.') {
540 	printf("0%s", buf);
541     } else if (buf[0] == '-' and buf[1] == '.') {
542 	printf("-0%s", &buf[1]);
543     } else {
544 	printf("%s", buf);
545     }
546     if (index(buf, '.') == nil) {
547 	printf(".0");
548     }
549 }
550 
551 /*
552  * Print out a character using ^? notation for unprintables.
553  */
554 
555 public printchar(c)
556 char c;
557 {
558     if (c == 0) {
559 	putchar('\\');
560 	putchar('0');
561     } else if (c == '\n') {
562 	putchar('\\');
563 	putchar('n');
564     } else if (c > 0 and c < ' ') {
565 	putchar('^');
566 	putchar(c - 1 + 'A');
567     } else {
568 	putchar(c);
569     }
570 }
571