xref: /original-bsd/old/dbx/printsym.c (revision f82e54c4)
1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static	char sccsid[] = "@(#)printsym.c	1.13 (Berkeley) 06/23/84";
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", "extref", "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  * If the procedure or function is internal, the argument count is
123  * not valid so we ignore it.
124  */
125 
126 public printparams(f, frame)
127 Symbol f;
128 Frame frame;
129 {
130     Symbol param;
131     int n, m, s;
132 
133     n = nargspassed(frame);
134     if (isinternal(f)) {
135 	n = 0;
136     }
137     param = f->chain;
138     if (param != nil or n > 0) {
139 	printf("(");
140 	m = n;
141 	if (param != nil) {
142 	    for (;;) {
143 		s = size(param) div sizeof(Word);
144 		if (s == 0) {
145 		    s = 1;
146 		}
147 		m -= s;
148 		printv(param, frame);
149 		param = param->chain;
150 	    if (param == nil) break;
151 		printf(", ");
152 	    }
153 	}
154 	if (m > 0) {
155 	    if (m > MAXARGSPASSED) {
156 		m = MAXARGSPASSED;
157 	    }
158 	    if (f->chain != nil) {
159 		printf(", ");
160 	    }
161 	    for (;;) {
162 		--m;
163 		printf("0x%x", argn(n - m, frame));
164 	    if (m <= 0) break;
165 		printf(", ");
166 	    }
167 	}
168 	printf(")");
169     }
170 }
171 
172 /*
173  * Test if a symbol should be printed.  We don't print files,
174  * for example, simply because there's no good way to do it.
175  * The symbol must be within the given function.
176  */
177 
178 public Boolean should_print(s)
179 Symbol s;
180 {
181     Boolean b;
182     register Symbol t;
183 
184     switch (s->class) {
185 	case VAR:
186 	case FVAR:
187 	    if (isparam(s)) {
188 		b = false;
189 	    } else {
190 		t = rtype(s->type);
191 		if (t == nil) {
192 		    b = false;
193 		} else {
194 		    switch (t->class) {
195 			case FILET:
196 			case SET:
197 			case BADUSE:
198 			    b = false;
199 			    break;
200 
201 			default:
202 			    b = true;
203 			    break;
204 		    }
205 		}
206 	    }
207 	    break;
208 
209 	default:
210 	    b = false;
211 	    break;
212     }
213     return b;
214 }
215 
216 /*
217  * Print the name and value of a variable.
218  */
219 
220 public printv(s, frame)
221 Symbol s;
222 Frame frame;
223 {
224     Address addr;
225     int len;
226     Symbol t;
227 
228     if (isambiguous(s) and ismodule(container(s))) {
229 	printname(stdout, s);
230 	printf(" = ");
231     } else {
232 	printf("%s = ", symname(s));
233     }
234 /*
235  * Not today.
236     t = rtype(s->type);
237     if (t->class == ARRAY and not istypename(t->type, "char")) {
238 	printf("ARRAY");
239     } else {
240  */
241        if (isvarparam(s)) {
242 	   rpush(address(s, frame), sizeof(Address));
243 	   addr = pop(Address);
244 	   len = size(s->type);
245        } else {
246 	   addr = address(s, frame);
247 	   len = size(s);
248        }
249        if (canpush(len)) {
250 	   rpush(addr, len);
251 	   printval(s->type);
252        } else {
253 	   printf("*** expression too large ***");
254        }
255 /*
256  * Matches brace commented out above.
257    }
258  */
259 }
260 
261 /*
262  * Print out the name of a symbol.
263  */
264 
265 public printname(f, s)
266 File f;
267 Symbol s;
268 {
269     if (s == nil) {
270 	fprintf(f, "(noname)");
271     } else if (s == program) {
272 	fprintf(f, ".");
273     } else if (isredirected() or isambiguous(s)) {
274 	printwhich(f, s);
275     } else {
276 	fprintf(f, "%s", symname(s));
277     }
278 }
279 
280 /*
281  * Print the fully specified variable that is described by the given identifer.
282  */
283 
284 public printwhich(f, s)
285 File f;
286 Symbol s;
287 {
288     printouter(f, container(s));
289     fprintf(f, "%s", symname(s));
290 }
291 
292 /*
293  * Print the fully qualified name of each symbol that has the same name
294  * as the given symbol.
295  */
296 
297 public printwhereis(f, s)
298 File f;
299 Symbol s;
300 {
301     register Name n;
302     register Symbol t;
303 
304     checkref(s);
305     n = s->name;
306     t = lookup(n);
307     printwhich(f, t);
308     t = t->next_sym;
309     while (t != nil) {
310 	if (t->name == n) {
311 	    putc(' ', f);
312 	    printwhich(f, t);
313 	}
314 	t = t->next_sym;
315     }
316     putc('\n', f);
317 }
318 
319 private printouter(f, s)
320 File f;
321 Symbol s;
322 {
323     Symbol outer;
324 
325     if (s != nil) {
326 	outer = container(s);
327 	if (outer != nil and outer != program) {
328 	    printouter(f, outer);
329 	}
330 	fprintf(f, "%s.", symname(s));
331     }
332 }
333 
334 public printdecl(s)
335 Symbol s;
336 {
337     checkref(s);
338     (*language_op(s->language, L_PRINTDECL))(s);
339 }
340 
341 /*
342  * Straight dump of symbol information.
343  */
344 
345 public psym(s)
346 Symbol s;
347 {
348     printf("name\t%s\n", symname(s));
349     printf("lang\t%s\n", language_name(s->language));
350     printf("level\t%d\n", s->level);
351     printf("class\t%s\n", classname(s));
352     printf("type\t0x%x", s->type);
353     if (s->type != nil and s->type->name != nil) {
354 	printf(" (%s)", symname(s->type));
355     }
356     printf("\nchain\t0x%x", s->chain);
357     if (s->chain != nil and s->chain->name != nil) {
358 	printf(" (%s)", symname(s->chain));
359     }
360     printf("\nblock\t0x%x", s->block);
361     if (s->block->name != nil) {
362 	printf(" (");
363 	printname(stdout, s->block);
364 	putchar(')');
365     }
366     putchar('\n');
367     switch (s->class) {
368 	case VAR:
369 	case REF:
370 	    if (s->level >= 3) {
371 		printf("address\t0x%x\n", s->symvalue.offset);
372 	    } else {
373 		printf("offset\t%d\n", s->symvalue.offset);
374 	    }
375 	    printf("size\t%d\n", size(s));
376 	    break;
377 
378 	case RECORD:
379 	case VARNT:
380 	    printf("size\t%d\n", s->symvalue.offset);
381 	    break;
382 
383 	case FIELD:
384 	    printf("offset\t%d\n", s->symvalue.field.offset);
385 	    printf("size\t%d\n", s->symvalue.field.length);
386 	    break;
387 
388 	case PROG:
389 	case PROC:
390 	case FUNC:
391 	    printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
392 	    if (isinline(s)) {
393 		printf("inline procedure\n");
394 	    }
395 	    if (nosource(s)) {
396 		printf("does not have source information\n");
397 	    } else {
398 		printf("has source information\n");
399 	    }
400 	    break;
401 
402 	case RANGE:
403 	    prangetype(s->symvalue.rangev.lowertype);
404 	    printf("lower\t%d\n", s->symvalue.rangev.lower);
405 	    prangetype(s->symvalue.rangev.uppertype);
406 	    printf("upper\t%d\n", s->symvalue.rangev.upper);
407 	    break;
408 
409 	default:
410 	    /* do nothing */
411 	    break;
412     }
413 }
414 
415 private prangetype(r)
416 Rangetype r;
417 {
418     switch (r) {
419 	case R_CONST:
420 	    printf("CONST");
421 	    break;
422 
423 	case R_ARG:
424 	    printf("ARG");
425 	    break;
426 
427 	case R_TEMP:
428 	    printf("TEMP");
429 	    break;
430 
431 	case R_ADJUST:
432 	    printf("ADJUST");
433 	    break;
434     }
435 }
436 
437 /*
438  * Print out the value on top of the stack according to the given type.
439  */
440 
441 public printval(t)
442 Symbol t;
443 {
444     Symbol s;
445 
446     checkref(t);
447     if (t->class == TYPEREF) {
448 	resolveRef(t);
449     }
450     switch (t->class) {
451 	case PROC:
452 	case FUNC:
453 	    s = pop(Symbol);
454 	    printf("%s", symname(s));
455 	    break;
456 
457 	default:
458 	    if (t->language == nil) {
459 		error("unknown language");
460 	    } else if (t->language == primlang) {
461 		(*language_op(findlanguage(".c"), L_PRINTVAL))(t);
462 	    } else {
463 		(*language_op(t->language, L_PRINTVAL))(t);
464 	    }
465 	    break;
466     }
467 }
468 
469 /*
470  * Print out the value of a record, field by field.
471  */
472 
473 public printrecord(s)
474 Symbol s;
475 {
476     Symbol f;
477 
478     if (s->chain == nil) {
479 	error("record has no fields");
480     }
481     printf("(");
482     sp -= size(s);
483     f = s->chain;
484     if (f != nil) {
485 	for (;;) {
486 	    printfield(f);
487 	    f = f->chain;
488 	if (f == nil) break;
489 	    printf(", ");
490 	}
491     }
492     printf(")");
493 }
494 
495 /*
496  * Print out a field.
497  */
498 
499 private printfield(f)
500 Symbol f;
501 {
502     Stack *savesp;
503     register int off, len;
504 
505     printf("%s = ", symname(f));
506     savesp = sp;
507     off = f->symvalue.field.offset;
508     len = f->symvalue.field.length;
509     sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE);
510     printval(f);
511     sp = savesp;
512 }
513 
514 /*
515  * Print out the contents of an array.
516  * Haven't quite figured out what the best format is.
517  *
518  * This is rather inefficient.
519  *
520  * The "2*elsize" is there since "printval" drops the stack by elsize.
521  */
522 
523 public printarray(a)
524 Symbol a;
525 {
526     Stack *savesp, *newsp;
527     Symbol eltype;
528     long elsize;
529     String sep;
530 
531     savesp = sp;
532     sp -= (size(a));
533     newsp = sp;
534     eltype = rtype(a->type);
535     elsize = size(eltype);
536     printf("(");
537     if (eltype->class == RECORD or eltype->class == ARRAY or
538       eltype->class == VARNT) {
539 	sep = "\n";
540 	putchar('\n');
541     } else {
542 	sep = ", ";
543     }
544     for (sp += elsize; sp <= savesp; sp += 2*elsize) {
545 	if (sp - elsize != newsp) {
546 	    fputs(sep, stdout);
547 	}
548 	printval(eltype);
549     }
550     sp = newsp;
551     if (streq(sep, "\n")) {
552 	putchar('\n');
553     }
554     printf(")");
555 }
556 
557 /*
558  * Print out the value of a real number in Pascal notation.
559  * This is, unfortunately, different than what one gets
560  * from "%g" in printf.
561  */
562 
563 public prtreal(r)
564 double r;
565 {
566     extern char *index();
567     char buf[256];
568 
569     sprintf(buf, "%g", r);
570     if (buf[0] == '.') {
571 	printf("0%s", buf);
572     } else if (buf[0] == '-' and buf[1] == '.') {
573 	printf("-0%s", &buf[1]);
574     } else {
575 	printf("%s", buf);
576     }
577     if (index(buf, '.') == nil) {
578 	printf(".0");
579     }
580 }
581 
582 /*
583  * Print out a character using ^? notation for unprintables.
584  */
585 
586 public printchar(c)
587 char c;
588 {
589     if (c == 0) {
590 	putchar('\\');
591 	putchar('0');
592     } else if (c == '\n') {
593 	putchar('\\');
594 	putchar('n');
595     } else if (c > 0 and c < ' ') {
596 	putchar('^');
597 	putchar(c - 1 + 'A');
598     } else if (c >= ' ' && c <= '~') {
599 	putchar(c);
600     } else {
601 	printf("\\0%o",c);
602     }
603 }
604