Commit | Line | Data |
---|---|---|
373a8247 | 1 | /* Support for printing Pascal types for GDB, the GNU debugger. |
3666a048 | 2 | Copyright (C) 2000-2021 Free Software Foundation, Inc. |
373a8247 PM |
3 | |
4 | This file is part of GDB. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
a9762ec7 | 8 | the Free Software Foundation; either version 3 of the License, or |
373a8247 PM |
9 | (at your option) any later version. |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
a9762ec7 | 17 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
373a8247 PM |
18 | |
19 | /* This file is derived from p-typeprint.c */ | |
20 | ||
21 | #include "defs.h" | |
04ea0df1 | 22 | #include "gdb_obstack.h" |
373a8247 PM |
23 | #include "bfd.h" /* Binary File Description */ |
24 | #include "symtab.h" | |
25 | #include "gdbtypes.h" | |
26 | #include "expression.h" | |
27 | #include "value.h" | |
28 | #include "gdbcore.h" | |
29 | #include "target.h" | |
373a8247 | 30 | #include "language.h" |
373a8247 PM |
31 | #include "p-lang.h" |
32 | #include "typeprint.h" | |
50f182aa | 33 | #include "gdb-demangle.h" |
373a8247 | 34 | #include <ctype.h> |
7f6aba03 | 35 | #include "cli/cli-style.h" |
373a8247 | 36 | |
46157d77 | 37 | /* See language.h. */ |
373a8247 PM |
38 | |
39 | void | |
46157d77 AB |
40 | pascal_language::print_type (struct type *type, const char *varstring, |
41 | struct ui_file *stream, int show, int level, | |
42 | const struct type_print_options *flags) const | |
373a8247 | 43 | { |
52f0bd74 | 44 | enum type_code code; |
373a8247 PM |
45 | int demangled_args; |
46 | ||
78134374 | 47 | code = type->code (); |
373a8247 PM |
48 | |
49 | if (show > 0) | |
f168693b | 50 | type = check_typedef (type); |
373a8247 | 51 | |
3e9313ab PM |
52 | if ((code == TYPE_CODE_FUNC |
53 | || code == TYPE_CODE_METHOD)) | |
373a8247 | 54 | { |
46157d77 | 55 | type_print_varspec_prefix (type, stream, show, 0, flags); |
373a8247 PM |
56 | } |
57 | /* first the name */ | |
58 | fputs_filtered (varstring, stream); | |
59 | ||
3e9313ab PM |
60 | if ((varstring != NULL && *varstring != '\0') |
61 | && !(code == TYPE_CODE_FUNC | |
62 | || code == TYPE_CODE_METHOD)) | |
373a8247 PM |
63 | { |
64 | fputs_filtered (" : ", stream); | |
65 | } | |
66 | ||
3e9313ab PM |
67 | if (!(code == TYPE_CODE_FUNC |
68 | || code == TYPE_CODE_METHOD)) | |
373a8247 | 69 | { |
46157d77 | 70 | type_print_varspec_prefix (type, stream, show, 0, flags); |
373a8247 PM |
71 | } |
72 | ||
46157d77 | 73 | type_print_base (type, stream, show, level, flags); |
373a8247 | 74 | /* For demangled function names, we have the arglist as part of the name, |
0df8b418 | 75 | so don't print an additional pair of ()'s. */ |
373a8247 PM |
76 | |
77 | demangled_args = varstring ? strchr (varstring, '(') != NULL : 0; | |
46157d77 | 78 | type_print_varspec_suffix (type, stream, show, 0, demangled_args, |
79d43c61 | 79 | flags); |
373a8247 PM |
80 | |
81 | } | |
82 | ||
46157d77 | 83 | /* See language.h. */ |
5c6ce71d TT |
84 | |
85 | void | |
46157d77 AB |
86 | pascal_language::print_typedef (struct type *type, struct symbol *new_symbol, |
87 | struct ui_file *stream) const | |
5c6ce71d | 88 | { |
f168693b | 89 | type = check_typedef (type); |
5c6ce71d | 90 | fprintf_filtered (stream, "type "); |
987012b8 | 91 | fprintf_filtered (stream, "%s = ", new_symbol->print_name ()); |
5c6ce71d | 92 | type_print (type, "", stream, 0); |
e1709896 | 93 | fprintf_filtered (stream, ";"); |
5c6ce71d TT |
94 | } |
95 | ||
46157d77 | 96 | /* See p-lang.h. */ |
373a8247 | 97 | |
46157d77 AB |
98 | void |
99 | pascal_language::type_print_derivation_info (struct ui_file *stream, | |
100 | struct type *type) const | |
373a8247 | 101 | { |
0d5cff50 | 102 | const char *name; |
373a8247 PM |
103 | int i; |
104 | ||
105 | for (i = 0; i < TYPE_N_BASECLASSES (type); i++) | |
106 | { | |
107 | fputs_filtered (i == 0 ? ": " : ", ", stream); | |
108 | fprintf_filtered (stream, "%s%s ", | |
109 | BASETYPE_VIA_PUBLIC (type, i) ? "public" : "private", | |
110 | BASETYPE_VIA_VIRTUAL (type, i) ? " virtual" : ""); | |
7d93a1e0 | 111 | name = TYPE_BASECLASS (type, i)->name (); |
373a8247 PM |
112 | fprintf_filtered (stream, "%s", name ? name : "(null)"); |
113 | } | |
114 | if (i > 0) | |
115 | { | |
116 | fputs_filtered (" ", stream); | |
117 | } | |
118 | } | |
119 | ||
46157d77 | 120 | /* See p-lang.h. */ |
373a8247 PM |
121 | |
122 | void | |
46157d77 AB |
123 | pascal_language::type_print_method_args (const char *physname, |
124 | const char *methodname, | |
125 | struct ui_file *stream) const | |
373a8247 | 126 | { |
61012eef GB |
127 | int is_constructor = (startswith (physname, "__ct__")); |
128 | int is_destructor = (startswith (physname, "__dt__")); | |
373a8247 | 129 | |
c96d965c | 130 | if (is_constructor || is_destructor) |
373a8247 | 131 | { |
c96d965c MS |
132 | physname += 6; |
133 | } | |
00b8699c | 134 | |
c96d965c | 135 | fputs_filtered (methodname, stream); |
00b8699c | 136 | |
c96d965c MS |
137 | if (physname && (*physname != 0)) |
138 | { | |
373a8247 | 139 | fputs_filtered (" (", stream); |
0df8b418 | 140 | /* We must demangle this. */ |
8ce17b9a | 141 | while (isdigit (physname[0])) |
373a8247 | 142 | { |
3a9d7214 | 143 | int len = 0; |
1d06ead6 | 144 | int i, j; |
3a9d7214 PM |
145 | char *argname; |
146 | ||
8ce17b9a | 147 | while (isdigit (physname[len])) |
373a8247 PM |
148 | { |
149 | len++; | |
150 | } | |
151 | i = strtol (physname, &argname, 0); | |
152 | physname += len; | |
1d06ead6 TT |
153 | |
154 | for (j = 0; j < i; ++j) | |
d0e7e15a | 155 | fputc_filtered (physname[j], stream); |
1d06ead6 | 156 | |
373a8247 PM |
157 | physname += i; |
158 | if (physname[0] != 0) | |
159 | { | |
160 | fputs_filtered (", ", stream); | |
161 | } | |
162 | } | |
163 | fputs_filtered (")", stream); | |
164 | } | |
165 | } | |
166 | ||
46157d77 | 167 | /* See p-lang.h. */ |
373a8247 PM |
168 | |
169 | void | |
46157d77 AB |
170 | pascal_language::type_print_varspec_prefix (struct type *type, |
171 | struct ui_file *stream, | |
172 | int show, int passed_a_ptr, | |
173 | const struct type_print_options *flags) const | |
373a8247 | 174 | { |
373a8247 PM |
175 | if (type == 0) |
176 | return; | |
177 | ||
7d93a1e0 | 178 | if (type->name () && show <= 0) |
373a8247 PM |
179 | return; |
180 | ||
181 | QUIT; | |
182 | ||
78134374 | 183 | switch (type->code ()) |
373a8247 PM |
184 | { |
185 | case TYPE_CODE_PTR: | |
186 | fprintf_filtered (stream, "^"); | |
46157d77 | 187 | type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1, |
79d43c61 | 188 | flags); |
0df8b418 MS |
189 | break; /* Pointer should be handled normally |
190 | in pascal. */ | |
373a8247 | 191 | |
373a8247 PM |
192 | case TYPE_CODE_METHOD: |
193 | if (passed_a_ptr) | |
194 | fprintf_filtered (stream, "("); | |
7022349d | 195 | if (TYPE_TARGET_TYPE (type) != NULL |
78134374 | 196 | && TYPE_TARGET_TYPE (type)->code () != TYPE_CODE_VOID) |
373a8247 PM |
197 | { |
198 | fprintf_filtered (stream, "function "); | |
199 | } | |
200 | else | |
201 | { | |
202 | fprintf_filtered (stream, "procedure "); | |
203 | } | |
204 | ||
205 | if (passed_a_ptr) | |
206 | { | |
207 | fprintf_filtered (stream, " "); | |
46157d77 | 208 | type_print_base (TYPE_SELF_TYPE (type), |
79d43c61 | 209 | stream, 0, passed_a_ptr, flags); |
373a8247 PM |
210 | fprintf_filtered (stream, "::"); |
211 | } | |
212 | break; | |
213 | ||
214 | case TYPE_CODE_REF: | |
46157d77 AB |
215 | type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1, |
216 | flags); | |
373a8247 PM |
217 | fprintf_filtered (stream, "&"); |
218 | break; | |
219 | ||
220 | case TYPE_CODE_FUNC: | |
221 | if (passed_a_ptr) | |
222 | fprintf_filtered (stream, "("); | |
223 | ||
7022349d | 224 | if (TYPE_TARGET_TYPE (type) != NULL |
78134374 | 225 | && TYPE_TARGET_TYPE (type)->code () != TYPE_CODE_VOID) |
373a8247 PM |
226 | { |
227 | fprintf_filtered (stream, "function "); | |
228 | } | |
229 | else | |
230 | { | |
231 | fprintf_filtered (stream, "procedure "); | |
232 | } | |
233 | ||
234 | break; | |
235 | ||
236 | case TYPE_CODE_ARRAY: | |
237 | if (passed_a_ptr) | |
238 | fprintf_filtered (stream, "("); | |
239 | fprintf_filtered (stream, "array "); | |
d5d6fca5 | 240 | if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0 |
cf88be68 | 241 | && type->bounds ()->high.kind () != PROP_UNDEFINED) |
43bbcdc2 | 242 | fprintf_filtered (stream, "[%s..%s] ", |
cf88be68 SM |
243 | plongest (type->bounds ()->low.const_val ()), |
244 | plongest (type->bounds ()->high.const_val ())); | |
373a8247 PM |
245 | fprintf_filtered (stream, "of "); |
246 | break; | |
247 | ||
248 | case TYPE_CODE_UNDEF: | |
249 | case TYPE_CODE_STRUCT: | |
250 | case TYPE_CODE_UNION: | |
251 | case TYPE_CODE_ENUM: | |
252 | case TYPE_CODE_INT: | |
253 | case TYPE_CODE_FLT: | |
254 | case TYPE_CODE_VOID: | |
255 | case TYPE_CODE_ERROR: | |
256 | case TYPE_CODE_CHAR: | |
257 | case TYPE_CODE_BOOL: | |
258 | case TYPE_CODE_SET: | |
259 | case TYPE_CODE_RANGE: | |
260 | case TYPE_CODE_STRING: | |
373a8247 PM |
261 | case TYPE_CODE_COMPLEX: |
262 | case TYPE_CODE_TYPEDEF: | |
0c9150e4 | 263 | case TYPE_CODE_FIXED_POINT: |
373a8247 | 264 | /* These types need no prefix. They are listed here so that |
dda83cd7 | 265 | gcc -Wall will reveal any types that haven't been handled. */ |
373a8247 PM |
266 | break; |
267 | default: | |
46157d77 | 268 | gdb_assert_not_reached ("unexpected type"); |
373a8247 PM |
269 | break; |
270 | } | |
271 | } | |
272 | ||
46157d77 AB |
273 | /* See p-lang.h. */ |
274 | ||
275 | void | |
276 | pascal_language::print_func_args (struct type *type, struct ui_file *stream, | |
277 | const struct type_print_options *flags) const | |
373a8247 | 278 | { |
1f704f76 | 279 | int i, len = type->num_fields (); |
ad3bbd48 | 280 | |
373a8247 PM |
281 | if (len) |
282 | { | |
283 | fprintf_filtered (stream, "("); | |
284 | } | |
285 | for (i = 0; i < len; i++) | |
286 | { | |
287 | if (i > 0) | |
288 | { | |
289 | fputs_filtered (", ", stream); | |
290 | wrap_here (" "); | |
291 | } | |
0df8b418 | 292 | /* Can we find if it is a var parameter ?? |
46157d77 AB |
293 | if ( TYPE_FIELD(type, i) == ) |
294 | { | |
295 | fprintf_filtered (stream, "var "); | |
296 | } */ | |
297 | print_type (type->field (i).type (), "" /* TYPE_FIELD_NAME | |
298 | seems invalid! */ | |
79d43c61 | 299 | ,stream, -1, 0, flags); |
373a8247 PM |
300 | } |
301 | if (len) | |
302 | { | |
303 | fprintf_filtered (stream, ")"); | |
304 | } | |
305 | } | |
306 | ||
46157d77 | 307 | /* See p-lang.h. */ |
7022349d | 308 | |
46157d77 AB |
309 | void |
310 | pascal_language::type_print_func_varspec_suffix (struct type *type, | |
311 | struct ui_file *stream, | |
312 | int show, int passed_a_ptr, | |
313 | int demangled_args, | |
314 | const struct type_print_options *flags) const | |
7022349d PA |
315 | { |
316 | if (TYPE_TARGET_TYPE (type) == NULL | |
78134374 | 317 | || TYPE_TARGET_TYPE (type)->code () != TYPE_CODE_VOID) |
7022349d PA |
318 | { |
319 | fprintf_filtered (stream, " : "); | |
46157d77 | 320 | type_print_varspec_prefix (TYPE_TARGET_TYPE (type), |
7022349d PA |
321 | stream, 0, 0, flags); |
322 | ||
323 | if (TYPE_TARGET_TYPE (type) == NULL) | |
324 | type_print_unknown_return_type (stream); | |
325 | else | |
46157d77 | 326 | type_print_base (TYPE_TARGET_TYPE (type), stream, show, 0, |
7022349d PA |
327 | flags); |
328 | ||
46157d77 AB |
329 | type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, |
330 | passed_a_ptr, 0, flags); | |
7022349d PA |
331 | } |
332 | } | |
333 | ||
46157d77 | 334 | /* See p-lang.h. */ |
373a8247 | 335 | |
46157d77 AB |
336 | void |
337 | pascal_language::type_print_varspec_suffix (struct type *type, | |
338 | struct ui_file *stream, | |
339 | int show, int passed_a_ptr, | |
340 | int demangled_args, | |
341 | const struct type_print_options *flags) const | |
373a8247 PM |
342 | { |
343 | if (type == 0) | |
344 | return; | |
345 | ||
7d93a1e0 | 346 | if (type->name () && show <= 0) |
373a8247 PM |
347 | return; |
348 | ||
349 | QUIT; | |
350 | ||
78134374 | 351 | switch (type->code ()) |
373a8247 PM |
352 | { |
353 | case TYPE_CODE_ARRAY: | |
354 | if (passed_a_ptr) | |
355 | fprintf_filtered (stream, ")"); | |
356 | break; | |
357 | ||
373a8247 PM |
358 | case TYPE_CODE_METHOD: |
359 | if (passed_a_ptr) | |
360 | fprintf_filtered (stream, ")"); | |
46157d77 AB |
361 | type_print_method_args ("", "", stream); |
362 | type_print_func_varspec_suffix (type, stream, show, | |
7022349d | 363 | passed_a_ptr, 0, flags); |
373a8247 PM |
364 | break; |
365 | ||
366 | case TYPE_CODE_PTR: | |
367 | case TYPE_CODE_REF: | |
46157d77 AB |
368 | type_print_varspec_suffix (TYPE_TARGET_TYPE (type), |
369 | stream, 0, 1, 0, flags); | |
373a8247 PM |
370 | break; |
371 | ||
372 | case TYPE_CODE_FUNC: | |
373 | if (passed_a_ptr) | |
374 | fprintf_filtered (stream, ")"); | |
375 | if (!demangled_args) | |
46157d77 AB |
376 | print_func_args (type, stream, flags); |
377 | type_print_func_varspec_suffix (type, stream, show, | |
7022349d | 378 | passed_a_ptr, 0, flags); |
373a8247 PM |
379 | break; |
380 | ||
381 | case TYPE_CODE_UNDEF: | |
382 | case TYPE_CODE_STRUCT: | |
383 | case TYPE_CODE_UNION: | |
384 | case TYPE_CODE_ENUM: | |
385 | case TYPE_CODE_INT: | |
386 | case TYPE_CODE_FLT: | |
387 | case TYPE_CODE_VOID: | |
388 | case TYPE_CODE_ERROR: | |
389 | case TYPE_CODE_CHAR: | |
390 | case TYPE_CODE_BOOL: | |
391 | case TYPE_CODE_SET: | |
392 | case TYPE_CODE_RANGE: | |
393 | case TYPE_CODE_STRING: | |
373a8247 PM |
394 | case TYPE_CODE_COMPLEX: |
395 | case TYPE_CODE_TYPEDEF: | |
0c9150e4 | 396 | case TYPE_CODE_FIXED_POINT: |
373a8247 | 397 | /* These types do not need a suffix. They are listed so that |
dda83cd7 | 398 | gcc -Wall will report types that may not have been considered. */ |
373a8247 PM |
399 | break; |
400 | default: | |
46157d77 | 401 | gdb_assert_not_reached ("unexpected type"); |
373a8247 PM |
402 | break; |
403 | } | |
404 | } | |
405 | ||
46157d77 | 406 | /* See p-lang.h. */ |
373a8247 PM |
407 | |
408 | void | |
46157d77 AB |
409 | pascal_language::type_print_base (struct type *type, struct ui_file *stream, int show, |
410 | int level, const struct type_print_options *flags) const | |
373a8247 | 411 | { |
52f0bd74 AC |
412 | int i; |
413 | int len; | |
b4aa388a | 414 | LONGEST lastval; |
373a8247 PM |
415 | enum |
416 | { | |
417 | s_none, s_public, s_private, s_protected | |
418 | } | |
419 | section_type; | |
373a8247 | 420 | |
ad3bbd48 | 421 | QUIT; |
373a8247 PM |
422 | wrap_here (" "); |
423 | if (type == NULL) | |
424 | { | |
7f6aba03 | 425 | fputs_styled ("<type unknown>", metadata_style.style (), stream); |
373a8247 PM |
426 | return; |
427 | } | |
428 | ||
429 | /* void pointer */ | |
78134374 SM |
430 | if ((type->code () == TYPE_CODE_PTR) |
431 | && (TYPE_TARGET_TYPE (type)->code () == TYPE_CODE_VOID)) | |
373a8247 | 432 | { |
7d93a1e0 | 433 | fputs_filtered (type->name () ? type->name () : "pointer", |
306d9ac5 | 434 | stream); |
373a8247 PM |
435 | return; |
436 | } | |
437 | /* When SHOW is zero or less, and there is a valid type name, then always | |
438 | just print the type name directly from the type. */ | |
439 | ||
440 | if (show <= 0 | |
7d93a1e0 | 441 | && type->name () != NULL) |
373a8247 | 442 | { |
7d93a1e0 | 443 | fputs_filtered (type->name (), stream); |
373a8247 PM |
444 | return; |
445 | } | |
446 | ||
f168693b | 447 | type = check_typedef (type); |
373a8247 | 448 | |
78134374 | 449 | switch (type->code ()) |
373a8247 PM |
450 | { |
451 | case TYPE_CODE_TYPEDEF: | |
452 | case TYPE_CODE_PTR: | |
373a8247 | 453 | case TYPE_CODE_REF: |
46157d77 AB |
454 | type_print_base (TYPE_TARGET_TYPE (type), stream, show, level, |
455 | flags); | |
373a8247 PM |
456 | break; |
457 | ||
458 | case TYPE_CODE_ARRAY: | |
46157d77 | 459 | print_type (TYPE_TARGET_TYPE (type), NULL, stream, 0, 0, flags); |
373a8247 PM |
460 | break; |
461 | ||
462 | case TYPE_CODE_FUNC: | |
463 | case TYPE_CODE_METHOD: | |
373a8247 PM |
464 | break; |
465 | case TYPE_CODE_STRUCT: | |
7d93a1e0 | 466 | if (type->name () != NULL) |
373a8247 | 467 | { |
7d93a1e0 | 468 | fputs_filtered (type->name (), stream); |
373a8247 PM |
469 | fputs_filtered (" = ", stream); |
470 | } | |
471 | if (HAVE_CPLUS_STRUCT (type)) | |
472 | { | |
473 | fprintf_filtered (stream, "class "); | |
474 | } | |
475 | else | |
476 | { | |
477 | fprintf_filtered (stream, "record "); | |
478 | } | |
479 | goto struct_union; | |
480 | ||
481 | case TYPE_CODE_UNION: | |
7d93a1e0 | 482 | if (type->name () != NULL) |
373a8247 | 483 | { |
7d93a1e0 | 484 | fputs_filtered (type->name (), stream); |
373a8247 PM |
485 | fputs_filtered (" = ", stream); |
486 | } | |
487 | fprintf_filtered (stream, "case <?> of "); | |
488 | ||
489 | struct_union: | |
490 | wrap_here (" "); | |
491 | if (show < 0) | |
492 | { | |
493 | /* If we just printed a tag name, no need to print anything else. */ | |
7d93a1e0 | 494 | if (type->name () == NULL) |
373a8247 PM |
495 | fprintf_filtered (stream, "{...}"); |
496 | } | |
7d93a1e0 | 497 | else if (show > 0 || type->name () == NULL) |
373a8247 | 498 | { |
46157d77 | 499 | type_print_derivation_info (stream, type); |
373a8247 PM |
500 | |
501 | fprintf_filtered (stream, "\n"); | |
1f704f76 | 502 | if ((type->num_fields () == 0) && (TYPE_NFN_FIELDS (type) == 0)) |
373a8247 | 503 | { |
e46d3488 | 504 | if (type->is_stub ()) |
32f47895 TT |
505 | fprintf_filtered (stream, "%*s<incomplete type>\n", |
506 | level + 4, ""); | |
373a8247 | 507 | else |
32f47895 TT |
508 | fprintf_filtered (stream, "%*s<no data fields>\n", |
509 | level + 4, ""); | |
373a8247 PM |
510 | } |
511 | ||
512 | /* Start off with no specific section type, so we can print | |
513 | one for the first field we find, and use that section type | |
0df8b418 | 514 | thereafter until we find another type. */ |
373a8247 PM |
515 | |
516 | section_type = s_none; | |
517 | ||
518 | /* If there is a base class for this type, | |
519 | do not print the field that it occupies. */ | |
520 | ||
1f704f76 | 521 | len = type->num_fields (); |
373a8247 PM |
522 | for (i = TYPE_N_BASECLASSES (type); i < len; i++) |
523 | { | |
524 | QUIT; | |
525 | /* Don't print out virtual function table. */ | |
61012eef | 526 | if ((startswith (TYPE_FIELD_NAME (type, i), "_vptr")) |
373a8247 PM |
527 | && is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5])) |
528 | continue; | |
529 | ||
530 | /* If this is a pascal object or class we can print the | |
dda83cd7 | 531 | various section labels. */ |
373a8247 PM |
532 | |
533 | if (HAVE_CPLUS_STRUCT (type)) | |
534 | { | |
535 | if (TYPE_FIELD_PROTECTED (type, i)) | |
536 | { | |
537 | if (section_type != s_protected) | |
538 | { | |
539 | section_type = s_protected; | |
32f47895 TT |
540 | fprintf_filtered (stream, "%*sprotected\n", |
541 | level + 2, ""); | |
373a8247 PM |
542 | } |
543 | } | |
544 | else if (TYPE_FIELD_PRIVATE (type, i)) | |
545 | { | |
546 | if (section_type != s_private) | |
547 | { | |
548 | section_type = s_private; | |
32f47895 TT |
549 | fprintf_filtered (stream, "%*sprivate\n", |
550 | level + 2, ""); | |
373a8247 PM |
551 | } |
552 | } | |
553 | else | |
554 | { | |
555 | if (section_type != s_public) | |
556 | { | |
557 | section_type = s_public; | |
32f47895 TT |
558 | fprintf_filtered (stream, "%*spublic\n", |
559 | level + 2, ""); | |
373a8247 PM |
560 | } |
561 | } | |
562 | } | |
563 | ||
564 | print_spaces_filtered (level + 4, stream); | |
ceacbf6e | 565 | if (field_is_static (&type->field (i))) |
d6a843b5 | 566 | fprintf_filtered (stream, "static "); |
46157d77 | 567 | print_type (type->field (i).type (), |
373a8247 | 568 | TYPE_FIELD_NAME (type, i), |
79d43c61 | 569 | stream, show - 1, level + 4, flags); |
ceacbf6e | 570 | if (!field_is_static (&type->field (i)) |
373a8247 PM |
571 | && TYPE_FIELD_PACKED (type, i)) |
572 | { | |
573 | /* It is a bitfield. This code does not attempt | |
574 | to look at the bitpos and reconstruct filler, | |
575 | unnamed fields. This would lead to misleading | |
576 | results if the compiler does not put out fields | |
577 | for such things (I don't know what it does). */ | |
578 | fprintf_filtered (stream, " : %d", | |
579 | TYPE_FIELD_BITSIZE (type, i)); | |
580 | } | |
581 | fprintf_filtered (stream, ";\n"); | |
582 | } | |
583 | ||
0df8b418 | 584 | /* If there are both fields and methods, put a space between. */ |
373a8247 PM |
585 | len = TYPE_NFN_FIELDS (type); |
586 | if (len && section_type != s_none) | |
587 | fprintf_filtered (stream, "\n"); | |
588 | ||
0df8b418 | 589 | /* Object pascal: print out the methods. */ |
373a8247 PM |
590 | |
591 | for (i = 0; i < len; i++) | |
592 | { | |
593 | struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); | |
594 | int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i); | |
0d5cff50 | 595 | const char *method_name = TYPE_FN_FIELDLIST_NAME (type, i); |
9216103f | 596 | |
373a8247 | 597 | /* this is GNU C++ specific |
dda83cd7 SM |
598 | how can we know constructor/destructor? |
599 | It might work for GNU pascal. */ | |
373a8247 PM |
600 | for (j = 0; j < len2; j++) |
601 | { | |
1d06ead6 | 602 | const char *physname = TYPE_FN_FIELD_PHYSNAME (f, j); |
373a8247 | 603 | |
61012eef GB |
604 | int is_constructor = (startswith (physname, "__ct__")); |
605 | int is_destructor = (startswith (physname, "__dt__")); | |
373a8247 PM |
606 | |
607 | QUIT; | |
608 | if (TYPE_FN_FIELD_PROTECTED (f, j)) | |
609 | { | |
610 | if (section_type != s_protected) | |
611 | { | |
612 | section_type = s_protected; | |
32f47895 TT |
613 | fprintf_filtered (stream, "%*sprotected\n", |
614 | level + 2, ""); | |
373a8247 PM |
615 | } |
616 | } | |
617 | else if (TYPE_FN_FIELD_PRIVATE (f, j)) | |
618 | { | |
619 | if (section_type != s_private) | |
620 | { | |
621 | section_type = s_private; | |
32f47895 TT |
622 | fprintf_filtered (stream, "%*sprivate\n", |
623 | level + 2, ""); | |
373a8247 PM |
624 | } |
625 | } | |
626 | else | |
627 | { | |
628 | if (section_type != s_public) | |
629 | { | |
630 | section_type = s_public; | |
32f47895 TT |
631 | fprintf_filtered (stream, "%*spublic\n", |
632 | level + 2, ""); | |
373a8247 PM |
633 | } |
634 | } | |
635 | ||
636 | print_spaces_filtered (level + 4, stream); | |
637 | if (TYPE_FN_FIELD_STATIC_P (f, j)) | |
638 | fprintf_filtered (stream, "static "); | |
639 | if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0) | |
640 | { | |
641 | /* Keep GDB from crashing here. */ | |
642 | fprintf_filtered (stream, "<undefined type> %s;\n", | |
643 | TYPE_FN_FIELD_PHYSNAME (f, j)); | |
644 | break; | |
645 | } | |
646 | ||
647 | if (is_constructor) | |
648 | { | |
649 | fprintf_filtered (stream, "constructor "); | |
650 | } | |
651 | else if (is_destructor) | |
652 | { | |
653 | fprintf_filtered (stream, "destructor "); | |
654 | } | |
3e9313ab | 655 | else if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) != 0 |
78134374 | 656 | && TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE(f, j))->code () != TYPE_CODE_VOID) |
373a8247 PM |
657 | { |
658 | fprintf_filtered (stream, "function "); | |
659 | } | |
660 | else | |
661 | { | |
662 | fprintf_filtered (stream, "procedure "); | |
663 | } | |
0df8b418 | 664 | /* This does not work, no idea why !! */ |
373a8247 | 665 | |
46157d77 | 666 | type_print_method_args (physname, method_name, stream); |
373a8247 | 667 | |
3e9313ab | 668 | if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) != 0 |
78134374 | 669 | && TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE(f, j))->code () != TYPE_CODE_VOID) |
373a8247 PM |
670 | { |
671 | fputs_filtered (" : ", stream); | |
672 | type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), | |
673 | "", stream, -1); | |
674 | } | |
675 | if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) | |
676 | fprintf_filtered (stream, "; virtual"); | |
677 | ||
678 | fprintf_filtered (stream, ";\n"); | |
679 | } | |
680 | } | |
32f47895 | 681 | fprintf_filtered (stream, "%*send", level, ""); |
373a8247 PM |
682 | } |
683 | break; | |
684 | ||
685 | case TYPE_CODE_ENUM: | |
7d93a1e0 | 686 | if (type->name () != NULL) |
373a8247 | 687 | { |
7d93a1e0 | 688 | fputs_filtered (type->name (), stream); |
373a8247 PM |
689 | if (show > 0) |
690 | fputs_filtered (" ", stream); | |
691 | } | |
692 | /* enum is just defined by | |
dda83cd7 | 693 | type enume_name = (enum_member1,enum_member2,...) */ |
373a8247 PM |
694 | fprintf_filtered (stream, " = "); |
695 | wrap_here (" "); | |
696 | if (show < 0) | |
697 | { | |
698 | /* If we just printed a tag name, no need to print anything else. */ | |
7d93a1e0 | 699 | if (type->name () == NULL) |
373a8247 PM |
700 | fprintf_filtered (stream, "(...)"); |
701 | } | |
7d93a1e0 | 702 | else if (show > 0 || type->name () == NULL) |
373a8247 PM |
703 | { |
704 | fprintf_filtered (stream, "("); | |
1f704f76 | 705 | len = type->num_fields (); |
373a8247 PM |
706 | lastval = 0; |
707 | for (i = 0; i < len; i++) | |
708 | { | |
709 | QUIT; | |
710 | if (i) | |
711 | fprintf_filtered (stream, ", "); | |
712 | wrap_here (" "); | |
713 | fputs_filtered (TYPE_FIELD_NAME (type, i), stream); | |
14e75d8e | 714 | if (lastval != TYPE_FIELD_ENUMVAL (type, i)) |
373a8247 | 715 | { |
3e43a32a | 716 | fprintf_filtered (stream, |
14e75d8e JK |
717 | " := %s", |
718 | plongest (TYPE_FIELD_ENUMVAL (type, i))); | |
719 | lastval = TYPE_FIELD_ENUMVAL (type, i); | |
373a8247 PM |
720 | } |
721 | lastval++; | |
722 | } | |
723 | fprintf_filtered (stream, ")"); | |
724 | } | |
725 | break; | |
726 | ||
727 | case TYPE_CODE_VOID: | |
728 | fprintf_filtered (stream, "void"); | |
729 | break; | |
730 | ||
731 | case TYPE_CODE_UNDEF: | |
732 | fprintf_filtered (stream, "record <unknown>"); | |
733 | break; | |
734 | ||
735 | case TYPE_CODE_ERROR: | |
b00fdb78 | 736 | fprintf_filtered (stream, "%s", TYPE_ERROR_NAME (type)); |
373a8247 PM |
737 | break; |
738 | ||
0df8b418 | 739 | /* this probably does not work for enums. */ |
373a8247 PM |
740 | case TYPE_CODE_RANGE: |
741 | { | |
742 | struct type *target = TYPE_TARGET_TYPE (type); | |
ad3bbd48 | 743 | |
5537ddd0 | 744 | print_type_scalar (target, type->bounds ()->low.const_val (), stream); |
373a8247 | 745 | fputs_filtered ("..", stream); |
5537ddd0 | 746 | print_type_scalar (target, type->bounds ()->high.const_val (), stream); |
373a8247 PM |
747 | } |
748 | break; | |
749 | ||
750 | case TYPE_CODE_SET: | |
751 | fputs_filtered ("set of ", stream); | |
46157d77 | 752 | print_type (type->index_type (), "", stream, |
79d43c61 | 753 | show - 1, level, flags); |
373a8247 PM |
754 | break; |
755 | ||
6604db2e PM |
756 | case TYPE_CODE_STRING: |
757 | fputs_filtered ("String", stream); | |
758 | break; | |
759 | ||
373a8247 PM |
760 | default: |
761 | /* Handle types not explicitly handled by the other cases, | |
dda83cd7 SM |
762 | such as fundamental types. For these, just print whatever |
763 | the type name is, as recorded in the type itself. If there | |
764 | is no type name, then complain. */ | |
7d93a1e0 | 765 | if (type->name () != NULL) |
373a8247 | 766 | { |
7d93a1e0 | 767 | fputs_filtered (type->name (), stream); |
373a8247 PM |
768 | } |
769 | else | |
770 | { | |
771 | /* At least for dump_symtab, it is important that this not be | |
772 | an error (). */ | |
7f6aba03 TT |
773 | fprintf_styled (stream, metadata_style.style (), |
774 | "<invalid unnamed pascal type code %d>", | |
78134374 | 775 | type->code ()); |
373a8247 PM |
776 | } |
777 | break; | |
778 | } | |
779 | } |