#include "defs.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "value.h"
#include "frame.h"
#include "inferior.h"
#include "gdbcore.h"
#include "target.h"
#include "demangle.h"
#include "language.h"
#include "gdbcmd.h"
#include <errno.h>
#include "gdb_string.h"
extern int hp_som_som_object_present;
extern int overload_debug;
static int typecmp (int staticp, struct type *t1[], value_ptr t2[]);
static value_ptr value_arg_coerce (value_ptr, struct type *, int);
static CORE_ADDR value_push (CORE_ADDR, value_ptr);
static value_ptr search_struct_field (char *, value_ptr, int,
struct type *, int);
static value_ptr search_struct_method (char *, value_ptr *,
value_ptr *,
int, int *, struct type *);
static int check_field_in (struct type *, const char *);
static CORE_ADDR allocate_space_in_inferior (int);
static value_ptr cast_into_complex (struct type *, value_ptr);
static struct fn_field *find_method_list (value_ptr * argp, char *method,
int offset, int *static_memfuncp,
struct type *type, int *num_fns,
struct type **basetype,
int *boffset);
void _initialize_valops (void);
#define VALUE_SUBSTRING_START(VAL) VALUE_FRAME(VAL)
#if 0
static int auto_abandon = 0;
#endif
int overload_resolution = 0;
int unwind_on_signal_p = 0;
extern struct type *msym_text_symbol_type;
extern struct type *msym_data_symbol_type;
extern struct type *msym_unknown_symbol_type;
extern unsigned int symbol_generation;
cached_value_ptr
create_cached_function (name, type)
char *name;
struct type *type;
{
cached_value_ptr ptr;
ptr = (struct cached_value *) xmalloc (sizeof (struct cached_value));
ptr->name = xstrdup (name);
ptr->type = type;
memset (&ptr->val, 0, sizeof (struct value));
ptr->generation = (unsigned int) -1;
return ptr;
}
value_ptr
lookup_cached_function (cval)
cached_value_ptr cval;
{
value_ptr val = NULL;
value_ptr next = NULL;
if (cval->generation != symbol_generation)
{
val = find_function_in_inferior (cval->name, cval->type);
cval->val = *val;
cval->val.next = NULL;
cval->generation = symbol_generation;
}
val = allocate_value (cval->val.type);
next = val->next;
*val = cval->val;
val->next = next;
return val;
}
value_ptr
find_function_in_inferior (char *name, struct type *type)
{
register struct symbol *sym;
sym = lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
if (sym != NULL)
{
if (SYMBOL_CLASS (sym) != LOC_BLOCK)
{
error ("\"%s\" exists in this program but is not a function.",
name);
}
return value_of_variable (sym, NULL);
}
else
{
struct minimal_symbol *msymbol = lookup_minimal_symbol (name, NULL, NULL);
if (msymbol != NULL)
{
if (type != NULL)
return value_from_longest (type, (LONGEST) SYMBOL_VALUE_ADDRESS (msymbol));
else
return value_from_longest (lookup_pointer_type (msym_text_symbol_type),
(LONGEST) SYMBOL_VALUE_ADDRESS (msymbol));
}
else
{
if (!target_has_execution)
error ("evaluation of this expression requires the target program to be active");
else
error ("evaluation of this expression requires the program to have a function named \"%s\".", name);
}
}
}
value_ptr
value_allocate_space_in_inferior (int len)
{
value_ptr blocklen;
value_ptr val;
static cached_value_ptr fval = NULL;
if (fval == NULL)
fval = create_cached_function ("malloc", builtin_type_voidptrfuncptr);
blocklen = value_from_longest (builtin_type_int, (LONGEST) len);
val = call_function_by_hand (lookup_cached_function (fval), 1, &blocklen);
if (value_logical_not (val))
{
if (!target_has_execution)
error ("No memory available to program now: you need to start the target first");
else
error ("No memory available to program: call to malloc failed");
}
return val;
}
static CORE_ADDR
allocate_space_in_inferior (int len)
{
return value_as_long (value_allocate_space_in_inferior (len));
}
value_ptr
value_cast (struct type *type, register value_ptr arg2)
{
register enum type_code code1;
register enum type_code code2;
register int scalar;
struct type *type2;
int convert_to_boolean = 0;
if (VALUE_TYPE (arg2) == type)
return arg2;
CHECK_TYPEDEF (type);
code1 = TYPE_CODE (type);
COERCE_REF (arg2);
type2 = check_typedef (VALUE_TYPE (arg2));
if (code1 == TYPE_CODE_ARRAY)
{
struct type *element_type = TYPE_TARGET_TYPE (type);
unsigned element_length = TYPE_LENGTH (check_typedef (element_type));
if (element_length > 0
&& TYPE_ARRAY_UPPER_BOUND_TYPE (type) == BOUND_CANNOT_BE_DETERMINED)
{
struct type *range_type = TYPE_INDEX_TYPE (type);
int val_length = TYPE_LENGTH (type2);
LONGEST low_bound, high_bound, new_length;
if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
low_bound = 0, high_bound = 0;
new_length = val_length / element_length;
if (val_length % element_length != 0)
warning ("array element type size does not divide object size in cast");
range_type = create_range_type ((struct type *) NULL,
TYPE_TARGET_TYPE (range_type),
low_bound,
new_length + low_bound - 1);
VALUE_TYPE (arg2) = create_array_type ((struct type *) NULL,
element_type, range_type);
return arg2;
}
}
if (current_language->c_style_arrays &&
(TYPE_CODE (type2) == TYPE_CODE_ARRAY ||
TYPE_CODE (type2) == TYPE_CODE_STRING))
arg2 = value_coerce_array (arg2);
if (TYPE_CODE (type2) == TYPE_CODE_FUNC)
arg2 = value_coerce_function (arg2);
type2 = check_typedef (VALUE_TYPE (arg2));
COERCE_VARYING_ARRAY (arg2, type2);
code2 = TYPE_CODE (type2);
if (code1 == TYPE_CODE_COMPLEX)
return cast_into_complex (type, arg2);
if (code1 == TYPE_CODE_BOOL)
{
code1 = TYPE_CODE_INT;
convert_to_boolean = 1;
}
if (code1 == TYPE_CODE_CHAR)
code1 = TYPE_CODE_INT;
if (code2 == TYPE_CODE_BOOL || code2 == TYPE_CODE_CHAR)
code2 = TYPE_CODE_INT;
scalar = (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_FLT
|| code2 == TYPE_CODE_ENUM || code2 == TYPE_CODE_RANGE);
if (code1 == TYPE_CODE_STRUCT
&& code2 == TYPE_CODE_STRUCT
&& TYPE_NAME (type) != 0)
{
value_ptr v = search_struct_field (type_name_no_tag (type),
arg2, 0, type2, 1);
if (v)
{
VALUE_TYPE (v) = type;
return v;
}
}
if (code1 == TYPE_CODE_FLT && scalar)
return value_from_double (type, value_as_double (arg2));
else if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_ENUM
|| code1 == TYPE_CODE_RANGE)
&& (scalar || code2 == TYPE_CODE_PTR))
{
LONGEST longest;
if (hp_som_som_object_present &&
(code2 == TYPE_CODE_PTR))
{
unsigned int *ptr;
value_ptr retvalp;
switch (TYPE_CODE (TYPE_TARGET_TYPE (type2)))
{
case TYPE_CODE_MEMBER:
retvalp = value_from_longest (type, value_as_long (arg2));
ptr = (unsigned int *) VALUE_CONTENTS (retvalp);
*ptr &= ~0x20000000;
return retvalp;
case TYPE_CODE_METHOD:
error ("Pointers to methods not supported with HP aCC");
default:
break;
}
}
longest = value_as_long (arg2);
return value_from_longest (type, convert_to_boolean ?
(LONGEST) (longest ? 1 : 0) : longest);
}
else if (code1 == TYPE_CODE_PTR && (code2 == TYPE_CODE_INT ||
code2 == TYPE_CODE_ENUM ||
code2 == TYPE_CODE_RANGE))
{
int ptr_bit = HOST_CHAR_BIT * TYPE_LENGTH (type);
LONGEST longest = value_as_long (arg2);
if (ptr_bit < sizeof (LONGEST) * HOST_CHAR_BIT)
{
if (longest >= ((LONGEST) 1 << ptr_bit)
|| longest <= -((LONGEST) 1 << ptr_bit))
warning ("value truncated");
}
return value_from_longest (type, longest);
}
else if (TYPE_LENGTH (type) == TYPE_LENGTH (type2))
{
if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
{
struct type *t1 = check_typedef (TYPE_TARGET_TYPE (type));
struct type *t2 = check_typedef (TYPE_TARGET_TYPE (type2));
if (TYPE_CODE (t1) == TYPE_CODE_STRUCT
&& TYPE_CODE (t2) == TYPE_CODE_STRUCT
&& !value_logical_not (arg2))
{
value_ptr v;
if (TYPE_NAME (t1) != NULL)
{
v = search_struct_field (type_name_no_tag (t1),
value_ind (arg2), 0, t2, 1);
if (v)
{
v = value_addr (v);
VALUE_TYPE (v) = type;
return v;
}
}
if (TYPE_NAME (t2) != NULL)
{
v = search_struct_field (type_name_no_tag (t2),
value_zero (t1, not_lval), 0, t1, 1);
if (v)
{
value_ptr v2 = value_ind (arg2);
VALUE_ADDRESS (v2) -= VALUE_ADDRESS (v)
+ VALUE_OFFSET (v);
v2->aligner.contents[0] -= VALUE_EMBEDDED_OFFSET (v);
VALUE_EMBEDDED_OFFSET (v2) = 0;
v2 = value_addr (v2);
VALUE_TYPE (v2) = type;
return v2;
}
}
}
}
VALUE_TYPE (arg2) = type;
arg2 = value_change_enclosing_type (arg2, type);
VALUE_POINTED_TO_OFFSET (arg2) = 0;
return arg2;
}
else if (chill_varying_type (type))
{
struct type *range1, *range2, *eltype1, *eltype2;
value_ptr val;
int count1, count2;
LONGEST low_bound, high_bound;
char *valaddr, *valaddr_data;
eltype2 = NULL;
if (code2 == TYPE_CODE_BITSTRING)
error ("not implemented: converting bitstring to varying type");
if ((code2 != TYPE_CODE_ARRAY && code2 != TYPE_CODE_STRING)
|| (eltype1 = check_typedef (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 1))),
eltype2 = check_typedef (TYPE_TARGET_TYPE (type2)),
(TYPE_LENGTH (eltype1) != TYPE_LENGTH (eltype2)
)))
error ("Invalid conversion to varying type");
range1 = TYPE_FIELD_TYPE (TYPE_FIELD_TYPE (type, 1), 0);
range2 = TYPE_FIELD_TYPE (type2, 0);
if (get_discrete_bounds (range1, &low_bound, &high_bound) < 0)
count1 = -1;
else
count1 = high_bound - low_bound + 1;
if (get_discrete_bounds (range2, &low_bound, &high_bound) < 0)
count1 = -1, count2 = 0;
else
count2 = high_bound - low_bound + 1;
if (count2 > count1)
error ("target varying type is too small");
val = allocate_value (type);
valaddr = VALUE_CONTENTS_RAW (val);
valaddr_data = valaddr + TYPE_FIELD_BITPOS (type, 1) / 8;
store_signed_integer (valaddr, TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)),
count2);
memcpy (valaddr_data, VALUE_CONTENTS (arg2),
count2 * TYPE_LENGTH (eltype2));
memset (valaddr_data + count2 * TYPE_LENGTH (eltype2), '\0',
(count1 - count2) * TYPE_LENGTH (eltype2));
return val;
}
else if (VALUE_LVAL (arg2) == lval_memory)
{
return value_at_lazy (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2),
VALUE_BFD_SECTION (arg2));
}
else if (code1 == TYPE_CODE_VOID)
{
return value_zero (builtin_type_void, not_lval);
}
else
{
error ("Invalid cast.");
return 0;
}
}
value_ptr
value_zero (struct type *type, enum lval_type lv)
{
register value_ptr val = allocate_value (type);
memset (VALUE_CONTENTS (val), 0, TYPE_LENGTH (check_typedef (type)));
VALUE_LVAL (val) = lv;
return val;
}
value_ptr
value_at (struct type *type, CORE_ADDR addr, asection *sect)
{
register value_ptr val;
if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID)
error ("Attempt to dereference a generic pointer.");
val = allocate_value (type);
if (GDB_TARGET_IS_D10V
&& TYPE_CODE (type) == TYPE_CODE_PTR
&& TYPE_TARGET_TYPE (type)
&& (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC))
{
unsigned long num;
unsigned short snum;
snum = read_memory_unsigned_integer (addr, 2);
num = D10V_MAKE_IADDR (snum);
store_address (VALUE_CONTENTS_RAW (val), 4, num);
}
else if (GDB_TARGET_IS_D10V
&& TYPE_CODE (type) == TYPE_CODE_PTR)
{
unsigned long num;
unsigned short snum;
snum = read_memory_unsigned_integer (addr, 2);
num = D10V_MAKE_DADDR (snum);
store_address (VALUE_CONTENTS_RAW (val), 4, num);
}
else
read_memory (addr, VALUE_CONTENTS_ALL_RAW (val), TYPE_LENGTH (type));
VALUE_LVAL (val) = lval_memory;
VALUE_ADDRESS (val) = addr;
VALUE_BFD_SECTION (val) = sect;
return val;
}
value_ptr
value_at_lazy (struct type *type, CORE_ADDR addr, asection *sect)
{
register value_ptr val;
if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID)
error ("Attempt to dereference a generic pointer.");
val = allocate_value (type);
VALUE_LVAL (val) = lval_memory;
VALUE_ADDRESS (val) = addr;
VALUE_LAZY (val) = 1;
VALUE_BFD_SECTION (val) = sect;
return val;
}
int
value_fetch_lazy (register value_ptr val)
{
CORE_ADDR addr = VALUE_ADDRESS (val) + VALUE_OFFSET (val);
int length = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (val));
struct type *type = VALUE_TYPE (val);
if (GDB_TARGET_IS_D10V
&& TYPE_CODE (type) == TYPE_CODE_PTR
&& TYPE_TARGET_TYPE (type)
&& (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC))
{
unsigned long num;
unsigned short snum;
snum = read_memory_unsigned_integer (addr, 2);
num = D10V_MAKE_IADDR (snum);
store_address (VALUE_CONTENTS_RAW (val), 4, num);
}
else if (GDB_TARGET_IS_D10V
&& TYPE_CODE (type) == TYPE_CODE_PTR)
{
unsigned long num;
unsigned short snum;
snum = read_memory_unsigned_integer (addr, 2);
num = D10V_MAKE_DADDR (snum);
store_address (VALUE_CONTENTS_RAW (val), 4, num);
}
else if (length)
read_memory (addr, VALUE_CONTENTS_ALL_RAW (val), length);
VALUE_LAZY (val) = 0;
return 0;
}
value_ptr
value_assign (register value_ptr toval, register value_ptr fromval)
{
register struct type *type;
register value_ptr val;
char raw_buffer[MAX_REGISTER_RAW_SIZE];
int use_buffer = 0;
if (!toval->modifiable)
error ("Left operand of assignment is not a modifiable lvalue.");
COERCE_REF (toval);
type = VALUE_TYPE (toval);
if (VALUE_LVAL (toval) != lval_internalvar)
fromval = value_cast (type, fromval);
else
COERCE_ARRAY (fromval);
CHECK_TYPEDEF (type);
if (VALUE_REGNO (toval) >= 0)
{
int regno = VALUE_REGNO (toval);
if (REGISTER_CONVERTIBLE (regno))
{
struct type *fromtype = check_typedef (VALUE_TYPE (fromval));
REGISTER_CONVERT_TO_RAW (fromtype, regno,
VALUE_CONTENTS (fromval), raw_buffer);
use_buffer = REGISTER_RAW_SIZE (regno);
}
}
switch (VALUE_LVAL (toval))
{
case lval_internalvar:
set_internalvar (VALUE_INTERNALVAR (toval), fromval);
val = value_copy (VALUE_INTERNALVAR (toval)->value);
val = value_change_enclosing_type (val, VALUE_ENCLOSING_TYPE (fromval));
VALUE_EMBEDDED_OFFSET (val) = VALUE_EMBEDDED_OFFSET (fromval);
VALUE_POINTED_TO_OFFSET (val) = VALUE_POINTED_TO_OFFSET (fromval);
return val;
case lval_internalvar_component:
set_internalvar_component (VALUE_INTERNALVAR (toval),
VALUE_OFFSET (toval),
VALUE_BITPOS (toval),
VALUE_BITSIZE (toval),
fromval);
break;
case lval_memory:
{
char *dest_buffer;
CORE_ADDR changed_addr;
int changed_len;
if (VALUE_BITSIZE (toval))
{
char buffer[sizeof (LONGEST)];
changed_len = (VALUE_BITPOS (toval)
+ VALUE_BITSIZE (toval)
+ HOST_CHAR_BIT - 1)
/ HOST_CHAR_BIT;
if (changed_len > (int) sizeof (LONGEST))
error ("Can't handle bitfields which don't fit in a %d bit word.",
sizeof (LONGEST) * HOST_CHAR_BIT);
read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
buffer, changed_len);
modify_field (buffer, value_as_long (fromval),
VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
changed_addr = VALUE_ADDRESS (toval) + VALUE_OFFSET (toval);
dest_buffer = buffer;
}
else if (use_buffer)
{
changed_addr = VALUE_ADDRESS (toval) + VALUE_OFFSET (toval);
changed_len = use_buffer;
dest_buffer = raw_buffer;
}
else
{
changed_addr = VALUE_ADDRESS (toval) + VALUE_OFFSET (toval);
changed_len = TYPE_LENGTH (type);
dest_buffer = VALUE_CONTENTS (fromval);
}
write_memory (changed_addr, dest_buffer, changed_len);
if (memory_changed_hook)
memory_changed_hook (changed_addr, changed_len);
}
break;
case lval_register:
if (VALUE_BITSIZE (toval))
{
char buffer[sizeof (LONGEST)];
int len =
REGISTER_RAW_SIZE (VALUE_REGNO (toval)) - VALUE_OFFSET (toval);
if (len > (int) sizeof (LONGEST))
error ("Can't handle bitfields in registers larger than %d bits.",
sizeof (LONGEST) * HOST_CHAR_BIT);
if (VALUE_BITPOS (toval) + VALUE_BITSIZE (toval)
> len * HOST_CHAR_BIT)
error ("Can't assign to bitfields that cross register "
"boundaries.");
read_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
buffer, len);
modify_field (buffer, value_as_long (fromval),
VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
buffer, len);
}
else if (use_buffer)
write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
raw_buffer, use_buffer);
else
{
#ifdef REGISTER_CONVERT_FROM_TYPE
memcpy (raw_buffer, VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
REGISTER_CONVERT_FROM_TYPE (VALUE_REGNO (toval), type, raw_buffer);
write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
raw_buffer, TYPE_LENGTH (type));
#else
write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
#endif
}
reinit_frame_cache ();
break;
case lval_reg_frame_relative:
{
int amount_to_copy = (VALUE_BITSIZE (toval) ? 1 : TYPE_LENGTH (type));
int reg_size = REGISTER_RAW_SIZE (VALUE_FRAME_REGNUM (toval));
int byte_offset = VALUE_OFFSET (toval) % reg_size;
int reg_offset = VALUE_OFFSET (toval) / reg_size;
int amount_copied;
char *buffer = (char *) alloca (amount_to_copy
+ sizeof (LONGEST)
+ MAX_REGISTER_RAW_SIZE);
int regno;
struct frame_info *frame;
for (frame = get_current_frame ();
frame && FRAME_FP (frame) != VALUE_FRAME (toval);
frame = get_prev_frame (frame))
;
if (!frame)
error ("Value being assigned to is no longer active.");
amount_to_copy += (reg_size - amount_to_copy % reg_size);
for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset,
amount_copied = 0);
amount_copied < amount_to_copy;
amount_copied += reg_size, regno++)
{
get_saved_register (buffer + amount_copied,
(int *) NULL, (CORE_ADDR *) NULL,
frame, regno, (enum lval_type *) NULL);
}
if (VALUE_BITSIZE (toval))
modify_field (buffer + byte_offset,
value_as_long (fromval),
VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
else if (use_buffer)
memcpy (buffer + byte_offset, raw_buffer, use_buffer);
else
memcpy (buffer + byte_offset, VALUE_CONTENTS (fromval),
TYPE_LENGTH (type));
for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset,
amount_copied = 0);
amount_copied < amount_to_copy;
amount_copied += reg_size, regno++)
{
enum lval_type lval;
CORE_ADDR addr;
int optim;
get_saved_register ((char *) NULL,
&optim, &addr, frame, regno, &lval);
if (optim)
error ("Attempt to assign to a value that was optimized out.");
if (lval == lval_memory)
write_memory (addr, buffer + amount_copied, reg_size);
else if (lval == lval_register)
write_register_bytes (addr, buffer + amount_copied, reg_size);
else
error ("Attempt to assign to an unmodifiable value.");
}
if (register_changed_hook)
register_changed_hook (-1);
}
break;
default:
error ("Left operand of assignment is not an lvalue.");
}
if ((VALUE_BITSIZE (toval) > 0)
&& (VALUE_BITSIZE (toval) < 8 * (int) sizeof (LONGEST)))
{
LONGEST fieldval = value_as_long (fromval);
LONGEST valmask = (((ULONGEST) 1) << VALUE_BITSIZE (toval)) - 1;
fieldval &= valmask;
if (!TYPE_UNSIGNED (type) && (fieldval & (valmask ^ (valmask >> 1))))
fieldval |= ~valmask;
fromval = value_from_longest (type, fieldval);
}
val = value_copy (toval);
memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS (fromval),
TYPE_LENGTH (type));
VALUE_TYPE (val) = type;
val = value_change_enclosing_type (val, VALUE_ENCLOSING_TYPE (fromval));
VALUE_EMBEDDED_OFFSET (val) = VALUE_EMBEDDED_OFFSET (fromval);
VALUE_POINTED_TO_OFFSET (val) = VALUE_POINTED_TO_OFFSET (fromval);
return val;
}
value_ptr
value_repeat (value_ptr arg1, int count)
{
register value_ptr val;
if (VALUE_LVAL (arg1) != lval_memory)
error ("Only values in memory can be extended with '@'.");
if (count < 1)
error ("Invalid number %d of repetitions.", count);
val = allocate_repeat_value (VALUE_ENCLOSING_TYPE (arg1), count);
read_memory (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1),
VALUE_CONTENTS_ALL_RAW (val),
TYPE_LENGTH (VALUE_ENCLOSING_TYPE (val)));
VALUE_LVAL (val) = lval_memory;
VALUE_ADDRESS (val) = VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1);
return val;
}
value_ptr
value_of_variable (struct symbol *var, struct block *b)
{
value_ptr val;
struct frame_info *frame = NULL;
if (!b)
frame = NULL;
else if (symbol_read_needs_frame (var))
{
frame = block_innermost_frame (b);
if (!frame)
{
if (BLOCK_FUNCTION (b)
&& SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)))
error ("No frame is currently executing in block %s.",
SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)));
else
error ("No frame is currently executing in specified block");
}
}
val = read_var_value (var, frame);
if (!val)
error ("Address of symbol \"%s\" is unknown.", SYMBOL_SOURCE_NAME (var));
return val;
}
value_ptr
value_coerce_array (value_ptr arg1)
{
register struct type *type = check_typedef (VALUE_TYPE (arg1));
if (VALUE_LVAL (arg1) != lval_memory)
error ("Attempt to take address of value not located in memory.");
return value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
(VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));
}
value_ptr
value_coerce_function (value_ptr arg1)
{
value_ptr retval;
if (VALUE_LVAL (arg1) != lval_memory)
error ("Attempt to take address of value not located in memory.");
retval = value_from_pointer (lookup_pointer_type (VALUE_TYPE (arg1)),
(VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));
VALUE_BFD_SECTION (retval) = VALUE_BFD_SECTION (arg1);
return retval;
}
value_ptr
value_addr (value_ptr arg1)
{
value_ptr arg2;
struct type *type = check_typedef (VALUE_TYPE (arg1));
if (TYPE_CODE (type) == TYPE_CODE_REF)
{
arg2 = value_copy (arg1);
VALUE_TYPE (arg2) = lookup_pointer_type (TYPE_TARGET_TYPE (type));
return arg2;
}
if (TYPE_CODE (type) == TYPE_CODE_FUNC)
return value_coerce_function (arg1);
if (VALUE_LVAL (arg1) != lval_memory)
error ("Attempt to take address of value not located in memory.");
arg2 = value_from_pointer (lookup_pointer_type (VALUE_TYPE (arg1)),
(VALUE_ADDRESS (arg1)
+ VALUE_OFFSET (arg1)
+ VALUE_EMBEDDED_OFFSET (arg1)));
arg2 = value_change_enclosing_type (arg2, lookup_pointer_type (VALUE_ENCLOSING_TYPE (arg1)));
VALUE_POINTED_TO_OFFSET (arg2) = VALUE_EMBEDDED_OFFSET (arg1);
VALUE_BFD_SECTION (arg2) = VALUE_BFD_SECTION (arg1);
return arg2;
}
value_ptr
value_ind (value_ptr arg1)
{
struct type *base_type;
value_ptr arg2;
COERCE_ARRAY (arg1);
base_type = check_typedef (VALUE_TYPE (arg1));
if (TYPE_CODE (base_type) == TYPE_CODE_MEMBER)
error ("not implemented: member types in value_ind");
if (TYPE_CODE (base_type) == TYPE_CODE_INT)
return value_at (builtin_type_int,
(CORE_ADDR) value_as_long (arg1),
VALUE_BFD_SECTION (arg1));
else if (TYPE_CODE (base_type) == TYPE_CODE_PTR)
{
struct type *enc_type;
enc_type = check_typedef (VALUE_ENCLOSING_TYPE (arg1));
enc_type = TYPE_TARGET_TYPE (enc_type);
arg2 = value_at_lazy (enc_type,
value_as_pointer (arg1) - VALUE_POINTED_TO_OFFSET (arg1),
VALUE_BFD_SECTION (arg1));
VALUE_TYPE (arg2) = TYPE_TARGET_TYPE (base_type);
arg2 = value_change_enclosing_type (arg2, enc_type);
VALUE_EMBEDDED_OFFSET (arg2) = VALUE_POINTED_TO_OFFSET (arg1);
arg2 = value_full_object (arg2, NULL, 0, 0, 0);
return arg2;
}
error ("Attempt to take contents of a non-pointer value.");
return 0;
}
CORE_ADDR
push_word (CORE_ADDR sp, ULONGEST word)
{
register int len = REGISTER_SIZE;
char buffer[MAX_REGISTER_RAW_SIZE];
store_unsigned_integer (buffer, len, word);
if (INNER_THAN (1, 2))
{
sp -= len;
write_memory (sp, buffer, len);
}
else
{
write_memory (sp, buffer, len);
sp += len;
}
return sp;
}
CORE_ADDR
push_bytes (CORE_ADDR sp, char *buffer, int len)
{
if (INNER_THAN (1, 2))
{
sp -= len;
write_memory (sp, buffer, len);
}
else
{
write_memory (sp, buffer, len);
sp += len;
}
return sp;
}
#ifndef PARM_BOUNDARY
#define PARM_BOUNDARY (0)
#endif
static CORE_ADDR
value_push (register CORE_ADDR sp, value_ptr arg)
{
register int len = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg));
register int container_len = len;
register int offset;
if (PARM_BOUNDARY)
container_len = ((len + PARM_BOUNDARY / TARGET_CHAR_BIT - 1)
& ~(PARM_BOUNDARY / TARGET_CHAR_BIT - 1));
if (TARGET_BYTE_ORDER == BIG_ENDIAN)
offset = container_len - len;
else
offset = 0;
if (INNER_THAN (1, 2))
{
sp -= container_len;
write_memory (sp + offset, VALUE_CONTENTS_ALL (arg), len);
}
else
{
write_memory (sp + offset, VALUE_CONTENTS_ALL (arg), len);
sp += container_len;
}
return sp;
}
#ifndef PUSH_ARGUMENTS
#define PUSH_ARGUMENTS default_push_arguments
#endif
CORE_ADDR
default_push_arguments (int nargs, value_ptr *args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr)
{
int i;
for (i = nargs - 1; i >= 0; i--)
sp = value_push (sp, args[i]);
return sp;
}
int
default_coerce_float_to_double (struct type *formal, struct type *actual)
{
return formal == NULL;
}
int
standard_coerce_float_to_double (struct type *formal, struct type *actual)
{
return 1;
}
static value_ptr
value_arg_coerce (value_ptr arg, struct type *param_type, int is_prototyped)
{
register struct type *arg_type = check_typedef (VALUE_TYPE (arg));
register struct type *type
= param_type ? check_typedef (param_type) : arg_type;
switch (TYPE_CODE (type))
{
case TYPE_CODE_REF:
if (TYPE_CODE (arg_type) != TYPE_CODE_REF)
{
arg = value_addr (arg);
VALUE_TYPE (arg) = param_type;
return arg;
}
break;
case TYPE_CODE_INT:
case TYPE_CODE_CHAR:
case TYPE_CODE_BOOL:
case TYPE_CODE_ENUM:
if (!is_prototyped)
{
if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
type = builtin_type_int;
}
if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
type = builtin_type_int;
break;
case TYPE_CODE_FLT:
if (!is_prototyped && COERCE_FLOAT_TO_DOUBLE (param_type, arg_type))
{
if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double))
type = builtin_type_double;
else if (TYPE_LENGTH (type) > TYPE_LENGTH (builtin_type_double))
type = builtin_type_long_double;
}
break;
case TYPE_CODE_FUNC:
type = lookup_pointer_type (type);
break;
case TYPE_CODE_ARRAY:
if (current_language->c_style_arrays)
type = lookup_pointer_type (TYPE_TARGET_TYPE (type));
break;
case TYPE_CODE_UNDEF:
case TYPE_CODE_PTR:
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
case TYPE_CODE_VOID:
case TYPE_CODE_SET:
case TYPE_CODE_RANGE:
case TYPE_CODE_STRING:
case TYPE_CODE_BITSTRING:
case TYPE_CODE_ERROR:
case TYPE_CODE_MEMBER:
case TYPE_CODE_METHOD:
case TYPE_CODE_COMPLEX:
default:
break;
}
return value_cast (type, arg);
}
CORE_ADDR
find_function_addr (value_ptr function, struct type **retval_type)
{
register struct type *ftype = check_typedef (VALUE_TYPE (function));
register enum type_code code = TYPE_CODE (ftype);
struct type *value_type;
CORE_ADDR funaddr;
if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD)
{
funaddr = VALUE_ADDRESS (function);
value_type = TYPE_TARGET_TYPE (ftype);
}
else if (code == TYPE_CODE_PTR)
{
funaddr = value_as_pointer (function);
ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
|| TYPE_CODE (ftype) == TYPE_CODE_METHOD)
{
funaddr = CONVERT_FROM_FUNC_PTR_ADDR (funaddr);
value_type = TYPE_TARGET_TYPE (ftype);
}
else
value_type = builtin_type_int;
}
else if (code == TYPE_CODE_INT)
{
if (TYPE_LENGTH (ftype) == 1)
funaddr = value_as_pointer (value_addr (function));
else
funaddr = (CORE_ADDR) value_as_long (function);
value_type = builtin_type_int;
}
else if (code == TYPE_CODE_ERROR)
{
value_type = builtin_type_error;
}
else
error ("Invalid data type for function to be called.");
*retval_type = value_type;
return funaddr;
}
#ifndef STACK_ALLOC
#if INNER_THAN (1, 2)
#define STACK_ALLOC(sp, start, len) ((sp) -= (len), (start) = (sp), (start))
#else
#define STACK_ALLOC(sp, start, len) ((sp) += (len), (start) = ((sp) - (len)), (start))
#endif
#endif
static value_ptr hand_function_call (value_ptr function,
struct type *expect_type, int nargs,
value_ptr * args, int);
static value_ptr
hand_function_call (value_ptr function, struct type *expect_type,
int nargs, value_ptr *args, int restore_frame)
{
CORE_ADDR sp;
int i;
int rc;
CORE_ADDR start_sp;
static ULONGEST *dummy;
int sizeof_dummy1;
char *dummy1;
CORE_ADDR old_sp;
struct type *value_type;
unsigned char struct_return;
CORE_ADDR struct_addr = 0;
struct inferior_status *inf_status;
struct cleanup *old_chain;
CORE_ADDR funaddr;
int using_gcc;
CORE_ADDR real_pc;
struct type *param_type = NULL;
struct type *ftype = check_typedef (SYMBOL_TYPE (function));
dummy = alloca (SIZEOF_CALL_DUMMY_WORDS);
sizeof_dummy1 = REGISTER_SIZE * SIZEOF_CALL_DUMMY_WORDS / sizeof (ULONGEST);
dummy1 = alloca (sizeof_dummy1);
memcpy (dummy, CALL_DUMMY_WORDS, SIZEOF_CALL_DUMMY_WORDS);
if (!target_has_execution)
noprocess ();
inf_status = save_inferior_status (restore_frame);
old_chain = make_cleanup_restore_inferior_status (inf_status);
funaddr = find_function_addr (function, &value_type);
CHECK_TYPEDEF (value_type);
if ((value_type == NULL) || (value_type->code == TYPE_CODE_ERROR))
value_type = expect_type;
if ((value_type == NULL) || (value_type->code == TYPE_CODE_ERROR))
error ("Unable to call function at 0x%lx: no return type information available.\n"
"To call this function anyway, you can cast the return type explicitly (e.g. 'print (float) fabs (3.0)')",
(unsigned long) funaddr);
{
struct block *b = block_for_pc (funaddr);
using_gcc = (b == NULL ? 2 : BLOCK_GCC_COMPILED (b));
}
struct_return = using_struct_return (function, funaddr, value_type,
using_gcc);
PUSH_DUMMY_FRAME;
old_sp = sp = read_sp ();
#if 0
if (INNER_THAN (1, 2))
{
sp -= sizeof_dummy1;
start_sp = sp;
}
else
{
start_sp = sp;
sp += sizeof_dummy1;
}
#endif
for (i = 0; i < (int) (SIZEOF_CALL_DUMMY_WORDS / sizeof (dummy[0])); i++)
store_unsigned_integer (&dummy1[i * REGISTER_SIZE],
REGISTER_SIZE,
(ULONGEST) dummy[i]);
STACK_ALLOC (sp, start_sp, sizeof_dummy1);
#ifdef GDB_TARGET_IS_HPPA
real_pc = FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
value_type, using_gcc);
#else
FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
value_type, using_gcc);
real_pc = start_sp;
#endif
if (CALL_DUMMY_LOCATION == ON_STACK)
{
write_memory (start_sp, (char *) dummy1, sizeof_dummy1);
}
if (CALL_DUMMY_LOCATION == BEFORE_TEXT_END)
{
extern CORE_ADDR text_end;
static int checked = 0;
if (!checked)
for (start_sp = text_end - sizeof_dummy1; start_sp < text_end; ++start_sp)
if (read_memory_integer (start_sp, 1) != 0)
error ("text segment full -- no place to put call");
checked = 1;
sp = old_sp;
real_pc = text_end - sizeof_dummy1;
write_memory (real_pc, (char *) dummy1, sizeof_dummy1);
}
if (CALL_DUMMY_LOCATION == AFTER_TEXT_END)
{
extern CORE_ADDR text_end;
int errcode;
sp = old_sp;
real_pc = text_end;
errcode = target_write_memory (real_pc, (char *) dummy1, sizeof_dummy1);
if (errcode != 0)
error ("Cannot write text segment -- call_function failed");
}
if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT)
{
real_pc = funaddr;
}
#ifdef lint
sp = old_sp;
#endif
if (nargs < TYPE_NFIELDS (ftype))
{
error ("too few arguments in call to function at 0x%lx", (unsigned long) funaddr);
}
for (i = nargs - 1; i >= 0; i--)
{
if (i >= TYPE_NFIELDS (ftype))
args[i] = value_arg_coerce (args[i], NULL, 0);
else
{
int is_prototyped = TYPE_FLAGS (ftype) & TYPE_FLAG_PROTOTYPED;
param_type = TYPE_FIELD_TYPE (ftype, i);
args[i] = value_arg_coerce (args[i], param_type, is_prototyped);
}
if (using_gcc == 0)
if (param_type)
if (TYPE_CODE (param_type) == TYPE_CODE_PTR)
if (TYPE_CODE (param_type->target_type) == TYPE_CODE_FUNC)
if (using_gcc == 0)
if (args[i]->lval == not_lval)
{
char *arg_name;
if (find_pc_partial_function ((CORE_ADDR) args[i]->aligner.contents[0], &arg_name, NULL, NULL))
error ("\
You cannot use function <%s> as argument. \n\
You must use a pointer to function type variable. Command ignored.", arg_name);
}
}
if (REG_STRUCT_HAS_ADDR_P ())
{
for (i = nargs - 1; i >= 0; i--)
{
struct type *arg_type = check_typedef (VALUE_TYPE (args[i]));
if ((TYPE_CODE (arg_type) == TYPE_CODE_STRUCT
|| TYPE_CODE (arg_type) == TYPE_CODE_UNION
|| TYPE_CODE (arg_type) == TYPE_CODE_ARRAY
|| TYPE_CODE (arg_type) == TYPE_CODE_STRING
|| TYPE_CODE (arg_type) == TYPE_CODE_BITSTRING
|| TYPE_CODE (arg_type) == TYPE_CODE_SET
|| (TYPE_CODE (arg_type) == TYPE_CODE_FLT
&& TYPE_LENGTH (arg_type) > 8)
)
&& REG_STRUCT_HAS_ADDR (using_gcc, arg_type))
{
CORE_ADDR addr;
int len;
int aligned_len;
arg_type = check_typedef (VALUE_ENCLOSING_TYPE (args[i]));
len = TYPE_LENGTH (arg_type);
if (STACK_ALIGN_P ())
aligned_len = STACK_ALIGN (len);
else
aligned_len = len;
STACK_ALLOC (sp, struct_addr, len);
write_memory (sp, VALUE_CONTENTS_ALL (args[i]), len);
if (INNER_THAN (1, 2))
{
addr = sp;
}
else
{
sp += aligned_len;
}
args[i] = value_from_pointer (lookup_pointer_type (arg_type),
addr);
}
}
}
if (struct_return)
{
int len = TYPE_LENGTH (value_type);
if (STACK_ALIGN_P ())
len = STACK_ALIGN (len);
STACK_ALLOC (sp, struct_addr, len);
}
if (EXTRA_STACK_ALIGNMENT_NEEDED)
{
if (STACK_ALIGN_P () && INNER_THAN (1, 2))
{
int len = 0;
for (i = nargs - 1; i >= 0; i--)
len += TYPE_LENGTH (VALUE_ENCLOSING_TYPE (args[i]));
if (CALL_DUMMY_STACK_ADJUST_P)
len += CALL_DUMMY_STACK_ADJUST;
sp -= STACK_ALIGN (len) - len;
}
}
sp = PUSH_ARGUMENTS (nargs, args, sp, struct_return, struct_addr);
#ifdef PUSH_RETURN_ADDRESS
sp = PUSH_RETURN_ADDRESS (real_pc, sp);
#endif
if (STACK_ALIGN_P () && !INNER_THAN (1, 2))
{
if (CALL_DUMMY_STACK_ADJUST_P)
sp += CALL_DUMMY_STACK_ADJUST;
sp = STACK_ALIGN (sp);
}
if (CALL_DUMMY_STACK_ADJUST_P)
if (INNER_THAN (1, 2))
{
sp -= CALL_DUMMY_STACK_ADJUST;
}
if (struct_return)
STORE_STRUCT_RETURN (struct_addr, sp);
write_sp (sp);
if (SAVE_DUMMY_FRAME_TOS_P ())
SAVE_DUMMY_FRAME_TOS (sp);
{
char retbuf[REGISTER_BYTES];
char *name;
struct symbol *symbol;
name = NULL;
symbol = find_pc_function (funaddr);
if (symbol)
{
name = SYMBOL_SOURCE_NAME (symbol);
}
else
{
struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (funaddr);
if (msymbol)
{
name = SYMBOL_SOURCE_NAME (msymbol);
}
}
if (name == NULL)
{
char format[80];
sprintf (format, "at %s", local_hex_format ());
name = alloca (80);
sprintf (name, format, (unsigned long) funaddr);
}
rc = run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, retbuf);
if (rc == 1)
{
if (unwind_on_signal_p)
{
POP_FRAME;
error ("\
The program being debugged was signaled while in a function called from GDB.\n\
GDB has restored the context to what it was before the call.\n\
To change this behavior use \"set unwindonsignal off\"\n\
Evaluation of the expression containing the function (%s) will be abandoned.",
name);
}
else
{
discard_cleanups (old_chain);
discard_inferior_status (inf_status);
error ("\
The program being debugged was signaled while in a function called from GDB.\n\
GDB remains in the frame where the signal was received.\n\
To change this behavior use \"set unwindonsignal on\"\n\
Evaluation of the expression containing the function (%s) will be abandoned.",
name);
}
}
if (rc == 2)
{
discard_cleanups (old_chain);
discard_inferior_status (inf_status);
error ("\
The program being debugged stopped while in a function called from GDB.\n\
When the function (%s) is done executing, GDB will silently\n\
stop (instead of continuing to evaluate the expression containing\n\
the function call).", name);
}
do_cleanups (old_chain);
#ifdef VALUE_RETURNED_FROM_STACK
if (struct_return)
return (value_ptr) VALUE_RETURNED_FROM_STACK (value_type, struct_addr);
#endif
return value_being_returned (value_type, retbuf, struct_return);
}
}
value_ptr
call_function_by_hand (value_ptr function, int nargs, value_ptr *args)
{
if (CALL_DUMMY_P)
{
return hand_function_call (function, NULL, nargs, args, 1);
}
else
{
error ("Cannot invoke functions on this machine.");
}
}
value_ptr
call_function_by_hand_expecting_type (value_ptr function, struct type *expect_type,
int nargs, value_ptr *args, int restore_frame)
{
if (CALL_DUMMY_P)
{
return hand_function_call (function, expect_type, nargs, args, restore_frame);
}
else
{
error ("Cannot invoke functions on this machine.");
}
}
value_ptr
value_array (int lowbound, int highbound, value_ptr *elemvec)
{
int nelem;
int idx;
unsigned int typelength;
value_ptr val;
struct type *rangetype;
struct type *arraytype;
CORE_ADDR addr;
nelem = highbound - lowbound + 1;
if (nelem <= 0)
{
error ("bad array bounds (%d, %d)", lowbound, highbound);
}
typelength = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (elemvec[0]));
for (idx = 1; idx < nelem; idx++)
{
if (TYPE_LENGTH (VALUE_ENCLOSING_TYPE (elemvec[idx])) != typelength)
{
error ("array elements must all be the same size");
}
}
rangetype = create_range_type ((struct type *) NULL, builtin_type_int,
lowbound, highbound);
arraytype = create_array_type ((struct type *) NULL,
VALUE_ENCLOSING_TYPE (elemvec[0]), rangetype);
if (!current_language->c_style_arrays)
{
val = allocate_value (arraytype);
for (idx = 0; idx < nelem; idx++)
{
memcpy (VALUE_CONTENTS_ALL_RAW (val) + (idx * typelength),
VALUE_CONTENTS_ALL (elemvec[idx]),
typelength);
}
VALUE_BFD_SECTION (val) = VALUE_BFD_SECTION (elemvec[0]);
return val;
}
addr = allocate_space_in_inferior (nelem * typelength);
for (idx = 0; idx < nelem; idx++)
{
write_memory (addr + (idx * typelength), VALUE_CONTENTS_ALL (elemvec[idx]),
typelength);
}
val = value_at_lazy (arraytype, addr, VALUE_BFD_SECTION (elemvec[0]));
return (val);
}
value_ptr
value_string (char *ptr, int len)
{
value_ptr val;
int lowbound = current_language->string_lower_bound;
struct type *rangetype = create_range_type ((struct type *) NULL,
builtin_type_int,
lowbound, len + lowbound - 1);
struct type *stringtype
= create_string_type ((struct type *) NULL, rangetype);
CORE_ADDR addr;
if (current_language->c_style_arrays == 0)
{
val = allocate_value (stringtype);
memcpy (VALUE_CONTENTS_RAW (val), ptr, len);
return val;
}
addr = allocate_space_in_inferior (len);
write_memory (addr, ptr, len);
val = value_at_lazy (stringtype, addr, NULL);
return (val);
}
value_ptr
value_bitstring (char *ptr, int len)
{
value_ptr val;
struct type *domain_type = create_range_type (NULL, builtin_type_int,
0, len - 1);
struct type *type = create_set_type ((struct type *) NULL, domain_type);
TYPE_CODE (type) = TYPE_CODE_BITSTRING;
val = allocate_value (type);
memcpy (VALUE_CONTENTS_RAW (val), ptr, TYPE_LENGTH (type));
return val;
}
static int
typecmp (int staticp, struct type *t1[], value_ptr 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++)
{
struct type *tt1, *tt2;
if (!t2[i])
return i + 1;
tt1 = check_typedef (t1[i]);
tt2 = check_typedef (VALUE_TYPE (t2[i]));
if (TYPE_CODE (tt1) == TYPE_CODE_REF
&& (TYPE_CODE (check_typedef (TYPE_TARGET_TYPE (tt1))) == TYPE_CODE (tt2)))
{
if (TYPE_CODE (tt2) == TYPE_CODE_ARRAY)
t2[i] = value_coerce_array (t2[i]);
else
t2[i] = value_addr (t2[i]);
continue;
}
while ( TYPE_CODE(tt1) == TYPE_CODE_REF ||
TYPE_CODE (tt1) == TYPE_CODE_PTR)
{
tt1 = check_typedef( TYPE_TARGET_TYPE(tt1) );
}
while ( TYPE_CODE(tt2) == TYPE_CODE_ARRAY ||
TYPE_CODE(tt2) == TYPE_CODE_PTR ||
TYPE_CODE(tt2) == TYPE_CODE_REF)
{
tt2 = check_typedef( TYPE_TARGET_TYPE(tt2) );
}
if (TYPE_CODE (tt1) == TYPE_CODE (tt2))
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;
}
static value_ptr
search_struct_field (char *name, register value_ptr arg1, int offset,
register struct type *type, int looking_for_baseclass)
{
int i;
int nbases = TYPE_N_BASECLASSES (type);
CHECK_TYPEDEF (type);
if (!looking_for_baseclass)
for (i = TYPE_NFIELDS (type) - 1; i >= nbases; i--)
{
char *t_field_name = TYPE_FIELD_NAME (type, i);
if (t_field_name && (strcmp_iw (t_field_name, name) == 0))
{
value_ptr v;
if (TYPE_FIELD_STATIC (type, i))
v = value_static_field (type, i);
else
v = value_primitive_field (arg1, offset, i, type);
if (v == 0)
error ("there is no field named %s", name);
return v;
}
if (t_field_name
&& (t_field_name[0] == '\0'
|| (TYPE_CODE (type) == TYPE_CODE_UNION
&& (strcmp_iw (t_field_name, "else") == 0))))
{
struct type *field_type = TYPE_FIELD_TYPE (type, i);
if (TYPE_CODE (field_type) == TYPE_CODE_UNION
|| TYPE_CODE (field_type) == TYPE_CODE_STRUCT)
{
value_ptr v;
int new_offset = offset;
if (TYPE_CODE (field_type) == TYPE_CODE_STRUCT
|| (TYPE_NFIELDS (field_type) > 0
&& TYPE_FIELD_BITPOS (field_type, 0) == 0))
new_offset += TYPE_FIELD_BITPOS (type, i) / 8;
v = search_struct_field (name, arg1, new_offset, field_type,
looking_for_baseclass);
if (v)
return v;
}
}
}
for (i = 0; i < nbases; i++)
{
value_ptr v;
struct type *basetype = check_typedef (TYPE_BASECLASS (type, i));
int found_baseclass = (looking_for_baseclass
&& TYPE_BASECLASS_NAME (type, i) != NULL
&& (strcmp_iw (name, TYPE_BASECLASS_NAME (type, i)) == 0));
if (BASETYPE_VIA_VIRTUAL (type, i))
{
int boffset;
value_ptr v2 = allocate_value (basetype);
boffset = baseclass_offset (type, i,
VALUE_CONTENTS (arg1) + offset,
VALUE_ADDRESS (arg1)
+ VALUE_OFFSET (arg1) + offset);
if (boffset == -1)
error ("virtual baseclass botch");
boffset += offset;
if (boffset < 0 || boffset >= TYPE_LENGTH (type))
{
CORE_ADDR base_addr;
base_addr = VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1) + boffset;
if (target_read_memory (base_addr, VALUE_CONTENTS_RAW (v2),
TYPE_LENGTH (basetype)) != 0)
error ("virtual baseclass botch");
VALUE_LVAL (v2) = lval_memory;
VALUE_ADDRESS (v2) = base_addr;
}
else
{
VALUE_LVAL (v2) = VALUE_LVAL (arg1);
VALUE_ADDRESS (v2) = VALUE_ADDRESS (arg1);
VALUE_OFFSET (v2) = VALUE_OFFSET (arg1) + boffset;
if (VALUE_LAZY (arg1))
VALUE_LAZY (v2) = 1;
else
memcpy (VALUE_CONTENTS_RAW (v2),
VALUE_CONTENTS_RAW (arg1) + boffset,
TYPE_LENGTH (basetype));
}
if (found_baseclass)
return v2;
v = search_struct_field (name, v2, 0, TYPE_BASECLASS (type, i),
looking_for_baseclass);
}
else if (found_baseclass)
v = value_primitive_field (arg1, offset, i, type);
else
v = search_struct_field (name, arg1,
offset + TYPE_BASECLASS_BITPOS (type, i) / 8,
basetype, looking_for_baseclass);
if (v)
return v;
}
return NULL;
}
void
find_rt_vbase_offset (struct type *type, struct type *basetype, char *valaddr,
int offset, int *boffset_p, int *skip_p)
{
int boffset;
int index;
int skip;
value_ptr vp;
CORE_ADDR vtbl;
struct type *pbc;
boffset = 0;
pbc = TYPE_PRIMARY_BASE (type);
if (pbc)
{
find_rt_vbase_offset (pbc, basetype, valaddr, offset, &boffset, &skip);
if (skip < 0)
{
*boffset_p = boffset;
*skip_p = -1;
return;
}
}
else
skip = 0;
index = virtual_base_index_skip_primaries (basetype, type);
if (index < 0)
{
*skip_p = skip + virtual_base_list_length_skip_primaries (type);
*boffset_p = 0;
return;
}
vtbl = *(CORE_ADDR *) (valaddr + offset);
if (vtbl == 0)
error ("Couldn't find virtual table -- object may not be constructed yet.");
vp = value_at (builtin_type_int, vtbl + 4 * (-skip - index - HP_ACC_VBASE_START), NULL);
boffset = value_as_long (vp);
*skip_p = -1;
*boffset_p = boffset;
return;
}
static value_ptr
search_struct_method (char *name, register value_ptr *arg1p,
register value_ptr *args, int offset,
int *static_memfuncp, register struct type *type)
{
int i;
value_ptr v;
int name_matched = 0;
char dem_opname[64];
CHECK_TYPEDEF (type);
for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--)
{
char *t_field_name = TYPE_FN_FIELDLIST_NAME (type, i);
if (strncmp (t_field_name, "__", 2) == 0 ||
strncmp (t_field_name, "op", 2) == 0 ||
strncmp (t_field_name, "type", 4) == 0)
{
if (cplus_demangle_opname (t_field_name, dem_opname, DMGL_ANSI))
t_field_name = dem_opname;
else if (cplus_demangle_opname (t_field_name, dem_opname, 0))
t_field_name = dem_opname;
}
if (t_field_name && (strcmp_iw (t_field_name, name) == 0))
{
int j = TYPE_FN_FIELDLIST_LENGTH (type, i) - 1;
struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
name_matched = 1;
if (j > 0 && args == 0)
error ("cannot resolve overloaded method `%s': no arguments supplied", name);
while (j >= 0)
{
if (TYPE_FN_FIELD_STUB (f, j))
check_stub_method (type, i, j);
if (!typecmp (TYPE_FN_FIELD_STATIC_P (f, j),
TYPE_FN_FIELD_ARGS (f, j), args))
{
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
return value_virtual_fn_field (arg1p, f, j, type, offset);
if (TYPE_FN_FIELD_STATIC_P (f, j) && static_memfuncp)
*static_memfuncp = 1;
v = value_fn_field (arg1p, f, j, type, offset);
if (v != NULL)
return v;
}
j--;
}
}
}
for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
{
int base_offset;
if (BASETYPE_VIA_VIRTUAL (type, i))
{
if (TYPE_HAS_VTABLE (type))
{
int skip;
find_rt_vbase_offset (type, TYPE_BASECLASS (type, i),
VALUE_CONTENTS_ALL (*arg1p),
offset + VALUE_EMBEDDED_OFFSET (*arg1p),
&base_offset, &skip);
if (skip >= 0)
error ("Virtual base class offset not found in vtable");
}
else
{
struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i));
char *base_valaddr;
if (offset < 0 || offset >= TYPE_LENGTH (type))
{
base_valaddr = (char *) alloca (TYPE_LENGTH (baseclass));
if (target_read_memory (VALUE_ADDRESS (*arg1p)
+ VALUE_OFFSET (*arg1p) + offset,
base_valaddr,
TYPE_LENGTH (baseclass)) != 0)
error ("virtual baseclass botch");
}
else
base_valaddr = VALUE_CONTENTS (*arg1p) + offset;
base_offset =
baseclass_offset (type, i, base_valaddr,
VALUE_ADDRESS (*arg1p)
+ VALUE_OFFSET (*arg1p) + offset);
if (base_offset == -1)
error ("virtual baseclass botch");
}
}
else
{
base_offset = TYPE_BASECLASS_BITPOS (type, i) / 8;
}
v = search_struct_method (name, arg1p, args, base_offset + offset,
static_memfuncp, TYPE_BASECLASS (type, i));
if (v == (value_ptr) - 1)
{
name_matched = 1;
}
else if (v)
{
return v;
}
}
if (name_matched)
return (value_ptr) - 1;
else
return NULL;
}
value_ptr
value_struct_elt (register value_ptr *argp, register value_ptr *args,
char *name, int *static_memfuncp, char *err)
{
register struct type *t;
value_ptr v;
COERCE_ARRAY (*argp);
t = check_typedef (VALUE_TYPE (*argp));
while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
{
*argp = value_ind (*argp);
if (TYPE_CODE (VALUE_TYPE (*argp)) != TYPE_CODE_FUNC)
COERCE_ARRAY (*argp);
t = check_typedef (VALUE_TYPE (*argp));
}
if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
error ("not implemented: member type in value_struct_elt");
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
&& TYPE_CODE (t) != TYPE_CODE_UNION)
error ("Attempt to extract a component of a value that is not a %s.", err);
if (static_memfuncp)
*static_memfuncp = 0;
if (!args)
{
v = search_struct_field (name, *argp, 0, t, 0);
if (v)
return v;
if (destructor_name_p (name, t))
error ("Cannot get value of destructor");
v = search_struct_method (name, argp, args, 0, static_memfuncp, t);
if (v == (value_ptr) - 1)
error ("Cannot take address of a method");
else if (v == 0)
{
if (TYPE_NFN_FIELDS (t))
error ("There is no member or method named %s.", name);
else
error ("There is no member named %s.", name);
}
return v;
}
if (destructor_name_p (name, t))
{
if (!args[1])
{
int m_index, f_index;
v = NULL;
if (get_destructor_fn_field (t, &m_index, &f_index))
{
v = value_fn_field (NULL, TYPE_FN_FIELDLIST1 (t, m_index),
f_index, NULL, 0);
}
if (v == NULL)
error ("could not find destructor function named %s.", name);
else
return v;
}
else
{
error ("destructor should not have any argument");
}
}
else
v = search_struct_method (name, argp, args, 0, static_memfuncp, t);
if (v == (value_ptr) - 1)
{
error ("One of the arguments you tried to pass to %s could not be converted to what the function wants.", name);
}
else if (v == 0)
{
v = search_struct_field (name, *argp, 0, t, 0);
}
if (!v)
error ("Structure has no component named %s.", name);
return v;
}
static struct fn_field *
find_method_list (value_ptr *argp, char *method, int offset,
int *static_memfuncp, struct type *type, int *num_fns,
struct type **basetype, int *boffset)
{
int i;
struct fn_field *f;
CHECK_TYPEDEF (type);
*num_fns = 0;
for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--)
{
char *fn_field_name = TYPE_FN_FIELDLIST_NAME (type, i);
if (fn_field_name && (strcmp_iw (fn_field_name, method) == 0))
{
*num_fns = TYPE_FN_FIELDLIST_LENGTH (type, i);
*basetype = type;
*boffset = offset;
return TYPE_FN_FIELDLIST1 (type, i);
}
}
for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
{
int base_offset;
if (BASETYPE_VIA_VIRTUAL (type, i))
{
if (TYPE_HAS_VTABLE (type))
{
int skip;
find_rt_vbase_offset (type, TYPE_BASECLASS (type, i),
VALUE_CONTENTS_ALL (*argp),
offset + VALUE_EMBEDDED_OFFSET (*argp),
&base_offset, &skip);
if (skip >= 0)
error ("Virtual base class offset not found in vtable");
}
else
{
base_offset = VALUE_OFFSET (*argp) + offset;
base_offset =
baseclass_offset (type, i,
VALUE_CONTENTS (*argp) + base_offset,
VALUE_ADDRESS (*argp) + base_offset);
if (base_offset == -1)
error ("virtual baseclass botch");
}
}
else
{
base_offset = TYPE_BASECLASS_BITPOS (type, i) / 8;
}
f = find_method_list (argp, method, base_offset + offset,
static_memfuncp, TYPE_BASECLASS (type, i), num_fns, basetype, boffset);
if (f)
return f;
}
return NULL;
}
struct fn_field *
value_find_oload_method_list (value_ptr *argp, char *method, int offset,
int *static_memfuncp, int *num_fns,
struct type **basetype, int *boffset)
{
struct type *t;
t = check_typedef (VALUE_TYPE (*argp));
while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
{
*argp = value_ind (*argp);
if (TYPE_CODE (VALUE_TYPE (*argp)) != TYPE_CODE_FUNC)
COERCE_ARRAY (*argp);
t = check_typedef (VALUE_TYPE (*argp));
}
if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
error ("Not implemented: member type in value_find_oload_lis");
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
&& TYPE_CODE (t) != TYPE_CODE_UNION)
error ("Attempt to extract a component of a value that is not a struct or union");
if (static_memfuncp)
*static_memfuncp = 0;
return find_method_list (argp, method, 0, static_memfuncp, t, num_fns, basetype, boffset);
}
int
find_overload_match (struct type **arg_types, int nargs, char *name, int method,
int lax, value_ptr obj, struct symbol *fsym,
value_ptr *valp, struct symbol **symp, int *staticp)
{
int nparms;
struct type **parm_types;
int champ_nparms = 0;
short oload_champ = -1;
short oload_ambiguous = 0;
short oload_ambig_champ = -1;
short oload_non_standard = 0;
short oload_incompatible = 0;
struct badness_vector *bv;
struct badness_vector *oload_champ_bv = NULL;
value_ptr temp = obj;
struct fn_field *fns_ptr = NULL;
struct symbol **oload_syms = NULL;
int num_fns = 0;
struct type *basetype = NULL;
int boffset;
register int jj;
register int ix;
char *obj_type_name = NULL;
char *func_name = NULL;
if (method)
{
int i;
int len;
struct type *domain;
obj_type_name = TYPE_NAME (VALUE_TYPE (obj));
if ((!obj_type_name || !*obj_type_name) &&
(TYPE_CODE (VALUE_TYPE (obj)) == TYPE_CODE_PTR))
obj_type_name = TYPE_NAME (TYPE_TARGET_TYPE (VALUE_TYPE (obj)));
if ((!obj_type_name || !*obj_type_name) &&
(TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (obj))) == TYPE_CODE_PTR))
obj_type_name = TYPE_NAME (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (obj))));
fns_ptr = value_find_oload_method_list (&temp, name, 0,
staticp,
&num_fns,
&basetype, &boffset);
if (!fns_ptr || !num_fns)
error ("Couldn't find method %s%s%s",
obj_type_name ? obj_type_name : "",
(obj_type_name && *obj_type_name) ? "::" : "",
name);
domain = TYPE_DOMAIN_TYPE (fns_ptr[0].type);
len = TYPE_NFN_FIELDS (domain);
for (i = 0; i < len; i++)
{
int j;
struct fn_field *f = TYPE_FN_FIELDLIST1 (domain, i);
int len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
for (j = 0; j < len2; j++)
{
if (TYPE_FN_FIELD_STUB (f, j) && (!strcmp_iw (TYPE_FN_FIELDLIST_NAME (domain,i),name)))
check_stub_method (domain, i, j);
}
}
}
else
{
int i = -1;
func_name = cplus_demangle (SYMBOL_NAME (fsym), DMGL_NO_OPTS);
if (!func_name)
{
*symp = fsym;
return 0;
}
oload_syms = make_symbol_overload_list (fsym);
while (oload_syms[++i])
num_fns++;
if (!num_fns)
error ("Couldn't find function %s", func_name);
}
oload_champ_bv = NULL;
for (ix = 0; ix < num_fns; ix++)
{
if (method)
{
nparms=0;
if (TYPE_FN_FIELD_ARGS(fns_ptr,ix))
{
while (TYPE_CODE(TYPE_FN_FIELD_ARGS(fns_ptr,ix)[nparms]) != TYPE_CODE_VOID)
nparms++;
}
}
else
{
nparms=TYPE_NFIELDS(SYMBOL_TYPE(oload_syms[ix]));
}
nparms = method ? TYPE_NFIELDS (fns_ptr[ix].type)
: TYPE_NFIELDS (SYMBOL_TYPE (oload_syms[ix]));
parm_types = (struct type **) xmalloc (nparms * (sizeof (struct type *)));
for (jj = 0; jj < nparms; jj++)
parm_types[jj] = method ? TYPE_FIELD_TYPE (fns_ptr[ix].type, jj)
: TYPE_FIELD_TYPE (SYMBOL_TYPE (oload_syms[ix]), jj);
bv = rank_function (parm_types, nparms, arg_types, nargs);
if (!oload_champ_bv)
{
oload_champ_bv = bv;
oload_champ = 0;
champ_nparms = nparms;
}
else
switch (compare_badness (bv, oload_champ_bv))
{
case 0:
oload_ambiguous = 1;
oload_ambig_champ = ix;
break;
case 1:
oload_ambiguous = 2;
oload_ambig_champ = ix;
break;
case 2:
oload_champ_bv = bv;
oload_ambiguous = 0;
oload_champ = ix;
oload_ambig_champ = -1;
champ_nparms = nparms;
break;
case 3:
default:
break;
}
free (parm_types);
if (overload_debug)
{
if (method)
fprintf_filtered (gdb_stderr,"Overloaded method instance %s, # of parms %d\n", fns_ptr[ix].physname, nparms);
else
fprintf_filtered (gdb_stderr,"Overloaded function instance %s # of parms %d\n", SYMBOL_DEMANGLED_NAME (oload_syms[ix]), nparms);
for (jj = 0; jj < nargs; jj++)
fprintf_filtered (gdb_stderr,"...Badness @ %d : %d\n", jj, bv->rank[jj]);
fprintf_filtered (gdb_stderr,"Overload resolution champion is %d, ambiguous? %d\n", oload_champ, oload_ambiguous);
}
}
#if 0
if (oload_ambiguous)
{
if (method)
error ("Cannot resolve overloaded method %s%s%s to unique instance; disambiguate by specifying function signature",
obj_type_name ? obj_type_name : "",
(obj_type_name && *obj_type_name) ? "::" : "",
name);
else
error ("Cannot resolve overloaded function %s to unique instance; disambiguate by specifying function signature",
func_name);
}
#endif
for (ix = 1; ix <= nargs; ix++)
{
if (oload_champ_bv->rank[ix] >= 100)
oload_incompatible = 1;
else if (oload_champ_bv->rank[ix] >= 10)
oload_non_standard = 1;
}
if (oload_incompatible)
{
if (method)
error ("Cannot resolve method %s%s%s to any overloaded instance",
obj_type_name ? obj_type_name : "",
(obj_type_name && *obj_type_name) ? "::" : "",
name);
else
error ("Cannot resolve function %s to any overloaded instance",
func_name);
}
else if (oload_non_standard)
{
if (method)
warning ("Using non-standard conversion to match method %s%s%s to supplied arguments",
obj_type_name ? obj_type_name : "",
(obj_type_name && *obj_type_name) ? "::" : "",
name);
else
warning ("Using non-standard conversion to match function %s to supplied arguments",
func_name);
}
if (method)
{
if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, oload_champ))
*valp = value_virtual_fn_field (&temp, fns_ptr, oload_champ, basetype, boffset);
else
*valp = value_fn_field (&temp, fns_ptr, oload_champ, basetype, boffset);
}
else
{
*symp = oload_syms[oload_champ];
free (func_name);
}
return oload_incompatible ? 100 : (oload_non_standard ? 10 : 0);
}
int
destructor_name_p (const char *name, const struct type *type)
{
if (name[0] == '~')
{
char *dname = type_name_no_tag (type);
char *cp = strchr (dname, '<');
unsigned int len;
if (cp == NULL)
len = strlen (dname);
else
len = cp - dname;
if (strlen (name + 1) != len || !STREQN (dname, name + 1, len))
error ("name of destructor must equal name of class");
else
return 1;
}
return 0;
}
static int
check_field_in (register struct type *type, const char *name)
{
register int i;
for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
{
char *t_field_name = TYPE_FIELD_NAME (type, i);
if (t_field_name && (strcmp_iw (t_field_name, name) == 0))
return 1;
}
if (destructor_name_p (name, type))
{
int m_index, f_index;
return get_destructor_fn_field (type, &m_index, &f_index);
}
for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i)
{
if (strcmp_iw (TYPE_FN_FIELDLIST_NAME (type, i), name) == 0)
return 1;
}
for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
if (check_field_in (TYPE_BASECLASS (type, i), name))
return 1;
return 0;
}
int
check_field (register value_ptr arg1, const char *name)
{
register struct type *t;
COERCE_ARRAY (arg1);
t = VALUE_TYPE (arg1);
for (;;)
{
CHECK_TYPEDEF (t);
if (TYPE_CODE (t) != TYPE_CODE_PTR && TYPE_CODE (t) != TYPE_CODE_REF)
break;
t = TYPE_TARGET_TYPE (t);
}
if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
error ("not implemented: member type in check_field");
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
&& TYPE_CODE (t) != TYPE_CODE_UNION)
error ("Internal error: `this' is not an aggregate");
return check_field_in (t, name);
}
value_ptr
value_struct_elt_for_reference (struct type *domain, int offset,
struct type *curtype, char *name,
struct type *intype)
{
register struct type *t = curtype;
register int i;
value_ptr v;
if (TYPE_CODE (t) != TYPE_CODE_STRUCT
&& TYPE_CODE (t) != TYPE_CODE_UNION)
error ("Internal error: non-aggregate type to value_struct_elt_for_reference");
for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--)
{
char *t_field_name = TYPE_FIELD_NAME (t, i);
if (t_field_name && STREQ (t_field_name, name))
{
if (TYPE_FIELD_STATIC (t, i))
{
v = value_static_field (t, i);
if (v == NULL)
error ("Internal error: could not find static variable %s",
name);
return v;
}
if (TYPE_FIELD_PACKED (t, i))
error ("pointers to bitfield members not allowed");
return value_from_longest
(lookup_reference_type (lookup_member_type (TYPE_FIELD_TYPE (t, i),
domain)),
offset + (LONGEST) (TYPE_FIELD_BITPOS (t, i) >> 3));
}
}
if (destructor_name_p (name, t))
{
error ("member pointers to destructors not implemented yet");
}
while (intype && TYPE_CODE (intype) == TYPE_CODE_PTR)
intype = TYPE_TARGET_TYPE (intype);
for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
{
char *t_field_name = TYPE_FN_FIELDLIST_NAME (t, i);
char dem_opname[64];
if (strncmp (t_field_name, "__", 2) == 0 ||
strncmp (t_field_name, "op", 2) == 0 ||
strncmp (t_field_name, "type", 4) == 0)
{
if (cplus_demangle_opname (t_field_name, dem_opname, DMGL_ANSI))
t_field_name = dem_opname;
else if (cplus_demangle_opname (t_field_name, dem_opname, 0))
t_field_name = dem_opname;
}
if (t_field_name && STREQ (t_field_name, name))
{
int j = TYPE_FN_FIELDLIST_LENGTH (t, i);
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
if (intype == 0 && j > 1)
error ("non-unique member `%s' requires type instantiation", name);
if (intype)
{
while (j--)
if (TYPE_FN_FIELD_TYPE (f, j) == intype)
break;
if (j < 0)
error ("no member function matches that type instantiation");
}
else
j = 0;
if (TYPE_FN_FIELD_STUB (f, j))
check_stub_method (t, i, j);
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
{
return value_from_longest
(lookup_reference_type
(lookup_member_type (TYPE_FN_FIELD_TYPE (f, j),
domain)),
(LONGEST) METHOD_PTR_FROM_VOFFSET (TYPE_FN_FIELD_VOFFSET (f, j)));
}
else
{
struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
0, VAR_NAMESPACE, 0, NULL);
if (s == NULL)
{
v = 0;
}
else
{
v = read_var_value (s, 0);
#if 0
VALUE_TYPE (v) = lookup_reference_type
(lookup_member_type (TYPE_FN_FIELD_TYPE (f, j),
domain));
#endif
}
return v;
}
}
}
for (i = TYPE_N_BASECLASSES (t) - 1; i >= 0; i--)
{
value_ptr v;
int base_offset;
if (BASETYPE_VIA_VIRTUAL (t, i))
base_offset = 0;
else
base_offset = TYPE_BASECLASS_BITPOS (t, i) / 8;
v = value_struct_elt_for_reference (domain,
offset + base_offset,
TYPE_BASECLASS (t, i),
name,
intype);
if (v)
return v;
}
return 0;
}
struct type *
value_rtti_type (value_ptr v, int *full, int *top, int *using_enc)
{
struct type *known_type;
struct type *rtti_type;
CORE_ADDR coreptr;
value_ptr vp;
int using_enclosing = 0;
long top_offset = 0;
char rtti_type_name[256];
if (full)
*full = 0;
if (top)
*top = -1;
if (using_enc)
*using_enc = 0;
known_type = VALUE_TYPE (v);
CHECK_TYPEDEF (known_type);
if (TYPE_CODE (known_type) != TYPE_CODE_CLASS)
return NULL;
if (TYPE_HAS_VTABLE(known_type))
{
if (!TYPE_HAS_VTABLE (known_type))
{
known_type = VALUE_ENCLOSING_TYPE (v);
CHECK_TYPEDEF (known_type);
if ((TYPE_CODE (known_type) != TYPE_CODE_CLASS) ||
!TYPE_HAS_VTABLE (known_type))
return NULL;
CHECK_TYPEDEF (known_type);
using_enclosing = 1;
}
if (using_enclosing && using_enc)
*using_enc = 1;
coreptr = *(CORE_ADDR *) ((VALUE_CONTENTS_ALL (v))
+ VALUE_OFFSET (v)
+ (using_enclosing ? 0 : VALUE_EMBEDDED_OFFSET (v)));
if (coreptr == 0)
return NULL;
vp = value_at (builtin_type_int,
coreptr + 4 * HP_ACC_TOP_OFFSET_OFFSET,
VALUE_BFD_SECTION (v));
top_offset = value_as_long (vp);
if (top)
*top = top_offset;
vp = value_at (builtin_type_int, coreptr + 4 * HP_ACC_TYPEINFO_OFFSET, VALUE_BFD_SECTION (v));
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
if (!coreptr)
error ("Retrieved null typeinfo pointer in trying to determine run-time type");
vp = value_at (builtin_type_int, coreptr + 4, VALUE_BFD_SECTION (v));
coreptr = *(CORE_ADDR *) (VALUE_CONTENTS (vp));
read_memory_string (coreptr, rtti_type_name, 256);
if (strlen (rtti_type_name) == 0)
error ("Retrieved null type name from typeinfo");
rtti_type = lookup_typename (rtti_type_name, (struct block *) 0, 1);
if (!rtti_type)
error ("Could not find run-time type: invalid type name %s in typeinfo??", rtti_type_name);
CHECK_TYPEDEF (rtti_type);
#if 0
printf ("RTTI type name %s, tag %s, full? %d\n", TYPE_NAME (rtti_type), TYPE_TAG_NAME (rtti_type), full ? *full : -1);
#endif
if (full
&&
(((top_offset == 0) &&
using_enclosing &&
TYPE_LENGTH (known_type) == TYPE_LENGTH (rtti_type))
||
((top_offset == VALUE_EMBEDDED_OFFSET (v)) &&
!using_enclosing &&
TYPE_LENGTH (VALUE_ENCLOSING_TYPE (v)) == TYPE_LENGTH (rtti_type))))
*full = 1;
}
else
{
CORE_ADDR vtbl;
struct minimal_symbol *minsym;
struct symbol *sym;
char *demangled_name;
struct type *btype;
if (TYPE_VPTR_FIELDNO(known_type) < 0)
fill_in_vptr_fieldno(known_type);
if (TYPE_VPTR_FIELDNO(known_type) < 0)
return NULL;
btype = TYPE_VPTR_BASETYPE (known_type);
CHECK_TYPEDEF (btype);
if (btype != known_type )
{
v = value_cast (btype, v);
if (using_enc)
*using_enc=1;
}
if (VALUE_ADDRESS (value_field (v, TYPE_VPTR_FIELDNO (known_type))) == 0)
return NULL;
if (VALUE_ENCLOSING_TYPE(v) != VALUE_TYPE(v))
{
value_ptr tempval;
tempval=value_field(v,TYPE_VPTR_FIELDNO(known_type));
VALUE_ADDRESS(tempval)+=(TYPE_BASECLASS_BITPOS(known_type,TYPE_VPTR_FIELDNO(known_type))/8);
vtbl=value_as_pointer(tempval);
using_enclosing=1;
}
else
{
vtbl=value_as_pointer(value_field(v,TYPE_VPTR_FIELDNO(known_type)));
using_enclosing=0;
}
minsym=lookup_minimal_symbol_by_pc(vtbl);
if (minsym==NULL || (demangled_name=SYMBOL_NAME(minsym))==NULL || !VTBL_PREFIX_P(demangled_name))
return NULL;
demangled_name=cplus_demangle(demangled_name,DMGL_PARAMS|DMGL_ANSI);
*(strchr(demangled_name,' '))=0;
rtti_type=lookup_typename(demangled_name, (struct block *)0,1);
if (rtti_type==NULL)
return NULL;
if (TYPE_N_BASECLASSES(rtti_type) > 1 && full && (*full) != 1)
{
if (top)
*top=TYPE_BASECLASS_BITPOS(rtti_type,TYPE_VPTR_FIELDNO(rtti_type))/8;
if (top && ((*top) >0))
{
if (TYPE_LENGTH(rtti_type) > TYPE_LENGTH(known_type))
{
if (full)
*full=0;
}
else
{
if (full)
*full=1;
}
}
}
else
{
if (full)
*full=1;
}
if (using_enc)
*using_enc=using_enclosing;
}
return rtti_type;
}
struct type *
value_rtti_target_type (value_ptr v, int *full, int *top, int *using_enc)
{
value_ptr target;
target = value_ind (v);
return value_rtti_type (target, full, top, using_enc);
}
value_ptr
value_full_object (value_ptr argp, struct type *rtype, int xfull, int xtop,
int xusing_enc)
{
struct type *real_type;
int full = 0;
int top = -1;
int using_enc = 0;
value_ptr new_val;
if (rtype)
{
real_type = rtype;
full = xfull;
top = xtop;
using_enc = xusing_enc;
}
else
real_type = value_rtti_type (argp, &full, &top, &using_enc);
if (!real_type || real_type == VALUE_ENCLOSING_TYPE (argp))
return argp;
if (full)
{
argp = value_change_enclosing_type (argp, real_type);
return argp;
}
if (VALUE_LVAL (argp) != lval_memory)
{
warning ("Couldn't retrieve complete object of RTTI type %s; object may be in register(s).", TYPE_NAME (real_type));
return argp;
}
new_val = value_at_lazy (real_type, VALUE_ADDRESS (argp) - top +
(using_enc ? 0 : VALUE_EMBEDDED_OFFSET (argp)),
VALUE_BFD_SECTION (argp));
VALUE_TYPE (new_val) = VALUE_TYPE (argp);
VALUE_EMBEDDED_OFFSET (new_val) = using_enc ? top + VALUE_EMBEDDED_OFFSET (argp) : top;
return new_val;
}
value_ptr
value_of_local (char *name, int complain)
{
struct symbol *func, *sym;
struct block *b;
int i;
value_ptr ret;
if (selected_frame == 0)
{
if (complain)
error ("no frame selected");
else
return 0;
}
func = get_frame_function (selected_frame);
if (!func)
{
if (complain)
error ("no %s in nameless context", name);
else
return 0;
}
b = SYMBOL_BLOCK_VALUE (func);
i = BLOCK_NSYMS (b);
if (i <= 0)
{
if (complain)
error ("no args, no %s", name);
else
return 0;
}
sym = lookup_block_symbol (b, name, VAR_NAMESPACE);
if (sym == NULL)
{
if (complain)
error ("current stack frame does not contain a variable named \"%s\"", name);
else
return NULL;
}
ret = read_var_value (sym, selected_frame);
if (ret == 0 && complain)
error ("%s argument unreadable", name);
return ret;
}
value_ptr
value_of_this (int complain)
{
if (current_language->la_language == language_objc)
return value_of_local ("self", complain);
else
return value_of_local ("this", complain);
}
value_ptr
value_slice (value_ptr array, int lowbound, int length)
{
struct type *slice_range_type, *slice_type, *range_type;
LONGEST lowerbound, upperbound, offset;
value_ptr slice;
struct type *array_type;
array_type = check_typedef (VALUE_TYPE (array));
COERCE_VARYING_ARRAY (array, array_type);
if (TYPE_CODE (array_type) != TYPE_CODE_ARRAY
&& TYPE_CODE (array_type) != TYPE_CODE_STRING
&& TYPE_CODE (array_type) != TYPE_CODE_BITSTRING)
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");
if (lowbound < lowerbound || length < 0
|| lowbound + length - 1 > upperbound
|| (current_language->la_language == language_chill
&& length == 0 && TYPE_CODE (array_type) == TYPE_CODE_ARRAY))
error ("slice out of range");
slice_range_type = create_range_type ((struct type *) NULL,
TYPE_TARGET_TYPE (range_type),
lowbound, lowbound + length - 1);
if (TYPE_CODE (array_type) == TYPE_CODE_BITSTRING)
{
int i;
slice_type = create_set_type ((struct type *) NULL, slice_range_type);
TYPE_CODE (slice_type) = TYPE_CODE_BITSTRING;
slice = value_zero (slice_type, not_lval);
for (i = 0; i < length; i++)
{
int element = value_bit_index (array_type,
VALUE_CONTENTS (array),
lowbound + i);
if (element < 0)
error ("internal error accessing bitstring");
else if (element > 0)
{
int j = i % TARGET_CHAR_BIT;
if (BITS_BIG_ENDIAN)
j = TARGET_CHAR_BIT - 1 - j;
VALUE_CONTENTS_RAW (slice)[i / TARGET_CHAR_BIT] |= (1 << j);
}
}
}
else
{
struct type *element_type = TYPE_TARGET_TYPE (array_type);
offset
= (lowbound - lowerbound) * TYPE_LENGTH (check_typedef (element_type));
slice_type = create_array_type ((struct type *) NULL, element_type,
slice_range_type);
TYPE_CODE (slice_type) = TYPE_CODE (array_type);
slice = allocate_value (slice_type);
if (VALUE_LAZY (array))
VALUE_LAZY (slice) = 1;
else
memcpy (VALUE_CONTENTS (slice), VALUE_CONTENTS (array) + offset,
TYPE_LENGTH (slice_type));
if (VALUE_LVAL (array) == lval_internalvar)
VALUE_LVAL (slice) = lval_internalvar_component;
else
VALUE_LVAL (slice) = VALUE_LVAL (array);
VALUE_ADDRESS (slice) = VALUE_ADDRESS (array);
VALUE_OFFSET (slice) = VALUE_OFFSET (array) + offset;
}
return slice;
}
value_ptr
varying_to_slice (value_ptr varray)
{
struct type *vtype = check_typedef (VALUE_TYPE (varray));
LONGEST length = unpack_long (TYPE_FIELD_TYPE (vtype, 0),
VALUE_CONTENTS (varray)
+ TYPE_FIELD_BITPOS (vtype, 0) / 8);
return value_slice (value_primitive_field (varray, 0, 1, vtype), 0, length);
}
value_ptr
value_literal_complex (value_ptr arg1, value_ptr arg2, struct type *type)
{
register value_ptr val;
struct type *real_type = TYPE_TARGET_TYPE (type);
val = allocate_value (type);
arg1 = value_cast (real_type, arg1);
arg2 = value_cast (real_type, arg2);
memcpy (VALUE_CONTENTS_RAW (val),
VALUE_CONTENTS (arg1), TYPE_LENGTH (real_type));
memcpy (VALUE_CONTENTS_RAW (val) + TYPE_LENGTH (real_type),
VALUE_CONTENTS (arg2), TYPE_LENGTH (real_type));
return val;
}
static value_ptr
cast_into_complex (struct type *type, register value_ptr val)
{
struct type *real_type = TYPE_TARGET_TYPE (type);
if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_COMPLEX)
{
struct type *val_real_type = TYPE_TARGET_TYPE (VALUE_TYPE (val));
value_ptr re_val = allocate_value (val_real_type);
value_ptr im_val = allocate_value (val_real_type);
memcpy (VALUE_CONTENTS_RAW (re_val),
VALUE_CONTENTS (val), TYPE_LENGTH (val_real_type));
memcpy (VALUE_CONTENTS_RAW (im_val),
VALUE_CONTENTS (val) + TYPE_LENGTH (val_real_type),
TYPE_LENGTH (val_real_type));
return value_literal_complex (re_val, im_val, type);
}
else if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT
|| TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT)
return value_literal_complex (val, value_zero (real_type, not_lval), type);
else
error ("cannot cast non-number to complex");
}
void
_initialize_valops (void)
{
#if 0
add_show_from_set
(add_set_cmd ("abandon", class_support, var_boolean, (char *) &auto_abandon,
"Set automatic abandonment of expressions upon failure.",
&setlist),
&showlist);
#endif
add_show_from_set
(add_set_cmd ("overload-resolution", class_support, var_boolean, (char *) &overload_resolution,
"Set overload resolution in evaluating C++ functions.",
&setlist),
&showlist);
overload_resolution = 1;
add_show_from_set (
add_set_cmd ("unwindonsignal", no_class, var_boolean,
(char *) &unwind_on_signal_p,
"Set unwinding of stack if a signal is received while in a call dummy.\n\
The unwindonsignal lets the user determine what gdb should do if a signal\n\
is received while in a function called from gdb (call dummy). If set, gdb\n\
unwinds the stack and restore the context to what as it was before the call.\n\
The default is to stop in the frame where the signal was received.", &setlist),
&showlist);
}