BSD 4_3_Tahoe release
[unix-history] / usr / src / ucb / 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
ca67e7b4 8static char sccsid[] = "@(#)printsym.c 5.5 (Berkeley) 1/12/88";
2a24676e 9#endif not lint
0022c355 10
24350cae 11static char rcsid[] = "$Header: printsym.c,v 1.4 87/04/15 00:23:35 donn 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[] = {
24350cae
DS
50 "bad use", "constant", "type", "variable", "array", "array",
51 "dynarray", "subarray", "fileptr", "record", "field",
0022c355 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:
24350cae 256 case OPENARRAY:
0022c355
ML
257 case DYNARRAY:
258 case SUBARRAY:
259 t = rtype(t->type);
260 if (compatible(t, t_char)) {
261 printv(p, frame);
262 } else {
263 printf("%s = (...)", symname(p));
264 }
265 break;
266
267 case RECORD:
268 printf("%s = (...)", symname(p));
269 break;
270
271 default:
272 printv(p, frame);
273 break;
274 }
275}
276
6eb0951d
ML
277/*
278 * Print the name and value of a variable.
279 */
280
281public printv(s, frame)
282Symbol s;
283Frame frame;
284{
285 Address addr;
286 int len;
287
288 if (isambiguous(s) and ismodule(container(s))) {
289 printname(stdout, s);
290 printf(" = ");
291 } else {
292 printf("%s = ", symname(s));
293 }
0022c355
ML
294 if (isvarparam(s) and not isopenarray(s)) {
295 rpush(address(s, frame), sizeof(Address));
296 addr = pop(Address);
6eb0951d 297 } else {
0022c355
ML
298 addr = address(s, frame);
299 }
300 len = size(s);
ffb79108
KM
301 if (not canpush(len)) {
302 printf("*** expression too large ***");
303 } else if (isreg(s)) {
304 push(Address, addr);
0022c355
ML
305 printval(s->type);
306 } else {
ffb79108
KM
307 rpush(addr, len);
308 printval(s->type);
0022c355 309 }
6eb0951d
ML
310}
311
312/*
313 * Print out the name of a symbol.
314 */
315
316public printname(f, s)
317File f;
318Symbol s;
319{
320 if (s == nil) {
321 fprintf(f, "(noname)");
2fd0f574
SL
322 } else if (s == program) {
323 fprintf(f, ".");
6eb0951d
ML
324 } else if (isredirected() or isambiguous(s)) {
325 printwhich(f, s);
326 } else {
327 fprintf(f, "%s", symname(s));
328 }
329}
330
331/*
332 * Print the fully specified variable that is described by the given identifer.
333 */
334
335public printwhich(f, s)
336File f;
337Symbol s;
338{
339 printouter(f, container(s));
340 fprintf(f, "%s", symname(s));
341}
342
343/*
344 * Print the fully qualified name of each symbol that has the same name
345 * as the given symbol.
346 */
347
348public printwhereis(f, s)
349File f;
350Symbol s;
351{
352 register Name n;
353 register Symbol t;
354
355 checkref(s);
356 n = s->name;
357 t = lookup(n);
358 printwhich(f, t);
359 t = t->next_sym;
360 while (t != nil) {
361 if (t->name == n) {
362 putc(' ', f);
363 printwhich(f, t);
364 }
365 t = t->next_sym;
366 }
367 putc('\n', f);
368}
369
370private printouter(f, s)
371File f;
372Symbol s;
373{
374 Symbol outer;
375
376 if (s != nil) {
377 outer = container(s);
378 if (outer != nil and outer != program) {
379 printouter(f, outer);
380 }
381 fprintf(f, "%s.", symname(s));
382 }
383}
384
385public printdecl(s)
386Symbol s;
387{
0022c355
ML
388 Language lang;
389
6eb0951d 390 checkref(s);
0022c355
ML
391 if (s->language == nil or s->language == primlang) {
392 lang = findlanguage(".s");
393 } else {
394 lang = s->language;
395 }
396 (*language_op(lang, L_PRINTDECL))(s);
6eb0951d
ML
397}
398
399/*
400 * Straight dump of symbol information.
401 */
402
403public psym(s)
404Symbol s;
405{
406 printf("name\t%s\n", symname(s));
407 printf("lang\t%s\n", language_name(s->language));
408 printf("level\t%d\n", s->level);
409 printf("class\t%s\n", classname(s));
410 printf("type\t0x%x", s->type);
411 if (s->type != nil and s->type->name != nil) {
412 printf(" (%s)", symname(s->type));
413 }
414 printf("\nchain\t0x%x", s->chain);
415 if (s->chain != nil and s->chain->name != nil) {
416 printf(" (%s)", symname(s->chain));
417 }
418 printf("\nblock\t0x%x", s->block);
24350cae 419 if (s->block != nil and s->block->name != nil) {
6eb0951d
ML
420 printf(" (");
421 printname(stdout, s->block);
422 putchar(')');
423 }
424 putchar('\n');
425 switch (s->class) {
0022c355
ML
426 case TYPE:
427 printf("size\t%d\n", size(s));
428 break;
429
6eb0951d
ML
430 case VAR:
431 case REF:
24350cae
DS
432 switch (s->storage) {
433 case INREG:
434 printf("reg\t%d\n", s->symvalue.offset);
435 break;
436
437 case STK:
438 printf("offset\t%d\n", s->symvalue.offset);
439 break;
440
441 case EXT:
442 printf("address\t0x%x\n", s->symvalue.offset);
443 break;
6eb0951d 444 }
4dc0ac37 445 printf("size\t%d\n", size(s));
6eb0951d
ML
446 break;
447
448 case RECORD:
449 case VARNT:
450 printf("size\t%d\n", s->symvalue.offset);
451 break;
452
453 case FIELD:
454 printf("offset\t%d\n", s->symvalue.field.offset);
455 printf("size\t%d\n", s->symvalue.field.length);
456 break;
457
8ee43d3e 458 case PROG:
6eb0951d
ML
459 case PROC:
460 case FUNC:
461 printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
a71dda28 462 if (isinline(s)) {
ffa66ed0 463 printf("inline procedure\n");
a71dda28 464 }
b38a9c14
ML
465 if (nosource(s)) {
466 printf("does not have source information\n");
467 } else {
468 printf("has source information\n");
469 }
6eb0951d
ML
470 break;
471
472 case RANGE:
8ee43d3e
ML
473 prangetype(s->symvalue.rangev.lowertype);
474 printf("lower\t%d\n", s->symvalue.rangev.lower);
475 prangetype(s->symvalue.rangev.uppertype);
6eb0951d
ML
476 printf("upper\t%d\n", s->symvalue.rangev.upper);
477 break;
478
479 default:
480 /* do nothing */
481 break;
482 }
483}
484
8ee43d3e
ML
485private prangetype(r)
486Rangetype r;
487{
488 switch (r) {
489 case R_CONST:
490 printf("CONST");
491 break;
492
493 case R_ARG:
494 printf("ARG");
495 break;
496
497 case R_TEMP:
498 printf("TEMP");
499 break;
500
501 case R_ADJUST:
502 printf("ADJUST");
503 break;
504 }
505}
506
6eb0951d
ML
507/*
508 * Print out the value on top of the stack according to the given type.
509 */
510
511public printval(t)
512Symbol t;
513{
514 Symbol s;
515
516 checkref(t);
2fd0f574
SL
517 if (t->class == TYPEREF) {
518 resolveRef(t);
519 }
6eb0951d
ML
520 switch (t->class) {
521 case PROC:
522 case FUNC:
523 s = pop(Symbol);
524 printf("%s", symname(s));
525 break;
526
527 default:
0022c355 528 if (t->language == nil or t->language == primlang) {
5e821af5 529 (*language_op(findlanguage(".c"), L_PRINTVAL))(t);
6eb0951d
ML
530 } else {
531 (*language_op(t->language, L_PRINTVAL))(t);
532 }
533 break;
534 }
535}
536
537/*
538 * Print out the value of a record, field by field.
539 */
540
541public printrecord(s)
542Symbol s;
543{
2fd0f574
SL
544 Symbol f;
545
6eb0951d
ML
546 if (s->chain == nil) {
547 error("record has no fields");
548 }
549 printf("(");
550 sp -= size(s);
2fd0f574
SL
551 f = s->chain;
552 if (f != nil) {
553 for (;;) {
554 printfield(f);
555 f = f->chain;
556 if (f == nil) break;
557 printf(", ");
558 }
559 }
6eb0951d
ML
560 printf(")");
561}
562
563/*
2fd0f574 564 * Print out a field.
6eb0951d
ML
565 */
566
2fd0f574
SL
567private printfield(f)
568Symbol f;
6eb0951d
ML
569{
570 Stack *savesp;
2fd0f574 571 register int off, len;
6eb0951d 572
2fd0f574 573 printf("%s = ", symname(f));
6eb0951d 574 savesp = sp;
2fd0f574
SL
575 off = f->symvalue.field.offset;
576 len = f->symvalue.field.length;
577 sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE);
578 printval(f);
6eb0951d
ML
579 sp = savesp;
580}
581
582/*
583 * Print out the contents of an array.
584 * Haven't quite figured out what the best format is.
585 *
586 * This is rather inefficient.
587 *
588 * The "2*elsize" is there since "printval" drops the stack by elsize.
589 */
590
591public printarray(a)
592Symbol a;
593{
594 Stack *savesp, *newsp;
595 Symbol eltype;
596 long elsize;
597 String sep;
598
599 savesp = sp;
20614ea9 600 sp -= (size(a));
6eb0951d
ML
601 newsp = sp;
602 eltype = rtype(a->type);
603 elsize = size(eltype);
604 printf("(");
605 if (eltype->class == RECORD or eltype->class == ARRAY or
606 eltype->class == VARNT) {
607 sep = "\n";
608 putchar('\n');
609 } else {
610 sep = ", ";
611 }
612 for (sp += elsize; sp <= savesp; sp += 2*elsize) {
613 if (sp - elsize != newsp) {
614 fputs(sep, stdout);
615 }
616 printval(eltype);
617 }
618 sp = newsp;
619 if (streq(sep, "\n")) {
620 putchar('\n');
621 }
622 printf(")");
623}
624
625/*
626 * Print out the value of a real number in Pascal notation.
627 * This is, unfortunately, different than what one gets
628 * from "%g" in printf.
629 */
630
631public prtreal(r)
632double r;
633{
634 extern char *index();
635 char buf[256];
636
24350cae
DS
637# ifdef IRIS
638 sprintf(buf, "%lg", r);
639# else
640 sprintf(buf, "%g", r);
641# endif
6eb0951d
ML
642 if (buf[0] == '.') {
643 printf("0%s", buf);
644 } else if (buf[0] == '-' and buf[1] == '.') {
645 printf("-0%s", &buf[1]);
646 } else {
647 printf("%s", buf);
648 }
649 if (index(buf, '.') == nil) {
650 printf(".0");
651 }
652}
653
654/*
655 * Print out a character using ^? notation for unprintables.
656 */
657
658public printchar(c)
659char c;
660{
661 if (c == 0) {
662 putchar('\\');
663 putchar('0');
664 } else if (c == '\n') {
665 putchar('\\');
666 putchar('n');
667 } else if (c > 0 and c < ' ') {
668 putchar('^');
669 putchar(c - 1 + 'A');
2fd0f574 670 } else if (c >= ' ' && c <= '~') {
6eb0951d 671 putchar(c);
2fd0f574 672 } else {
a1c8cef6 673 printf("\\0%o",c&0xff);
6eb0951d
ML
674 }
675}
0022c355
ML
676
677/*
678 * Print out a value for a range type (integer, char, or boolean).
679 */
680
681public printRangeVal (val, t)
682long val;
683Symbol t;
684{
685 if (t == t_boolean->type or istypename(t->type, "boolean")) {
686 if ((boolean) val) {
687 printf("true");
688 } else {
689 printf("false");
690 }
691 } else if (t == t_char->type or istypename(t->type, "char")) {
692 if (varIsSet("$hexchars")) {
693 printf("0x%lx", val);
694 } else {
695 putchar('\'');
696 printchar(val);
697 putchar('\'');
698 }
699 } else if (varIsSet("$hexints")) {
700 printf("0x%lx", val);
701 } else if (t->symvalue.rangev.lower >= 0) {
702 printf("%lu", val);
703 } else {
704 printf("%ld", val);
705 }
706}
707
708/*
709 * Print out an enumerated value by finding the corresponding
710 * name in the enumeration list.
711 */
712
713public printEnum (i, t)
714integer i;
715Symbol t;
716{
717 register Symbol e;
718
719 e = t->chain;
720 while (e != nil and e->symvalue.constval->value.lcon != i) {
721 e = e->chain;
722 }
723 if (e != nil) {
724 printf("%s", symname(e));
725 } else {
726 printf("%d", i);
727 }
728}
729
730/*
731 * Print out a null-terminated string (pointer to char)
732 * starting at the given address.
733 */
734
735public printString (addr, quotes)
736Address addr;
737boolean quotes;
738{
739 register Address a;
740 register integer i, len;
741 register boolean endofstring;
a1c8cef6
SL
742 register int unprintables;
743#define MAXGARBAGE 4
0022c355
ML
744 union {
745 char ch[sizeof(Word)];
746 int word;
747 } u;
748
749 if (varIsSet("$hexstrings")) {
750 printf("0x%x", addr);
751 } else {
752 if (quotes) {
753 putchar('"');
754 }
755 a = addr;
a1c8cef6 756 unprintables = 0;
0022c355
ML
757 endofstring = false;
758 while (not endofstring) {
759 dread(&u, a, sizeof(u));
760 i = 0;
761 do {
762 if (u.ch[i] == '\0') {
763 endofstring = true;
764 } else {
765 printchar(u.ch[i]);
a1c8cef6
SL
766 if (!isascii(u.ch[i]) and ++unprintables > MAXGARBAGE) {
767 endofstring = true;
768 printf("...");
769 }
0022c355
ML
770 }
771 ++i;
772 } while (i < sizeof(Word) and not endofstring);
773 a += sizeof(Word);
774 }
775 if (quotes) {
776 putchar('"');
777 }
778 }
779}