612 lines
22 KiB
Diff
612 lines
22 KiB
Diff
|
From: Christoph Weinmann <christoph.t.weinmann@intel.com>
|
||
|
[PATCH 1/6] fortran: allow multi-dimensional subarrays
|
||
|
https://sourceware.org/ml/gdb-patches/2015-12/msg00007.html
|
||
|
Message-Id: <1448976075-11456-2-git-send-email-christoph.t.weinmann@intel.com>
|
||
|
|
||
|
Add an argument count for subrange expressions in Fortran.
|
||
|
Based on the counted value calculate a new array with the
|
||
|
elements specified by the user. First parse the user input,
|
||
|
secondly copy the desired array values into the return
|
||
|
array, thirdly re-create the necessary ranges and bounds.
|
||
|
|
||
|
1| program prog
|
||
|
2| integer :: ary(10,5) = (/ (i,i=1,10) (j, j=1,5) /)
|
||
|
3| end program prog
|
||
|
|
||
|
(gdb) print ary(2:4,1:3)
|
||
|
old> Syntax error in expression near ':3'
|
||
|
new> $3 = ( ( 21, 31, 41) ( 22, 32, 42) ( 23, 33, 43) )
|
||
|
|
||
|
2013-11-25 Christoph Weinmann <christoph.t.weinmann@intel.com>
|
||
|
|
||
|
* eval.c (multi_f77_subscript): Remove function.
|
||
|
* eval.c (evaluate_subrange_expr): When evaluating
|
||
|
an array or string expression, call
|
||
|
value_f90_subarray.
|
||
|
* eval.c (value_f90_subarray): Add argument parsing
|
||
|
and compute result array based on user input.
|
||
|
* f-exp.y: Increment argument counter for every subrange
|
||
|
expression entered by the user.
|
||
|
* valops.c (value_slice): Call value_slice_1 with
|
||
|
additional default argument.
|
||
|
* valops.c (value_slice_1): Add functionality to
|
||
|
copy and return result values based on input.
|
||
|
* value.h: Add function definition.
|
||
|
|
||
|
|
||
|
|
||
|
Signed-off-by: Christoph Weinmann <christoph.t.weinmann@intel.com>
|
||
|
---
|
||
|
gdb/eval.c | 309 ++++++++++++++++++++++++++++++++++++++++++++++------------
|
||
|
gdb/f-exp.y | 2 +
|
||
|
gdb/valops.c | 157 ++++++++++++++++++++++++------
|
||
|
gdb/value.h | 2 +
|
||
|
4 files changed, 375 insertions(+), 95 deletions(-)
|
||
|
|
||
|
diff --git a/gdb/eval.c b/gdb/eval.c
|
||
|
index 84e2e34..2ceccbc 100644
|
||
|
--- a/gdb/eval.c
|
||
|
+++ b/gdb/eval.c
|
||
|
@@ -399,29 +399,253 @@ init_array_element (struct value *array, struct value *element,
|
||
|
return index;
|
||
|
}
|
||
|
|
||
|
+/* Evaluates any operation on Fortran arrays or strings with at least
|
||
|
+ one user provided parameter. Expects the input ARRAY to be either
|
||
|
+ an array, or a string. Evaluates EXP by incrementing POS, and
|
||
|
+ writes the content from the elt stack into a local struct. NARGS
|
||
|
+ specifies number of literal or range arguments the user provided.
|
||
|
+ NARGS must be the same number as ARRAY has dimensions. */
|
||
|
+
|
||
|
static struct value *
|
||
|
-value_f90_subarray (struct value *array,
|
||
|
- struct expression *exp, int *pos, enum noside noside)
|
||
|
+value_f90_subarray (struct value *array, struct expression *exp,
|
||
|
+ int *pos, int nargs, enum noside noside)
|
||
|
{
|
||
|
- int pc = (*pos) + 1;
|
||
|
+ int i, dim_count = 0;
|
||
|
LONGEST low_bound, high_bound;
|
||
|
struct type *range = check_typedef (TYPE_INDEX_TYPE (value_type (array)));
|
||
|
- enum f90_range_type range_type
|
||
|
- = (enum f90_range_type) longest_to_int (exp->elts[pc].longconst);
|
||
|
-
|
||
|
- *pos += 3;
|
||
|
+ struct value *new_array = array;
|
||
|
+ struct type *array_type = check_typedef (value_type (new_array));
|
||
|
+ struct type *temp_type;
|
||
|
+
|
||
|
+ /* Local struct to hold user data for Fortran subarray dimensions. */
|
||
|
+ struct subscript_store
|
||
|
+ {
|
||
|
+ /* For every dimension, we are either working on a range or an index
|
||
|
+ expression, so we store this info separately for later. */
|
||
|
+ enum
|
||
|
+ {
|
||
|
+ SUBSCRIPT_RANGE, /* e.g. "(lowbound:highbound)" */
|
||
|
+ SUBSCRIPT_INDEX /* e.g. "(literal)" */
|
||
|
+ } kind;
|
||
|
+
|
||
|
+ /* We also store either the lower and upper bound info, or the index
|
||
|
+ number. Before evaluation of the input values, we do not know if we are
|
||
|
+ actually working on a range of ranges, or an index in a range. So as a
|
||
|
+ first step we store all input in a union. The array calculation itself
|
||
|
+ deals with this later on. */
|
||
|
+ union
|
||
|
+ {
|
||
|
+ struct subscript_range
|
||
|
+ {
|
||
|
+ enum f90_range_type f90_range_type;
|
||
|
+ LONGEST low, high;
|
||
|
+ }
|
||
|
+ range;
|
||
|
+ LONGEST number;
|
||
|
+ };
|
||
|
+ } *subscript_array;
|
||
|
+
|
||
|
+ /* Check if the number of arguments provided by the user matches
|
||
|
+ the number of dimension of the array. A string has only one
|
||
|
+ dimension. */
|
||
|
+ if (nargs != calc_f77_array_dims (value_type (new_array)))
|
||
|
+ error (_("Wrong number of subscripts"));
|
||
|
+
|
||
|
+ subscript_array = alloca (sizeof (*subscript_array) * nargs);
|
||
|
+
|
||
|
+ /* Parse the user input into the SUBSCRIPT_ARRAY to store it. We need
|
||
|
+ to evaluate it first, as the input is from left-to-right. The
|
||
|
+ array is stored from right-to-left. So we have to use the user
|
||
|
+ input in reverse order. Later on, we need the input information to
|
||
|
+ re-calculate the output array. For multi-dimensional arrays, we
|
||
|
+ can be dealing with any possible combination of ranges and indices
|
||
|
+ for every dimension. */
|
||
|
+ for (i = 0; i < nargs; i++)
|
||
|
+ {
|
||
|
+ struct subscript_store *index = &subscript_array[i];
|
||
|
|
||
|
- if (range_type == LOW_BOUND_DEFAULT || range_type == BOTH_BOUND_DEFAULT)
|
||
|
- low_bound = TYPE_LOW_BOUND (range);
|
||
|
- else
|
||
|
- low_bound = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
|
||
|
+ /* The user input is a range, with or without lower and upper bound.
|
||
|
+ E.g.: "p arry(2:5)", "p arry( :5)", "p arry( : )", etc. */
|
||
|
+ if (exp->elts[*pos].opcode == OP_F90_RANGE)
|
||
|
+ {
|
||
|
+ int pc = (*pos) + 1;
|
||
|
+ struct subscript_range *range;
|
||
|
+
|
||
|
+ index->kind = SUBSCRIPT_RANGE;
|
||
|
+ range = &index->range;
|
||
|
+
|
||
|
+ *pos += 3;
|
||
|
+ range->f90_range_type = longest_to_int (exp->elts[pc].longconst);
|
||
|
+
|
||
|
+ /* If a lower bound was provided by the user, the bit has been
|
||
|
+ set and we can assign the value from the elt stack. Same for
|
||
|
+ upper bound. */
|
||
|
+ if ((range->f90_range_type == HIGH_BOUND_DEFAULT)
|
||
|
+ || range->f90_range_type == NONE_BOUND_DEFAULT)
|
||
|
+ range->low = value_as_long (evaluate_subexp (NULL_TYPE, exp,
|
||
|
+ pos, noside));
|
||
|
+ if ((range->f90_range_type == LOW_BOUND_DEFAULT)
|
||
|
+ || range->f90_range_type == NONE_BOUND_DEFAULT)
|
||
|
+ range->high = value_as_long (evaluate_subexp (NULL_TYPE, exp,
|
||
|
+ pos, noside));
|
||
|
+ }
|
||
|
+ /* User input is an index. E.g.: "p arry(5)". */
|
||
|
+ else
|
||
|
+ {
|
||
|
+ struct value *val;
|
||
|
|
||
|
- if (range_type == HIGH_BOUND_DEFAULT || range_type == BOTH_BOUND_DEFAULT)
|
||
|
- high_bound = TYPE_HIGH_BOUND (range);
|
||
|
- else
|
||
|
- high_bound = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
|
||
|
+ index->kind = SUBSCRIPT_INDEX;
|
||
|
+
|
||
|
+ /* Evaluate each subscript; it must be a legal integer in F77. This
|
||
|
+ ensures the validity of the provided index. */
|
||
|
+ val = evaluate_subexp_with_coercion (exp, pos, noside);
|
||
|
+ index->number = value_as_long (val);
|
||
|
+ }
|
||
|
+
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Traverse the array from right to left and evaluate each corresponding
|
||
|
+ user input. VALUE_SUBSCRIPT is called for every index, until a range
|
||
|
+ expression is evaluated. After a range expression has been evaluated,
|
||
|
+ every subsequent expression is also treated as a range. */
|
||
|
+ for (i = nargs - 1; i >= 0; i--)
|
||
|
+ {
|
||
|
+ struct subscript_store *index = &subscript_array[i];
|
||
|
+ struct type *index_type = TYPE_INDEX_TYPE (array_type);
|
||
|
+
|
||
|
+ switch (index->kind)
|
||
|
+ {
|
||
|
+ case SUBSCRIPT_RANGE:
|
||
|
+ {
|
||
|
+
|
||
|
+ /* When we hit the first range specified by the user, we must
|
||
|
+ treat any subsequent user entry as a range. We simply
|
||
|
+ increment DIM_COUNT which tells us how many times we are
|
||
|
+ calling VALUE_SLICE_1. */
|
||
|
+ struct subscript_range *range = &index->range;
|
||
|
+
|
||
|
+ /* If no lower bound was provided by the user, we take the
|
||
|
+ default boundary. Same for the high bound. */
|
||
|
+ if ((range->f90_range_type == LOW_BOUND_DEFAULT)
|
||
|
+ || (range->f90_range_type == BOTH_BOUND_DEFAULT))
|
||
|
+ range->low = TYPE_LOW_BOUND (index_type);
|
||
|
+
|
||
|
+ if ((range->f90_range_type == HIGH_BOUND_DEFAULT)
|
||
|
+ || (range->f90_range_type == BOTH_BOUND_DEFAULT))
|
||
|
+ range->high = TYPE_HIGH_BOUND (index_type);
|
||
|
+
|
||
|
+ /* Both user provided low and high bound have to be inside the
|
||
|
+ array bounds. Throw an error if not. */
|
||
|
+ if (range->low < TYPE_LOW_BOUND (index_type)
|
||
|
+ || range->low > TYPE_HIGH_BOUND (index_type)
|
||
|
+ || range->high < TYPE_LOW_BOUND (index_type)
|
||
|
+ || range->high > TYPE_HIGH_BOUND (index_type))
|
||
|
+ error (_("provided bound(s) outside array bound(s)"));
|
||
|
+
|
||
|
+ /* DIM_COUNT counts every user argument that is treated as a range.
|
||
|
+ This is necessary for expressions like 'print array(7, 8:9).
|
||
|
+ Here the first argument is a literal, but must be treated as a
|
||
|
+ range argument to allow the correct output representation. */
|
||
|
+ dim_count++;
|
||
|
+
|
||
|
+ new_array
|
||
|
+ = value_slice_1 (new_array,
|
||
|
+ longest_to_int (range->low),
|
||
|
+ longest_to_int (range->high - range->low + 1),
|
||
|
+ dim_count);
|
||
|
+ }
|
||
|
+ break;
|
||
|
+
|
||
|
+ case SUBSCRIPT_INDEX:
|
||
|
+ {
|
||
|
+ /* DIM_COUNT only stays '0' when no range argument was processed
|
||
|
+ before, starting from the last dimension. This way we can
|
||
|
+ reduce the number of dimensions from the result array.
|
||
|
+ However, if a range has been processed before an index, we
|
||
|
+ treat the index like a range with equal low- and high bounds
|
||
|
+ to get the value offset right. */
|
||
|
+ if (dim_count == 0)
|
||
|
+ new_array
|
||
|
+ = value_subscripted_rvalue (new_array, index->number,
|
||
|
+ f77_get_lowerbound (value_type
|
||
|
+ (new_array)));
|
||
|
+ else
|
||
|
+ {
|
||
|
+ /* Check for valid index input. */
|
||
|
+ if (index->number < TYPE_LOW_BOUND (index_type)
|
||
|
+ || index->number > TYPE_HIGH_BOUND (index_type))
|
||
|
+ error (_("error no such vector element"));
|
||
|
+
|
||
|
+ dim_count++;
|
||
|
+ new_array = value_slice_1 (new_array,
|
||
|
+ longest_to_int (index->number),
|
||
|
+ 1, /* length is '1' element */
|
||
|
+ dim_count);
|
||
|
+ }
|
||
|
+
|
||
|
+ }
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ /* With DIM_COUNT > 1 we currently have a one dimensional array, but expect
|
||
|
+ an array of arrays, depending on how many ranges have been provided by
|
||
|
+ the user. So we need to rebuild the array dimensions for printing it
|
||
|
+ correctly.
|
||
|
+ Starting from right to left in the user input, after we hit the first
|
||
|
+ range argument every subsequent argument is also treated as a range.
|
||
|
+ E.g.:
|
||
|
+ "p ary(3, 7, 2:15)" in Fortran has only 1 dimension, but we calculated 3
|
||
|
+ ranges.
|
||
|
+ "p ary(3, 7:12, 4)" in Fortran has only 1 dimension, but we calculated 2
|
||
|
+ ranges.
|
||
|
+ "p ary(2:4, 5, 7)" in Fortran has only 1 dimension, and we calculated 1
|
||
|
+ range. */
|
||
|
+ if (dim_count > 1)
|
||
|
+ {
|
||
|
+ struct value *v = NULL;
|
||
|
|
||
|
- return value_slice (array, low_bound, high_bound - low_bound + 1);
|
||
|
+ temp_type = TYPE_TARGET_TYPE (value_type (new_array));
|
||
|
+
|
||
|
+ /* Every SUBSCRIPT_RANGE in the user input signifies an actual range in
|
||
|
+ the output array. So we traverse the SUBSCRIPT_ARRAY again, looking
|
||
|
+ for a range entry. When we find one, we use the range info to create
|
||
|
+ an additional range_type to set the correct bounds and dimensions for
|
||
|
+ the output array. */
|
||
|
+ for (i = 0; i < nargs; i++)
|
||
|
+ {
|
||
|
+ struct subscript_store *index = &subscript_array[i];
|
||
|
+
|
||
|
+ if (index->kind == SUBSCRIPT_RANGE)
|
||
|
+ {
|
||
|
+ struct type *range_type, *interim_array_type;
|
||
|
+
|
||
|
+ range_type
|
||
|
+ = create_static_range_type (NULL,
|
||
|
+ temp_type,
|
||
|
+ 1,
|
||
|
+ index->range.high - index->range.low + 1);
|
||
|
+
|
||
|
+ interim_array_type = create_array_type (NULL,
|
||
|
+ temp_type,
|
||
|
+ range_type);
|
||
|
+
|
||
|
+ /* For some reason the type code of the contents is missing, so
|
||
|
+ reset it from the original array. */
|
||
|
+ TYPE_CODE (interim_array_type)
|
||
|
+ = TYPE_CODE (value_type (new_array));
|
||
|
+
|
||
|
+ v = allocate_value (interim_array_type);
|
||
|
+
|
||
|
+ temp_type = value_type (v);
|
||
|
+ }
|
||
|
+
|
||
|
+ }
|
||
|
+ value_contents_copy (v, 0, new_array, 0, TYPE_LENGTH (temp_type));
|
||
|
+ return v;
|
||
|
+ }
|
||
|
+
|
||
|
+ return new_array;
|
||
|
}
|
||
|
|
||
|
|
||
|
@@ -1810,14 +2034,11 @@ evaluate_subexp_standard (struct type *expect_type,
|
||
|
switch (code)
|
||
|
{
|
||
|
case TYPE_CODE_ARRAY:
|
||
|
- if (exp->elts[*pos].opcode == OP_F90_RANGE)
|
||
|
- return value_f90_subarray (arg1, exp, pos, noside);
|
||
|
- else
|
||
|
- goto multi_f77_subscript;
|
||
|
+ return value_f90_subarray (arg1, exp, pos, nargs, noside);
|
||
|
|
||
|
case TYPE_CODE_STRING:
|
||
|
if (exp->elts[*pos].opcode == OP_F90_RANGE)
|
||
|
- return value_f90_subarray (arg1, exp, pos, noside);
|
||
|
+ return value_f90_subarray (arg1, exp, pos, 1, noside);
|
||
|
else
|
||
|
{
|
||
|
arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||
|
@@ -2222,49 +2443,6 @@ evaluate_subexp_standard (struct type *expect_type,
|
||
|
}
|
||
|
return (arg1);
|
||
|
|
||
|
- multi_f77_subscript:
|
||
|
- {
|
||
|
- LONGEST subscript_array[MAX_FORTRAN_DIMS];
|
||
|
- int ndimensions = 1, i;
|
||
|
- struct value *array = arg1;
|
||
|
-
|
||
|
- if (nargs > MAX_FORTRAN_DIMS)
|
||
|
- error (_("Too many subscripts for F77 (%d Max)"), MAX_FORTRAN_DIMS);
|
||
|
-
|
||
|
- ndimensions = calc_f77_array_dims (type);
|
||
|
-
|
||
|
- if (nargs != ndimensions)
|
||
|
- error (_("Wrong number of subscripts"));
|
||
|
-
|
||
|
- gdb_assert (nargs > 0);
|
||
|
-
|
||
|
- /* Now that we know we have a legal array subscript expression
|
||
|
- let us actually find out where this element exists in the array. */
|
||
|
-
|
||
|
- /* Take array indices left to right. */
|
||
|
- for (i = 0; i < nargs; i++)
|
||
|
- {
|
||
|
- /* Evaluate each subscript; it must be a legal integer in F77. */
|
||
|
- arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||
|
-
|
||
|
- /* Fill in the subscript array. */
|
||
|
-
|
||
|
- subscript_array[i] = value_as_long (arg2);
|
||
|
- }
|
||
|
-
|
||
|
- /* Internal type of array is arranged right to left. */
|
||
|
- for (i = nargs; i > 0; i--)
|
||
|
- {
|
||
|
- struct type *array_type = check_typedef (value_type (array));
|
||
|
- LONGEST index = subscript_array[i - 1];
|
||
|
-
|
||
|
- array = value_subscripted_rvalue (array, index,
|
||
|
- f77_get_lowerbound (array_type));
|
||
|
- }
|
||
|
-
|
||
|
- return array;
|
||
|
- }
|
||
|
-
|
||
|
case BINOP_LOGICAL_AND:
|
||
|
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
|
||
|
if (noside == EVAL_SKIP)
|
||
|
@@ -3121,6 +3299,9 @@ calc_f77_array_dims (struct type *array_type)
|
||
|
int ndimen = 1;
|
||
|
struct type *tmp_type;
|
||
|
|
||
|
+ if (TYPE_CODE (array_type) == TYPE_CODE_STRING)
|
||
|
+ return 1;
|
||
|
+
|
||
|
if ((TYPE_CODE (array_type) != TYPE_CODE_ARRAY))
|
||
|
error (_("Can't get dimensions for a non-array type"));
|
||
|
|
||
|
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
|
||
|
index 56629dc..ab23df0 100644
|
||
|
--- a/gdb/f-exp.y
|
||
|
+++ b/gdb/f-exp.y
|
||
|
@@ -308,6 +308,8 @@ arglist : subrange
|
||
|
|
||
|
arglist : arglist ',' exp %prec ABOVE_COMMA
|
||
|
{ arglist_len++; }
|
||
|
+ | arglist ',' subrange %prec ABOVE_COMMA
|
||
|
+ { arglist_len++; }
|
||
|
;
|
||
|
|
||
|
/* There are four sorts of subrange types in F90. */
|
||
|
diff --git a/gdb/valops.c b/gdb/valops.c
|
||
|
index 5e5f685..f8d23fb 100644
|
||
|
--- a/gdb/valops.c
|
||
|
+++ b/gdb/valops.c
|
||
|
@@ -3759,56 +3759,151 @@ value_of_this_silent (const struct language_defn *lang)
|
||
|
struct value *
|
||
|
value_slice (struct value *array, int lowbound, int length)
|
||
|
{
|
||
|
+ /* Pass unaltered arguments to VALUE_SLICE_1, plus a CALL_COUNT of '1' as we
|
||
|
+ are only considering the highest dimension, or we are working on a one
|
||
|
+ dimensional array. So we call VALUE_SLICE_1 exactly once. */
|
||
|
+ return value_slice_1 (array, lowbound, length, 1);
|
||
|
+}
|
||
|
+
|
||
|
+/* CALL_COUNT is used to determine if we are calling the function once, e.g.
|
||
|
+ we are working on the current dimension of ARRAY, or if we are calling
|
||
|
+ the function repeatedly. In the later case we need to take elements
|
||
|
+ from the TARGET_TYPE of ARRAY.
|
||
|
+ With a CALL_COUNT greater than 1 we calculate the offsets for every element
|
||
|
+ that should be in the result array. Then we fetch the contents and then
|
||
|
+ copy them into the result array. The result array will have one dimension
|
||
|
+ less than the input array, so later on we need to recreate the indices and
|
||
|
+ ranges in the calling function. */
|
||
|
+
|
||
|
+struct value *
|
||
|
+value_slice_1 (struct value *array, int lowbound, int length, int call_count)
|
||
|
+{
|
||
|
struct type *slice_range_type, *slice_type, *range_type;
|
||
|
- LONGEST lowerbound, upperbound;
|
||
|
- struct value *slice;
|
||
|
- struct type *array_type;
|
||
|
+ struct type *array_type = check_typedef (value_type (array));
|
||
|
+ struct type *elt_type = check_typedef (TYPE_TARGET_TYPE (array_type));
|
||
|
+ unsigned int elt_size, elt_offs;
|
||
|
+ LONGEST elt_stride, ary_high_bound, ary_low_bound;
|
||
|
+ struct value *v;
|
||
|
+ int slice_range_size, i = 0, row_count = 1, elem_count = 1;
|
||
|
|
||
|
- array_type = check_typedef (value_type (array));
|
||
|
+ /* Check for legacy code if we are actually dealing with an array or
|
||
|
+ string. */
|
||
|
if (TYPE_CODE (array_type) != TYPE_CODE_ARRAY
|
||
|
&& TYPE_CODE (array_type) != TYPE_CODE_STRING)
|
||
|
error (_("cannot take slice of non-array"));
|
||
|
|
||
|
- range_type = TYPE_INDEX_TYPE (array_type);
|
||
|
- if (get_discrete_bounds (range_type, &lowerbound, &upperbound) < 0)
|
||
|
- error (_("slice from bad array or bitstring"));
|
||
|
+ ary_low_bound = TYPE_LOW_BOUND (TYPE_INDEX_TYPE (array_type));
|
||
|
+ ary_high_bound = TYPE_HIGH_BOUND (TYPE_INDEX_TYPE (array_type));
|
||
|
+
|
||
|
+ /* When we are working on a multi-dimensional array, we need to get the
|
||
|
+ attributes of the underlying type. */
|
||
|
+ if (call_count > 1)
|
||
|
+ {
|
||
|
+ elt_type = check_typedef (TYPE_TARGET_TYPE (elt_type));
|
||
|
+ row_count = TYPE_LENGTH (array_type)
|
||
|
+ / TYPE_LENGTH (TYPE_TARGET_TYPE (array_type));
|
||
|
+ }
|
||
|
+
|
||
|
+ elem_count = length;
|
||
|
+ elt_size = TYPE_LENGTH (elt_type);
|
||
|
+ elt_offs = longest_to_int (lowbound - ary_low_bound);
|
||
|
+ elt_stride = TYPE_LENGTH (TYPE_INDEX_TYPE (array_type));
|
||
|
+
|
||
|
+ elt_offs *= elt_size;
|
||
|
+
|
||
|
+ /* Check for valid user input. In case of Fortran this was already done
|
||
|
+ in the calling function. */
|
||
|
+ if (call_count == 1
|
||
|
+ && (!TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (array_type)
|
||
|
+ && elt_offs >= TYPE_LENGTH (array_type)))
|
||
|
+ error (_("no such vector element"));
|
||
|
|
||
|
- if (lowbound < lowerbound || length < 0
|
||
|
- || lowbound + length - 1 > upperbound)
|
||
|
- error (_("slice out of range"));
|
||
|
+ /* CALL_COUNT is 1 when we are dealing either with the highest dimension
|
||
|
+ of the array, or a one dimensional array. Set RANGE_TYPE accordingly.
|
||
|
+ In both cases we calculate how many rows/elements will be in the output
|
||
|
+ array by setting slice_range_size. */
|
||
|
+ if (call_count == 1)
|
||
|
+ {
|
||
|
+ range_type = TYPE_INDEX_TYPE (array_type);
|
||
|
+ slice_range_size = elem_count;
|
||
|
+
|
||
|
+ /* Check if the array bounds are valid. */
|
||
|
+ if (get_discrete_bounds (range_type, &ary_low_bound, &ary_high_bound) < 0)
|
||
|
+ error (_("slice from bad array or bitstring"));
|
||
|
+ }
|
||
|
+ /* When CALL_COUNT is greater than 1, we are dealing with an array of arrays.
|
||
|
+ So we need to get the type below the current one and set the RANGE_TYPE
|
||
|
+ accordingly. */
|
||
|
+ else
|
||
|
+ {
|
||
|
+ range_type = TYPE_INDEX_TYPE (TYPE_TARGET_TYPE (array_type));
|
||
|
+ slice_range_size = (ary_low_bound + row_count - 1) * (elem_count);
|
||
|
+ ary_low_bound = TYPE_LOW_BOUND (range_type);
|
||
|
+ }
|
||
|
|
||
|
/* FIXME-type-allocation: need a way to free this type when we are
|
||
|
- done with it. */
|
||
|
- slice_range_type = create_static_range_type ((struct type *) NULL,
|
||
|
- TYPE_TARGET_TYPE (range_type),
|
||
|
- lowbound,
|
||
|
- lowbound + length - 1);
|
||
|
+ done with it. */
|
||
|
|
||
|
+ slice_range_type = create_static_range_type (NULL, TYPE_TARGET_TYPE (range_type),
|
||
|
+ ary_low_bound, slice_range_size);
|
||
|
{
|
||
|
- struct type *element_type = TYPE_TARGET_TYPE (array_type);
|
||
|
- LONGEST offset
|
||
|
- = (lowbound - lowerbound) * TYPE_LENGTH (check_typedef (element_type));
|
||
|
+ struct type *element_type;
|
||
|
+
|
||
|
+ /* When CALL_COUNT equals 1 we can use the legacy code for subarrays. */
|
||
|
+ if (call_count == 1)
|
||
|
+ {
|
||
|
+ element_type = TYPE_TARGET_TYPE (array_type);
|
||
|
|
||
|
- slice_type = create_array_type ((struct type *) NULL,
|
||
|
- element_type,
|
||
|
- slice_range_type);
|
||
|
- TYPE_CODE (slice_type) = TYPE_CODE (array_type);
|
||
|
+ slice_type = create_array_type (NULL, element_type, slice_range_type);
|
||
|
+
|
||
|
+ TYPE_CODE (slice_type) = TYPE_CODE (array_type);
|
||
|
+
|
||
|
+ if (VALUE_LVAL (array) == lval_memory && value_lazy (array))
|
||
|
+ v = allocate_value_lazy (slice_type);
|
||
|
+ else
|
||
|
+ {
|
||
|
+ v = allocate_value (slice_type);
|
||
|
+ value_contents_copy (v,
|
||
|
+ value_embedded_offset (v),
|
||
|
+ array,
|
||
|
+ value_embedded_offset (array) + elt_offs,
|
||
|
+ elt_size * longest_to_int (length));
|
||
|
+ }
|
||
|
|
||
|
- if (VALUE_LVAL (array) == lval_memory && value_lazy (array))
|
||
|
- slice = allocate_value_lazy (slice_type);
|
||
|
+ }
|
||
|
+ /* When CALL_COUNT is larger than 1 we are working on a range of ranges.
|
||
|
+ So we copy the relevant elements into the new array we return. */
|
||
|
else
|
||
|
{
|
||
|
- slice = allocate_value (slice_type);
|
||
|
- value_contents_copy (slice, 0, array, offset,
|
||
|
- type_length_units (slice_type));
|
||
|
+ LONGEST dst_offset = 0;
|
||
|
+ LONGEST src_row_length = TYPE_LENGTH (TYPE_TARGET_TYPE (array_type));
|
||
|
+
|
||
|
+ element_type = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (array_type));
|
||
|
+ slice_type = create_array_type (NULL, element_type, slice_range_type);
|
||
|
+
|
||
|
+ TYPE_CODE (slice_type) = TYPE_CODE (TYPE_TARGET_TYPE (array_type));
|
||
|
+
|
||
|
+ v = allocate_value (slice_type);
|
||
|
+ for (i = 0; i < longest_to_int (row_count); i++)
|
||
|
+ {
|
||
|
+ /* Fetches the contents of ARRAY and copies them into V. */
|
||
|
+ value_contents_copy (v,
|
||
|
+ dst_offset,
|
||
|
+ array,
|
||
|
+ elt_offs,
|
||
|
+ elt_size * elem_count);
|
||
|
+ elt_offs += src_row_length;
|
||
|
+ dst_offset += elt_size * elem_count;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
- set_value_component_location (slice, array);
|
||
|
- VALUE_FRAME_ID (slice) = VALUE_FRAME_ID (array);
|
||
|
- set_value_offset (slice, value_offset (array) + offset);
|
||
|
+ set_value_component_location (v, array);
|
||
|
+ VALUE_REGNUM (v) = VALUE_REGNUM (array);
|
||
|
+ VALUE_FRAME_ID (v) = VALUE_FRAME_ID (array);
|
||
|
+ set_value_offset (v, value_offset (array) + elt_offs);
|
||
|
}
|
||
|
|
||
|
- return slice;
|
||
|
+ return v;
|
||
|
}
|
||
|
|
||
|
/* Create a value for a FORTRAN complex number. Currently most of the
|
||
|
diff --git a/gdb/value.h b/gdb/value.h
|
||
|
index eea0e59..05939c4 100644
|
||
|
--- a/gdb/value.h
|
||
|
+++ b/gdb/value.h
|
||
|
@@ -1056,6 +1056,8 @@ extern struct value *varying_to_slice (struct value *);
|
||
|
|
||
|
extern struct value *value_slice (struct value *, int, int);
|
||
|
|
||
|
+extern struct value *value_slice_1 (struct value *, int, int, int);
|
||
|
+
|
||
|
extern struct value *value_literal_complex (struct value *, struct value *,
|
||
|
struct type *);
|
||
|
|
||
|
--
|
||
|
1.7.0.7
|