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).