/* Support for printing C values for GDB, the GNU debugger.
Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2003, 2005, 2006, 2007
+ 1998, 1999, 2000, 2001, 2003, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GDB.
stream STREAM. */
static void
-print_function_pointer_address (CORE_ADDR address, struct ui_file *stream)
+print_function_pointer_address (struct gdbarch *gdbarch, CORE_ADDR address,
+ struct ui_file *stream, int addressprint)
{
- CORE_ADDR func_addr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
- address,
+ 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
if (addressprint && func_addr != address)
{
fputs_filtered ("@", stream);
- deprecated_print_address_numeric (address, 1, stream);
+ fputs_filtered (paddress (gdbarch, address), stream);
fputs_filtered (": ", stream);
}
- print_address_demangle (func_addr, stream, demangle);
+ print_address_demangle (gdbarch, func_addr, stream, demangle);
}
+/* A helper for textual_element_type. This checks the name of the
+ typedef. This is bogus but it isn't apparent that the compiler
+ provides us the help we may need. */
+
+static int
+textual_name (const char *name)
+{
+ return (!strcmp (name, "wchar_t")
+ || !strcmp (name, "char16_t")
+ || !strcmp (name, "char32_t"));
+}
+
/* Apply a heuristic to decide whether an array of TYPE or a pointer
to TYPE should be printed as a textual string. Return non-zero if
it should, or zero if it should be treated as an array of integers
static int
textual_element_type (struct type *type, char format)
{
- struct type *true_type = check_typedef (type);
+ struct type *true_type, *iter_type;
if (format != 0 && format != 's')
return 0;
+ /* We also rely on this for its side effect of setting up all the
+ typedef pointers. */
+ true_type = check_typedef (type);
+
/* TYPE_CODE_CHAR is always textual. */
if (TYPE_CODE (true_type) == TYPE_CODE_CHAR)
return 1;
+ /* Any other character-like types must be integral. */
+ if (TYPE_CODE (true_type) != TYPE_CODE_INT)
+ return 0;
+
+ /* We peel typedefs one by one, looking for a match. */
+ iter_type = type;
+ while (iter_type)
+ {
+ /* Check the name of the type. */
+ if (TYPE_NAME (iter_type) && textual_name (TYPE_NAME (iter_type)))
+ return 1;
+
+ if (TYPE_CODE (iter_type) != TYPE_CODE_TYPEDEF)
+ break;
+
+ /* Peel a single typedef. If the typedef doesn't have a target
+ type, we use check_typedef and hope the result is ok -- it
+ might be for C++, where wchar_t is a built-in type. */
+ if (TYPE_TARGET_TYPE (iter_type))
+ iter_type = TYPE_TARGET_TYPE (iter_type);
+ else
+ iter_type = check_typedef (iter_type);
+ }
+
if (format == 's')
{
/* Print this as a string if we can manage it. For now, no
/* Print data of type TYPE located at VALADDR (within GDB), which came from
the inferior at address ADDRESS, onto stdio stream STREAM according to
- FORMAT (a letter or 0 for natural format). The data at VALADDR is in
- target byte order.
+ OPTIONS. The data at VALADDR is in target byte order.
If the data are a string pointer, returns the number of string characters
- printed.
-
- If DEREF_REF is nonzero, then dereference references, otherwise just print
- them like pointers.
-
- The PRETTY parameter controls prettyprinting. */
+ printed. */
int
c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
- CORE_ADDR address, struct ui_file *stream, int format,
- int deref_ref, int recurse, enum val_prettyprint pretty)
+ CORE_ADDR address, struct ui_file *stream, int recurse,
+ const struct value_print_options *options)
{
+ 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;
+ struct type *elttype, *unresolved_elttype;
+ struct type *unresolved_type = type;
unsigned eltlen;
LONGEST val;
CORE_ADDR addr;
switch (TYPE_CODE (type))
{
case TYPE_CODE_ARRAY:
- elttype = check_typedef (TYPE_TARGET_TYPE (type));
- if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
+ unresolved_elttype = TYPE_TARGET_TYPE (type);
+ elttype = check_typedef (unresolved_elttype);
+ if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (unresolved_elttype) > 0)
{
eltlen = TYPE_LENGTH (elttype);
len = TYPE_LENGTH (type) / eltlen;
- if (prettyprint_arrays)
+ if (options->prettyprint_arrays)
{
print_spaces_filtered (2 + 2 * recurse, stream);
}
/* Print arrays of textual chars with a string syntax. */
- if (textual_element_type (elttype, format))
+ if (textual_element_type (unresolved_elttype, options->format))
{
/* If requested, look for the first null char and only print
elements up to it. */
- if (stop_print_at_null)
+ if (options->stop_print_at_null)
{
unsigned int temp_len;
- /* Look for a NULL char. */
for (temp_len = 0;
- (valaddr + embedded_offset)[temp_len]
- && temp_len < len && temp_len < print_max;
- temp_len++);
+ (temp_len < len
+ && temp_len < options->print_max
+ && extract_unsigned_integer (valaddr + embedded_offset
+ + temp_len * eltlen,
+ eltlen, byte_order) == 0);
+ ++temp_len)
+ ;
len = temp_len;
}
- LA_PRINT_STRING (stream, valaddr + embedded_offset, len, eltlen, 0);
+ LA_PRINT_STRING (stream, unresolved_elttype,
+ valaddr + embedded_offset, len, 0, options);
i = len;
}
else
i = 0;
}
val_print_array_elements (type, valaddr + embedded_offset, address, stream,
- format, deref_ref, recurse, pretty, i);
+ recurse, options, i);
fprintf_filtered (stream, "}");
}
break;
goto print_unpacked_pointer;
case TYPE_CODE_MEMBERPTR:
- if (format)
+ if (options->format)
{
- print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ print_scalar_formatted (valaddr + embedded_offset, type,
+ options, 0, stream);
break;
}
- cp_print_class_member (valaddr + embedded_offset,
- TYPE_DOMAIN_TYPE (type),
- stream, "&");
+ cp_print_class_member (valaddr + embedded_offset, type, stream, "&");
break;
case TYPE_CODE_METHODPTR:
break;
case TYPE_CODE_PTR:
- if (format && format != 's')
+ if (options->format && options->format != 's')
{
- print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ print_scalar_formatted (valaddr + embedded_offset, type,
+ options, 0, stream);
break;
}
- if (vtblprint && cp_is_vtbl_ptr_type (type))
+ if (options->vtblprint && cp_is_vtbl_ptr_type (type))
{
/* Print the unmangled name if desired. */
/* Print vtable entry - we only get here if we ARE using
-fvtable_thunks. (Otherwise, look under TYPE_CODE_STRUCT.) */
CORE_ADDR addr
= extract_typed_address (valaddr + embedded_offset, type);
- print_function_pointer_address (addr, stream);
+ print_function_pointer_address (gdbarch, addr, stream,
+ options->addressprint);
break;
}
- elttype = check_typedef (TYPE_TARGET_TYPE (type));
+ 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 (addr, stream);
+ print_function_pointer_address (gdbarch, addr, stream,
+ options->addressprint);
/* Return value is irrelevant except for string pointers. */
return (0);
}
- if (addressprint)
- {
- deprecated_print_address_numeric (addr, 1, stream);
- }
+ if (options->addressprint)
+ fputs_filtered (paddress (gdbarch, addr), stream);
/* For a pointer to a textual type, also print the string
pointed to, unless pointer is null. */
- /* FIXME: need to handle wchar_t here... */
- if (textual_element_type (elttype, format) && addr != 0)
+ if (textual_element_type (unresolved_elttype, options->format)
+ && addr != 0)
{
- i = val_print_string (addr, -1, TYPE_LENGTH (elttype), stream);
+ i = val_print_string (unresolved_elttype, addr, -1, stream,
+ options);
}
else if (cp_is_vtbl_member (type))
{
fputs_filtered (SYMBOL_PRINT_NAME (msymbol), stream);
fputs_filtered (">", stream);
}
- if (vt_address && vtblprint)
+ if (vt_address && options->vtblprint)
{
struct value *vt_val;
struct symbol *wsym = (struct symbol *) NULL;
int is_this_fld;
if (msymbol != NULL)
- wsym = lookup_symbol (DEPRECATED_SYMBOL_NAME (msymbol), block,
- VAR_DOMAIN, &is_this_fld, NULL);
+ wsym = lookup_symbol (SYMBOL_LINKAGE_NAME (msymbol), block,
+ VAR_DOMAIN, &is_this_fld);
if (wsym)
{
}
else
{
- wtype = TYPE_TARGET_TYPE (type);
+ wtype = unresolved_elttype;
}
vt_val = value_at (wtype, vt_address);
- common_val_print (vt_val, stream, format,
- deref_ref, recurse + 1, pretty);
- if (pretty)
+ common_val_print (vt_val, stream, recurse + 1, options,
+ current_language);
+ if (options->pretty)
{
fprintf_filtered (stream, "\n");
print_spaces_filtered (2 + 2 * recurse, stream);
case TYPE_CODE_REF:
elttype = check_typedef (TYPE_TARGET_TYPE (type));
- if (addressprint)
+ if (options->addressprint)
{
CORE_ADDR addr
= extract_typed_address (valaddr + embedded_offset, type);
fprintf_filtered (stream, "@");
- deprecated_print_address_numeric (addr, 1, stream);
- if (deref_ref)
+ fputs_filtered (paddress (gdbarch, addr), stream);
+ if (options->deref_ref)
fputs_filtered (": ", stream);
}
/* De-reference the reference. */
- if (deref_ref)
+ if (options->deref_ref)
{
if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF)
{
struct value *deref_val =
value_at
(TYPE_TARGET_TYPE (type),
- unpack_pointer (lookup_pointer_type (builtin_type_void),
- valaddr + embedded_offset));
- common_val_print (deref_val, stream, format, deref_ref,
- recurse, pretty);
+ unpack_pointer (type, valaddr + embedded_offset));
+ common_val_print (deref_val, stream, recurse, options,
+ current_language);
}
else
fputs_filtered ("???", stream);
break;
case TYPE_CODE_UNION:
- if (recurse && !unionprint)
+ if (recurse && !options->unionprint)
{
fprintf_filtered (stream, "{...}");
break;
/* Fall through. */
case TYPE_CODE_STRUCT:
/*FIXME: Abstract this away */
- if (vtblprint && cp_is_vtbl_ptr_type (type))
+ if (options->vtblprint && cp_is_vtbl_ptr_type (type))
{
/* Print the unmangled name if desired. */
/* Print vtable entry - we only get here if NOT using
CORE_ADDR addr
= extract_typed_address (valaddr + offset, field_type);
- print_function_pointer_address (addr, stream);
+ print_function_pointer_address (gdbarch, addr, stream,
+ options->addressprint);
}
else
- cp_print_value_fields (type, type, valaddr, embedded_offset, address, stream, format,
- recurse, pretty, NULL, 0);
+ cp_print_value_fields (type, type, valaddr, embedded_offset, address, stream,
+ recurse, options, NULL, 0);
break;
case TYPE_CODE_ENUM:
- if (format)
+ if (options->format)
{
- print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ print_scalar_formatted (valaddr + embedded_offset, type,
+ options, 0, stream);
break;
}
len = TYPE_NFIELDS (type);
break;
case TYPE_CODE_FLAGS:
- if (format)
- print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ if (options->format)
+ print_scalar_formatted (valaddr + embedded_offset, type,
+ options, 0, stream);
else
val_print_type_code_flags (type, valaddr + embedded_offset, stream);
break;
case TYPE_CODE_FUNC:
case TYPE_CODE_METHOD:
- if (format)
+ if (options->format)
{
- print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ print_scalar_formatted (valaddr + embedded_offset, type,
+ options, 0, stream);
break;
}
/* FIXME, we should consider, at least for ANSI C language, eliminating
type_print (type, "", stream, -1);
fprintf_filtered (stream, "} ");
/* Try to print what function it points to, and its address. */
- print_address_demangle (address, stream, demangle);
+ print_address_demangle (gdbarch, address, stream, demangle);
break;
case TYPE_CODE_BOOL:
- format = format ? format : output_format;
- if (format)
- print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ if (options->format || options->output_format)
+ {
+ struct value_print_options opts = *options;
+ opts.format = (options->format ? options->format
+ : options->output_format);
+ print_scalar_formatted (valaddr + embedded_offset, type,
+ &opts, 0, stream);
+ }
else
{
val = unpack_long (type, valaddr + embedded_offset);
/* FALLTHROUGH */
case TYPE_CODE_INT:
- format = format ? format : output_format;
- if (format)
+ if (options->format || options->output_format)
{
- print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ struct value_print_options opts = *options;
+ opts.format = (options->format ? options->format
+ : options->output_format);
+ print_scalar_formatted (valaddr + embedded_offset, type,
+ &opts, 0, stream);
}
else
{
Since we don't know whether the value is really intended to
be used as an integer or a character, print the character
equivalent as well. */
- if (textual_element_type (type, format))
+ if (textual_element_type (unresolved_type, options->format))
{
fputs_filtered (" ", stream);
LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr + embedded_offset),
- stream);
+ unresolved_type, stream);
}
}
break;
case TYPE_CODE_CHAR:
- format = format ? format : output_format;
- if (format)
+ if (options->format || options->output_format)
{
- print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ struct value_print_options opts = *options;
+ opts.format = (options->format ? options->format
+ : options->output_format);
+ print_scalar_formatted (valaddr + embedded_offset, type,
+ &opts, 0, stream);
}
else
{
else
fprintf_filtered (stream, "%d", (int) val);
fputs_filtered (" ", stream);
- LA_PRINT_CHAR ((unsigned char) val, stream);
+ LA_PRINT_CHAR ((unsigned char) val, unresolved_type, stream);
}
break;
case TYPE_CODE_FLT:
- if (format)
+ if (options->format)
{
- print_scalar_formatted (valaddr + embedded_offset, type, format, 0, stream);
+ print_scalar_formatted (valaddr + embedded_offset, type,
+ options, 0, stream);
}
else
{
}
break;
+ case TYPE_CODE_DECFLOAT:
+ if (options->format)
+ print_scalar_formatted (valaddr + embedded_offset, type,
+ options, 0, stream);
+ else
+ print_decimal_floating (valaddr + embedded_offset, type, stream);
+ break;
+
case TYPE_CODE_VOID:
fprintf_filtered (stream, "void");
break;
break;
case TYPE_CODE_COMPLEX:
- if (format)
+ if (options->format)
print_scalar_formatted (valaddr + embedded_offset,
TYPE_TARGET_TYPE (type),
- format, 0, stream);
+ options, 0, stream);
else
print_floating (valaddr + embedded_offset, TYPE_TARGET_TYPE (type),
stream);
fprintf_filtered (stream, " + ");
- if (format)
+ if (options->format)
print_scalar_formatted (valaddr + embedded_offset
+ TYPE_LENGTH (TYPE_TARGET_TYPE (type)),
TYPE_TARGET_TYPE (type),
- format, 0, stream);
+ options, 0, stream);
else
print_floating (valaddr + embedded_offset
+ TYPE_LENGTH (TYPE_TARGET_TYPE (type)),
}
\f
int
-c_value_print (struct value *val, struct ui_file *stream, int format,
- enum val_prettyprint pretty)
+c_value_print (struct value *val, struct ui_file *stream,
+ const struct value_print_options *options)
{
- struct type *type, *real_type;
+ struct type *type, *real_type, *val_type;
int full, top, using_enc;
+ struct value_print_options opts = *options;
+
+ opts.deref_ref = 1;
/* If it is a pointer, indicate what it points to.
C++: if it is a member pointer, we will take care
of that when we print it. */
- type = check_typedef (value_type (val));
+ /* Preserve the original type before stripping typedefs. We prefer
+ to pass down the original type when possible, but for local
+ checks it is better to look past the typedefs. */
+ val_type = value_type (val);
+ type = check_typedef (val_type);
if (TYPE_CODE (type) == TYPE_CODE_PTR
|| TYPE_CODE (type) == TYPE_CODE_REF)
/* Hack: remove (char *) for char strings. Their
type is indicated by the quoted string anyway.
(Don't use textual_element_type here; quoted strings
- are always exactly (char *). */
- if (TYPE_CODE (type) == TYPE_CODE_PTR
- && TYPE_NAME (type) == NULL
- && TYPE_NAME (TYPE_TARGET_TYPE (type)) != NULL
- && strcmp (TYPE_NAME (TYPE_TARGET_TYPE (type)), "char") == 0)
+ are always exactly (char *), (wchar_t *), or the like. */
+ if (TYPE_CODE (val_type) == TYPE_CODE_PTR
+ && TYPE_NAME (val_type) == NULL
+ && TYPE_NAME (TYPE_TARGET_TYPE (val_type)) != NULL
+ && (strcmp (TYPE_NAME (TYPE_TARGET_TYPE (val_type)), "char") == 0
+ || textual_name (TYPE_NAME (TYPE_TARGET_TYPE (val_type)))))
{
/* Print nothing */
}
- else if (objectprint && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
+ else if (options->objectprint
+ && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
{
if (TYPE_CODE(type) == TYPE_CODE_REF)
}
type_print (type, "", stream, -1);
fprintf_filtered (stream, ") ");
+ val_type = type;
}
else
{
if (!value_initialized (val))
fprintf_filtered (stream, " [uninitialized] ");
- if (objectprint && (TYPE_CODE (type) == TYPE_CODE_CLASS))
+ if (options->objectprint && (TYPE_CODE (type) == TYPE_CODE_CLASS))
{
/* Attempt to determine real type of object */
real_type = value_rtti_type (val, &full, &top, &using_enc);
/* Print out object: enclosing type is same as real_type if full */
return val_print (value_enclosing_type (val),
value_contents_all (val), 0,
- VALUE_ADDRESS (val), stream, format, 1, 0, pretty);
+ value_address (val), stream, 0,
+ &opts, current_language);
/* Note: When we look up RTTI entries, we don't get any information on
const or volatile attributes */
}
TYPE_NAME (value_enclosing_type (val)));
return val_print (value_enclosing_type (val),
value_contents_all (val), 0,
- VALUE_ADDRESS (val), stream, format, 1, 0, pretty);
+ value_address (val), stream, 0,
+ &opts, current_language);
}
/* Otherwise, we end up at the return outside this "if" */
}
- return val_print (type, value_contents_all (val),
+ return val_print (val_type, value_contents_all (val),
value_embedded_offset (val),
- VALUE_ADDRESS (val) + value_offset (val),
- stream, format, 1, 0, pretty);
+ value_address (val),
+ stream, 0, &opts, current_language);
}