]>
Commit | Line | Data |
---|---|---|
c906108c | 1 | /* Support for printing Modula 2 types for GDB, the GNU debugger. |
1d506c26 | 2 | Copyright (C) 1986-2024 Free Software Foundation, Inc. |
c906108c | 3 | |
c5aa993b JM |
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 |
c5aa993b JM |
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/>. */ |
c906108c | 18 | |
e5dc0d5d | 19 | #include "event-top.h" |
83b6e1f1 | 20 | #include "language.h" |
bf31fd38 | 21 | #include "gdbsupport/gdb_obstack.h" |
ef0f16cc | 22 | #include "bfd.h" |
c906108c SS |
23 | #include "symtab.h" |
24 | #include "gdbtypes.h" | |
25 | #include "expression.h" | |
26 | #include "value.h" | |
27 | #include "gdbcore.h" | |
c906108c | 28 | #include "m2-lang.h" |
72019c9c GM |
29 | #include "target.h" |
30 | #include "language.h" | |
31 | #include "demangle.h" | |
32 | #include "c-lang.h" | |
33 | #include "typeprint.h" | |
34 | #include "cp-abi.h" | |
7f6aba03 | 35 | #include "cli/cli-style.h" |
c906108c | 36 | |
72019c9c GM |
37 | static void m2_print_bounds (struct type *type, |
38 | struct ui_file *stream, int show, int level, | |
39 | int print_high); | |
40 | ||
79d43c61 TT |
41 | static void m2_typedef (struct type *, struct ui_file *, int, int, |
42 | const struct type_print_options *); | |
43 | static void m2_array (struct type *, struct ui_file *, int, int, | |
44 | const struct type_print_options *); | |
45 | static void m2_pointer (struct type *, struct ui_file *, int, int, | |
46 | const struct type_print_options *); | |
47 | static void m2_ref (struct type *, struct ui_file *, int, int, | |
48 | const struct type_print_options *); | |
49 | static void m2_procedure (struct type *, struct ui_file *, int, int, | |
50 | const struct type_print_options *); | |
72019c9c GM |
51 | static void m2_union (struct type *, struct ui_file *); |
52 | static void m2_enum (struct type *, struct ui_file *, int, int); | |
79d43c61 TT |
53 | static void m2_range (struct type *, struct ui_file *, int, int, |
54 | const struct type_print_options *); | |
72019c9c GM |
55 | static void m2_type_name (struct type *type, struct ui_file *stream); |
56 | static void m2_short_set (struct type *type, struct ui_file *stream, | |
57 | int show, int level); | |
58 | static int m2_long_set (struct type *type, struct ui_file *stream, | |
79d43c61 | 59 | int show, int level, const struct type_print_options *flags); |
844781a1 | 60 | static int m2_unbounded_array (struct type *type, struct ui_file *stream, |
79d43c61 TT |
61 | int show, int level, |
62 | const struct type_print_options *flags); | |
72019c9c | 63 | static void m2_record_fields (struct type *type, struct ui_file *stream, |
79d43c61 | 64 | int show, int level, const struct type_print_options *flags); |
72019c9c GM |
65 | static void m2_unknown (const char *s, struct type *type, |
66 | struct ui_file *stream, int show, int level); | |
67 | ||
68 | int m2_is_long_set (struct type *type); | |
69 | int m2_is_long_set_of_type (struct type *type, struct type **of_type); | |
844781a1 | 70 | int m2_is_unbounded_array (struct type *type); |
72019c9c GM |
71 | |
72 | ||
c906108c | 73 | void |
025bb325 MS |
74 | m2_print_type (struct type *type, const char *varstring, |
75 | struct ui_file *stream, | |
79d43c61 TT |
76 | int show, int level, |
77 | const struct type_print_options *flags) | |
c906108c | 78 | { |
f168693b | 79 | type = check_typedef (type); |
72019c9c GM |
80 | |
81 | QUIT; | |
82 | ||
1285ce86 | 83 | stream->wrap_here (4); |
72019c9c GM |
84 | if (type == NULL) |
85 | { | |
7f6aba03 | 86 | fputs_styled (_("<type unknown>"), metadata_style.style (), stream); |
72019c9c GM |
87 | return; |
88 | } | |
89 | ||
78134374 | 90 | switch (type->code ()) |
72019c9c GM |
91 | { |
92 | case TYPE_CODE_SET: | |
93 | m2_short_set(type, stream, show, level); | |
94 | break; | |
95 | ||
96 | case TYPE_CODE_STRUCT: | |
79d43c61 TT |
97 | if (m2_long_set (type, stream, show, level, flags) |
98 | || m2_unbounded_array (type, stream, show, level, flags)) | |
72019c9c | 99 | break; |
79d43c61 | 100 | m2_record_fields (type, stream, show, level, flags); |
72019c9c GM |
101 | break; |
102 | ||
103 | case TYPE_CODE_TYPEDEF: | |
79d43c61 | 104 | m2_typedef (type, stream, show, level, flags); |
72019c9c GM |
105 | break; |
106 | ||
107 | case TYPE_CODE_ARRAY: | |
79d43c61 | 108 | m2_array (type, stream, show, level, flags); |
72019c9c GM |
109 | break; |
110 | ||
111 | case TYPE_CODE_PTR: | |
79d43c61 | 112 | m2_pointer (type, stream, show, level, flags); |
72019c9c GM |
113 | break; |
114 | ||
115 | case TYPE_CODE_REF: | |
79d43c61 | 116 | m2_ref (type, stream, show, level, flags); |
72019c9c GM |
117 | break; |
118 | ||
72019c9c GM |
119 | case TYPE_CODE_METHOD: |
120 | m2_unknown (_("method"), type, stream, show, level); | |
121 | break; | |
122 | ||
123 | case TYPE_CODE_FUNC: | |
79d43c61 | 124 | m2_procedure (type, stream, show, level, flags); |
72019c9c GM |
125 | break; |
126 | ||
127 | case TYPE_CODE_UNION: | |
128 | m2_union (type, stream); | |
129 | break; | |
130 | ||
131 | case TYPE_CODE_ENUM: | |
132 | m2_enum (type, stream, show, level); | |
133 | break; | |
134 | ||
135 | case TYPE_CODE_VOID: | |
136 | break; | |
137 | ||
138 | case TYPE_CODE_UNDEF: | |
025bb325 | 139 | /* i18n: Do not translate the "struct" part! */ |
72019c9c GM |
140 | m2_unknown (_("undef"), type, stream, show, level); |
141 | break; | |
142 | ||
143 | case TYPE_CODE_ERROR: | |
144 | m2_unknown (_("error"), type, stream, show, level); | |
145 | break; | |
146 | ||
147 | case TYPE_CODE_RANGE: | |
79d43c61 | 148 | m2_range (type, stream, show, level, flags); |
72019c9c GM |
149 | break; |
150 | ||
72019c9c GM |
151 | default: |
152 | m2_type_name (type, stream); | |
153 | break; | |
154 | } | |
155 | } | |
156 | ||
5c6ce71d TT |
157 | /* Print a typedef using M2 syntax. TYPE is the underlying type. |
158 | NEW_SYMBOL is the symbol naming the type. STREAM is the stream on | |
159 | which to print. */ | |
160 | ||
161 | void | |
790e2a12 AB |
162 | m2_language::print_typedef (struct type *type, struct symbol *new_symbol, |
163 | struct ui_file *stream) const | |
5c6ce71d | 164 | { |
f168693b | 165 | type = check_typedef (type); |
6cb06a8c | 166 | gdb_printf (stream, "TYPE "); |
5f9c5a63 SM |
167 | if (!new_symbol->type ()->name () |
168 | || strcmp ((new_symbol->type ())->name (), | |
987012b8 | 169 | new_symbol->linkage_name ()) != 0) |
6cb06a8c | 170 | gdb_printf (stream, "%s = ", new_symbol->print_name ()); |
5c6ce71d | 171 | else |
6cb06a8c | 172 | gdb_printf (stream, "<builtin> = "); |
5c6ce71d | 173 | type_print (type, "", stream, 0); |
6cb06a8c | 174 | gdb_printf (stream, ";"); |
5c6ce71d TT |
175 | } |
176 | ||
844781a1 | 177 | /* m2_type_name - if a, type, has a name then print it. */ |
72019c9c GM |
178 | |
179 | void | |
180 | m2_type_name (struct type *type, struct ui_file *stream) | |
181 | { | |
7d93a1e0 | 182 | if (type->name () != NULL) |
0426ad51 | 183 | gdb_puts (type->name (), stream); |
72019c9c GM |
184 | } |
185 | ||
844781a1 | 186 | /* m2_range - displays a Modula-2 subrange type. */ |
72019c9c GM |
187 | |
188 | void | |
189 | m2_range (struct type *type, struct ui_file *stream, int show, | |
79d43c61 | 190 | int level, const struct type_print_options *flags) |
72019c9c | 191 | { |
5537ddd0 | 192 | if (type->bounds ()->high.const_val () == type->bounds ()->low.const_val ()) |
09e2d7c7 | 193 | { |
27710edb SM |
194 | /* FIXME: type::target_type used to be TYPE_DOMAIN_TYPE but that was |
195 | wrong. Not sure if type::target_type is correct though. */ | |
196 | m2_print_type (type->target_type (), "", stream, show, level, | |
09e2d7c7 DE |
197 | flags); |
198 | } | |
72019c9c GM |
199 | else |
200 | { | |
27710edb | 201 | struct type *target = type->target_type (); |
72019c9c | 202 | |
6cb06a8c | 203 | gdb_printf (stream, "["); |
5537ddd0 | 204 | print_type_scalar (target, type->bounds ()->low.const_val (), stream); |
6cb06a8c | 205 | gdb_printf (stream, ".."); |
5537ddd0 | 206 | print_type_scalar (target, type->bounds ()->high.const_val (), stream); |
6cb06a8c | 207 | gdb_printf (stream, "]"); |
72019c9c GM |
208 | } |
209 | } | |
210 | ||
211 | static void | |
212 | m2_typedef (struct type *type, struct ui_file *stream, int show, | |
79d43c61 | 213 | int level, const struct type_print_options *flags) |
72019c9c | 214 | { |
7d93a1e0 | 215 | if (type->name () != NULL) |
72019c9c | 216 | { |
0426ad51 TT |
217 | gdb_puts (type->name (), stream); |
218 | gdb_puts (" = ", stream); | |
72019c9c | 219 | } |
27710edb | 220 | m2_print_type (type->target_type (), "", stream, show, level, flags); |
72019c9c GM |
221 | } |
222 | ||
844781a1 | 223 | /* m2_array - prints out a Modula-2 ARRAY ... OF type. */ |
72019c9c GM |
224 | |
225 | static void m2_array (struct type *type, struct ui_file *stream, | |
79d43c61 | 226 | int show, int level, const struct type_print_options *flags) |
72019c9c | 227 | { |
6cb06a8c | 228 | gdb_printf (stream, "ARRAY ["); |
df86565b | 229 | if (type->target_type ()->length () > 0 |
9c0fb734 | 230 | && type->bounds ()->high.is_constant ()) |
72019c9c | 231 | { |
3d967001 | 232 | if (type->index_type () != 0) |
72019c9c | 233 | { |
3d967001 | 234 | m2_print_bounds (type->index_type (), stream, show, -1, 0); |
6cb06a8c | 235 | gdb_printf (stream, ".."); |
3d967001 | 236 | m2_print_bounds (type->index_type (), stream, show, -1, 1); |
72019c9c GM |
237 | } |
238 | else | |
df86565b SM |
239 | gdb_puts (pulongest ((type->length () |
240 | / type->target_type ()->length ())), | |
0426ad51 | 241 | stream); |
72019c9c | 242 | } |
6cb06a8c | 243 | gdb_printf (stream, "] OF "); |
27710edb | 244 | m2_print_type (type->target_type (), "", stream, show, level, flags); |
72019c9c GM |
245 | } |
246 | ||
247 | static void | |
248 | m2_pointer (struct type *type, struct ui_file *stream, int show, | |
79d43c61 | 249 | int level, const struct type_print_options *flags) |
72019c9c GM |
250 | { |
251 | if (TYPE_CONST (type)) | |
6cb06a8c | 252 | gdb_printf (stream, "[...] : "); |
72019c9c | 253 | else |
6cb06a8c | 254 | gdb_printf (stream, "POINTER TO "); |
72019c9c | 255 | |
27710edb | 256 | m2_print_type (type->target_type (), "", stream, show, level, flags); |
72019c9c GM |
257 | } |
258 | ||
259 | static void | |
260 | m2_ref (struct type *type, struct ui_file *stream, int show, | |
79d43c61 | 261 | int level, const struct type_print_options *flags) |
72019c9c | 262 | { |
6cb06a8c | 263 | gdb_printf (stream, "VAR"); |
27710edb | 264 | m2_print_type (type->target_type (), "", stream, show, level, flags); |
72019c9c GM |
265 | } |
266 | ||
267 | static void | |
268 | m2_unknown (const char *s, struct type *type, struct ui_file *stream, | |
269 | int show, int level) | |
270 | { | |
6cb06a8c | 271 | gdb_printf (stream, "%s %s", s, _("is unknown")); |
72019c9c GM |
272 | } |
273 | ||
274 | static void m2_union (struct type *type, struct ui_file *stream) | |
275 | { | |
6cb06a8c | 276 | gdb_printf (stream, "union"); |
72019c9c GM |
277 | } |
278 | ||
279 | static void | |
280 | m2_procedure (struct type *type, struct ui_file *stream, | |
79d43c61 | 281 | int show, int level, const struct type_print_options *flags) |
72019c9c | 282 | { |
6cb06a8c | 283 | gdb_printf (stream, "PROCEDURE "); |
72019c9c | 284 | m2_type_name (type, stream); |
27710edb SM |
285 | if (type->target_type () == NULL |
286 | || type->target_type ()->code () != TYPE_CODE_VOID) | |
72019c9c | 287 | { |
1f704f76 | 288 | int i, len = type->num_fields (); |
72019c9c | 289 | |
6cb06a8c | 290 | gdb_printf (stream, " ("); |
72019c9c GM |
291 | for (i = 0; i < len; i++) |
292 | { | |
293 | if (i > 0) | |
294 | { | |
0426ad51 | 295 | gdb_puts (", ", stream); |
1285ce86 | 296 | stream->wrap_here (4); |
72019c9c | 297 | } |
940da03e | 298 | m2_print_type (type->field (i).type (), "", stream, -1, 0, flags); |
72019c9c | 299 | } |
6cb06a8c | 300 | gdb_printf (stream, ") : "); |
27710edb SM |
301 | if (type->target_type () != NULL) |
302 | m2_print_type (type->target_type (), "", stream, 0, 0, flags); | |
7022349d PA |
303 | else |
304 | type_print_unknown_return_type (stream); | |
72019c9c GM |
305 | } |
306 | } | |
307 | ||
308 | static void | |
309 | m2_print_bounds (struct type *type, | |
310 | struct ui_file *stream, int show, int level, | |
311 | int print_high) | |
312 | { | |
27710edb | 313 | struct type *target = type->target_type (); |
72019c9c | 314 | |
1f704f76 | 315 | if (type->num_fields () == 0) |
72019c9c GM |
316 | return; |
317 | ||
318 | if (print_high) | |
5537ddd0 | 319 | print_type_scalar (target, type->bounds ()->high.const_val (), stream); |
72019c9c | 320 | else |
5537ddd0 | 321 | print_type_scalar (target, type->bounds ()->low.const_val (), stream); |
72019c9c GM |
322 | } |
323 | ||
324 | static void | |
325 | m2_short_set (struct type *type, struct ui_file *stream, int show, int level) | |
326 | { | |
6cb06a8c | 327 | gdb_printf(stream, "SET ["); |
3d967001 | 328 | m2_print_bounds (type->index_type (), stream, |
72019c9c GM |
329 | show - 1, level, 0); |
330 | ||
6cb06a8c | 331 | gdb_printf(stream, ".."); |
3d967001 | 332 | m2_print_bounds (type->index_type (), stream, |
72019c9c | 333 | show - 1, level, 1); |
6cb06a8c | 334 | gdb_printf(stream, "]"); |
72019c9c GM |
335 | } |
336 | ||
337 | int | |
338 | m2_is_long_set (struct type *type) | |
339 | { | |
025bb325 MS |
340 | LONGEST previous_high = 0; /* Unnecessary initialization |
341 | keeps gcc -Wall happy. */ | |
72019c9c GM |
342 | int len, i; |
343 | struct type *range; | |
344 | ||
78134374 | 345 | if (type->code () == TYPE_CODE_STRUCT) |
72019c9c GM |
346 | { |
347 | ||
844781a1 GM |
348 | /* check if all fields of the RECORD are consecutive sets. */ |
349 | ||
1f704f76 | 350 | len = type->num_fields (); |
72019c9c GM |
351 | for (i = TYPE_N_BASECLASSES (type); i < len; i++) |
352 | { | |
940da03e | 353 | if (type->field (i).type () == NULL) |
72019c9c | 354 | return 0; |
940da03e | 355 | if (type->field (i).type ()->code () != TYPE_CODE_SET) |
72019c9c | 356 | return 0; |
33d16dd9 SM |
357 | if (type->field (i).name () != NULL |
358 | && (strcmp (type->field (i).name (), "") != 0)) | |
72019c9c | 359 | return 0; |
940da03e | 360 | range = type->field (i).type ()->index_type (); |
72019c9c | 361 | if ((i > TYPE_N_BASECLASSES (type)) |
5537ddd0 | 362 | && previous_high + 1 != range->bounds ()->low.const_val ()) |
72019c9c | 363 | return 0; |
5537ddd0 | 364 | previous_high = range->bounds ()->high.const_val (); |
72019c9c GM |
365 | } |
366 | return len>0; | |
367 | } | |
368 | return 0; | |
369 | } | |
370 | ||
844781a1 | 371 | /* m2_get_discrete_bounds - a wrapper for get_discrete_bounds which |
dda83cd7 SM |
372 | understands that CHARs might be signed. |
373 | This should be integrated into gdbtypes.c | |
374 | inside get_discrete_bounds. */ | |
72019c9c | 375 | |
1f8d2881 | 376 | static bool |
72019c9c GM |
377 | m2_get_discrete_bounds (struct type *type, LONGEST *lowp, LONGEST *highp) |
378 | { | |
f168693b | 379 | type = check_typedef (type); |
78134374 | 380 | switch (type->code ()) |
72019c9c GM |
381 | { |
382 | case TYPE_CODE_CHAR: | |
df86565b | 383 | if (type->length () < sizeof (LONGEST)) |
72019c9c | 384 | { |
c6d940a9 | 385 | if (!type->is_unsigned ()) |
72019c9c | 386 | { |
df86565b | 387 | *lowp = -(1 << (type->length () * TARGET_CHAR_BIT - 1)); |
72019c9c GM |
388 | *highp = -*lowp - 1; |
389 | return 0; | |
390 | } | |
391 | } | |
d182e398 | 392 | [[fallthrough]]; |
72019c9c GM |
393 | default: |
394 | return get_discrete_bounds (type, lowp, highp); | |
395 | } | |
396 | } | |
397 | ||
844781a1 | 398 | /* m2_is_long_set_of_type - returns TRUE if the long set was declared as |
dda83cd7 SM |
399 | SET OF <oftype> of_type is assigned to the |
400 | subtype. */ | |
72019c9c GM |
401 | |
402 | int | |
403 | m2_is_long_set_of_type (struct type *type, struct type **of_type) | |
404 | { | |
405 | int len, i; | |
406 | struct type *range; | |
407 | struct type *target; | |
408 | LONGEST l1, l2; | |
409 | LONGEST h1, h2; | |
410 | ||
78134374 | 411 | if (type->code () == TYPE_CODE_STRUCT) |
72019c9c | 412 | { |
1f704f76 | 413 | len = type->num_fields (); |
72019c9c GM |
414 | i = TYPE_N_BASECLASSES (type); |
415 | if (len == 0) | |
416 | return 0; | |
940da03e | 417 | range = type->field (i).type ()->index_type (); |
27710edb | 418 | target = range->target_type (); |
72019c9c | 419 | |
cf88be68 SM |
420 | l1 = type->field (i).type ()->bounds ()->low.const_val (); |
421 | h1 = type->field (len - 1).type ()->bounds ()->high.const_val (); | |
72019c9c | 422 | *of_type = target; |
1f8d2881 | 423 | if (m2_get_discrete_bounds (target, &l2, &h2)) |
72019c9c GM |
424 | return (l1 == l2 && h1 == h2); |
425 | error (_("long_set failed to find discrete bounds for its subtype")); | |
426 | return 0; | |
427 | } | |
428 | error (_("expecting long_set")); | |
429 | return 0; | |
430 | } | |
431 | ||
432 | static int | |
79d43c61 TT |
433 | m2_long_set (struct type *type, struct ui_file *stream, int show, int level, |
434 | const struct type_print_options *flags) | |
72019c9c | 435 | { |
72019c9c GM |
436 | struct type *of_type; |
437 | int i; | |
1f704f76 | 438 | int len = type->num_fields (); |
72019c9c GM |
439 | LONGEST low; |
440 | LONGEST high; | |
441 | ||
442 | if (m2_is_long_set (type)) | |
443 | { | |
7d93a1e0 | 444 | if (type->name () != NULL) |
72019c9c | 445 | { |
0426ad51 | 446 | gdb_puts (type->name (), stream); |
72019c9c GM |
447 | if (show == 0) |
448 | return 1; | |
0426ad51 | 449 | gdb_puts (" = ", stream); |
72019c9c GM |
450 | } |
451 | ||
72019c9c GM |
452 | if (get_long_set_bounds (type, &low, &high)) |
453 | { | |
6cb06a8c | 454 | gdb_printf(stream, "SET OF "); |
72019c9c GM |
455 | i = TYPE_N_BASECLASSES (type); |
456 | if (m2_is_long_set_of_type (type, &of_type)) | |
79d43c61 | 457 | m2_print_type (of_type, "", stream, show - 1, level, flags); |
72019c9c GM |
458 | else |
459 | { | |
6cb06a8c | 460 | gdb_printf(stream, "["); |
940da03e | 461 | m2_print_bounds (type->field (i).type ()->index_type (), |
72019c9c GM |
462 | stream, show - 1, level, 0); |
463 | ||
6cb06a8c | 464 | gdb_printf(stream, ".."); |
72019c9c | 465 | |
940da03e | 466 | m2_print_bounds (type->field (len - 1).type ()->index_type (), |
72019c9c | 467 | stream, show - 1, level, 1); |
6cb06a8c | 468 | gdb_printf(stream, "]"); |
72019c9c GM |
469 | } |
470 | } | |
471 | else | |
025bb325 | 472 | /* i18n: Do not translate the "SET OF" part! */ |
6cb06a8c | 473 | gdb_printf(stream, _("SET OF <unknown>")); |
72019c9c GM |
474 | |
475 | return 1; | |
476 | } | |
477 | return 0; | |
478 | } | |
479 | ||
844781a1 | 480 | /* m2_is_unbounded_array - returns TRUE if, type, should be regarded |
dda83cd7 | 481 | as a Modula-2 unbounded ARRAY type. */ |
844781a1 GM |
482 | |
483 | int | |
484 | m2_is_unbounded_array (struct type *type) | |
485 | { | |
78134374 | 486 | if (type->code () == TYPE_CODE_STRUCT) |
844781a1 GM |
487 | { |
488 | /* | |
489 | * check if we have a structure with exactly two fields named | |
490 | * _m2_contents and _m2_high. It also checks to see if the | |
27710edb | 491 | * type of _m2_contents is a pointer. The type::target_type |
844781a1 GM |
492 | * of the pointer determines the unbounded ARRAY OF type. |
493 | */ | |
1f704f76 | 494 | if (type->num_fields () != 2) |
844781a1 | 495 | return 0; |
33d16dd9 | 496 | if (strcmp (type->field (0).name (), "_m2_contents") != 0) |
844781a1 | 497 | return 0; |
33d16dd9 | 498 | if (strcmp (type->field (1).name (), "_m2_high") != 0) |
844781a1 | 499 | return 0; |
940da03e | 500 | if (type->field (0).type ()->code () != TYPE_CODE_PTR) |
844781a1 GM |
501 | return 0; |
502 | return 1; | |
503 | } | |
504 | return 0; | |
505 | } | |
506 | ||
507 | /* m2_unbounded_array - if the struct type matches a Modula-2 unbounded | |
dda83cd7 SM |
508 | parameter type then display the type as an |
509 | ARRAY OF type. Returns TRUE if an unbounded | |
510 | array type was detected. */ | |
844781a1 GM |
511 | |
512 | static int | |
513 | m2_unbounded_array (struct type *type, struct ui_file *stream, int show, | |
79d43c61 | 514 | int level, const struct type_print_options *flags) |
844781a1 GM |
515 | { |
516 | if (m2_is_unbounded_array (type)) | |
517 | { | |
518 | if (show > 0) | |
519 | { | |
0426ad51 | 520 | gdb_puts ("ARRAY OF ", stream); |
27710edb | 521 | m2_print_type (type->field (0).type ()->target_type (), |
79d43c61 | 522 | "", stream, 0, level, flags); |
844781a1 GM |
523 | } |
524 | return 1; | |
525 | } | |
526 | return 0; | |
527 | } | |
528 | ||
72019c9c GM |
529 | void |
530 | m2_record_fields (struct type *type, struct ui_file *stream, int show, | |
79d43c61 | 531 | int level, const struct type_print_options *flags) |
72019c9c | 532 | { |
844781a1 | 533 | /* Print the tag if it exists. */ |
7d93a1e0 | 534 | if (type->name () != NULL) |
72019c9c | 535 | { |
7d93a1e0 | 536 | if (!startswith (type->name (), "$$")) |
72019c9c | 537 | { |
0426ad51 | 538 | gdb_puts (type->name (), stream); |
72019c9c | 539 | if (show > 0) |
6cb06a8c | 540 | gdb_printf (stream, " = "); |
72019c9c GM |
541 | } |
542 | } | |
1285ce86 | 543 | stream->wrap_here (4); |
72019c9c GM |
544 | if (show < 0) |
545 | { | |
78134374 | 546 | if (type->code () == TYPE_CODE_STRUCT) |
6cb06a8c | 547 | gdb_printf (stream, "RECORD ... END "); |
78134374 | 548 | else if (type->code () == TYPE_CODE_UNION) |
6cb06a8c | 549 | gdb_printf (stream, "CASE ... END "); |
72019c9c GM |
550 | } |
551 | else if (show > 0) | |
552 | { | |
5648af48 | 553 | int i; |
1f704f76 | 554 | int len = type->num_fields (); |
5648af48 | 555 | |
78134374 | 556 | if (type->code () == TYPE_CODE_STRUCT) |
6cb06a8c | 557 | gdb_printf (stream, "RECORD\n"); |
78134374 | 558 | else if (type->code () == TYPE_CODE_UNION) |
025bb325 | 559 | /* i18n: Do not translate "CASE" and "OF". */ |
6cb06a8c | 560 | gdb_printf (stream, _("CASE <variant> OF\n")); |
72019c9c GM |
561 | |
562 | for (i = TYPE_N_BASECLASSES (type); i < len; i++) | |
563 | { | |
564 | QUIT; | |
565 | ||
d0b1020b | 566 | print_spaces (level + 4, stream); |
33d16dd9 | 567 | fputs_styled (type->field (i).name (), |
3f0cbb04 | 568 | variable_name_style.style (), stream); |
0426ad51 | 569 | gdb_puts (" : ", stream); |
940da03e | 570 | m2_print_type (type->field (i).type (), |
72019c9c | 571 | "", |
79d43c61 | 572 | stream, 0, level + 4, flags); |
8c329d5c | 573 | if (type->field (i).is_packed ()) |
72019c9c GM |
574 | { |
575 | /* It is a bitfield. This code does not attempt | |
576 | to look at the bitpos and reconstruct filler, | |
577 | unnamed fields. This would lead to misleading | |
578 | results if the compiler does not put out fields | |
579 | for such things (I don't know what it does). */ | |
3757d2d4 | 580 | gdb_printf (stream, " : %d", type->field (i).bitsize ()); |
72019c9c | 581 | } |
6cb06a8c | 582 | gdb_printf (stream, ";\n"); |
72019c9c GM |
583 | } |
584 | ||
6cb06a8c | 585 | gdb_printf (stream, "%*sEND ", level, ""); |
72019c9c GM |
586 | } |
587 | } | |
588 | ||
589 | void | |
590 | m2_enum (struct type *type, struct ui_file *stream, int show, int level) | |
591 | { | |
b4aa388a SP |
592 | LONGEST lastval; |
593 | int i, len; | |
c906108c | 594 | |
72019c9c GM |
595 | if (show < 0) |
596 | { | |
597 | /* If we just printed a tag name, no need to print anything else. */ | |
7d93a1e0 | 598 | if (type->name () == NULL) |
6cb06a8c | 599 | gdb_printf (stream, "(...)"); |
72019c9c | 600 | } |
7d93a1e0 | 601 | else if (show > 0 || type->name () == NULL) |
72019c9c | 602 | { |
6cb06a8c | 603 | gdb_printf (stream, "("); |
1f704f76 | 604 | len = type->num_fields (); |
72019c9c GM |
605 | lastval = 0; |
606 | for (i = 0; i < len; i++) | |
607 | { | |
608 | QUIT; | |
609 | if (i > 0) | |
6cb06a8c | 610 | gdb_printf (stream, ", "); |
1285ce86 | 611 | stream->wrap_here (4); |
33d16dd9 | 612 | fputs_styled (type->field (i).name (), |
3f0cbb04 | 613 | variable_name_style.style (), stream); |
970db518 | 614 | if (lastval != type->field (i).loc_enumval ()) |
72019c9c | 615 | { |
6cb06a8c TT |
616 | gdb_printf (stream, " = %s", |
617 | plongest (type->field (i).loc_enumval ())); | |
970db518 | 618 | lastval = type->field (i).loc_enumval (); |
72019c9c GM |
619 | } |
620 | lastval++; | |
621 | } | |
6cb06a8c | 622 | gdb_printf (stream, ")"); |
72019c9c | 623 | } |
c906108c | 624 | } |