7b4ac7e1 |
1 | /* Print values for GNU debugger gdb. |
2 | Copyright (C) 1986 Free Software Foundation, Inc. |
3 | |
4 | GDB is distributed in the hope that it will be useful, but WITHOUT ANY |
5 | WARRANTY. No author or distributor accepts responsibility to anyone |
6 | for the consequences of using it or for whether it serves any |
7 | particular purpose or works at all, unless he says so in writing. |
8 | Refer to the GDB General Public License for full details. |
9 | |
10 | Everyone is granted permission to copy, modify and redistribute GDB, |
11 | but only under the conditions described in the GDB General Public |
12 | License. A copy of this license is supposed to have been given to you |
13 | along with GDB so you can know your rights and responsibilities. It |
14 | should be in a file named COPYING. Among other things, the copyright |
15 | notice and this notice must be preserved on all copies. |
16 | |
17 | In other words, go ahead and share GDB, but don't try to stop |
18 | anyone else from sharing it farther. Help stamp out software hoarding! |
19 | */ |
20 | |
21 | #include <stdio.h> |
22 | #include "defs.h" |
23 | #include "initialize.h" |
24 | #include "symtab.h" |
25 | #include "value.h" |
26 | |
27 | /* Maximum number of chars to print for a string pointer value |
28 | or vector contents. */ |
29 | |
30 | static int print_max; |
31 | |
32 | static void type_print_varspec_suffix (); |
33 | static void type_print_varspec_prefix (); |
34 | static void type_print_base (); |
632ea0cc |
35 | static void type_print_method_args (); |
7b4ac7e1 |
36 | |
37 | START_FILE |
38 | |
39 | char **unsigned_type_table; |
40 | char **signed_type_table; |
41 | char **float_type_table; |
42 | \f |
43 | /* Print the value VAL in C-ish syntax on stream STREAM. |
44 | If the object printed is a string pointer, returns |
45 | the number of string bytes printed. */ |
46 | |
47 | value_print (val, stream) |
48 | value val; |
49 | FILE *stream; |
50 | { |
51 | register int i, n, typelen; |
52 | |
53 | /* A "repeated" value really contains several values in a row. |
54 | They are made by the @ operator. |
55 | Print such values as if they were arrays. */ |
56 | |
57 | if (VALUE_REPEATED (val)) |
58 | { |
59 | n = VALUE_REPETITIONS (val); |
60 | typelen = TYPE_LENGTH (VALUE_TYPE (val)); |
61 | fputc ('{', stream); |
62 | /* Print arrays of characters using string syntax. */ |
63 | if (VALUE_TYPE (val) == builtin_type_char |
64 | || VALUE_TYPE (val) == builtin_type_unsigned_char) |
65 | { |
66 | fputc ('"', stream); |
67 | for (i = 0; i < n && i < print_max; i++) |
68 | { |
69 | QUIT; |
70 | printchar (VALUE_CONTENTS (val)[i], stream); |
71 | } |
72 | if (i < n) |
73 | fprintf (stream, "..."); |
74 | fputc ('"', stream); |
75 | } |
76 | else |
77 | { |
78 | for (i = 0; i < n && i < print_max; i++) |
79 | { |
80 | if (i) |
81 | fprintf (stream, ", "); |
82 | val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i, |
83 | VALUE_ADDRESS (val) + typelen * i, stream); |
84 | } |
85 | if (i < n) |
86 | fprintf (stream, "..."); |
87 | } |
88 | fputc ('}', stream); |
89 | } |
90 | else |
91 | { |
632ea0cc |
92 | /* If it is a pointer, indicate what it points to. |
93 | |
94 | C++: if it is a member pointer, we will take care |
95 | of that when we print it. */ |
7b4ac7e1 |
96 | if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR) |
97 | { |
98 | fprintf (stream, "("); |
99 | type_print (VALUE_TYPE (val), "", stream, -1); |
100 | fprintf (stream, ") "); |
101 | } |
102 | return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), |
103 | VALUE_ADDRESS (val), stream); |
104 | } |
105 | } |
106 | \f |
107 | /* Print on STREAM data stored in debugger at address VALADDR |
108 | according to the format of type TYPE. |
109 | ADDRESS is the location in the inferior that the data |
110 | is supposed to have come from. |
111 | |
112 | If the data are a string pointer, returns the number of |
113 | sting characters printed. */ |
114 | |
115 | int |
116 | val_print (type, valaddr, address, stream) |
117 | struct type *type; |
118 | char *valaddr; |
119 | CORE_ADDR address; |
120 | FILE *stream; |
121 | { |
122 | register int i; |
123 | int len; |
124 | struct type *elttype; |
125 | int eltlen; |
126 | int val; |
127 | unsigned char c; |
128 | |
129 | QUIT; |
130 | |
131 | switch (TYPE_CODE (type)) |
132 | { |
133 | case TYPE_CODE_ARRAY: |
134 | if (TYPE_LENGTH (type) >= 0) |
135 | { |
136 | elttype = TYPE_TARGET_TYPE (type); |
137 | eltlen = TYPE_LENGTH (elttype); |
138 | len = TYPE_LENGTH (type) / eltlen; |
139 | fprintf (stream, "{"); |
140 | /* For an array of chars, print with string syntax. */ |
141 | if (elttype == builtin_type_char |
142 | || elttype == builtin_type_unsigned_char) |
143 | { |
144 | fputc ('"', stream); |
145 | for (i = 0; i < len && i < print_max; i++) |
146 | { |
147 | QUIT; |
148 | printchar (valaddr[i], stream); |
149 | } |
150 | if (i < len) |
151 | fprintf (stream, "..."); |
152 | fputc ('"', stream); |
153 | } |
154 | else |
155 | { |
156 | for (i = 0; i < len && i < print_max; i++) |
157 | { |
158 | if (i) fprintf (stream, ", "); |
159 | val_print (elttype, valaddr + i * eltlen, |
160 | 0, stream); |
161 | } |
162 | if (i < len) |
163 | fprintf (stream, "..."); |
164 | } |
165 | fprintf (stream, "}"); |
166 | break; |
167 | } |
168 | /* Array of unspecified length: treat like pointer. */ |
169 | |
170 | case TYPE_CODE_PTR: |
171 | fprintf (stream, "0x%x", * (int *) valaddr); |
172 | /* For a pointer to char or unsigned char, |
173 | also print the string pointed to, unless pointer is null. */ |
174 | if ((TYPE_TARGET_TYPE (type) == builtin_type_char |
175 | || TYPE_TARGET_TYPE (type) == builtin_type_unsigned_char) |
176 | && unpack_long (type, valaddr) != 0) |
177 | { |
178 | fputc (' ', stream); |
179 | fputc ('"', stream); |
180 | for (i = 0; i < print_max; i++) |
181 | { |
182 | QUIT; |
183 | read_memory (unpack_long (type, valaddr) + i, &c, 1); |
184 | if (c == 0) |
185 | break; |
186 | printchar (c, stream); |
187 | } |
188 | fputc ('"', stream); |
189 | if (i == print_max) |
190 | fprintf (stream, "..."); |
191 | fflush (stream); |
192 | /* Return number of characters printed, plus one for the |
193 | terminating null if we have "reached the end". */ |
194 | return i + (i != print_max); |
195 | } |
196 | break; |
197 | |
632ea0cc |
198 | case TYPE_CODE_MPTR: |
199 | { |
200 | struct type *domain = TYPE_DOMAIN_TYPE (type); |
201 | struct type *target = TYPE_TARGET_TYPE (type); |
202 | struct fn_field *f; |
203 | int j, len2; |
204 | char *kind = ""; |
205 | |
206 | val = unpack_long (builtin_type_int, valaddr); |
207 | if (TYPE_CODE (target) == TYPE_CODE_FUNC) |
208 | { |
209 | if (val < 128) |
210 | { |
211 | len = TYPE_NFN_FIELDS (domain); |
212 | for (i = 0; i < len; i++) |
213 | { |
214 | f = TYPE_FN_FIELDLIST1 (domain, i); |
215 | len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); |
216 | |
217 | for (j = 0; j < len2; j++) |
218 | { |
219 | QUIT; |
220 | if (TYPE_FN_FIELD_VOFFSET (f, j) == val) |
221 | { |
222 | kind = " virtual"; |
223 | goto common; |
224 | } |
225 | } |
226 | } |
227 | } |
228 | else |
229 | { |
230 | struct symbol *sym = find_pc_function (val); |
231 | if (sym == 0) |
232 | error ("invalid pointer to member function"); |
233 | len = TYPE_NFN_FIELDS (domain); |
234 | for (i = 0; i < len; i++) |
235 | { |
236 | f = TYPE_FN_FIELDLIST1 (domain, i); |
237 | len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); |
238 | |
239 | for (j = 0; j < len2; j++) |
240 | { |
241 | QUIT; |
242 | if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j))) |
243 | goto common; |
244 | } |
245 | } |
246 | } |
247 | common: |
248 | if (i < len) |
249 | { |
250 | fprintf (stream, "& "); |
251 | type_print_base (domain, stream, 0, 0); |
252 | fprintf (stream, "::%s", kind); |
253 | type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0); |
254 | if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' |
255 | && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$') |
256 | type_print_method_args |
257 | (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", |
258 | TYPE_FN_FIELDLIST_NAME (domain, i), stream); |
259 | else |
260 | type_print_method_args |
261 | (TYPE_FN_FIELD_ARGS (f, j), "", |
262 | TYPE_FN_FIELDLIST_NAME (domain, i), stream); |
263 | break; |
264 | } |
265 | } |
266 | else |
267 | { |
268 | /* VAL is a byte offset into the structure type DOMAIN. |
269 | Find the name of the field for that offset and |
270 | print it. */ |
271 | int extra = 0; |
272 | int bits = 0; |
273 | len = TYPE_NFIELDS (domain); |
274 | val <<= 3; /* @@ Make VAL into bit offset */ |
275 | for (i = 0; i < len; i++) |
276 | { |
277 | int bitpos = TYPE_FIELD_BITPOS (domain, i); |
278 | QUIT; |
279 | if (val == bitpos) |
280 | break; |
281 | if (val < bitpos && i > 0) |
282 | { |
283 | int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target)); |
284 | /* Somehow pointing into a field. */ |
285 | i -= 1; |
286 | extra = (val - TYPE_FIELD_BITPOS (domain, i)); |
287 | if (extra & 0x3) |
288 | bits = 1; |
289 | else |
290 | extra >>= 3; |
291 | break; |
292 | } |
293 | } |
294 | if (i < len) |
295 | { |
296 | fprintf (stream, "& "); |
297 | type_print_base (domain, stream, 0, 0); |
298 | fprintf (stream, "::"); |
299 | fprintf (stream, "%s", TYPE_FIELD_NAME (domain, i)); |
300 | if (extra) |
301 | fprintf (stream, " + %d bytes", extra); |
302 | if (bits) |
303 | fprintf (stream, " (offset in bits)"); |
304 | break; |
305 | } |
306 | } |
307 | fputc ('(', stream); |
308 | type_print (type, "", stream, -1); |
309 | fprintf (stream, ") %d", val >> 3); |
310 | break; |
311 | } |
312 | |
313 | case TYPE_CODE_REF: |
314 | fprintf (stream, "(0x%x &) = ", * (int *) valaddr); |
315 | /* De-reference the reference. */ |
316 | if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF) |
317 | { |
318 | value val = value_at (TYPE_TARGET_TYPE (type), * (int *)valaddr); |
319 | val_print (VALUE_TYPE (val), VALUE_CONTENTS (val), |
320 | VALUE_ADDRESS (val), stream); |
321 | } |
322 | else |
323 | fprintf (stream, "???"); |
324 | break; |
325 | |
7b4ac7e1 |
326 | case TYPE_CODE_STRUCT: |
327 | case TYPE_CODE_UNION: |
328 | fprintf (stream, "{"); |
329 | len = TYPE_NFIELDS (type); |
632ea0cc |
330 | if (TYPE_BASECLASS (type)) |
331 | { |
332 | i = 1; |
333 | fprintf (stream, "<%s> = ", TYPE_NAME (TYPE_BASECLASS (type))); |
334 | val_print (TYPE_FIELD_TYPE (type, 0), |
335 | valaddr + TYPE_FIELD_BITPOS (type, 0) / 8, |
336 | 0, stream); |
337 | |
338 | } |
339 | else i = 0; |
340 | for (; i < len; i++) |
7b4ac7e1 |
341 | { |
342 | if (i) fprintf (stream, ", "); |
343 | fprintf (stream, "%s = ", TYPE_FIELD_NAME (type, i)); |
632ea0cc |
344 | /* check if static field */ |
345 | if (TYPE_FIELD_STATIC (type, i)) |
346 | { |
347 | value v; |
348 | |
349 | v = value_static_field (type, TYPE_FIELD_NAME (type, i), i); |
350 | val_print (TYPE_FIELD_TYPE (type, i), |
351 | VALUE_CONTENTS (v), 0, stream); |
352 | } |
353 | else if (TYPE_FIELD_PACKED (type, i)) |
7b4ac7e1 |
354 | { |
355 | val = unpack_field_as_long (type, valaddr, i); |
356 | val_print (TYPE_FIELD_TYPE (type, i), &val, 0, stream); |
357 | } |
358 | else |
632ea0cc |
359 | { |
360 | val_print (TYPE_FIELD_TYPE (type, i), |
361 | valaddr + TYPE_FIELD_BITPOS (type, i) / 8, |
362 | 0, stream); |
363 | } |
7b4ac7e1 |
364 | } |
365 | fprintf (stream, "}"); |
366 | break; |
367 | |
368 | case TYPE_CODE_ENUM: |
369 | len = TYPE_NFIELDS (type); |
370 | val = unpack_long (builtin_type_int, valaddr); |
371 | for (i = 0; i < len; i++) |
372 | { |
373 | QUIT; |
374 | if (val == TYPE_FIELD_VALUE (type, i)) |
375 | break; |
376 | } |
377 | if (i < len) |
378 | fprintf (stream, "%s", TYPE_FIELD_NAME (type, i)); |
379 | else |
380 | fprintf (stream, "%d", val); |
381 | break; |
382 | |
383 | case TYPE_CODE_FUNC: |
384 | fprintf (stream, "{"); |
385 | type_print (type, "", stream, -1); |
386 | fprintf (stream, "} "); |
387 | fprintf (stream, "0x%x", address); |
388 | break; |
389 | |
390 | case TYPE_CODE_INT: |
391 | fprintf (stream, |
392 | TYPE_UNSIGNED (type) ? "%u" : "%d", |
393 | unpack_long (type, valaddr)); |
394 | if (type == builtin_type_char |
395 | || type == builtin_type_unsigned_char) |
396 | { |
397 | fprintf (stream, " '"); |
398 | printchar (unpack_long (type, valaddr), stream); |
399 | fputc ('\'', stream); |
400 | } |
401 | break; |
402 | |
403 | case TYPE_CODE_FLT: |
404 | #ifdef IEEE_FLOAT |
405 | if (is_nan (unpack_double (type, valaddr))) |
406 | { |
407 | fprintf (stream, "Nan"); |
408 | break; |
409 | } |
410 | #endif |
411 | fprintf (stream, "%g", unpack_double (type, valaddr)); |
412 | break; |
413 | |
414 | case TYPE_CODE_VOID: |
415 | fprintf (stream, "void"); |
416 | break; |
417 | |
418 | default: |
419 | error ("Invalid type code in symbol table."); |
420 | } |
421 | fflush (stream); |
422 | } |
423 | \f |
424 | #ifdef IEEE_FLOAT |
425 | |
426 | union ieee { |
427 | int i[2]; |
428 | double d; |
429 | }; |
430 | |
431 | /* Nonzero if ARG (a double) is a NAN. */ |
432 | |
433 | int |
434 | is_nan (arg) |
435 | union ieee arg; |
436 | { |
437 | int lowhalf, highhalf; |
438 | union { int i; char c; } test; |
439 | |
440 | /* Separate the high and low words of the double. |
441 | Distinguish big and little-endian machines. */ |
442 | test.i = 1; |
443 | if (test.c != 1) |
444 | /* Big-endian machine */ |
445 | lowhalf = arg.i[1], highhalf = arg.i[0]; |
446 | else |
447 | lowhalf = arg.i[0], highhalf = arg.i[1]; |
448 | |
449 | /* Nan: exponent is the maximum possible, and fraction is nonzero. */ |
450 | return (((highhalf>>20) & 0x7ff) == 0x7ff |
451 | && |
452 | ! ((highhalf & 0xfffff == 0) && (lowhalf == 0))); |
453 | } |
454 | #endif |
455 | \f |
456 | /* Print a description of a type TYPE |
457 | in the form of a declaration of a variable named VARSTRING. |
458 | Output goes to STREAM (via stdio). |
459 | If SHOW is positive, we show the contents of the outermost level |
460 | of structure even if there is a type name that could be used instead. |
461 | If SHOW is negative, we never show the details of elements' types. */ |
462 | |
463 | type_print (type, varstring, stream, show) |
464 | struct type *type; |
465 | char *varstring; |
466 | FILE *stream; |
467 | int show; |
468 | { |
469 | type_print_1 (type, varstring, stream, show, 0); |
470 | } |
471 | |
472 | /* LEVEL is the depth to indent lines by. */ |
473 | |
474 | type_print_1 (type, varstring, stream, show, level) |
475 | struct type *type; |
476 | char *varstring; |
477 | FILE *stream; |
478 | int show; |
479 | int level; |
480 | { |
481 | register enum type_code code; |
482 | type_print_base (type, stream, show, level); |
483 | code = TYPE_CODE (type); |
484 | if ((varstring && *varstring) |
485 | || |
486 | /* Need a space if going to print stars or brackets; |
487 | but not if we will print just a type name. */ |
488 | ((show > 0 || TYPE_NAME (type) == 0) |
489 | && |
490 | (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC |
632ea0cc |
491 | || code == TYPE_CODE_ARRAY |
492 | || code == TYPE_CODE_MPTR |
493 | || code == TYPE_CODE_REF))) |
7b4ac7e1 |
494 | fprintf (stream, " "); |
495 | type_print_varspec_prefix (type, stream, show, 0); |
496 | fprintf (stream, "%s", varstring); |
497 | type_print_varspec_suffix (type, stream, show, 0); |
498 | } |
499 | |
632ea0cc |
500 | /* Print the method arguments ARGS to the file STREAM. */ |
501 | static void |
502 | type_print_method_args (args, prefix, varstring, stream) |
503 | struct type **args; |
504 | char *prefix, *varstring; |
505 | FILE *stream; |
506 | { |
507 | int i; |
508 | |
509 | fprintf (stream, " %s%s (", prefix, varstring); |
510 | if (args[1] && args[1]->code != TYPE_CODE_VOID) |
511 | { |
512 | i = 1; /* skip the class variable */ |
513 | while (1) |
514 | { |
515 | type_print (args[i++], "", stream, 0); |
516 | if (args[i]->code != TYPE_CODE_VOID) |
517 | { |
518 | fprintf (stream, ", "); |
519 | } |
520 | else break; |
521 | } |
522 | } |
523 | fprintf (stream, ")"); |
524 | } |
525 | |
7b4ac7e1 |
526 | /* Print any asterisks or open-parentheses needed before the |
527 | variable name (to describe its type). |
528 | |
529 | On outermost call, pass 0 for PASSED_A_PTR. |
530 | On outermost call, SHOW > 0 means should ignore |
531 | any typename for TYPE and show its details. |
532 | SHOW is always zero on recursive calls. */ |
533 | |
534 | static void |
535 | type_print_varspec_prefix (type, stream, show, passed_a_ptr) |
536 | struct type *type; |
537 | FILE *stream; |
538 | int show; |
539 | int passed_a_ptr; |
540 | { |
541 | if (TYPE_NAME (type) && show <= 0) |
542 | return; |
543 | |
544 | QUIT; |
545 | |
546 | switch (TYPE_CODE (type)) |
547 | { |
548 | case TYPE_CODE_PTR: |
549 | type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); |
550 | fputc ('*', stream); |
551 | break; |
552 | |
632ea0cc |
553 | case TYPE_CODE_MPTR: |
554 | type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); |
555 | if (passed_a_ptr) |
556 | fputc ('(', stream); |
557 | type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, 1); |
558 | fprintf (stream, "::*"); |
559 | break; |
560 | |
561 | case TYPE_CODE_REF: |
562 | type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); |
563 | fputc ('&', stream); |
564 | break; |
565 | |
7b4ac7e1 |
566 | case TYPE_CODE_FUNC: |
632ea0cc |
567 | type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, |
568 | passed_a_ptr); |
7b4ac7e1 |
569 | if (passed_a_ptr) |
570 | fputc ('(', stream); |
571 | break; |
632ea0cc |
572 | |
573 | case TYPE_CODE_ARRAY: |
574 | type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, |
575 | passed_a_ptr); |
7b4ac7e1 |
576 | } |
577 | } |
578 | |
579 | /* Print any array sizes, function arguments or close parentheses |
580 | needed after the variable name (to describe its type). |
581 | Args work like type_print_varspec_prefix. */ |
582 | |
583 | static void |
584 | type_print_varspec_suffix (type, stream, show, passed_a_ptr) |
585 | struct type *type; |
586 | FILE *stream; |
587 | int show; |
588 | int passed_a_ptr; |
589 | { |
590 | if (TYPE_NAME (type) && show <= 0) |
591 | return; |
592 | |
593 | QUIT; |
594 | |
595 | switch (TYPE_CODE (type)) |
596 | { |
597 | case TYPE_CODE_ARRAY: |
632ea0cc |
598 | type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, |
599 | passed_a_ptr); |
7b4ac7e1 |
600 | fprintf (stream, "["); |
601 | if (TYPE_LENGTH (type) >= 0) |
602 | fprintf (stream, "%d", |
603 | TYPE_LENGTH (type) / TYPE_LENGTH (TYPE_TARGET_TYPE (type))); |
604 | fprintf (stream, "]"); |
605 | break; |
606 | |
632ea0cc |
607 | case TYPE_CODE_MPTR: |
608 | if (passed_a_ptr) |
609 | fputc (')', stream); |
610 | /* Fall through. */ |
7b4ac7e1 |
611 | case TYPE_CODE_PTR: |
632ea0cc |
612 | case TYPE_CODE_REF: |
7b4ac7e1 |
613 | type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1); |
614 | break; |
615 | |
616 | case TYPE_CODE_FUNC: |
632ea0cc |
617 | type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, |
618 | passed_a_ptr); |
7b4ac7e1 |
619 | if (passed_a_ptr) |
620 | fprintf (stream, ")"); |
621 | fprintf (stream, "()"); |
622 | break; |
623 | } |
624 | } |
625 | |
626 | /* Print the name of the type (or the ultimate pointer target, |
627 | function value or array element), or the description of a |
628 | structure or union. |
629 | |
630 | SHOW nonzero means don't print this type as just its name; |
631 | show its real definition even if it has a name. |
632 | SHOW zero means print just typename or struct tag if there is one |
633 | SHOW negative means abbreviate structure elements. |
634 | SHOW is decremented for printing of structure elements. |
635 | |
636 | LEVEL is the depth to indent by. |
637 | We increase it for some recursive calls. */ |
638 | |
639 | static void |
640 | type_print_base (type, stream, show, level) |
641 | struct type *type; |
642 | FILE *stream; |
643 | int show; |
644 | int level; |
645 | { |
646 | char *name; |
647 | register int i; |
648 | register int len; |
649 | register int lastval; |
650 | |
651 | QUIT; |
652 | |
653 | if (TYPE_NAME (type) && show <= 0) |
654 | { |
655 | fprintf (stream, TYPE_NAME (type)); |
656 | return; |
657 | } |
658 | |
659 | switch (TYPE_CODE (type)) |
660 | { |
661 | case TYPE_CODE_ARRAY: |
662 | case TYPE_CODE_PTR: |
632ea0cc |
663 | case TYPE_CODE_MPTR: |
664 | case TYPE_CODE_REF: |
7b4ac7e1 |
665 | case TYPE_CODE_FUNC: |
666 | type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); |
667 | break; |
668 | |
669 | case TYPE_CODE_STRUCT: |
670 | fprintf (stream, "struct "); |
671 | goto struct_union; |
672 | |
673 | case TYPE_CODE_UNION: |
674 | fprintf (stream, "union "); |
675 | struct_union: |
676 | if (TYPE_NAME (type) && (name = TYPE_NAME (type))) |
677 | { |
678 | while (*name != ' ') name++; |
679 | fprintf (stream, "%s ", name + 1); |
680 | } |
681 | if (show < 0) |
682 | fprintf (stream, "{...}"); |
683 | else |
684 | { |
632ea0cc |
685 | struct type *basetype, *dtype; |
686 | |
687 | dtype = type; |
688 | basetype = TYPE_BASECLASS (type); |
689 | while (basetype) |
690 | { |
691 | if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype))) |
692 | { |
693 | while (*name != ' ') name++; |
694 | fprintf (stream, ": %s %s ", |
695 | TYPE_VIA_PUBLIC (dtype) ? "public" : "private", |
696 | name + 1); |
697 | } |
698 | dtype = basetype; |
699 | basetype = TYPE_BASECLASS (basetype); |
700 | } |
7b4ac7e1 |
701 | fprintf (stream, "{"); |
702 | len = TYPE_NFIELDS (type); |
632ea0cc |
703 | if (len) fprintf (stream, "\n"); |
704 | else fprintf (stream, "<no data fields>\n"); |
705 | |
706 | /* If there is a base class for this type, |
707 | do not print the field that it occupies. */ |
708 | for (i = !! TYPE_BASECLASS (type); i < len; i++) |
7b4ac7e1 |
709 | { |
710 | QUIT; |
632ea0cc |
711 | /* Don't print out virtual function table. */ |
712 | if (! strncmp (TYPE_FIELD_NAME (type, i), |
713 | "_vptr$", 6)) |
714 | continue; |
7b4ac7e1 |
715 | |
632ea0cc |
716 | print_spaces (level + 4, stream); |
717 | if (TYPE_FIELD_STATIC (type, i)) |
7b4ac7e1 |
718 | { |
632ea0cc |
719 | fprintf (stream, "static "); |
7b4ac7e1 |
720 | } |
7b4ac7e1 |
721 | type_print_1 (TYPE_FIELD_TYPE (type, i), |
722 | TYPE_FIELD_NAME (type, i), |
723 | stream, show - 1, level + 4); |
632ea0cc |
724 | if (!TYPE_FIELD_STATIC (type, i) |
725 | && TYPE_FIELD_PACKED (type, i)) |
726 | { |
727 | /* ??? don't know what to put here ??? */; |
728 | } |
729 | fprintf (stream, ";\n"); |
730 | } |
7b4ac7e1 |
731 | |
632ea0cc |
732 | /* C++: print out the methods */ |
733 | len = TYPE_NFN_FIELDS (type); |
734 | if (len) fprintf (stream, "\n"); |
735 | for (i = 0; i < len; i++) |
736 | { |
737 | struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); |
738 | int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i); |
7b4ac7e1 |
739 | |
632ea0cc |
740 | for (j = 0; j < len2; j++) |
741 | { |
742 | QUIT; |
743 | print_spaces (level + 4, stream); |
744 | if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) |
745 | fprintf (stream, "virtual "); |
746 | type_print_base (TYPE_FN_FIELD_TYPE (f, j), stream, 0, level); |
747 | type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0); |
748 | if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' |
749 | && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$') |
750 | type_print_method_args |
751 | (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", |
752 | TYPE_FN_FIELDLIST_NAME (type, i), stream); |
753 | else |
754 | type_print_method_args |
755 | (TYPE_FN_FIELD_ARGS (f, j), "", |
756 | TYPE_FN_FIELDLIST_NAME (type, i), stream); |
757 | |
758 | fprintf (stream, ";\n"); |
759 | } |
760 | if (len2) fprintf (stream, "\n"); |
7b4ac7e1 |
761 | } |
632ea0cc |
762 | |
7b4ac7e1 |
763 | print_spaces (level, stream); |
764 | fputc ('}', stream); |
765 | } |
766 | break; |
767 | |
768 | case TYPE_CODE_ENUM: |
769 | fprintf (stream, "enum "); |
770 | if (TYPE_NAME (type)) |
771 | { |
772 | name = TYPE_NAME (type); |
773 | while (*name != ' ') name++; |
774 | fprintf (stream, "%s ", name + 1); |
775 | } |
776 | if (show < 0) |
777 | fprintf (stream, "{...}"); |
778 | else |
779 | { |
780 | fprintf (stream, "{"); |
781 | len = TYPE_NFIELDS (type); |
782 | lastval = 0; |
783 | for (i = 0; i < len; i++) |
784 | { |
785 | QUIT; |
786 | if (i) fprintf (stream, ", "); |
787 | fprintf (stream, "%s", TYPE_FIELD_NAME (type, i)); |
788 | if (lastval != TYPE_FIELD_VALUE (type, i)) |
789 | { |
790 | fprintf (stream, " : %d", TYPE_FIELD_VALUE (type, i)); |
791 | lastval = TYPE_FIELD_VALUE (type, i); |
792 | } |
793 | lastval++; |
794 | } |
795 | fprintf (stream, "}"); |
796 | } |
797 | break; |
798 | |
799 | case TYPE_CODE_INT: |
800 | if (TYPE_UNSIGNED (type)) |
801 | name = unsigned_type_table[TYPE_LENGTH (type)]; |
802 | else |
803 | name = signed_type_table[TYPE_LENGTH (type)]; |
804 | fprintf (stream, "%s", name); |
805 | break; |
806 | |
807 | case TYPE_CODE_FLT: |
808 | name = float_type_table[TYPE_LENGTH (type)]; |
809 | fprintf (stream, "%s", name); |
810 | break; |
811 | |
812 | case TYPE_CODE_VOID: |
813 | fprintf (stream, "void"); |
814 | break; |
815 | |
816 | case 0: |
817 | fprintf (stream, "struct unknown"); |
818 | break; |
819 | |
820 | default: |
821 | error ("Invalid type code in symbol table."); |
822 | } |
823 | } |
824 | \f |
825 | static void |
826 | set_maximum_command (arg) |
827 | char *arg; |
828 | { |
829 | if (!arg) error_no_arg ("value for maximum elements to print"); |
830 | print_max = atoi (arg); |
831 | } |
832 | |
833 | static |
834 | initialize () |
835 | { |
836 | add_com ("set-maximum", class_vars, set_maximum_command, |
837 | "Set NUMBER as limit on string chars or array elements to print."); |
838 | |
839 | print_max = 200; |
840 | |
841 | unsigned_type_table |
842 | = (char **) xmalloc ((1 + sizeof (unsigned long)) * sizeof (char *)); |
843 | bzero (unsigned_type_table, (1 + sizeof (unsigned long))); |
844 | unsigned_type_table[sizeof (unsigned char)] = "unsigned char"; |
845 | unsigned_type_table[sizeof (unsigned short)] = "unsigned short"; |
846 | unsigned_type_table[sizeof (unsigned long)] = "unsigned long"; |
847 | unsigned_type_table[sizeof (unsigned int)] = "unsigned int"; |
848 | |
849 | signed_type_table |
850 | = (char **) xmalloc ((1 + sizeof (long)) * sizeof (char *)); |
851 | bzero (signed_type_table, (1 + sizeof (long))); |
852 | signed_type_table[sizeof (char)] = "char"; |
853 | signed_type_table[sizeof (short)] = "short"; |
854 | signed_type_table[sizeof (long)] = "long"; |
855 | signed_type_table[sizeof (int)] = "int"; |
856 | |
857 | float_type_table |
858 | = (char **) xmalloc ((1 + sizeof (double)) * sizeof (char *)); |
859 | bzero (float_type_table, (1 + sizeof (double))); |
860 | float_type_table[sizeof (float)] = "float"; |
861 | float_type_table[sizeof (double)] = "double"; |
862 | } |
863 | |
864 | END_FILE |