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