* value.h (struct internalvar): Remove.
authorUlrich Weigand <uweigand@de.ibm.com>
Wed, 3 Jun 2009 18:16:44 +0000 (18:16 +0000)
committerUlrich Weigand <uweigand@de.ibm.com>
Wed, 3 Jun 2009 18:16:44 +0000 (18:16 +0000)
(get_internalvar_integer): Add prototype.
(set_internalvar_integer): Add prototype.
(clear_internalvar): Add prototype.

* value.c (struct internalvar): Move here.  Add type member.  Remove
endian member.  Add union_internalvar member instead of value member.
(init_if_undefined_command): Use intvar->type.
(create_internalvar): Do not initialize value/endian, but type.
(create_internalvar_type_lazy): Call create_internalvar.
(value_of_internalvar): Handle host-side internalvar contents.
(set_internalvar_component): Likewise.
(set_internalvar): Likewise.
(get_internalvar_integer): New function.
(clear_internalvar): Likewise.
(set_internalvar_integer): Likewise.
(preserve_values): Handle host-side internalvar contents.

* breakpoint.c (set_breakpoint_count, set_tracepoint_count): Call
set_internalvar_integer instead of set_internalvar.
* findcmd.c (find_command): Likewise.
* infrun.c (handle_inferior_event): Likewise.
* source.c (forward_search_command, reverse_search_command): Likewise.
* tracepoint.c (set_traceframe_num, set_tracepoint_num,
set_traceframe_context): Likewise.

* printcmd.c (x_command): Call clear_internalvar instead of
set_internalvar.
* tracepoint.c (set_traceframe_context): Likewise.

* breakpoint.c (get_number_trailer): Call get_internalvar_integer
instead of value_of_internalvar.
* linespec.c (decode_dollar): Likewise.

* expprint.c (dump_subexp_body_standard): Use internalvar_name
instead of accessing internalvar private elements.
* valops.c (value_assign): Copy from original source instead of
accessing internalvar private elements.

12 files changed:
gdb/ChangeLog
gdb/breakpoint.c
gdb/expprint.c
gdb/findcmd.c
gdb/infrun.c
gdb/linespec.c
gdb/printcmd.c
gdb/source.c
gdb/tracepoint.c
gdb/valops.c
gdb/value.c
gdb/value.h

index 378619513d00eea88503eefac6bdd449a22ca748..11bf9cac27c24ca4ed1a4e9138b3754ff2a9505f 100644 (file)
@@ -1,3 +1,44 @@
+2009-06-03  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * value.h (struct internalvar): Remove.
+       (get_internalvar_integer): Add prototype.
+       (set_internalvar_integer): Add prototype.
+       (clear_internalvar): Add prototype.
+
+       * value.c (struct internalvar): Move here.  Add type member.  Remove
+       endian member.  Add union_internalvar member instead of value member.
+       (init_if_undefined_command): Use intvar->type.
+       (create_internalvar): Do not initialize value/endian, but type.
+       (create_internalvar_type_lazy): Call create_internalvar.
+       (value_of_internalvar): Handle host-side internalvar contents.
+       (set_internalvar_component): Likewise.
+       (set_internalvar): Likewise.
+       (get_internalvar_integer): New function.
+       (clear_internalvar): Likewise.
+       (set_internalvar_integer): Likewise.
+       (preserve_values): Handle host-side internalvar contents.
+
+       * breakpoint.c (set_breakpoint_count, set_tracepoint_count): Call
+       set_internalvar_integer instead of set_internalvar.
+       * findcmd.c (find_command): Likewise.
+       * infrun.c (handle_inferior_event): Likewise.
+       * source.c (forward_search_command, reverse_search_command): Likewise.
+       * tracepoint.c (set_traceframe_num, set_tracepoint_num,
+       set_traceframe_context): Likewise.
+
+       * printcmd.c (x_command): Call clear_internalvar instead of
+       set_internalvar.
+       * tracepoint.c (set_traceframe_context): Likewise.
+       
+       * breakpoint.c (get_number_trailer): Call get_internalvar_integer
+       instead of value_of_internalvar.
+       * linespec.c (decode_dollar): Likewise.
+
+       * expprint.c (dump_subexp_body_standard): Use internalvar_name
+       instead of accessing internalvar private elements.
+       * valops.c (value_assign): Copy from original source instead of
+       accessing internalvar private elements.
+
 2009-06-03  Ulrich Weigand  <uweigand@de.ibm.com>
 
        * scm-lang.c (builtin_type_scm): Remove.
index 8b2d55e35b53624b15e4cff4b43737b12588d251..bccfc787b667c63355583ef996dcb4c333a8cdef 100644 (file)
@@ -368,8 +368,7 @@ void
 set_breakpoint_count (int num)
 {
   breakpoint_count = num;
-  set_internalvar (lookup_internalvar ("bpnum"),
-                  value_from_longest (builtin_type_int32, (LONGEST) num));
+  set_internalvar_integer (lookup_internalvar ("bpnum"), num);
 }
 
 /* Used in run_command to zero the hit count when a new run starts. */
@@ -421,16 +420,15 @@ get_number_trailer (char **pp, int trailer)
          to pass to lookup_internalvar().  */
       char *varname;
       char *start = ++p;
-      struct value *val;
+      LONGEST val;
 
       while (isalnum (*p) || *p == '_')
        p++;
       varname = (char *) alloca (p - start + 1);
       strncpy (varname, start, p - start);
       varname[p - start] = '\0';
-      val = value_of_internalvar (lookup_internalvar (varname));
-      if (TYPE_CODE (value_type (val)) == TYPE_CODE_INT)
-       retval = (int) value_as_long (val);
+      if (get_internalvar_integer (lookup_internalvar (varname), &val))
+       retval = (int) val;
       else
        {
          printf_filtered (_("Convenience variable must have integer value.\n"));
@@ -8275,8 +8273,7 @@ static void
 set_tracepoint_count (int num)
 {
   tracepoint_count = num;
-  set_internalvar (lookup_internalvar ("tpnum"),
-                  value_from_longest (builtin_type_int32, (LONGEST) num));
+  set_internalvar_integer (lookup_internalvar ("tpnum"), num);
 }
 
 void
index 6048a387e6d81873cbaad6e916ffdc795ed053f8..e83d1011ab5b9de7cf4396f1407950435449233c 100644 (file)
@@ -1002,7 +1002,7 @@ dump_subexp_body_standard (struct expression *exp,
       fprintf_filtered (stream, "Internal var @");
       gdb_print_host_address (exp->elts[elt].internalvar, stream);
       fprintf_filtered (stream, " (%s)",
-                       exp->elts[elt].internalvar->name);
+                       internalvar_name (exp->elts[elt].internalvar));
       elt += 2;
       break;
     case OP_FUNCALL:
index 7ae43e5dc5b86f39ff3428fff55cf89007e25d6e..09d93fced1035809b73a9a013206e2a895fc7d3c 100644 (file)
@@ -291,9 +291,7 @@ find_command (char *args, int from_tty)
 
   /* Record and print the results.  */
 
-  set_internalvar (lookup_internalvar ("numfound"),
-                  value_from_longest (builtin_type_int32,
-                                      (LONGEST) found_count));
+  set_internalvar_integer (lookup_internalvar ("numfound"), found_count);
   if (found_count > 0)
     {
       struct gdbarch *gdbarch = current_gdbarch;
index 9b302bf0b568fcb3f8eb55ebbf2e3847eeeab2c6..3540acf9d7796c6a06df4a96d73ca075095bb16e 100644 (file)
@@ -2512,9 +2512,8 @@ handle_inferior_event (struct execution_control_state *ecs)
 
       /* Record the exit code in the convenience variable $_exitcode, so
          that the user can inspect this again later.  */
-      set_internalvar (lookup_internalvar ("_exitcode"),
-                      value_from_longest (builtin_type_int32,
-                                          (LONGEST) ecs->ws.value.integer));
+      set_internalvar_integer (lookup_internalvar ("_exitcode"),
+                              (LONGEST) ecs->ws.value.integer);
       gdb_flush (gdb_stdout);
       target_mourn_inferior ();
       singlestep_breakpoints_inserted_p = 0;
index e2018e6a22e58b1df7b28e6215e343b5a2cc8dec..3d0ceed84c89e10be552d14460a7e497c8119e52 100644 (file)
@@ -1669,7 +1669,7 @@ static struct symtabs_and_lines
 decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
               char ***canonical, struct symtab *file_symtab)
 {
-  struct value *valx;
+  LONGEST valx;
   int index = 0;
   int need_canonical = 0;
   struct symtabs_and_lines values;
@@ -1684,10 +1684,12 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
   if (!*p)             /* Reached end of token without hitting non-digit.  */
     {
       /* We have a value history reference.  */
+      struct value *val_history;
       sscanf ((copy[1] == '$') ? copy + 2 : copy + 1, "%d", &index);
-      valx = access_value_history ((copy[1] == '$') ? -index : index);
-      if (TYPE_CODE (value_type (valx)) != TYPE_CODE_INT)
+      val_history = access_value_history ((copy[1] == '$') ? -index : index);
+      if (TYPE_CODE (value_type (val_history)) != TYPE_CODE_INT)
        error (_("History values used in line specs must have integer values."));
+      valx = value_as_long (val_history);
     }
   else
     {
@@ -1709,8 +1711,7 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
        return minsym_found (funfirstline, msymbol);
 
       /* Not a user variable or function -- must be convenience variable.  */
-      valx = value_of_internalvar (lookup_internalvar (copy + 1));
-      if (TYPE_CODE (value_type (valx)) != TYPE_CODE_INT)
+      if (!get_internalvar_integer (lookup_internalvar (copy + 1), &valx))
        error (_("Convenience variables used in line specs must have integer values."));
     }
 
@@ -1718,7 +1719,7 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
 
   /* Either history value or convenience value from above, in valx.  */
   val.symtab = file_symtab ? file_symtab : default_symtab;
-  val.line = value_as_long (valx);
+  val.line = valx;
   val.pc = 0;
 
   values.sals = (struct symtab_and_line *) xmalloc (sizeof val);
index 4cb681f4fe09199a9cd3f72d4141af0c0926db20..b0d7a171ad804519ac1df7771e7fda9395b30628 100644 (file)
@@ -1369,8 +1369,7 @@ x_command (char *exp, int from_tty)
         then don't fetch it now; instead mark it by voiding the $__
         variable.  */
       if (value_lazy (last_examine_value))
-       set_internalvar (lookup_internalvar ("__"),
-                        allocate_value (builtin_type_void));
+       clear_internalvar (lookup_internalvar ("__"));
       else
        set_internalvar (lookup_internalvar ("__"), last_examine_value);
     }
index e1bbb7f529bbacc26d6a4f8985d4962690b407a0..e4766167b6dd8afc702286a6c8d555b87991d601 100644 (file)
@@ -1615,9 +1615,7 @@ forward_search_command (char *regex, int from_tty)
          /* Match! */
          fclose (stream);
          print_source_lines (current_source_symtab, line, line + 1, 0);
-         set_internalvar (lookup_internalvar ("_"),
-                          value_from_longest (builtin_type_int32,
-                                              (LONGEST) line));
+         set_internalvar_integer (lookup_internalvar ("_"), line);
          current_source_line = max (line - lines_to_list / 2, 1);
          return;
        }
@@ -1695,9 +1693,7 @@ reverse_search_command (char *regex, int from_tty)
          /* Match! */
          fclose (stream);
          print_source_lines (current_source_symtab, line, line + 1, 0);
-         set_internalvar (lookup_internalvar ("_"),
-                          value_from_longest (builtin_type_int32,
-                                              (LONGEST) line));
+         set_internalvar_integer (lookup_internalvar ("_"), line);
          current_source_line = max (line - lines_to_list / 2, 1);
          return;
        }
index 31c5f4ae159c923f7c6c4d55eb6142e202e7aec9..fb686e145e1939c9bd493087fd06b89cc254b2d8 100644 (file)
@@ -208,8 +208,7 @@ static void
 set_traceframe_num (int num)
 {
   traceframe_number = num;
-  set_internalvar (lookup_internalvar ("trace_frame"),
-                  value_from_longest (builtin_type_int32, (LONGEST) num));
+  set_internalvar_integer (lookup_internalvar ("trace_frame"), num);
 }
 
 /* Set tracepoint number to NUM.  */
@@ -217,8 +216,7 @@ static void
 set_tracepoint_num (int num)
 {
   tracepoint_number = num;
-  set_internalvar (lookup_internalvar ("tracepoint"),
-                  value_from_longest (builtin_type_int32, (LONGEST) num));
+  set_internalvar_integer (lookup_internalvar ("tracepoint"), num);
 }
 
 /* Set externally visible debug variables for querying/printing
@@ -240,13 +238,9 @@ set_traceframe_context (struct frame_info *trace_frame)
       traceframe_fun = 0;
       traceframe_sal.pc = traceframe_sal.line = 0;
       traceframe_sal.symtab = NULL;
-      set_internalvar (lookup_internalvar ("trace_func"),
-                      allocate_value (builtin_type_void));
-      set_internalvar (lookup_internalvar ("trace_file"),
-                      allocate_value (builtin_type_void));
-      set_internalvar (lookup_internalvar ("trace_line"),
-                      value_from_longest (builtin_type_int32,
-                                          (LONGEST) - 1));
+      clear_internalvar (lookup_internalvar ("trace_func"));
+      clear_internalvar (lookup_internalvar ("trace_file"));
+      set_internalvar_integer (lookup_internalvar ("trace_line"), -1);
       return;
     }
 
@@ -257,16 +251,14 @@ set_traceframe_context (struct frame_info *trace_frame)
 
   /* Save linenumber as "$trace_line", a debugger variable visible to
      users.  */
-  set_internalvar (lookup_internalvar ("trace_line"),
-                  value_from_longest (builtin_type_int32,
-                                      (LONGEST) traceframe_sal.line));
+  set_internalvar_integer (lookup_internalvar ("trace_line"),
+                          traceframe_sal.line);
 
   /* Save func name as "$trace_func", a debugger variable visible to
      users.  */
-  if (traceframe_fun == NULL ||
-      SYMBOL_LINKAGE_NAME (traceframe_fun) == NULL)
-    set_internalvar (lookup_internalvar ("trace_func"),
-                    allocate_value (builtin_type_void));
+  if (traceframe_fun == NULL
+      || SYMBOL_LINKAGE_NAME (traceframe_fun) == NULL)
+    clear_internalvar (lookup_internalvar ("trace_func"));
   else
     {
       len = strlen (SYMBOL_LINKAGE_NAME (traceframe_fun));
@@ -285,10 +277,9 @@ set_traceframe_context (struct frame_info *trace_frame)
 
   /* Save file name as "$trace_file", a debugger variable visible to
      users.  */
-  if (traceframe_sal.symtab == NULL ||
-      traceframe_sal.symtab->filename == NULL)
-    set_internalvar (lookup_internalvar ("trace_file"),
-                    allocate_value (builtin_type_void));
+  if (traceframe_sal.symtab == NULL
+      || traceframe_sal.symtab->filename == NULL)
+    clear_internalvar (lookup_internalvar ("trace_file"));
   else
     {
       len = strlen (traceframe_sal.symtab->filename);
index f06d32c3696b79c66833a57160e25fa2674b38ac..5907d96116ca2bb2a6a85d6b0370190aa705a1e7 100644 (file)
@@ -774,7 +774,7 @@ value_assign (struct value *toval, struct value *fromval)
     {
     case lval_internalvar:
       set_internalvar (VALUE_INTERNALVAR (toval), fromval);
-      val = value_copy (VALUE_INTERNALVAR (toval)->value);
+      val = value_copy (fromval);
       val = value_change_enclosing_type (val, 
                                         value_enclosing_type (fromval));
       set_value_embedded_offset (val, value_embedded_offset (fromval));
index 215ead54bdecda4c4b2db91f10b27abe61151fcf..e9dfe6ab8646f6bb7619db72b75547049527f565 100644 (file)
@@ -878,6 +878,32 @@ show_values (char *num_exp, int from_tty)
    The user refers to them with a '$' prefix
    that does not appear in the variable names stored internally.  */
 
+struct internalvar
+{
+  struct internalvar *next;
+  char *name;
+  struct type *type;
+
+  /* True if this internalvar is the canonical name for a convenience
+     function.  */
+  int canonical;
+
+  /* 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;
+
+  /* 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;
+    } u;
+};
+
 static struct internalvar *internalvars;
 
 /* If the variable does not already exist create it and give it the value given.
@@ -906,7 +932,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 (value_type (intvar->value)) == TYPE_CODE_VOID)
+  if (TYPE_CODE (intvar->type) == TYPE_CODE_VOID)
     evaluate_expression (expr);
 
   do_cleanups (old_chain);
@@ -941,11 +967,9 @@ create_internalvar (const char *name)
   struct internalvar *var;
   var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
   var->name = concat (name, (char *)NULL);
-  var->value = allocate_value (builtin_type_void);
-  var->endian = gdbarch_byte_order (current_gdbarch);
+  var->type = builtin_type_void;
   var->make_value = NULL;
   var->canonical = 0;
-  release_value (var->value);
   var->next = internalvars;
   internalvars = var;
   return var;
@@ -959,14 +983,8 @@ create_internalvar (const char *name)
 struct internalvar *
 create_internalvar_type_lazy (char *name, internalvar_make_value fun)
 {
-  struct internalvar *var;
-  var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
-  var->name = concat (name, (char *)NULL);
-  var->value = NULL;
+  struct internalvar *var = create_internalvar (name);
   var->make_value = fun;
-  var->endian = gdbarch_byte_order (current_gdbarch);
-  var->next = internalvars;
-  internalvars = var;
   return var;
 }
 
@@ -992,14 +1010,31 @@ struct value *
 value_of_internalvar (struct internalvar *var)
 {
   struct value *val;
-  int i, j;
-  gdb_byte temp;
 
   if (var->make_value != NULL)
     val = (*var->make_value) (var);
   else
     {
-      val = value_copy (var->value);
+      switch (TYPE_CODE (var->type))
+       {
+       case TYPE_CODE_VOID:
+       case TYPE_CODE_INTERNAL_FUNCTION:
+         val = allocate_value (var->type);
+         break;
+
+       case TYPE_CODE_INT:
+         val = value_from_longest (var->type, var->u.l);
+         break;
+
+       case TYPE_CODE_PTR:
+         val = value_from_pointer (var->type, var->u.a);
+         break;
+
+       default:
+         val = value_copy (var->u.v);
+         break;
+       }
+
       if (value_lazy (val))
        value_fetch_lazy (val);
 
@@ -1013,127 +1048,210 @@ value_of_internalvar (struct internalvar *var)
         assignments to them don't just replace the previous value
         altogether.  At the moment, this seems like the behavior we
         want.  */
-      if (var->value->lval == lval_computed)
-       VALUE_LVAL (val) = lval_computed;
-      else
+      if (val->lval != lval_computed)
        {
          VALUE_LVAL (val) = lval_internalvar;
          VALUE_INTERNALVAR (val) = var;
        }
     }
 
-  /* Values are always stored in the target's byte order.  When connected to a
-     target this will most likely always be correct, so there's normally no
-     need to worry about it.
+  return val;
+}
 
-     However, internal variables can be set up before the target endian is
-     known and so may become out of date.  Fix it up before anybody sees.
+int
+get_internalvar_integer (struct internalvar *var, LONGEST *result)
+{
+  switch (TYPE_CODE (var->type))
+    {
+    case TYPE_CODE_INT:
+      *result = var->u.l;
+      return 1;
 
-     Internal variables usually hold simple scalar values, and we can
-     correct those.  More complex values (e.g. structures and floating
-     point types) are left alone, because they would be too complicated
-     to correct.  */
+    default:
+      return 0;
+    }
+}
 
-  if (var->endian != gdbarch_byte_order (current_gdbarch))
+static int
+get_internalvar_function (struct internalvar *var,
+                         struct internal_function **result)
+{
+  switch (TYPE_CODE (var->type))
     {
-      gdb_byte *array = value_contents_raw (val);
-      struct type *type = check_typedef (value_enclosing_type (val));
-      switch (TYPE_CODE (type))
-       {
-       case TYPE_CODE_INT:
-       case TYPE_CODE_PTR:
-         /* Reverse the bytes.  */
-         for (i = 0, j = TYPE_LENGTH (type) - 1; i < j; i++, j--)
-           {
-             temp = array[j];
-             array[j] = array[i];
-             array[i] = temp;
-           }
-         break;
-       }
-    }
+    case TYPE_CODE_INTERNAL_FUNCTION:
+      *result = var->u.f;
+      return 1;
 
-  return val;
+    default:
+      return 0;
+    }
 }
 
 void
 set_internalvar_component (struct internalvar *var, int offset, int bitpos,
                           int bitsize, struct value *newval)
 {
-  gdb_byte *addr = value_contents_writeable (var->value) + offset;
+  gdb_byte *addr;
 
-  if (bitsize)
-    modify_field (addr, value_as_long (newval),
-                 bitpos, bitsize);
-  else
-    memcpy (addr, value_contents (newval), TYPE_LENGTH (value_type (newval)));
+  switch (TYPE_CODE (var->type))
+    {
+    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);
+
+      if (bitsize)
+       modify_field (addr + offset,
+                     value_as_long (newval), bitpos, bitsize);
+      else
+       memcpy (addr + offset, value_contents (newval),
+               TYPE_LENGTH (value_type (newval)));
+      break;
+    }
 }
 
 void
 set_internalvar (struct internalvar *var, struct value *val)
 {
-  struct value *newval;
+  struct type *new_type = check_typedef (value_type (val));
+  union internalvar_data new_data = { 0 };
 
   if (var->canonical)
     error (_("Cannot overwrite convenience function %s"), var->name);
 
-  newval = value_copy (val);
-  newval->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 (newval))
-    value_fetch_lazy (newval);
-
-  /* Begin code which must not call error().  If var->value points to
-     something free'd, an error() obviously leaves a dangling pointer.
-     But we also get a dangling pointer if var->value points to
-     something in the value chain (i.e., before release_value is
-     called), because after the error free_all_values will get called before
-     long.  */
-  value_free (var->value);
-  var->value = newval;
-  var->endian = gdbarch_byte_order (current_gdbarch);
-  release_value (newval);
+  /* Prepare new contents.  */
+  switch (TYPE_CODE (new_type))
+    {
+    case TYPE_CODE_VOID:
+      break;
+
+    case TYPE_CODE_INTERNAL_FUNCTION:
+      gdb_assert (VALUE_LVAL (val) == lval_internalvar);
+      get_internalvar_function (VALUE_INTERNALVAR (val), &new_data.f);
+      break;
+
+    case TYPE_CODE_INT:
+      new_data.l = value_as_long (val);
+      break;
+
+    case TYPE_CODE_PTR:
+      new_data.a = value_as_address (val);
+      break;
+
+    default:
+      new_data.v = value_copy (val);
+      new_data.v->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);
+
+      /* 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);
+      break;
+    }
+
+  /* Clean up old contents.  */
+  clear_internalvar (var);
+
+  /* Switch over.  */
+  var->type = new_type;
+  var->u = new_data;
   /* End code which must not call error().  */
 }
 
+void
+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;
+}
+
+static void
+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;
+}
+
+void
+clear_internalvar (struct internalvar *var)
+{
+  /* Clean up old contents.  */
+  switch (TYPE_CODE (var->type))
+    {
+    case TYPE_CODE_VOID:
+    case TYPE_CODE_INTERNAL_FUNCTION:
+    case TYPE_CODE_INT:
+    case TYPE_CODE_PTR:
+      break;
+
+    default:
+      value_free (var->u.v);
+      break;
+    }
+
+  /* Set to void type.  */
+  var->type = builtin_type_void;
+}
+
 char *
 internalvar_name (struct internalvar *var)
 {
   return var->name;
 }
 
-static struct value *
-value_create_internal_function (const char *name,
-                               internal_function_fn handler,
-                               void *cookie)
+static struct internal_function *
+create_internal_function (const char *name,
+                         internal_function_fn handler, void *cookie)
 {
-  struct value *result = allocate_value (internal_fn_type);
-  gdb_byte *addr = value_contents_writeable (result);
-  struct internal_function **fnp = (struct internal_function **) addr;
   struct internal_function *ifn = XNEW (struct internal_function);
   ifn->name = xstrdup (name);
   ifn->handler = handler;
   ifn->cookie = cookie;
-  *fnp = ifn;
-  return result;
+  return ifn;
 }
 
 char *
 value_internal_function_name (struct value *val)
 {
-  gdb_byte *addr = value_contents_writeable (val);
-  struct internal_function *ifn = * (struct internal_function **) addr;
+  struct internal_function *ifn;
+  int result;
+
+  gdb_assert (VALUE_LVAL (val) == lval_internalvar);
+  result = get_internalvar_function (VALUE_INTERNALVAR (val), &ifn);
+  gdb_assert (result);
+
   return ifn->name;
 }
 
 struct value *
 call_internal_function (struct value *func, int argc, struct value **argv)
 {
-  gdb_byte *addr = value_contents_writeable (func);
-  struct internal_function *ifn = * (struct internal_function **) addr;
+  struct internal_function *ifn;
+  int result;
+
+  gdb_assert (VALUE_LVAL (func) == lval_internalvar);
+  result = get_internalvar_function (VALUE_INTERNALVAR (func), &ifn);
+  gdb_assert (result);
+
   return (*ifn->handler) (ifn->cookie, argc, argv);
 }
 
@@ -1165,9 +1283,11 @@ add_internal_function (const char *name, const char *doc,
                       internal_function_fn handler, void *cookie)
 {
   struct cmd_list_element *cmd;
+  struct internal_function *ifn;
   struct internalvar *var = lookup_internalvar (name);
-  struct value *fnval = value_create_internal_function (name, handler, cookie);
-  set_internalvar (var, fnval);
+
+  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,
@@ -1216,8 +1336,23 @@ preserve_values (struct objfile *objfile)
        preserve_one_value (cur->values[i], objfile, copied_types);
 
   for (var = internalvars; var; var = var->next)
-    if (var->value)
-      preserve_one_value (var->value, objfile, copied_types);
+    {
+      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;
+       }
+    }
 
   for (val = values_in_python; val; val = val->next)
     preserve_one_value (val, objfile, copied_types);
@@ -2067,6 +2202,5 @@ Placeholder command for showing help on convenience functions."),
 
   internal_fn_type = alloc_type (NULL);
   TYPE_CODE (internal_fn_type) = TYPE_CODE_INTERNAL_FUNCTION;
-  TYPE_LENGTH (internal_fn_type) = sizeof (struct internal_function *);
   TYPE_NAME (internal_fn_type) = "<internal function>";
 }
index 456c9c86cdff58e56ef6f8b567a63fd32cf50f38..fcff0ad4aa1f4e6b138d40a98d857c22e03d6e35 100644 (file)
@@ -309,23 +309,6 @@ extern struct value *coerce_ref (struct value *value);
 
 extern struct value *coerce_array (struct value *value);
 
-/* Internal variables (variables for convenience of use of debugger)
-   are recorded as a chain of these structures.  */
-
-typedef struct value * (*internalvar_make_value) (struct internalvar *);
-
-struct internalvar
-{
-  struct internalvar *next;
-  char *name;
-  struct value *value;
-  internalvar_make_value make_value;
-  int endian;
-  /* True if this internalvar is the canonical name for a convenience
-     function.  */
-  int canonical;
-};
-
 \f
 
 #include "symtab.h"
@@ -538,8 +521,14 @@ extern struct value *access_value_history (int num);
 
 extern struct value *value_of_internalvar (struct internalvar *var);
 
+extern int get_internalvar_integer (struct internalvar *var, LONGEST *l);
+
 extern void set_internalvar (struct internalvar *var, struct value *val);
 
+extern void set_internalvar_integer (struct internalvar *var, LONGEST l);
+
+extern void clear_internalvar (struct internalvar *var);
+
 extern void set_internalvar_component (struct internalvar *var,
                                       int offset,
                                       int bitpos, int bitsize,
@@ -549,6 +538,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 *);
+
 extern struct internalvar *
   create_internalvar_type_lazy (char *name, internalvar_make_value fun);