made minimum granularity of vertical movement a parameter read from DESC file
[unix-history] / usr / src / old / dbx / printsym.c
CommitLineData
6eb0951d
ML
1/* Copyright (c) 1982 Regents of the University of California */
2
e1f4dbca 3static char sccsid[] = "@(#)printsym.c 1.13 (Berkeley) %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",
2fd0f574 44 "procparam", "funcparam", "module", "tag", "common", "extref", "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.
2fd0f574
SL
121 *
122 * If the procedure or function is internal, the argument count is
123 * not valid so we ignore it.
6eb0951d
ML
124 */
125
126public printparams(f, frame)
127Symbol f;
128Frame frame;
129{
130 Symbol param;
131 int n, m, s;
132
133 n = nargspassed(frame);
2fd0f574
SL
134 if (isinternal(f)) {
135 n = 0;
136 }
6eb0951d
ML
137 param = f->chain;
138 if (param != nil or n > 0) {
139 printf("(");
140 m = n;
141 if (param != nil) {
142 for (;;) {
143 s = size(param) div sizeof(Word);
144 if (s == 0) {
145 s = 1;
146 }
147 m -= s;
148 printv(param, frame);
149 param = param->chain;
150 if (param == nil) break;
151 printf(", ");
152 }
153 }
154 if (m > 0) {
b38a9c14
ML
155 if (m > MAXARGSPASSED) {
156 m = MAXARGSPASSED;
157 }
6eb0951d
ML
158 if (f->chain != nil) {
159 printf(", ");
160 }
161 for (;;) {
162 --m;
163 printf("0x%x", argn(n - m, frame));
164 if (m <= 0) break;
165 printf(", ");
166 }
167 }
168 printf(")");
169 }
170}
171
172/*
173 * Test if a symbol should be printed. We don't print files,
174 * for example, simply because there's no good way to do it.
175 * The symbol must be within the given function.
176 */
177
178public Boolean should_print(s)
179Symbol s;
180{
181 Boolean b;
182 register Symbol t;
183
184 switch (s->class) {
185 case VAR:
186 case FVAR:
eb18c137
ML
187 if (isparam(s)) {
188 b = false;
189 } else {
190 t = rtype(s->type);
191 if (t == nil) {
192 b = false;
193 } else {
194 switch (t->class) {
195 case FILET:
196 case SET:
eb18c137
ML
197 case BADUSE:
198 b = false;
199 break;
200
201 default:
202 b = true;
203 break;
204 }
205 }
206 }
6eb0951d
ML
207 break;
208
209 default:
210 b = false;
211 break;
212 }
213 return b;
214}
215
216/*
217 * Print the name and value of a variable.
218 */
219
220public printv(s, frame)
221Symbol s;
222Frame frame;
223{
224 Address addr;
225 int len;
2fd0f574 226 Symbol t;
6eb0951d
ML
227
228 if (isambiguous(s) and ismodule(container(s))) {
229 printname(stdout, s);
230 printf(" = ");
231 } else {
232 printf("%s = ", symname(s));
233 }
2fd0f574
SL
234/*
235 * Not today.
236 t = rtype(s->type);
237 if (t->class == ARRAY and not istypename(t->type, "char")) {
238 printf("ARRAY");
6eb0951d 239 } else {
2fd0f574 240 */
63a90519
AF
241 if (isvarparam(s)) {
242 rpush(address(s, frame), sizeof(Address));
243 addr = pop(Address);
244 len = size(s->type);
245 } else {
246 addr = address(s, frame);
247 len = size(s);
248 }
249 if (canpush(len)) {
250 rpush(addr, len);
251 printval(s->type);
252 } else {
253 printf("*** expression too large ***");
254 }
2fd0f574
SL
255/*
256 * Matches brace commented out above.
63a90519 257 }
2fd0f574 258 */
6eb0951d
ML
259}
260
261/*
262 * Print out the name of a symbol.
263 */
264
265public printname(f, s)
266File f;
267Symbol s;
268{
269 if (s == nil) {
270 fprintf(f, "(noname)");
2fd0f574
SL
271 } else if (s == program) {
272 fprintf(f, ".");
6eb0951d
ML
273 } else if (isredirected() or isambiguous(s)) {
274 printwhich(f, s);
275 } else {
276 fprintf(f, "%s", symname(s));
277 }
278}
279
280/*
281 * Print the fully specified variable that is described by the given identifer.
282 */
283
284public printwhich(f, s)
285File f;
286Symbol s;
287{
288 printouter(f, container(s));
289 fprintf(f, "%s", symname(s));
290}
291
292/*
293 * Print the fully qualified name of each symbol that has the same name
294 * as the given symbol.
295 */
296
297public printwhereis(f, s)
298File f;
299Symbol s;
300{
301 register Name n;
302 register Symbol t;
303
304 checkref(s);
305 n = s->name;
306 t = lookup(n);
307 printwhich(f, t);
308 t = t->next_sym;
309 while (t != nil) {
310 if (t->name == n) {
311 putc(' ', f);
312 printwhich(f, t);
313 }
314 t = t->next_sym;
315 }
316 putc('\n', f);
317}
318
319private printouter(f, s)
320File f;
321Symbol s;
322{
323 Symbol outer;
324
325 if (s != nil) {
326 outer = container(s);
327 if (outer != nil and outer != program) {
328 printouter(f, outer);
329 }
330 fprintf(f, "%s.", symname(s));
331 }
332}
333
334public printdecl(s)
335Symbol s;
336{
337 checkref(s);
338 (*language_op(s->language, L_PRINTDECL))(s);
339}
340
341/*
342 * Straight dump of symbol information.
343 */
344
345public psym(s)
346Symbol s;
347{
348 printf("name\t%s\n", symname(s));
349 printf("lang\t%s\n", language_name(s->language));
350 printf("level\t%d\n", s->level);
351 printf("class\t%s\n", classname(s));
352 printf("type\t0x%x", s->type);
353 if (s->type != nil and s->type->name != nil) {
354 printf(" (%s)", symname(s->type));
355 }
356 printf("\nchain\t0x%x", s->chain);
357 if (s->chain != nil and s->chain->name != nil) {
358 printf(" (%s)", symname(s->chain));
359 }
360 printf("\nblock\t0x%x", s->block);
361 if (s->block->name != nil) {
362 printf(" (");
363 printname(stdout, s->block);
364 putchar(')');
365 }
366 putchar('\n');
367 switch (s->class) {
368 case VAR:
369 case REF:
370 if (s->level >= 3) {
371 printf("address\t0x%x\n", s->symvalue.offset);
372 } else {
373 printf("offset\t%d\n", s->symvalue.offset);
374 }
4dc0ac37 375 printf("size\t%d\n", size(s));
6eb0951d
ML
376 break;
377
378 case RECORD:
379 case VARNT:
380 printf("size\t%d\n", s->symvalue.offset);
381 break;
382
383 case FIELD:
384 printf("offset\t%d\n", s->symvalue.field.offset);
385 printf("size\t%d\n", s->symvalue.field.length);
386 break;
387
8ee43d3e 388 case PROG:
6eb0951d
ML
389 case PROC:
390 case FUNC:
391 printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
a71dda28 392 if (isinline(s)) {
ffa66ed0 393 printf("inline procedure\n");
a71dda28 394 }
b38a9c14
ML
395 if (nosource(s)) {
396 printf("does not have source information\n");
397 } else {
398 printf("has source information\n");
399 }
6eb0951d
ML
400 break;
401
402 case RANGE:
8ee43d3e
ML
403 prangetype(s->symvalue.rangev.lowertype);
404 printf("lower\t%d\n", s->symvalue.rangev.lower);
405 prangetype(s->symvalue.rangev.uppertype);
6eb0951d
ML
406 printf("upper\t%d\n", s->symvalue.rangev.upper);
407 break;
408
409 default:
410 /* do nothing */
411 break;
412 }
413}
414
8ee43d3e
ML
415private prangetype(r)
416Rangetype r;
417{
418 switch (r) {
419 case R_CONST:
420 printf("CONST");
421 break;
422
423 case R_ARG:
424 printf("ARG");
425 break;
426
427 case R_TEMP:
428 printf("TEMP");
429 break;
430
431 case R_ADJUST:
432 printf("ADJUST");
433 break;
434 }
435}
436
6eb0951d
ML
437/*
438 * Print out the value on top of the stack according to the given type.
439 */
440
441public printval(t)
442Symbol t;
443{
444 Symbol s;
445
446 checkref(t);
2fd0f574
SL
447 if (t->class == TYPEREF) {
448 resolveRef(t);
449 }
6eb0951d
ML
450 switch (t->class) {
451 case PROC:
452 case FUNC:
453 s = pop(Symbol);
454 printf("%s", symname(s));
455 break;
456
457 default:
458 if (t->language == nil) {
459 error("unknown language");
2fd0f574
SL
460 } else if (t->language == primlang) {
461 (*language_op(findlanguage(".c"), L_PRINTVAL))(t);
6eb0951d
ML
462 } else {
463 (*language_op(t->language, L_PRINTVAL))(t);
464 }
465 break;
466 }
467}
468
469/*
470 * Print out the value of a record, field by field.
471 */
472
473public printrecord(s)
474Symbol s;
475{
2fd0f574
SL
476 Symbol f;
477
6eb0951d
ML
478 if (s->chain == nil) {
479 error("record has no fields");
480 }
481 printf("(");
482 sp -= size(s);
2fd0f574
SL
483 f = s->chain;
484 if (f != nil) {
485 for (;;) {
486 printfield(f);
487 f = f->chain;
488 if (f == nil) break;
489 printf(", ");
490 }
491 }
6eb0951d
ML
492 printf(")");
493}
494
495/*
2fd0f574 496 * Print out a field.
6eb0951d
ML
497 */
498
2fd0f574
SL
499private printfield(f)
500Symbol f;
6eb0951d
ML
501{
502 Stack *savesp;
2fd0f574 503 register int off, len;
6eb0951d 504
2fd0f574 505 printf("%s = ", symname(f));
6eb0951d 506 savesp = sp;
2fd0f574
SL
507 off = f->symvalue.field.offset;
508 len = f->symvalue.field.length;
509 sp += ((off + len + BITSPERBYTE - 1) div BITSPERBYTE);
510 printval(f);
6eb0951d
ML
511 sp = savesp;
512}
513
514/*
515 * Print out the contents of an array.
516 * Haven't quite figured out what the best format is.
517 *
518 * This is rather inefficient.
519 *
520 * The "2*elsize" is there since "printval" drops the stack by elsize.
521 */
522
523public printarray(a)
524Symbol a;
525{
526 Stack *savesp, *newsp;
527 Symbol eltype;
528 long elsize;
529 String sep;
530
531 savesp = sp;
20614ea9 532 sp -= (size(a));
6eb0951d
ML
533 newsp = sp;
534 eltype = rtype(a->type);
535 elsize = size(eltype);
536 printf("(");
537 if (eltype->class == RECORD or eltype->class == ARRAY or
538 eltype->class == VARNT) {
539 sep = "\n";
540 putchar('\n');
541 } else {
542 sep = ", ";
543 }
544 for (sp += elsize; sp <= savesp; sp += 2*elsize) {
545 if (sp - elsize != newsp) {
546 fputs(sep, stdout);
547 }
548 printval(eltype);
549 }
550 sp = newsp;
551 if (streq(sep, "\n")) {
552 putchar('\n');
553 }
554 printf(")");
555}
556
557/*
558 * Print out the value of a real number in Pascal notation.
559 * This is, unfortunately, different than what one gets
560 * from "%g" in printf.
561 */
562
563public prtreal(r)
564double r;
565{
566 extern char *index();
567 char buf[256];
568
569 sprintf(buf, "%g", r);
570 if (buf[0] == '.') {
571 printf("0%s", buf);
572 } else if (buf[0] == '-' and buf[1] == '.') {
573 printf("-0%s", &buf[1]);
574 } else {
575 printf("%s", buf);
576 }
577 if (index(buf, '.') == nil) {
578 printf(".0");
579 }
580}
581
582/*
583 * Print out a character using ^? notation for unprintables.
584 */
585
586public printchar(c)
587char c;
588{
589 if (c == 0) {
590 putchar('\\');
591 putchar('0');
592 } else if (c == '\n') {
593 putchar('\\');
594 putchar('n');
595 } else if (c > 0 and c < ' ') {
596 putchar('^');
597 putchar(c - 1 + 'A');
2fd0f574 598 } else if (c >= ' ' && c <= '~') {
6eb0951d 599 putchar(c);
2fd0f574
SL
600 } else {
601 printf("\\0%o",c);
6eb0951d
ML
602 }
603}