Move duplicated code into new files
[deliverable/binutils-gdb.git] / gdb / varobj.c
index 0467a7930caf53958d6998b203f866d2813e56f2..cf1b8a8800c15b1ca6df76f00c969ee9dffe9f9d 100644 (file)
@@ -33,6 +33,7 @@
 #include "vec.h"
 #include "gdbthread.h"
 #include "inferior.h"
+#include "varobj-iter.h"
 
 #if HAVE_PYTHON
 #include "python/python.h"
@@ -108,17 +109,6 @@ struct varobj_root
   struct varobj_root *next;
 };
 
-/* A node or item of varobj, composed of the name and the value.  */
-
-struct varobj_item
-{
-  /* Name of this item.  */
-  char *name;
-
-  /* Value of this item.  */
-  struct value *value;
-};
-
 /* Dynamic part of varobj.  */
 
 struct varobj_dynamic
@@ -140,14 +130,14 @@ struct varobj_dynamic
 
   /* The iterator returned by the printer's 'children' method, or NULL
      if not available.  */
-  PyObject *child_iter;
+  struct varobj_iter *child_iter;
 
   /* We request one extra item from the iterator, so that we can
      report to the caller whether there are more items than we have
      already reported.  However, we don't want to install this value
      when we read it, because that will mess up future updates.  So,
      we stash it here instead.  */
-  PyObject *saved_item;
+  varobj_item *saved_item;
 };
 
 struct cpstack
@@ -222,13 +212,9 @@ static char *my_value_of_variable (struct varobj *var,
 
 static int is_root_p (struct varobj *var);
 
-#if HAVE_PYTHON
-
 static struct varobj *varobj_add_child (struct varobj *var,
                                        struct varobj_item *item);
 
-#endif /* HAVE_PYTHON */
-
 /* Private data */
 
 /* Mappings of varobj_display_formats enums to gdb's format codes.  */
@@ -256,7 +242,7 @@ is_root_p (struct varobj *var)
 #ifdef HAVE_PYTHON
 /* Helper function to install a Python environment suitable for
    use during operations on VAR.  */
-static struct cleanup *
+struct cleanup *
 varobj_ensure_python_env (struct varobj *var)
 {
   return ensure_python_env (var->root->exp->gdbarch,
@@ -313,7 +299,7 @@ varobj_create (char *objname,
     {
       struct frame_info *fi;
       struct frame_id old_id = null_frame_id;
-      struct block *block;
+      const struct block *block;
       const char *p;
       struct value *value = NULL;
       volatile struct gdb_exception except;
@@ -711,8 +697,6 @@ varobj_restrict_range (VEC (varobj_p) *children, int *from, int *to)
     }
 }
 
-#if HAVE_PYTHON
-
 /* A helper for update_dynamic_varobj_children that installs a new
    child when needed.  */
 
@@ -757,6 +741,8 @@ install_dynamic_child (struct varobj *var,
     }
 }
 
+#if HAVE_PYTHON
+
 static int
 dynamic_varobj_has_child_method (struct varobj *var)
 {
@@ -772,9 +758,36 @@ dynamic_varobj_has_child_method (struct varobj *var)
   do_cleanups (back_to);
   return result;
 }
+#endif
+
+/* A factory for creating dynamic varobj's iterators.  Returns an
+   iterator object suitable for iterating over VAR's children.  */
 
+static struct varobj_iter *
+varobj_get_iterator (struct varobj *var)
+{
+#if HAVE_PYTHON
+  if (var->dynamic->pretty_printer)
+    return py_varobj_get_iterator (var, var->dynamic->pretty_printer);
 #endif
 
+  gdb_assert_not_reached (_("\
+requested an iterator from a non-dynamic varobj"));
+}
+
+/* Release and clear VAR's saved item, if any.  */
+
+static void
+varobj_clear_saved_item (struct varobj_dynamic *var)
+{
+  if (var->saved_item != NULL)
+    {
+      value_free (var->saved_item->value);
+      xfree (var->saved_item);
+      var->saved_item = NULL;
+    }
+}
+
 static int
 update_dynamic_varobj_children (struct varobj *var,
                                VEC (varobj_p) **changed,
@@ -786,49 +799,21 @@ update_dynamic_varobj_children (struct varobj *var,
                                int from,
                                int to)
 {
-#if HAVE_PYTHON
-  struct cleanup *back_to;
-  PyObject *children;
   int i;
-  PyObject *printer = var->dynamic->pretty_printer;
-
-  if (!gdb_python_initialized)
-    return 0;
-
-  back_to = varobj_ensure_python_env (var);
 
   *cchanged = 0;
-  if (!PyObject_HasAttr (printer, gdbpy_children_cst))
-    {
-      do_cleanups (back_to);
-      return 0;
-    }
 
   if (update_children || var->dynamic->child_iter == NULL)
     {
-      children = PyObject_CallMethodObjArgs (printer, gdbpy_children_cst,
-                                            NULL);
+      varobj_iter_delete (var->dynamic->child_iter);
+      var->dynamic->child_iter = varobj_get_iterator (var);
 
-      if (!children)
-       {
-         gdbpy_print_stack ();
-         error (_("Null value returned for children"));
-       }
+      varobj_clear_saved_item (var->dynamic);
 
-      make_cleanup_py_decref (children);
+      i = 0;
 
-      Py_XDECREF (var->dynamic->child_iter);
-      var->dynamic->child_iter = PyObject_GetIter (children);
       if (var->dynamic->child_iter == NULL)
-       {
-         gdbpy_print_stack ();
-         error (_("Could not get children iterator"));
-       }
-
-      Py_XDECREF (var->dynamic->saved_item);
-      var->dynamic->saved_item = NULL;
-
-      i = 0;
+       return 0;
     }
   else
     i = VEC_length (varobj_p, var->children);
@@ -837,104 +822,52 @@ update_dynamic_varobj_children (struct varobj *var,
      are more children.  */
   for (; to < 0 || i < to + 1; ++i)
     {
-      PyObject *item;
-      int force_done = 0;
+      varobj_item *item;
 
       /* See if there was a leftover from last time.  */
-      if (var->dynamic->saved_item)
+      if (var->dynamic->saved_item != NULL)
        {
          item = var->dynamic->saved_item;
          var->dynamic->saved_item = NULL;
        }
       else
-       item = PyIter_Next (var->dynamic->child_iter);
-
-      if (!item)
        {
-         /* Normal end of iteration.  */
-         if (!PyErr_Occurred ())
-           break;
-
-         /* If we got a memory error, just use the text as the
-            item.  */
-         if (PyErr_ExceptionMatches (gdbpy_gdb_memory_error))
-           {
-             PyObject *type, *value, *trace;
-             char *name_str, *value_str;
-
-             PyErr_Fetch (&type, &value, &trace);
-             value_str = gdbpy_exception_to_string (type, value);
-             Py_XDECREF (type);
-             Py_XDECREF (value);
-             Py_XDECREF (trace);
-             if (!value_str)
-               {
-                 gdbpy_print_stack ();
-                 break;
-               }
-
-             name_str = xstrprintf ("<error at %d>", i);
-             item = Py_BuildValue ("(ss)", name_str, value_str);
-             xfree (name_str);
-             xfree (value_str);
-             if (!item)
-               {
-                 gdbpy_print_stack ();
-                 break;
-               }
-
-             force_done = 1;
-           }
-         else
-           {
-             /* Any other kind of error.  */
-             gdbpy_print_stack ();
-             break;
-           }
+         item = varobj_iter_next (var->dynamic->child_iter);
+         /* Release vitem->value so its lifetime is not bound to the
+            execution of a command.  */
+         if (item != NULL && item->value != NULL)
+           release_value_or_incref (item->value);
        }
 
+      if (item == NULL)
+       {
+         /* Iteration is done.  Remove iterator from VAR.  */
+         varobj_iter_delete (var->dynamic->child_iter);
+         var->dynamic->child_iter = NULL;
+         break;
+       }
       /* We don't want to push the extra child on any report list.  */
       if (to < 0 || i < to)
        {
-         PyObject *py_v;
-         const char *name;
-         struct varobj_item varobj_item;
-         struct cleanup *inner;
          int can_mention = from < 0 || i >= from;
 
-         inner = make_cleanup_py_decref (item);
-
-         if (!PyArg_ParseTuple (item, "sO", &name, &py_v))
-           {
-             gdbpy_print_stack ();
-             error (_("Invalid item from the child list"));
-           }
-
-         varobj_item.value = convert_value_from_python (py_v);
-         if (varobj_item.value == NULL)
-           gdbpy_print_stack ();
-         varobj_item.name = xstrdup (name);
-
          install_dynamic_child (var, can_mention ? changed : NULL,
                                 can_mention ? type_changed : NULL,
                                 can_mention ? new : NULL,
                                 can_mention ? unchanged : NULL,
                                 can_mention ? cchanged : NULL, i,
-                                &varobj_item);
-         do_cleanups (inner);
+                                item);
+
+         xfree (item);
        }
       else
        {
-         Py_XDECREF (var->dynamic->saved_item);
          var->dynamic->saved_item = item;
 
          /* We want to truncate the child list just before this
             element.  */
          break;
        }
-
-      if (force_done)
-       break;
     }
 
   if (i < VEC_length (varobj_p, var->children))
@@ -953,13 +886,8 @@ update_dynamic_varobj_children (struct varobj *var,
     *cchanged = 1;
 
   var->num_children = VEC_length (varobj_p, var->children);
-  do_cleanups (back_to);
 
   return 1;
-#else
-  gdb_assert_not_reached ("should never be called if Python is not enabled");
-#endif
 }
 
 int
@@ -967,7 +895,7 @@ varobj_get_num_children (struct varobj *var)
 {
   if (var->num_children == -1)
     {
-      if (var->dynamic->pretty_printer != NULL)
+      if (varobj_is_dynamic_p (var))
        {
          int dummy;
 
@@ -994,7 +922,7 @@ varobj_list_children (struct varobj *var, int *from, int *to)
 
   var->dynamic->children_requested = 1;
 
-  if (var->dynamic->pretty_printer != NULL)
+  if (varobj_is_dynamic_p (var))
     {
       /* This, in theory, can result in the number of children changing without
         frontend noticing.  But well, calling -var-list-children on the same
@@ -1036,8 +964,6 @@ varobj_list_children (struct varobj *var, int *from, int *to)
   return var->children;
 }
 
-#if HAVE_PYTHON
-
 static struct varobj *
 varobj_add_child (struct varobj *var, struct varobj_item *item)
 {
@@ -1049,8 +975,6 @@ varobj_add_child (struct varobj *var, struct varobj_item *item)
   return v;
 }
 
-#endif /* HAVE_PYTHON */
-
 /* Obtain the type of an object Variable as a string similar to the one gdb
    prints on the console.  */
 
@@ -1080,18 +1004,18 @@ varobj_get_gdb_type (struct varobj *var)
 static int
 is_path_expr_parent (struct varobj *var)
 {
-  struct type *type;
-
-  /* "Fake" children are not path_expr parents.  */
-  if (CPLUS_FAKE_CHILD (var))
-    return 0;
+  gdb_assert (var->root->lang_ops->is_path_expr_parent != NULL);
+  return var->root->lang_ops->is_path_expr_parent (var);
+}
 
-  type = varobj_get_value_type (var);
+/* Is VAR a path expression parent, i.e., can it be used to construct
+   a valid path expression?  By default we assume any VAR can be a path
+   parent.  */
 
-  /* Anonymous unions and structs are also not path_expr parents.  */
-  return !((TYPE_CODE (type) == TYPE_CODE_STRUCT
-           || TYPE_CODE (type) == TYPE_CODE_UNION)
-          && TYPE_NAME (type) == NULL);
+int
+varobj_default_is_path_expr_parent (struct varobj *var)
+{
+  return 1;
 }
 
 /* Return the path expression parent for VAR.  */
@@ -1142,8 +1066,10 @@ varobj_get_attributes (struct varobj *var)
   return attributes;
 }
 
+/* Return true if VAR is a dynamic varobj.  */
+
 int
-varobj_pretty_printed_p (struct varobj *var)
+varobj_is_dynamic_p (struct varobj *var)
 {
   return var->dynamic->pretty_printer != NULL;
 }
@@ -1245,7 +1171,7 @@ install_visualizer (struct varobj_dynamic *var, PyObject *constructor,
   Py_XDECREF (var->pretty_printer);
   var->pretty_printer = visualizer;
 
-  Py_XDECREF (var->child_iter);
+  varobj_iter_delete (var->child_iter);
   var->child_iter = NULL;
 }
 
@@ -1798,10 +1724,9 @@ varobj_update (struct varobj **varp, int explicit)
            }
        }
 
-      /* We probably should not get children of a varobj that has a
-        pretty-printer, but for which -var-list-children was never
-        invoked.  */
-      if (v->dynamic->pretty_printer != NULL)
+      /* We probably should not get children of a dynamic varobj, but
+        for which -var-list-children was never invoked.  */
+      if (varobj_is_dynamic_p (v))
        {
          VEC (varobj_p) *changed = 0, *type_changed = 0, *unchanged = 0;
          VEC (varobj_p) *new = 0;
@@ -2233,12 +2158,12 @@ free_variable (struct varobj *var)
 
       Py_XDECREF (var->dynamic->constructor);
       Py_XDECREF (var->dynamic->pretty_printer);
-      Py_XDECREF (var->dynamic->child_iter);
-      Py_XDECREF (var->dynamic->saved_item);
       do_cleanups (cleanup);
     }
 #endif
 
+  varobj_iter_delete (var->dynamic->child_iter);
+  varobj_clear_saved_item (var->dynamic);
   value_free (var->value);
 
   /* Free the expression if this is a root variable.  */
This page took 0.029065 seconds and 4 git commands to generate.