Re: [RFA] print arrays with indexes

Joel Brobecker
2005-09-14T17:13:55Z

Hello,

It'd be nice to have this patch reviewed. It touches quite a few files,
so I'd rather not wait for too long to avoid merging conflicts. Once
we agree on the interface, I think the code will follow naturally.

Thank you!

On Wed, Sep 07, 2005 at 01:24:02PM -0700, Joel Brobecker wrote:
> > > There is also Jim's suggestion which has some merits. I'm more of
> > > an all or nothing kind of guy, so I prefer the approach I've chosen,
> > > but I am flexible.
> >
> > I've got no strong opinions on this either way. Thresholds seem
> > complicated as a UI.
>
> I feel the same way too.
>
> Here is a revised patch, that implements the language method.
> Now, with C, we get:
>
> (gdb) p array
> $1 = {[0] = 1, [1] = 2, [2] = 3, [3] = 4}
>
> This is also the default for all the other languages, except Ada, where
> the debugger will print:
>
> (gdb) p one_two_three
> $1 = (1 => 1, 2 => 2, 3 => 3)
>
> 2005-09-07 Joel Brobecker <brobecker@adacore.com>
>
> * language.h (language_defn): New field la_print_array_index.
> (LA_PRINT_ARRAY_INDEX): New macro.
> (default_print_array_index): Add declaration.
> * language.c (default_print_array_index): new function.
> (unknown_language): Add value for new field.
> (auto_language): Likewise.
> (local_language): Likewise.
> * c-lang.c (c_language_defn): Likewise.
> (cpluc_language_defn): Likewise.
> (asm_language_defn): Likewise.
> (minimal_language_defn): Likewise.
> * f-lang.c (f_language_defn): Likewise.
> * jv-lang.c (java_language_defn): Likewise.
> * m2-lang.c (m2_language_defn): Likewise.
> * objc-lang.c (objc_language_defn): Likewise.
> * p-lang.c (pascal_language_defn): Likewise.
> * ada-lang.c (ada_print_array_index): New function.
> (ada_language_defn): Add value for new field.
> * valprint.h (print_array_indexes_p): Add declaration.
> (maybe_print_array_index): Add declaration.
> (val_print_array_elements): Add new parameter to function profile.
> * valprint.c (print_array_indexes): New static variable.
> (show_print_array_indexes): New function.
> (print_array_indexes_p): New function.
> (maybe_print_array_index): New function.
> (val_print_array_elements): Add new parameter real_index_offset.
> Print the index of each element if required by the user.
> (_initialize_valprint): Add new array-indexes "set/show print" command.
> * c-valprint.c (c_val_print): Update call to val_print_array_elements.
> * p-valprint.c (pascal_val_print): Likewise.
> * ada-valprint.c (ada_get_array_low_bound_and_type): New function,
> mostly extracted from print_optional_low_bound().
> (print_optional_low_bound): Replace extracted code by call to
> ada_get_array_low_bound_and_type(). Stop printing the low bound
> if indexes will be printed for all elements of the array.
> (val_print_packed_array_elements): Print the index of each element
> of the array if necessary.
> (ada_val_print_1): For non-packed arrays, compute the array low
> bound, and pass it to val_print_array_elements().
>
> Tested on x86-linux, no regression. Testcases and documentation to follow
> after the review.
>
> Thanks,
> --
> Joel

> Index: language.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/language.h,v
> retrieving revision 1.35
> diff -u -p -r1.35 language.h
> --- language.h 9 May 2005 21:20:34 -0000 1.35
> +++ language.h 7 Sep 2005 20:00:10 -0000
> @@ -275,6 +275,12 @@ struct language_defn
> void (*la_language_arch_info) (struct gdbarch *,
> struct language_arch_info *);
>
> + /* Print the index of an element of an array. */
> + void (*la_print_array_index) (struct value *index_value,
> + struct ui_file *stream,
> + int format,
> + enum val_prettyprint pretty);
> +
> /* Add fields above this point, so the magic number is always last. */
> /* Magic number for compat checking */
>
> @@ -362,6 +368,9 @@ extern enum language set_language (enum
> #define LA_EMIT_CHAR(ch, stream, quoter) \
> (current_language->la_emitchar(ch, stream, quoter))
>
> +#define LA_PRINT_ARRAY_INDEX(index_value, stream, format, pretty) \
> + (current_language->la_print_array_index(index_value, stream, format, pretty))
> +
> /* Test a character to decide whether it can be printed in literal form
> or needs to be printed in another representation. For example,
> in C the literal form of the character with octal value 141 is 'a'
> @@ -457,4 +466,10 @@ extern char *language_class_name_from_ph
> /* Splitting strings into words. */
> extern char *default_word_break_characters (void);
>
> +/* Print the index of an array element using the C99 syntax. */
> +extern void default_print_array_index (struct value *index_value,
> + struct ui_file *stream,
> + int format,
> + enum val_prettyprint pretty);
> +
> #endif /* defined (LANGUAGE_H) */
> Index: language.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/language.c,v
> retrieving revision 1.62
> diff -u -p -r1.62 language.c
> --- language.c 29 Aug 2005 12:57:49 -0000 1.62
> +++ language.c 7 Sep 2005 20:00:09 -0000
> @@ -1057,6 +1057,17 @@ default_word_break_characters (void)
> return " \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,-";
> }
>
> +/* Print the index of array elements using the C99 syntax. */
> +
> +void
> +default_print_array_index (struct value *index_value, struct ui_file *stream,
> + int format, enum val_prettyprint pretty)
> +{
> + fprintf_filtered (stream, "[");
> + LA_VALUE_PRINT (index_value, stream, format, pretty);
> + fprintf_filtered (stream, "] = ");
> +}
> +
> /* Define the language that is no language. */
>
> static int
> @@ -1181,6 +1192,7 @@ const struct language_defn unknown_langu
> NULL,
> default_word_break_characters,
> unknown_language_arch_info, /* la_language_arch_info. */
> + default_print_array_index,
> LANG_MAGIC
> };
>
> @@ -1217,6 +1229,7 @@ const struct language_defn auto_language
> NULL,
> default_word_break_characters,
> unknown_language_arch_info, /* la_language_arch_info. */
> + default_print_array_index,
> LANG_MAGIC
> };
>
> @@ -1252,6 +1265,7 @@ const struct language_defn local_languag
> NULL,
> default_word_break_characters,
> unknown_language_arch_info, /* la_language_arch_info. */
> + default_print_array_index,
> LANG_MAGIC
> };
> \f
> Index: c-lang.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/c-lang.c,v
> retrieving revision 1.37
> diff -u -p -r1.37 c-lang.c
> --- c-lang.c 9 May 2005 21:20:30 -0000 1.37
> +++ c-lang.c 7 Sep 2005 19:58:49 -0000
> @@ -595,6 +595,7 @@ const struct language_defn c_language_de
> NULL,
> default_word_break_characters,
> c_language_arch_info,
> + default_print_array_index,
> LANG_MAGIC
> };
>
> @@ -653,6 +654,7 @@ const struct language_defn cplus_languag
> &builtin_type_char, /* Type of string elements */
> default_word_break_characters,
> NULL, /* FIXME: la_language_arch_info. */
> + default_print_array_index,
> LANG_MAGIC
> };
>
> @@ -688,6 +690,7 @@ const struct language_defn asm_language_
> NULL,
> default_word_break_characters,
> c_language_arch_info, /* FIXME: la_language_arch_info. */
> + default_print_array_index,
> LANG_MAGIC
> };
>
> @@ -728,6 +731,7 @@ const struct language_defn minimal_langu
> NULL,
> default_word_break_characters,
> c_language_arch_info,
> + default_print_array_index,
> LANG_MAGIC
> };
>
> Index: f-lang.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/f-lang.c,v
> retrieving revision 1.31
> diff -u -p -r1.31 f-lang.c
> --- f-lang.c 9 May 2005 21:20:30 -0000 1.31
> +++ f-lang.c 7 Sep 2005 19:59:30 -0000
> @@ -485,6 +485,7 @@ const struct language_defn f_language_de
> &builtin_type_f_character, /* Type of string elements */
> default_word_break_characters,
> NULL, /* FIXME: la_language_arch_info. */
> + default_print_array_index,
> LANG_MAGIC
> };
>
> Index: jv-lang.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/jv-lang.c,v
> retrieving revision 1.42
> diff -u -p -r1.42 jv-lang.c
> --- jv-lang.c 27 May 2005 04:39:32 -0000 1.42
> +++ jv-lang.c 7 Sep 2005 20:00:08 -0000
> @@ -1114,6 +1114,7 @@ const struct language_defn java_language
> NULL,
> default_word_break_characters,
> c_language_arch_info,
> + default_print_array_index,
> LANG_MAGIC
> };
>
> Index: m2-lang.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/m2-lang.c,v
> retrieving revision 1.23
> diff -u -p -r1.23 m2-lang.c
> --- m2-lang.c 9 May 2005 21:20:34 -0000 1.23
> +++ m2-lang.c 7 Sep 2005 20:00:14 -0000
> @@ -437,6 +437,7 @@ const struct language_defn m2_language_d
> &builtin_type_m2_char, /* Type of string elements */
> default_word_break_characters,
> NULL, /* FIXME: la_language_arch_info. */
> + default_print_array_index,
> LANG_MAGIC
> };
>
> Index: objc-lang.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/objc-lang.c,v
> retrieving revision 1.49
> diff -u -p -r1.49 objc-lang.c
> --- objc-lang.c 12 Jul 2005 12:11:44 -0000 1.49
> +++ objc-lang.c 7 Sep 2005 20:00:33 -0000
> @@ -684,6 +684,7 @@ const struct language_defn objc_language
> &builtin_type_char, /* Type of string elements */
> default_word_break_characters,
> NULL, /* FIXME: la_language_arch_info. */
> + default_print_array_index,
> LANG_MAGIC
> };
>
> Index: p-lang.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/p-lang.c,v
> retrieving revision 1.25
> diff -u -p -r1.25 p-lang.c
> --- p-lang.c 9 May 2005 21:20:34 -0000 1.25
> +++ p-lang.c 7 Sep 2005 20:00:36 -0000
> @@ -477,6 +477,7 @@ const struct language_defn pascal_langua
> &builtin_type_char, /* Type of string elements */
> default_word_break_characters,
> NULL, /* FIXME: la_language_arch_info. */
> + default_print_array_index,
> LANG_MAGIC
> };
>
> Index: scm-lang.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/scm-lang.c,v
> retrieving revision 1.32
> diff -u -p -r1.32 scm-lang.c
> --- scm-lang.c 27 May 2005 04:39:32 -0000 1.32
> +++ scm-lang.c 7 Sep 2005 20:01:01 -0000
> @@ -269,6 +269,7 @@ const struct language_defn scm_language_
> NULL,
> default_word_break_characters,
> c_language_arch_info,
> + default_print_array_index,
> LANG_MAGIC
> };
>
> Index: ada-lang.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/ada-lang.c,v
> retrieving revision 1.78
> diff -u -p -r1.78 ada-lang.c
> --- ada-lang.c 9 May 2005 21:20:29 -0000 1.78
> +++ ada-lang.c 7 Sep 2005 19:58:31 -0000
> @@ -303,6 +303,16 @@ ada_get_gdb_completer_word_break_charact
> return ada_completer_word_break_characters;
> }
>
> +/* Print an array element index using the Ada syntax. */
> +
> +static void
> +ada_print_array_index (struct value *index_value, struct ui_file *stream,
> + int format, enum val_prettyprint pretty)
> +{
> + LA_VALUE_PRINT (index_value, stream, format, pretty);
> + fprintf_filtered (stream, " => ");
> +}
> +
> /* Read the string located at ADDR from the inferior and store the
> result into BUF. */
>
> @@ -8766,6 +8776,7 @@ const struct language_defn ada_language_
> NULL,
> ada_get_gdb_completer_word_break_characters,
> ada_language_arch_info,
> + ada_print_array_index,
> LANG_MAGIC
> };
>
> Index: valprint.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/valprint.h,v
> retrieving revision 1.10
> diff -u -p -r1.10 valprint.h
> --- valprint.h 9 May 2005 21:20:35 -0000 1.10
> +++ valprint.h 7 Sep 2005 20:01:35 -0000
> @@ -50,10 +50,16 @@ extern int output_format;
>
> extern int stop_print_at_null; /* Stop printing at null char? */
>
> +extern int print_array_indexes_p (void);
> +
> +extern void maybe_print_array_index (struct type *index_type, LONGEST index,
> + struct ui_file *stream, int format,
> + enum val_prettyprint pretty);
> +
> extern void val_print_array_elements (struct type *, const gdb_byte *,
> CORE_ADDR, struct ui_file *, int,
> int, int, enum val_prettyprint,
> - unsigned int);
> + unsigned int, LONGEST);
>
> extern void val_print_type_code_int (struct type *, const gdb_byte *,
> struct ui_file *);
> Index: valprint.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/valprint.c,v
> retrieving revision 1.54
> diff -u -p -r1.54 valprint.c
> --- valprint.c 10 Jun 2005 06:07:32 -0000 1.54
> +++ valprint.c 7 Sep 2005 20:01:35 -0000
> @@ -100,6 +100,17 @@ Default output radix for printing of val
> }
> int output_format = 0;
>
> +/* By default we print arrays without printing the index of each element in
> + the array. This behavior can be changed by setting PRINT_ARRAY_INDEXES. */
> +
> +static int print_array_indexes = 0;
> +static void
> +show_print_array_indexes (struct ui_file *file, int from_tty,
> + struct cmd_list_element *c, const char *value)
> +{
> + fprintf_filtered (file, _("Printing of array indexes is %s.\n"), value);
> +}
> +
> /* Print repeat counts if there are more than this many repetitions of an
> element in an array. Referenced by the low level language dependent
> print routines. */
> @@ -859,9 +870,41 @@ print_char_chars (struct ui_file *stream
> }
> }
>
> +/* Return non-zero if the debugger should print the index of each element
> + when printing array values. */
> +
> +int
> +print_array_indexes_p (void)
> +{
> + return print_array_indexes;
> +}
> +
> +/* Print on STREAM using the given FORMAT the index for the element
> + at INDEX of an array whose index type is INDEX_TYPE. */
> +
> +void
> +maybe_print_array_index (struct type *index_type, LONGEST index,
> + struct ui_file *stream, int format,
> + enum val_prettyprint pretty)
> +{
> + struct value *index_value;
> +
> + if (!print_array_indexes)
> + return;
> +
> + index_value = value_from_longest (index_type, index);
> +
> + LA_PRINT_ARRAY_INDEX (index_value, stream, format, pretty);
> +}
> +
> /* Called by various <lang>_val_print routines to print elements of an
> array in the form "<elem1>, <elem2>, <elem3>, ...".
>
> + Some languages such as Ada allow the user to specify arrays where
> + the index of the first element is not zero. REAL_INDEX_OFFSET is
> + the user-level index of the first element of the array. For many
> + languages such as C or C++, it is always zero.
> +
> (FIXME?) Assumes array element separator is a comma, which is correct
> for all languages currently handled.
> (FIXME?) Some languages have a notation for repeated array elements,
> @@ -873,11 +916,11 @@ val_print_array_elements (struct type *t
> CORE_ADDR address, struct ui_file *stream,
> int format, int deref_ref,
> int recurse, enum val_prettyprint pretty,
> - unsigned int i)
> + unsigned int i, LONGEST real_index_offset)
> {
> unsigned int things_printed = 0;
> unsigned len;
> - struct type *elttype;
> + struct type *elttype, *index_type;
> unsigned eltlen;
> /* Position of the array element we are examining to see
> whether it is repeated. */
> @@ -888,6 +931,7 @@ val_print_array_elements (struct type *t
> elttype = TYPE_TARGET_TYPE (type);
> eltlen = TYPE_LENGTH (check_typedef (elttype));
> len = TYPE_LENGTH (type) / eltlen;
> + index_type = TYPE_INDEX_TYPE (type);
>
> annotate_array_section_begin (i, elttype);
>
> @@ -906,6 +950,8 @@ val_print_array_elements (struct type *t
> }
> }
> wrap_here (n_spaces (2 + 2 * recurse));
> + maybe_print_array_index (index_type, i + real_index_offset,
> + stream, format, pretty);
>
> rep1 = i + 1;
> reps = 1;
> @@ -1396,6 +1442,12 @@ Show the default input and output number
> Use 'show input-radix' or 'show output-radix' to independently show each."),
> &showlist);
>
> + add_setshow_boolean_cmd ("array-indexes", class_support,
> + &print_array_indexes, _("\
> +Set printing of array indexes."), _("\
> +Show printing of array indexes"), NULL, NULL, show_print_array_indexes,
> + &setprintlist, &showprintlist);
> +
> /* Give people the defaults which they are used to. */
> prettyprint_structs = 0;
> prettyprint_arrays = 0;
> Index: c-valprint.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/c-valprint.c,v
> retrieving revision 1.37
> diff -u -p -r1.37 c-valprint.c
> --- c-valprint.c 9 May 2005 21:20:30 -0000 1.37
> +++ c-valprint.c 7 Sep 2005 19:58:50 -0000
> @@ -133,7 +133,7 @@ c_val_print (struct type *type, const gd
> i = 0;
> }
> val_print_array_elements (type, valaddr + embedded_offset, address, stream,
> - format, deref_ref, recurse, pretty, i);
> + format, deref_ref, recurse, pretty, i, 0);
> fprintf_filtered (stream, "}");
> }
> break;
> Index: p-valprint.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/p-valprint.c,v
> retrieving revision 1.39
> diff -u -p -r1.39 p-valprint.c
> --- p-valprint.c 9 May 2005 21:20:34 -0000 1.39
> +++ p-valprint.c 7 Sep 2005 20:00:37 -0000
> @@ -123,7 +123,7 @@ pascal_val_print (struct type *type, con
> i = 0;
> }
> val_print_array_elements (type, valaddr + embedded_offset, address, stream,
> - format, deref_ref, recurse, pretty, i);
> + format, deref_ref, recurse, pretty, i, 0);
> fprintf_filtered (stream, "}");
> }
> break;
> Index: ada-valprint.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/ada-valprint.c,v
> retrieving revision 1.23
> diff -u -p -r1.23 ada-valprint.c
> --- ada-valprint.c 9 May 2005 21:20:30 -0000 1.23
> +++ ada-valprint.c 7 Sep 2005 19:58:33 -0000
> @@ -75,6 +75,44 @@ adjust_type_signedness (struct type *typ
> TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
> }
>
> +/* Assuming TYPE is a simple, non-empty array type, compute the lower
> + bound and the array index type. Save the low bound into LOW_BOUND
> + if not NULL. Save the index type in INDEX_TYPE if not NULL.
> +
> + Return 1 if the operation was successful. Return zero otherwise,
> + in which case the value of LOW_BOUND and INDEX_TYPE is undefined. */
> +
> +static int
> +ada_get_array_low_bound_and_type (struct type *type,
> + long *low_bound,
> + struct type **index_type)
> +{
> + struct type *index = TYPE_INDEX_TYPE (type);
> + long low = 0;
> +
> + if (index == NULL)
> + return 0;
> +
> + if (TYPE_CODE (index) != TYPE_CODE_RANGE
> + && TYPE_CODE (index) != TYPE_CODE_ENUM)
> + return 0;
> +
> + low = TYPE_LOW_BOUND (index);
> + if (low > TYPE_HIGH_BOUND (index))
> + return 0;
> +
> + if (TYPE_CODE (index) == TYPE_CODE_RANGE)
> + index = TYPE_TARGET_TYPE (index);
> +
> + if (low_bound)
> + *low_bound = low;
> +
> + if (index_type)
> + *index_type = index;
> +
> + return 1;
> +}
> +
> /* Assuming TYPE is a simple, non-empty array type, prints its lower bound
> on STREAM, if non-standard (i.e., other than 1 for numbers, other
> than lower bound of index type for enumerated type). Returns 1
> @@ -86,19 +124,10 @@ print_optional_low_bound (struct ui_file
> struct type *index_type;
> long low_bound;
>
> - index_type = TYPE_INDEX_TYPE (type);
> - low_bound = 0;
> -
> - if (index_type == NULL)
> + if (print_array_indexes_p ())
> return 0;
> - if (TYPE_CODE (index_type) == TYPE_CODE_RANGE)
> - {
> - low_bound = TYPE_LOW_BOUND (index_type);
> - if (low_bound > TYPE_HIGH_BOUND (index_type))
> - return 0;
> - index_type = TYPE_TARGET_TYPE (index_type);
> - }
> - else
> +
> + if (!ada_get_array_low_bound_and_type (type, &low_bound, &index_type))
> return 0;
>
> switch (TYPE_CODE (index_type))
> @@ -137,16 +166,18 @@ val_print_packed_array_elements (struct
> unsigned int i;
> unsigned int things_printed = 0;
> unsigned len;
> - struct type *elttype;
> + struct type *elttype, *index_type;
> unsigned eltlen;
> unsigned long bitsize = TYPE_FIELD_BITSIZE (type, 0);
> struct value *mark = value_mark ();
> + LONGEST low = 0;
>
> elttype = TYPE_TARGET_TYPE (type);
> eltlen = TYPE_LENGTH (check_typedef (elttype));
> + index_type = TYPE_INDEX_TYPE (type);
>
> {
> - LONGEST low, high;
> + LONGEST high;
> if (get_discrete_bounds (TYPE_FIELD_TYPE (type, 0), &low, &high) < 0)
> len = 1;
> else
> @@ -174,6 +205,7 @@ val_print_packed_array_elements (struct
> }
> }
> wrap_here (n_spaces (2 + 2 * recurse));
> + maybe_print_array_index (index_type, i + low, stream, format, pretty);
>
> i0 = i;
> v0 = ada_value_primitive_packed_val (NULL, valaddr,
> @@ -219,6 +251,8 @@ val_print_packed_array_elements (struct
> fprintf_filtered (stream, ", ");
> }
> wrap_here (n_spaces (2 + 2 * recurse));
> + maybe_print_array_index (index_type, j + low,
> + stream, format, pretty);
> }
> val_print (elttype, value_contents (v0), 0, 0, stream, format,
> 0, recurse + 1, pretty);
> @@ -824,7 +858,11 @@ ada_val_print_1 (struct type *type, cons
> }
> else
> {
> + long low_bound = 0;
> +
> len = 0;
> + ada_get_array_low_bound_and_type (type, &low_bound, NULL);
> +
> fprintf_filtered (stream, "(");
> print_optional_low_bound (stream, type);
> if (TYPE_FIELD_BITSIZE (type, 0) > 0)
> @@ -833,7 +871,7 @@ ada_val_print_1 (struct type *type, cons
> else
> val_print_array_elements (type, valaddr, address, stream,
> format, deref_ref, recurse,
> - pretty, 0);
> + pretty, 0, low_bound);
> fprintf_filtered (stream, ")");
> }
> gdb_flush (stream);

--
Joel