public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM] archer-pmuldoon-python-backtrace: Implement gdb.FrameIterator
@ 2012-04-02 15:01 pmuldoon
0 siblings, 0 replies; only message in thread
From: pmuldoon @ 2012-04-02 15:01 UTC (permalink / raw)
To: archer-commits
The branch, archer-pmuldoon-python-backtrace has been updated
via 313ec1898851d0162bb917768a2fa517220649fa (commit)
from ec9f7997ebf301d320fe4c9293788f7cc55feac1 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email.
- Log -----------------------------------------------------------------
commit 313ec1898851d0162bb917768a2fa517220649fa
Author: Phil Muldoon <pmuldoon@redhat.com>
Date: Mon Apr 2 16:01:20 2012 +0100
Implement gdb.FrameIterator
-----------------------------------------------------------------------
Summary of changes:
gdb/python/py-frame.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 150 insertions(+), 4 deletions(-)
First 500 lines of diff:
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index 12a54e8..f02c9a1 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -29,7 +29,7 @@
#include "symfile.h"
#include "objfiles.h"
-typedef struct {
+typedef struct frapy_type_object {
PyObject_HEAD
struct frame_id frame_id;
struct gdbarch *gdbarch;
@@ -45,6 +45,13 @@ typedef struct {
int frame_id_is_next;
} frame_object;
+/* A frame iterator object. */
+typedef struct {
+ PyObject_HEAD
+ struct frapy_type_object *source;
+ struct frapy_type_object *current;
+} frame_iterator_object;
+
/* Require a valid frame. This must be called inside a TRY_CATCH, or
another context in which a gdb exception is allowed. */
#define FRAPY_REQUIRE_VALID(frame_obj, frame) \
@@ -54,6 +61,8 @@ typedef struct {
error (_("Frame is invalid.")); \
} while (0)
+static PyTypeObject frame_iterator_object_type;
+
/* Returns the frame_info object corresponding to the given Python Frame
object. If the frame doesn't exist anymore (the frame id doesn't
correspond to any frame in the inferior), returns NULL. */
@@ -589,6 +598,95 @@ frapy_richcompare (PyObject *self, PyObject *other, int op)
Py_RETURN_FALSE;
}
+static PyObject *
+frapy_iter (PyObject *self)
+{
+ struct frame_info *fi;
+ frame_iterator_object *frame_iter_obj;
+ FRAPY_REQUIRE_VALID (self, fi);
+
+ frame_iter_obj = PyObject_New (frame_iterator_object,
+ &frame_iterator_object_type);
+ if (frame_iter_obj == NULL)
+ return NULL;
+
+ Py_INCREF (self);
+ frame_iter_obj->source = (frame_object *) self;
+ frame_iter_obj->current = NULL;
+ return (PyObject *) frame_iter_obj;
+}
+
+
+static PyObject *
+frapy_iternext (PyObject *self)
+{
+ frame_iterator_object *iter_obj = (frame_iterator_object *) self;
+ PyObject *result;
+ struct frame_info *prev;
+
+ /* If the user does: foo = gdb.FrameIterator(gdb.newest_frame()) the
+ next iteration will return the next oldest frame. But we want to
+ account for the first frame in iterations also. */
+ if (iter_obj->current != NULL)
+ result = frapy_older ((PyObject *)iter_obj->current, NULL);
+ else
+ result = (PyObject *) iter_obj->source;
+
+ /* Iteration stops on error (preserve the exception), or when
+ frapy_older returns None. */
+ if (result == NULL)
+ return NULL;
+
+ iter_obj->current = (frame_object *)result;
+ if (result == Py_None)
+ return NULL;
+
+ return result;
+}
+
+/* Return a reference to the block iterator. */
+static PyObject *
+frapy_frame_iter (PyObject *self)
+{
+ frame_iterator_object *iter_obj = (frame_iterator_object *) self;
+
+ Py_INCREF (self);
+ return self;
+}
+
+static void
+frapy_iterator_dealloc (PyObject *obj)
+{
+ frame_iterator_object *iter_obj = (frame_iterator_object *) obj;
+
+ Py_XDECREF (iter_obj->current);
+}
+
+static int
+frapy_frame_iter_init (PyObject *self, PyObject *args, PyObject *kw)
+{
+ static char *keywords[] = { "frame", NULL };
+ frame_iterator_object *iter_obj = (frame_iterator_object *) self;
+ PyObject *frame;
+
+ if (! PyArg_ParseTupleAndKeywords (args, kw, "O",
+ keywords, &frame))
+ return -1;
+
+ iter_obj->current = NULL;
+ iter_obj->source = NULL;
+
+ if (frapy_is_valid (frame, NULL))
+ {
+ Py_INCREF (frame);
+ iter_obj->source = (frame_object *)frame;
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
/* Sets up the Frame API in the gdb module. */
void
@@ -598,6 +696,10 @@ gdbpy_initialize_frames (void)
if (PyType_Ready (&frame_object_type) < 0)
return;
+ frame_iterator_object_type.tp_new = PyType_GenericNew;
+ if (PyType_Ready (&frame_iterator_object_type) < 0)
+ return;
+
/* Note: These would probably be best exposed as class attributes of
Frame, but I don't know how to do it except by messing with the
type's dictionary. That seems too messy. */
@@ -617,7 +719,10 @@ gdbpy_initialize_frames (void)
#undef SET
Py_INCREF (&frame_object_type);
+ Py_INCREF (&frame_iterator_object_type);
+
PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type);
+ PyModule_AddObject (gdb_module, "FrameIterator", (PyObject *) &frame_iterator_object_type);
}
\f
@@ -682,14 +787,14 @@ PyTypeObject frame_object_type = {
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+ Py_TPFLAGS_DEFAULT| Py_TPFLAGS_HAVE_ITER, /* tp_flags */
"GDB frame object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
frapy_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
+ frapy_iter, /* tp_iter */
+ 0, /* tp_iternext */
frame_object_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
@@ -701,3 +806,44 @@ PyTypeObject frame_object_type = {
0, /* tp_init */
0, /* tp_alloc */
};
+
+static PyTypeObject frame_iterator_object_type = {
+ PyObject_HEAD_INIT (NULL)
+ 0, /*ob_size*/
+ "gdb.FrameIterator", /*tp_name*/
+ sizeof (frame_iterator_object), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ frapy_iterator_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
+ "GDB frame iterator object", /*tp_doc */
+ 0, /*tp_traverse */
+ 0, /*tp_clear */
+ 0, /*tp_richcompare */
+ 0, /*tp_weaklistoffset */
+ frapy_frame_iter, /*tp_iter */
+ frapy_iternext, /*tp_iternext */
+ 0, /*tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ frapy_frame_iter_init, /* tp_init */
+ 0, /* tp_alloc */
+};
hooks/post-receive
--
Repository for Project Archer.
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2012-04-02 15:01 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-02 15:01 [SCM] archer-pmuldoon-python-backtrace: Implement gdb.FrameIterator pmuldoon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).