NCR3000 needs explicit include of sys/sockio.h
[unix-history] / usr / src / old / dbx / printsym.c
CommitLineData
2a24676e 1/*
8a90f3aa
KB
2 * Copyright (c) 1983 The Regents of the University of California.
3 * All rights reserved.
4 *
6ecf3d85 5 * %sccs.include.redist.c%
2a24676e 6 */
6eb0951d 7
2a24676e 8#ifndef lint
6ecf3d85 9static char sccsid[] = "@(#)printsym.c 5.7 (Berkeley) %G%";
8a90f3aa 10#endif /* not lint */
6eb0951d
ML
11
12/*
13 * Printing of symbolic information.
14 */
15
16#include "defs.h"
17#include "symbols.h"
18#include "languages.h"
19#include "printsym.h"
20#include "tree.h"
21#include "eval.h"
22#include "mappings.h"
23#include "process.h"
24#include "runtime.h"
25#include "machine.h"
26#include "names.h"
0022c355 27#include "keywords.h"
6eb0951d 28#include "main.h"
a1c8cef6 29#include <ctype.h>
6eb0951d
ML
30
31#ifndef public
32#endif
33
b38a9c14
ML
34/*
35 * Maximum number of arguments to a function.
36 * This is used as a check for the possibility that the stack has been
37 * overwritten and therefore a saved argument pointer might indicate
38 * to an absurdly large number of arguments.
39 */
40
41#define MAXARGSPASSED 20
42
6eb0951d
ML
43/*
44 * Return a pointer to the string for the name of the class that
45 * the given symbol belongs to.
46 */
47
48private String clname[] = {
24350cae
DS
49 "bad use", "constant", "type", "variable", "array", "array",
50 "dynarray", "subarray", "fileptr", "record", "field",
0022c355 51 "procedure", "function", "funcvar",
6eb0951d
ML
52 "ref", "pointer", "file", "set", "range", "label", "withptr",
53 "scalar", "string", "program", "improper", "variant",
2fd0f574 54 "procparam", "funcparam", "module", "tag", "common", "extref", "typeref"
6eb0951d
ML
55};
56
57public String classname(s)
58Symbol s;
59{
60 return clname[ord(s->class)];
61}
62
63/*
64 * Note the entry of the given block, unless it's the main program.
65 */
66
67public printentry(s)
68Symbol s;
69{
70 if (s != program) {
0022c355
ML
71 printf("\nentering %s ", classname(s));
72 printname(stdout, s);
73 printf("\n");
6eb0951d
ML
74 }
75}
76
77/*
78 * Note the exit of the given block
79 */
80
81public printexit(s)
82Symbol s;
83{
84 if (s != program) {
0022c355
ML
85 printf("leaving %s ", classname(s));
86 printname(stdout, s);
87 printf("\n\n");
6eb0951d
ML
88 }
89}
90
91/*
92 * Note the call of s from t.
93 */
94
95public printcall(s, t)
96Symbol s, t;
97{
0022c355
ML
98 printf("calling ");
99 printname(stdout, s);
6eb0951d 100 printparams(s, nil);
0022c355
ML
101 printf(" from %s ", classname(t));
102 printname(stdout, t);
103 printf("\n");
6eb0951d
ML
104}
105
106/*
107 * Note the return from s. If s is a function, print the value
108 * it is returning. This is somewhat painful, since the function
109 * has actually just returned.
110 */
111
112public printrtn(s)
113Symbol s;
114{
115 register Symbol t;
116 register int len;
117 Boolean isindirect;
118
119 printf("returning ");
63a90519 120 if (s->class == FUNC && (!istypename(s->type,"void"))) {
6eb0951d
ML
121 len = size(s->type);
122 if (canpush(len)) {
123 t = rtype(s->type);
124 isindirect = (Boolean) (t->class == RECORD or t->class == VARNT);
125 pushretval(len, isindirect);
126 printval(s->type);
127 putchar(' ');
128 } else {
129 printf("(value too large) ");
130 }
131 }
0022c355
ML
132 printf("from ");
133 printname(stdout, s);
134 printf("\n");
6eb0951d
ML
135}
136
137/*
138 * Print the values of the parameters of the given procedure or function.
139 * The frame distinguishes recursive instances of a procedure.
2fd0f574
SL
140 *
141 * If the procedure or function is internal, the argument count is
142 * not valid so we ignore it.
6eb0951d
ML
143 */
144
145public printparams(f, frame)
146Symbol f;
147Frame frame;
148{
149 Symbol param;
150 int n, m, s;
151
152 n = nargspassed(frame);
2fd0f574
SL
153 if (isinternal(f)) {
154 n = 0;
155 }
0022c355 156 printf("(");
6eb0951d
ML
157 param = f->chain;
158 if (param != nil or n > 0) {
6eb0951d
ML
159 m = n;
160 if (param != nil) {
161 for (;;) {
0022c355 162 s = psize(param) div sizeof(Word);
6eb0951d
ML
163 if (s == 0) {
164 s = 1;
165 }
166 m -= s;
0022c355
ML
167 if (showaggrs) {
168 printv(param, frame);
169 } else {
170 printparamv(param, frame);
171 }
6eb0951d
ML
172 param = param->chain;
173 if (param == nil) break;
174 printf(", ");
175 }
176 }
177 if (m > 0) {
b38a9c14
ML
178 if (m > MAXARGSPASSED) {
179 m = MAXARGSPASSED;
180 }
6eb0951d
ML
181 if (f->chain != nil) {
182 printf(", ");
183 }
184 for (;;) {
185 --m;
186 printf("0x%x", argn(n - m, frame));
187 if (m <= 0) break;
188 printf(", ");
189 }
190 }
6eb0951d 191 }
0022c355 192 printf(")");
6eb0951d
ML
193}
194
195/*
196 * Test if a symbol should be printed. We don't print files,
197 * for example, simply because there's no good way to do it.
198 * The symbol must be within the given function.
199 */
200
201public Boolean should_print(s)
202Symbol s;
203{
204 Boolean b;
205 register Symbol t;
206
207 switch (s->class) {
208 case VAR:
209 case FVAR:
eb18c137
ML
210 if (isparam(s)) {
211 b = false;
212 } else {
213 t = rtype(s->type);
214 if (t == nil) {
215 b = false;
216 } else {
217 switch (t->class) {
218 case FILET:
219 case SET:
eb18c137
ML
220 case BADUSE:
221 b = false;
222 break;
223
224 default:
225 b = true;
226 break;
227 }
228 }
229 }
6eb0951d
ML
230 break;
231
232 default:
233 b = false;
234 break;
235 }
236 return b;
237}
238
0022c355
ML
239/*
240 * Print out a parameter value.
241 *
242 * Since this is intended to be printed on a single line with other information
243 * aggregate values are not printed.
244 */
245
246public printparamv (p, frame)
247Symbol p;
248Frame frame;
249{
250 Symbol t;
251
252 t = rtype(p->type);
253 switch (t->class) {
254 case ARRAY:
24350cae 255 case OPENARRAY:
0022c355
ML
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);
24350cae 418 if (s->block != nil and s->block->name != nil) {
6eb0951d
ML
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:
24350cae
DS
431 switch (s->storage) {
432 case INREG:
433 printf("reg\t%d\n", s->symvalue.offset);
434 break;
435
436 case STK:
437 printf("offset\t%d\n", s->symvalue.offset);
438 break;
439
440 case EXT:
441 printf("address\t0x%x\n", s->symvalue.offset);
442 break;
6eb0951d 443 }
4dc0ac37 444 printf("size\t%d\n", size(s));
6eb0951d
ML
445 break;
446
447 case RECORD:
448 case VARNT:
449 printf("size\t%d\n", s->symvalue.offset);
450 break;
451
452 case FIELD:
453 printf("offset\t%d\n", s->symvalue.field.offset);
454 printf("size\t%d\n", s->symvalue.field.length);
455 break;
456
8ee43d3e 457 case PROG:
6eb0951d
ML
458 case PROC:
459 case FUNC:
460 printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
a71dda28 461 if (isinline(s)) {
ffa66ed0 462 printf("inline procedure\n");
a71dda28 463 }
b38a9c14
ML
464 if (nosource(s)) {
465 printf("does not have source information\n");
466 } else {
467 printf("has source information\n");
468 }
6eb0951d
ML
469 break;
470
471 case RANGE:
8ee43d3e
ML
472 prangetype(s->symvalue.rangev.lowertype);
473 printf("lower\t%d\n", s->symvalue.rangev.lower);
474 prangetype(s->symvalue.rangev.uppertype);
6eb0951d
ML
475 printf("upper\t%d\n", s->symvalue.rangev.upper);
476 break;
477
478 default:
479 /* do nothing */
480 break;
481 }
482}
483
8ee43d3e
ML
484private prangetype(r)
485Rangetype r;
486{
487 switch (r) {
488 case R_CONST:
489 printf("CONST");
490 break;
491
492 case R_ARG:
493 printf("ARG");
494 break;
495
496 case R_TEMP:
497 printf("TEMP");
498 break;
499
500 case R_ADJUST:
501 printf("ADJUST");
502 break;
503 }
504}
505
6eb0951d
ML
506/*
507 * Print out the value on top of the stack according to the given type.
508 */
509
510public printval(t)
511Symbol t;
512{
513 Symbol s;
514
515 checkref(t);
2fd0f574
SL
516 if (t->class == TYPEREF) {
517 resolveRef(t);
518 }
6eb0951d
ML
519 switch (t->class) {
520 case PROC:
521 case FUNC:
522 s = pop(Symbol);
523 printf("%s", symname(s));
524 break;
525
526 default:
0022c355 527 if (t->language == nil or t->language == primlang) {
5e821af5 528 (*language_op(findlanguage(".c"), L_PRINTVAL))(t);
6eb0951d
ML
529 } else {
530 (*language_op(t->language, L_PRINTVAL))(t);
531 }
532 break;
533 }
534}
535
536/*
537 * Print out the value of a record, field by field.
538 */
539
540public printrecord(s)
541Symbol s;
542{
2fd0f574
SL
543 Symbol f;
544
6eb0951d
ML
545 if (s->chain == nil) {
546 error("record has no fields");
547 }
548 printf("(");
549 sp -= size(s);
2fd0f574
SL
550 f = s->chain;
551 if (f != nil) {
552 for (;;) {
553 printfield(f);
554 f = f->chain;
555 if (f == nil) break;
556 printf(", ");
557 }
558 }
6eb0951d
ML
559 printf(")");
560}
561
562/*
2fd0f574 563 * Print out a field.
6eb0951d
ML
564 */
565
2fd0f574
SL
566private printfield(f)
567Symbol f;
6eb0951d
ML
568{
569 Stack *savesp;
2fd0f574 570 register int off, len;
6eb0951d 571
2fd0f574 572 printf("%s = ", symname(f));
6eb0951d 573 savesp = sp;
2fd0f574
SL
574 off = f->symvalue.field.offset;
575 len = f->symvalue.field.length;
576 sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE);
577 printval(f);
6eb0951d
ML
578 sp = savesp;
579}
580
581/*
582 * Print out the contents of an array.
583 * Haven't quite figured out what the best format is.
584 *
585 * This is rather inefficient.
586 *
587 * The "2*elsize" is there since "printval" drops the stack by elsize.
588 */
589
590public printarray(a)
591Symbol a;
592{
593 Stack *savesp, *newsp;
594 Symbol eltype;
595 long elsize;
596 String sep;
597
598 savesp = sp;
20614ea9 599 sp -= (size(a));
6eb0951d
ML
600 newsp = sp;
601 eltype = rtype(a->type);
602 elsize = size(eltype);
603 printf("(");
604 if (eltype->class == RECORD or eltype->class == ARRAY or
605 eltype->class == VARNT) {
606 sep = "\n";
607 putchar('\n');
608 } else {
609 sep = ", ";
610 }
611 for (sp += elsize; sp <= savesp; sp += 2*elsize) {
612 if (sp - elsize != newsp) {
613 fputs(sep, stdout);
614 }
615 printval(eltype);
616 }
617 sp = newsp;
618 if (streq(sep, "\n")) {
619 putchar('\n');
620 }
621 printf(")");
622}
623
624/*
625 * Print out the value of a real number in Pascal notation.
626 * This is, unfortunately, different than what one gets
627 * from "%g" in printf.
628 */
629
630public prtreal(r)
631double r;
632{
633 extern char *index();
634 char buf[256];
635
24350cae
DS
636# ifdef IRIS
637 sprintf(buf, "%lg", r);
638# else
639 sprintf(buf, "%g", r);
640# endif
6eb0951d
ML
641 if (buf[0] == '.') {
642 printf("0%s", buf);
643 } else if (buf[0] == '-' and buf[1] == '.') {
644 printf("-0%s", &buf[1]);
645 } else {
646 printf("%s", buf);
647 }
648 if (index(buf, '.') == nil) {
649 printf(".0");
650 }
651}
652
653/*
654 * Print out a character using ^? notation for unprintables.
655 */
656
657public printchar(c)
658char c;
659{
660 if (c == 0) {
661 putchar('\\');
662 putchar('0');
663 } else if (c == '\n') {
664 putchar('\\');
665 putchar('n');
666 } else if (c > 0 and c < ' ') {
667 putchar('^');
668 putchar(c - 1 + 'A');
2fd0f574 669 } else if (c >= ' ' && c <= '~') {
6eb0951d 670 putchar(c);
2fd0f574 671 } else {
a1c8cef6 672 printf("\\0%o",c&0xff);
6eb0951d
ML
673 }
674}
0022c355
ML
675
676/*
677 * Print out a value for a range type (integer, char, or boolean).
678 */
679
680public printRangeVal (val, t)
681long val;
682Symbol t;
683{
684 if (t == t_boolean->type or istypename(t->type, "boolean")) {
685 if ((boolean) val) {
686 printf("true");
687 } else {
688 printf("false");
689 }
690 } else if (t == t_char->type or istypename(t->type, "char")) {
691 if (varIsSet("$hexchars")) {
692 printf("0x%lx", val);
693 } else {
694 putchar('\'');
695 printchar(val);
696 putchar('\'');
697 }
698 } else if (varIsSet("$hexints")) {
699 printf("0x%lx", val);
700 } else if (t->symvalue.rangev.lower >= 0) {
701 printf("%lu", val);
702 } else {
703 printf("%ld", val);
704 }
705}
706
707/*
708 * Print out an enumerated value by finding the corresponding
709 * name in the enumeration list.
710 */
711
712public printEnum (i, t)
713integer i;
714Symbol t;
715{
716 register Symbol e;
717
718 e = t->chain;
719 while (e != nil and e->symvalue.constval->value.lcon != i) {
720 e = e->chain;
721 }
722 if (e != nil) {
723 printf("%s", symname(e));
724 } else {
725 printf("%d", i);
726 }
727}
728
729/*
730 * Print out a null-terminated string (pointer to char)
731 * starting at the given address.
732 */
733
734public printString (addr, quotes)
735Address addr;
736boolean quotes;
737{
738 register Address a;
739 register integer i, len;
740 register boolean endofstring;
a1c8cef6
SL
741 register int unprintables;
742#define MAXGARBAGE 4
0022c355
ML
743 union {
744 char ch[sizeof(Word)];
745 int word;
746 } u;
747
748 if (varIsSet("$hexstrings")) {
749 printf("0x%x", addr);
750 } else {
751 if (quotes) {
752 putchar('"');
753 }
754 a = addr;
a1c8cef6 755 unprintables = 0;
0022c355
ML
756 endofstring = false;
757 while (not endofstring) {
758 dread(&u, a, sizeof(u));
759 i = 0;
760 do {
761 if (u.ch[i] == '\0') {
762 endofstring = true;
763 } else {
764 printchar(u.ch[i]);
a1c8cef6
SL
765 if (!isascii(u.ch[i]) and ++unprintables > MAXGARBAGE) {
766 endofstring = true;
767 printf("...");
768 }
0022c355
ML
769 }
770 ++i;
771 } while (i < sizeof(Word) and not endofstring);
772 a += sizeof(Word);
773 }
774 if (quotes) {
775 putchar('"');
776 }
777 }
778}