[14/55] Introduce value_print_array_elements

Message ID 20191208182958.10181-15-tom@tromey.com
State New, archived
Headers

Commit Message

Tom Tromey Dec. 8, 2019, 6:29 p.m. UTC
  This introduces value_print_array_elements, which is an analogue of
val_print_array_elements that uses the value API.

gdb/ChangeLog
2019-12-08  Tom Tromey  <tom@tromey.com>

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

Change-Id: I82d7666ce30b8cae3689fbf392177b08ef861a3b
---
 gdb/ChangeLog  |   5 ++
 gdb/valprint.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/valprint.h |   6 +++
 3 files changed, 137 insertions(+)
  

Comments

Simon Marchi Jan. 15, 2020, 5:15 a.m. UTC | #1
On 2019-12-08 1:29 p.m., Tom Tromey wrote:
> This introduces value_print_array_elements, which is an analogue of
> val_print_array_elements that uses the value API.
> 
> gdb/ChangeLog
> 2019-12-08  Tom Tromey  <tom@tromey.com>
> 
> 	* valprint.c (value_print_array_elements): New function.
> 	* valprint.h (value_print_array_elements): Declare.
> 
> Change-Id: I82d7666ce30b8cae3689fbf392177b08ef861a3b
> ---
>  gdb/ChangeLog  |   5 ++
>  gdb/valprint.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++
>  gdb/valprint.h |   6 +++
>  3 files changed, 137 insertions(+)
> 
> diff --git a/gdb/valprint.c b/gdb/valprint.c
> index d09a42926e2..b2506dc6fc4 100644
> --- a/gdb/valprint.c
> +++ b/gdb/valprint.c
> @@ -2184,6 +2184,132 @@ 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, ", ");
> +	    }

You could remove these extra braces.

Simon
  
Tom Tromey Jan. 23, 2020, 11:37 p.m. UTC | #2
>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:

>> +	  else
>> +	    {
>> +	      fprintf_filtered (stream, ", ");
>> +	    }

Simon> You could remove these extra braces.

Done.

Tom
  

Patch

diff --git a/gdb/valprint.c b/gdb/valprint.c
index d09a42926e2..b2506dc6fc4 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -2184,6 +2184,132 @@  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
diff --git a/gdb/valprint.h b/gdb/valprint.h
index f1c93aa26b6..68b1083c742 100644
--- a/gdb/valprint.h
+++ b/gdb/valprint.h
@@ -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 *,