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