diff options
author | Jan Vrany <jan.vrany@labware.com> | 2023-10-10 11:22:56 +0100 |
---|---|---|
committer | Jan Vrany <jan.vrany@labware.com> | 2023-10-10 11:22:56 +0100 |
commit | 4825fd2d3552a047264a1f3d900ce30047a8c5f6 (patch) | |
tree | 0cdbeb05638b51fb0f27fef50ce81c7e3e366682 /gdb/python | |
parent | 80a3485f81303639c7212a15cf9e453a830913f8 (diff) | |
download | binutils-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.c | 74 | ||||
-rw-r--r-- | gdb/python/python-internal.h | 5 | ||||
-rw-r--r-- | gdb/python/python.c | 4 |
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 (¤t_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} }; |