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