date and time created 88/01/12 01:01:59 by donn
[unix-history] / usr / src / old / dbx / printsym.c
CommitLineData
2a24676e
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6eb0951d 6
2a24676e 7#ifndef lint
a1c8cef6 8static char sccsid[] = "@(#)printsym.c 5.4 (Berkeley) %G%";
2a24676e 9#endif not lint
0022c355
ML
10
11static char rcsid[] = "$Header: printsym.c,v 1.5 84/12/26 10:41:28 linton Exp $";
6eb0951d
ML
12
13/*
14 * Printing of symbolic information.
15 */
16
17#include "defs.h"
18#include "symbols.h"
19#include "languages.h"
20#include "printsym.h"
21#include "tree.h"
22#include "eval.h"
23#include "mappings.h"
24#include "process.h"
25#include "runtime.h"
26#include "machine.h"
27#include "names.h"
0022c355 28#include "keywords.h"
6eb0951d 29#include "main.h"
a1c8cef6 30#include <ctype.h>
6eb0951d
ML
31
32#ifndef public
33#endif
34
b38a9c14
ML
35/*
36 * Maximum number of arguments to a function.
37 * This is used as a check for the possibility that the stack has been
38 * overwritten and therefore a saved argument pointer might indicate
39 * to an absurdly large number of arguments.
40 */
41
42#define MAXARGSPASSED 20
43
6eb0951d
ML
44/*
45 * Return a pointer to the string for the name of the class that
46 * the given symbol belongs to.
47 */
48
49private String clname[] = {
0022c355
ML
50 "bad use", "constant", "type", "variable", "array", "@dynarray",
51 "@subarray", "fileptr", "record", "field",
52 "procedure", "function", "funcvar",
6eb0951d
ML
53 "ref", "pointer", "file", "set", "range", "label", "withptr",
54 "scalar", "string", "program", "improper", "variant",
2fd0f574 55 "procparam", "funcparam", "module", "tag", "common", "extref", "typeref"
6eb0951d
ML
56};
57
58public String classname(s)
59Symbol s;
60{
61 return clname[ord(s->class)];
62}
63
64/*
65 * Note the entry of the given block, unless it's the main program.
66 */
67
68public printentry(s)
69Symbol s;
70{
71 if (s != program) {
0022c355
ML
72 printf("\nentering %s ", classname(s));
73 printname(stdout, s);
74 printf("\n");
6eb0951d
ML
75 }
76}
77
78/*
79 * Note the exit of the given block
80 */
81
82public printexit(s)
83Symbol s;
84{
85 if (s != program) {
0022c355
ML
86 printf("leaving %s ", classname(s));
87 printname(stdout, s);
88 printf("\n\n");
6eb0951d
ML
89 }
90}
91
92/*
93 * Note the call of s from t.
94 */
95
96public printcall(s, t)
97Symbol s, t;
98{
0022c355
ML
99 printf("calling ");
100 printname(stdout, s);
6eb0951d 101 printparams(s, nil);
0022c355
ML
102 printf(" from %s ", classname(t));
103 printname(stdout, t);
104 printf("\n");
6eb0951d
ML
105}
106
107/*
108 * Note the return from s. If s is a function, print the value
109 * it is returning. This is somewhat painful, since the function
110 * has actually just returned.
111 */
112
113public printrtn(s)
114Symbol s;
115{
116 register Symbol t;
117 register int len;
118 Boolean isindirect;
119
120 printf("returning ");
63a90519 121 if (s->class == FUNC && (!istypename(s->type,"void"))) {
6eb0951d
ML
122 len = size(s->type);
123 if (canpush(len)) {
124 t = rtype(s->type);
125 isindirect = (Boolean) (t->class == RECORD or t->class == VARNT);
126 pushretval(len, isindirect);
127 printval(s->type);
128 putchar(' ');
129 } else {
130 printf("(value too large) ");
131 }
132 }
0022c355
ML
133 printf("from ");
134 printname(stdout, s);
135 printf("\n");
6eb0951d
ML
136}
137
138/*
139 * Print the values of the parameters of the given procedure or function.
140 * The frame distinguishes recursive instances of a procedure.
2fd0f574
SL
141 *
142 * If the procedure or function is internal, the argument count is
143 * not valid so we ignore it.
6eb0951d
ML
144 */
145
146public printparams(f, frame)
147Symbol f;
148Frame frame;
149{
150 Symbol param;
151 int n, m, s;
152
153 n = nargspassed(frame);
2fd0f574
SL
154 if (isinternal(f)) {
155 n = 0;
156 }
0022c355 157 printf("(");
6eb0951d
ML
158 param = f->chain;
159 if (param != nil or n > 0) {
6eb0951d
ML
160 m = n;
161 if (param != nil) {
162 for (;;) {
0022c355 163 s = psize(param) div sizeof(Word);
6eb0951d
ML
164 if (s == 0) {
165 s = 1;
166 }
167 m -= s;
0022c355
ML
168 if (showaggrs) {
169 printv(param, frame);
170 } else {
171 printparamv(param, frame);
172 }
6eb0951d
ML
173 param = param->chain;
174 if (param == nil) break;
175 printf(", ");
176 }
177 }
178 if (m > 0) {
b38a9c14
ML
179 if (m > MAXARGSPASSED) {
180 m = MAXARGSPASSED;
181 }
6eb0951d
ML
182 if (f->chain != nil) {
183 printf(", ");
184 }
185 for (;;) {
186 --m;
187 printf("0x%x", argn(n - m, frame));
188 if (m <= 0) break;
189 printf(", ");
190 }
191 }
6eb0951d 192 }
0022c355 193 printf(")");
6eb0951d
ML
194}
195
196/*
197 * Test if a symbol should be printed. We don't print files,
198 * for example, simply because there's no good way to do it.
199 * The symbol must be within the given function.
200 */
201
202public Boolean should_print(s)
203Symbol s;
204{
205 Boolean b;
206 register Symbol t;
207
208 switch (s->class) {
209 case VAR:
210 case FVAR:
eb18c137
ML
211 if (isparam(s)) {
212 b = false;
213 } else {
214 t = rtype(s->type);
215 if (t == nil) {
216 b = false;
217 } else {
218 switch (t->class) {
219 case FILET:
220 case SET:
eb18c137
ML
221 case BADUSE:
222 b = false;
223 break;
224
225 default:
226 b = true;
227 break;
228 }
229 }
230 }
6eb0951d
ML
231 break;
232
233 default:
234 b = false;
235 break;
236 }
237 return b;
238}
239
0022c355
ML
240/*
241 * Print out a parameter value.
242 *
243 * Since this is intended to be printed on a single line with other information
244 * aggregate values are not printed.
245 */
246
247public printparamv (p, frame)
248Symbol p;
249Frame frame;
250{
251 Symbol t;
252
253 t = rtype(p->type);
254 switch (t->class) {
255 case ARRAY:
256 case DYNARRAY:
257 case SUBARRAY:
258 t = rtype(t->type);
259 if (compatible(t, t_char)) {
260 printv(p, frame);
261 } else {
262 printf("%s = (...)", symname(p));
263 }
264 break;
265
266 case RECORD:
267 printf("%s = (...)", symname(p));
268 break;
269
270 default:
271 printv(p, frame);
272 break;
273 }
274}
275
6eb0951d
ML
276/*
277 * Print the name and value of a variable.
278 */
279
280public printv(s, frame)
281Symbol s;
282Frame frame;
283{
284 Address addr;
285 int len;
286
287 if (isambiguous(s) and ismodule(container(s))) {
288 printname(stdout, s);
289 printf(" = ");
290 } else {
291 printf("%s = ", symname(s));
292 }
0022c355
ML
293 if (isvarparam(s) and not isopenarray(s)) {
294 rpush(address(s, frame), sizeof(Address));
295 addr = pop(Address);
6eb0951d 296 } else {
0022c355
ML
297 addr = address(s, frame);
298 }
299 len = size(s);
ffb79108
KM
300 if (not canpush(len)) {
301 printf("*** expression too large ***");
302 } else if (isreg(s)) {
303 push(Address, addr);
0022c355
ML
304 printval(s->type);
305 } else {
ffb79108
KM
306 rpush(addr, len);
307 printval(s->type);
0022c355 308 }
6eb0951d
ML
309}
310
311/*
312 * Print out the name of a symbol.
313 */
314
315public printname(f, s)
316File f;
317Symbol s;
318{
319 if (s == nil) {
320 fprintf(f, "(noname)");
2fd0f574
SL
321 } else if (s == program) {
322 fprintf(f, ".");
6eb0951d
ML
323 } else if (isredirected() or isambiguous(s)) {
324 printwhich(f, s);
325 } else {
326 fprintf(f, "%s", symname(s));
327 }
328}
329
330/*
331 * Print the fully specified variable that is described by the given identifer.
332 */
333
334public printwhich(f, s)
335File f;
336Symbol s;
337{
338 printouter(f, container(s));
339 fprintf(f, "%s", symname(s));
340}
341
342/*
343 * Print the fully qualified name of each symbol that has the same name
344 * as the given symbol.
345 */
346
347public printwhereis(f, s)
348File f;
349Symbol s;
350{
351 register Name n;
352 register Symbol t;
353
354 checkref(s);
355 n = s->name;
356 t = lookup(n);
357 printwhich(f, t);
358 t = t->next_sym;
359 while (t != nil) {
360 if (t->name == n) {
361 putc(' ', f);
362 printwhich(f, t);
363 }
364 t = t->next_sym;
365 }
366 putc('\n', f);
367}
368
369private printouter(f, s)
370File f;
371Symbol s;
372{
373 Symbol outer;
374
375 if (s != nil) {
376 outer = container(s);
377 if (outer != nil and outer != program) {
378 printouter(f, outer);
379 }
380 fprintf(f, "%s.", symname(s));
381 }
382}
383
384public printdecl(s)
385Symbol s;
386{
0022c355
ML
387 Language lang;
388
6eb0951d 389 checkref(s);
0022c355
ML
390 if (s->language == nil or s->language == primlang) {
391 lang = findlanguage(".s");
392 } else {
393 lang = s->language;
394 }
395 (*language_op(lang, L_PRINTDECL))(s);
6eb0951d
ML
396}
397
398/*
399 * Straight dump of symbol information.
400 */
401
402public psym(s)
403Symbol s;
404{
405 printf("name\t%s\n", symname(s));
406 printf("lang\t%s\n", language_name(s->language));
407 printf("level\t%d\n", s->level);
408 printf("class\t%s\n", classname(s));
409 printf("type\t0x%x", s->type);
410 if (s->type != nil and s->type->name != nil) {
411 printf(" (%s)", symname(s->type));
412 }
413 printf("\nchain\t0x%x", s->chain);
414 if (s->chain != nil and s->chain->name != nil) {
415 printf(" (%s)", symname(s->chain));
416 }
417 printf("\nblock\t0x%x", s->block);
418 if (s->block->name != nil) {
419 printf(" (");
420 printname(stdout, s->block);
421 putchar(')');
422 }
423 putchar('\n');
424 switch (s->class) {
0022c355
ML
425 case TYPE:
426 printf("size\t%d\n", size(s));
427 break;
428
6eb0951d
ML
429 case VAR:
430 case REF:
431 if (s->level >= 3) {
432 printf("address\t0x%x\n", s->symvalue.offset);
433 } else {
434 printf("offset\t%d\n", s->symvalue.offset);
435 }
4dc0ac37 436 printf("size\t%d\n", size(s));
6eb0951d
ML
437 break;
438
439 case RECORD:
440 case VARNT:
441 printf("size\t%d\n", s->symvalue.offset);
442 break;
443
444 case FIELD:
445 printf("offset\t%d\n", s->symvalue.field.offset);
446 printf("size\t%d\n", s->symvalue.field.length);
447 break;
448
8ee43d3e 449 case PROG:
6eb0951d
ML
450 case PROC:
451 case FUNC:
452 printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
a71dda28 453 if (isinline(s)) {
ffa66ed0 454 printf("inline procedure\n");
a71dda28 455 }
b38a9c14
ML
456 if (nosource(s)) {
457 printf("does not have source information\n");
458 } else {
459 printf("has source information\n");
460 }
6eb0951d
ML
461 break;
462
463 case RANGE:
8ee43d3e
ML
464 prangetype(s->symvalue.rangev.lowertype);
465 printf("lower\t%d\n", s->symvalue.rangev.lower);
466 prangetype(s->symvalue.rangev.uppertype);
6eb0951d
ML
467 printf("upper\t%d\n", s->symvalue.rangev.upper);
468 break;
469
470 default:
471 /* do nothing */
472 break;
473 }
474}
475
8ee43d3e
ML
476private prangetype(r)
477Rangetype r;
478{
479 switch (r) {
480 case R_CONST:
481 printf("CONST");
482 break;
483
484 case R_ARG:
485 printf("ARG");
486 break;
487
488 case R_TEMP:
489 printf("TEMP");
490 break;
491
492 case R_ADJUST:
493 printf("ADJUST");
494 break;
495 }
496}
497
6eb0951d
ML
498/*
499 * Print out the value on top of the stack according to the given type.
500 */
501
502public printval(t)
503Symbol t;
504{
505 Symbol s;
506
507 checkref(t);
2fd0f574
SL
508 if (t->class == TYPEREF) {
509 resolveRef(t);
510 }
6eb0951d
ML
511 switch (t->class) {
512 case PROC:
513 case FUNC:
514 s = pop(Symbol);
515 printf("%s", symname(s));
516 break;
517
518 default:
0022c355 519 if (t->language == nil or t->language == primlang) {
5e821af5 520 (*language_op(findlanguage(".c"), L_PRINTVAL))(t);
6eb0951d
ML
521 } else {
522 (*language_op(t->language, L_PRINTVAL))(t);
523 }
524 break;
525 }
526}
527
528/*
529 * Print out the value of a record, field by field.
530 */
531
532public printrecord(s)
533Symbol s;
534{
2fd0f574
SL
535 Symbol f;
536
6eb0951d
ML
537 if (s->chain == nil) {
538 error("record has no fields");
539 }
540 printf("(");
541 sp -= size(s);
2fd0f574
SL
542 f = s->chain;
543 if (f != nil) {
544 for (;;) {
545 printfield(f);
546 f = f->chain;
547 if (f == nil) break;
548 printf(", ");
549 }
550 }
6eb0951d
ML
551 printf(")");
552}
553
554/*
2fd0f574 555 * Print out a field.
6eb0951d
ML
556 */
557
2fd0f574
SL
558private printfield(f)
559Symbol f;
6eb0951d
ML
560{
561 Stack *savesp;
2fd0f574 562 register int off, len;
6eb0951d 563
2fd0f574 564 printf("%s = ", symname(f));
6eb0951d 565 savesp = sp;
2fd0f574
SL
566 off = f->symvalue.field.offset;
567 len = f->symvalue.field.length;
568 sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE);
569 printval(f);
6eb0951d
ML
570 sp = savesp;
571}
572
573/*
574 * Print out the contents of an array.
575 * Haven't quite figured out what the best format is.
576 *
577 * This is rather inefficient.
578 *
579 * The "2*elsize" is there since "printval" drops the stack by elsize.
580 */
581
582public printarray(a)
583Symbol a;
584{
585 Stack *savesp, *newsp;
586 Symbol eltype;
587 long elsize;
588 String sep;
589
590 savesp = sp;
20614ea9 591 sp -= (size(a));
6eb0951d
ML
592 newsp = sp;
593 eltype = rtype(a->type);
594 elsize = size(eltype);
595 printf("(");
596 if (eltype->class == RECORD or eltype->class == ARRAY or
597 eltype->class == VARNT) {
598 sep = "\n";
599 putchar('\n');
600 } else {
601 sep = ", ";
602 }
603 for (sp += elsize; sp <= savesp; sp += 2*elsize) {
604 if (sp - elsize != newsp) {
605 fputs(sep, stdout);
606 }
607 printval(eltype);
608 }
609 sp = newsp;
610 if (streq(sep, "\n")) {
611 putchar('\n');
612 }
613 printf(")");
614}
615
616/*
617 * Print out the value of a real number in Pascal notation.
618 * This is, unfortunately, different than what one gets
619 * from "%g" in printf.
620 */
621
622public prtreal(r)
623double r;
624{
625 extern char *index();
626 char buf[256];
627
628 sprintf(buf, "%g", r);
629 if (buf[0] == '.') {
630 printf("0%s", buf);
631 } else if (buf[0] == '-' and buf[1] == '.') {
632 printf("-0%s", &buf[1]);
633 } else {
634 printf("%s", buf);
635 }
636 if (index(buf, '.') == nil) {
637 printf(".0");
638 }
639}
640
641/*
642 * Print out a character using ^? notation for unprintables.
643 */
644
645public printchar(c)
646char c;
647{
648 if (c == 0) {
649 putchar('\\');
650 putchar('0');
651 } else if (c == '\n') {
652 putchar('\\');
653 putchar('n');
654 } else if (c > 0 and c < ' ') {
655 putchar('^');
656 putchar(c - 1 + 'A');
2fd0f574 657 } else if (c >= ' ' && c <= '~') {
6eb0951d 658 putchar(c);
2fd0f574 659 } else {
a1c8cef6 660 printf("\\0%o",c&0xff);
6eb0951d
ML
661 }
662}
0022c355
ML
663
664/*
665 * Print out a value for a range type (integer, char, or boolean).
666 */
667
668public printRangeVal (val, t)
669long val;
670Symbol t;
671{
672 if (t == t_boolean->type or istypename(t->type, "boolean")) {
673 if ((boolean) val) {
674 printf("true");
675 } else {
676 printf("false");
677 }
678 } else if (t == t_char->type or istypename(t->type, "char")) {
679 if (varIsSet("$hexchars")) {
680 printf("0x%lx", val);
681 } else {
682 putchar('\'');
683 printchar(val);
684 putchar('\'');
685 }
686 } else if (varIsSet("$hexints")) {
687 printf("0x%lx", val);
688 } else if (t->symvalue.rangev.lower >= 0) {
689 printf("%lu", val);
690 } else {
691 printf("%ld", val);
692 }
693}
694
695/*
696 * Print out an enumerated value by finding the corresponding
697 * name in the enumeration list.
698 */
699
700public printEnum (i, t)
701integer i;
702Symbol t;
703{
704 register Symbol e;
705
706 e = t->chain;
707 while (e != nil and e->symvalue.constval->value.lcon != i) {
708 e = e->chain;
709 }
710 if (e != nil) {
711 printf("%s", symname(e));
712 } else {
713 printf("%d", i);
714 }
715}
716
717/*
718 * Print out a null-terminated string (pointer to char)
719 * starting at the given address.
720 */
721
722public printString (addr, quotes)
723Address addr;
724boolean quotes;
725{
726 register Address a;
727 register integer i, len;
728 register boolean endofstring;
a1c8cef6
SL
729 register int unprintables;
730#define MAXGARBAGE 4
0022c355
ML
731 union {
732 char ch[sizeof(Word)];
733 int word;
734 } u;
735
736 if (varIsSet("$hexstrings")) {
737 printf("0x%x", addr);
738 } else {
739 if (quotes) {
740 putchar('"');
741 }
742 a = addr;
a1c8cef6 743 unprintables = 0;
0022c355
ML
744 endofstring = false;
745 while (not endofstring) {
746 dread(&u, a, sizeof(u));
747 i = 0;
748 do {
749 if (u.ch[i] == '\0') {
750 endofstring = true;
751 } else {
752 printchar(u.ch[i]);
a1c8cef6
SL
753 if (!isascii(u.ch[i]) and ++unprintables > MAXGARBAGE) {
754 endofstring = true;
755 printf("...");
756 }
0022c355
ML
757 }
758 ++i;
759 } while (i < sizeof(Word) and not endofstring);
760 a += sizeof(Word);
761 }
762 if (quotes) {
763 putchar('"');
764 }
765 }
766}