branch delta of linton changes from net.sources
[unix-history] / usr / src / old / dbx / printsym.c
CommitLineData
6eb0951d
ML
1/* Copyright (c) 1982 Regents of the University of California */
2
2fd0f574
SL
3static char sccsid[] = "@(#)printsym.c 1.12 8/10/83";
4
5static char rcsid[] = "$Header: printsym.c,v 1.3 84/03/27 10:23:14 linton Exp $";
6eb0951d
ML
6
7/*
8 * Printing of symbolic information.
9 */
10
11#include "defs.h"
12#include "symbols.h"
13#include "languages.h"
14#include "printsym.h"
15#include "tree.h"
16#include "eval.h"
17#include "mappings.h"
18#include "process.h"
19#include "runtime.h"
20#include "machine.h"
21#include "names.h"
22#include "main.h"
23
24#ifndef public
25#endif
26
b38a9c14
ML
27/*
28 * Maximum number of arguments to a function.
29 * This is used as a check for the possibility that the stack has been
30 * overwritten and therefore a saved argument pointer might indicate
31 * to an absurdly large number of arguments.
32 */
33
34#define MAXARGSPASSED 20
35
6eb0951d
ML
36/*
37 * Return a pointer to the string for the name of the class that
38 * the given symbol belongs to.
39 */
40
41private String clname[] = {
42 "bad use", "constant", "type", "variable", "array", "fileptr",
43 "record", "field", "procedure", "function", "funcvar",
44 "ref", "pointer", "file", "set", "range", "label", "withptr",
45 "scalar", "string", "program", "improper", "variant",
2fd0f574 46 "procparam", "funcparam", "module", "tag", "common", "extref", "typeref"
6eb0951d
ML
47};
48
49public String classname(s)
50Symbol s;
51{
52 return clname[ord(s->class)];
53}
54
55/*
56 * Note the entry of the given block, unless it's the main program.
57 */
58
59public printentry(s)
60Symbol s;
61{
62 if (s != program) {
63 printf("\nentering %s %s\n", classname(s), symname(s));
64 }
65}
66
67/*
68 * Note the exit of the given block
69 */
70
71public printexit(s)
72Symbol s;
73{
74 if (s != program) {
75 printf("leaving %s %s\n\n", classname(s), symname(s));
76 }
77}
78
79/*
80 * Note the call of s from t.
81 */
82
83public printcall(s, t)
84Symbol s, t;
85{
86 printf("calling %s", symname(s));
87 printparams(s, nil);
88 printf(" from %s %s\n", classname(t), symname(t));
89}
90
91/*
92 * Note the return from s. If s is a function, print the value
93 * it is returning. This is somewhat painful, since the function
94 * has actually just returned.
95 */
96
97public printrtn(s)
98Symbol s;
99{
100 register Symbol t;
101 register int len;
102 Boolean isindirect;
103
104 printf("returning ");
63a90519 105 if (s->class == FUNC && (!istypename(s->type,"void"))) {
6eb0951d
ML
106 len = size(s->type);
107 if (canpush(len)) {
108 t = rtype(s->type);
109 isindirect = (Boolean) (t->class == RECORD or t->class == VARNT);
110 pushretval(len, isindirect);
111 printval(s->type);
112 putchar(' ');
113 } else {
114 printf("(value too large) ");
115 }
116 }
117 printf("from %s\n", symname(s));
118}
119
120/*
121 * Print the values of the parameters of the given procedure or function.
122 * The frame distinguishes recursive instances of a procedure.
2fd0f574
SL
123 *
124 * If the procedure or function is internal, the argument count is
125 * not valid so we ignore it.
6eb0951d
ML
126 */
127
128public printparams(f, frame)
129Symbol f;
130Frame frame;
131{
132 Symbol param;
133 int n, m, s;
134
135 n = nargspassed(frame);
2fd0f574
SL
136 if (isinternal(f)) {
137 n = 0;
138 }
6eb0951d
ML
139 param = f->chain;
140 if (param != nil or n > 0) {
141 printf("(");
142 m = n;
143 if (param != nil) {
144 for (;;) {
145 s = size(param) div sizeof(Word);
146 if (s == 0) {
147 s = 1;
148 }
149 m -= s;
150 printv(param, frame);
151 param = param->chain;
152 if (param == nil) break;
153 printf(", ");
154 }
155 }
156 if (m > 0) {
b38a9c14
ML
157 if (m > MAXARGSPASSED) {
158 m = MAXARGSPASSED;
159 }
6eb0951d
ML
160 if (f->chain != nil) {
161 printf(", ");
162 }
163 for (;;) {
164 --m;
165 printf("0x%x", argn(n - m, frame));
166 if (m <= 0) break;
167 printf(", ");
168 }
169 }
170 printf(")");
171 }
172}
173
174/*
175 * Test if a symbol should be printed. We don't print files,
176 * for example, simply because there's no good way to do it.
177 * The symbol must be within the given function.
178 */
179
180public Boolean should_print(s)
181Symbol s;
182{
183 Boolean b;
184 register Symbol t;
185
186 switch (s->class) {
187 case VAR:
188 case FVAR:
eb18c137
ML
189 if (isparam(s)) {
190 b = false;
191 } else {
192 t = rtype(s->type);
193 if (t == nil) {
194 b = false;
195 } else {
196 switch (t->class) {
197 case FILET:
198 case SET:
eb18c137
ML
199 case BADUSE:
200 b = false;
201 break;
202
203 default:
204 b = true;
205 break;
206 }
207 }
208 }
6eb0951d
ML
209 break;
210
211 default:
212 b = false;
213 break;
214 }
215 return b;
216}
217
218/*
219 * Print the name and value of a variable.
220 */
221
222public printv(s, frame)
223Symbol s;
224Frame frame;
225{
226 Address addr;
227 int len;
2fd0f574 228 Symbol t;
6eb0951d
ML
229
230 if (isambiguous(s) and ismodule(container(s))) {
231 printname(stdout, s);
232 printf(" = ");
233 } else {
234 printf("%s = ", symname(s));
235 }
2fd0f574
SL
236/*
237 * Not today.
238 t = rtype(s->type);
239 if (t->class == ARRAY and not istypename(t->type, "char")) {
240 printf("ARRAY");
6eb0951d 241 } else {
2fd0f574 242 */
63a90519
AF
243 if (isvarparam(s)) {
244 rpush(address(s, frame), sizeof(Address));
245 addr = pop(Address);
246 len = size(s->type);
247 } else {
248 addr = address(s, frame);
249 len = size(s);
250 }
251 if (canpush(len)) {
252 rpush(addr, len);
253 printval(s->type);
254 } else {
255 printf("*** expression too large ***");
256 }
2fd0f574
SL
257/*
258 * Matches brace commented out above.
63a90519 259 }
2fd0f574 260 */
6eb0951d
ML
261}
262
263/*
264 * Print out the name of a symbol.
265 */
266
267public printname(f, s)
268File f;
269Symbol s;
270{
271 if (s == nil) {
272 fprintf(f, "(noname)");
2fd0f574
SL
273 } else if (s == program) {
274 fprintf(f, ".");
6eb0951d
ML
275 } else if (isredirected() or isambiguous(s)) {
276 printwhich(f, s);
277 } else {
278 fprintf(f, "%s", symname(s));
279 }
280}
281
282/*
283 * Print the fully specified variable that is described by the given identifer.
284 */
285
286public printwhich(f, s)
287File f;
288Symbol s;
289{
290 printouter(f, container(s));
291 fprintf(f, "%s", symname(s));
292}
293
294/*
295 * Print the fully qualified name of each symbol that has the same name
296 * as the given symbol.
297 */
298
299public printwhereis(f, s)
300File f;
301Symbol s;
302{
303 register Name n;
304 register Symbol t;
305
306 checkref(s);
307 n = s->name;
308 t = lookup(n);
309 printwhich(f, t);
310 t = t->next_sym;
311 while (t != nil) {
312 if (t->name == n) {
313 putc(' ', f);
314 printwhich(f, t);
315 }
316 t = t->next_sym;
317 }
318 putc('\n', f);
319}
320
321private printouter(f, s)
322File f;
323Symbol s;
324{
325 Symbol outer;
326
327 if (s != nil) {
328 outer = container(s);
329 if (outer != nil and outer != program) {
330 printouter(f, outer);
331 }
332 fprintf(f, "%s.", symname(s));
333 }
334}
335
336public printdecl(s)
337Symbol s;
338{
339 checkref(s);
340 (*language_op(s->language, L_PRINTDECL))(s);
341}
342
343/*
344 * Straight dump of symbol information.
345 */
346
347public psym(s)
348Symbol s;
349{
350 printf("name\t%s\n", symname(s));
351 printf("lang\t%s\n", language_name(s->language));
352 printf("level\t%d\n", s->level);
353 printf("class\t%s\n", classname(s));
354 printf("type\t0x%x", s->type);
355 if (s->type != nil and s->type->name != nil) {
356 printf(" (%s)", symname(s->type));
357 }
358 printf("\nchain\t0x%x", s->chain);
359 if (s->chain != nil and s->chain->name != nil) {
360 printf(" (%s)", symname(s->chain));
361 }
362 printf("\nblock\t0x%x", s->block);
363 if (s->block->name != nil) {
364 printf(" (");
365 printname(stdout, s->block);
366 putchar(')');
367 }
368 putchar('\n');
369 switch (s->class) {
370 case VAR:
371 case REF:
372 if (s->level >= 3) {
373 printf("address\t0x%x\n", s->symvalue.offset);
374 } else {
375 printf("offset\t%d\n", s->symvalue.offset);
376 }
4dc0ac37 377 printf("size\t%d\n", size(s));
6eb0951d
ML
378 break;
379
380 case RECORD:
381 case VARNT:
382 printf("size\t%d\n", s->symvalue.offset);
383 break;
384
385 case FIELD:
386 printf("offset\t%d\n", s->symvalue.field.offset);
387 printf("size\t%d\n", s->symvalue.field.length);
388 break;
389
8ee43d3e 390 case PROG:
6eb0951d
ML
391 case PROC:
392 case FUNC:
393 printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
a71dda28 394 if (isinline(s)) {
ffa66ed0 395 printf("inline procedure\n");
a71dda28 396 }
b38a9c14
ML
397 if (nosource(s)) {
398 printf("does not have source information\n");
399 } else {
400 printf("has source information\n");
401 }
6eb0951d
ML
402 break;
403
404 case RANGE:
8ee43d3e
ML
405 prangetype(s->symvalue.rangev.lowertype);
406 printf("lower\t%d\n", s->symvalue.rangev.lower);
407 prangetype(s->symvalue.rangev.uppertype);
6eb0951d
ML
408 printf("upper\t%d\n", s->symvalue.rangev.upper);
409 break;
410
411 default:
412 /* do nothing */
413 break;
414 }
415}
416
8ee43d3e
ML
417private prangetype(r)
418Rangetype r;
419{
420 switch (r) {
421 case R_CONST:
422 printf("CONST");
423 break;
424
425 case R_ARG:
426 printf("ARG");
427 break;
428
429 case R_TEMP:
430 printf("TEMP");
431 break;
432
433 case R_ADJUST:
434 printf("ADJUST");
435 break;
436 }
437}
438
6eb0951d
ML
439/*
440 * Print out the value on top of the stack according to the given type.
441 */
442
443public printval(t)
444Symbol t;
445{
446 Symbol s;
447
448 checkref(t);
2fd0f574
SL
449 if (t->class == TYPEREF) {
450 resolveRef(t);
451 }
6eb0951d
ML
452 switch (t->class) {
453 case PROC:
454 case FUNC:
455 s = pop(Symbol);
456 printf("%s", symname(s));
457 break;
458
459 default:
460 if (t->language == nil) {
461 error("unknown language");
2fd0f574
SL
462 } else if (t->language == primlang) {
463 (*language_op(findlanguage(".c"), L_PRINTVAL))(t);
6eb0951d
ML
464 } else {
465 (*language_op(t->language, L_PRINTVAL))(t);
466 }
467 break;
468 }
469}
470
471/*
472 * Print out the value of a record, field by field.
473 */
474
475public printrecord(s)
476Symbol s;
477{
2fd0f574
SL
478 Symbol f;
479
6eb0951d
ML
480 if (s->chain == nil) {
481 error("record has no fields");
482 }
483 printf("(");
484 sp -= size(s);
2fd0f574
SL
485 f = s->chain;
486 if (f != nil) {
487 for (;;) {
488 printfield(f);
489 f = f->chain;
490 if (f == nil) break;
491 printf(", ");
492 }
493 }
6eb0951d
ML
494 printf(")");
495}
496
497/*
2fd0f574 498 * Print out a field.
6eb0951d
ML
499 */
500
2fd0f574
SL
501private printfield(f)
502Symbol f;
6eb0951d
ML
503{
504 Stack *savesp;
2fd0f574 505 register int off, len;
6eb0951d 506
2fd0f574 507 printf("%s = ", symname(f));
6eb0951d 508 savesp = sp;
2fd0f574
SL
509 off = f->symvalue.field.offset;
510 len = f->symvalue.field.length;
511 sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE);
512 printval(f);
6eb0951d
ML
513 sp = savesp;
514}
515
516/*
517 * Print out the contents of an array.
518 * Haven't quite figured out what the best format is.
519 *
520 * This is rather inefficient.
521 *
522 * The "2*elsize" is there since "printval" drops the stack by elsize.
523 */
524
525public printarray(a)
526Symbol a;
527{
528 Stack *savesp, *newsp;
529 Symbol eltype;
530 long elsize;
531 String sep;
532
533 savesp = sp;
20614ea9 534 sp -= (size(a));
6eb0951d
ML
535 newsp = sp;
536 eltype = rtype(a->type);
537 elsize = size(eltype);
538 printf("(");
539 if (eltype->class == RECORD or eltype->class == ARRAY or
540 eltype->class == VARNT) {
541 sep = "\n";
542 putchar('\n');
543 } else {
544 sep = ", ";
545 }
546 for (sp += elsize; sp <= savesp; sp += 2*elsize) {
547 if (sp - elsize != newsp) {
548 fputs(sep, stdout);
549 }
550 printval(eltype);
551 }
552 sp = newsp;
553 if (streq(sep, "\n")) {
554 putchar('\n');
555 }
556 printf(")");
557}
558
559/*
560 * Print out the value of a real number in Pascal notation.
561 * This is, unfortunately, different than what one gets
562 * from "%g" in printf.
563 */
564
565public prtreal(r)
566double r;
567{
568 extern char *index();
569 char buf[256];
570
571 sprintf(buf, "%g", r);
572 if (buf[0] == '.') {
573 printf("0%s", buf);
574 } else if (buf[0] == '-' and buf[1] == '.') {
575 printf("-0%s", &buf[1]);
576 } else {
577 printf("%s", buf);
578 }
579 if (index(buf, '.') == nil) {
580 printf(".0");
581 }
582}
583
584/*
585 * Print out a character using ^? notation for unprintables.
586 */
587
588public printchar(c)
589char c;
590{
591 if (c == 0) {
592 putchar('\\');
593 putchar('0');
594 } else if (c == '\n') {
595 putchar('\\');
596 putchar('n');
597 } else if (c > 0 and c < ' ') {
598 putchar('^');
599 putchar(c - 1 + 'A');
2fd0f574 600 } else if (c >= ' ' && c <= '~') {
6eb0951d 601 putchar(c);
2fd0f574
SL
602 } else {
603 printf("\\0%o",c);
6eb0951d
ML
604 }
605}