diff options
author | Michael Tiemann <tiemann@cygnus> | 1993-02-01 01:12:37 +0000 |
---|---|---|
committer | Michael Tiemann <tiemann@cygnus> | 1993-02-01 01:12:37 +0000 |
commit | a163ddeca1312849cdcdabd3020c57fa92a7039a (patch) | |
tree | 0bf5ce472ab757c6a06cdcc7733a05576822e446 /gdb/valops.c | |
parent | edf67bd18137953e9258f07a3474052e595a7524 (diff) | |
download | gdb-a163ddeca1312849cdcdabd3020c57fa92a7039a.zip gdb-a163ddeca1312849cdcdabd3020c57fa92a7039a.tar.gz gdb-a163ddeca1312849cdcdabd3020c57fa92a7039a.tar.bz2 |
* valops.c (typecmp): Now static.
Diffstat (limited to 'gdb/valops.c')
-rw-r--r-- | gdb/valops.c | 282 |
1 files changed, 204 insertions, 78 deletions
diff --git a/gdb/valops.c b/gdb/valops.c index 0ac1f9f..c0931c5 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -50,7 +50,61 @@ search_struct_method PARAMS ((char *, value *, value *, int, int *, static int check_field_in PARAMS ((struct type *, const char *)); +static CORE_ADDR +allocate_space_in_inferior PARAMS ((int)); + +/* Allocate NBYTES of space in the inferior using the inferior's malloc + and return a value that is a pointer to the allocated space. */ + +static CORE_ADDR +allocate_space_in_inferior (len) + int len; +{ + register value val; + register struct symbol *sym; + struct minimal_symbol *msymbol; + struct type *type; + value blocklen; + LONGEST maddr; + + /* Find the address of malloc in the inferior. */ + + sym = lookup_symbol ("malloc", 0, VAR_NAMESPACE, 0, NULL); + if (sym != NULL) + { + if (SYMBOL_CLASS (sym) != LOC_BLOCK) + { + error ("\"malloc\" exists in this program but is not a function."); + } + val = value_of_variable (sym); + } + else + { + msymbol = lookup_minimal_symbol ("malloc", (struct objfile *) NULL); + if (msymbol != NULL) + { + type = lookup_pointer_type (builtin_type_char); + type = lookup_function_type (type); + type = lookup_pointer_type (type); + maddr = (LONGEST) SYMBOL_VALUE_ADDRESS (msymbol); + val = value_from_longest (type, maddr); + } + else + { + error ("evaluation of this expression requires the program to have a function \"malloc\"."); + } + } + + blocklen = value_from_longest (builtin_type_int, (LONGEST) len); + val = call_function_by_hand (val, 1, &blocklen); + if (value_logical_not (val)) + { + error ("No memory available to program."); + } + return (value_as_long (val)); +} + /* Cast value ARG2 to type TYPE and return as a value. More general than a C cast: accepts any two types of the same length, and if ARG2 is an lvalue it can be cast into anything at all. */ @@ -425,9 +479,28 @@ value_of_variable (var) return val; } -/* Given a value which is an array, return a value which is - a pointer to its first (actually, zeroth) element. - FIXME, this should be subtracting the array's lower bound. */ +/* Given a value which is an array, return a value which is a pointer to its + first element, regardless of whether or not the array has a nonzero lower + bound. + + FIXME: A previous comment here indicated that this routine should be + substracting the array's lower bound. It's not clear to me that this + is correct. Given an array subscripting operation, it would certainly + work to do the adjustment here, essentially computing: + + (&array[0] - (lowerbound * sizeof array[0])) + (index * sizeof array[0]) + + However I believe a more appropriate and logical place to account for + the lower bound is to do so in value_subscript, essentially computing: + + (&array[0] + ((index - lowerbound) * sizeof array[0])) + + As further evidence consider what would happen with operations other + than array subscripting, where the caller would get back a value that + had an address somewhere before the actual first element of the array, + and the information about the lower bound would be lost because of + the coercion to pointer type. + */ value value_coerce_array (arg1) @@ -917,54 +990,147 @@ call_function_by_hand (function, nargs, args) error ("Cannot invoke functions on this machine."); } #endif /* no CALL_DUMMY. */ + -/* Create a value for a string constant: - Call the function malloc in the inferior to get space for it, - then copy the data into that space - and then return the address with type char *. - PTR points to the string constant data; LEN is number of characters. - Note that the string may contain embedded null bytes. */ +/* Create a value for an array by allocating space in the inferior, copying + the data into that space, and then setting up an array value. + + The array bounds are set from LOWBOUND and HIGHBOUND, and the array is + populated from the values passed in ELEMVEC. + + The element type of the array is inherited from the type of the + first element, and all elements must have the same size (though we + don't currently enforce any restriction on their types). */ value -value_string (ptr, len) - char *ptr; - int len; +value_array (lowbound, highbound, elemvec) + int lowbound; + int highbound; + value *elemvec; { - register value val; - register struct symbol *sym; - value blocklen; + int nelem; + int idx; + int typelength; + value val; + struct type *rangetype; + struct type *arraytype; + CORE_ADDR addr; - /* Find the address of malloc in the inferior. */ + /* Validate that the bounds are reasonable and that each of the elements + have the same size. */ - sym = lookup_symbol ("malloc", 0, VAR_NAMESPACE, 0, NULL); - if (sym != NULL) + nelem = highbound - lowbound + 1; + if (nelem <= 0) { - if (SYMBOL_CLASS (sym) != LOC_BLOCK) - error ("\"malloc\" exists in this program but is not a function."); - val = value_of_variable (sym); + error ("bad array bounds (%d, %d)", lowbound, highbound); } - else + typelength = TYPE_LENGTH (VALUE_TYPE (elemvec[0])); + for (idx = 0; idx < nelem; idx++) { - struct minimal_symbol *msymbol; - msymbol = lookup_minimal_symbol ("malloc", (struct objfile *) NULL); - if (msymbol != NULL) - val = - value_from_longest (lookup_pointer_type (lookup_function_type ( - lookup_pointer_type (builtin_type_char))), - (LONGEST) SYMBOL_VALUE_ADDRESS (msymbol)); - else - error ("String constants require the program to have a function \"malloc\"."); + if (TYPE_LENGTH (VALUE_TYPE (elemvec[idx])) != typelength) + { + error ("array elements must all be the same size"); + } } - blocklen = value_from_longest (builtin_type_int, (LONGEST) (len + 1)); - val = call_function_by_hand (val, 1, &blocklen); - if (value_logical_not (val)) - error ("No memory available for string constant."); - write_memory (value_as_pointer (val), ptr, len + 1); - VALUE_TYPE (val) = lookup_pointer_type (builtin_type_char); - return val; + /* Allocate space to store the array in the inferior, and then initialize + it by copying in each element. FIXME: Is it worth it to create a + local buffer in which to collect each value and then write all the + bytes in one operation? */ + + addr = allocate_space_in_inferior (nelem * typelength); + for (idx = 0; idx < nelem; idx++) + { + write_memory (addr + (idx * typelength), VALUE_CONTENTS (elemvec[idx]), + typelength); + } + + /* Create the array type and set up an array value to be evaluated lazily. */ + + rangetype = create_range_type ((struct type *) NULL, builtin_type_int, + lowbound, highbound); + arraytype = create_array_type ((struct type *) NULL, + VALUE_TYPE (elemvec[0]), rangetype); + val = value_at_lazy (arraytype, addr); + return (val); +} + +/* Create a value for a string constant by allocating space in the inferior, + copying the data into that space, and returning the address with type + TYPE_CODE_STRING. PTR points to the string constant data; LEN is number + of characters. + Note that string types are like array of char types with a lower bound of + zero and an upper bound of LEN - 1. Also note that the string may contain + embedded null bytes. */ + +value +value_string (ptr, len) + char *ptr; + int len; +{ + value val; + struct type *rangetype; + struct type *stringtype; + CORE_ADDR addr; + + /* Allocate space to store the string in the inferior, and then + copy LEN bytes from PTR in gdb to that address in the inferior. */ + + addr = allocate_space_in_inferior (len); + write_memory (addr, ptr, len); + + /* Create the string type and set up a string value to be evaluated + lazily. */ + + rangetype = create_range_type ((struct type *) NULL, builtin_type_int, + 0, len - 1); + stringtype = create_string_type ((struct type *) NULL, rangetype); + val = value_at_lazy (stringtype, addr); + return (val); } +/* Compare two argument lists and return the position in which they differ, + or zero if equal. + + STATICP is nonzero if the T1 argument list came from a + static member function. + + For non-static member functions, we ignore the first argument, + which is the type of the instance variable. This is because we want + to handle calls with objects from derived classes. This is not + entirely correct: we should actually check to make sure that a + requested operation is type secure, shouldn't we? FIXME. */ + +static int +typecmp (staticp, t1, t2) + int staticp; + struct type *t1[]; + value t2[]; +{ + int i; + + if (t2 == 0) + return 1; + if (staticp && t1 == 0) + return t2[1] != 0; + if (t1 == 0) + return 1; + if (TYPE_CODE (t1[0]) == TYPE_CODE_VOID) return 0; + if (t1[!staticp] == 0) return 0; + for (i = !staticp; t1[i] && TYPE_CODE (t1[i]) != TYPE_CODE_VOID; i++) + { + if (! t2[i]) + return i+1; + if (TYPE_CODE (t1[i]) == TYPE_CODE_REF + && TYPE_TARGET_TYPE (t1[i]) == VALUE_TYPE (t2[i])) + continue; + if (TYPE_CODE (t1[i]) != TYPE_CODE (VALUE_TYPE (t2[i]))) + return i+1; + } + if (!t1[i]) return 0; + return t2[i] ? i+1 : 0; +} + /* Helper function used by value_struct_elt to recurse through baseclasses. Look for a field NAME in ARG1. Adjust the address of ARG1 by OFFSET bytes, and search in it assuming it has (class) type TYPE. @@ -1446,46 +1612,6 @@ value_struct_elt_for_reference (domain, offset, curtype, name, intype) return 0; } -/* Compare two argument lists and return the position in which they differ, - or zero if equal. - - STATICP is nonzero if the T1 argument list came from a - static member function. - - For non-static member functions, we ignore the first argument, - which is the type of the instance variable. This is because we want - to handle calls with objects from derived classes. This is not - entirely correct: we should actually check to make sure that a - requested operation is type secure, shouldn't we? FIXME. */ - -int -typecmp (staticp, t1, t2) - int staticp; - struct type *t1[]; - value t2[]; -{ - int i; - - if (t2 == 0) - return 1; - if (staticp && t1 == 0) - return t2[1] != 0; - if (t1 == 0) - return 1; - if (t1[0]->code == TYPE_CODE_VOID) return 0; - if (t1[!staticp] == 0) return 0; - for (i = !staticp; t1[i] && t1[i]->code != TYPE_CODE_VOID; i++) - { - if (! t2[i] - || t1[i]->code != t2[i]->type->code -/* Too pessimistic: || t1[i]->target_type != t2[i]->type->target_type */ - ) - return i+1; - } - if (!t1[i]) return 0; - return t2[i] ? i+1 : 0; -} - /* C++: return the value of the class instance variable, if one exists. Flag COMPLAIN signals an error if the request is made in an inappropriate context. */ |