From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8466 invoked by alias); 2 Apr 2012 15:01:45 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 8438 invoked by uid 9514); 2 Apr 2012 15:01:43 -0000 Date: Mon, 02 Apr 2012 15:01:00 -0000 Message-ID: <20120402150143.8422.qmail@sourceware.org> From: pmuldoon@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] archer-pmuldoon-python-backtrace: Implement gdb.FrameIterator X-Git-Refname: refs/heads/archer-pmuldoon-python-backtrace X-Git-Reftype: branch X-Git-Oldrev: ec9f7997ebf301d320fe4c9293788f7cc55feac1 X-Git-Newrev: 313ec1898851d0162bb917768a2fa517220649fa X-SW-Source: 2012-q2/txt/msg00003.txt.bz2 List-Id: 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 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); } @@ -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.