* c-exp.y (yyerror): Pass error message if given.
[deliverable/binutils-gdb.git] / gdb / values.c
index 2981265b571bc0deb937114c89e39c89259b650d..a5b2c69f6c2eac22280426d685787d515a966e20 100644 (file)
@@ -3,19 +3,19 @@
 
 This file is part of GDB.
 
-GDB is free software; you can redistribute it and/or modify
+This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
 
-GDB is distributed in the hope that it will be useful,
+This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GDB; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+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>
@@ -29,7 +29,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "gdbcmd.h"
 
 extern char *cplus_demangle ();
-extern char *cplus_mangle_opname ();
 
 /* The value-history records all the values printed
    by print commands during this session.  Each chunk
@@ -50,7 +49,6 @@ struct value_history_chunk
 static struct value_history_chunk *value_history_chain;
 
 static int value_history_count;        /* Abs number of last entry stored */
-
 \f
 /* List of all value objects currently allocated
    (except for those released by calls to release_value)
@@ -494,9 +492,9 @@ show_convenience ()
 #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\
@@ -533,6 +531,16 @@ value_as_double (val)
     error ("Invalid floating value found in program.");
   return foo;
 }
+/* Extract a value as a C pointer.
+   Does not deallocate the value.  */
+CORE_ADDR
+value_as_pointer (val)
+     value val;
+{
+  /* 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);
+}
 \f
 /* Unpack raw data (copied from debugee, target byte order) at VALADDR
    as a long, or as a double, assuming the raw data is described
@@ -548,6 +556,9 @@ value_as_double (val)
    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;
@@ -557,7 +568,7 @@ unpack_long (type, valaddr)
   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)
     {
@@ -675,10 +686,12 @@ unpack_long (type, valaddr)
          error ("That operation is not possible on an integer of that size.");
        }
     }
+  /* 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)
     {
-      if (len == sizeof (char *))
+      if (len == sizeof (CORE_ADDR))
        {
          CORE_ADDR retval;
          bcopy (valaddr, &retval, sizeof (retval));
@@ -688,6 +701,8 @@ unpack_long (type, valaddr)
     }
   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 */
@@ -736,6 +751,7 @@ unpack_double (type, valaddr, invp)
       else
        {
          error ("Unexpected type of floating point number.");
+         return 0; /* Placate lint.  */
        }
     }
   else if (nosign) {
@@ -750,6 +766,54 @@ unpack_double (type, valaddr, invp)
     return unpack_long (type, valaddr);
   }
 }
+
+/* Unpack raw data (copied from debugee, target byte order) at VALADDR
+   as a CORE_ADDR, assuming the raw data is described by type TYPE.
+   We don't assume any alignment for the raw data.  Return value is in
+   host byte order.
+
+   If you want functions and arrays to be coerced to pointers, and
+   references to be dereferenced, call value_as_pointer() instead.
+
+   C++: It is assumed that the front-end has taken care of
+   all matters concerning pointers to members.  A pointer
+   to member which reaches here is considered to be equivalent
+   to an INT (or some size).  After all, it is only an offset.  */
+
+CORE_ADDR
+unpack_pointer (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)
    of a struct or union type ARG_TYPE,
@@ -776,7 +840,7 @@ value_primitive_field (arg1, offset, fieldno, arg_type)
   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));
@@ -857,7 +921,7 @@ value_virtual_fn_field (arg1, f, j, type)
      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;
@@ -923,18 +987,24 @@ value_headof (arg, 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;
   int i, nelems;
   int offset, best_offset = 0;
   struct symbol *sym;
   CORE_ADDR pc_for_sym;
   char *demangled_name;
-
-  vtbl = value_ind (value_field (value_ind (arg), TYPE_VPTR_FIELDNO (dtype)));
+  btype = TYPE_VPTR_BASETYPE (dtype);
+  check_stub_type (btype);
+  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)));
 
   /* 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))
+  if (i < 0 || ! VTBL_PREFIX_P (demangled_name = misc_function_vector[i].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.
@@ -948,33 +1018,46 @@ value_headof (arg, btype, dtype)
 
   /* Now search through the virtual function table.  */
   entry = value_ind (vtbl);
-  entry_type = VALUE_TYPE (entry);
-  nelems = value_as_long (value_field (entry, 2));
+  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));
-      offset = value_as_long (value_field (entry, 0));
-      if (offset < best_offset)
+      entry = value_subscript (vtbl, value_from_longest (builtin_type_int, 
+                                                     (LONGEST) i));
+      offset = longest_to_int (value_as_long (value_field (entry, 0)));
+      /* 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_long (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), -1);
+      *(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;
 }
@@ -1021,7 +1104,6 @@ value_static_field (type, fieldname, fieldno)
 
   if (fieldno < 0)
     {
-      register struct type *t = type;
       /* Look for static field.  */
       int i;
       for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
@@ -1084,7 +1166,7 @@ baseclass_addr (type, index, valaddr, valuep, errp)
 
   if (errp)
     *errp = 0;
-  
+
   if (BASETYPE_VIA_VIRTUAL (type, index))
     {
       /* Must hunt for the pointer to this virtual baseclass.  */
@@ -1107,12 +1189,13 @@ baseclass_addr (type, index, valaddr, valuep, errp)
              CORE_ADDR addr;
              int status;
 
-             addr = unpack_long (TYPE_FIELD_TYPE (type, i),
+             addr
+               = unpack_pointer (TYPE_FIELD_TYPE (type, i),
                                  valaddr + (TYPE_FIELD_BITPOS (type, i) / 8));
 
              status = target_read_memory (addr,
                                           VALUE_CONTENTS_RAW (val),
-                                          TYPE_LENGTH (type));
+                                          TYPE_LENGTH (basetype));
              VALUE_LVAL (val) = lval_memory;
              VALUE_ADDRESS (val) = addr;
 
@@ -1139,7 +1222,7 @@ baseclass_addr (type, index, valaddr, valuep, errp)
        {
          char *baddr;
 
-         baddr = baseclass_addr (type, i, valaddr, valuep);
+         baddr = baseclass_addr (type, i, valaddr, valuep, errp);
          if (baddr)
            return baddr;
        }
@@ -1169,39 +1252,14 @@ check_stub_method (type, i, j)
      struct type *type;
      int i, j;
 {
-  extern char *gdb_mangle_typename (), *strchr ();
+  extern char *gdb_mangle_name (), *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 *mangled_name = gdb_mangle_name (type, i, j);
+  char *demangled_name = cplus_demangle (mangled_name, 0);
   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);
-      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;
@@ -1255,7 +1313,7 @@ check_stub_method (type, i, j)
     argtypes[argcount] = NULL;         /* List terminator */
 
   free (demangled_name);
-  
+
   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));
@@ -1283,7 +1341,8 @@ unpack_field_as_long (type, valaddr, fieldno)
   val = val >> (bitpos % 8);
 #endif
 
-  val &= (1 << bitsize) - 1;
+  if (bitsize < 8 * sizeof (val))
+    val &= (((unsigned long)1) << bitsize) - 1;
   return val;
 }
 
@@ -1300,9 +1359,10 @@ modify_field (addr, fieldval, bitpos, bitsize)
 {
   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);
@@ -1313,7 +1373,11 @@ modify_field (addr, fieldval, bitpos, bitsize)
   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 */
@@ -1323,7 +1387,7 @@ modify_field (addr, fieldval, bitpos, bitsize)
 /* Convert C numbers into newly allocated values */
 
 value
-value_from_long (type, num)
+value_from_longest (type, num)
      struct type *type;
      register LONGEST num;
 {
@@ -1331,7 +1395,10 @@ value_from_long (type, 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)
     {
       if (len == sizeof (char))
        * (char *) VALUE_CONTENTS_RAW (val) = num;
This page took 0.041157 seconds and 4 git commands to generate.