xref: /original-bsd/old/dbx/printsym.c (revision f0fd5f8a)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)printsym.c 1.2 12/15/82";
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  * Return a pointer to the string for the name of the class that
27  * the given symbol belongs to.
28  */
29 
30 private String clname[] = {
31     "bad use", "constant", "type", "variable", "array", "fileptr",
32     "record", "field", "procedure", "function", "funcvar",
33     "ref", "pointer", "file", "set", "range", "label", "withptr",
34     "scalar", "string", "program", "improper", "variant",
35     "procparam", "funcparam", "module", "typeref", "tag"
36 };
37 
38 public String classname(s)
39 Symbol s;
40 {
41     return clname[ord(s->class)];
42 }
43 
44 /*
45  * Note the entry of the given block, unless it's the main program.
46  */
47 
48 public printentry(s)
49 Symbol s;
50 {
51     if (s != program) {
52 	printf("\nentering %s %s\n", classname(s), symname(s));
53     }
54 }
55 
56 /*
57  * Note the exit of the given block
58  */
59 
60 public printexit(s)
61 Symbol s;
62 {
63     if (s != program) {
64 	printf("leaving %s %s\n\n", classname(s), symname(s));
65     }
66 }
67 
68 /*
69  * Note the call of s from t.
70  */
71 
72 public printcall(s, t)
73 Symbol s, t;
74 {
75     printf("calling %s", symname(s));
76     printparams(s, nil);
77     printf(" from %s %s\n", classname(t), symname(t));
78 }
79 
80 /*
81  * Note the return from s.  If s is a function, print the value
82  * it is returning.  This is somewhat painful, since the function
83  * has actually just returned.
84  */
85 
86 public printrtn(s)
87 Symbol s;
88 {
89     register Symbol t;
90     register int len;
91     Boolean isindirect;
92 
93     printf("returning ");
94     if (s->class == FUNC) {
95 	len = size(s->type);
96 	if (canpush(len)) {
97 	    t = rtype(s->type);
98 	    isindirect = (Boolean) (t->class == RECORD or t->class == VARNT);
99 	    pushretval(len, isindirect);
100 	    printval(s->type);
101 	    putchar(' ');
102 	} else {
103 	    printf("(value too large) ");
104 	}
105     }
106     printf("from %s\n", symname(s));
107 }
108 
109 /*
110  * Print the values of the parameters of the given procedure or function.
111  * The frame distinguishes recursive instances of a procedure.
112  */
113 
114 public printparams(f, frame)
115 Symbol f;
116 Frame frame;
117 {
118     Symbol param;
119     int n, m, s;
120 
121     n = nargspassed(frame);
122     param = f->chain;
123     if (param != nil or n > 0) {
124 	printf("(");
125 	m = n;
126 	if (param != nil) {
127 	    for (;;) {
128 		s = size(param) div sizeof(Word);
129 		if (s == 0) {
130 		    s = 1;
131 		}
132 		m -= s;
133 		printv(param, frame);
134 		param = param->chain;
135 	    if (param == nil) break;
136 		printf(", ");
137 	    }
138 	}
139 	if (m > 0) {
140 	    if (f->chain != nil) {
141 		printf(", ");
142 	    }
143 	    for (;;) {
144 		--m;
145 		printf("0x%x", argn(n - m, frame));
146 	    if (m <= 0) break;
147 		printf(", ");
148 	    }
149 	}
150 	printf(")");
151     }
152 }
153 
154 /*
155  * Test if a symbol should be printed.  We don't print files,
156  * for example, simply because there's no good way to do it.
157  * The symbol must be within the given function.
158  */
159 
160 public Boolean should_print(s)
161 Symbol s;
162 {
163     Boolean b;
164     register Symbol t;
165 
166     switch (s->class) {
167 	case VAR:
168 	case FVAR:
169 	    t = rtype(s->type);
170 	    b = (Boolean) (
171 		not isparam(s) and
172 		t != nil and t->class != FILET and t->class != SET
173 	    );
174 	    break;
175 
176 	default:
177 	    b = false;
178 	    break;
179     }
180     return b;
181 }
182 
183 /*
184  * Print the name and value of a variable.
185  */
186 
187 public printv(s, frame)
188 Symbol s;
189 Frame frame;
190 {
191     Address addr;
192     int len;
193 
194     if (isambiguous(s) and ismodule(container(s))) {
195 	printname(stdout, s);
196 	printf(" = ");
197     } else {
198 	printf("%s = ", symname(s));
199     }
200     if (isvarparam(s)) {
201 	rpush(address(s, frame), sizeof(Address));
202 	addr = pop(Address);
203 	len = size(s->type);
204     } else {
205 	addr = address(s, frame);
206 	len = size(s);
207     }
208     if (canpush(len)) {
209 	rpush(addr, len);
210 	printval(s->type);
211     } else {
212 	printf("*** expression too large ***");
213     }
214 }
215 
216 /*
217  * Print out the name of a symbol.
218  */
219 
220 public printname(f, s)
221 File f;
222 Symbol s;
223 {
224     if (s == nil) {
225 	fprintf(f, "(noname)");
226     } else if (isredirected() or isambiguous(s)) {
227 	printwhich(f, s);
228     } else {
229 	fprintf(f, "%s", symname(s));
230     }
231 }
232 
233 /*
234  * Print the fully specified variable that is described by the given identifer.
235  */
236 
237 public printwhich(f, s)
238 File f;
239 Symbol s;
240 {
241     printouter(f, container(s));
242     fprintf(f, "%s", symname(s));
243 }
244 
245 /*
246  * Print the fully qualified name of each symbol that has the same name
247  * as the given symbol.
248  */
249 
250 public printwhereis(f, s)
251 File f;
252 Symbol s;
253 {
254     register Name n;
255     register Symbol t;
256 
257     checkref(s);
258     n = s->name;
259     t = lookup(n);
260     printwhich(f, t);
261     t = t->next_sym;
262     while (t != nil) {
263 	if (t->name == n) {
264 	    putc(' ', f);
265 	    printwhich(f, t);
266 	}
267 	t = t->next_sym;
268     }
269     putc('\n', f);
270 }
271 
272 private printouter(f, s)
273 File f;
274 Symbol s;
275 {
276     Symbol outer;
277 
278     if (s != nil) {
279 	outer = container(s);
280 	if (outer != nil and outer != program) {
281 	    printouter(f, outer);
282 	}
283 	fprintf(f, "%s.", symname(s));
284     }
285 }
286 
287 public printdecl(s)
288 Symbol s;
289 {
290     checkref(s);
291     (*language_op(s->language, L_PRINTDECL))(s);
292 }
293 
294 /*
295  * Straight dump of symbol information.
296  */
297 
298 public psym(s)
299 Symbol s;
300 {
301     printf("name\t%s\n", symname(s));
302     printf("lang\t%s\n", language_name(s->language));
303     printf("level\t%d\n", s->level);
304     printf("class\t%s\n", classname(s));
305     printf("type\t0x%x", s->type);
306     if (s->type != nil and s->type->name != nil) {
307 	printf(" (%s)", symname(s->type));
308     }
309     printf("\nchain\t0x%x", s->chain);
310     if (s->chain != nil and s->chain->name != nil) {
311 	printf(" (%s)", symname(s->chain));
312     }
313     printf("\nblock\t0x%x", s->block);
314     if (s->block->name != nil) {
315 	printf(" (");
316 	printname(stdout, s->block);
317 	putchar(')');
318     }
319     putchar('\n');
320     switch (s->class) {
321 	case VAR:
322 	case REF:
323 	    if (s->level >= 3) {
324 		printf("address\t0x%x\n", s->symvalue.offset);
325 	    } else {
326 		printf("offset\t%d\n", s->symvalue.offset);
327 	    }
328 	    break;
329 
330 	case RECORD:
331 	case VARNT:
332 	    printf("size\t%d\n", s->symvalue.offset);
333 	    break;
334 
335 	case FIELD:
336 	    printf("offset\t%d\n", s->symvalue.field.offset);
337 	    printf("size\t%d\n", s->symvalue.field.length);
338 	    break;
339 
340 	case PROC:
341 	case FUNC:
342 	    printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
343 	    break;
344 
345 	case RANGE:
346 	    printf("lower\t%d\n", s->symvalue.rangev.lower);
347 	    printf("upper\t%d\n", s->symvalue.rangev.upper);
348 	    break;
349 
350 	default:
351 	    /* do nothing */
352 	    break;
353     }
354 }
355 
356 /*
357  * Print out the value on top of the stack according to the given type.
358  */
359 
360 public printval(t)
361 Symbol t;
362 {
363     Symbol s;
364 
365     checkref(t);
366     switch (t->class) {
367 	case PROC:
368 	case FUNC:
369 	    s = pop(Symbol);
370 	    printf("%s", symname(s));
371 	    break;
372 
373 	default:
374 	    if (t->language == nil) {
375 		error("unknown language");
376 	    } else {
377 		(*language_op(t->language, L_PRINTVAL))(t);
378 	    }
379 	    break;
380     }
381 }
382 
383 /*
384  * Print out the value of a record, field by field.
385  */
386 
387 public printrecord(s)
388 Symbol s;
389 {
390     if (s->chain == nil) {
391 	error("record has no fields");
392     }
393     printf("(");
394     sp -= size(s);
395     printfield(s->chain);
396     printf(")");
397 }
398 
399 /*
400  * Print out a field, first printing out other fields.
401  * This is done because the fields are chained together backwards.
402  */
403 
404 private printfield(s)
405 Symbol s;
406 {
407     Stack *savesp;
408 
409     if (s->chain != nil) {
410 	printfield(s->chain);
411 	printf(", ");
412     }
413     printf("%s = ", symname(s));
414     savesp = sp;
415     sp += ((s->symvalue.field.offset div BITSPERBYTE) + size(s->type));
416     printval(s);
417     sp = savesp;
418 }
419 
420 /*
421  * Print out the contents of an array.
422  * Haven't quite figured out what the best format is.
423  *
424  * This is rather inefficient.
425  *
426  * The "2*elsize" is there since "printval" drops the stack by elsize.
427  */
428 
429 public printarray(a)
430 Symbol a;
431 {
432     Stack *savesp, *newsp;
433     Symbol eltype;
434     long elsize;
435     String sep;
436 
437     savesp = sp;
438     sp -= size(a);
439     newsp = sp;
440     eltype = rtype(a->type);
441     elsize = size(eltype);
442     printf("(");
443     if (eltype->class == RECORD or eltype->class == ARRAY or
444       eltype->class == VARNT) {
445 	sep = "\n";
446 	putchar('\n');
447     } else {
448 	sep = ", ";
449     }
450     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
451 	if (sp - elsize != newsp) {
452 	    fputs(sep, stdout);
453 	}
454 	printval(eltype);
455     }
456     sp = newsp;
457     if (streq(sep, "\n")) {
458 	putchar('\n');
459     }
460     printf(")");
461 }
462 
463 /*
464  * Print out the value of a real number in Pascal notation.
465  * This is, unfortunately, different than what one gets
466  * from "%g" in printf.
467  */
468 
469 public prtreal(r)
470 double r;
471 {
472     extern char *index();
473     char buf[256];
474 
475     sprintf(buf, "%g", r);
476     if (buf[0] == '.') {
477 	printf("0%s", buf);
478     } else if (buf[0] == '-' and buf[1] == '.') {
479 	printf("-0%s", &buf[1]);
480     } else {
481 	printf("%s", buf);
482     }
483     if (index(buf, '.') == nil) {
484 	printf(".0");
485     }
486 }
487 
488 /*
489  * Print out a character using ^? notation for unprintables.
490  */
491 
492 public printchar(c)
493 char c;
494 {
495     if (c == 0) {
496 	putchar('\\');
497 	putchar('0');
498     } else if (c == '\n') {
499 	putchar('\\');
500 	putchar('n');
501     } else if (c > 0 and c < ' ') {
502 	putchar('^');
503 	putchar(c - 1 + 'A');
504     } else {
505 	putchar(c);
506     }
507 }
508