This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH 3/3] Add a gdb.events.frame_change event registry
- From: Maxime Coste <frrrwww at gmail dot com>
- To: gdb-patches at sourceware dot org
- Cc: Maxime Coste <frrrwww at gmail dot com>
- Date: Tue, 30 Apr 2013 14:01:19 +0200
- Subject: [PATCH 3/3] Add a gdb.events.frame_change event registry
- References: <87vc75xew9 dot fsf at fleche dot redhat dot com> <1367323279-24567-1-git-send-email-frrrwww at gmail dot com>
---
ChangeLog | 7 ++++
gdb/Makefile.in | 6 +++
gdb/NEWS | 5 +++
gdb/doc/gdb.texinfo | 9 +++++
gdb/python/py-events.h | 1 +
gdb/python/py-evts.c | 3 ++
gdb/python/py-framechangeevent.c | 73 ++++++++++++++++++++++++++++++++++
gdb/python/py-framechangeevent.h | 29 ++++++++++++++
gdb/python/python-internal.h | 1 +
gdb/python/python.c | 18 +++++++++
gdb/testsuite/gdb.python/py-events.exp | 8 ++++
gdb/testsuite/gdb.python/py-events.py | 8 ++++
12 files changed, 168 insertions(+)
create mode 100644 gdb/python/py-framechangeevent.c
create mode 100644 gdb/python/py-framechangeevent.h
diff --git a/ChangeLog b/ChangeLog
index 0ee72e5..4f278fa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -13,6 +13,13 @@
* varobj.c: Idem.
* doc/observer.texi: add a frame_changed observer
* frame.c: Idem
+ * py-framechangeevent.c: add python frame_change event registry.
+ * py-framechangeevent.h: Idem.
+ * python/python.c (python_frame_changed): Idem.
+ * doc/gdb.texinfo: Idem.
+ * Makefile.in: Idem.
+ * testsuite/gdb.python/py-events.exp: Idem.
+ * testsuite/gdb.python/py-events.py: Idem.
2013-04-29 Jan-Benedict Glaw <jbglaw@lug-owl.de>
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/NEWS b/gdb/NEWS
index 76b48e8..af36e1f 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -51,6 +51,11 @@ show remote trace-status-packet
** The -trace-save MI command can optionally save trace buffer in Common
Trace Format now.
+* Python scripting
+
+ ** User visible frame change events are notified through
+ the gdb.events.frame_change event registry
+
*** Changes in GDB 7.6
* Target record has been renamed to record-full.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 8bc1213..df3de08 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -24588,6 +24588,15 @@ A reference to the object file (@code{gdb.Objfile}) which has been loaded.
@xref{Objfiles In Python}, for details of the @code{gdb.Objfile} object.
@end defvar
+@item events.frame_change
+Emits @code{gdb.FrameChangeEvent} which indicates that the selected frame
+has changed in a user visible way (such by hitting a breakpoint, or moving
+in the callstack due to a user command).
+
+@defvar FrameChangeEvent.frame
+A reference to the newly selected frame (@code{gdb.Frame})
+@end defvar
+
@end table
@node Threads In Python
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..7b4bec9
--- /dev/null
+++ b/gdb/python/py-framechangeevent.c
@@ -0,0 +1,73 @@
+/* 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;
+
+ py_frame = frame != NULL ? frame_info_to_frame_object (frame) : Py_None;
+ if (!py_frame || evpy_add_attribute (frame_change_event,
+ "frame", py_frame) < 0)
+ goto fail_frame;
+
+ Py_XDECREF (py_frame);
+ return frame_change_event;
+
+ fail_frame:
+ Py_XDECREF (py_frame);
+ 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. 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..ab578ed 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)
}
}
+/* Callback for frame changed observer */
+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);
+}
+
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");
diff --git a/gdb/testsuite/gdb.python/py-events.exp b/gdb/testsuite/gdb.python/py-events.exp
index 7bd6562..dd3fd75 100644
--- a/gdb/testsuite/gdb.python/py-events.exp
+++ b/gdb/testsuite/gdb.python/py-events.exp
@@ -77,6 +77,14 @@ gdb_test "step 3" ".*event type: continue.*
.*breakpoint number: 4.*
all threads stopped"
+# Test that up triggers frame change event
+gdb_test "up" ".*event type: frame change.*
+.*frame name: first.*"
+
+# Test that breakpoint triggers frame change event
+gdb_test "continue" ".*event type: frame change.*
+.*frame name: do_nothing.*"
+
delete_breakpoints
#test exited event.
diff --git a/gdb/testsuite/gdb.python/py-events.py b/gdb/testsuite/gdb.python/py-events.py
index bfab78e..b7244b2 100644
--- a/gdb/testsuite/gdb.python/py-events.py
+++ b/gdb/testsuite/gdb.python/py-events.py
@@ -60,6 +60,13 @@ def new_objfile_handler (event):
else:
print ("new objfile is None")
+def frame_change_handler (event):
+ if (isinstance (event, gdb.FrameChangeEvent)):
+ print ("event type: frame change")
+ name = event.frame.name()
+ if (name is not None):
+ print ("frame name: %s" % (name))
+
class test_events (gdb.Command):
"""Test events."""
@@ -71,6 +78,7 @@ class test_events (gdb.Command):
gdb.events.stop.connect (breakpoint_stop_handler)
gdb.events.exited.connect (exit_handler)
gdb.events.cont.connect (continue_handler)
+ gdb.events.frame_change.connect (frame_change_handler)
print ("Event testers registered.")
test_events ()
--
1.8.2.1