(struct varobj): New member print_value.
[deliverable/binutils-gdb.git] / gdb / varobj.c
index e3c193e1ae6e50c846d5940c263700ad7ef1dde8..056cf58f65091c10d2805c1b55053f560668a93d 100644 (file)
@@ -1,5 +1,7 @@
 /* Implementation of the GDB variable objects API.
-   Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
+
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
 
    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
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
+#include "exceptions.h"
 #include "value.h"
 #include "expression.h"
 #include "frame.h"
 #include "language.h"
 #include "wrapper.h"
 #include "gdbcmd.h"
-#include <math.h>
+#include "block.h"
+
+#include "gdb_assert.h"
+#include "gdb_string.h"
 
 #include "varobj.h"
+#include "vec.h"
 
 /* Non-zero if we want to see trace of varobj level stuff.  */
 
 int varobjdebug = 0;
+static void
+show_varobjdebug (struct ui_file *file, int from_tty,
+                 struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Varobj debugging is %s.\n"), value);
+}
 
 /* String representations of gdb's format codes */
 char *varobj_format_string[] =
@@ -52,7 +65,7 @@ struct varobj_root
   struct block *valid_block;
 
   /* The frame for this expression */
-  CORE_ADDR frame;
+  struct frame_id frame;
 
   /* If 1, "update" always recomputes the frame & valid block
      using the currently selected frame. */
@@ -68,6 +81,10 @@ struct varobj_root
   struct varobj_root *next;
 };
 
+typedef struct varobj *varobj_p;
+
+DEF_VEC_P (varobj_p);
+
 /* Every variable in the system has a structure of this type defined
    for it. This structure holds all information necessary to manipulate
    a particular object variable. Members which must be freed are noted. */
@@ -90,7 +107,9 @@ struct varobj
   /* The type of this variable. This may NEVER be NULL. */
   struct type *type;
 
-  /* The value of this expression or subexpression.  This may be NULL. */
+  /* The value of this expression or subexpression.  This may be NULL. 
+     Invariant: if varobj_value_is_changeable_p (this) is non-zero, 
+     the value is either NULL, or not lazy.  */
   struct value *value;
 
   /* Did an error occur evaluating the expression or getting its value? */
@@ -102,37 +121,20 @@ struct varobj
   /* If this object is a child, this points to its immediate parent. */
   struct varobj *parent;
 
-  /* A list of this object's children */
-  struct varobj_child *children;
+  /* Children of this object.  */
+  VEC (varobj_p) *children;
 
   /* Description of the root variable. Points to root variable for children. */
   struct varobj_root *root;
 
   /* The format of the output for this object */
   enum varobj_display_formats format;
-};
-
-/* Every variable keeps a linked list of its children, described
-   by the following structure. */
-/* FIXME: Deprecated.  All should use vlist instead */
-
-struct varobj_child
-{
-
-  /* Pointer to the child's data */
-  struct varobj *child;
-
-  /* Pointer to the next child */
-  struct varobj_child *next;
-};
 
-/* A stack of varobjs */
-/* FIXME: Deprecated.  All should use vlist instead */
+  /* Was this variable updated via a varobj_set_value operation */
+  int updated;
 
-struct vstack
-{
-  struct varobj *var;
-  struct vstack *next;
+  /* Last print value.  */
+  char *print_value;
 };
 
 struct cpstack
@@ -162,14 +164,8 @@ static int install_variable (struct varobj *);
 
 static void uninstall_variable (struct varobj *);
 
-static struct varobj *child_exists (struct varobj *, char *);
-
 static struct varobj *create_child (struct varobj *, int, char *);
 
-static void save_child_in_parent (struct varobj *, struct varobj *);
-
-static void remove_child_from_parent (struct varobj *, struct varobj *);
-
 /* Utility routines */
 
 static struct varobj *new_variable (void);
@@ -188,16 +184,13 @@ static struct type *get_target_type (struct type *);
 
 static enum varobj_display_formats variable_default_display (struct varobj *);
 
-static int my_value_equal (struct value *, struct value *, int *);
-
-static void vpush (struct vstack **pstack, struct varobj *var);
-
-static struct varobj *vpop (struct vstack **pstack);
-
 static void cppush (struct cpstack **pstack, char *name);
 
 static char *cppop (struct cpstack **pstack);
 
+static int install_new_value (struct varobj *var, struct value *value, 
+                             int initial);
+
 /* Language-specific routines. */
 
 static enum varobj_languages variable_language (struct varobj *var);
@@ -212,13 +205,16 @@ static struct value *value_of_root (struct varobj **var_handle, int *);
 
 static struct value *value_of_child (struct varobj *parent, int index);
 
-static struct type *type_of_child (struct varobj *var);
-
 static int variable_editable (struct varobj *var);
 
 static char *my_value_of_variable (struct varobj *var);
 
-static int type_changeable (struct varobj *var);
+static char *value_get_print_value (struct value *value,
+                                   enum varobj_display_formats format);
+
+static int varobj_value_is_changeable_p (struct varobj *var);
+
+static int is_root_p (struct varobj *var);
 
 /* C implementation */
 
@@ -310,8 +306,7 @@ struct language_specific
 };
 
 /* Array of known source language routines. */
-static struct language_specific
-  languages[vlang_end][sizeof (struct language_specific)] = {
+static struct language_specific languages[vlang_end] = {
   /* Unknown (try treating as C */
   {
    vlang_unknown,
@@ -389,9 +384,35 @@ static struct vlist **varobj_table;
 \f
 
 /* API Implementation */
+static int
+is_root_p (struct varobj *var)
+{
+  return (var->root->rootvar == var);
+}
 
 /* Creates a varobj (not its children) */
 
+/* Return the full FRAME which corresponds to the given CORE_ADDR
+   or NULL if no FRAME on the chain corresponds to CORE_ADDR.  */
+
+static struct frame_info *
+find_frame_addr_in_frame_chain (CORE_ADDR frame_addr)
+{
+  struct frame_info *frame = NULL;
+
+  if (frame_addr == (CORE_ADDR) 0)
+    return NULL;
+
+  while (1)
+    {
+      frame = get_prev_frame (frame);
+      if (frame == NULL)
+       return NULL;
+      if (get_frame_base_address (frame) == frame_addr)
+       return frame;
+    }
+}
+
 struct varobj *
 varobj_create (char *objname,
               char *expression, CORE_ADDR frame, enum varobj_type type)
@@ -410,14 +431,21 @@ varobj_create (char *objname,
     {
       char *p;
       enum varobj_languages lang;
+      struct value *value;
 
       /* Parse and evaluate the expression, filling in as much
          of the variable's data as possible */
 
       /* Allow creator to specify context of variable */
       if ((type == USE_CURRENT_FRAME) || (type == USE_SELECTED_FRAME))
-       fi = selected_frame;
+       fi = deprecated_selected_frame;
       else
+       /* FIXME: cagney/2002-11-23: This code should be doing a
+          lookup using the frame ID and not just the frame's
+          ``address''.  This, of course, means an interface change.
+          However, with out that interface change ISAs, such as the
+          ia64 with its two stacks, won't work.  Similar goes for the
+          case where there is a frameless function.  */
        fi = find_frame_addr_in_frame_chain (frame);
 
       /* frame = -2 means always use selected frame */
@@ -426,7 +454,7 @@ varobj_create (char *objname,
 
       block = NULL;
       if (fi != NULL)
-       block = get_frame_block (fi);
+       block = get_frame_block (fi, 0);
 
       p = expression;
       innermost_block = NULL;
@@ -441,8 +469,8 @@ varobj_create (char *objname,
       if (var->root->exp->elts[0].opcode == OP_TYPE)
        {
          do_cleanups (old_chain);
-         fprintf_unfiltered (gdb_stderr,
-                             "Attempt to use a type name as an expression.");
+         fprintf_unfiltered (gdb_stderr, "Attempt to use a type name"
+                             " as an expression.\n");
          return NULL;
        }
 
@@ -456,36 +484,32 @@ varobj_create (char *objname,
          Since select_frame is so benign, just call it for all cases. */
       if (fi != NULL)
        {
-         var->root->frame = FRAME_FP (fi);
-         old_fi = selected_frame;
-         select_frame (fi, -1);
+         var->root->frame = get_frame_id (fi);
+         old_fi = deprecated_selected_frame;
+         select_frame (fi);
        }
 
       /* We definitively need to catch errors here.
          If evaluate_expression succeeds we got the value we wanted.
          But if it fails, we still go on with a call to evaluate_type()  */
-      if (gdb_evaluate_expression (var->root->exp, &var->value))
-       {
-         /* no error */
-         release_value (var->value);
-         if (VALUE_LAZY (var->value))
-           gdb_value_fetch_lazy (var->value);
-       }
-      else
-       var->value = evaluate_type (var->root->exp);
+      if (!gdb_evaluate_expression (var->root->exp, &value))
+       /* Error getting the value.  Try to at least get the
+          right type.  */
+       value = evaluate_type (var->root->exp);
 
-      var->type = VALUE_TYPE (var->value);
+      var->type = value_type (value);
+      install_new_value (var, value, 1 /* Initial assignment */);
 
       /* Set language info */
       lang = variable_language (var);
-      var->root->lang = languages[lang];
+      var->root->lang = &languages[lang];
 
       /* Set ourselves as our root */
       var->root->rootvar = var;
 
       /* Reset the selected frame */
       if (fi != NULL)
-       select_frame (old_fi, -1);
+       select_frame (old_fi);
     }
 
   /* If the variable object name is null, that means this
@@ -514,13 +538,13 @@ char *
 varobj_gen_name (void)
 {
   static int id = 0;
-  char obj_name[31];
+  char *obj_name;
 
   /* generate a name for this object */
   id++;
-  sprintf (obj_name, "var%d", id);
+  obj_name = xstrprintf ("var%d", id);
 
-  return xstrdup (obj_name);
+  return obj_name;
 }
 
 /* Given an "objname", returns the pointer to the corresponding varobj
@@ -544,7 +568,7 @@ varobj_get_handle (char *objname)
     cv = cv->next;
 
   if (cv == NULL)
-    error ("Variable object not found");
+    error (_("Variable object not found"));
 
   return cv->var;
 }
@@ -603,7 +627,7 @@ varobj_delete (struct varobj *var, char ***dellist, int only_children)
        }
 
       if (mycount || (*cp != NULL))
-       warning ("varobj_delete: assertion failed - mycount(=%d) <> 0",
+       warning (_("varobj_delete: assertion failed - mycount(=%d) <> 0"),
                 mycount);
     }
 
@@ -667,21 +691,38 @@ varobj_list_children (struct varobj *var, struct varobj ***childlist)
   if (var->num_children == -1)
     var->num_children = number_of_children (var);
 
+  /* If that failed, give up.  */
+  if (var->num_children == -1)
+    return -1;
+
+  /* If we're called when the list of children is not yet initialized,
+     allocate enough elements in it.  */
+  while (VEC_length (varobj_p, var->children) < var->num_children)
+    VEC_safe_push (varobj_p, var->children, NULL);
+
   /* List of children */
   *childlist = xmalloc ((var->num_children + 1) * sizeof (struct varobj *));
 
   for (i = 0; i < var->num_children; i++)
     {
+      varobj_p existing;
+
       /* Mark as the end in case we bail out */
       *((*childlist) + i) = NULL;
 
-      /* check if child exists, if not create */
-      name = name_of_child (var, i);
-      child = child_exists (var, name);
-      if (child == NULL)
-       child = create_child (var, i, name);
+      existing = VEC_index (varobj_p, var->children, i);
 
-      *((*childlist) + i) = child;
+      if (existing == NULL)
+       {
+         /* Either it's the first call to varobj_list_children for
+            this variable object, and the child was never created,
+            or it was explicitly deleted by the client.  */
+         name = name_of_child (var, i);
+         existing = create_child (var, i, name);
+         VEC_replace (varobj_p, var->children, i, existing);
+       }
+
+      *((*childlist) + i) = existing;
     }
 
   /* End of list is marked by a NULL pointer */
@@ -713,13 +754,21 @@ varobj_get_type (struct varobj *var)
   /* To print the type, we simply create a zero ``struct value *'' and
      cast it to our type. We then typeprint this variable. */
   val = value_zero (var->type, not_lval);
-  type_print (VALUE_TYPE (val), "", stb, -1);
+  type_print (value_type (val), "", stb, -1);
 
   thetype = ui_file_xstrdup (stb, &length);
   do_cleanups (old_chain);
   return thetype;
 }
 
+/* Obtain the type of an object variable.  */
+
+struct type *
+varobj_get_gdb_type (struct varobj *var)
+{
+  return var->type;
+}
+
 enum varobj_languages
 varobj_get_language (struct varobj *var)
 {
@@ -753,6 +802,7 @@ varobj_set_value (struct varobj *var, char *expression)
 {
   struct value *val;
   int offset = 0;
+  int error = 0;
 
   /* The argument "expression" contains the variable's new value.
      We need to first construct a legal expression for this -- ugh! */
@@ -761,16 +811,13 @@ varobj_set_value (struct varobj *var, char *expression)
   struct value *value;
   int saved_input_radix = input_radix;
 
-  if (variable_editable (var) && !var->error)
+  if (var->value != NULL && variable_editable (var) && !var->error)
     {
       char *s = expression;
       int i;
-      struct value *temp;
 
       input_radix = 10;                /* ALWAYS reset to decimal temporarily */
-      if (!gdb_parse_exp_1 (&s, 0, 0, &exp))
-       /* We cannot proceed without a well-formed expression. */
-       return 0;
+      exp = parse_exp_1 (&s, 0, 0);
       if (!gdb_evaluate_expression (exp, &value))
        {
          /* We cannot proceed without a valid expression. */
@@ -778,39 +825,35 @@ varobj_set_value (struct varobj *var, char *expression)
          return 0;
        }
 
-      /* If our parent is "public", "private", or "protected", we could
-         be asking to modify the value of a baseclass. If so, we need to
-         adjust our address by the offset of our baseclass in the subclass,
-         since VALUE_ADDRESS (var->value) points at the start of the subclass.
-         For some reason, value_cast doesn't take care of this properly. */
-      temp = var->value;
-      if (var->parent != NULL && CPLUS_FAKE_CHILD (var->parent))
-       {
-         struct varobj *super, *sub;
-         struct type *type;
-         super = var->parent->parent;
-         sub = super->parent;
-         if (sub != NULL)
-           {
-             /* Yes, it is a baseclass */
-             type = get_type_deref (sub);
-
-             if (super->index < TYPE_N_BASECLASSES (type))
-               {
-                 temp = value_copy (var->value);
-                 for (i = 0; i < super->index; i++)
-                   offset += TYPE_LENGTH (TYPE_FIELD_TYPE (type, i));
-               }
-           }
-       }
-
-      VALUE_ADDRESS (temp) += offset;
-      if (!gdb_value_assign (temp, value, &val))
+      /* All types that are editable must also be changeable.  */
+      gdb_assert (varobj_value_is_changeable_p (var));
+
+      /* The value of a changeable variable object must not be lazy.  */
+      gdb_assert (!value_lazy (var->value));
+
+      /* Need to coerce the input.  We want to check if the
+        value of the variable object will be different
+        after assignment, and the first thing value_assign
+        does is coerce the input.
+        For example, if we are assigning an array to a pointer variable we
+        should compare the pointer with the the array's address, not with the
+        array's content.  */
+      value = coerce_array (value);
+
+      /* The new value may be lazy.  gdb_value_assign, or 
+        rather value_contents, will take care of this.
+        If fetching of the new value will fail, gdb_value_assign
+        with catch the exception.  */
+      if (!gdb_value_assign (var->value, value, &val))
        return 0;
-      VALUE_ADDRESS (val) -= offset;
-      value_free (var->value);
-      release_value (val);
-      var->value = val;
+     
+      /* If the value has changed, record it, so that next -var-update can
+        report this change.  If a variable had a value of '1', we've set it
+        to '333' and then set again to '1', when -var-update will report this
+        variable as changed -- because the first assignment has set the
+        'updated' flag.  There's no need to optimize that, because return value
+        of -var-update should be considered an approximation.  */
+      var->updated = install_new_value (var, val, 0 /* Compare values. */);
       input_radix = saved_input_radix;
       return 1;
     }
@@ -849,6 +892,124 @@ varobj_list (struct varobj ***varlist)
   return rootcount;
 }
 
+/* Assign a new value to a variable object.  If INITIAL is non-zero,
+   this is the first assignement after the variable object was just
+   created, or changed type.  In that case, just assign the value 
+   and return 0.
+   Otherwise, assign the value and if type_changeable returns non-zero,
+   find if the new value is different from the current value.
+   Return 1 if so, and 0 if the values are equal.  
+
+   The VALUE parameter should not be released -- the function will
+   take care of releasing it when needed.  */
+static int
+install_new_value (struct varobj *var, struct value *value, int initial)
+{ 
+  int changeable;
+  int need_to_fetch;
+  int changed = 0;
+
+  var->error = 0;
+  /* We need to know the varobj's type to decide if the value should
+     be fetched or not.  C++ fake children (public/protected/private) don't have
+     a type. */
+  gdb_assert (var->type || CPLUS_FAKE_CHILD (var));
+  changeable = varobj_value_is_changeable_p (var);
+  need_to_fetch = changeable;
+
+  /* We are not interested in the address of references, and given
+     that in C++ a reference is not rebindable, it cannot
+     meaningfully change.  So, get hold of the real value.  */
+  if (value)
+    {
+      value = coerce_ref (value);
+      release_value (value);
+    }
+
+  if (var->type && TYPE_CODE (var->type) == TYPE_CODE_UNION)
+    /* For unions, we need to fetch the value implicitly because
+       of implementation of union member fetch.  When gdb
+       creates a value for a field and the value of the enclosing
+       structure is not lazy,  it immediately copies the necessary
+       bytes from the enclosing values.  If the enclosing value is
+       lazy, the call to value_fetch_lazy on the field will read
+       the data from memory.  For unions, that means we'll read the
+       same memory more than once, which is not desirable.  So
+       fetch now.  */
+    need_to_fetch = 1;
+
+  /* The new value might be lazy.  If the type is changeable,
+     that is we'll be comparing values of this type, fetch the
+     value now.  Otherwise, on the next update the old value
+     will be lazy, which means we've lost that old value.  */
+  if (need_to_fetch && value && value_lazy (value))
+    {
+      if (!gdb_value_fetch_lazy (value))
+       {
+         var->error = 1;
+         /* Set the value to NULL, so that for the next -var-update,
+            we don't try to compare the new value with this value,
+            that we couldn't even read.  */
+         value = NULL;
+       }
+      else
+       var->error = 0;
+    }
+
+  /* If the type is changeable, compare the old and the new values.
+     If this is the initial assignment, we don't have any old value
+     to compare with.  */
+  if (initial)
+    var->print_value = value_get_print_value (value, var->format);
+  else if (changeable)
+    {
+      /* If the value of the varobj was changed by -var-set-value, then the 
+        value in the varobj and in the target is the same.  However, that value
+        is different from the value that the varobj had after the previous
+        -var-update. So need to the varobj as changed.  */      
+      if (var->updated)
+       changed = 1;
+      else 
+       {
+         /* Try to compare the values.  That requires that both
+            values are non-lazy.  */
+         
+         /* Quick comparison of NULL values.  */
+         if (var->value == NULL && value == NULL)
+           /* Equal. */
+           ;
+         else if (var->value == NULL || value == NULL)
+           changed = 1;
+         else
+           {
+             char *print_value;
+             gdb_assert (!value_lazy (var->value));
+             gdb_assert (!value_lazy (value));
+             print_value = value_get_print_value (value, var->format);
+
+             if (strcmp (var->print_value, print_value) != 0)
+               {
+                 xfree (var->print_value);
+                 var->print_value = print_value;
+                 changed = 1;
+               }
+             else
+               xfree (print_value);
+           }
+       }
+    }
+
+  /* We must always keep the new value, since children depend on it.  */
+  if (var->value != NULL)
+    value_free (var->value);
+  var->value = value;
+  var->updated = 0;
+
+  gdb_assert (!var->value || value_type (var->value));
+
+  return changed;
+}
+
 /* Update the values for a variable and its children.  This is a
    two-pronged attack.  First, re-parse the value for the root's
    expression to see if it's changed.  Then go all the way
@@ -869,30 +1030,31 @@ int
 varobj_update (struct varobj **varp, struct varobj ***changelist)
 {
   int changed = 0;
+  int error = 0;
   int type_changed;
   int i;
   int vleft;
-  int error2;
   struct varobj *v;
   struct varobj **cv;
   struct varobj **templist = NULL;
   struct value *new;
-  struct vstack *stack = NULL;
-  struct vstack *result = NULL;
-  struct frame_info *old_fi;
+  VEC (varobj_p) *stack = NULL;
+  VEC (varobj_p) *result = NULL;
+  struct frame_id old_fid;
+  struct frame_info *fi;
 
   /* sanity check: have we been passed a pointer? */
   if (changelist == NULL)
     return -1;
 
   /*  Only root variables can be updated... */
-  if ((*varp)->root->rootvar != *varp)
+  if (!is_root_p (*varp))
     /* Not a root var */
     return -1;
 
   /* Save the selected stack frame, since we will need to change it
      in order to evaluate expressions. */
-  old_fi = selected_frame;
+  old_fid = get_frame_id (deprecated_selected_frame);
 
   /* Update the root variable. value_of_root can return NULL
      if the variable is no longer around, i.e. we stepped out of
@@ -901,118 +1063,76 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
      has changed. */
   type_changed = 1;
   new = value_of_root (varp, &type_changed);
+
+  /* Restore selected frame */
+  fi = frame_find_by_id (old_fid);
+  if (fi)
+    select_frame (fi);
+
   if (new == NULL)
     {
       (*varp)->error = 1;
       return -1;
     }
 
-  /* Initialize a stack for temporary results */
-  vpush (&result, NULL);
-
   /* If this is a "use_selected_frame" varobj, and its type has changed,
      them note that it's changed. */
   if (type_changed)
-    {
-      vpush (&result, *varp);
-      changed++;
-    }
-  /* If values are not equal, note that it's changed.
-     There a couple of exceptions here, though.
-     We don't want some types to be reported as "changed". */
-  else if (type_changeable (*varp)
-          && !my_value_equal ((*varp)->value, new, &error2))
-    {
-      vpush (&result, *varp);
-      changed++;
-      /* error2 replaces var->error since this new value
-         WILL replace the old one. */
-      (*varp)->error = error2;
-    }
-
-  /* We must always keep around the new value for this root
-     variable expression, or we lose the updated children! */
-  value_free ((*varp)->value);
-  (*varp)->value = new;
-
-  /* Initialize a stack */
-  vpush (&stack, NULL);
+    VEC_safe_push (varobj_p, result, *varp);
 
-  /* Push the root's children */
-  if ((*varp)->children != NULL)
+  if (install_new_value ((*varp), new, type_changed))
     {
-      struct varobj_child *c;
-      for (c = (*varp)->children; c != NULL; c = c->next)
-       vpush (&stack, c->child);
+      /* If type_changed is 1, install_new_value will never return
+        non-zero, so we'll never report the same variable twice.  */
+      gdb_assert (!type_changed);
+      VEC_safe_push (varobj_p, result, *varp);
     }
 
+  VEC_safe_push (varobj_p, stack, *varp);
+
   /* Walk through the children, reconstructing them all. */
-  v = vpop (&stack);
-  while (v != NULL)
+  while (!VEC_empty (varobj_p, stack))
     {
-      /* Push any children */
-      if (v->children != NULL)
-       {
-         struct varobj_child *c;
-         for (c = v->children; c != NULL; c = c->next)
-           vpush (&stack, c->child);
-       }
+      v = VEC_pop (varobj_p, stack);
 
-      /* Update this variable */
-      new = value_of_child (v->parent, v->index);
-      if (type_changeable (v) && !my_value_equal (v->value, new, &error2))
+      /* Push any children.  Use reverse order so that the first
+        child is popped from the work stack first, and so
+        will be added to result first.  This does not
+        affect correctness, just "nicer".  */
+      for (i = VEC_length (varobj_p, v->children)-1; i >= 0; --i)
        {
-         /* Note that it's changed */
-         vpush (&result, v);
-         changed++;
+         varobj_p c = VEC_index (varobj_p, v->children, i);
+         /* Child may be NULL if explicitly deleted by -var-delete.  */
+         if (c != NULL)
+           VEC_safe_push (varobj_p, stack, c);
        }
-      /* error2 replaces v->error since this new value
-         WILL replace the old one. */
-      v->error = error2;
 
-      /* We must always keep new values, since children depend on it. */
-      if (v->value != NULL)
-       value_free (v->value);
-      v->value = new;
-
-      /* Get next child */
-      v = vpop (&stack);
+      /* Update this variable, unless it's a root, which is already
+        updated.  */
+      if (v != *varp)
+       {         
+         new = value_of_child (v->parent, v->index);
+         if (install_new_value (v, new, 0 /* type not changed */))
+           {
+             /* Note that it's changed */
+             VEC_safe_push (varobj_p, result, v);
+             v->updated = 0;
+           }
+       }
     }
 
   /* Alloc (changed + 1) list entries */
-  /* FIXME: add a cleanup for the allocated list(s)
-     because one day the select_frame called below can longjump */
+  changed = VEC_length (varobj_p, result);
   *changelist = xmalloc ((changed + 1) * sizeof (struct varobj *));
-  if (changed > 1)
-    {
-      templist = xmalloc ((changed + 1) * sizeof (struct varobj *));
-      cv = templist;
-    }
-  else
-    cv = *changelist;
-
-  /* Copy from result stack to list */
-  vleft = changed;
-  *cv = vpop (&result);
-  while ((*cv != NULL) && (vleft > 0))
-    {
-      vleft--;
-      cv++;
-      *cv = vpop (&result);
-    }
-  if (vleft)
-    warning ("varobj_update: assertion failed - vleft <> 0");
+  cv = *changelist;
 
-  if (changed > 1)
+  for (i = 0; i < changed; ++i)
     {
-      /* Now we revert the order. */
-      for (i = 0; i < changed; i++)
-       *(*changelist + i) = *(templist + changed - 1 - i);
-      *(*changelist + changed) = NULL;
+      *cv = VEC_index (varobj_p, result, i);
+      gdb_assert (*cv != NULL);
+      ++cv;
     }
-
-  /* Restore selected frame */
-  select_frame (old_fi, -1);
+  *cv = 0;
 
   if (type_changed)
     return -2;
@@ -1048,18 +1168,17 @@ delete_variable_1 (struct cpstack **resultp, int *delcountp,
                   struct varobj *var, int only_children_p,
                   int remove_from_parent_p)
 {
-  struct varobj_child *vc;
-  struct varobj_child *next;
+  int i;
 
   /* Delete any children of this variable, too. */
-  for (vc = var->children; vc != NULL; vc = next)
-    {
+  for (i = 0; i < VEC_length (varobj_p, var->children); ++i)
+    {   
+      varobj_p child = VEC_index (varobj_p, var->children, i);
       if (!remove_from_parent_p)
-       vc->child->parent = NULL;
-      delete_variable_1 (resultp, delcountp, vc->child, 0, only_children_p);
-      next = vc->next;
-      xfree (vc);
+       child->parent = NULL;
+      delete_variable_1 (resultp, delcountp, child, 0, only_children_p);
     }
+  VEC_free (varobj_p, var->children);
 
   /* if we were called to delete only the children we are done here */
   if (only_children_p)
@@ -1081,7 +1200,7 @@ delete_variable_1 (struct cpstack **resultp, int *delcountp,
      discarding the list afterwards */
   if ((remove_from_parent_p) && (var->parent != NULL))
     {
-      remove_child_from_parent (var->parent, var);
+      VEC_replace (varobj_p, var->parent->children, var->index, NULL);
     }
 
   if (var->obj_name != NULL)
@@ -1111,7 +1230,7 @@ install_variable (struct varobj *var)
     cv = cv->next;
 
   if (cv != NULL)
-    error ("Duplicate variable object name");
+    error (_("Duplicate variable object name"));
 
   /* Add varobj to hash table */
   newvl = xmalloc (sizeof (struct vlist));
@@ -1120,7 +1239,7 @@ install_variable (struct varobj *var)
   *(varobj_table + index) = newvl;
 
   /* If root, add varobj to root list */
-  if (var->root->rootvar == var)
+  if (is_root_p (var))
     {
       /* Add to list of root variables */
       if (rootlist == NULL)
@@ -1179,7 +1298,7 @@ uninstall_variable (struct varobj *var)
   xfree (cv);
 
   /* If root, remove varobj from root list */
-  if (var->root->rootvar == var)
+  if (is_root_p (var))
     {
       /* Remove from list of root variables */
       if (rootlist == var->root)
@@ -1210,94 +1329,43 @@ uninstall_variable (struct varobj *var)
 
 }
 
-/* Does a child with the name NAME exist in VAR? If so, return its data.
-   If not, return NULL. */
-static struct varobj *
-child_exists (struct varobj *var, char *name)
-{
-  struct varobj_child *vc;
-
-  for (vc = var->children; vc != NULL; vc = vc->next)
-    {
-      if (STREQ (vc->child->name, name))
-       return vc->child;
-    }
-
-  return NULL;
-}
-
 /* Create and install a child of the parent of the given name */
 static struct varobj *
 create_child (struct varobj *parent, int index, char *name)
 {
   struct varobj *child;
   char *childs_name;
+  struct value *value;
 
   child = new_variable ();
 
   /* name is allocated by name_of_child */
   child->name = name;
   child->index = index;
-  child->value = value_of_child (parent, index);
-  if (child->value == NULL || parent->error)
-    child->error = 1;
+  value = value_of_child (parent, index);
   child->parent = parent;
   child->root = parent->root;
-  childs_name =
-    (char *) xmalloc ((strlen (parent->obj_name) + strlen (name) + 2) *
-                     sizeof (char));
-  sprintf (childs_name, "%s.%s", parent->obj_name, name);
+  childs_name = xstrprintf ("%s.%s", parent->obj_name, name);
   child->obj_name = childs_name;
   install_variable (child);
 
-  /* Save a pointer to this child in the parent */
-  save_child_in_parent (parent, child);
+  /* Compute the type of the child.  Must do this before
+     calling install_new_value.  */
+  if (value != NULL)
+    /* If the child had no evaluation errors, var->value
+       will be non-NULL and contain a valid type. */
+    child->type = value_type (value);
+  else
+    /* Otherwise, we must compute the type. */
+    child->type = (*child->root->lang->type_of_child) (child->parent, 
+                                                      child->index);
+  install_new_value (child, value, 1);
 
-  /* Note the type of this child */
-  child->type = type_of_child (child);
+  if ((!CPLUS_FAKE_CHILD (child) && child->value == NULL) || parent->error)
+    child->error = 1;
 
   return child;
 }
-
-/* FIXME: This should be a generic add to list */
-/* Save CHILD in the PARENT's data. */
-static void
-save_child_in_parent (struct varobj *parent, struct varobj *child)
-{
-  struct varobj_child *vc;
-
-  /* Insert the child at the top */
-  vc = parent->children;
-  parent->children =
-    (struct varobj_child *) xmalloc (sizeof (struct varobj_child));
-
-  parent->children->next = vc;
-  parent->children->child = child;
-}
-
-/* FIXME: This should be a generic remove from list */
-/* Remove the CHILD from the PARENT's list of children. */
-static void
-remove_child_from_parent (struct varobj *parent, struct varobj *child)
-{
-  struct varobj_child *vc, *prev;
-
-  /* Find the child in the parent's list */
-  prev = NULL;
-  for (vc = parent->children; vc != NULL;)
-    {
-      if (vc->child == child)
-       break;
-      prev = vc;
-      vc = vc->next;
-    }
-
-  if (prev == NULL)
-    parent->children = vc->next;
-  else
-    prev->next = vc->next;
-
-}
 \f
 
 /*
@@ -1322,6 +1390,8 @@ new_variable (void)
   var->children = NULL;
   var->format = 0;
   var->root = NULL;
+  var->updated = 0;
+  var->print_value = NULL;
 
   return var;
 }
@@ -1335,7 +1405,7 @@ new_root_variable (void)
   var->root->lang = NULL;
   var->root->exp = NULL;
   var->root->valid_block = NULL;
-  var->root->frame = (CORE_ADDR) -1;
+  var->root->frame = null_frame_id;
   var->root->use_selected_frame = 0;
   var->root->rootvar = NULL;
 
@@ -1347,14 +1417,15 @@ static void
 free_variable (struct varobj *var)
 {
   /* Free the expression if this is a root variable. */
-  if (var->root->rootvar == var)
+  if (is_root_p (var))
     {
-      free_current_contents ((char **) &var->root->exp);
+      free_current_contents (&var->root->exp);
       xfree (var->root);
     }
 
   xfree (var->name);
   xfree (var->obj_name);
+  xfree (var->print_value);
   xfree (var);
 }
 
@@ -1370,22 +1441,25 @@ make_cleanup_free_variable (struct varobj *var)
   return make_cleanup (do_free_variable_cleanup, var);
 }
 
-/* This returns the type of the variable. This skips past typedefs
-   and returns the real type of the variable. It also dereferences
-   pointers and references. */
+/* This returns the type of the variable. It also skips past typedefs
+   to return the real type of the variable.
+
+   NOTE: TYPE_TARGET_TYPE should NOT be used anywhere in this file
+   except within get_target_type and get_type. */
 static struct type *
 get_type (struct varobj *var)
 {
   struct type *type;
   type = var->type;
 
-  while (type != NULL && TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
-    type = TYPE_TARGET_TYPE (type);
+  if (type != NULL)
+    type = check_typedef (type);
 
   return type;
 }
 
-/* This returns the type of the variable, dereferencing pointers, too. */
+/* This returns the type of the variable, dereferencing references, pointers
+   and references to pointers, too. */
 static struct type *
 get_type_deref (struct varobj *var)
 {
@@ -1393,23 +1467,30 @@ get_type_deref (struct varobj *var)
 
   type = get_type (var);
 
-  if (type != NULL && (TYPE_CODE (type) == TYPE_CODE_PTR
-                      || TYPE_CODE (type) == TYPE_CODE_REF))
-    type = get_target_type (type);
+  if (type)
+    {
+      if (TYPE_CODE (type) == TYPE_CODE_REF)
+       type = get_target_type (type);
+      if (TYPE_CODE (type) == TYPE_CODE_PTR)
+       type = get_target_type (type);
+    }
 
   return type;
 }
 
 /* This returns the target type (or NULL) of TYPE, also skipping
-   past typedefs, just like get_type (). */
+   past typedefs, just like get_type ().
+
+   NOTE: TYPE_TARGET_TYPE should NOT be used anywhere in this file
+   except within get_target_type and get_type. */
 static struct type *
 get_target_type (struct type *type)
 {
   if (type != NULL)
     {
       type = TYPE_TARGET_TYPE (type);
-      while (type != NULL && TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
-       type = TYPE_TARGET_TYPE (type);
+      if (type != NULL)
+       type = check_typedef (type);
     }
 
   return type;
@@ -1423,92 +1504,6 @@ variable_default_display (struct varobj *var)
   return FORMAT_NATURAL;
 }
 
-/* This function is similar to gdb's value_equal, except that this
-   one is "safe" -- it NEVER longjmps. It determines if the VAR's
-   value is the same as VAL2. */
-static int
-my_value_equal (struct value *val1, struct value *val2, int *error2)
-{
-  int r, err1, err2;
-
-  *error2 = 0;
-  /* Special case: NULL values. If both are null, say
-     they're equal. */
-  if (val1 == NULL && val2 == NULL)
-    return 1;
-  else if (val1 == NULL || val2 == NULL)
-    return 0;
-
-  /* This is bogus, but unfortunately necessary. We must know
-     exactly what caused an error -- reading val1 or val2 --  so
-     that we can really determine if we think that something has changed. */
-  err1 = 0;
-  err2 = 0;
-  /* We do need to catch errors here because the whole purpose
-     is to test if value_equal() has errored */
-  if (!gdb_value_equal (val1, val1, &r))
-    err1 = 1;
-
-  if (!gdb_value_equal (val2, val2, &r))
-    *error2 = err2 = 1;
-
-  if (err1 != err2)
-    return 0;
-
-  if (!gdb_value_equal (val1, val2, &r))
-    {
-      /* An error occurred, this could have happened if
-         either val1 or val2 errored. ERR1 and ERR2 tell
-         us which of these it is. If both errored, then
-         we assume nothing has changed. If one of them is
-         valid, though, then something has changed. */
-      if (err1 == err2)
-       {
-         /* both the old and new values caused errors, so
-            we say the value did not change */
-         /* This is indeterminate, though. Perhaps we should
-            be safe and say, yes, it changed anyway?? */
-         return 1;
-       }
-      else
-       {
-         return 0;
-       }
-    }
-
-  return r;
-}
-
-/* FIXME: The following should be generic for any pointer */
-static void
-vpush (struct vstack **pstack, struct varobj *var)
-{
-  struct vstack *s;
-
-  s = (struct vstack *) xmalloc (sizeof (struct vstack));
-  s->var = var;
-  s->next = *pstack;
-  *pstack = s;
-}
-
-/* FIXME: The following should be generic for any pointer */
-static struct varobj *
-vpop (struct vstack **pstack)
-{
-  struct vstack *s;
-  struct varobj *v;
-
-  if ((*pstack)->var == NULL && (*pstack)->next == NULL)
-    return NULL;
-
-  s = *pstack;
-  v = s->var;
-  *pstack = (*pstack)->next;
-  xfree (s);
-
-  return v;
-}
-
 /* FIXME: The following should be generic for any pointer */
 static void
 cppush (struct cpstack **pstack, char *name)
@@ -1616,7 +1611,7 @@ value_of_root (struct varobj **var_handle, int *type_changed)
   /* This should really be an exception, since this should
      only get called with a root variable. */
 
-  if (var->root->rootvar != var)
+  if (!is_root_p (var))
     return NULL;
 
   if (var->root->use_selected_frame)
@@ -1670,27 +1665,9 @@ value_of_child (struct varobj *parent, int index)
 
   value = (*parent->root->lang->value_of_child) (parent, index);
 
-  /* If we're being lazy, fetch the real value of the variable. */
-  if (value != NULL && VALUE_LAZY (value))
-    gdb_value_fetch_lazy (value);
-
   return value;
 }
 
-/* What is the type of VAR? */
-static struct type *
-type_of_child (struct varobj *var)
-{
-
-  /* If the child had no evaluation errors, var->value
-     will be non-NULL and contain a valid type. */
-  if (var->value != NULL)
-    return VALUE_TYPE (var->value);
-
-  /* Otherwise, we must compute the type. */
-  return (*var->root->lang->type_of_child) (var->parent, var->index);
-}
-
 /* Is this variable editable? Use the variable's type to make
    this determination. */
 static int
@@ -1706,11 +1683,31 @@ my_value_of_variable (struct varobj *var)
   return (*var->root->lang->value_of_variable) (var);
 }
 
-/* Is VAR something that can change? Depending on language,
-   some variable's values never change. For example,
-   struct and unions never change values. */
+static char *
+value_get_print_value (struct value *value, enum varobj_display_formats format)
+{
+  long dummy;
+  struct ui_file *stb = mem_fileopen ();
+  struct cleanup *old_chain = make_cleanup_ui_file_delete (stb);
+  char *thevalue;
+           
+  common_val_print (value, stb, format_code[(int) format], 1, 0, 0);
+  thevalue = ui_file_xstrdup (stb, &dummy);
+  do_cleanups (old_chain);
+  return thevalue;
+}
+
+/* Return non-zero if changes in value of VAR
+   must be detected and reported by -var-update.
+   Return zero is -var-update should never report
+   changes of such values.  This makes sense for structures
+   (since the changes in children values will be reported separately),
+   or for artifical objects (like 'public' pseudo-field in C++).
+
+   Return value of 0 means that gdb need not call value_fetch_lazy
+   for the value of this variable object.  */
 static int
-type_changeable (struct varobj *var)
+varobj_value_is_changeable_p (struct varobj *var)
 {
   int r;
   struct type *type;
@@ -1754,7 +1751,9 @@ c_number_of_children (struct varobj *var)
          && TYPE_ARRAY_UPPER_BOUND_TYPE (type) != BOUND_CANNOT_BE_DETERMINED)
        children = TYPE_LENGTH (type) / TYPE_LENGTH (target);
       else
-       children = -1;
+       /* If we don't know how many elements there are, don't display
+          any.  */
+       children = 0;
       break;
 
     case TYPE_CODE_STRUCT:
@@ -1763,9 +1762,9 @@ c_number_of_children (struct varobj *var)
       break;
 
     case TYPE_CODE_PTR:
-      /* This is where things get compilcated. All pointers have one child.
+      /* This is where things get complicated. All pointers have one child.
          Except, of course, for struct and union ptr, which we automagically
-         dereference for the user and function ptrs, which have no children.
+         dereference for the user, and function ptrs which have no children.
          We also don't dereference void* as we don't know what to show.
          We can show char* so we allow it to be dereferenced.  If you decide
          to test for it, please mind that a little magic is necessary to
@@ -1803,71 +1802,155 @@ c_name_of_variable (struct varobj *parent)
   return savestring (parent->name, strlen (parent->name));
 }
 
-static char *
-c_name_of_child (struct varobj *parent, int index)
+/* Return the value of element TYPE_INDEX of a structure
+   value VALUE.  VALUE's type should be a structure,
+   or union, or a typedef to struct/union.  
+
+   Returns NULL if getting the value fails.  Never throws.  */
+static struct value *
+value_struct_element_index (struct value *value, int type_index)
 {
-  struct type *type;
-  struct type *target;
-  char *name;
-  char *string;
+  struct value *result = NULL;
+  volatile struct gdb_exception e;
 
-  type = get_type (parent);
-  target = get_target_type (type);
+  struct type *type = value_type (value);
+  type = check_typedef (type);
 
+  gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT
+             || TYPE_CODE (type) == TYPE_CODE_UNION);
+
+  TRY_CATCH (e, RETURN_MASK_ERROR)
+    {
+      if (TYPE_FIELD_STATIC (type, type_index))
+       result = value_static_field (type, type_index);
+      else
+       result = value_primitive_field (value, 0, type_index, type);
+    }
+  if (e.reason < 0)
+    {
+      return NULL;
+    }
+  else
+    {
+      return result;
+    }
+}
+
+/* Obtain the information about child INDEX of the variable
+   object PARENT.  
+   If CNAME is not null, sets *CNAME to the name of the child relative
+   to the parent.
+   If CVALUE is not null, sets *CVALUE to the value of the child.
+   If CTYPE is not null, sets *CTYPE to the type of the child.
+
+   If any of CNAME, CVALUE, or CTYPE is not null, but the corresponding
+   information cannot be determined, set *CNAME, *CVALUE, or *CTYPE
+   to NULL.  */
+static void 
+c_describe_child (struct varobj *parent, int index,
+                 char **cname, struct value **cvalue, struct type **ctype)
+{
+  struct value *value = parent->value;
+  struct type *type = get_type (parent);
+
+  if (cname)
+    *cname = NULL;
+  if (cvalue)
+    *cvalue = NULL;
+  if (ctype)
+    *ctype = NULL;
+
+  /* Pointers to structures are treated just like
+     structures when accessing children.  */
+  if (TYPE_CODE (type) == TYPE_CODE_PTR)
+    {
+      struct type *target_type = get_target_type (type);
+      if (TYPE_CODE (target_type) == TYPE_CODE_STRUCT
+         || TYPE_CODE (target_type) == TYPE_CODE_UNION)
+       {
+         if (value)
+           gdb_value_ind (value, &value);        
+         type = target_type;
+       }
+    }
+      
   switch (TYPE_CODE (type))
     {
     case TYPE_CODE_ARRAY:
-      {
-       /* We never get here unless parent->num_children is greater than 0... */
-       int len = 1;
-       while ((int) pow ((double) 10, (double) len) < index)
-         len++;
-       name = (char *) xmalloc (1 + len * sizeof (char));
-       sprintf (name, "%d", index);
-      }
+      if (cname)
+       *cname = xstrprintf ("%d", index
+                            + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)));
+
+      if (cvalue && value)
+       {
+         int real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type));
+         struct value *indval = 
+           value_from_longest (builtin_type_int, (LONGEST) real_index);
+         gdb_value_subscript (value, indval, cvalue);
+       }
+
+      if (ctype)
+       *ctype = get_target_type (type);
+
       break;
 
     case TYPE_CODE_STRUCT:
     case TYPE_CODE_UNION:
-      string = TYPE_FIELD_NAME (type, index);
-      name = savestring (string, strlen (string));
+      if (cname)
+       {
+         char *string = TYPE_FIELD_NAME (type, index);
+         *cname = savestring (string, strlen (string));
+       }
+
+      if (cvalue && value)
+       {
+         /* For C, varobj index is the same as type index.  */
+         *cvalue = value_struct_element_index (value, index);
+       }
+
+      if (ctype)
+       *ctype = TYPE_FIELD_TYPE (type, index);
+
       break;
 
     case TYPE_CODE_PTR:
-      switch (TYPE_CODE (target))
-       {
-       case TYPE_CODE_STRUCT:
-       case TYPE_CODE_UNION:
-         string = TYPE_FIELD_NAME (target, index);
-         name = savestring (string, strlen (string));
-         break;
+      if (cname)
+       *cname = xstrprintf ("*%s", parent->name);
 
-       default:
-         name =
-           (char *) xmalloc ((strlen (parent->name) + 2) * sizeof (char));
-         sprintf (name, "*%s", parent->name);
-         break;
-       }
+      if (cvalue && value)
+       gdb_value_ind (value, cvalue);
+
+      if (ctype)
+       *ctype = get_target_type (type);
+      
       break;
 
     default:
       /* This should not happen */
-      name = xstrdup ("???");
+      if (cname)
+       *cname = xstrdup ("???");
+      /* Don't set value and type, we don't know then. */
     }
+}
 
+static char *
+c_name_of_child (struct varobj *parent, int index)
+{
+  char *name;
+  c_describe_child (parent, index, &name, NULL, NULL);
   return name;
 }
 
 static struct value *
 c_value_of_root (struct varobj **var_handle)
 {
-  struct value *new_val;
+  struct value *new_val = NULL;
   struct varobj *var = *var_handle;
   struct frame_info *fi;
   int within_scope;
 
   /*  Only root variables can be updated... */
-  if (var->root->rootvar != var)
+  if (!is_root_p (var))
     /* Not a root var */
     return NULL;
 
@@ -1878,14 +1961,17 @@ c_value_of_root (struct varobj **var_handle)
   else
     {
       reinit_frame_cache ();
-
-
-      fi = find_frame_addr_in_frame_chain (var->root->frame);
-
+      fi = frame_find_by_id (var->root->frame);
       within_scope = fi != NULL;
       /* FIXME: select_frame could fail */
-      if (within_scope)
-       select_frame (fi, -1);
+      if (fi)
+       {
+         CORE_ADDR pc = get_frame_pc (fi);
+         if (pc <  BLOCK_START (var->root->valid_block) ||
+             pc >= BLOCK_END (var->root->valid_block))
+           within_scope = 0;
+         select_frame (fi);
+       }         
     }
 
   if (within_scope)
@@ -1895,24 +1981,12 @@ c_value_of_root (struct varobj **var_handle)
          go on */
       if (gdb_evaluate_expression (var->root->exp, &new_val))
        {
-         if (VALUE_LAZY (new_val))
-           {
-             /* We need to catch errors because if
-                value_fetch_lazy fails we still want to continue
-                (after making val->error = 1) */
-             /* FIXME: Shouldn't be using VALUE_CONTENTS?  The
-                comment on value_fetch_lazy() says it is only
-                called from the macro... */
-             if (!gdb_value_fetch_lazy (new_val))
-               var->error = 1;
-             else
-               var->error = 0;
-           }
+         var->error = 0;
+         release_value (new_val);
        }
       else
        var->error = 1;
 
-      release_value (new_val);
       return new_val;
     }
 
@@ -1922,59 +1996,8 @@ c_value_of_root (struct varobj **var_handle)
 static struct value *
 c_value_of_child (struct varobj *parent, int index)
 {
-  struct value *value;
-  struct value *temp;
-  struct value *indval;
-  struct type *type, *target;
-  char *name;
-
-  type = get_type (parent);
-  target = get_target_type (type);
-  name = name_of_child (parent, index);
-  temp = parent->value;
-  value = NULL;
-
-  if (temp != NULL)
-    {
-      switch (TYPE_CODE (type))
-       {
-       case TYPE_CODE_ARRAY:
-#if 0
-         /* This breaks if the array lives in a (vector) register. */
-         value = value_slice (temp, index, 1);
-         temp = value_coerce_array (value);
-         gdb_value_ind (temp, &value);
-#else
-         indval = value_from_longest (builtin_type_int, (LONGEST) index);
-         gdb_value_subscript (temp, indval, &value);
-#endif
-         break;
-
-       case TYPE_CODE_STRUCT:
-       case TYPE_CODE_UNION:
-         value = value_struct_elt (&temp, NULL, name, NULL, "vstructure");
-         break;
-
-       case TYPE_CODE_PTR:
-         switch (TYPE_CODE (target))
-           {
-           case TYPE_CODE_STRUCT:
-           case TYPE_CODE_UNION:
-             value =
-               value_struct_elt (&temp, NULL, name, NULL, "vstructure");
-             break;
-
-           default:
-             gdb_value_ind (temp, &value);
-             break;
-           }
-         break;
-
-       default:
-         break;
-       }
-    }
-
+  struct value *value = NULL;
+  c_describe_child (parent, index, NULL, &value, NULL);
   if (value != NULL)
     release_value (value);
 
@@ -1984,42 +2007,8 @@ c_value_of_child (struct varobj *parent, int index)
 static struct type *
 c_type_of_child (struct varobj *parent, int index)
 {
-  struct type *type;
-  char *name = name_of_child (parent, index);
-
-  switch (TYPE_CODE (parent->type))
-    {
-    case TYPE_CODE_ARRAY:
-      type = TYPE_TARGET_TYPE (parent->type);
-      break;
-
-    case TYPE_CODE_STRUCT:
-    case TYPE_CODE_UNION:
-      type = lookup_struct_elt_type (parent->type, name, 0);
-      break;
-
-    case TYPE_CODE_PTR:
-      switch (TYPE_CODE (TYPE_TARGET_TYPE (parent->type)))
-       {
-       case TYPE_CODE_STRUCT:
-       case TYPE_CODE_UNION:
-         type = lookup_struct_elt_type (parent->type, name, 0);
-         break;
-
-       default:
-         type = TYPE_TARGET_TYPE (parent->type);
-         break;
-       }
-      break;
-
-    default:
-      /* This should not happen as only the above types have children */
-      warning ("Child of parent whose type does not allow children");
-      /* FIXME: Can we still go on? */
-      type = NULL;
-      break;
-    }
-
+  struct type *type = NULL;
+  c_describe_child (parent, index, NULL, NULL, &type);
   return type;
 }
 
@@ -2032,7 +2021,6 @@ c_variable_editable (struct varobj *var)
     case TYPE_CODE_UNION:
     case TYPE_CODE_ARRAY:
     case TYPE_CODE_FUNC:
-    case TYPE_CODE_MEMBER:
     case TYPE_CODE_METHOD:
       return 0;
       break;
@@ -2046,21 +2034,15 @@ c_variable_editable (struct varobj *var)
 static char *
 c_value_of_variable (struct varobj *var)
 {
-  struct type *type;
-  struct value *val;
+  /* BOGUS: if val_print sees a struct/class, or a reference to one,
+     it will print out its children instead of "{...}".  So we need to
+     catch that case explicitly.  */
+  struct type *type = get_type (var);
 
-  if (var->value != NULL)
-    val = var->value;
-  else
-    {
-      /* This can happen if we attempt to get the value of a struct
-         member when the parent is an invalid pointer. */
-      return xstrdup ("???");
-    }
+  /* Strip top-level references. */
+  while (TYPE_CODE (type) == TYPE_CODE_REF)
+    type = check_typedef (TYPE_TARGET_TYPE (type));
 
-  /* BOGUS: if val_print sees a struct/class, it will print out its
-     children instead of "{...}" */
-  type = get_type (var);
   switch (TYPE_CODE (type))
     {
     case TYPE_CODE_STRUCT:
@@ -2070,29 +2052,28 @@ c_value_of_variable (struct varobj *var)
 
     case TYPE_CODE_ARRAY:
       {
-       char number[18];
-       sprintf (number, "[%d]", var->num_children);
-       return xstrdup (number);
+       char *number;
+       number = xstrprintf ("[%d]", var->num_children);
+       return (number);
       }
       /* break; */
 
     default:
       {
-       long dummy;
-       struct ui_file *stb = mem_fileopen ();
-       struct cleanup *old_chain = make_cleanup_ui_file_delete (stb);
-       char *thevalue;
-
-       if (VALUE_LAZY (val))
-         gdb_value_fetch_lazy (val);
-       val_print (VALUE_TYPE (val), VALUE_CONTENTS_RAW (val), 0,
-                  VALUE_ADDRESS (val),
-                  stb, format_code[(int) var->format], 1, 0, 0);
-       thevalue = ui_file_xstrdup (stb, &dummy);
-       do_cleanups (old_chain);
-       return thevalue;
+       if (var->value == NULL)
+         {
+           /* This can happen if we attempt to get the value of a struct
+              member when the parent is an invalid pointer. This is an
+              error condition, so we should tell the caller. */
+           return NULL;
+         }
+       else
+         {
+           gdb_assert (varobj_value_is_changeable_p (var));
+           gdb_assert (!value_lazy (var->value));
+           return value_get_print_value (var->value, var->format);
+         }
       }
-      /* break; */
     }
 }
 \f
@@ -2139,9 +2120,9 @@ cplus_number_of_children (struct varobj *var)
       type = get_type_deref (var->parent);
 
       cplus_class_num_children (type, kids);
-      if (STREQ (var->name, "public"))
+      if (strcmp (var->name, "public") == 0)
        children = kids[v_public];
-      else if (STREQ (var->name, "private"))
+      else if (strcmp (var->name, "private") == 0)
        children = kids[v_private];
       else
        children = kids[v_protected];
@@ -2192,7 +2173,6 @@ cplus_name_of_child (struct varobj *parent, int index)
 {
   char *name;
   struct type *type;
-  int children[3];
 
   if (CPLUS_FAKE_CHILD (parent))
     {
@@ -2207,48 +2187,97 @@ cplus_name_of_child (struct varobj *parent, int index)
     {
     case TYPE_CODE_STRUCT:
     case TYPE_CODE_UNION:
-      cplus_class_num_children (type, children);
-
       if (CPLUS_FAKE_CHILD (parent))
        {
-         /* FIXME: This assumes that type orders
-            inherited, public, private, protected */
-         int i = index + TYPE_N_BASECLASSES (type);
-         if (STREQ (parent->name, "private")
-             || STREQ (parent->name, "protected"))
-           i += children[v_public];
-         if (STREQ (parent->name, "protected"))
-           i += children[v_private];
-
-         name = TYPE_FIELD_NAME (type, i);
+         /* The fields of the class type are ordered as they
+            appear in the class.  We are given an index for a
+            particular access control type ("public","protected",
+            or "private").  We must skip over fields that don't
+            have the access control we are looking for to properly
+            find the indexed field. */
+         int type_index = TYPE_N_BASECLASSES (type);
+         if (strcmp (parent->name, "private") == 0)
+           {
+             while (index >= 0)
+               {
+                 if (TYPE_VPTR_BASETYPE (type) == type
+                     && type_index == TYPE_VPTR_FIELDNO (type))
+                   ; /* ignore vptr */
+                 else if (TYPE_FIELD_PRIVATE (type, type_index))
+                   --index;
+                 ++type_index;
+               }
+             --type_index;
+           }
+         else if (strcmp (parent->name, "protected") == 0)
+           {
+             while (index >= 0)
+               {
+                 if (TYPE_VPTR_BASETYPE (type) == type
+                     && type_index == TYPE_VPTR_FIELDNO (type))
+                   ; /* ignore vptr */
+                 else if (TYPE_FIELD_PROTECTED (type, type_index))
+                   --index;
+                 ++type_index;
+               }
+             --type_index;
+           }
+         else
+           {
+             while (index >= 0)
+               {
+                 if (TYPE_VPTR_BASETYPE (type) == type
+                     && type_index == TYPE_VPTR_FIELDNO (type))
+                   ; /* ignore vptr */
+                 else if (!TYPE_FIELD_PRIVATE (type, type_index) &&
+                     !TYPE_FIELD_PROTECTED (type, type_index))
+                   --index;
+                 ++type_index;
+               }
+             --type_index;
+           }
+
+         name = TYPE_FIELD_NAME (type, type_index);
        }
       else if (index < TYPE_N_BASECLASSES (type))
+       /* We are looking up the name of a base class */
        name = TYPE_FIELD_NAME (type, index);
       else
        {
+         int children[3];
+         cplus_class_num_children(type, children);
+
          /* Everything beyond the baseclasses can
-            only be "public", "private", or "protected" */
+            only be "public", "private", or "protected"
+
+            The special "fake" children are always output by varobj in
+            this order. So if INDEX == 2, it MUST be "protected". */
          index -= TYPE_N_BASECLASSES (type);
          switch (index)
            {
            case 0:
-             if (children[v_public] != 0)
-               {
-                 name = "public";
-                 break;
-               }
+             if (children[v_public] > 0)
+               name = "public";
+             else if (children[v_private] > 0)
+               name = "private";
+             else 
+               name = "protected";
+             break;
            case 1:
-             if (children[v_private] != 0)
+             if (children[v_public] > 0)
                {
-                 name = "private";
-                 break;
+                 if (children[v_private] > 0)
+                   name = "private";
+                 else
+                   name = "protected";
                }
+             else if (children[v_private] > 0)
+               name = "protected";
+             break;
            case 2:
-             if (children[v_protected] != 0)
-               {
-                 name = "protected";
-                 break;
-               }
+             /* Must be protected */
+             name = "protected";
+             break;
            default:
              /* error! */
              break;
@@ -2282,7 +2311,6 @@ cplus_value_of_child (struct varobj *parent, int index)
 {
   struct type *type;
   struct value *value;
-  char *name;
 
   if (CPLUS_FAKE_CHILD (parent))
     type = get_type_deref (parent->parent);
@@ -2290,17 +2318,25 @@ cplus_value_of_child (struct varobj *parent, int index)
     type = get_type_deref (parent);
 
   value = NULL;
-  name = name_of_child (parent, index);
 
   if (((TYPE_CODE (type)) == TYPE_CODE_STRUCT) ||
       ((TYPE_CODE (type)) == TYPE_CODE_UNION))
     {
       if (CPLUS_FAKE_CHILD (parent))
        {
+         char *name;
          struct value *temp = parent->parent->value;
-         value = value_struct_elt (&temp, NULL, name,
-                                   NULL, "cplus_structure");
-         release_value (value);
+
+         if (temp == NULL)
+           return NULL;
+
+         name = name_of_child (parent, index);
+         gdb_value_struct_elt (NULL, &value, &temp, NULL, name, NULL,
+                               "cplus_structure");
+         if (value != NULL)
+           release_value (value);
+
+         xfree (name);
        }
       else if (index >= TYPE_N_BASECLASSES (type))
        {
@@ -2312,10 +2348,11 @@ cplus_value_of_child (struct varobj *parent, int index)
          /* Baseclass */
          if (parent->value != NULL)
            {
-             struct value *temp;
+             struct value *temp = NULL;
 
-             if (TYPE_CODE (VALUE_TYPE (parent->value)) == TYPE_CODE_PTR
-                 || TYPE_CODE (VALUE_TYPE (parent->value)) == TYPE_CODE_REF)
+             /* No special processing for references is needed --
+                value_cast below handles references.  */
+             if (TYPE_CODE (value_type (parent->value)) == TYPE_CODE_PTR)
                {
                  if (!gdb_value_ind (parent->value, &temp))
                    return NULL;
@@ -2323,8 +2360,17 @@ cplus_value_of_child (struct varobj *parent, int index)
              else
                temp = parent->value;
 
-             value = value_cast (TYPE_FIELD_TYPE (type, index), temp);
-             release_value (value);
+             if (temp != NULL)
+               {
+                 value = value_cast (TYPE_FIELD_TYPE (type, index), temp);
+                 release_value (value);
+               }
+             else
+               {
+                 /* We failed to evaluate the parent's value, so don't even
+                    bother trying to evaluate this child. */
+                 return NULL;
+               }
            }
        }
     }
@@ -2340,21 +2386,31 @@ cplus_type_of_child (struct varobj *parent, int index)
 {
   struct type *type, *t;
 
-  t = get_type_deref (parent);
+  if (CPLUS_FAKE_CHILD (parent))
+    {
+      /* Looking for the type of a child of public, private, or protected. */
+      t = get_type_deref (parent->parent);
+    }
+  else
+    t = get_type_deref (parent);
+
   type = NULL;
   switch (TYPE_CODE (t))
     {
     case TYPE_CODE_STRUCT:
     case TYPE_CODE_UNION:
-      if (index >= TYPE_N_BASECLASSES (t))
+      if (CPLUS_FAKE_CHILD (parent))
        {
-         /* special */
-         return NULL;
+         char *name = cplus_name_of_child (parent, index);
+         type = lookup_struct_elt_type (t, name, 0);
+         xfree (name);
        }
+      else if (index < TYPE_N_BASECLASSES (t))
+       type = TYPE_FIELD_TYPE (t, index);
       else
        {
-         /* Baseclass */
-         type = TYPE_FIELD_TYPE (t, index);
+         /* special */
+         return NULL;
        }
       break;
 
@@ -2475,7 +2531,12 @@ _initialize_varobj (void)
   varobj_table = xmalloc (sizeof_table);
   memset (varobj_table, 0, sizeof_table);
 
-  add_show_from_set (add_set_cmd ("debugvarobj", class_maintenance, var_zinteger, (char *) &varobjdebug, "Set varobj debugging.\n\
-When non-zero, varobj debugging is enabled.", &setlist),
-                    &showlist);
+  add_setshow_zinteger_cmd ("debugvarobj", class_maintenance,
+                           &varobjdebug, _("\
+Set varobj debugging."), _("\
+Show varobj debugging."), _("\
+When non-zero, varobj debugging is enabled."),
+                           NULL,
+                           show_varobjdebug,
+                           &setlist, &showlist);
 }
This page took 0.05339 seconds and 4 git commands to generate.