-/* Low level packing and unpacking of values for GDB.
- Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+/* Low level packing and unpacking of values for GDB, the GNU Debugger.
+ Copyright 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
This file is part of GDB.
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-#include <stdio.h>
-#include <string.h>
#include "defs.h"
-#include "param.h"
+#include <string.h>
#include "symtab.h"
+#include "gdbtypes.h"
#include "value.h"
#include "gdbcore.h"
#include "frame.h"
#include "command.h"
#include "gdbcmd.h"
+#include "target.h"
+#include "demangle.h"
-extern char *cplus_demangle ();
-extern char *cplus_mangle_opname ();
+/* Local function prototypes. */
+
+static value
+value_headof PARAMS ((value, struct type *, struct type *));
+
+static void
+show_values PARAMS ((char *, int));
+
+static void
+show_convenience PARAMS ((char *, int));
/* The value-history records all the values printed
by print commands during this session. Each chunk
It contains the same contents, for same memory address,
but it's a different block of storage. */
-static value
+value
value_copy (arg)
value arg;
{
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;
}
{
for (i = 0; i < VALUE_HISTORY_CHUNK; i++)
if (val = value_history_chain->values[i])
- free (val);
+ 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;
return var;
var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
- var->name = concat (name, "", "");
+ var->name = concat (name, NULL);
var->value = allocate_value (builtin_type_void);
release_value (var->value);
var->next = internalvars;
modify_field (addr, (int) 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 ("$%s = ", var->name);
+ printf_filtered ("$%s = ", var->name);
value_print (var->value, stdout, 0, Val_pretty_default);
- printf ("\n");
+ printf_filtered ("\n");
}
if (!varseen)
printf ("No debugger convenience variables now defined.\n\
{
/* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
whether we want this to be true eventually. */
- return value_as_long (val);
+ return ADDR_BITS_REMOVE(value_as_long (val));
}
\f
/* Unpack raw data (copied from debugee, target byte order) at VALADDR
to member which reaches here is considered to be equivalent
to an INT (or some size). After all, it is only an offset. */
+/* FIXME: This should be rewritten as a switch statement for speed and
+ ease of comprehension. */
+
LONGEST
unpack_long (type, valaddr)
struct type *type;
register int len = TYPE_LENGTH (type);
register int nosign = TYPE_UNSIGNED (type);
- if (code == TYPE_CODE_ENUM)
+ if (code == TYPE_CODE_ENUM || code == TYPE_CODE_BOOL)
code = TYPE_CODE_INT;
if (code == TYPE_CODE_FLT)
{
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;
}
if (len == sizeof (short))
{
unsigned short retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (int))
{
unsigned int retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (long))
{
unsigned long retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (long long))
{
unsigned long long retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
{
if (len == sizeof (char))
{
- char retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ SIGNED char retval; /* plain chars might be unsigned on host */
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (short))
{
short retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (int))
{
int retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (long))
{
long retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
if (len == sizeof (long long))
{
long long retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
else 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;
- }
+ if (len == sizeof(long))
+ {
+ unsigned long retval;
+ memcpy (&retval, valaddr, sizeof(retval));
+ SWAP_TARGET_AND_HOST (&retval, sizeof(retval));
+ return retval;
+ }
+ else if (len == sizeof(short))
+ {
+ unsigned short retval;
+ memcpy (&retval, valaddr, len);
+ SWAP_TARGET_AND_HOST (&retval, len);
+ return retval;
+ }
}
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;
}
if (len == sizeof (CORE_ADDR))
{
CORE_ADDR retval;
- bcopy (valaddr, &retval, sizeof (retval));
+ memcpy (&retval, valaddr, sizeof (retval));
SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
return retval;
}
offset += TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
if (TYPE_FIELD_BITSIZE (arg_type, fieldno))
{
- v = value_from_long (type,
+ v = value_from_longest (type,
unpack_field_as_long (arg_type,
VALUE_CONTENTS (arg1),
fieldno));
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)
return value_primitive_field (arg1, 0, fieldno, VALUE_TYPE (arg1));
}
+/* Return a non-virtual function as a value.
+ F is the list of member functions which contains the desired method.
+ J is an index into F which provides the desired method. */
+
value
-value_fn_field (arg1, fieldno, subfieldno)
- register value arg1;
- register int fieldno;
- int subfieldno;
+value_fn_field (f, j)
+ struct fn_field *f;
+ int j;
{
register value v;
- struct fn_field *f = TYPE_FN_FIELDLIST1 (VALUE_TYPE (arg1), fieldno);
- register struct type *type = TYPE_FN_FIELD_TYPE (f, subfieldno);
+ register struct type *type = TYPE_FN_FIELD_TYPE (f, j);
struct symbol *sym;
- sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, subfieldno),
+ sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
0, VAR_NAMESPACE, 0, NULL);
if (! sym) error ("Internal error: could not find physical method named %s",
- TYPE_FN_FIELD_PHYSNAME (f, subfieldno));
+ TYPE_FN_FIELD_PHYSNAME (f, j));
v = allocate_value (type);
VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
should serve just fine as a function type). Then, index into
the table, and convert final value to appropriate function type. */
value entry, vfn, vtbl;
- value vi = value_from_long (builtin_type_int,
+ value vi = value_from_longest (builtin_type_int,
(LONGEST) TYPE_FN_FIELD_VOFFSET (f, j));
struct type *fcontext = TYPE_FN_FIELD_FCONTEXT (f, j);
struct type *context;
/* 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;
int i, nelems;
int offset, best_offset = 0;
struct symbol *sym;
CORE_ADDR pc_for_sym;
char *demangled_name;
+ struct minimal_symbol *msymbol;
btype = TYPE_VPTR_BASETYPE (dtype);
check_stub_type (btype);
vtbl = value_ind (value_field (value_ind (vtbl), TYPE_VPTR_FIELDNO (btype)));
/* Check that VTBL looks like it points to a virtual function table. */
- i = find_pc_misc_function (VALUE_ADDRESS (vtbl));
- if (i < 0 || ! VTBL_PREFIX_P (misc_function_vector[i].name))
+ msymbol = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (vtbl));
+ if (msymbol == NULL
+ || !VTBL_PREFIX_P (demangled_name = msymbol -> name))
{
/* 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 (arg), sizeof (struct type));
TYPE_NAME (error_type) = savestring ("suspicious *", sizeof ("suspicious *"));
VALUE_TYPE (arg) = error_type;
return arg;
/* Now search through the virtual function table. */
entry = value_ind (vtbl);
- entry_type = VALUE_TYPE (entry);
nelems = longest_to_int (value_as_long (value_field (entry, 2)));
for (i = 1; i <= nelems; i++)
{
- entry = value_subscript (vtbl, value_from_long (builtin_type_int, i));
+ entry = value_subscript (vtbl, value_from_longest (builtin_type_int,
+ (LONGEST) i));
offset = longest_to_int (value_as_long (value_field (entry, 0)));
- if (offset < best_offset)
+ /* If we use '<=' we can handle single inheritance
+ * where all offsets are zero - just use the first entry found. */
+ if (offset <= best_offset)
{
best_offset = offset;
best_entry = entry;
}
}
- if (best_entry == 0)
- return arg;
-
/* Move the pointer according to BEST_ENTRY's offset, and figure
out what type we should return as the new pointer. */
- 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);
- *(strchr (demangled_name, ':')) = '\0';
+ if (best_entry == 0)
+ {
+ /* An alternative method (which should no longer be necessary).
+ * But we leave it in for future use, when we will hopefully
+ * have optimizes the vtable to use thunks instead of offsets. */
+ /* Use the name of vtable itself to extract a base type. */
+ demangled_name += 4; /* Skip _vt$ prefix. */
+ }
+ else
+ {
+ 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), 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));
- free (demangled_name);
- arg = value_add (value_cast (builtin_type_int, arg),
- value_field (best_entry, 0));
+ if (best_entry)
+ {
+ free (demangled_name);
+ arg = value_add (value_cast (builtin_type_int, arg),
+ value_field (best_entry, 0));
+ }
VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym));
return arg;
}
return value_headof (arg, 0, type);
}
-/* The value of a static class member does not depend
- on its instance, only on its type. If FIELDNO >= 0,
- then fieldno is a valid field number and is used directly.
- Otherwise, FIELDNAME is the name of the field we are
- searching for. If it is not a static field name, an
- error is signaled. TYPE is the type in which we look for the
- static field member.
-
- Return zero if we couldn't find anything; the caller may signal
- an error in that case. */
-
-value
-value_static_field (type, fieldname, fieldno)
- register struct type *type;
- char *fieldname;
- register int fieldno;
-{
- register value v;
- struct symbol *sym;
- char *phys_name;
-
- if (fieldno < 0)
- {
- /* Look for static field. */
- int i;
- for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
- if (! strcmp (TYPE_FIELD_NAME (type, i), fieldname))
- {
- if (TYPE_FIELD_STATIC (type, i))
- {
- fieldno = i;
- goto found;
- }
- else
- error ("field `%s' is not static", fieldname);
- }
- for (; i > 0; i--)
- {
- v = value_static_field (TYPE_BASECLASS (type, i), fieldname, -1);
- if (v != 0)
- return v;
- }
-
- if (destructor_name_p (fieldname, type))
- error ("Cannot get value of destructor");
-
- for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--)
- {
- if (! strcmp (TYPE_FN_FIELDLIST_NAME (type, i), fieldname))
- error ("Cannot get value of method \"%s\"", fieldname);
- }
- error("there is no field named %s", fieldname);
- }
-
- found:
- phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno);
- sym = lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL);
- if (! sym) error ("Internal error: could not find physical static variable named %s", phys_name);
-
- type = TYPE_FIELD_TYPE (type, fieldno);
- v = value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
- return v;
-}
-
/* Compute the address of the baseclass which is
- the INDEXth baseclass of TYPE. The TYPE base
+ the INDEXth baseclass of class TYPE. The TYPE base
of the object is at VALADDR.
If ERRP is non-NULL, set *ERRP to be the errno code of any error,
register int n_baseclasses = TYPE_N_BASECLASSES (type);
char *vbase_name, *type_name = type_name_no_tag (basetype);
- if (TYPE_MAIN_VARIANT (basetype))
- basetype = TYPE_MAIN_VARIANT (basetype);
-
vbase_name = (char *)alloca (strlen (type_name) + 8);
sprintf (vbase_name, "_vb$%s", type_name);
/* First look for the virtual baseclass pointer
status = target_read_memory (addr,
VALUE_CONTENTS_RAW (val),
- TYPE_LENGTH (type));
+ TYPE_LENGTH (basetype));
VALUE_LVAL (val) = lval_memory;
VALUE_ADDRESS (val) = addr;
*valuep = 0;
return valaddr + TYPE_BASECLASS_BITPOS (type, index) / 8;
}
+\f
+/* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at
+ VALADDR.
-/* Ugly hack to convert method stubs into method types.
-
- He ain't kiddin'. This demangles the name of the method into a string
- including argument types, parses out each argument type, generates
- a string casting a zero to that type, evaluates the string, and stuffs
- the resulting type into an argtype vector!!! Then it knows the type
- of the whole function (including argument types for overloading),
- which info used to be in the stab's but was removed to hack back
- the space required for them. */
-void
-check_stub_method (type, i, j)
- struct type *type;
- int i, j;
-{
- extern char *gdb_mangle_typename (), *strchr ();
- struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
- char *field_name = TYPE_FN_FIELDLIST_NAME (type, i);
- char *inner_name = gdb_mangle_typename (type);
- int mangled_name_len = (strlen (field_name)
- + strlen (inner_name)
- + strlen (TYPE_FN_FIELD_PHYSNAME (f, j))
- + 1);
- char *mangled_name;
- char *demangled_name;
- char *argtypetext, *p;
- int depth = 0, argcount = 1;
- struct type **argtypes;
-
- if (OPNAME_PREFIX_P (field_name))
- {
- char *opname = cplus_mangle_opname (field_name + 3);
- if (opname == NULL)
- error ("No mangling for \"%s\"", field_name);
- mangled_name_len += strlen (opname);
- mangled_name = (char *)xmalloc (mangled_name_len);
-
- strncpy (mangled_name, field_name, 3);
- mangled_name[3] = '\0';
- strcat (mangled_name, opname);
- }
- else
- {
- mangled_name = (char *)xmalloc (mangled_name_len);
- strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i));
- }
- strcat (mangled_name, inner_name);
- strcat (mangled_name, TYPE_FN_FIELD_PHYSNAME (f, j));
- demangled_name = cplus_demangle (mangled_name, 0);
-
- /* Now, read in the parameters that define this type. */
- argtypetext = strchr (demangled_name, '(') + 1;
- p = argtypetext;
- while (*p)
- {
- if (*p == '(')
- depth += 1;
- else if (*p == ')')
- depth -= 1;
- else if (*p == ',' && depth == 0)
- argcount += 1;
-
- p += 1;
- }
- /* We need one more slot for the void [...] or NULL [end of arglist] */
- argtypes = (struct type **)xmalloc ((argcount+1) * sizeof (struct type *));
- p = argtypetext;
- argtypes[0] = lookup_pointer_type (type);
- argcount = 1;
-
- if (*p != ')') /* () means no args, skip while */
- {
- while (*p)
- {
- if (*p == '(')
- depth += 1;
- else if (*p == ')')
- depth -= 1;
-
- if (depth <= 0 && (*p == ',' || *p == ')'))
- {
- char *tmp = (char *)alloca (p - argtypetext + 4);
- value val;
- tmp[0] = '(';
- bcopy (argtypetext, tmp+1, p - argtypetext);
- tmp[p-argtypetext+1] = ')';
- tmp[p-argtypetext+2] = '0';
- tmp[p-argtypetext+3] = '\0';
- val = parse_and_eval (tmp);
- argtypes[argcount] = VALUE_TYPE (val);
- argcount += 1;
- argtypetext = p + 1;
- }
- p += 1;
- }
- }
-
- if (p[-2] != '.') /* ... */
- argtypes[argcount] = builtin_type_void; /* Ellist terminator */
- else
- argtypes[argcount] = NULL; /* List terminator */
+ 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.
- free (demangled_name);
+ If the field is signed, we also do sign extension. */
- type = lookup_method_type (type, TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), argtypes);
- /* Free the stub type...it's no longer needed. */
- free (TYPE_FN_FIELD_TYPE (f, j));
- TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
- TYPE_FN_FIELD_TYPE (f, j) = type;
-}
-\f
-long
+LONGEST
unpack_field_as_long (type, valaddr, fieldno)
struct type *type;
char *valaddr;
int fieldno;
{
- long val;
+ unsigned LONGEST val;
+ unsigned LONGEST valmask;
int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+ int lsbcount;
+
+ memcpy (&val, valaddr + bitpos / 8, sizeof (val));
+ SWAP_TARGET_AND_HOST (&val, 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;
- val &= (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
{
long oword;
- /* Reject values too big to fit in the field in question.
- Otherwise adjoining fields may be corrupted. */
- if (fieldval & ~((1<<bitsize)-1))
+ /* 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);
+ memcpy (&oword, addr, sizeof oword);
SWAP_TARGET_AND_HOST (&oword, sizeof oword); /* To host format */
/* Shifting for bit field depends on endianness of the target machine. */
bitpos = sizeof (oword) * 8 - bitpos - bitsize;
#endif
- oword &= ~(((1 << bitsize) - 1) << bitpos);
+ /* Mask out old value, while avoiding shifts >= longword size */
+ if (bitsize < 8 * sizeof (oword))
+ oword &= ~(((((unsigned long)1) << bitsize) - 1) << bitpos);
+ else
+ oword &= ~((-1) << bitpos);
oword |= fieldval << bitpos;
SWAP_TARGET_AND_HOST (&oword, sizeof oword); /* To target format */
- bcopy (&oword, addr, sizeof oword);
+ memcpy (addr, &oword, sizeof oword);
}
\f
/* Convert C numbers into newly allocated values */
value
-value_from_long (type, num)
+value_from_longest (type, num)
struct type *type;
register LONGEST num;
{
register enum type_code code = TYPE_CODE (type);
register int len = TYPE_LENGTH (type);
- if (code == TYPE_CODE_INT || code == TYPE_CODE_ENUM)
+ /* 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)
{
if (len == sizeof (char))
* (char *) VALUE_CONTENTS_RAW (val) = num;
if (code == TYPE_CODE_ERROR)
error ("Function return type unknown.");
- if (code == TYPE_CODE_STRUCT
- || code == TYPE_CODE_UNION)
- error ("Specifying a struct or union return value is not supported.");
+ if ( code == TYPE_CODE_STRUCT
+ || code == TYPE_CODE_UNION) /* FIXME, implement struct return. */
+ error ("GDB does not support specifying a struct or union return value.");
/* FIXME, this is bogus. We don't know what the return conventions
are, or how values should be promoted.... */