* valops.c (typecmp): Now static.
authorMichael Tiemann <tiemann@cygnus>
Mon, 1 Feb 1993 01:12:37 +0000 (01:12 +0000)
committerMichael Tiemann <tiemann@cygnus>
Mon, 1 Feb 1993 01:12:37 +0000 (01:12 +0000)
gdb/ChangeLog
gdb/valops.c

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