[PATCH 3/3] Add a gdb.events.frame_change event registry

Maxime Coste
2013-04-26T19:03:41Z

---
gdb/Makefile.in | 6 ++++
gdb/python/py-events.h | 1 +
gdb/python/py-evts.c | 3 ++
gdb/python/py-framechangeevent.c | 76 ++++++++++++++++++++++++++++++++++++++++
gdb/python/py-framechangeevent.h | 29 +++++++++++++++
gdb/python/python-internal.h | 1 +
gdb/python/python.c | 18 ++++++++++
7 files changed, 134 insertions(+)
create mode 100644 gdb/python/py-framechangeevent.c
create mode 100644 gdb/python/py-framechangeevent.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index c891c83..748d0ca 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -288,6 +288,7 @@ SUBDIR_PYTHON_OBS = \
py-exitedevent.o \
py-finishbreakpoint.o \
py-frame.o \
+ py-framechangeevent.o \
py-function.o \
py-gdb-readline.o \
py-inferior.o \
@@ -322,6 +323,7 @@ SUBDIR_PYTHON_SRCS = \
python/py-exitedevent.c \
python/py-finishbreakpoint.c \
python/py-frame.c \
+ python/py-framechangeevent.c \
python/py-function.c \
python/py-gdb-readline.c \
python/py-inferior.c \
@@ -2141,6 +2143,10 @@ py-frame.o: $(srcdir)/python/py-frame.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-frame.c
$(POSTCOMPILE)

+py-framechangeevent.o: $(srcdir)/python/py-framechangeevent.c
+ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-framechangeevent.c
+ $(POSTCOMPILE)
+
py-function.o: $(srcdir)/python/py-function.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-function.c
$(POSTCOMPILE)
diff --git a/gdb/python/py-events.h b/gdb/python/py-events.h
index 537bcc9..a61858c 100644
--- a/gdb/python/py-events.h
+++ b/gdb/python/py-events.h
@@ -45,6 +45,7 @@ typedef struct
eventregistry_object *cont;
eventregistry_object *exited;
eventregistry_object *new_objfile;
+ eventregistry_object *frame_change;

PyObject *module;

diff --git a/gdb/python/py-evts.c b/gdb/python/py-evts.c
index 4c079e2..f4d1fbf 100644
--- a/gdb/python/py-evts.c
+++ b/gdb/python/py-evts.c
@@ -81,6 +81,9 @@ gdbpy_initialize_py_events (void)
if (add_new_registry (&gdb_py_events.new_objfile, "new_objfile") < 0)
goto fail;

+ if (add_new_registry (&gdb_py_events.frame_change, "frame_change") < 0)
+ goto fail;
+
#ifndef IS_PY3K
Py_INCREF (gdb_py_events.module);
#endif
diff --git a/gdb/python/py-framechangeevent.c b/gdb/python/py-framechangeevent.c
new file mode 100644
index 0000000..f18ef39
--- /dev/null
+++ b/gdb/python/py-framechangeevent.c
@@ -0,0 +1,76 @@
+/* Python interface to inferior frame events.
+
+ Copyright (C) 2009-2013 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "py-framechangeevent.h"
+
+static PyTypeObject frame_change_event_object_type;
+
+static PyObject *
+create_frame_change_event_object (struct frame_info *frame)
+{
+ PyObject *frame_change_event;
+ PyObject *py_frame;
+
+ frame_change_event = create_event_object (&frame_change_event_object_type);
+ if (!frame_change_event)
+ goto fail;
+
+ /* Note that frame_to_frame_object returns a borrowed reference,
+ so we don't need a decref here. */
+ py_frame = frame ? frame_info_to_frame_object (frame) : Py_None;
+ if (!py_frame || evpy_add_attribute (frame_change_event,
+ "frame",
+ py_frame) < 0)
+ goto fail;
+
+ return frame_change_event;
+
+ fail:
+ Py_XDECREF (frame_change_event);
+ return NULL;
+}
+
+/* Callback observers when a frame event occurs. This function will create a
+ new Python frame event object. If only a specific thread is frameped the
+ thread object of the event will be set to that thread. Otherwise, if all
+ threads are frameped thread object will be set to None.
+ return 0 if the event was created and emitted successfully otherwise
+ returns -1. */
+
+int
+emit_frame_change_event (struct frame_info* frame)
+{
+ PyObject *frame_change_event_obj = NULL;
+
+ if (evregpy_no_listeners_p (gdb_py_events.frame_change))
+ return 0;
+
+ frame_change_event_obj = create_frame_change_event_object(frame);
+ if (frame_change_event_obj)
+ return evpy_emit_event (frame_change_event_obj, gdb_py_events.frame_change);
+ return -1;
+}
+
+GDBPY_NEW_EVENT_TYPE (frame_change,
+ "gdb.FrameChangeEvent",
+ "FrameChangeEvent",
+ "GDB frame event object",
+ event_object_type,
+ static);
diff --git a/gdb/python/py-framechangeevent.h b/gdb/python/py-framechangeevent.h
new file mode 100644
index 0000000..e7564b0
--- /dev/null
+++ b/gdb/python/py-framechangeevent.h
@@ -0,0 +1,29 @@
+/* Python interface to inferior events.
+
+ Copyright (C) 2009-2013 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PY_FRAMECHANGEEVENT_H
+#define GDB_PY_FRAMECHANGEEVENT_H
+
+#include "py-event.h"
+
+extern void frame_change_evpy_dealloc (PyObject *self);
+
+extern int emit_frame_change_event (struct frame_info* frame);
+
+#endif /* GDB_PY_FRAMECHANGEEVENT_H */
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index ea97226..676096d 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -301,6 +301,7 @@ void gdbpy_initialize_continue_event (void);
void gdbpy_initialize_exited_event (void);
void gdbpy_initialize_thread_event (void);
void gdbpy_initialize_new_objfile_event (void);
+void gdbpy_initialize_frame_change_event (void);
void gdbpy_initialize_arch (void);

struct cleanup *make_cleanup_py_decref (PyObject *py);
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 67d06e5..ded99c7 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -72,6 +72,7 @@ static const char *gdbpy_should_print_stack = python_excp_message;
#include "observer.h"
#include "interps.h"
#include "event-top.h"
+#include "py-framechangeevent.h"

static PyMethodDef GdbMethods[];

@@ -881,6 +882,21 @@ gdbpy_initialize_events (void)
}
}

+
+static void
+python_frame_changed (struct frame_info *frame)
+{
+ struct cleanup *cleanup;
+ struct gdbarch *arch = frame ? get_frame_arch(frame) : target_gdbarch();
+
+ cleanup = ensure_python_env (arch, current_language);
+
+ if (emit_frame_change_event (frame) < 0)
+ gdbpy_print_stack ();
+
+ do_cleanups (cleanup);
+}
+
\f

static void
@@ -1630,9 +1646,11 @@ message == an error message without a stack will be printed."),
gdbpy_initialize_exited_event ();
gdbpy_initialize_thread_event ();
gdbpy_initialize_new_objfile_event () ;
+ gdbpy_initialize_frame_change_event () ;
gdbpy_initialize_arch ();

observer_attach_before_prompt (before_prompt_hook);
+ observer_attach_frame_changed (python_frame_changed);

gdbpy_to_string_cst = PyString_FromString ("to_string");
gdbpy_children_cst = PyString_FromString ("children");
--
1.8.2.1