|
|
1.1 root 1: /* Copyright (c) 1982 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)printsym.c 1.12 8/10/83";
4:
5: /*
6: * Printing of symbolic information.
7: */
8:
9: #include "defs.h"
10: #include "symbols.h"
11: #include "languages.h"
12: #include "printsym.h"
13: #include "tree.h"
14: #include "eval.h"
15: #include "mappings.h"
16: #include "process.h"
17: #include "runtime.h"
18: #include "machine.h"
19: #include "names.h"
20: #include "main.h"
21:
22: #ifndef public
23: #endif
24:
25: /*
26: * Maximum number of arguments to a function.
27: * This is used as a check for the possibility that the stack has been
28: * overwritten and therefore a saved argument pointer might indicate
29: * to an absurdly large number of arguments.
30: */
31:
32: #define MAXARGSPASSED 20
33:
34: /*
35: * Return a pointer to the string for the name of the class that
36: * the given symbol belongs to.
37: */
38:
39: private String clname[] = {
40: "bad use", "constant", "type", "variable", "array", "fileptr",
41: "record", "field", "procedure", "function", "funcvar",
42: "ref", "pointer", "file", "set", "range", "label", "withptr",
43: "scalar", "string", "program", "improper", "variant",
44: "procparam", "funcparam", "module", "tag", "common", "typeref"
45: };
46:
47: public String classname(s)
48: Symbol s;
49: {
50: return clname[ord(s->class)];
51: }
52:
53: /*
54: * Note the entry of the given block, unless it's the main program.
55: */
56:
57: public printentry(s)
58: Symbol s;
59: {
60: if (s != program) {
61: printf("\nentering %s %s\n", classname(s), symname(s));
62: }
63: }
64:
65: /*
66: * Note the exit of the given block
67: */
68:
69: public printexit(s)
70: Symbol s;
71: {
72: if (s != program) {
73: printf("leaving %s %s\n\n", classname(s), symname(s));
74: }
75: }
76:
77: /*
78: * Note the call of s from t.
79: */
80:
81: public printcall(s, t)
82: Symbol s, t;
83: {
84: printf("calling %s", symname(s));
85: printparams(s, nil);
86: printf(" from %s %s\n", classname(t), symname(t));
87: }
88:
89: /*
90: * Note the return from s. If s is a function, print the value
91: * it is returning. This is somewhat painful, since the function
92: * has actually just returned.
93: */
94:
95: public printrtn(s)
96: Symbol s;
97: {
98: register Symbol t;
99: register int len;
100: Boolean isindirect;
101:
102: printf("returning ");
103: if (s->class == FUNC && (!istypename(s->type,"void"))) {
104: len = size(s->type);
105: if (canpush(len)) {
106: t = rtype(s->type);
107: isindirect = (Boolean) (t->class == RECORD or t->class == VARNT);
108: pushretval(len, isindirect);
109: printval(s->type);
110: putchar(' ');
111: } else {
112: printf("(value too large) ");
113: }
114: }
115: printf("from %s\n", symname(s));
116: }
117:
118: /*
119: * Print the values of the parameters of the given procedure or function.
120: * The frame distinguishes recursive instances of a procedure.
121: */
122:
123: public printparams(f, frame)
124: Symbol f;
125: Frame frame;
126: {
127: Symbol param;
128: int n, m, s;
129:
130: n = nargspassed(frame);
131: param = f->chain;
132: if (param != nil or n > 0) {
133: printf("(");
134: m = n;
135: if (param != nil) {
136: for (;;) {
137: s = size(param) div sizeof(Word);
138: if (s == 0) {
139: s = 1;
140: }
141: m -= s;
142: printv(param, frame);
143: param = param->chain;
144: if (param == nil) break;
145: printf(", ");
146: }
147: }
148: if (m > 0) {
149: if (m > MAXARGSPASSED) {
150: m = MAXARGSPASSED;
151: }
152: if (f->chain != nil) {
153: printf(", ");
154: }
155: for (;;) {
156: --m;
157: printf("0x%x", argn(n - m, frame));
158: if (m <= 0) break;
159: printf(", ");
160: }
161: }
162: printf(")");
163: }
164: }
165:
166: /*
167: * Test if a symbol should be printed. We don't print files,
168: * for example, simply because there's no good way to do it.
169: * The symbol must be within the given function.
170: */
171:
172: public Boolean should_print(s)
173: Symbol s;
174: {
175: Boolean b;
176: register Symbol t;
177:
178: switch (s->class) {
179: case VAR:
180: case FVAR:
181: if (isparam(s)) {
182: b = false;
183: } else {
184: t = rtype(s->type);
185: if (t == nil) {
186: b = false;
187: } else {
188: switch (t->class) {
189: case FILET:
190: case SET:
191: case BADUSE:
192: b = false;
193: break;
194:
195: default:
196: b = true;
197: break;
198: }
199: }
200: }
201: break;
202:
203: default:
204: b = false;
205: break;
206: }
207: return b;
208: }
209:
210: /*
211: * Print the name and value of a variable.
212: */
213:
214: public printv(s, frame)
215: Symbol s;
216: Frame frame;
217: {
218: Address addr;
219: int len;
220:
221: if (isambiguous(s) and ismodule(container(s))) {
222: printname(stdout, s);
223: printf(" = ");
224: } else {
225: printf("%s = ", symname(s));
226: }
227: if(s->type->class == ARRAY && (! istypename(s->type->type,"char")) ) {
228: printf(" ARRAY ");
229: } else {
230: if (isvarparam(s)) {
231: rpush(address(s, frame), sizeof(Address));
232: addr = pop(Address);
233: len = size(s->type);
234: } else {
235: addr = address(s, frame);
236: len = size(s);
237: }
238: if (canpush(len)) {
239: rpush(addr, len);
240: printval(s->type);
241: } else {
242: printf("*** expression too large ***");
243: }
244: }
245: }
246:
247: /*
248: * Print out the name of a symbol.
249: */
250:
251: public printname(f, s)
252: File f;
253: Symbol s;
254: {
255: if (s == nil) {
256: fprintf(f, "(noname)");
257: } else if (isredirected() or isambiguous(s)) {
258: printwhich(f, s);
259: } else {
260: fprintf(f, "%s", symname(s));
261: }
262: }
263:
264: /*
265: * Print the fully specified variable that is described by the given identifer.
266: */
267:
268: public printwhich(f, s)
269: File f;
270: Symbol s;
271: {
272: printouter(f, container(s));
273: fprintf(f, "%s", symname(s));
274: }
275:
276: /*
277: * Print the fully qualified name of each symbol that has the same name
278: * as the given symbol.
279: */
280:
281: public printwhereis(f, s)
282: File f;
283: Symbol s;
284: {
285: register Name n;
286: register Symbol t;
287:
288: checkref(s);
289: n = s->name;
290: t = lookup(n);
291: printwhich(f, t);
292: t = t->next_sym;
293: while (t != nil) {
294: if (t->name == n) {
295: putc(' ', f);
296: printwhich(f, t);
297: }
298: t = t->next_sym;
299: }
300: putc('\n', f);
301: }
302:
303: private printouter(f, s)
304: File f;
305: Symbol s;
306: {
307: Symbol outer;
308:
309: if (s != nil) {
310: outer = container(s);
311: if (outer != nil and outer != program) {
312: printouter(f, outer);
313: }
314: fprintf(f, "%s.", symname(s));
315: }
316: }
317:
318: public printdecl(s)
319: Symbol s;
320: {
321: checkref(s);
322: (*language_op(s->language, L_PRINTDECL))(s);
323: }
324:
325: /*
326: * Straight dump of symbol information.
327: */
328:
329: public psym(s)
330: Symbol s;
331: {
332: printf("name\t%s\n", symname(s));
333: printf("lang\t%s\n", language_name(s->language));
334: printf("level\t%d\n", s->level);
335: printf("class\t%s\n", classname(s));
336: printf("type\t0x%x", s->type);
337: if (s->type != nil and s->type->name != nil) {
338: printf(" (%s)", symname(s->type));
339: }
340: printf("\nchain\t0x%x", s->chain);
341: if (s->chain != nil and s->chain->name != nil) {
342: printf(" (%s)", symname(s->chain));
343: }
344: printf("\nblock\t0x%x", s->block);
345: if (s->block->name != nil) {
346: printf(" (");
347: printname(stdout, s->block);
348: putchar(')');
349: }
350: putchar('\n');
351: switch (s->class) {
352: case VAR:
353: case REF:
354: if (s->level >= 3) {
355: printf("address\t0x%x\n", s->symvalue.offset);
356: } else {
357: printf("offset\t%d\n", s->symvalue.offset);
358: }
359: printf("size\t%d\n", size(s));
360: break;
361:
362: case RECORD:
363: case VARNT:
364: printf("size\t%d\n", s->symvalue.offset);
365: break;
366:
367: case FIELD:
368: printf("offset\t%d\n", s->symvalue.field.offset);
369: printf("size\t%d\n", s->symvalue.field.length);
370: break;
371:
372: case PROG:
373: case PROC:
374: case FUNC:
375: printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
376: if (isinline(s)) {
377: printf("inline procedure\n");
378: }
379: if (nosource(s)) {
380: printf("does not have source information\n");
381: } else {
382: printf("has source information\n");
383: }
384: break;
385:
386: case RANGE:
387:
388: prangetype(s->symvalue.rangev.lowertype);
389: printf("lower\t%d\n", s->symvalue.rangev.lower);
390: prangetype(s->symvalue.rangev.uppertype);
391: printf("upper\t%d\n", s->symvalue.rangev.upper);
392: break;
393:
394: default:
395: /* do nothing */
396: break;
397: }
398: }
399:
400: private prangetype(r)
401: Rangetype r;
402: {
403: switch (r) {
404: case R_CONST:
405: printf("CONST");
406: break;
407:
408: case R_ARG:
409: printf("ARG");
410: break;
411:
412: case R_TEMP:
413: printf("TEMP");
414: break;
415:
416: case R_ADJUST:
417: printf("ADJUST");
418: break;
419: }
420: }
421:
422: /*
423: * Print out the value on top of the stack according to the given type.
424: */
425:
426: public printval(t)
427: Symbol t;
428: {
429: Symbol s;
430:
431: checkref(t);
432: switch (t->class) {
433: case PROC:
434: case FUNC:
435: s = pop(Symbol);
436: printf("%s", symname(s));
437: break;
438:
439: default:
440: if (t->language == nil) {
441: error("unknown language");
442: } else {
443: (*language_op(t->language, L_PRINTVAL))(t);
444: }
445: break;
446: }
447: }
448:
449: /*
450: * Print out the value of a record, field by field.
451: */
452:
453: public printrecord(s)
454: Symbol s;
455: {
456: if (s->chain == nil) {
457: error("record has no fields");
458: }
459: printf("(");
460: sp -= size(s);
461: printfield(s->chain);
462: printf(")");
463: }
464:
465: /*
466: * Print out a field, first printing out other fields.
467: * This is done because the fields are chained together backwards.
468: */
469:
470: private printfield(s)
471: Symbol s;
472: {
473: Stack *savesp;
474:
475: if (s->chain != nil) {
476: printfield(s->chain);
477: printf(", ");
478: }
479: printf("%s = ", symname(s));
480: savesp = sp;
481: sp += ((s->symvalue.field.offset div BITSPERBYTE) + size(s->type));
482: printval(s);
483: sp = savesp;
484: }
485:
486: /*
487: * Print out the contents of an array.
488: * Haven't quite figured out what the best format is.
489: *
490: * This is rather inefficient.
491: *
492: * The "2*elsize" is there since "printval" drops the stack by elsize.
493: */
494:
495: public printarray(a)
496: Symbol a;
497: {
498: Stack *savesp, *newsp;
499: Symbol eltype;
500: long elsize;
501: String sep;
502:
503: savesp = sp;
504: sp -= (size(a));
505: newsp = sp;
506: eltype = rtype(a->type);
507: elsize = size(eltype);
508: printf("(");
509: if (eltype->class == RECORD or eltype->class == ARRAY or
510: eltype->class == VARNT) {
511: sep = "\n";
512: putchar('\n');
513: } else {
514: sep = ", ";
515: }
516: for (sp += elsize; sp <= savesp; sp += 2*elsize) {
517: if (sp - elsize != newsp) {
518: fputs(sep, stdout);
519: }
520: printval(eltype);
521: }
522: sp = newsp;
523: if (streq(sep, "\n")) {
524: putchar('\n');
525: }
526: printf(")");
527: }
528:
529: /*
530: * Print out the value of a real number in Pascal notation.
531: * This is, unfortunately, different than what one gets
532: * from "%g" in printf.
533: */
534:
535: public prtreal(r)
536: double r;
537: {
538: extern char *index();
539: char buf[256];
540:
541: sprintf(buf, "%g", r);
542: if (buf[0] == '.') {
543: printf("0%s", buf);
544: } else if (buf[0] == '-' and buf[1] == '.') {
545: printf("-0%s", &buf[1]);
546: } else {
547: printf("%s", buf);
548: }
549: if (index(buf, '.') == nil) {
550: printf(".0");
551: }
552: }
553:
554: /*
555: * Print out a character using ^? notation for unprintables.
556: */
557:
558: public printchar(c)
559: char c;
560: {
561: if (c == 0) {
562: putchar('\\');
563: putchar('0');
564: } else if (c == '\n') {
565: putchar('\\');
566: putchar('n');
567: } else if (c > 0 and c < ' ') {
568: putchar('^');
569: putchar(c - 1 + 'A');
570: } else {
571: putchar(c);
572: }
573: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.