X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fvalprint.c;h=8893830ff3d063b5dce9876a61dc0abd7a340483;hb=2e0569314c2ee9e5635899d47b0bc0a4b9b08d8d;hp=b26924a6ef4a995e8cb6f890c25c130980ef444f;hpb=3b2b8feaf4aaa62c7d55ad845c3ff34165a3af22;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/valprint.c b/gdb/valprint.c index b26924a6ef..8893830ff3 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -1,8 +1,6 @@ /* Print values for GDB, the GNU debugger. - Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2015 Free Software Foundation, Inc. This file is part of GDB. @@ -20,7 +18,6 @@ along with this program. If not, see . */ #include "defs.h" -#include "gdb_string.h" #include "symtab.h" #include "gdbtypes.h" #include "value.h" @@ -32,20 +29,57 @@ #include "valprint.h" #include "floatformat.h" #include "doublest.h" -#include "exceptions.h" #include "dfp.h" -#include "python/python.h" +#include "extension.h" #include "ada-lang.h" #include "gdb_obstack.h" #include "charset.h" #include -#include +/* Maximum number of wchars returned from wchar_iterate. */ +#define MAX_WCHARS 4 + +/* A convenience macro to compute the size of a wchar_t buffer containing X + characters. */ +#define WCHAR_BUFLEN(X) ((X) * sizeof (gdb_wchar_t)) + +/* Character buffer size saved while iterating over wchars. */ +#define WCHAR_BUFLEN_MAX WCHAR_BUFLEN (MAX_WCHARS) + +/* A structure to encapsulate state information from iterated + character conversions. */ +struct converted_character +{ + /* The number of characters converted. */ + int num_chars; + + /* The result of the conversion. See charset.h for more. */ + enum wchar_iterate_result result; + + /* The (saved) converted character(s). */ + gdb_wchar_t chars[WCHAR_BUFLEN_MAX]; + + /* The first converted target byte. */ + const gdb_byte *buf; + + /* The number of bytes converted. */ + size_t buflen; + + /* How many times this character(s) is repeated. */ + int repeat_count; +}; + +typedef struct converted_character converted_character_d; +DEF_VEC_O (converted_character_d); + +/* Command lists for set/show print raw. */ +struct cmd_list_element *setprintrawlist; +struct cmd_list_element *showprintrawlist; /* Prototypes for local functions */ static int partial_memory_read (CORE_ADDR memaddr, gdb_byte *myaddr, - int len, int *errnoptr); + int len, int *errptr); static void show_print (char *, int); @@ -69,9 +103,9 @@ void _initialize_valprint (void); struct value_print_options user_print_options = { - Val_pretty_default, /* pretty */ - 0, /* prettyprint_arrays */ - 0, /* prettyprint_structs */ + Val_prettyformat_default, /* prettyformat */ + 0, /* prettyformat_arrays */ + 0, /* prettyformat_structs */ 0, /* vtblprint */ 1, /* unionprint */ 1, /* addressprint */ @@ -81,13 +115,13 @@ struct value_print_options user_print_options = 0, /* output_format */ 0, /* format */ 0, /* stop_print_at_null */ - 0, /* inspect_it */ 0, /* print_array_indexes */ 0, /* deref_ref */ 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. */ @@ -98,12 +132,12 @@ get_user_print_options (struct value_print_options *opts) } /* Initialize *OPTS to be a copy of the user print options, but with - pretty-printing disabled. */ + pretty-formatting disabled. */ void -get_raw_print_options (struct value_print_options *opts) +get_no_prettyformat_print_options (struct value_print_options *opts) { *opts = user_print_options; - opts->pretty = Val_no_prettyprint; + opts->prettyformat = Val_no_prettyformat; } /* Initialize *OPTS to be a copy of the user print options, but using @@ -186,19 +220,19 @@ show_stop_print_at_null (struct ui_file *file, int from_tty, /* Controls pretty printing of structures. */ static void -show_prettyprint_structs (struct ui_file *file, int from_tty, +show_prettyformat_structs (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("Prettyprinting of structures is %s.\n"), value); + fprintf_filtered (file, _("Pretty formatting of structures is %s.\n"), value); } /* Controls pretty printing of arrays. */ static void -show_prettyprint_arrays (struct ui_file *file, int from_tty, +show_prettyformat_arrays (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) { - fprintf_filtered (file, _("Prettyprinting of arrays is %s.\n"), value); + fprintf_filtered (file, _("Pretty formatting of arrays is %s.\n"), value); } /* If nonzero, causes unions inside structures or other unions to be @@ -221,20 +255,30 @@ 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, we want to print scalar arguments, but not aggregate arguments. This function distinguishes between the two. */ -static int -scalar_type_p (struct type *type) +int +val_print_scalar_type_p (struct type *type) { - CHECK_TYPEDEF (type); + type = check_typedef (type); while (TYPE_CODE (type) == TYPE_CODE_REF) { type = TYPE_TARGET_TYPE (type); - CHECK_TYPEDEF (type); + type = check_typedef (type); } switch (TYPE_CODE (type)) { @@ -243,39 +287,31 @@ scalar_type_p (struct type *type) case TYPE_CODE_UNION: case TYPE_CODE_SET: case TYPE_CODE_STRING: - case TYPE_CODE_BITSTRING: return 0; default: return 1; } } -/* 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, const struct value *val) { - CHECK_TYPEDEF (type); + type = check_typedef (type); if (TYPE_CODE (type) != TYPE_CODE_UNION && TYPE_CODE (type) != TYPE_CODE_STRUCT && TYPE_CODE (type) != TYPE_CODE_ARRAY) { - if (!value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset, - TARGET_CHAR_BIT * TYPE_LENGTH (type))) + if (value_bits_any_optimized_out (val, + TARGET_CHAR_BIT * embedded_offset, + TARGET_CHAR_BIT * TYPE_LENGTH (type))) { - val_print_optimized_out (stream); + val_print_optimized_out (val, stream); return 0; } @@ -297,9 +333,18 @@ valprint_check_validity (struct ui_file *stream, } void -val_print_optimized_out (struct ui_file *stream) +val_print_optimized_out (const struct value *val, struct ui_file *stream) +{ + if (val != NULL && value_lval_const (val) == lval_register) + val_print_not_saved (stream); + else + fprintf_filtered (stream, _("")); +} + +void +val_print_not_saved (struct ui_file *stream) { - fprintf_filtered (stream, _("")); + fprintf_filtered (stream, _("")); } void @@ -314,6 +359,546 @@ val_print_invalid_address (struct ui_file *stream) fprintf_filtered (stream, _("")); } +/* Print a pointer based on the type of its target. + + Arguments to this functions are roughly the same as those in + generic_val_print. A difference is that ADDRESS is the address to print, + with embedded_offset already added. ELTTYPE represents + the pointed type after check_typedef. */ + +static void +print_unpacked_pointer (struct type *type, struct type *elttype, + CORE_ADDR address, struct ui_file *stream, + const struct value_print_options *options) +{ + struct gdbarch *gdbarch = get_type_arch (type); + + if (TYPE_CODE (elttype) == TYPE_CODE_FUNC) + { + /* Try to print what function it points to. */ + print_function_pointer_address (options, gdbarch, address, stream); + return; + } + + if (options->symbol_print) + print_address_demangle (options, gdbarch, address, stream, demangle); + else if (options->addressprint) + fputs_filtered (paddress (gdbarch, address), stream); +} + +/* generic_val_print helper for TYPE_CODE_ARRAY. */ + +static void +generic_val_print_array (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) +{ + struct type *unresolved_elttype = TYPE_TARGET_TYPE (type); + struct 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->prettyformat_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, "}"); + } + else + { + /* Array of unspecified length: treat like pointer to first elt. */ + print_unpacked_pointer (type, elttype, address + embedded_offset, stream, + options); + } + +} + +/* generic_val_print helper for TYPE_CODE_PTR. */ + +static void +generic_val_print_ptr (struct type *type, const gdb_byte *valaddr, + int embedded_offset, struct ui_file *stream, + const struct value *original_value, + const struct value_print_options *options) +{ + if (options->format && options->format != 's') + { + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); + } + else + { + struct type *unresolved_elttype = TYPE_TARGET_TYPE(type); + struct type *elttype = check_typedef (unresolved_elttype); + CORE_ADDR addr = unpack_pointer (type, valaddr + embedded_offset); + + print_unpacked_pointer (type, elttype, addr, stream, options); + } +} + + +/* generic_val_print helper for TYPE_CODE_MEMBERPTR. */ + +static void +generic_val_print_memberptr (struct type *type, const gdb_byte *valaddr, + int embedded_offset, struct ui_file *stream, + const struct value *original_value, + const struct value_print_options *options) +{ + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); +} + +/* generic_val_print helper for TYPE_CODE_REF. */ + +static void +generic_val_print_ref (struct type *type, const gdb_byte *valaddr, + int embedded_offset, struct ui_file *stream, int recurse, + const struct value *original_value, + const struct value_print_options *options) +{ + struct gdbarch *gdbarch = get_type_arch (type); + struct type *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); + } +} + +/* generic_val_print helper for TYPE_CODE_ENUM. */ + +static void +generic_val_print_enum (struct type *type, const gdb_byte *valaddr, + int embedded_offset, struct ui_file *stream, + const struct value *original_value, + const struct value_print_options *options) +{ + unsigned int i; + unsigned int len; + LONGEST val; + + if (options->format) + { + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); + return; + } + 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); +} + +/* generic_val_print helper for TYPE_CODE_FLAGS. */ + +static void +generic_val_print_flags (struct type *type, const gdb_byte *valaddr, + int embedded_offset, struct ui_file *stream, + const struct value *original_value, + const struct value_print_options *options) + +{ + 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); +} + +/* generic_val_print helper for TYPE_CODE_FUNC and TYPE_CODE_METHOD. */ + +static void +generic_val_print_func (struct type *type, const gdb_byte *valaddr, + int embedded_offset, CORE_ADDR address, + struct ui_file *stream, + const struct value *original_value, + const struct value_print_options *options) +{ + struct gdbarch *gdbarch = get_type_arch (type); + + if (options->format) + { + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); + } + else + { + /* 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); + } +} + +/* generic_val_print helper for TYPE_CODE_BOOL. */ + +static void +generic_val_print_bool (struct type *type, const gdb_byte *valaddr, + int embedded_offset, struct ui_file *stream, + const struct value *original_value, + const struct value_print_options *options, + const struct generic_val_print_decorations *decorations) +{ + LONGEST val; + + 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); + } +} + +/* generic_val_print helper for TYPE_CODE_INT. */ + +static void +generic_val_print_int (struct type *type, const gdb_byte *valaddr, + int embedded_offset, struct ui_file *stream, + const struct value *original_value, + const struct value_print_options *options) +{ + 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); +} + +/* generic_val_print helper for TYPE_CODE_CHAR. */ + +static void +generic_val_print_char (struct type *type, struct type *unresolved_type, + const gdb_byte *valaddr, int embedded_offset, + struct ui_file *stream, + const struct value *original_value, + const struct value_print_options *options) +{ + LONGEST val; + + 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); + } +} + +/* generic_val_print helper for TYPE_CODE_FLT. */ + +static void +generic_val_print_float (struct type *type, const gdb_byte *valaddr, + int embedded_offset, struct ui_file *stream, + const struct value *original_value, + const struct value_print_options *options) +{ + if (options->format) + { + val_print_scalar_formatted (type, valaddr, embedded_offset, + original_value, options, 0, stream); + } + else + { + print_floating (valaddr + embedded_offset, type, stream); + } +} + +/* generic_val_print helper for TYPE_CODE_DECFLOAT. */ + +static void +generic_val_print_decfloat (struct type *type, const gdb_byte *valaddr, + int embedded_offset, struct ui_file *stream, + const struct value *original_value, + const struct value_print_options *options) +{ + 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); +} + +/* generic_val_print helper for TYPE_CODE_COMPLEX. */ + +static void +generic_val_print_complex (struct type *type, const gdb_byte *valaddr, + int embedded_offset, struct ui_file *stream, + const struct value *original_value, + const struct value_print_options *options, + const struct generic_val_print_decorations + *decorations) +{ + 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); +} + +/* 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 type *unresolved_type = type; + + type = check_typedef (type); + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: + generic_val_print_array (type, valaddr, embedded_offset, address, stream, + recurse, original_value, options); + break; + + case TYPE_CODE_MEMBERPTR: + generic_val_print_memberptr (type, valaddr, embedded_offset, stream, + original_value, options); + break; + + case TYPE_CODE_PTR: + generic_val_print_ptr (type, valaddr, embedded_offset, stream, + original_value, options); + break; + + case TYPE_CODE_REF: + generic_val_print_ref (type, valaddr, embedded_offset, stream, recurse, + original_value, options); + break; + + case TYPE_CODE_ENUM: + generic_val_print_enum (type, valaddr, embedded_offset, stream, + original_value, options); + break; + + case TYPE_CODE_FLAGS: + generic_val_print_flags (type, valaddr, embedded_offset, stream, + original_value, options); + break; + + case TYPE_CODE_FUNC: + case TYPE_CODE_METHOD: + generic_val_print_func (type, valaddr, embedded_offset, address, stream, + original_value, options); + break; + + case TYPE_CODE_BOOL: + generic_val_print_bool (type, valaddr, embedded_offset, stream, + original_value, options, decorations); + break; + + case TYPE_CODE_RANGE: + /* FIXME: create_static_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: + generic_val_print_int (type, valaddr, embedded_offset, stream, + original_value, options); + break; + + case TYPE_CODE_CHAR: + generic_val_print_char (type, unresolved_type, valaddr, embedded_offset, + stream, original_value, options); + break; + + case TYPE_CODE_FLT: + generic_val_print_float (type, valaddr, embedded_offset, stream, + original_value, options); + break; + + case TYPE_CODE_DECFLOAT: + generic_val_print_decfloat (type, valaddr, embedded_offset, stream, + original_value, options); + 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, _("")); + break; + + case TYPE_CODE_COMPLEX: + generic_val_print_complex (type, valaddr, embedded_offset, stream, + original_value, options, decorations); + 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 @@ -332,26 +917,22 @@ 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. + RECURSE. */ - If the data is printed as a string, returns the number of string - characters printed. */ - -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, const struct value_print_options *options, const struct language_defn *language) { - volatile struct gdb_exception except; int ret = 0; struct value_print_options local_opts = *options; struct type *real_type = check_typedef (type); - if (local_opts.pretty == Val_pretty_default) - local_opts.pretty = (local_opts.prettyprint_structs - ? Val_prettyprint : Val_no_prettyprint); + if (local_opts.prettyformat == Val_prettyformat_default) + local_opts.prettyformat = (local_opts.prettyformat_structs + ? Val_prettyformat : Val_no_prettyformat); QUIT; @@ -363,47 +944,49 @@ val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, { fprintf_filtered (stream, _("")); gdb_flush (stream); - return (0); + return; } if (!valprint_check_validity (stream, real_type, embedded_offset, val)) - return 0; + return; if (!options->raw) { - ret = apply_val_pretty_printer (type, valaddr, embedded_offset, - address, stream, recurse, - val, options, language); + ret = apply_ext_lang_val_pretty_printer (type, valaddr, embedded_offset, + address, stream, recurse, + val, options, language); if (ret) - return ret; + return; } /* Handle summary mode. If the value is a scalar, print it; otherwise, print an ellipsis. */ - if (options->summary && !scalar_type_p (type)) + if (options->summary && !val_print_scalar_type_p (type)) { fprintf_filtered (stream, "..."); - return 0; + return; } - TRY_CATCH (except, RETURN_MASK_ERROR) + TRY { - 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, _("")); - - return ret; + CATCH (except, RETURN_MASK_ERROR) + { + fprintf_filtered (stream, _("")); + } + END_CATCH } /* Check whether the value VAL is printable. Return 1 if it is; - return 0 and print an appropriate error message to STREAM if it - is not. */ + return 0 and print an appropriate error message to STREAM according to + OPTIONS if it is not. */ static int -value_check_printable (struct value *val, struct ui_file *stream) +value_check_printable (struct value *val, struct ui_file *stream, + const struct value_print_options *options) { if (val == 0) { @@ -413,7 +996,19 @@ value_check_printable (struct value *val, struct ui_file *stream) if (value_entirely_optimized_out (val)) { - val_print_optimized_out (stream); + if (options->summary && !val_print_scalar_type_p (value_type (val))) + fprintf_filtered (stream, "..."); + else + val_print_optimized_out (val, stream); + return 0; + } + + if (value_entirely_unavailable (val)) + { + if (options->summary && !val_print_scalar_type_p (value_type (val))) + fprintf_filtered (stream, "..."); + else + val_print_unavailable (stream); return 0; } @@ -430,19 +1025,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)) - return 0; + if (!value_check_printable (val, stream, options)) + return; if (language->la_language == language_ada) /* The value might have a dynamic type, which would cause trouble @@ -451,39 +1043,37 @@ 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)) - return 0; + if (!value_check_printable (val, stream, options)) + return; if (!options->raw) { - int r = apply_val_pretty_printer (value_type (val), - value_contents_for_printing (val), - value_embedded_offset (val), - value_address (val), - stream, 0, - val, options, current_language); + int r + = apply_ext_lang_val_pretty_printer (value_type (val), + value_contents_for_printing (val), + value_embedded_offset (val), + value_address (val), + stream, 0, + 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 _val_print routines to print @@ -543,6 +1133,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 @@ -550,7 +1141,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, @@ -578,9 +1168,10 @@ val_print_scalar_formatted (struct type *type, /* A scalar object that does not have all bits available can't be printed, because all bits contribute to its representation. */ - if (!value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset, - TARGET_CHAR_BIT * TYPE_LENGTH (type))) - val_print_optimized_out (stream); + if (value_bits_any_optimized_out (val, + TARGET_CHAR_BIT * embedded_offset, + TARGET_CHAR_BIT * TYPE_LENGTH (type))) + val_print_optimized_out (val, stream); else if (!value_bytes_available (val, embedded_offset, TYPE_LENGTH (type))) val_print_unavailable (stream); else @@ -1159,6 +1750,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. */ @@ -1196,7 +1812,7 @@ val_print_array_elements (struct type *type, { unsigned int things_printed = 0; unsigned len; - struct type *elttype, *index_type; + struct type *elttype, *index_type, *base_index_type; unsigned eltlen; /* Position of the array element we are examining to see whether it is repeated. */ @@ -1204,6 +1820,7 @@ val_print_array_elements (struct type *type, /* Number of repetitions we have detected so far. */ unsigned int reps; LONGEST low_bound, high_bound; + LONGEST low_pos, high_pos; elttype = TYPE_TARGET_TYPE (type); eltlen = TYPE_LENGTH (check_typedef (elttype)); @@ -1211,15 +1828,33 @@ val_print_array_elements (struct type *type, if (get_array_bounds (type, &low_bound, &high_bound)) { - /* The array length should normally be HIGH_BOUND - LOW_BOUND + 1. + if (TYPE_CODE (index_type) == TYPE_CODE_RANGE) + base_index_type = TYPE_TARGET_TYPE (index_type); + else + base_index_type = index_type; + + /* Non-contiguous enumerations types can by used as index types + in some languages (e.g. Ada). In this case, the array length + shall be computed from the positions of the first and last + literal in the enumeration type, and not from the values + of these literals. */ + if (!discrete_position (base_index_type, low_bound, &low_pos) + || !discrete_position (base_index_type, high_bound, &high_pos)) + { + warning (_("unable to get positions in array, use bounds instead")); + low_pos = low_bound; + high_pos = high_bound; + } + + /* The array length should normally be HIGH_POS - LOW_POS + 1. But we have to be a little extra careful, because some languages - such as Ada allow LOW_BOUND to be greater than HIGH_BOUND for + such as Ada allow LOW_POS to be greater than HIGH_POS for empty arrays. In that situation, the array length is just zero, not negative! */ - if (low_bound > high_bound) + if (low_pos > high_pos) len = 0; else - len = high_bound - low_bound + 1; + len = high_pos - low_pos + 1; } else { @@ -1234,7 +1869,7 @@ val_print_array_elements (struct type *type, { if (i != 0) { - if (options->prettyprint_arrays) + if (options->prettyformat_arrays) { fprintf_filtered (stream, ",\n"); print_spaces_filtered (2 + 2 * recurse, stream); @@ -1255,12 +1890,12 @@ val_print_array_elements (struct type *type, if (options->repeat_count_threshold < UINT_MAX) { while (rep1 < len - && value_available_contents_eq (val, - embedded_offset + i * eltlen, - val, - (embedded_offset - + rep1 * eltlen), - eltlen)) + && value_contents_eq (val, + embedded_offset + i * eltlen, + val, + (embedded_offset + + rep1 * eltlen), + eltlen)) { ++reps; ++rep1; @@ -1297,15 +1932,15 @@ val_print_array_elements (struct type *type, /* Read LEN bytes of target memory at address MEMADDR, placing the results in GDB's memory at MYADDR. Returns a count of the bytes - actually read, and optionally an errno value in the location - pointed to by ERRNOPTR if ERRNOPTR is non-null. */ + actually read, and optionally a target_xfer_status value in the + location pointed to by ERRPTR if ERRPTR is non-null. */ /* FIXME: cagney/1999-10-14: Only used by val_print_string. Can this function be eliminated. */ static int partial_memory_read (CORE_ADDR memaddr, gdb_byte *myaddr, - int len, int *errnoptr) + int len, int *errptr) { int nread; /* Number of bytes actually read. */ int errcode; /* Error from last read. */ @@ -1330,9 +1965,9 @@ partial_memory_read (CORE_ADDR memaddr, gdb_byte *myaddr, nread--; } } - if (errnoptr != NULL) + if (errptr != NULL) { - *errnoptr = errcode; + *errptr = errcode; } return (nread); } @@ -1341,13 +1976,15 @@ partial_memory_read (CORE_ADDR memaddr, gdb_byte *myaddr, each. Fetch at most FETCHLIMIT characters. BUFFER will be set to a newly allocated buffer containing the string, which the caller is responsible to free, and BYTES_READ will be set to the number of bytes read. Returns 0 on - success, or errno on failure. + success, or a target_xfer_status on failure. - If LEN > 0, reads exactly LEN characters (including eventual NULs in - the middle or end of the string). If LEN is -1, stops at the first - null character (not necessarily the first null byte) up to a maximum - of FETCHLIMIT characters. Set FETCHLIMIT to UINT_MAX to read as many - characters as possible from the string. + If LEN > 0, reads the lesser of LEN or FETCHLIMIT characters + (including eventual NULs in the middle or end of the string). + + If LEN is -1, stops at the first null character (not necessarily + the first null byte) up to a maximum of FETCHLIMIT characters. Set + FETCHLIMIT to UINT_MAX to read as many characters as possible from + the string. Unless an exception is thrown, BUFFER will always be allocated, even on failure. In this case, some characters might have been read before the @@ -1363,40 +2000,29 @@ int read_string (CORE_ADDR addr, int len, int width, unsigned int fetchlimit, enum bfd_endian byte_order, gdb_byte **buffer, int *bytes_read) { - int found_nul; /* Non-zero if we found the nul char. */ int errcode; /* Errno returned from bad reads. */ unsigned int nfetch; /* Chars to fetch / chars fetched. */ - unsigned int chunksize; /* Size of each fetch, in chars. */ gdb_byte *bufptr; /* Pointer to next available byte in buffer. */ - gdb_byte *limit; /* First location past end of fetch buffer. */ struct cleanup *old_chain = NULL; /* Top of the old cleanup chain. */ - /* Decide how large of chunks to try to read in one operation. This - is also pretty simple. If LEN >= zero, then we want fetchlimit chars, - so we might as well read them all in one operation. If LEN is -1, we - are looking for a NUL terminator to end the fetching, so we might as - well read in blocks that are large enough to be efficient, but not so - large as to be slow if fetchlimit happens to be large. So we choose the - minimum of 8 and fetchlimit. We used to use 200 instead of 8 but - 200 is way too big for remote debugging over a serial line. */ - - chunksize = (len == -1 ? min (8, fetchlimit) : fetchlimit); - /* Loop until we either have all the characters, or we encounter some error, such as bumping into the end of the address space. */ - found_nul = 0; *buffer = NULL; old_chain = make_cleanup (free_current_contents, buffer); if (len > 0) { - *buffer = (gdb_byte *) xmalloc (len * width); + /* We want fetchlimit chars, so we might as well read them all in + one operation. */ + unsigned int fetchlen = min (len, fetchlimit); + + *buffer = (gdb_byte *) xmalloc (fetchlen * width); bufptr = *buffer; - nfetch = partial_memory_read (addr, bufptr, len * width, &errcode) + nfetch = partial_memory_read (addr, bufptr, fetchlen * width, &errcode) / width; addr += nfetch * width; bufptr += nfetch * width; @@ -1404,6 +2030,18 @@ read_string (CORE_ADDR addr, int len, int width, unsigned int fetchlimit, else if (len == -1) { unsigned long bufsize = 0; + unsigned int chunksize; /* Size of each fetch, in chars. */ + int found_nul; /* Non-zero if we found the nul char. */ + gdb_byte *limit; /* First location past end of fetch buffer. */ + + found_nul = 0; + /* We are looking for a NUL terminator to end the fetching, so we + might as well read in blocks that are large enough to be efficient, + but not so large as to be slow if fetchlimit happens to be large. + So we choose the minimum of 8 and fetchlimit. We used to use 200 + instead of 8 but 200 is way too big for remote debugging over a + serial line. */ + chunksize = min (8, fetchlimit); do { @@ -1515,72 +2153,77 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int need_escape = *need_escapep; *need_escapep = 0; - if (gdb_iswprint (w) && (!need_escape || (!gdb_iswdigit (w) - && w != LCST ('8') - && w != LCST ('9')))) - { - gdb_wchar_t wchar = w; - if (w == gdb_btowc (quoter) || w == LCST ('\\')) - obstack_grow_wstr (output, LCST ("\\")); - obstack_grow (output, &wchar, sizeof (gdb_wchar_t)); - } - else + /* iswprint implementation on Windows returns 1 for tab character. + In order to avoid different printout on this host, we explicitly + use wchar_printable function. */ + switch (w) { - switch (w) + case LCST ('\a'): + obstack_grow_wstr (output, LCST ("\\a")); + break; + case LCST ('\b'): + obstack_grow_wstr (output, LCST ("\\b")); + break; + case LCST ('\f'): + obstack_grow_wstr (output, LCST ("\\f")); + break; + case LCST ('\n'): + obstack_grow_wstr (output, LCST ("\\n")); + break; + case LCST ('\r'): + obstack_grow_wstr (output, LCST ("\\r")); + break; + case LCST ('\t'): + obstack_grow_wstr (output, LCST ("\\t")); + break; + case LCST ('\v'): + obstack_grow_wstr (output, LCST ("\\v")); + break; + default: { - case LCST ('\a'): - obstack_grow_wstr (output, LCST ("\\a")); - break; - case LCST ('\b'): - obstack_grow_wstr (output, LCST ("\\b")); - break; - case LCST ('\f'): - obstack_grow_wstr (output, LCST ("\\f")); - break; - case LCST ('\n'): - obstack_grow_wstr (output, LCST ("\\n")); - break; - case LCST ('\r'): - obstack_grow_wstr (output, LCST ("\\r")); - break; - case LCST ('\t'): - obstack_grow_wstr (output, LCST ("\\t")); - break; - case LCST ('\v'): - obstack_grow_wstr (output, LCST ("\\v")); - break; - default: - { - int i; + if (wchar_printable (w) && (!need_escape || (!gdb_iswdigit (w) + && w != LCST ('8') + && w != LCST ('9')))) + { + gdb_wchar_t wchar = w; - for (i = 0; i + width <= orig_len; i += width) - { - char octal[30]; - ULONGEST value; + if (w == gdb_btowc (quoter) || w == LCST ('\\')) + obstack_grow_wstr (output, LCST ("\\")); + obstack_grow (output, &wchar, sizeof (gdb_wchar_t)); + } + else + { + int i; + + for (i = 0; i + width <= orig_len; i += width) + { + char octal[30]; + ULONGEST value; - value = extract_unsigned_integer (&orig[i], width, + value = extract_unsigned_integer (&orig[i], width, byte_order); - /* If the value fits in 3 octal digits, print it that - way. Otherwise, print it as a hex escape. */ - if (value <= 0777) - sprintf (octal, "\\%.3o", (int) (value & 0777)); - else - sprintf (octal, "\\x%lx", (long) value); - append_string_as_wide (octal, output); - } - /* If we somehow have extra bytes, print them now. */ - while (i < orig_len) - { - char octal[5]; + /* If the value fits in 3 octal digits, print it that + way. Otherwise, print it as a hex escape. */ + if (value <= 0777) + xsnprintf (octal, sizeof (octal), "\\%.3o", + (int) (value & 0777)); + else + xsnprintf (octal, sizeof (octal), "\\x%lx", (long) value); + append_string_as_wide (octal, output); + } + /* If we somehow have extra bytes, print them now. */ + while (i < orig_len) + { + char octal[5]; - sprintf (octal, "\\%.3o", orig[i] & 0xff); - append_string_as_wide (octal, output); - ++i; - } + xsnprintf (octal, sizeof (octal), "\\%.3o", orig[i] & 0xff); + append_string_as_wide (octal, output); + ++i; + } - *need_escapep = 1; - } + *need_escapep = 1; + } break; } } @@ -1662,9 +2305,9 @@ generic_emit_char (int c, struct type *type, struct ui_file *stream, make_cleanup_obstack_free (&output); convert_between_encodings (INTERMEDIATE_ENCODING, host_charset (), - obstack_base (&wchar_buf), + (gdb_byte *) obstack_base (&wchar_buf), obstack_object_size (&wchar_buf), - 1, &output, translit_char); + sizeof (gdb_wchar_t), &output, translit_char); obstack_1grow (&output, '\0'); fputs_filtered (obstack_base (&output), stream); @@ -1672,6 +2315,243 @@ generic_emit_char (int c, struct type *type, struct ui_file *stream, do_cleanups (cleanups); } +/* Return the repeat count of the next character/byte in ITER, + storing the result in VEC. */ + +static int +count_next_character (struct wchar_iterator *iter, + VEC (converted_character_d) **vec) +{ + struct converted_character *current; + + if (VEC_empty (converted_character_d, *vec)) + { + struct converted_character tmp; + gdb_wchar_t *chars; + + tmp.num_chars + = wchar_iterate (iter, &tmp.result, &chars, &tmp.buf, &tmp.buflen); + if (tmp.num_chars > 0) + { + gdb_assert (tmp.num_chars < MAX_WCHARS); + memcpy (tmp.chars, chars, tmp.num_chars * sizeof (gdb_wchar_t)); + } + VEC_safe_push (converted_character_d, *vec, &tmp); + } + + current = VEC_last (converted_character_d, *vec); + + /* Count repeated characters or bytes. */ + current->repeat_count = 1; + if (current->num_chars == -1) + { + /* EOF */ + return -1; + } + else + { + gdb_wchar_t *chars; + struct converted_character d; + int repeat; + + d.repeat_count = 0; + + while (1) + { + /* Get the next character. */ + d.num_chars + = wchar_iterate (iter, &d.result, &chars, &d.buf, &d.buflen); + + /* If a character was successfully converted, save the character + into the converted character. */ + if (d.num_chars > 0) + { + gdb_assert (d.num_chars < MAX_WCHARS); + memcpy (d.chars, chars, WCHAR_BUFLEN (d.num_chars)); + } + + /* Determine if the current character is the same as this + new character. */ + if (d.num_chars == current->num_chars && d.result == current->result) + { + /* There are two cases to consider: + + 1) Equality of converted character (num_chars > 0) + 2) Equality of non-converted character (num_chars == 0) */ + if ((current->num_chars > 0 + && memcmp (current->chars, d.chars, + WCHAR_BUFLEN (current->num_chars)) == 0) + || (current->num_chars == 0 + && current->buflen == d.buflen + && memcmp (current->buf, d.buf, current->buflen) == 0)) + ++current->repeat_count; + else + break; + } + else + break; + } + + /* Push this next converted character onto the result vector. */ + repeat = current->repeat_count; + VEC_safe_push (converted_character_d, *vec, &d); + return repeat; + } +} + +/* Print the characters in CHARS to the OBSTACK. QUOTE_CHAR is the quote + character to use with string output. WIDTH is the size of the output + character type. BYTE_ORDER is the the target byte order. OPTIONS + is the user's print options. */ + +static void +print_converted_chars_to_obstack (struct obstack *obstack, + VEC (converted_character_d) *chars, + int quote_char, int width, + enum bfd_endian byte_order, + const struct value_print_options *options) +{ + unsigned int idx; + struct converted_character *elem; + enum {START, SINGLE, REPEAT, INCOMPLETE, FINISH} state, last; + gdb_wchar_t wide_quote_char = gdb_btowc (quote_char); + int need_escape = 0; + + /* Set the start state. */ + idx = 0; + last = state = START; + elem = NULL; + + while (1) + { + switch (state) + { + case START: + /* Nothing to do. */ + break; + + case SINGLE: + { + int j; + + /* We are outputting a single character + (< options->repeat_count_threshold). */ + + if (last != SINGLE) + { + /* We were outputting some other type of content, so we + must output and a comma and a quote. */ + if (last != START) + obstack_grow_wstr (obstack, LCST (", ")); + obstack_grow (obstack, &wide_quote_char, sizeof (gdb_wchar_t)); + } + /* Output the character. */ + for (j = 0; j < elem->repeat_count; ++j) + { + if (elem->result == wchar_iterate_ok) + print_wchar (elem->chars[0], elem->buf, elem->buflen, width, + byte_order, obstack, quote_char, &need_escape); + else + print_wchar (gdb_WEOF, elem->buf, elem->buflen, width, + byte_order, obstack, quote_char, &need_escape); + } + } + break; + + case REPEAT: + { + int j; + char *s; + + /* We are outputting a character with a repeat count + greater than options->repeat_count_threshold. */ + + if (last == SINGLE) + { + /* We were outputting a single string. Terminate the + string. */ + obstack_grow (obstack, &wide_quote_char, sizeof (gdb_wchar_t)); + } + if (last != START) + obstack_grow_wstr (obstack, LCST (", ")); + + /* Output the character and repeat string. */ + obstack_grow_wstr (obstack, LCST ("'")); + if (elem->result == wchar_iterate_ok) + print_wchar (elem->chars[0], elem->buf, elem->buflen, width, + byte_order, obstack, quote_char, &need_escape); + else + print_wchar (gdb_WEOF, elem->buf, elem->buflen, width, + byte_order, obstack, quote_char, &need_escape); + obstack_grow_wstr (obstack, LCST ("'")); + s = xstrprintf (_(" "), elem->repeat_count); + for (j = 0; s[j]; ++j) + { + gdb_wchar_t w = gdb_btowc (s[j]); + obstack_grow (obstack, &w, sizeof (gdb_wchar_t)); + } + xfree (s); + } + break; + + case INCOMPLETE: + /* We are outputting an incomplete sequence. */ + if (last == SINGLE) + { + /* If we were outputting a string of SINGLE characters, + terminate the quote. */ + obstack_grow (obstack, &wide_quote_char, sizeof (gdb_wchar_t)); + } + if (last != START) + obstack_grow_wstr (obstack, LCST (", ")); + + /* Output the incomplete sequence string. */ + obstack_grow_wstr (obstack, LCST ("buf, elem->buflen, width, byte_order, + obstack, 0, &need_escape); + obstack_grow_wstr (obstack, LCST (">")); + + /* We do not attempt to outupt anything after this. */ + state = FINISH; + break; + + case FINISH: + /* All done. If we were outputting a string of SINGLE + characters, the string must be terminated. Otherwise, + REPEAT and INCOMPLETE are always left properly terminated. */ + if (last == SINGLE) + obstack_grow (obstack, &wide_quote_char, sizeof (gdb_wchar_t)); + + return; + } + + /* Get the next element and state. */ + last = state; + if (state != FINISH) + { + elem = VEC_index (converted_character_d, chars, idx++); + switch (elem->result) + { + case wchar_iterate_ok: + case wchar_iterate_invalid: + if (elem->repeat_count > options->repeat_count_threshold) + state = REPEAT; + else + state = SINGLE; + break; + + case wchar_iterate_incomplete: + state = INCOMPLETE; + break; + + case wchar_iterate_eof: + state = FINISH; + break; + } + } + } +} + /* Print the character string STRING, printing at most LENGTH characters. LENGTH is -1 if the string is nul terminated. TYPE is the type of each character. OPTIONS holds the printing options; @@ -1691,16 +2571,13 @@ generic_printstr (struct ui_file *stream, struct type *type, { enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); unsigned int i; - unsigned int things_printed = 0; - int in_quotes = 0; - int need_comma = 0; int width = TYPE_LENGTH (type); struct obstack wchar_buf, output; struct cleanup *cleanup; struct wchar_iterator *iter; int finished = 0; - int need_escape = 0; - gdb_wchar_t wide_quote_char = gdb_btowc (quote_char); + struct converted_character *last; + VEC (converted_character_d) *converted_chars; if (length == -1) { @@ -1734,166 +2611,46 @@ generic_printstr (struct ui_file *stream, struct type *type, /* Arrange to iterate over the characters, in wchar_t form. */ iter = make_wchar_iterator (string, length * width, encoding, width); cleanup = make_cleanup_wchar_iterator (iter); + converted_chars = NULL; + make_cleanup (VEC_cleanup (converted_character_d), &converted_chars); - /* WCHAR_BUF is the obstack we use to represent the string in - wchar_t form. */ - obstack_init (&wchar_buf); - make_cleanup_obstack_free (&wchar_buf); - - while (!finished && things_printed < options->print_max) + /* Convert characters until the string is over or the maximum + number of printed characters has been reached. */ + i = 0; + while (i < options->print_max) { - int num_chars; - enum wchar_iterate_result result; - gdb_wchar_t *chars; - const gdb_byte *buf; - size_t buflen; + int r; QUIT; - if (need_comma) - { - obstack_grow_wstr (&wchar_buf, LCST (", ")); - need_comma = 0; - } - - num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen); - /* We only look at repetitions when we were able to convert a - single character in isolation. This makes the code simpler - and probably does the sensible thing in the majority of - cases. */ - while (num_chars == 1 && things_printed < options->print_max) - { - /* Count the number of repetitions. */ - unsigned int reps = 0; - gdb_wchar_t current_char = chars[0]; - const gdb_byte *orig_buf = buf; - int orig_len = buflen; + /* Grab the next character and repeat count. */ + r = count_next_character (iter, &converted_chars); - if (need_comma) - { - obstack_grow_wstr (&wchar_buf, LCST (", ")); - need_comma = 0; - } - - while (num_chars == 1 && current_char == chars[0]) - { - num_chars = wchar_iterate (iter, &result, &chars, - &buf, &buflen); - ++reps; - } - - /* Emit CURRENT_CHAR according to the repetition count and - options. */ - if (reps > options->repeat_count_threshold) - { - if (in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\")); - obstack_grow (&wchar_buf, &wide_quote_char, - sizeof (gdb_wchar_t)); - obstack_grow_wstr (&wchar_buf, LCST (", ")); - in_quotes = 0; - } - obstack_grow_wstr (&wchar_buf, LCST ("'")); - need_escape = 0; - print_wchar (current_char, orig_buf, orig_len, width, - byte_order, &wchar_buf, '\'', &need_escape); - obstack_grow_wstr (&wchar_buf, LCST ("'")); - { - /* Painful gyrations. */ - int j; - char *s = xstrprintf (_(" "), reps); - - for (j = 0; s[j]; ++j) - { - gdb_wchar_t w = gdb_btowc (s[j]); - obstack_grow (&wchar_buf, &w, sizeof (gdb_wchar_t)); - } - xfree (s); - } - things_printed += options->repeat_count_threshold; - need_comma = 1; - } - else - { - /* Saw the character one or more times, but fewer than - the repetition threshold. */ - if (!in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\")); - obstack_grow (&wchar_buf, &wide_quote_char, - sizeof (gdb_wchar_t)); - in_quotes = 1; - need_escape = 0; - } + /* If less than zero, the end of the input string was reached. */ + if (r < 0) + break; - while (reps-- > 0) - { - print_wchar (current_char, orig_buf, - orig_len, width, - byte_order, &wchar_buf, - quote_char, &need_escape); - ++things_printed; - } - } - } + /* Otherwise, add the count to the total print count and get + the next character. */ + i += r; + } - /* NUM_CHARS and the other outputs from wchar_iterate are valid - here regardless of which branch was taken above. */ - if (num_chars < 0) - { - /* Hit EOF. */ - finished = 1; - break; - } + /* Get the last element and determine if the entire string was + processed. */ + last = VEC_last (converted_character_d, converted_chars); + finished = (last->result == wchar_iterate_eof); - switch (result) - { - case wchar_iterate_invalid: - if (!in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\")); - obstack_grow (&wchar_buf, &wide_quote_char, - sizeof (gdb_wchar_t)); - in_quotes = 1; - } - need_escape = 0; - print_wchar (gdb_WEOF, buf, buflen, width, byte_order, - &wchar_buf, quote_char, &need_escape); - break; + /* Ensure that CONVERTED_CHARS is terminated. */ + last->result = wchar_iterate_eof; - case wchar_iterate_incomplete: - if (in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\")); - obstack_grow (&wchar_buf, &wide_quote_char, - sizeof (gdb_wchar_t)); - obstack_grow_wstr (&wchar_buf, LCST (",")); - in_quotes = 0; - } - obstack_grow_wstr (&wchar_buf, - LCST (" ")); - finished = 1; - break; - } - } + /* WCHAR_BUF is the obstack we use to represent the string in + wchar_t form. */ + obstack_init (&wchar_buf); + make_cleanup_obstack_free (&wchar_buf); - /* Terminate the quotes if necessary. */ - if (in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\")); - obstack_grow (&wchar_buf, &wide_quote_char, - sizeof (gdb_wchar_t)); - } + /* Print the output string to the obstack. */ + print_converted_chars_to_obstack (&wchar_buf, converted_chars, quote_char, + width, byte_order, options); if (force_ellipses || !finished) obstack_grow_wstr (&wchar_buf, LCST ("...")); @@ -1903,9 +2660,9 @@ generic_printstr (struct ui_file *stream, struct type *type, make_cleanup_obstack_free (&output); convert_between_encodings (INTERMEDIATE_ENCODING, host_charset (), - obstack_base (&wchar_buf), + (gdb_byte *) obstack_base (&wchar_buf), obstack_object_size (&wchar_buf), - 1, &output, translit_char); + sizeof (gdb_wchar_t), &output, translit_char); obstack_1grow (&output, '\0'); fputs_filtered (obstack_base (&output), stream); @@ -1960,8 +2717,10 @@ val_print_string (struct type *elttype, const char *encoding, LEN is -1. */ /* Determine found_nul by looking at the last character read. */ - found_nul = extract_unsigned_integer (buffer + bytes_read - width, width, - byte_order) == 0; + found_nul = 0; + if (bytes_read >= width) + found_nul = extract_unsigned_integer (buffer + bytes_read - width, width, + byte_order) == 0; if (len == -1 && !found_nul) { gdb_byte *peekbuf; @@ -1989,28 +2748,20 @@ 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); } if (errcode != 0) { - if (errcode == EIO) - { - fprintf_filtered (stream, "
"); - } - else - { - fprintf_filtered (stream, " ", safe_strerror (errcode)); - } + char *str; + + str = memory_error_message (errcode, gdbarch, addr); + make_cleanup (xfree, str); + + fprintf_filtered (stream, ""); } gdb_flush (stream); @@ -2159,7 +2910,7 @@ set_print (char *arg, int from_tty) { printf_unfiltered ( "\"set print\" must be followed by the name of a print subcommand.\n"); - help_list (setprintlist, "set print ", -1, gdb_stdout); + help_list (setprintlist, "set print ", all_commands, gdb_stdout); } static void @@ -2167,6 +2918,21 @@ show_print (char *args, int from_tty) { cmd_show_list (showprintlist, from_tty, ""); } + +static void +set_print_raw (char *arg, int from_tty) +{ + printf_unfiltered ( + "\"set print raw\" must be followed by the name of a \"print raw\" subcommand.\n"); + help_list (setprintrawlist, "set print raw ", all_commands, gdb_stdout); +} + +static void +show_print_raw (char *args, int from_tty) +{ + cmd_show_list (showprintrawlist, from_tty, ""); +} + void _initialize_valprint (void) @@ -2184,11 +2950,19 @@ _initialize_valprint (void) add_alias_cmd ("p", "print", no_class, 1, &showlist); add_alias_cmd ("pr", "print", no_class, 1, &showlist); + add_prefix_cmd ("raw", no_class, set_print_raw, + _("\ +Generic command for setting what things to print in \"raw\" mode."), + &setprintrawlist, "set print raw ", 0, &setprintlist); + add_prefix_cmd ("raw", no_class, show_print_raw, + _("Generic command for showing \"print raw\" settings."), + &showprintrawlist, "show print raw ", 0, &showprintlist); + add_setshow_uinteger_cmd ("elements", no_class, &user_print_options.print_max, _("\ Set limit on string chars or array elements to print."), _("\ Show limit on string chars or array elements to print."), _("\ -\"set print elements 0\" causes there to be no limit."), +\"set print elements unlimited\" causes there to be no limit."), NULL, show_print_max, &setprintlist, &showprintlist); @@ -2205,17 +2979,17 @@ Show printing of char arrays to stop at first null char."), NULL, &user_print_options.repeat_count_threshold, _("\ Set threshold for repeated print elements."), _("\ Show threshold for repeated print elements."), _("\ -\"set print repeats 0\" causes all elements to be individually printed."), +\"set print repeats unlimited\" causes all elements to be individually printed."), NULL, show_repeat_count_threshold, &setprintlist, &showprintlist); add_setshow_boolean_cmd ("pretty", class_support, - &user_print_options.prettyprint_structs, _("\ -Set prettyprinting of structures."), _("\ -Show prettyprinting of structures."), NULL, + &user_print_options.prettyformat_structs, _("\ +Set pretty formatting of structures."), _("\ +Show pretty formatting of structures."), NULL, NULL, - show_prettyprint_structs, + show_prettyformat_structs, &setprintlist, &showprintlist); add_setshow_boolean_cmd ("union", class_support, @@ -2227,11 +3001,11 @@ Show printing of unions interior to structures."), NULL, &setprintlist, &showprintlist); add_setshow_boolean_cmd ("array", class_support, - &user_print_options.prettyprint_arrays, _("\ -Set prettyprinting of arrays."), _("\ -Show prettyprinting of arrays."), NULL, + &user_print_options.prettyformat_arrays, _("\ +Set pretty formatting of arrays."), _("\ +Show pretty formatting of arrays."), NULL, NULL, - show_prettyprint_arrays, + show_prettyformat_arrays, &setprintlist, &showprintlist); add_setshow_boolean_cmd ("address", class_support, @@ -2242,6 +3016,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."), _("\