aboutsummaryrefslogtreecommitdiff
path: root/gdb/python
diff options
context:
space:
mode:
authorJan Vrany <jan.vrany@labware.com>2023-10-10 11:22:56 +0100
committerJan Vrany <jan.vrany@labware.com>2023-10-10 11:22:56 +0100
commit4825fd2d3552a047264a1f3d900ce30047a8c5f6 (patch)
tree0cdbeb05638b51fb0f27fef50ce81c7e3e366682 /gdb/python
parent80a3485f81303639c7212a15cf9e453a830913f8 (diff)
downloadbinutils-4825fd2d3552a047264a1f3d900ce30047a8c5f6.zip
binutils-4825fd2d3552a047264a1f3d900ce30047a8c5f6.tar.gz
binutils-4825fd2d3552a047264a1f3d900ce30047a8c5f6.tar.bz2
gdb/python: implement support for sending custom MI async notifications
This commit adds a new Python function, gdb.notify_mi, that can be used to emit custom async notification to MI channel. This can be used, among other things, to implement notifications about events MI does not support, such as remote connection closed or register change. Reviewed-By: Eli Zaretskii <eliz@gnu.org> Approved-By: Andrew Burgess <aburgess@redhat.com>
Diffstat (limited to 'gdb/python')
-rw-r--r--gdb/python/py-mi.c74
-rw-r--r--gdb/python/python-internal.h5
-rw-r--r--gdb/python/python.c4
3 files changed, 83 insertions, 0 deletions
diff --git a/gdb/python/py-mi.c b/gdb/python/py-mi.c
index 36bcb6c..a7b4f4f 100644
--- a/gdb/python/py-mi.c
+++ b/gdb/python/py-mi.c
@@ -19,8 +19,14 @@
#include "defs.h"
#include "python-internal.h"
+#include "utils.h"
+#include "ui.h"
#include "ui-out.h"
+#include "interps.h"
+#include "target.h"
#include "mi/mi-parse.h"
+#include "mi/mi-console.h"
+#include "mi/mi-interp.h"
/* A ui_out subclass that creates a Python object based on the data
that is passed in. */
@@ -455,3 +461,71 @@ serialize_mi_results (PyObject *results)
serialize_mi_result_1 (value, key_string.get ());
}
}
+
+/* See python-internal.h. */
+
+PyObject *
+gdbpy_notify_mi (PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ static const char *keywords[] = { "name", "data", nullptr };
+ char *name = nullptr;
+ PyObject *data = Py_None;
+
+ if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "s|O", keywords,
+ &name, &data))
+ return nullptr;
+
+ /* Validate notification name. */
+ const int name_len = strlen (name);
+ if (name_len == 0)
+ {
+ PyErr_SetString (PyExc_ValueError, _("MI notification name is empty."));
+ return nullptr;
+ }
+ for (int i = 0; i < name_len; i++)
+ {
+ if (!isalnum (name[i]) && name[i] != '-')
+ {
+ PyErr_Format
+ (PyExc_ValueError,
+ _("MI notification name contains invalid character: %c."),
+ name[i]);
+ return nullptr;
+ }
+ }
+
+ /* Validate additional data. */
+ if (!(data == Py_None || PyDict_Check (data)))
+ {
+ PyErr_Format
+ (PyExc_ValueError,
+ _("MI notification data must be either None or a dictionary, not %s"),
+ Py_TYPE (data)->tp_name);
+ return nullptr;
+ }
+
+ SWITCH_THRU_ALL_UIS ()
+ {
+ struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
+
+ if (mi == nullptr)
+ continue;
+
+ target_terminal::scoped_restore_terminal_state term_state;
+ target_terminal::ours_for_output ();
+
+ gdb_printf (mi->event_channel, "%s", name);
+ if (data != Py_None)
+ {
+ ui_out *mi_uiout = mi->interp_ui_out ();
+ ui_out_redirect_pop redir (mi_uiout, mi->event_channel);
+ scoped_restore restore_uiout
+ = make_scoped_restore (&current_uiout, mi_uiout);
+
+ serialize_mi_results (data);
+ }
+ gdb_flush (mi->event_channel);
+ }
+
+ Py_RETURN_NONE;
+}
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 60b795f..847bed8 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -499,6 +499,11 @@ extern PyObject *gdbpy_execute_mi_command (PyObject *self, PyObject *args,
extern void serialize_mi_results (PyObject *results);
+/* Implementation of the gdb.notify_mi function. */
+
+extern PyObject *gdbpy_notify_mi (PyObject *self, PyObject *args,
+ PyObject *kw);
+
/* Convert Python object OBJ to a program_space pointer. OBJ must be a
gdb.Progspace reference. Return nullptr if the gdb.Progspace is not
valid (see gdb.Progspace.is_valid), otherwise return the program_space
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 6a978d6..faa7e0c 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -2669,6 +2669,10 @@ Return the name of the currently selected language." },
"print_options () -> dict\n\
Return the current print options." },
+ { "notify_mi", (PyCFunction) gdbpy_notify_mi,
+ METH_VARARGS | METH_KEYWORDS,
+ "notify_mi (name, data) -> None\n\
+Output async record to MI channels if any." },
{NULL, NULL, 0, NULL}
};