diff options
author | Yao Qi <yao@codesourcery.com> | 2013-08-30 09:44:46 +0800 |
---|---|---|
committer | Yao Qi <yao@codesourcery.com> | 2014-06-12 15:27:15 +0800 |
commit | e525021603958709381fc4dc296cc2586aaa5dd7 (patch) | |
tree | 329c330c7a6febccb5e29d93fd96e06fecea512f /gdb/varobj.c | |
parent | 5a2e0d6e89f69f0c3d013cf43f3bd3d97b5e628b (diff) | |
download | gdb-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.c | 112 |
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; } |