Index: gdb/valprint.c |
diff --git a/gdb/valprint.c b/gdb/valprint.c |
index 325cf40edb9c67f2e7787b28c981f4d534b5a5c7..fc5942da77887069a9a1e19192245711df5c8755 100644 |
--- a/gdb/valprint.c |
+++ b/gdb/valprint.c |
@@ -85,7 +85,8 @@ struct value_print_options user_print_options = |
1, /* static_field_print */ |
1, /* pascal_static_field_print */ |
0, /* raw */ |
- 0 /* summary */ |
+ 0, /* summary */ |
+ 1 /* symbol_print */ |
}; |
/* Initialize *OPTS to be a copy of the user print options. */ |
@@ -219,6 +220,16 @@ show_addressprint (struct ui_file *file, int from_tty, |
{ |
fprintf_filtered (file, _("Printing of addresses is %s.\n"), value); |
} |
+ |
+static void |
+show_symbol_print (struct ui_file *file, int from_tty, |
+ struct cmd_list_element *c, const char *value) |
+{ |
+ fprintf_filtered (file, |
+ _("Printing of symbols when printing pointers is %s.\n"), |
+ value); |
+} |
+ |
/* A helper function for val_print. When printing in "summary" mode, |
@@ -248,17 +259,9 @@ scalar_type_p (struct type *type) |
} |
} |
-/* Helper function to check the validity of some bits of a value. |
- |
- If TYPE represents some aggregate type (e.g., a structure), return 1. |
- |
- Otherwise, any of the bytes starting at OFFSET and extending for |
- TYPE_LENGTH(TYPE) bytes are invalid, print a message to STREAM and |
- return 0. The checking is done using FUNCS. |
- |
- Otherwise, return 1. */ |
+/* See its definition in value.h. */ |
-static int |
+int |
valprint_check_validity (struct ui_file *stream, |
struct type *type, |
int embedded_offset, |
@@ -312,6 +315,361 @@ val_print_invalid_address (struct ui_file *stream) |
fprintf_filtered (stream, _("<invalid address>")); |
} |
+/* A generic val_print that is suitable for use by language |
+ implementations of the la_val_print method. This function can |
+ handle most type codes, though not all, notably exception |
+ TYPE_CODE_UNION and TYPE_CODE_STRUCT, which must be implemented by |
+ the caller. |
+ |
+ Most arguments are as to val_print. |
+ |
+ The additional DECORATIONS argument can be used to customize the |
+ output in some small, language-specific ways. */ |
+ |
+void |
+generic_val_print (struct type *type, const gdb_byte *valaddr, |
+ int embedded_offset, CORE_ADDR address, |
+ struct ui_file *stream, int recurse, |
+ const struct value *original_value, |
+ const struct value_print_options *options, |
+ const struct generic_val_print_decorations *decorations) |
+{ |
+ struct gdbarch *gdbarch = get_type_arch (type); |
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); |
+ unsigned int i = 0; /* Number of characters printed. */ |
+ unsigned len; |
+ struct type *elttype, *unresolved_elttype; |
+ struct type *unresolved_type = type; |
+ LONGEST val; |
+ CORE_ADDR addr; |
+ |
+ CHECK_TYPEDEF (type); |
+ switch (TYPE_CODE (type)) |
+ { |
+ case TYPE_CODE_ARRAY: |
+ unresolved_elttype = TYPE_TARGET_TYPE (type); |
+ elttype = check_typedef (unresolved_elttype); |
+ if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (unresolved_elttype) > 0) |
+ { |
+ LONGEST low_bound, high_bound; |
+ |
+ if (!get_array_bounds (type, &low_bound, &high_bound)) |
+ error (_("Could not determine the array high bound")); |
+ |
+ if (options->prettyprint_arrays) |
+ { |
+ print_spaces_filtered (2 + 2 * recurse, stream); |
+ } |
+ |
+ fprintf_filtered (stream, "{"); |
+ val_print_array_elements (type, valaddr, embedded_offset, |
+ address, stream, |
+ recurse, original_value, options, 0); |
+ fprintf_filtered (stream, "}"); |
+ break; |
+ } |
+ /* Array of unspecified length: treat like pointer to first |
+ elt. */ |
+ addr = address + embedded_offset; |
+ goto print_unpacked_pointer; |
+ |
+ case TYPE_CODE_MEMBERPTR: |
+ val_print_scalar_formatted (type, valaddr, embedded_offset, |
+ original_value, options, 0, stream); |
+ break; |
+ |
+ case TYPE_CODE_PTR: |
+ if (options->format && options->format != 's') |
+ { |
+ val_print_scalar_formatted (type, valaddr, embedded_offset, |
+ original_value, options, 0, stream); |
+ break; |
+ } |
+ unresolved_elttype = TYPE_TARGET_TYPE (type); |
+ elttype = check_typedef (unresolved_elttype); |
+ { |
+ addr = unpack_pointer (type, valaddr + embedded_offset); |
+ print_unpacked_pointer: |
+ |
+ if (TYPE_CODE (elttype) == TYPE_CODE_FUNC) |
+ { |
+ /* Try to print what function it points to. */ |
+ print_function_pointer_address (options, gdbarch, addr, stream); |
+ return; |
+ } |
+ |
+ if (options->symbol_print) |
+ print_address_demangle (options, gdbarch, addr, stream, demangle); |
+ else if (options->addressprint) |
+ fputs_filtered (paddress (gdbarch, addr), stream); |
+ } |
+ break; |
+ |
+ case TYPE_CODE_REF: |
+ elttype = check_typedef (TYPE_TARGET_TYPE (type)); |
+ if (options->addressprint) |
+ { |
+ CORE_ADDR addr |
+ = extract_typed_address (valaddr + embedded_offset, type); |
+ |
+ fprintf_filtered (stream, "@"); |
+ fputs_filtered (paddress (gdbarch, addr), stream); |
+ if (options->deref_ref) |
+ fputs_filtered (": ", stream); |
+ } |
+ /* De-reference the reference. */ |
+ if (options->deref_ref) |
+ { |
+ if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF) |
+ { |
+ struct value *deref_val; |
+ |
+ deref_val = coerce_ref_if_computed (original_value); |
+ if (deref_val != NULL) |
+ { |
+ /* More complicated computed references are not supported. */ |
+ gdb_assert (embedded_offset == 0); |
+ } |
+ else |
+ deref_val = value_at (TYPE_TARGET_TYPE (type), |
+ unpack_pointer (type, |
+ (valaddr |
+ + embedded_offset))); |
+ |
+ common_val_print (deref_val, stream, recurse, options, |
+ current_language); |
+ } |
+ else |
+ fputs_filtered ("???", stream); |
+ } |
+ break; |
+ |
+ case TYPE_CODE_ENUM: |
+ if (options->format) |
+ { |
+ val_print_scalar_formatted (type, valaddr, embedded_offset, |
+ original_value, options, 0, stream); |
+ break; |
+ } |
+ len = TYPE_NFIELDS (type); |
+ val = unpack_long (type, valaddr + embedded_offset); |
+ for (i = 0; i < len; i++) |
+ { |
+ QUIT; |
+ if (val == TYPE_FIELD_ENUMVAL (type, i)) |
+ { |
+ break; |
+ } |
+ } |
+ if (i < len) |
+ { |
+ fputs_filtered (TYPE_FIELD_NAME (type, i), stream); |
+ } |
+ else if (TYPE_FLAG_ENUM (type)) |
+ { |
+ int first = 1; |
+ |
+ /* We have a "flag" enum, so we try to decompose it into |
+ pieces as appropriate. A flag enum has disjoint |
+ constants by definition. */ |
+ fputs_filtered ("(", stream); |
+ for (i = 0; i < len; ++i) |
+ { |
+ QUIT; |
+ |
+ if ((val & TYPE_FIELD_ENUMVAL (type, i)) != 0) |
+ { |
+ if (!first) |
+ fputs_filtered (" | ", stream); |
+ first = 0; |
+ |
+ val &= ~TYPE_FIELD_ENUMVAL (type, i); |
+ fputs_filtered (TYPE_FIELD_NAME (type, i), stream); |
+ } |
+ } |
+ |
+ if (first || val != 0) |
+ { |
+ if (!first) |
+ fputs_filtered (" | ", stream); |
+ fputs_filtered ("unknown: ", stream); |
+ print_longest (stream, 'd', 0, val); |
+ } |
+ |
+ fputs_filtered (")", stream); |
+ } |
+ else |
+ print_longest (stream, 'd', 0, val); |
+ break; |
+ |
+ case TYPE_CODE_FLAGS: |
+ if (options->format) |
+ val_print_scalar_formatted (type, valaddr, embedded_offset, |
+ original_value, options, 0, stream); |
+ else |
+ val_print_type_code_flags (type, valaddr + embedded_offset, |
+ stream); |
+ break; |
+ |
+ case TYPE_CODE_FUNC: |
+ case TYPE_CODE_METHOD: |
+ if (options->format) |
+ { |
+ val_print_scalar_formatted (type, valaddr, embedded_offset, |
+ original_value, options, 0, stream); |
+ break; |
+ } |
+ /* FIXME, we should consider, at least for ANSI C language, |
+ eliminating the distinction made between FUNCs and POINTERs |
+ to FUNCs. */ |
+ fprintf_filtered (stream, "{"); |
+ type_print (type, "", stream, -1); |
+ fprintf_filtered (stream, "} "); |
+ /* Try to print what function it points to, and its address. */ |
+ print_address_demangle (options, gdbarch, address, stream, demangle); |
+ break; |
+ |
+ case TYPE_CODE_BOOL: |
+ if (options->format || options->output_format) |
+ { |
+ struct value_print_options opts = *options; |
+ opts.format = (options->format ? options->format |
+ : options->output_format); |
+ val_print_scalar_formatted (type, valaddr, embedded_offset, |
+ original_value, &opts, 0, stream); |
+ } |
+ else |
+ { |
+ val = unpack_long (type, valaddr + embedded_offset); |
+ if (val == 0) |
+ fputs_filtered (decorations->false_name, stream); |
+ else if (val == 1) |
+ fputs_filtered (decorations->true_name, stream); |
+ else |
+ print_longest (stream, 'd', 0, val); |
+ } |
+ break; |
+ |
+ case TYPE_CODE_RANGE: |
+ /* FIXME: create_range_type does not set the unsigned bit in a |
+ range type (I think it probably should copy it from the |
+ target type), so we won't print values which are too large to |
+ fit in a signed integer correctly. */ |
+ /* FIXME: Doesn't handle ranges of enums correctly. (Can't just |
+ print with the target type, though, because the size of our |
+ type and the target type might differ). */ |
+ |
+ /* FALLTHROUGH */ |
+ |
+ case TYPE_CODE_INT: |
+ if (options->format || options->output_format) |
+ { |
+ struct value_print_options opts = *options; |
+ |
+ opts.format = (options->format ? options->format |
+ : options->output_format); |
+ val_print_scalar_formatted (type, valaddr, embedded_offset, |
+ original_value, &opts, 0, stream); |
+ } |
+ else |
+ val_print_type_code_int (type, valaddr + embedded_offset, stream); |
+ break; |
+ |
+ case TYPE_CODE_CHAR: |
+ if (options->format || options->output_format) |
+ { |
+ struct value_print_options opts = *options; |
+ |
+ opts.format = (options->format ? options->format |
+ : options->output_format); |
+ val_print_scalar_formatted (type, valaddr, embedded_offset, |
+ original_value, &opts, 0, stream); |
+ } |
+ else |
+ { |
+ val = unpack_long (type, valaddr + embedded_offset); |
+ if (TYPE_UNSIGNED (type)) |
+ fprintf_filtered (stream, "%u", (unsigned int) val); |
+ else |
+ fprintf_filtered (stream, "%d", (int) val); |
+ fputs_filtered (" ", stream); |
+ LA_PRINT_CHAR (val, unresolved_type, stream); |
+ } |
+ break; |
+ |
+ case TYPE_CODE_FLT: |
+ if (options->format) |
+ { |
+ val_print_scalar_formatted (type, valaddr, embedded_offset, |
+ original_value, options, 0, stream); |
+ } |
+ else |
+ { |
+ print_floating (valaddr + embedded_offset, type, stream); |
+ } |
+ break; |
+ |
+ case TYPE_CODE_DECFLOAT: |
+ if (options->format) |
+ val_print_scalar_formatted (type, valaddr, embedded_offset, |
+ original_value, options, 0, stream); |
+ else |
+ print_decimal_floating (valaddr + embedded_offset, |
+ type, stream); |
+ break; |
+ |
+ case TYPE_CODE_VOID: |
+ fputs_filtered (decorations->void_name, stream); |
+ break; |
+ |
+ case TYPE_CODE_ERROR: |
+ fprintf_filtered (stream, "%s", TYPE_ERROR_NAME (type)); |
+ break; |
+ |
+ case TYPE_CODE_UNDEF: |
+ /* This happens (without TYPE_FLAG_STUB set) on systems which |
+ don't use dbx xrefs (NO_DBX_XREFS in gcc) if a file has a |
+ "struct foo *bar" and no complete type for struct foo in that |
+ file. */ |
+ fprintf_filtered (stream, _("<incomplete type>")); |
+ break; |
+ |
+ case TYPE_CODE_COMPLEX: |
+ fprintf_filtered (stream, "%s", decorations->complex_prefix); |
+ if (options->format) |
+ val_print_scalar_formatted (TYPE_TARGET_TYPE (type), |
+ valaddr, embedded_offset, |
+ original_value, options, 0, stream); |
+ else |
+ print_floating (valaddr + embedded_offset, |
+ TYPE_TARGET_TYPE (type), |
+ stream); |
+ fprintf_filtered (stream, "%s", decorations->complex_infix); |
+ if (options->format) |
+ val_print_scalar_formatted (TYPE_TARGET_TYPE (type), |
+ valaddr, |
+ embedded_offset |
+ + TYPE_LENGTH (TYPE_TARGET_TYPE (type)), |
+ original_value, |
+ options, 0, stream); |
+ else |
+ print_floating (valaddr + embedded_offset |
+ + TYPE_LENGTH (TYPE_TARGET_TYPE (type)), |
+ TYPE_TARGET_TYPE (type), |
+ stream); |
+ fprintf_filtered (stream, "%s", decorations->complex_suffix); |
+ break; |
+ |
+ case TYPE_CODE_UNION: |
+ case TYPE_CODE_STRUCT: |
+ case TYPE_CODE_METHODPTR: |
+ default: |
+ error (_("Unhandled type code %d in symbol table."), |
+ TYPE_CODE (type)); |
+ } |
+ gdb_flush (stream); |
+} |
+ |
/* Print using the given LANGUAGE the data of type TYPE located at |
VALADDR + EMBEDDED_OFFSET (within GDB), which came from the |
inferior at address ADDRESS + EMBEDDED_OFFSET, onto stdio stream |
@@ -330,12 +688,9 @@ val_print_invalid_address (struct ui_file *stream) |
RECURSE indicates the amount of indentation to supply before |
continuation lines; this amount is roughly twice the value of |
- RECURSE. |
- |
- If the data is printed as a string, returns the number of string |
- characters printed. */ |
+ RECURSE. */ |
-int |
+void |
val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, |
CORE_ADDR address, struct ui_file *stream, int recurse, |
const struct value *val, |
@@ -361,11 +716,11 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, |
{ |
fprintf_filtered (stream, _("<incomplete type>")); |
gdb_flush (stream); |
- return (0); |
+ return; |
} |
if (!valprint_check_validity (stream, real_type, embedded_offset, val)) |
- return 0; |
+ return; |
if (!options->raw) |
{ |
@@ -373,7 +728,7 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, |
address, stream, recurse, |
val, options, language); |
if (ret) |
- return ret; |
+ return; |
} |
/* Handle summary mode. If the value is a scalar, print it; |
@@ -381,19 +736,17 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, |
if (options->summary && !scalar_type_p (type)) |
{ |
fprintf_filtered (stream, "..."); |
- return 0; |
+ return; |
} |
TRY_CATCH (except, RETURN_MASK_ERROR) |
{ |
- ret = language->la_val_print (type, valaddr, embedded_offset, address, |
- stream, recurse, val, |
- &local_opts); |
+ language->la_val_print (type, valaddr, embedded_offset, address, |
+ stream, recurse, val, |
+ &local_opts); |
} |
if (except.reason < 0) |
fprintf_filtered (stream, _("<error reading variable>")); |
- |
- return ret; |
} |
/* Check whether the value VAL is printable. Return 1 if it is; |
@@ -432,19 +785,16 @@ value_check_printable (struct value *val, struct ui_file *stream, |
/* Print using the given LANGUAGE the value VAL onto stream STREAM according |
to OPTIONS. |
- If the data are a string pointer, returns the number of string characters |
- printed. |
- |
This is a preferable interface to val_print, above, because it uses |
GDB's value mechanism. */ |
-int |
+void |
common_val_print (struct value *val, struct ui_file *stream, int recurse, |
const struct value_print_options *options, |
const struct language_defn *language) |
{ |
if (!value_check_printable (val, stream, options)) |
- return 0; |
+ return; |
if (language->la_language == language_ada) |
/* The value might have a dynamic type, which would cause trouble |
@@ -453,24 +803,21 @@ common_val_print (struct value *val, struct ui_file *stream, int recurse, |
get a fixed representation of our value. */ |
val = ada_to_fixed_value (val); |
- return val_print (value_type (val), value_contents_for_printing (val), |
- value_embedded_offset (val), value_address (val), |
- stream, recurse, |
- val, options, language); |
+ val_print (value_type (val), value_contents_for_printing (val), |
+ value_embedded_offset (val), value_address (val), |
+ stream, recurse, |
+ val, options, language); |
} |
/* Print on stream STREAM the value VAL according to OPTIONS. The value |
- is printed using the current_language syntax. |
+ is printed using the current_language syntax. */ |
- If the object printed is a string pointer, return the number of string |
- bytes printed. */ |
- |
-int |
+void |
value_print (struct value *val, struct ui_file *stream, |
const struct value_print_options *options) |
{ |
if (!value_check_printable (val, stream, options)) |
- return 0; |
+ return; |
if (!options->raw) |
{ |
@@ -482,10 +829,10 @@ value_print (struct value *val, struct ui_file *stream, |
val, options, current_language); |
if (r) |
- return r; |
+ return; |
} |
- return LA_VALUE_PRINT (val, stream, options); |
+ LA_VALUE_PRINT (val, stream, options); |
} |
/* Called by various <lang>_val_print routines to print |
@@ -545,6 +892,7 @@ val_print_type_code_flags (struct type *type, const gdb_byte *valaddr, |
} |
} |
fputs_filtered ("]", stream); |
+} |
/* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR, |
according to OPTIONS and SIZE on STREAM. Format i is not supported |
@@ -552,7 +900,6 @@ val_print_type_code_flags (struct type *type, const gdb_byte *valaddr, |
This is how the elements of an array or structure are printed |
with a format. */ |
-} |
void |
val_print_scalar_formatted (struct type *type, |
@@ -1161,6 +1508,31 @@ print_char_chars (struct ui_file *stream, struct type *type, |
} |
} |
+/* Print function pointer with inferior address ADDRESS onto stdio |
+ stream STREAM. */ |
+ |
+void |
+print_function_pointer_address (const struct value_print_options *options, |
+ struct gdbarch *gdbarch, |
+ CORE_ADDR address, |
+ struct ui_file *stream) |
+{ |
+ CORE_ADDR func_addr |
+ = gdbarch_convert_from_func_ptr_addr (gdbarch, address, |
+ ¤t_target); |
+ |
+ /* If the function pointer is represented by a description, print |
+ the address of the description. */ |
+ if (options->addressprint && func_addr != address) |
+ { |
+ fputs_filtered ("@", stream); |
+ fputs_filtered (paddress (gdbarch, address), stream); |
+ fputs_filtered (": ", stream); |
+ } |
+ print_address_demangle (options, gdbarch, func_addr, stream, demangle); |
+} |
+ |
+ |
/* Print on STREAM using the given OPTIONS the index for the element |
at INDEX of an array whose index type is INDEX_TYPE. */ |
@@ -1991,10 +2363,6 @@ val_print_string (struct type *elttype, const char *encoding, |
and then the error message. */ |
if (errcode == 0 || bytes_read > 0) |
{ |
- if (options->addressprint) |
- { |
- fputs_filtered (" ", stream); |
- } |
LA_PRINT_STRING (stream, elttype, buffer, bytes_read / width, |
encoding, force_ellipsis, options); |
} |
@@ -2003,13 +2371,13 @@ val_print_string (struct type *elttype, const char *encoding, |
{ |
if (errcode == EIO) |
{ |
- fprintf_filtered (stream, " <Address "); |
+ fprintf_filtered (stream, "<Address "); |
fputs_filtered (paddress (gdbarch, addr), stream); |
fprintf_filtered (stream, " out of bounds>"); |
} |
else |
{ |
- fprintf_filtered (stream, " <Error reading address "); |
+ fprintf_filtered (stream, "<Error reading address "); |
fputs_filtered (paddress (gdbarch, addr), stream); |
fprintf_filtered (stream, ": %s>", safe_strerror (errcode)); |
} |
@@ -2244,6 +2612,14 @@ Show printing of addresses."), NULL, |
show_addressprint, |
&setprintlist, &showprintlist); |
+ add_setshow_boolean_cmd ("symbol", class_support, |
+ &user_print_options.symbol_print, _("\ |
+Set printing of symbol names when printing pointers."), _("\ |
+Show printing of symbol names when printing pointers."), |
+ NULL, NULL, |
+ show_symbol_print, |
+ &setprintlist, &showprintlist); |
+ |
add_setshow_zuinteger_cmd ("input-radix", class_support, &input_radix_1, |
_("\ |
Set default input radix for entering numbers."), _("\ |