|
|
1.1 root 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: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)printsym.c 5.5 (Berkeley) 1/12/88";
9: #endif not lint
10:
11: static char rcsid[] = "$Header: printsym.c,v 1.4 87/04/15 00:23:35 donn Exp $";
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"
28: #include "keywords.h"
29: #include "main.h"
30: #include <ctype.h>
31:
32: #ifndef public
33: #endif
34:
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:
44: /*
45: * Return a pointer to the string for the name of the class that
46: * the given symbol belongs to.
47: */
48:
49: private String clname[] = {
50: "bad use", "constant", "type", "variable", "array", "array",
51: "dynarray", "subarray", "fileptr", "record", "field",
52: "procedure", "function", "funcvar",
53: "ref", "pointer", "file", "set", "range", "label", "withptr",
54: "scalar", "string", "program", "improper", "variant",
55: "procparam", "funcparam", "module", "tag", "common", "extref", "typeref"
56: };
57:
58: public String classname(s)
59: Symbol 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:
68: public printentry(s)
69: Symbol s;
70: {
71: if (s != program) {
72: printf("\nentering %s ", classname(s));
73: printname(stdout, s);
74: printf("\n");
75: }
76: }
77:
78: /*
79: * Note the exit of the given block
80: */
81:
82: public printexit(s)
83: Symbol s;
84: {
85: if (s != program) {
86: printf("leaving %s ", classname(s));
87: printname(stdout, s);
88: printf("\n\n");
89: }
90: }
91:
92: /*
93: * Note the call of s from t.
94: */
95:
96: public printcall(s, t)
97: Symbol s, t;
98: {
99: printf("calling ");
100: printname(stdout, s);
101: printparams(s, nil);
102: printf(" from %s ", classname(t));
103: printname(stdout, t);
104: printf("\n");
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:
113: public printrtn(s)
114: Symbol s;
115: {
116: register Symbol t;
117: register int len;
118: Boolean isindirect;
119:
120: printf("returning ");
121: if (s->class == FUNC && (!istypename(s->type,"void"))) {
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: }
133: printf("from ");
134: printname(stdout, s);
135: printf("\n");
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.
141: *
142: * If the procedure or function is internal, the argument count is
143: * not valid so we ignore it.
144: */
145:
146: public printparams(f, frame)
147: Symbol f;
148: Frame frame;
149: {
150: Symbol param;
151: int n, m, s;
152:
153: n = nargspassed(frame);
154: if (isinternal(f)) {
155: n = 0;
156: }
157: printf("(");
158: param = f->chain;
159: if (param != nil or n > 0) {
160: m = n;
161: if (param != nil) {
162: for (;;) {
163: s = psize(param) div sizeof(Word);
164: if (s == 0) {
165: s = 1;
166: }
167: m -= s;
168: if (showaggrs) {
169: printv(param, frame);
170: } else {
171: printparamv(param, frame);
172: }
173: param = param->chain;
174: if (param == nil) break;
175: printf(", ");
176: }
177: }
178: if (m > 0) {
179: if (m > MAXARGSPASSED) {
180: m = MAXARGSPASSED;
181: }
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: }
192: }
193: printf(")");
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:
202: public Boolean should_print(s)
203: Symbol s;
204: {
205: Boolean b;
206: register Symbol t;
207:
208: switch (s->class) {
209: case VAR:
210: case FVAR:
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:
221: case BADUSE:
222: b = false;
223: break;
224:
225: default:
226: b = true;
227: break;
228: }
229: }
230: }
231: break;
232:
233: default:
234: b = false;
235: break;
236: }
237: return b;
238: }
239:
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:
247: public printparamv (p, frame)
248: Symbol p;
249: Frame frame;
250: {
251: Symbol t;
252:
253: t = rtype(p->type);
254: switch (t->class) {
255: case ARRAY:
256: case OPENARRAY:
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:
277: /*
278: * Print the name and value of a variable.
279: */
280:
281: public printv(s, frame)
282: Symbol s;
283: Frame 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: }
294: if (isvarparam(s) and not isopenarray(s)) {
295: rpush(address(s, frame), sizeof(Address));
296: addr = pop(Address);
297: } else {
298: addr = address(s, frame);
299: }
300: len = size(s);
301: if (not canpush(len)) {
302: printf("*** expression too large ***");
303: } else if (isreg(s)) {
304: push(Address, addr);
305: printval(s->type);
306: } else {
307: rpush(addr, len);
308: printval(s->type);
309: }
310: }
311:
312: /*
313: * Print out the name of a symbol.
314: */
315:
316: public printname(f, s)
317: File f;
318: Symbol s;
319: {
320: if (s == nil) {
321: fprintf(f, "(noname)");
322: } else if (s == program) {
323: fprintf(f, ".");
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:
335: public printwhich(f, s)
336: File f;
337: Symbol 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:
348: public printwhereis(f, s)
349: File f;
350: Symbol 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:
370: private printouter(f, s)
371: File f;
372: Symbol 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:
385: public printdecl(s)
386: Symbol s;
387: {
388: Language lang;
389:
390: checkref(s);
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);
397: }
398:
399: /*
400: * Straight dump of symbol information.
401: */
402:
403: public psym(s)
404: Symbol 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);
419: if (s->block != nil and s->block->name != nil) {
420: printf(" (");
421: printname(stdout, s->block);
422: putchar(')');
423: }
424: putchar('\n');
425: switch (s->class) {
426: case TYPE:
427: printf("size\t%d\n", size(s));
428: break;
429:
430: case VAR:
431: case REF:
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;
444: }
445: printf("size\t%d\n", size(s));
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:
458: case PROG:
459: case PROC:
460: case FUNC:
461: printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
462: if (isinline(s)) {
463: printf("inline procedure\n");
464: }
465: if (nosource(s)) {
466: printf("does not have source information\n");
467: } else {
468: printf("has source information\n");
469: }
470: break;
471:
472: case RANGE:
473: prangetype(s->symvalue.rangev.lowertype);
474: printf("lower\t%d\n", s->symvalue.rangev.lower);
475: prangetype(s->symvalue.rangev.uppertype);
476: printf("upper\t%d\n", s->symvalue.rangev.upper);
477: break;
478:
479: default:
480: /* do nothing */
481: break;
482: }
483: }
484:
485: private prangetype(r)
486: Rangetype 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:
507: /*
508: * Print out the value on top of the stack according to the given type.
509: */
510:
511: public printval(t)
512: Symbol t;
513: {
514: Symbol s;
515:
516: checkref(t);
517: if (t->class == TYPEREF) {
518: resolveRef(t);
519: }
520: switch (t->class) {
521: case PROC:
522: case FUNC:
523: s = pop(Symbol);
524: printf("%s", symname(s));
525: break;
526:
527: default:
528: if (t->language == nil or t->language == primlang) {
529: (*language_op(findlanguage(".c"), L_PRINTVAL))(t);
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:
541: public printrecord(s)
542: Symbol s;
543: {
544: Symbol f;
545:
546: if (s->chain == nil) {
547: error("record has no fields");
548: }
549: printf("(");
550: sp -= size(s);
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: }
560: printf(")");
561: }
562:
563: /*
564: * Print out a field.
565: */
566:
567: private printfield(f)
568: Symbol f;
569: {
570: Stack *savesp;
571: register int off, len;
572:
573: printf("%s = ", symname(f));
574: savesp = sp;
575: off = f->symvalue.field.offset;
576: len = f->symvalue.field.length;
577: sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE);
578: printval(f);
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:
591: public printarray(a)
592: Symbol a;
593: {
594: Stack *savesp, *newsp;
595: Symbol eltype;
596: long elsize;
597: String sep;
598:
599: savesp = sp;
600: sp -= (size(a));
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:
631: public prtreal(r)
632: double r;
633: {
634: extern char *index();
635: char buf[256];
636:
637: # ifdef IRIS
638: sprintf(buf, "%lg", r);
639: # else
640: sprintf(buf, "%g", r);
641: # endif
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:
658: public printchar(c)
659: char 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');
670: } else if (c >= ' ' && c <= '~') {
671: putchar(c);
672: } else {
673: printf("\\0%o",c&0xff);
674: }
675: }
676:
677: /*
678: * Print out a value for a range type (integer, char, or boolean).
679: */
680:
681: public printRangeVal (val, t)
682: long val;
683: Symbol 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:
713: public printEnum (i, t)
714: integer i;
715: Symbol 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:
735: public printString (addr, quotes)
736: Address addr;
737: boolean quotes;
738: {
739: register Address a;
740: register integer i, len;
741: register boolean endofstring;
742: register int unprintables;
743: #define MAXGARBAGE 4
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;
756: unprintables = 0;
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]);
766: if (!isascii(u.ch[i]) and ++unprintables > MAXGARBAGE) {
767: endofstring = true;
768: printf("...");
769: }
770: }
771: ++i;
772: } while (i < sizeof(Word) and not endofstring);
773: a += sizeof(Word);
774: }
775: if (quotes) {
776: putchar('"');
777: }
778: }
779: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.