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