a few fixes of printing float data, and now generates
[unix-history] / usr / src / old / dbx / printsym.c
CommitLineData
6eb0951d
ML
1/* Copyright (c) 1982 Regents of the University of California */
2
63a90519 3static char sccsid[] = "@(#)printsym.c 1.7 %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:
181 t = rtype(s->type);
182 b = (Boolean) (
183 not isparam(s) and
184 t != nil and t->class != FILET and t->class != SET
185 );
186 break;
187
188 default:
189 b = false;
190 break;
191 }
192 return b;
193}
194
195/*
196 * Print the name and value of a variable.
197 */
198
199public printv(s, frame)
200Symbol s;
201Frame frame;
202{
203 Address addr;
204 int len;
205
206 if (isambiguous(s) and ismodule(container(s))) {
207 printname(stdout, s);
208 printf(" = ");
209 } else {
210 printf("%s = ", symname(s));
211 }
63a90519
AF
212 if(s->type->class == ARRAY && (! istypename(s->type->type,"char")) ) {
213 printf(" ARRAY ");
6eb0951d 214 } else {
63a90519
AF
215 if (isvarparam(s)) {
216 rpush(address(s, frame), sizeof(Address));
217 addr = pop(Address);
218 len = size(s->type);
219 } else {
220 addr = address(s, frame);
221 len = size(s);
222 }
223 if (canpush(len)) {
224 rpush(addr, len);
225 printval(s->type);
226 } else {
227 printf("*** expression too large ***");
228 }
229 }
6eb0951d
ML
230}
231
232/*
233 * Print out the name of a symbol.
234 */
235
236public printname(f, s)
237File f;
238Symbol s;
239{
240 if (s == nil) {
241 fprintf(f, "(noname)");
242 } else if (isredirected() or isambiguous(s)) {
243 printwhich(f, s);
244 } else {
245 fprintf(f, "%s", symname(s));
246 }
247}
248
249/*
250 * Print the fully specified variable that is described by the given identifer.
251 */
252
253public printwhich(f, s)
254File f;
255Symbol s;
256{
257 printouter(f, container(s));
258 fprintf(f, "%s", symname(s));
259}
260
261/*
262 * Print the fully qualified name of each symbol that has the same name
263 * as the given symbol.
264 */
265
266public printwhereis(f, s)
267File f;
268Symbol s;
269{
270 register Name n;
271 register Symbol t;
272
273 checkref(s);
274 n = s->name;
275 t = lookup(n);
276 printwhich(f, t);
277 t = t->next_sym;
278 while (t != nil) {
279 if (t->name == n) {
280 putc(' ', f);
281 printwhich(f, t);
282 }
283 t = t->next_sym;
284 }
285 putc('\n', f);
286}
287
288private printouter(f, s)
289File f;
290Symbol s;
291{
292 Symbol outer;
293
294 if (s != nil) {
295 outer = container(s);
296 if (outer != nil and outer != program) {
297 printouter(f, outer);
298 }
299 fprintf(f, "%s.", symname(s));
300 }
301}
302
303public printdecl(s)
304Symbol s;
305{
306 checkref(s);
307 (*language_op(s->language, L_PRINTDECL))(s);
308}
309
310/*
311 * Straight dump of symbol information.
312 */
313
314public psym(s)
315Symbol s;
316{
317 printf("name\t%s\n", symname(s));
318 printf("lang\t%s\n", language_name(s->language));
319 printf("level\t%d\n", s->level);
320 printf("class\t%s\n", classname(s));
321 printf("type\t0x%x", s->type);
322 if (s->type != nil and s->type->name != nil) {
323 printf(" (%s)", symname(s->type));
324 }
325 printf("\nchain\t0x%x", s->chain);
326 if (s->chain != nil and s->chain->name != nil) {
327 printf(" (%s)", symname(s->chain));
328 }
329 printf("\nblock\t0x%x", s->block);
330 if (s->block->name != nil) {
331 printf(" (");
332 printname(stdout, s->block);
333 putchar(')');
334 }
335 putchar('\n');
336 switch (s->class) {
337 case VAR:
338 case REF:
339 if (s->level >= 3) {
340 printf("address\t0x%x\n", s->symvalue.offset);
341 } else {
342 printf("offset\t%d\n", s->symvalue.offset);
343 }
4dc0ac37 344 printf("size\t%d\n", size(s));
6eb0951d
ML
345 break;
346
347 case RECORD:
348 case VARNT:
349 printf("size\t%d\n", s->symvalue.offset);
350 break;
351
352 case FIELD:
353 printf("offset\t%d\n", s->symvalue.field.offset);
354 printf("size\t%d\n", s->symvalue.field.length);
355 break;
356
357 case PROC:
358 case FUNC:
359 printf("address\t0x%x\n", s->symvalue.funcv.beginaddr);
b38a9c14
ML
360 if (nosource(s)) {
361 printf("does not have source information\n");
362 } else {
363 printf("has source information\n");
364 }
6eb0951d
ML
365 break;
366
367 case RANGE:
20614ea9
AF
368 switch(s->symvalue.rangev.lowertype) {
369
370 case R_CONST : printf("CONST");
371 break;
372 case R_ARG : printf("ARG");
373 break;
374 case R_TEMP : printf("TEMP");
375 break;
376 case R_ADJUST : printf("ADJUST");
377 break;
378 }
6eb0951d 379 printf("lower\t%d\n", s->symvalue.rangev.lower);
20614ea9
AF
380
381 switch(s->symvalue.rangev.uppertype) {
382
383 case R_CONST : printf("CONST");
384 break;
385 case R_ARG : printf("ARG");
386 break;
387 case R_TEMP : printf("TEMP");
388 break;
389 case R_ADJUST : printf("ADJUST");
390 break;
391 }
392
6eb0951d
ML
393 printf("upper\t%d\n", s->symvalue.rangev.upper);
394 break;
395
396 default:
397 /* do nothing */
398 break;
399 }
400}
401
402/*
403 * Print out the value on top of the stack according to the given type.
404 */
405
406public printval(t)
407Symbol t;
408{
409 Symbol s;
410
411 checkref(t);
412 switch (t->class) {
413 case PROC:
414 case FUNC:
415 s = pop(Symbol);
416 printf("%s", symname(s));
417 break;
418
419 default:
420 if (t->language == nil) {
421 error("unknown language");
422 } else {
423 (*language_op(t->language, L_PRINTVAL))(t);
424 }
425 break;
426 }
427}
428
429/*
430 * Print out the value of a record, field by field.
431 */
432
433public printrecord(s)
434Symbol s;
435{
436 if (s->chain == nil) {
437 error("record has no fields");
438 }
439 printf("(");
440 sp -= size(s);
441 printfield(s->chain);
442 printf(")");
443}
444
445/*
446 * Print out a field, first printing out other fields.
447 * This is done because the fields are chained together backwards.
448 */
449
450private printfield(s)
451Symbol s;
452{
453 Stack *savesp;
454
455 if (s->chain != nil) {
456 printfield(s->chain);
457 printf(", ");
458 }
459 printf("%s = ", symname(s));
460 savesp = sp;
461 sp += ((s->symvalue.field.offset div BITSPERBYTE) + size(s->type));
462 printval(s);
463 sp = savesp;
464}
465
466/*
467 * Print out the contents of an array.
468 * Haven't quite figured out what the best format is.
469 *
470 * This is rather inefficient.
471 *
472 * The "2*elsize" is there since "printval" drops the stack by elsize.
473 */
474
475public printarray(a)
476Symbol a;
477{
478 Stack *savesp, *newsp;
479 Symbol eltype;
480 long elsize;
481 String sep;
482
483 savesp = sp;
20614ea9 484 sp -= (size(a));
6eb0951d
ML
485 newsp = sp;
486 eltype = rtype(a->type);
487 elsize = size(eltype);
488 printf("(");
489 if (eltype->class == RECORD or eltype->class == ARRAY or
490 eltype->class == VARNT) {
491 sep = "\n";
492 putchar('\n');
493 } else {
494 sep = ", ";
495 }
496 for (sp += elsize; sp <= savesp; sp += 2*elsize) {
497 if (sp - elsize != newsp) {
498 fputs(sep, stdout);
499 }
500 printval(eltype);
501 }
502 sp = newsp;
503 if (streq(sep, "\n")) {
504 putchar('\n');
505 }
506 printf(")");
507}
508
509/*
510 * Print out the value of a real number in Pascal notation.
511 * This is, unfortunately, different than what one gets
512 * from "%g" in printf.
513 */
514
515public prtreal(r)
516double r;
517{
518 extern char *index();
519 char buf[256];
520
521 sprintf(buf, "%g", r);
522 if (buf[0] == '.') {
523 printf("0%s", buf);
524 } else if (buf[0] == '-' and buf[1] == '.') {
525 printf("-0%s", &buf[1]);
526 } else {
527 printf("%s", buf);
528 }
529 if (index(buf, '.') == nil) {
530 printf(".0");
531 }
532}
533
534/*
535 * Print out a character using ^? notation for unprintables.
536 */
537
538public printchar(c)
539char c;
540{
541 if (c == 0) {
542 putchar('\\');
543 putchar('0');
544 } else if (c == '\n') {
545 putchar('\\');
546 putchar('n');
547 } else if (c > 0 and c < ' ') {
548 putchar('^');
549 putchar(c - 1 + 'A');
550 } else {
551 putchar(c);
552 }
553}