fix key letter so ^A, ^B, etc. isn't generated.
[unix-history] / usr / src / old / dbx / printsym.c
CommitLineData
6eb0951d
ML
1/* Copyright (c) 1982 Regents of the University of California */
2
ffa66ed0 3static char sccsid[] = "@(#)printsym.c 1.12 %G%";
6eb0951d
ML
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
b38a9c14
ML
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
6eb0951d
ML
34/*
35 * Return a pointer to the string for the name of the class that
36 * the given symbol belongs to.
37 */
38
39private 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",
20614ea9 44 "procparam", "funcparam", "module", "tag", "common", "typeref"
6eb0951d
ML
45};
46
47public String classname(s)
48Symbol 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
57public printentry(s)
58Symbol 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
69public printexit(s)
70Symbol 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
81public printcall(s, t)
82Symbol 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
95public printrtn(s)
96Symbol s;
97{
98 register Symbol t;
99 register int len;
100 Boolean isindirect;
101
102 printf("returning ");
63a90519 103 if (s->class == FUNC && (!istypename(s->type,"void"))) {
6eb0951d
ML
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
123public printparams(f, frame)
124Symbol f;
125Frame 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) {
b38a9c14
ML
149 if (m > MAXARGSPASSED) {
150 m = MAXARGSPASSED;
151 }
6eb0951d
ML
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
172public Boolean should_print(s)
173Symbol s;
174{
175 Boolean b;
176 register Symbol t;
177
178 switch (s->class) {
179 case VAR:
180 case FVAR:
eb18c137
ML
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:
eb18c137
ML
191 case BADUSE:
192 b = false;
193 break;
194
195 default:
196 b = true;
197 break;
198 }
199 }
200 }
6eb0951d
ML
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
214public printv(s, frame)
215Symbol s;
216Frame 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 }
63a90519
AF
227 if(s->type->class == ARRAY && (! istypename(s->type->type,"char")) ) {
228 printf(" ARRAY ");
6eb0951d 229 } else {
63a90519
AF
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 }
6eb0951d
ML
245}
246
247/*
248 * Print out the name of a symbol.
249 */
250
251public printname(f, s)
252File f;
253Symbol 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
268public printwhich(f, s)
269File f;
270Symbol 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
281public printwhereis(f, s)
282File f;
283Symbol 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
303private printouter(f, s)
304File f;
305Symbol 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
318public printdecl(s)
319Symbol s;
320{
321 checkref(s);
322 (*language_op(s->language, L_PRINTDECL))(s);
323}
324
325/*
326 * Straight dump of symbol information.
327 */
328
329public psym(s)
330Symbol 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 }
4dc0ac37 359 printf("size\t%d\n", size(s));
6eb0951d
ML
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
8ee43d3e 372 case PROG:
6eb0951d
ML
373 case PROC:
374 case FUNC:
375 printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
a71dda28 376 if (isinline(s)) {
ffa66ed0 377 printf("inline procedure\n");
a71dda28 378 }
b38a9c14
ML
379 if (nosource(s)) {
380 printf("does not have source information\n");
381 } else {
382 printf("has source information\n");
383 }
6eb0951d
ML
384 break;
385
386 case RANGE:
20614ea9 387
8ee43d3e
ML
388 prangetype(s->symvalue.rangev.lowertype);
389 printf("lower\t%d\n", s->symvalue.rangev.lower);
390 prangetype(s->symvalue.rangev.uppertype);
6eb0951d
ML
391 printf("upper\t%d\n", s->symvalue.rangev.upper);
392 break;
393
394 default:
395 /* do nothing */
396 break;
397 }
398}
399
8ee43d3e
ML
400private prangetype(r)
401Rangetype 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
6eb0951d
ML
422/*
423 * Print out the value on top of the stack according to the given type.
424 */
425
426public printval(t)
427Symbol 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
453public printrecord(s)
454Symbol 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
470private printfield(s)
471Symbol 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
495public printarray(a)
496Symbol a;
497{
498 Stack *savesp, *newsp;
499 Symbol eltype;
500 long elsize;
501 String sep;
502
503 savesp = sp;
20614ea9 504 sp -= (size(a));
6eb0951d
ML
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
535public prtreal(r)
536double 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
558public printchar(c)
559char 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}