* gdbtypes.h (struct builtin_type): Add internal_fn member.
authorUlrich Weigand <uweigand@de.ibm.com>
Thu, 2 Jul 2009 12:11:19 +0000 (12:11 +0000)
committerUlrich Weigand <uweigand@de.ibm.com>
Thu, 2 Jul 2009 12:11:19 +0000 (12:11 +0000)
* gdbtypes.c (gdbtypes_post_init): Initialize it.
* value.c (internal_fn_type): Remove.
(_initialize_values): Do not initialize it.

* value.c (struct internalvar): Add enum internalvar_kind type and
kind member.  Restructure union internalvar_data type.  Remove type,
canonical, and make_value members.
(init_if_undefined_command): Update for data structure changes.
(create_internalvar): Likewise.
(create_internalvar_type_lazy): Likewise.
(get_internalvar_integer): Likewise.
(get_internalvar_function): Likewise.
(set_internalvar_component): Likewise.
(set_internalvar): Likewise.
(set_internalvar_integer): Likewise.
(set_internalvar_function): Likewise.
(clear_internalvar): Likewise.
(add_internal_function): Likewise.
(preserve_one_internalvar): New function.
(preserve_values): Call it.

* value.h (value_of_internalvar): Add GDBARCH parameter.
(internalvar_make_value): Likewise.
* value.c (value_of_internalvar): Add GDBARCH parameter.  Pass it to
make_value callback.  Use it to generate per-architecture result value
types for internal variables with no pre-defined type.  Update for data
structure changes.
(show_convenience): Pass architecture to value_of_internalvar.
* eval.c (evaluate_subexp_standard): Likewise.
* infrun.c (siginfo_make_value): Add GDBARCH parameter.  Use it
instead of current frame architecture.  Return per-architecture type.

* value.h (set_internalvar_string): Add prototype.
* value.c (set_internalvar_string): New function.
* tracepoint.c (set_traceframe_context): Use it.

gdb/ChangeLog
gdb/eval.c
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/infrun.c
gdb/tracepoint.c
gdb/value.c
gdb/value.h

index cfc9ac2..6279557 100644 (file)
@@ -1,5 +1,44 @@
 2009-07-02  Ulrich Weigand  <uweigand@de.ibm.com>
 
+       * gdbtypes.h (struct builtin_type): Add internal_fn member.
+       * gdbtypes.c (gdbtypes_post_init): Initialize it.
+       * value.c (internal_fn_type): Remove.
+       (_initialize_values): Do not initialize it.
+
+       * value.c (struct internalvar): Add enum internalvar_kind type and
+       kind member.  Restructure union internalvar_data type.  Remove type,
+       canonical, and make_value members.
+       (init_if_undefined_command): Update for data structure changes.
+       (create_internalvar): Likewise.
+       (create_internalvar_type_lazy): Likewise.
+       (get_internalvar_integer): Likewise.
+       (get_internalvar_function): Likewise.
+       (set_internalvar_component): Likewise.
+       (set_internalvar): Likewise.
+       (set_internalvar_integer): Likewise.
+       (set_internalvar_function): Likewise.
+       (clear_internalvar): Likewise.
+       (add_internal_function): Likewise.
+       (preserve_one_internalvar): New function.
+       (preserve_values): Call it.
+
+       * value.h (value_of_internalvar): Add GDBARCH parameter.
+       (internalvar_make_value): Likewise.
+       * value.c (value_of_internalvar): Add GDBARCH parameter.  Pass it to
+       make_value callback.  Use it to generate per-architecture result value
+       types for internal variables with no pre-defined type.  Update for data
+       structure changes.
+       (show_convenience): Pass architecture to value_of_internalvar.
+       * eval.c (evaluate_subexp_standard): Likewise.
+       * infrun.c (siginfo_make_value): Add GDBARCH parameter.  Use it
+       instead of current frame architecture.  Return per-architecture type.
+
+       * value.h (set_internalvar_string): Add prototype.
+       * value.c (set_internalvar_string): New function.
+       * tracepoint.c (set_traceframe_context): Use it.
+
+2009-07-02  Ulrich Weigand  <uweigand@de.ibm.com>
+
        * jv-lang.h (java_int_type, java_byte_type, java_short_type,
        java_long_type, java_boolean_type, java_char_type, java_float_type,
        java_double_type, java_void_type): Remove.
index 67e94dd..4a35c93 100644 (file)
@@ -779,7 +779,8 @@ evaluate_subexp_standard (struct type *expect_type,
 
     case OP_INTERNALVAR:
       (*pos) += 2;
-      return value_of_internalvar (exp->elts[pc + 1].internalvar);
+      return value_of_internalvar (exp->gdbarch,
+                                  exp->elts[pc + 1].internalvar);
 
     case OP_STRING:
       tem = longest_to_int (exp->elts[pc + 1].longconst);
index 3d5ad3b..cd26db8 100644 (file)
@@ -3181,6 +3181,11 @@ gdbtypes_post_init (struct gdbarch *gdbarch)
   builtin_type->builtin_func_ptr =
     lookup_pointer_type (lookup_function_type (builtin_type->builtin_void));
 
+  /* This type represents a GDB internal function.  */
+  builtin_type->internal_fn =
+    init_type (TYPE_CODE_INTERNAL_FUNCTION, 0, 0,
+              "<internal function>", NULL);
+
   return builtin_type;
 }
 
index 97f018e..152443e 100644 (file)
@@ -999,6 +999,12 @@ struct builtin_type
      However, all function pointer types are interconvertible, so void
      (*) () can server as a generic function pointer.  */
   struct type *builtin_func_ptr;
+
+
+  /* Special-purpose types.  */
+
+  /* This type is used to represent a GDB internal function.  */
+  struct type *internal_fn;
 };
 
 /* Return the type table for the specified architecture.  */
index 45a8c87..ec17f6d 100644 (file)
@@ -5263,29 +5263,21 @@ static struct lval_funcs siginfo_value_funcs =
   };
 
 /* Return a new value with the correct type for the siginfo object of
-   the current thread.  Return a void value if there's no object
-   available.  */
+   the current thread using architecture GDBARCH.  Return a void value
+   if there's no object available.  */
 
 static struct value *
-siginfo_make_value (struct internalvar *var)
+siginfo_make_value (struct gdbarch *gdbarch, struct internalvar *var)
 {
-  struct type *type;
-  struct gdbarch *gdbarch;
-
   if (target_has_stack
-      && !ptid_equal (inferior_ptid, null_ptid))
+      && !ptid_equal (inferior_ptid, null_ptid)
+      && gdbarch_get_siginfo_type_p (gdbarch))
     {
-      gdbarch = get_frame_arch (get_current_frame ());
-
-      if (gdbarch_get_siginfo_type_p (gdbarch))
-       {
-         type = gdbarch_get_siginfo_type (gdbarch);
-
-         return allocate_computed_value (type, &siginfo_value_funcs, NULL);
-       }
+      struct type *type = gdbarch_get_siginfo_type (gdbarch);
+      return allocate_computed_value (type, &siginfo_value_funcs, NULL);
     }
 
-  return allocate_value (builtin_type_void);
+  return allocate_value (builtin_type (gdbarch)->builtin_void);
 }
 
 \f
index 7da4b16..dcd3df7 100644 (file)
@@ -228,12 +228,6 @@ set_traceframe_context (struct frame_info *trace_frame)
 {
   CORE_ADDR trace_pc;
 
-  static struct type *func_string, *file_string;
-  static struct type *func_range, *file_range;
-  struct value *func_val;
-  struct value *file_val;
-  int len;
-
   if (trace_frame == NULL)             /* Cease debugging any trace buffers.  */
     {
       traceframe_fun = 0;
@@ -261,20 +255,8 @@ set_traceframe_context (struct frame_info *trace_frame)
       || SYMBOL_LINKAGE_NAME (traceframe_fun) == NULL)
     clear_internalvar (lookup_internalvar ("trace_func"));
   else
-    {
-      len = strlen (SYMBOL_LINKAGE_NAME (traceframe_fun));
-      func_range = create_range_type (func_range,
-                                     builtin_type_int32, 0, len - 1);
-      func_string = create_array_type (func_string,
-                                      builtin_type_true_char, func_range);
-      func_val = allocate_value (func_string);
-      deprecated_set_value_type (func_val, func_string);
-      memcpy (value_contents_raw (func_val),
-             SYMBOL_LINKAGE_NAME (traceframe_fun),
-             len);
-      deprecated_set_value_modifiable (func_val, 0);
-      set_internalvar (lookup_internalvar ("trace_func"), func_val);
-    }
+    set_internalvar_string (lookup_internalvar ("trace_func"),
+                           SYMBOL_LINKAGE_NAME (traceframe_fun));
 
   /* Save file name as "$trace_file", a debugger variable visible to
      users.  */
@@ -282,20 +264,8 @@ set_traceframe_context (struct frame_info *trace_frame)
       || traceframe_sal.symtab->filename == NULL)
     clear_internalvar (lookup_internalvar ("trace_file"));
   else
-    {
-      len = strlen (traceframe_sal.symtab->filename);
-      file_range = create_range_type (file_range,
-                                     builtin_type_int32, 0, len - 1);
-      file_string = create_array_type (file_string,
-                                      builtin_type_true_char, file_range);
-      file_val = allocate_value (file_string);
-      deprecated_set_value_type (file_val, file_string);
-      memcpy (value_contents_raw (file_val),
-             traceframe_sal.symtab->filename,
-             len);
-      deprecated_set_value_modifiable (file_val, 0);
-      set_internalvar (lookup_internalvar ("trace_file"), file_val);
-    }
+    set_internalvar_string (lookup_internalvar ("trace_file"),
+                           traceframe_sal.symtab->filename);
 }
 
 /* ACTIONS functions: */
index 7566921..01066e9 100644 (file)
@@ -222,9 +222,6 @@ static struct value_history_chunk *value_history_chain;
 
 static int value_history_count;        /* Abs number of last entry stored */
 
-/* The type of internal functions.  */
-
-static struct type *internal_fn_type;
 \f
 /* List of all value objects currently allocated
    (except for those released by calls to release_value)
@@ -882,25 +879,67 @@ struct internalvar
 {
   struct internalvar *next;
   char *name;
-  struct type *type;
 
-  /* True if this internalvar is the canonical name for a convenience
-     function.  */
-  int canonical;
+  /* We support various different kinds of content of an internal variable.
+     enum internalvar_kind specifies the kind, and union internalvar_data
+     provides the data associated with this particular kind.  */
+
+  enum internalvar_kind
+    {
+      /* The internal variable is empty.  */
+      INTERNALVAR_VOID,
+
+      /* The value of the internal variable is provided directly as
+        a GDB value object.  */
+      INTERNALVAR_VALUE,
+
+      /* A fresh value is computed via a call-back routine on every
+        access to the internal variable.  */
+      INTERNALVAR_MAKE_VALUE,
 
-  /* If this function is non-NULL, it is used to compute a fresh value
-     on every access to the internalvar.  */
-  internalvar_make_value make_value;
+      /* The internal variable holds a GDB internal convenience function.  */
+      INTERNALVAR_FUNCTION,
+
+      /* The variable holds a simple scalar value.  */
+      INTERNALVAR_SCALAR,
+
+      /* The variable holds a GDB-provided string.  */
+      INTERNALVAR_STRING,
+
+    } kind;
 
-  /* To reduce dependencies on target properties (like byte order) that
-     may change during the lifetime of an internal variable, we store
-     simple scalar values as host objects.  */
   union internalvar_data
     {
-      struct value *v;
-      struct internal_function *f;
-      LONGEST l;
-      CORE_ADDR a;
+      /* A value object used with INTERNALVAR_VALUE.  */
+      struct value *value;
+
+      /* The call-back routine used with INTERNALVAR_MAKE_VALUE.  */
+      internalvar_make_value make_value;
+
+      /* The internal function used with INTERNALVAR_FUNCTION.  */
+      struct
+       {
+         struct internal_function *function;
+         /* True if this is the canonical name for the function.  */
+         int canonical;
+       } fn;
+
+      /* A scalar value used with INTERNALVAR_SCALAR.  */
+      struct
+        {
+         /* If type is non-NULL, it will be used as the type to generate
+            a value for this internal variable.  If type is NULL, a default
+            integer type for the architecture is used.  */
+         struct type *type;
+         union
+           {
+             LONGEST l;    /* Used with TYPE_CODE_INT and NULL types.  */
+             CORE_ADDR a;  /* Used with TYPE_CODE_PTR types.  */
+           } val;
+        } scalar;
+
+      /* A string value used with INTERNALVAR_STRING.  */
+      char *string;
     } u;
 };
 
@@ -932,7 +971,7 @@ init_if_undefined_command (char* args, int from_tty)
 
   /* Only evaluate the expression if the lvalue is void.
      This may still fail if the expresssion is invalid.  */
-  if (TYPE_CODE (intvar->type) == TYPE_CODE_VOID)
+  if (intvar->kind == INTERNALVAR_VOID)
     evaluate_expression (expr);
 
   do_cleanups (old_chain);
@@ -967,9 +1006,7 @@ create_internalvar (const char *name)
   struct internalvar *var;
   var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
   var->name = concat (name, (char *)NULL);
-  var->type = builtin_type_void;
-  var->make_value = NULL;
-  var->canonical = 0;
+  var->kind = INTERNALVAR_VOID;
   var->next = internalvars;
   internalvars = var;
   return var;
@@ -984,7 +1021,8 @@ struct internalvar *
 create_internalvar_type_lazy (char *name, internalvar_make_value fun)
 {
   struct internalvar *var = create_internalvar (name);
-  var->make_value = fun;
+  var->kind = INTERNALVAR_MAKE_VALUE;
+  var->u.make_value = fun;
   return var;
 }
 
@@ -1006,53 +1044,77 @@ lookup_internalvar (const char *name)
   return create_internalvar (name);
 }
 
+/* Return current value of internal variable VAR.  For variables that
+   are not inherently typed, use a value type appropriate for GDBARCH.  */
+
 struct value *
-value_of_internalvar (struct internalvar *var)
+value_of_internalvar (struct gdbarch *gdbarch, struct internalvar *var)
 {
   struct value *val;
 
-  if (var->make_value != NULL)
-    val = (*var->make_value) (var);
-  else
+  switch (var->kind)
     {
-      switch (TYPE_CODE (var->type))
-       {
-       case TYPE_CODE_VOID:
-       case TYPE_CODE_INTERNAL_FUNCTION:
-         val = allocate_value (var->type);
-         break;
+    case INTERNALVAR_VOID:
+      val = allocate_value (builtin_type (gdbarch)->builtin_void);
+      break;
 
-       case TYPE_CODE_INT:
-         val = value_from_longest (var->type, var->u.l);
-         break;
+    case INTERNALVAR_FUNCTION:
+      val = allocate_value (builtin_type (gdbarch)->internal_fn);
+      break;
 
-       case TYPE_CODE_PTR:
-         val = value_from_pointer (var->type, var->u.a);
-         break;
+    case INTERNALVAR_SCALAR:
+      if (!var->u.scalar.type)
+       val = value_from_longest (builtin_type (gdbarch)->builtin_int,
+                                 var->u.scalar.val.l);
+      else if (TYPE_CODE (var->u.scalar.type) == TYPE_CODE_INT)
+       val = value_from_longest (var->u.scalar.type, var->u.scalar.val.l);
+      else if (TYPE_CODE (var->u.scalar.type) == TYPE_CODE_PTR)
+       val = value_from_pointer (var->u.scalar.type, var->u.scalar.val.a);
+      else
+        internal_error (__FILE__, __LINE__, "bad type");
+      break;
 
-       default:
-         val = value_copy (var->u.v);
-         break;
-       }
+    case INTERNALVAR_STRING:
+      val = value_cstring (var->u.string, strlen (var->u.string),
+                          builtin_type (gdbarch)->builtin_char);
+      break;
 
+    case INTERNALVAR_VALUE:
+      val = value_copy (var->u.value);
       if (value_lazy (val))
        value_fetch_lazy (val);
+      break;
 
-      /* If the variable's value is a computed lvalue, we want
-        references to it to produce another computed lvalue, where
-        referencces and assignments actually operate through the
-        computed value's functions.
-
-        This means that internal variables with computed values
-        behave a little differently from other internal variables:
-        assignments to them don't just replace the previous value
-        altogether.  At the moment, this seems like the behavior we
-        want.  */
-      if (val->lval != lval_computed)
-       {
-         VALUE_LVAL (val) = lval_internalvar;
-         VALUE_INTERNALVAR (val) = var;
-       }
+    case INTERNALVAR_MAKE_VALUE:
+      val = (*var->u.make_value) (gdbarch, var);
+      break;
+
+    default:
+      internal_error (__FILE__, __LINE__, "bad kind");
+    }
+
+  /* Change the VALUE_LVAL to lval_internalvar so that future operations
+     on this value go back to affect the original internal variable.
+
+     Do not do this for INTERNALVAR_MAKE_VALUE variables, as those have
+     no underlying modifyable state in the internal variable.
+
+     Likewise, if the variable's value is a computed lvalue, we want
+     references to it to produce another computed lvalue, where
+     references and assignments actually operate through the
+     computed value's functions.
+
+     This means that internal variables with computed values
+     behave a little differently from other internal variables:
+     assignments to them don't just replace the previous value
+     altogether.  At the moment, this seems like the behavior we
+     want.  */
+
+  if (var->kind != INTERNALVAR_MAKE_VALUE
+      && val->lval != lval_computed)
+    {
+      VALUE_LVAL (val) = lval_internalvar;
+      VALUE_INTERNALVAR (val) = var;
     }
 
   return val;
@@ -1061,11 +1123,16 @@ value_of_internalvar (struct internalvar *var)
 int
 get_internalvar_integer (struct internalvar *var, LONGEST *result)
 {
-  switch (TYPE_CODE (var->type))
+  switch (var->kind)
     {
-    case TYPE_CODE_INT:
-      *result = var->u.l;
-      return 1;
+    case INTERNALVAR_SCALAR:
+      if (var->u.scalar.type == NULL
+         || TYPE_CODE (var->u.scalar.type) == TYPE_CODE_INT)
+       {
+         *result = var->u.scalar.val.l;
+         return 1;
+       }
+      /* Fall through.  */
 
     default:
       return 0;
@@ -1076,10 +1143,10 @@ static int
 get_internalvar_function (struct internalvar *var,
                          struct internal_function **result)
 {
-  switch (TYPE_CODE (var->type))
+  switch (var->kind)
     {
-    case TYPE_CODE_INTERNAL_FUNCTION:
-      *result = var->u.f;
+    case INTERNALVAR_FUNCTION:
+      *result = var->u.fn.function;
       return 1;
 
     default:
@@ -1093,17 +1160,10 @@ set_internalvar_component (struct internalvar *var, int offset, int bitpos,
 {
   gdb_byte *addr;
 
-  switch (TYPE_CODE (var->type))
+  switch (var->kind)
     {
-    case TYPE_CODE_VOID:
-    case TYPE_CODE_INTERNAL_FUNCTION:
-    case TYPE_CODE_INT:
-    case TYPE_CODE_PTR:
-      /* We can never get a component of a basic type.  */
-      internal_error (__FILE__, __LINE__, "set_internalvar_component");
-
-    default:
-      addr = value_contents_writeable (var->u.v);
+    case INTERNALVAR_VALUE:
+      addr = value_contents_writeable (var->u.value);
 
       if (bitsize)
        modify_field (addr + offset,
@@ -1112,52 +1172,65 @@ set_internalvar_component (struct internalvar *var, int offset, int bitpos,
        memcpy (addr + offset, value_contents (newval),
                TYPE_LENGTH (value_type (newval)));
       break;
+
+    default:
+      /* We can never get a component of any other kind.  */
+      internal_error (__FILE__, __LINE__, "set_internalvar_component");
     }
 }
 
 void
 set_internalvar (struct internalvar *var, struct value *val)
 {
-  struct type *new_type = check_typedef (value_type (val));
+  enum internalvar_kind new_kind;
   union internalvar_data new_data = { 0 };
 
-  if (var->canonical)
+  if (var->kind == INTERNALVAR_FUNCTION && var->u.fn.canonical)
     error (_("Cannot overwrite convenience function %s"), var->name);
 
   /* Prepare new contents.  */
-  switch (TYPE_CODE (new_type))
+  switch (TYPE_CODE (check_typedef (value_type (val))))
     {
     case TYPE_CODE_VOID:
+      new_kind = INTERNALVAR_VOID;
       break;
 
     case TYPE_CODE_INTERNAL_FUNCTION:
       gdb_assert (VALUE_LVAL (val) == lval_internalvar);
-      get_internalvar_function (VALUE_INTERNALVAR (val), &new_data.f);
+      new_kind = INTERNALVAR_FUNCTION;
+      get_internalvar_function (VALUE_INTERNALVAR (val),
+                               &new_data.fn.function);
+      /* Copies created here are never canonical.  */
       break;
 
     case TYPE_CODE_INT:
-      new_data.l = value_as_long (val);
+      new_kind = INTERNALVAR_SCALAR;
+      new_data.scalar.type = value_type (val);
+      new_data.scalar.val.l = value_as_long (val);
       break;
 
     case TYPE_CODE_PTR:
-      new_data.a = value_as_address (val);
+      new_kind = INTERNALVAR_SCALAR;
+      new_data.scalar.type = value_type (val);
+      new_data.scalar.val.a = value_as_address (val);
       break;
 
     default:
-      new_data.v = value_copy (val);
-      new_data.v->modifiable = 1;
+      new_kind = INTERNALVAR_VALUE;
+      new_data.value = value_copy (val);
+      new_data.value->modifiable = 1;
 
       /* 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 (new_data.v))
-       value_fetch_lazy (new_data.v);
+      if (value_lazy (new_data.value))
+       value_fetch_lazy (new_data.value);
 
       /* Release the value from the value chain to prevent it from being
         deleted by free_all_values.  From here on this function should not
         call error () until new_data is installed into the var->u to avoid
         leaking memory.  */
-      release_value (new_data.v);
+      release_value (new_data.value);
       break;
     }
 
@@ -1165,7 +1238,7 @@ set_internalvar (struct internalvar *var, struct value *val)
   clear_internalvar (var);
 
   /* Switch over.  */
-  var->type = new_type;
+  var->kind = new_kind;
   var->u = new_data;
   /* End code which must not call error().  */
 }
@@ -1176,9 +1249,19 @@ set_internalvar_integer (struct internalvar *var, LONGEST l)
   /* Clean up old contents.  */
   clear_internalvar (var);
 
-  /* Use a platform-independent 32-bit integer type.  */
-  var->type = builtin_type_int32;
-  var->u.l = l;
+  var->kind = INTERNALVAR_SCALAR;
+  var->u.scalar.type = NULL;
+  var->u.scalar.val.l = l;
+}
+
+void
+set_internalvar_string (struct internalvar *var, const char *string)
+{
+  /* Clean up old contents.  */
+  clear_internalvar (var);
+
+  var->kind = INTERNALVAR_STRING;
+  var->u.string = xstrdup (string);
 }
 
 static void
@@ -1187,29 +1270,32 @@ set_internalvar_function (struct internalvar *var, struct internal_function *f)
   /* Clean up old contents.  */
   clear_internalvar (var);
 
-  var->type = internal_fn_type;
-  var->u.f = f;
+  var->kind = INTERNALVAR_FUNCTION;
+  var->u.fn.function = f;
+  var->u.fn.canonical = 1;
+  /* Variables installed here are always the canonical version.  */
 }
 
 void
 clear_internalvar (struct internalvar *var)
 {
   /* Clean up old contents.  */
-  switch (TYPE_CODE (var->type))
+  switch (var->kind)
     {
-    case TYPE_CODE_VOID:
-    case TYPE_CODE_INTERNAL_FUNCTION:
-    case TYPE_CODE_INT:
-    case TYPE_CODE_PTR:
+    case INTERNALVAR_VALUE:
+      value_free (var->u.value);
+      break;
+
+    case INTERNALVAR_STRING:
+      xfree (var->u.string);
       break;
 
     default:
-      value_free (var->u.v);
       break;
     }
 
-  /* Set to void type.  */
-  var->type = builtin_type_void;
+  /* Reset to void kind.  */
+  var->kind = INTERNALVAR_VOID;
 }
 
 char *
@@ -1288,7 +1374,6 @@ add_internal_function (const char *name, const char *doc,
 
   ifn = create_internal_function (name, handler, cookie);
   set_internalvar_function (var, ifn);
-  var->canonical = 1;
 
   cmd = add_cmd (xstrdup (name), no_class, function_command, (char *) doc,
                 &functionlist);
@@ -1311,6 +1396,26 @@ preserve_one_value (struct value *value, struct objfile *objfile,
                                                 copied_types);
 }
 
+/* Likewise for internal variable VAR.  */
+
+static void
+preserve_one_internalvar (struct internalvar *var, struct objfile *objfile,
+                         htab_t copied_types)
+{
+  switch (var->kind)
+    {
+    case INTERNALVAR_SCALAR:
+      if (var->u.scalar.type && TYPE_OBJFILE (var->u.scalar.type) == objfile)
+       var->u.scalar.type
+         = copy_type_recursive (objfile, var->u.scalar.type, copied_types);
+      break;
+
+    case INTERNALVAR_VALUE:
+      preserve_one_value (var->u.value, objfile, copied_types);
+      break;
+    }
+}
+
 /* Update the internal variables and value history when OBJFILE is
    discarded; we must copy the types out of the objfile.  New global types
    will be created for every convenience variable which currently points to
@@ -1336,23 +1441,7 @@ preserve_values (struct objfile *objfile)
        preserve_one_value (cur->values[i], objfile, copied_types);
 
   for (var = internalvars; var; var = var->next)
-    {
-      if (TYPE_OBJFILE (var->type) == objfile)
-       var->type = copy_type_recursive (objfile, var->type, copied_types);
-
-      switch (TYPE_CODE (var->type))
-       {
-       case TYPE_CODE_VOID:
-       case TYPE_CODE_INTERNAL_FUNCTION:
-       case TYPE_CODE_INT:
-       case TYPE_CODE_PTR:
-         break;
-
-       default:
-         preserve_one_value (var->u.v, objfile, copied_types);
-         break;
-       }
-    }
+    preserve_one_internalvar (var, objfile, copied_types);
 
   for (val = values_in_python; val; val = val->next)
     preserve_one_value (val, objfile, copied_types);
@@ -1363,6 +1452,7 @@ preserve_values (struct objfile *objfile)
 static void
 show_convenience (char *ignore, int from_tty)
 {
+  struct gdbarch *gdbarch = current_gdbarch;
   struct internalvar *var;
   int varseen = 0;
   struct value_print_options opts;
@@ -1375,7 +1465,7 @@ show_convenience (char *ignore, int from_tty)
          varseen = 1;
        }
       printf_filtered (("$%s = "), var->name);
-      value_print (value_of_internalvar (var), gdb_stdout,
+      value_print (value_of_internalvar (gdbarch, var), gdb_stdout,
                   &opts);
       printf_filtered (("\n"));
     }
@@ -2172,8 +2262,4 @@ VARIABLE is already initialized."));
   add_prefix_cmd ("function", no_class, function_command, _("\
 Placeholder command for showing help on convenience functions."),
                  &functionlist, "function ", 0, &cmdlist);
-
-  internal_fn_type = alloc_type (NULL);
-  TYPE_CODE (internal_fn_type) = TYPE_CODE_INTERNAL_FUNCTION;
-  TYPE_NAME (internal_fn_type) = "<internal function>";
 }
index e3a16c5..e3574c1 100644 (file)
@@ -522,7 +522,8 @@ extern void binop_promote (const struct language_defn *language,
 
 extern struct value *access_value_history (int num);
 
-extern struct value *value_of_internalvar (struct internalvar *var);
+extern struct value *value_of_internalvar (struct gdbarch *gdbarch,
+                                          struct internalvar *var);
 
 extern int get_internalvar_integer (struct internalvar *var, LONGEST *l);
 
@@ -530,6 +531,9 @@ extern void set_internalvar (struct internalvar *var, struct value *val);
 
 extern void set_internalvar_integer (struct internalvar *var, LONGEST l);
 
+extern void set_internalvar_string (struct internalvar *var,
+                                   const char *string);
+
 extern void clear_internalvar (struct internalvar *var);
 
 extern void set_internalvar_component (struct internalvar *var,
@@ -541,8 +545,8 @@ extern struct internalvar *lookup_only_internalvar (const char *name);
 
 extern struct internalvar *create_internalvar (const char *name);
 
-typedef struct value * (*internalvar_make_value) (struct internalvar *);
-
+typedef struct value * (*internalvar_make_value) (struct gdbarch *,
+                                                 struct internalvar *);
 extern struct internalvar *
   create_internalvar_type_lazy (char *name, internalvar_make_value fun);