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