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