]> Git Repo - binutils.git/blobdiff - gdb/varobj.c
* source.c (find_and_open_source): Try rewriting the source
[binutils.git] / gdb / varobj.c
index 25860cbd502cf63b7dd554e6dd06fee7e1abfef2..dc1c356a0b420a3460353e3358be0cc9ec74f9b5 100644 (file)
@@ -1,6 +1,6 @@
 /* Implementation of the GDB variable objects API.
 
-   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
@@ -32,6 +32,7 @@
 #include "gdb_string.h"
 
 #include "varobj.h"
+#include "vec.h"
 
 /* Non-zero if we want to see trace of varobj level stuff.  */
 
@@ -80,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. */
@@ -102,22 +107,20 @@ 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. 
-     Invariant: if type_changeable (this) is non-zero, the value is either
-     NULL, or not lazy.  */
+  /* The value of this expression or subexpression.  A NULL value
+     indicates there was an error getting this value.
+     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? */
-  int error;
-
   /* The number of (immediate) children this variable has */
   int num_children;
 
   /* 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;
@@ -127,29 +130,9 @@ struct varobj
 
   /* Was this variable updated via a varobj_set_value operation */
   int updated;
-};
-
-/* 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 */
 
-struct vstack
-{
-  struct varobj *var;
-  struct vstack *next;
+  /* Last print value.  */
+  char *print_value;
 };
 
 struct cpstack
@@ -179,14 +162,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);
@@ -205,10 +182,6 @@ static struct type *get_target_type (struct type *);
 
 static enum varobj_display_formats variable_default_display (struct varobj *);
 
-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);
@@ -234,7 +207,12 @@ 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 */
 
@@ -326,8 +304,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,
@@ -405,6 +382,11 @@ 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) */
 
@@ -518,7 +500,7 @@ varobj_create (char *objname,
 
       /* 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;
@@ -707,21 +689,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);
+
+      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) = child;
+      *((*childlist) + i) = existing;
     }
 
   /* End of list is marked by a NULL pointer */
@@ -810,7 +809,7 @@ varobj_set_value (struct varobj *var, char *expression)
   struct value *value;
   int saved_input_radix = input_radix;
 
-  if (var->value != NULL && variable_editable (var) && !var->error)
+  if (var->value != NULL && variable_editable (var))
     {
       char *s = expression;
       int i;
@@ -825,7 +824,7 @@ varobj_set_value (struct varobj *var, char *expression)
        }
 
       /* All types that are editable must also be changeable.  */
-      gdb_assert (type_changeable (var));
+      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));
@@ -908,12 +907,11 @@ install_new_value (struct varobj *var, struct value *value, int initial)
   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 = type_changeable (var);
+  changeable = varobj_value_is_changeable_p (var);
   need_to_fetch = changeable;
 
   /* We are not interested in the address of references, and given
@@ -945,27 +943,30 @@ install_new_value (struct varobj *var, struct value *value, int initial)
     {
       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 && changeable)
+  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.  */      
+        -var-update. So need to the varobj as changed.  */
       if (var->updated)
-       changed = 1;
+       {
+         xfree (var->print_value);
+         var->print_value = value_get_print_value (value, var->format);
+         changed = 1;
+       }
       else 
        {
          /* Try to compare the values.  That requires that both
@@ -976,29 +977,41 @@ install_new_value (struct varobj *var, struct value *value, int initial)
            /* Equal. */
            ;
          else if (var->value == NULL || value == NULL)
-           changed = 1;
+           {
+             xfree (var->print_value);
+             var->print_value = value_get_print_value (value, var->format);
+             changed = 1;
+           }
          else
            {
+             char *print_value;
              gdb_assert (!value_lazy (var->value));
              gdb_assert (!value_lazy (value));
-             
-             if (!value_contents_equal (var->value, value))
-               changed = 1;
+             print_value = value_get_print_value (value, var->format);
+
+             gdb_assert (var->print_value != NULL && print_value != NULL);
+             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
@@ -1028,8 +1041,8 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
   struct varobj **cv;
   struct varobj **templist = NULL;
   struct value *new;
-  struct vstack *stack = NULL;
-  struct vstack *result = NULL;
+  VEC (varobj_p) *stack = NULL;
+  VEC (varobj_p) *result = NULL;
   struct frame_id old_fid;
   struct frame_info *fi;
 
@@ -1038,7 +1051,7 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
     return -1;
 
   /*  Only root variables can be updated... */
-  if ((*varp)->root->rootvar != *varp)
+  if (!is_root_p (*varp))
     /* Not a root var */
     return -1;
 
@@ -1059,100 +1072,72 @@ varobj_update (struct varobj **varp, struct varobj ***changelist)
   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++;
-    }
+    VEC_safe_push (varobj_p, result, *varp);
 
   if (install_new_value ((*varp), new, type_changed))
     {
       /* 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);
-      vpush (&result, (*varp));
-      changed++;
+      VEC_safe_push (varobj_p, result, *varp);
     }
 
-  /* Initialize a stack */
-  vpush (&stack, NULL);
-
-  /* Push the root's children */
-  if ((*varp)->children != NULL)
+  if (new == NULL)
     {
-      struct varobj_child *c;
-      for (c = (*varp)->children; c != NULL; c = c->next)
-       vpush (&stack, c->child);
+      /* This means the varobj itself is out of scope.
+        Report it.  */
+      VEC_free (varobj_p, result);
+      return -1;
     }
 
+  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)
+      v = VEC_pop (varobj_p, stack);
+
+      /* 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)
        {
-         struct varobj_child *c;
-         for (c = v->children; c != NULL; c = c->next)
-           vpush (&stack, c->child);
+         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);
        }
 
-      /* Update this variable */
-      new = value_of_child (v->parent, v->index);
-      if (install_new_value (v, new, 0 /* type not changed */))
-       {
-         /* Note that it's changed */
-         vpush (&result, v);
-         v->updated = 0;
-         changed++;
+      /* 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;
+           }
        }
-
-      /* Get next child */
-      v = vpop (&stack);
     }
 
   /* 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;
     }
+  *cv = 0;
 
   if (type_changed)
     return -2;
@@ -1188,18 +1173,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)
@@ -1221,7 +1205,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)
@@ -1260,7 +1244,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)
@@ -1319,7 +1303,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)
@@ -1350,22 +1334,6 @@ 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 (strcmp (vc->child->name, name) == 0)
-       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)
@@ -1386,9 +1354,6 @@ create_child (struct varobj *parent, int index, char *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)
@@ -1401,51 +1366,8 @@ create_child (struct varobj *parent, int index, char *name)
                                                       child->index);
   install_new_value (child, value, 1);
 
-  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
 
 /*
@@ -1464,13 +1386,13 @@ new_variable (void)
   var->index = -1;
   var->type = NULL;
   var->value = NULL;
-  var->error = 0;
   var->num_children = -1;
   var->parent = NULL;
   var->children = NULL;
   var->format = 0;
   var->root = NULL;
   var->updated = 0;
+  var->print_value = NULL;
 
   return var;
 }
@@ -1496,7 +1418,7 @@ 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 (&var->root->exp);
       xfree (var->root);
@@ -1504,6 +1426,7 @@ free_variable (struct varobj *var)
 
   xfree (var->name);
   xfree (var->obj_name);
+  xfree (var->print_value);
   xfree (var);
 }
 
@@ -1536,7 +1459,8 @@ get_type (struct varobj *var)
   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)
 {
@@ -1544,9 +1468,13 @@ 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;
 }
@@ -1577,36 +1505,6 @@ variable_default_display (struct varobj *var)
   return FORMAT_NATURAL;
 }
 
-/* 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)
@@ -1714,7 +1612,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)
@@ -1786,6 +1684,27 @@ my_value_of_variable (struct varobj *var)
   return (*var->root->lang->value_of_variable) (var);
 }
 
+static char *
+value_get_print_value (struct value *value, enum varobj_display_formats format)
+{
+  long dummy;
+  struct ui_file *stb;
+  struct cleanup *old_chain;
+  char *thevalue;
+
+  if (value == NULL)
+    return NULL;
+
+  stb = mem_fileopen ();
+  old_chain = make_cleanup_ui_file_delete (stb);
+
+  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
@@ -1796,7 +1715,7 @@ my_value_of_variable (struct varobj *var)
    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;
@@ -1840,7 +1759,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:
@@ -1849,9 +1770,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
@@ -1889,73 +1810,164 @@ 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:
-      name = xstrprintf ("%d", index
-                        + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type)));
+      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 = xstrprintf ("*%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;
 
 
   /* Determine whether the variable is still around. */
-  if (var->root->valid_block == NULL)
+  if (var->root->valid_block == NULL || var->root->use_selected_frame)
     within_scope = 1;
   else
     {
-      reinit_frame_cache ();
       fi = frame_find_by_id (var->root->frame);
       within_scope = fi != NULL;
       /* FIXME: select_frame could fail */
@@ -1965,7 +1977,8 @@ c_value_of_root (struct varobj **var_handle)
          if (pc <  BLOCK_START (var->root->valid_block) ||
              pc >= BLOCK_END (var->root->valid_block))
            within_scope = 0;
-         select_frame (fi);
+         else
+           select_frame (fi);
        }         
     }
 
@@ -1976,11 +1989,8 @@ c_value_of_root (struct varobj **var_handle)
          go on */
       if (gdb_evaluate_expression (var->root->exp, &new_val))
        {
-         var->error = 0;
          release_value (new_val);
        }
-      else
-       var->error = 1;
 
       return new_val;
     }
@@ -1991,109 +2001,19 @@ 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;
-  int real_index;
-
-  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:
-         real_index = index + TYPE_LOW_BOUND (TYPE_INDEX_TYPE (type));
-#if 0
-         /* This breaks if the array lives in a (vector) register. */
-         value = value_slice (temp, real_index, 1);
-         temp = value_coerce_array (value);
-         gdb_value_ind (temp, &value);
-#else
-         indval = value_from_longest (builtin_type_int, (LONGEST) real_index);
-         gdb_value_subscript (temp, indval, &value);
-#endif
-         break;
-
-       case TYPE_CODE_STRUCT:
-       case TYPE_CODE_UNION:
-         gdb_value_struct_elt (NULL, &value, &temp, NULL, name, NULL,
-                               "vstructure");
-         break;
-
-       case TYPE_CODE_PTR:
-         switch (TYPE_CODE (target))
-           {
-           case TYPE_CODE_STRUCT:
-           case TYPE_CODE_UNION:
-             gdb_value_struct_elt (NULL, &value, &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);
 
-  xfree (name);
   return value;
 }
 
 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 = get_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 (get_target_type (parent->type)))
-       {
-       case TYPE_CODE_STRUCT:
-       case TYPE_CODE_UNION:
-         type = lookup_struct_elt_type (parent->type, name, 0);
-         break;
-
-       default:
-         type = get_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;
-    }
-
-  xfree (name);
+  struct type *type = NULL;
+  c_describe_child (parent, index, NULL, NULL, &type);
   return type;
 }
 
@@ -2154,19 +2074,10 @@ c_value_of_variable (struct varobj *var)
          }
        else
          {
-           long dummy;
-           struct ui_file *stb = mem_fileopen ();
-           struct cleanup *old_chain = make_cleanup_ui_file_delete (stb);
-           char *thevalue;
-
-           gdb_assert (type_changeable (var));
+           gdb_assert (varobj_value_is_changeable_p (var));
            gdb_assert (!value_lazy (var->value));
-           common_val_print (var->value, stb,
-                             format_code[(int) var->format], 1, 0, 0);
-           thevalue = ui_file_xstrdup (stb, &dummy);
-           do_cleanups (old_chain);
-       return thevalue;
-      }
+           return value_get_print_value (var->value, var->format);
+         }
       }
     }
 }
This page took 0.055353 seconds and 4 git commands to generate.