Introduce value_print_array_elements
authorTom Tromey <tom@tromey.com>
Fri, 13 Mar 2020 23:39:52 +0000 (17:39 -0600)
committerTom Tromey <tom@tromey.com>
Sat, 14 Mar 2020 00:03:40 +0000 (18:03 -0600)
This introduces value_print_array_elements, which is an analogue of
val_print_array_elements that uses the value API.

gdb/ChangeLog
2020-03-13  Tom Tromey  <tom@tromey.com>

* valprint.c (value_print_array_elements): New function.
* valprint.h (value_print_array_elements): Declare.

gdb/ChangeLog
gdb/valprint.c
gdb/valprint.h

index 2c97ac85a4603987de1abc4cdf3c7ade09daf6e5..f47c14fc09c1f42a06a85b1267f055cf095d094e 100644 (file)
@@ -1,3 +1,8 @@
+2020-03-13  Tom Tromey  <tom@tromey.com>
+
+       * valprint.c (value_print_array_elements): New function.
+       * valprint.h (value_print_array_elements): Declare.
+
 2020-03-13  Tom Tromey  <tom@tromey.com>
 
        * printcmd.c (print_formatted): Use value_print_scalar_formatted.
index 9cdf18ee864dc212c2c66a817a9dffb2037100c9..07f0a40ebdf3f8c26429aca448a755a3532fb03d 100644 (file)
@@ -2213,6 +2213,130 @@ val_print_array_elements (struct type *type,
     }
 }
 
+/* See valprint.h.  */
+
+void
+value_print_array_elements (struct value *val, struct ui_file *stream,
+                           int recurse,
+                           const struct value_print_options *options,
+                           unsigned int i)
+{
+  unsigned int things_printed = 0;
+  unsigned len;
+  struct type *elttype, *index_type, *base_index_type;
+  unsigned eltlen;
+  /* Position of the array element we are examining to see
+     whether it is repeated.  */
+  unsigned int rep1;
+  /* Number of repetitions we have detected so far.  */
+  unsigned int reps;
+  LONGEST low_bound, high_bound;
+  LONGEST low_pos, high_pos;
+
+  struct type *type = check_typedef (value_type (val));
+
+  elttype = TYPE_TARGET_TYPE (type);
+  eltlen = type_length_units (check_typedef (elttype));
+  index_type = TYPE_INDEX_TYPE (type);
+
+  if (get_array_bounds (type, &low_bound, &high_bound))
+    {
+      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_POS to be greater than HIGH_POS for
+        empty arrays.  In that situation, the array length is just zero,
+        not negative!  */
+      if (low_pos > high_pos)
+       len = 0;
+      else
+       len = high_pos - low_pos + 1;
+    }
+  else
+    {
+      warning (_("unable to get bounds of array, assuming null array"));
+      low_bound = 0;
+      len = 0;
+    }
+
+  annotate_array_section_begin (i, elttype);
+
+  for (; i < len && things_printed < options->print_max; i++)
+    {
+      scoped_value_mark free_values;
+
+      if (i != 0)
+       {
+         if (options->prettyformat_arrays)
+           {
+             fprintf_filtered (stream, ",\n");
+             print_spaces_filtered (2 + 2 * recurse, stream);
+           }
+         else
+           fprintf_filtered (stream, ", ");
+       }
+      wrap_here (n_spaces (2 + 2 * recurse));
+      maybe_print_array_index (index_type, i + low_bound,
+                               stream, options);
+
+      rep1 = i + 1;
+      reps = 1;
+      /* Only check for reps if repeat_count_threshold is not set to
+        UINT_MAX (unlimited).  */
+      if (options->repeat_count_threshold < UINT_MAX)
+       {
+         while (rep1 < len
+                && value_contents_eq (val, i * eltlen,
+                                      val, rep1 * eltlen,
+                                      eltlen))
+           {
+             ++reps;
+             ++rep1;
+           }
+       }
+
+      struct value *element = value_from_component (val, elttype, eltlen * i);
+      common_val_print (element, stream, recurse + 1, options,
+                       current_language);
+
+      if (reps > options->repeat_count_threshold)
+       {
+         annotate_elt_rep (reps);
+         fprintf_filtered (stream, " %p[<repeats %u times>%p]",
+                           metadata_style.style ().ptr (), reps, nullptr);
+         annotate_elt_rep_end ();
+
+         i = rep1 - 1;
+         things_printed += options->repeat_count_threshold;
+       }
+      else
+       {
+         annotate_elt ();
+         things_printed++;
+       }
+    }
+  annotate_array_section_end ();
+  if (i < len)
+    fprintf_filtered (stream, "...");
+}
+
 /* 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 a target_xfer_status value in the
index 90df12dbd7e2719d265795a91db8b9acebfe425a..20a42310a985e77ccaaf37b25620d9ace97d17e7 100644 (file)
@@ -134,6 +134,12 @@ extern void val_print_array_elements (struct type *, LONGEST,
                                      const struct value_print_options *,
                                      unsigned int);
 
+/* Print elements of an array.  */
+
+extern void value_print_array_elements (struct value *, struct ui_file *, int,
+                                       const struct value_print_options *,
+                                       unsigned int);
+
 extern void val_print_scalar_formatted (struct type *,
                                        LONGEST,
                                        struct value *,