aboutsummaryrefslogtreecommitdiff
path: root/gdb/varobj.c
diff options
context:
space:
mode:
authorYao Qi <yao@codesourcery.com>2013-08-30 09:44:46 +0800
committerYao Qi <yao@codesourcery.com>2014-06-12 15:27:15 +0800
commite525021603958709381fc4dc296cc2586aaa5dd7 (patch)
tree329c330c7a6febccb5e29d93fd96e06fecea512f /gdb/varobj.c
parent5a2e0d6e89f69f0c3d013cf43f3bd3d97b5e628b (diff)
downloadgdb-e525021603958709381fc4dc296cc2586aaa5dd7.zip
gdb-e525021603958709381fc4dc296cc2586aaa5dd7.tar.gz
gdb-e525021603958709381fc4dc296cc2586aaa5dd7.tar.bz2
Generalize varobj iterator
This patch generalizes varobj iterator, in a python-independent way. Note varobj_item is still a typedef of PyObject, we can only focus on API changes, and leave the data type changes to the next patch. As a result, we include "varobj-iter.h" after the typedef of PyObject in varobj.c, but it is an intermediate state. Finally, varobj-iter.h is independent of PyObject. This change is helpful to move some python-related code out of varobj.c. V2: - Fix a missing cleanup. - Fix typos. - Use XNEW. - Check against NULL explicitly. - Update copyright year for new added files. V3: - Call PyGILState_Ensure before Py_XDECREF. - Use CPYCHECKER_STEALS_REFERENCE_TO_ARG. - Code indentation. V4: - use varobj_ensure_python_env instead of PyGILState_Ensure. gdb: 2014-06-12 Pedro Alves <pedro@codesourcery.com> Yao Qi <yao@codesourcery.com> * Makefile.in (SUBDIR_PYTHON_OBS): Add "py-varobj.o". (SUBDIR_PYTHON_SRCS): Add "python/py-varobj.c". (HFILES_NO_SRCDIR): Add "varobj-iter.h". (py-varobj.o): New rule. * python/py-varobj.c: New file. * python/python-internal.h (py_varobj_get_iterator): Declare. * varobj-iter.h: New file. * varobj.c: Include "varobj-iter.h" (struct varobj) <child_iter>: Change its type from "PyObject *" to "struct varobj_iter *". <saved_item>: Likewise. [HAVE_PYTHON] (varobj_ensure_python_env): Make it extern. [HAVE_PYTHON] (varobj_get_iterator): New function. (update_dynamic_varobj_children) [HAVE_PYTHON]: Move python-specific code to python/py-varobj.c. (install_visualizer): Call varobj_iter_delete instead of Py_XDECREF. * varobj.h (varobj_ensure_python_env): Declare.
Diffstat (limited to 'gdb/varobj.c')
-rw-r--r--gdb/varobj.c112
1 files changed, 35 insertions, 77 deletions
diff --git a/gdb/varobj.c b/gdb/varobj.c
index 0467a79..02cce5a 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -41,6 +41,8 @@
typedef int PyObject;
#endif
+#include "varobj-iter.h"
+
/* Non-zero if we want to see trace of varobj level stuff. */
unsigned int varobjdebug = 0;
@@ -140,14 +142,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
@@ -256,7 +258,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,
@@ -773,6 +775,19 @@ dynamic_varobj_has_child_method (struct varobj *var)
return result;
}
+/* 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 (var->dynamic->pretty_printer)
+ return py_varobj_get_iterator (var, var->dynamic->pretty_printer);
+
+ gdb_assert_not_reached (_("\
+requested an iterator from a non-dynamic varobj"));
+}
+
#endif
static int
@@ -788,9 +803,7 @@ update_dynamic_varobj_children (struct varobj *var,
{
#if HAVE_PYTHON
struct cleanup *back_to;
- PyObject *children;
int i;
- PyObject *printer = var->dynamic->pretty_printer;
if (!gdb_python_initialized)
return 0;
@@ -798,37 +811,22 @@ update_dynamic_varobj_children (struct varobj *var,
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"));
- }
+ Py_XDECREF (var->dynamic->saved_item);
+ var->dynamic->saved_item = NULL;
- 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"));
+ do_cleanups (back_to);
+ return 0;
}
-
- Py_XDECREF (var->dynamic->saved_item);
- var->dynamic->saved_item = NULL;
-
- i = 0;
}
else
i = VEC_length (varobj_p, var->children);
@@ -838,7 +836,6 @@ update_dynamic_varobj_children (struct varobj *var,
for (; to < 0 || i < to + 1; ++i)
{
PyObject *item;
- int force_done = 0;
/* See if there was a leftover from last time. */
if (var->dynamic->saved_item)
@@ -847,52 +844,17 @@ update_dynamic_varobj_children (struct varobj *var,
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);
}
+ 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)
{
@@ -932,9 +894,6 @@ update_dynamic_varobj_children (struct varobj *var,
element. */
break;
}
-
- if (force_done)
- break;
}
if (i < VEC_length (varobj_p, var->children))
@@ -953,9 +912,8 @@ update_dynamic_varobj_children (struct varobj *var,
*cchanged = 1;
var->num_children = VEC_length (varobj_p, var->children);
-
- do_cleanups (back_to);
+ do_cleanups (back_to);
return 1;
#else
gdb_assert_not_reached ("should never be called if Python is not enabled");
@@ -1245,7 +1203,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;
}