#include "frame.h"
#include "command.h"
#include "gdbcmd.h"
+#include "target.h"
+#include "demangle.h"
/* Local function prototypes. */
show_values PARAMS ((char *, int));
static void
-show_convenience PARAMS ((void));
+show_convenience PARAMS ((char *, int));
/* The value-history records all the values printed
by print commands during this session. Each chunk
VALUE_LAZY (val) = VALUE_LAZY (arg);
if (!VALUE_LAZY (val))
{
- bcopy (VALUE_CONTENTS_RAW (arg), VALUE_CONTENTS_RAW (val),
- TYPE_LENGTH (VALUE_TYPE (arg))
- * (VALUE_REPEATED (arg) ? VALUE_REPETITIONS (arg) : 1));
+ memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS_RAW (arg),
+ TYPE_LENGTH (VALUE_TYPE (arg))
+ * (VALUE_REPEATED (arg) ? VALUE_REPETITIONS (arg) : 1));
}
return val;
}
/* Check error now if about to store an invalid float. We return -1
to the caller, but allow them to continue, e.g. to print it as "Nan". */
- if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT) {
- (void) unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &i);
- if (i) return -1; /* Indicate value not saved in history */
- }
+ if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT)
+ {
+ unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &i);
+ if (i) return -1; /* Indicate value not saved in history */
+ }
/* Here we treat value_history_count as origin-zero
and applying to the value being stored now. */
register struct value_history_chunk *new
= (struct value_history_chunk *)
xmalloc (sizeof (struct value_history_chunk));
- bzero (new->values, sizeof new->values);
+ memset (new->values, 0, sizeof new->values);
new->next = value_history_chain;
value_history_chain = new;
}
while (value_history_chain)
{
for (i = 0; i < VALUE_HISTORY_CHUNK; i++)
- if (val = value_history_chain->values[i])
- free (val);
+ if ((val = value_history_chain->values[i]) != NULL)
+ free ((PTR)val);
next = value_history_chain->next;
- free (value_history_chain);
+ free ((PTR)value_history_chain);
value_history_chain = next;
}
value_history_count = 0;
if (num_exp)
{
- if (num_exp[0] == '+' && num_exp[1] == '\0')
- /* "info history +" should print from the stored position. */
- ;
- else
- /* "info history <exp>" should print around value number <exp>. */
+ /* "info history +" should print from the stored position.
+ "info history <exp>" should print around value number <exp>. */
+ if (num_exp[0] != '+' || num_exp[1] != '\0')
num = parse_and_eval_address (num_exp) - 5;
}
else
register struct internalvar *var;
for (var = internalvars; var; var = var->next)
- if (!strcmp (var->name, name))
+ if (STREQ (var->name, name))
return var;
var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
#endif
if (bitsize)
- modify_field (addr, (int) value_as_long (newval),
+ modify_field (addr, value_as_long (newval),
bitpos, bitsize);
else
- bcopy (VALUE_CONTENTS (newval), addr,
- TYPE_LENGTH (VALUE_TYPE (newval)));
+ memcpy (addr, VALUE_CONTENTS (newval), TYPE_LENGTH (VALUE_TYPE (newval)));
}
void
SET_TRAPPED_INTERNALVAR (var, val, 0, 0, 0);
#endif
- free (var->value);
+ free ((PTR)var->value);
var->value = value_copy (val);
+ /* Force the value to be fetched from the target now, to avoid problems
+ later when this internalvar is referenced and the target is gone or
+ has changed. */
+ if (VALUE_LAZY (var->value))
+ value_fetch_lazy (var->value);
release_value (var->value);
}
{
var = internalvars;
internalvars = var->next;
- free (var->name);
- free (var->value);
- free (var);
+ free ((PTR)var->name);
+ free ((PTR)var->value);
+ free ((PTR)var);
}
}
static void
-show_convenience ()
+show_convenience (ignore, from_tty)
+ char *ignore;
+ int from_tty;
{
register struct internalvar *var;
int varseen = 0;
#endif
if (!varseen)
{
-#if 0
- /* Useless noise. */
- printf ("Debugger convenience variables:\n\n");
-#endif
varseen = 1;
}
printf_filtered ("$%s = ", var->name);
{
/* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
whether we want this to be true eventually. */
+#if 0
+ /* ADDR_BITS_REMOVE is wrong if we are being called for a
+ non-address (e.g. argument to "signal", "info break", etc.), or
+ for pointers to char, in which the low bits *are* significant. */
+ return ADDR_BITS_REMOVE(value_as_long (val));
+#else
return value_as_long (val);
+#endif
}
\f
/* Unpack raw data (copied from debugee, target byte order) at VALADDR
if (len == sizeof (float))
{
float retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (double))
{
double retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
error ("Unexpected type of floating point number.");
}
}
- else if (code == TYPE_CODE_INT && nosign)
+ else if ((code == TYPE_CODE_INT || code == TYPE_CODE_CHAR) && nosign)
{
- if (len == sizeof (char))
- {
- unsigned char retval = * (unsigned char *) valaddr;
- /* SWAP_TARGET_AND_HOST (&retval, sizeof (unsigned char)); */
- return retval;
- }
-
- if (len == sizeof (short))
- {
- unsigned short retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
- if (len == sizeof (int))
- {
- unsigned int retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
- if (len == sizeof (long))
- {
- unsigned long retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-#ifdef LONG_LONG
- if (len == sizeof (long long))
- {
- unsigned long long retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-#endif
- else
- {
- error ("That operation is not possible on an integer of that size.");
- }
+ return extract_unsigned_integer (valaddr, len);
}
- else if (code == TYPE_CODE_INT)
+ else if (code == TYPE_CODE_INT || code == TYPE_CODE_CHAR)
{
- if (len == sizeof (char))
- {
- char retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
- if (len == sizeof (short))
- {
- short retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
- if (len == sizeof (int))
- {
- int retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
- if (len == sizeof (long))
- {
- long retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-
-#ifdef LONG_LONG
- if (len == sizeof (long long))
- {
- long long retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
-#endif
- else
- {
- error ("That operation is not possible on an integer of that size.");
- }
+ return extract_signed_integer (valaddr, len);
}
/* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
whether we want this to be true eventually. */
- else if (code == TYPE_CODE_PTR
- || code == TYPE_CODE_REF)
+ else if (code == TYPE_CODE_PTR || code == TYPE_CODE_REF)
{
- if (len == sizeof(long))
- {
- long retval;
- bcopy (valaddr, &retval, sizeof(retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof(retval));
- return retval;
- }
- else if (len == sizeof(short))
- {
- short retval;
- bcopy (valaddr, &retval, len);
- SWAP_TARGET_AND_HOST (&retval, len);
- return retval;
- }
+ return extract_address (valaddr, len);
}
else if (code == TYPE_CODE_MEMBER)
error ("not implemented: member types in unpack_long");
- else if (code == TYPE_CODE_CHAR)
- return *(unsigned char *)valaddr;
error ("Value not integer or pointer.");
return 0; /* For lint -- never reached */
if (len == sizeof (float))
{
float retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (double))
{
double retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
}
else if (nosign) {
/* Unsigned -- be sure we compensate for signed LONGEST. */
-#ifdef LONG_LONG
- return (unsigned long long) unpack_long (type, valaddr);
-#else
- return (unsigned long ) unpack_long (type, valaddr);
-#endif
+ return (unsigned LONGEST) unpack_long (type, valaddr);
} else {
/* Signed -- we are OK with unpack_long. */
return unpack_long (type, valaddr);
struct type *type;
char *valaddr;
{
-#if 0
- /* The user should be able to use an int (e.g. 0x7892) in contexts
- where a pointer is expected. So this doesn't do enough. */
- register enum type_code code = TYPE_CODE (type);
- register int len = TYPE_LENGTH (type);
-
- if (code == TYPE_CODE_PTR
- || code == TYPE_CODE_REF)
- {
- if (len == sizeof (CORE_ADDR))
- {
- CORE_ADDR retval;
- bcopy (valaddr, &retval, sizeof (retval));
- SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
- return retval;
- }
- error ("Unrecognized pointer size.");
- }
- else if (code == TYPE_CODE_MEMBER)
- error ("not implemented: member types in unpack_pointer");
-
- error ("Value is not a pointer.");
- return 0; /* For lint -- never reached */
-#else
/* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
whether we want this to be true eventually. */
return unpack_long (type, valaddr);
-#endif
}
\f
/* Given a value ARG1 (offset by OFFSET bytes)
if (VALUE_LAZY (arg1))
VALUE_LAZY (v) = 1;
else
- bcopy (VALUE_CONTENTS_RAW (arg1) + offset,
- VALUE_CONTENTS_RAW (v),
- TYPE_LENGTH (type));
+ memcpy (VALUE_CONTENTS_RAW (v), VALUE_CONTENTS_RAW (arg1) + offset,
+ TYPE_LENGTH (type));
}
VALUE_LVAL (v) = VALUE_LVAL (arg1);
if (VALUE_LVAL (arg1) == lval_internalvar)
J is an index into F which provides the desired method. */
value
-value_fn_field (f, j)
+value_fn_field (arg1p, f, j, type, offset)
+ value *arg1p;
struct fn_field *f;
int j;
+ struct type *type;
+ int offset;
{
register value v;
- register struct type *type = TYPE_FN_FIELD_TYPE (f, j);
+ register struct type *ftype = TYPE_FN_FIELD_TYPE (f, j);
struct symbol *sym;
sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
if (! sym) error ("Internal error: could not find physical method named %s",
TYPE_FN_FIELD_PHYSNAME (f, j));
- v = allocate_value (type);
+ v = allocate_value (ftype);
VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
- VALUE_TYPE (v) = type;
+ VALUE_TYPE (v) = ftype;
+
+ if (arg1p)
+ {
+ if (type != VALUE_TYPE (*arg1p))
+ *arg1p = value_ind (value_cast (lookup_pointer_type (type),
+ value_addr (*arg1p)));
+
+ /* Move the `this' pointer according to the offset. */
+ VALUE_OFFSET (*arg1p) += offset;
+ }
+
return v;
}
/* Return a virtual function as a value.
ARG1 is the object which provides the virtual function
- table pointer. ARG1 is side-effected in calling this function.
+ table pointer. *ARG1P is side-effected in calling this function.
F is the list of member functions which contains the desired virtual
function.
J is an index into F which provides the desired virtual function.
TYPE is the type in which F is located. */
value
-value_virtual_fn_field (arg1, f, j, type)
- value arg1;
+value_virtual_fn_field (arg1p, f, j, type, offset)
+ value *arg1p;
struct fn_field *f;
int j;
struct type *type;
+ int offset;
{
+ value arg1 = *arg1p;
/* First, get the virtual function table pointer. That comes
with a strange type, so cast it to type `pointer to long' (which
should serve just fine as a function type). Then, index into
/* The virtual function table is now an array of structures
which have the form { int16 offset, delta; void *pfn; }. */
- vtbl = value_ind (value_field (arg1, TYPE_VPTR_FIELDNO (context)));
+ vtbl = value_ind (value_primitive_field (arg1, 0,
+ TYPE_VPTR_FIELDNO (context),
+ TYPE_VPTR_BASETYPE (context)));
/* Index into the virtual function table. This is hard-coded because
looking up a field is not cheap, and it may be important to save
entry = value_subscript (vtbl, vi);
/* Move the `this' pointer according to the virtual function table. */
- VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0));
+ VALUE_OFFSET (arg1) += value_as_long (value_field (entry, 0)) + offset;
if (! VALUE_LAZY (arg1))
{
VALUE_LAZY (arg1) = 1;
/* Reinstantiate the function pointer with the correct type. */
VALUE_TYPE (vfn) = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
+ *arg1p = arg1;
return vfn;
}
FIXME-tiemann: should work with dossier entries as well. */
static value
-value_headof (arg, btype, dtype)
- value arg;
+value_headof (in_arg, btype, dtype)
+ value in_arg;
struct type *btype, *dtype;
{
/* First collect the vtables we must look at for this object. */
/* FIXME-tiemann: right now, just look at top-most vtable. */
- value vtbl, entry, best_entry = 0;
- /* FIXME: entry_type is never used. */
- struct type *entry_type;
+ value arg, vtbl, entry, best_entry = 0;
int i, nelems;
int offset, best_offset = 0;
struct symbol *sym;
btype = TYPE_VPTR_BASETYPE (dtype);
check_stub_type (btype);
+ arg = in_arg;
if (btype != dtype)
- vtbl = value_cast (lookup_pointer_type (btype), arg);
- else
- vtbl = arg;
- vtbl = value_ind (value_field (value_ind (vtbl), TYPE_VPTR_FIELDNO (btype)));
+ arg = value_cast (lookup_pointer_type (btype), arg);
+ vtbl = value_ind (value_field (value_ind (arg), TYPE_VPTR_FIELDNO (btype)));
/* Check that VTBL looks like it points to a virtual function table. */
msymbol = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (vtbl));
if (msymbol == NULL
- || !VTBL_PREFIX_P (demangled_name = msymbol -> name))
+ || !VTBL_PREFIX_P (demangled_name = SYMBOL_NAME (msymbol)))
{
/* If we expected to find a vtable, but did not, let the user
know that we aren't happy, but don't throw an error.
FIXME: there has to be a better way to do this. */
struct type *error_type = (struct type *)xmalloc (sizeof (struct type));
- bcopy (VALUE_TYPE (arg), error_type, sizeof (struct type));
+ memcpy (error_type, VALUE_TYPE (in_arg), sizeof (struct type));
TYPE_NAME (error_type) = savestring ("suspicious *", sizeof ("suspicious *"));
- VALUE_TYPE (arg) = error_type;
- return arg;
+ VALUE_TYPE (in_arg) = error_type;
+ return in_arg;
}
/* Now search through the virtual function table. */
{
pc_for_sym = value_as_pointer (value_field (best_entry, 2));
sym = find_pc_function (pc_for_sym);
- demangled_name = cplus_demangle (SYMBOL_NAME (sym), -1);
+ demangled_name = cplus_demangle (SYMBOL_NAME (sym), DMGL_ANSI);
*(strchr (demangled_name, ':')) = '\0';
}
sym = lookup_symbol (demangled_name, 0, VAR_NAMESPACE, 0, 0);
- if (sym == 0)
- error ("could not find type declaration for `%s'", SYMBOL_NAME (sym));
+ if (sym == NULL)
+ error ("could not find type declaration for `%s'", demangled_name);
if (best_entry)
{
free (demangled_name);
arg = value_add (value_cast (builtin_type_int, arg),
value_field (best_entry, 0));
}
+ else arg = in_arg;
VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym));
return arg;
}
return value_headof (arg, 0, type);
}
+/* Return true if the INDEXth field of TYPE is a virtual baseclass
+ pointer which is for the base class whose type is BASECLASS. */
+
+static int
+vb_match (type, index, basetype)
+ struct type *type;
+ int index;
+ struct type *basetype;
+{
+ struct type *fieldtype;
+ char *name = TYPE_FIELD_NAME (type, index);
+ char *field_class_name = NULL;
+
+ if (*name != '_')
+ return 0;
+ /* gcc 2.4 uses _vb$. */
+ if (name[1] == 'v' && name[2] == 'b' && name[3] == CPLUS_MARKER)
+ field_class_name = name + 4;
+ /* gcc 2.5 will use __vb_. */
+ if (name[1] == '_' && name[2] == 'v' && name[3] == 'b' && name[4] == '_')
+ field_class_name = name + 5;
+
+ if (field_class_name == NULL)
+ /* This field is not a virtual base class pointer. */
+ return 0;
+
+ /* It's a virtual baseclass pointer, now we just need to find out whether
+ it is for this baseclass. */
+ fieldtype = TYPE_FIELD_TYPE (type, index);
+ if (fieldtype == NULL
+ || TYPE_CODE (fieldtype) != TYPE_CODE_PTR)
+ /* "Can't happen". */
+ return 0;
+
+ /* What we check for is that either the types are equal (needed for
+ nameless types) or have the same name. This is ugly, and a more
+ elegant solution should be devised (which would probably just push
+ the ugliness into symbol reading unless we change the stabs format). */
+ if (TYPE_TARGET_TYPE (fieldtype) == basetype)
+ return 1;
+
+ if (TYPE_NAME (basetype) != NULL
+ && TYPE_NAME (TYPE_TARGET_TYPE (fieldtype)) != NULL
+ && STREQ (TYPE_NAME (basetype),
+ TYPE_NAME (TYPE_TARGET_TYPE (fieldtype))))
+ return 1;
+ return 0;
+}
+
+/* Compute the offset of the baseclass which is
+ the INDEXth baseclass of class TYPE, for a value ARG,
+ wih extra offset of OFFSET.
+ The result is the offste of the baseclass value relative
+ to (the address of)(ARG) + OFFSET.
+
+ -1 is returned on error. */
+
+int
+baseclass_offset (type, index, arg, offset)
+ struct type *type;
+ int index;
+ value arg;
+ int offset;
+{
+ struct type *basetype = TYPE_BASECLASS (type, index);
+
+ if (BASETYPE_VIA_VIRTUAL (type, index))
+ {
+ /* Must hunt for the pointer to this virtual baseclass. */
+ register int i, len = TYPE_NFIELDS (type);
+ register int n_baseclasses = TYPE_N_BASECLASSES (type);
+
+ /* First look for the virtual baseclass pointer
+ in the fields. */
+ for (i = n_baseclasses; i < len; i++)
+ {
+ if (vb_match (type, i, basetype))
+ {
+ CORE_ADDR addr
+ = unpack_pointer (TYPE_FIELD_TYPE (type, i),
+ VALUE_CONTENTS (arg) + VALUE_OFFSET (arg)
+ + offset
+ + (TYPE_FIELD_BITPOS (type, i) / 8));
+
+ if (VALUE_LVAL (arg) != lval_memory)
+ return -1;
+
+ return addr -
+ (LONGEST) (VALUE_ADDRESS (arg) + VALUE_OFFSET (arg) + offset);
+ }
+ }
+ /* Not in the fields, so try looking through the baseclasses. */
+ for (i = index+1; i < n_baseclasses; i++)
+ {
+ int boffset =
+ baseclass_offset (type, i, arg, offset);
+ if (boffset)
+ return boffset;
+ }
+ /* Not found. */
+ return -1;
+ }
+
+ /* Baseclass is easily computed. */
+ return TYPE_BASECLASS_BITPOS (type, index) / 8;
+}
+
/* Compute the address of the baseclass which is
the INDEXth baseclass of class TYPE. The TYPE base
of the object is at VALADDR.
of the baseclasss, but the address which could not be read
successfully. */
+/* FIXME Fix remaining uses of baseclass_addr to use baseclass_offset */
+
char *
baseclass_addr (type, index, valaddr, valuep, errp)
struct type *type;
/* Must hunt for the pointer to this virtual baseclass. */
register int i, len = TYPE_NFIELDS (type);
register int n_baseclasses = TYPE_N_BASECLASSES (type);
- char *vbase_name, *type_name = type_name_no_tag (basetype);
- vbase_name = (char *)alloca (strlen (type_name) + 8);
- sprintf (vbase_name, "_vb$%s", type_name);
/* First look for the virtual baseclass pointer
in the fields. */
for (i = n_baseclasses; i < len; i++)
{
- if (! strcmp (vbase_name, TYPE_FIELD_NAME (type, i)))
+ if (vb_match (type, i, basetype))
{
value val = allocate_value (basetype);
CORE_ADDR addr;
return valaddr + TYPE_BASECLASS_BITPOS (type, index) / 8;
}
\f
-long
+/* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at
+ VALADDR.
+
+ Extracting bits depends on endianness of the machine. Compute the
+ number of least significant bits to discard. For big endian machines,
+ we compute the total number of bits in the anonymous object, subtract
+ off the bit count from the MSB of the object to the MSB of the
+ bitfield, then the size of the bitfield, which leaves the LSB discard
+ count. For little endian machines, the discard count is simply the
+ number of bits from the LSB of the anonymous object to the LSB of the
+ bitfield.
+
+ If the field is signed, we also do sign extension. */
+
+LONGEST
unpack_field_as_long (type, valaddr, fieldno)
struct type *type;
char *valaddr;
int fieldno;
{
- unsigned long val;
+ unsigned LONGEST val;
+ unsigned LONGEST valmask;
int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+ int lsbcount;
+
+ val = extract_unsigned_integer (valaddr + bitpos / 8, sizeof (val));
- bcopy (valaddr + bitpos / 8, &val, sizeof val);
- SWAP_TARGET_AND_HOST (&val, sizeof val);
+ /* Extract bits. See comment above. */
- /* Extracting bits depends on endianness of the machine. */
#if BITS_BIG_ENDIAN
- val = val >> (sizeof val * 8 - bitpos % 8 - bitsize);
+ lsbcount = (sizeof val * 8 - bitpos % 8 - bitsize);
#else
- val = val >> (bitpos % 8);
+ lsbcount = (bitpos % 8);
#endif
+ val >>= lsbcount;
- if (bitsize < 8 * sizeof (val))
- val &= (((unsigned long)1) << bitsize) - 1;
- return val;
+ /* If the field does not entirely fill a LONGEST, then zero the sign bits.
+ If the field is signed, and is negative, then sign extend. */
+
+ if ((bitsize > 0) && (bitsize < 8 * sizeof (val)))
+ {
+ valmask = (((unsigned LONGEST) 1) << bitsize) - 1;
+ val &= valmask;
+ if (!TYPE_UNSIGNED (TYPE_FIELD_TYPE (type, fieldno)))
+ {
+ if (val & (valmask ^ (valmask >> 1)))
+ {
+ val |= ~valmask;
+ }
+ }
+ }
+ return (val);
}
/* Modify the value of a bitfield. ADDR points to a block of memory in
void
modify_field (addr, fieldval, bitpos, bitsize)
char *addr;
- int fieldval;
+ LONGEST fieldval;
int bitpos, bitsize;
{
- long oword;
+ LONGEST oword;
/* Reject values too big to fit in the field in question,
otherwise adjoining fields may be corrupted. */
if (bitsize < (8 * sizeof (fieldval))
&& 0 != (fieldval & ~((1<<bitsize)-1)))
- error ("Value %d does not fit in %d bits.", fieldval, bitsize);
-
- bcopy (addr, &oword, sizeof oword);
- SWAP_TARGET_AND_HOST (&oword, sizeof oword); /* To host format */
+ {
+ /* FIXME: would like to include fieldval in the message, but
+ we don't have a sprintf_longest. */
+ error ("Value does not fit in %d bits.", bitsize);
+ }
+
+ oword = extract_signed_integer (addr, sizeof oword);
/* Shifting for bit field depends on endianness of the target machine. */
#if BITS_BIG_ENDIAN
bitpos = sizeof (oword) * 8 - bitpos - bitsize;
#endif
- /* Mask out old value, while avoiding shifts >= longword size */
+ /* Mask out old value, while avoiding shifts >= size of oword */
if (bitsize < 8 * sizeof (oword))
- oword &= ~(((((unsigned long)1) << bitsize) - 1) << bitpos);
+ oword &= ~(((((unsigned LONGEST)1) << bitsize) - 1) << bitpos);
else
- oword &= ~((-1) << bitpos);
+ oword &= ~((~(unsigned LONGEST)0) << bitpos);
oword |= fieldval << bitpos;
- SWAP_TARGET_AND_HOST (&oword, sizeof oword); /* To target format */
- bcopy (&oword, addr, sizeof oword);
+ store_signed_integer (addr, sizeof oword, oword);
}
\f
/* Convert C numbers into newly allocated values */
register enum type_code code = TYPE_CODE (type);
register int len = TYPE_LENGTH (type);
- /* FIXME, we assume that pointers have the same form and byte order as
- integers, and that all pointers have the same form. */
- if (code == TYPE_CODE_INT || code == TYPE_CODE_ENUM ||
- code == TYPE_CODE_CHAR || code == TYPE_CODE_PTR ||
- code == TYPE_CODE_REF)
+ switch (code)
{
- if (len == sizeof (char))
- * (char *) VALUE_CONTENTS_RAW (val) = num;
- else if (len == sizeof (short))
- * (short *) VALUE_CONTENTS_RAW (val) = num;
- else if (len == sizeof (int))
- * (int *) VALUE_CONTENTS_RAW (val) = num;
- else if (len == sizeof (long))
- * (long *) VALUE_CONTENTS_RAW (val) = num;
-#ifdef LONG_LONG
- else if (len == sizeof (long long))
- * (long long *) VALUE_CONTENTS_RAW (val) = num;
-#endif
- else
- error ("Integer type encountered with unexpected data length.");
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_BOOL:
+ store_signed_integer (VALUE_CONTENTS_RAW (val), len, num);
+ break;
+
+ case TYPE_CODE_REF:
+ case TYPE_CODE_PTR:
+ /* This assumes that all pointers of a given length
+ have the same form. */
+ store_address (VALUE_CONTENTS_RAW (val), len, (CORE_ADDR) num);
+ break;
+
+ default:
+ error ("Unexpected type encountered for integer constant.");
}
- else
- error ("Unexpected type encountered for integer constant.");
-
- /* num was in host byte order. So now put the value's contents
- into target byte order. */
- SWAP_TARGET_AND_HOST (VALUE_CONTENTS_RAW (val), len);
-
return val;
}
On most machines, the struct convention is used unless we are
using gcc and the type is of a special size. */
+/* As of about 31 Mar 93, GCC was changed to be compatible with the
+ native compiler. GCC 2.3.3 was the last release that did it the
+ old way. Since gcc2_compiled was not changed, we have no
+ way to correctly win in all cases, so we just do the right thing
+ for gcc1 and for gcc2 after this change. Thus it loses for gcc
+ 2.0-2.3.3. This is somewhat unfortunate, but changing gcc2_compiled
+ would cause more chaos than dealing with some struct returns being
+ handled wrong. */
#if !defined (USE_STRUCT_CONVENTION)
#define USE_STRUCT_CONVENTION(gcc_p, type)\
- (!((gcc_p) && (TYPE_LENGTH (value_type) == 1 \
- || TYPE_LENGTH (value_type) == 2 \
- || TYPE_LENGTH (value_type) == 4 \
- || TYPE_LENGTH (value_type) == 8 \
- ) \
+ (!((gcc_p == 1) && (TYPE_LENGTH (value_type) == 1 \
+ || TYPE_LENGTH (value_type) == 2 \
+ || TYPE_LENGTH (value_type) == 4 \
+ || TYPE_LENGTH (value_type) == 8 \
+ ) \
))
#endif