Re: nios2: Remove binutils support for Nios II target
[binutils-gdb.git] / gdb / python / py-mi.c
blobcf75a18958e1de28dd8289a749d8246c214bd9cd
1 /* Python interface to MI commands
3 Copyright (C) 2023-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #include "python-internal.h"
21 #include "py-uiout.h"
22 #include "utils.h"
23 #include "ui.h"
24 #include "interps.h"
25 #include "target.h"
26 #include "mi/mi-parse.h"
27 #include "mi/mi-console.h"
28 #include "mi/mi-interp.h"
30 void
31 py_ui_out::add_field (const char *name, const gdbpy_ref<> &obj)
33 if (obj == nullptr)
35 m_error.emplace ();
36 return;
39 object_desc &desc = current ();
40 if (desc.type == ui_out_type_list)
42 if (PyList_Append (desc.obj.get (), obj.get ()) < 0)
43 m_error.emplace ();
45 else
47 if (PyDict_SetItemString (desc.obj.get (), name, obj.get ()) < 0)
48 m_error.emplace ();
52 void
53 py_ui_out::do_begin (ui_out_type type, const char *id)
55 if (m_error.has_value ())
56 return;
58 gdbpy_ref<> new_obj (type == ui_out_type_list
59 ? PyList_New (0)
60 : PyDict_New ());
61 if (new_obj == nullptr)
63 m_error.emplace ();
64 return;
67 object_desc new_desc;
68 if (id != nullptr)
69 new_desc.field_name = id;
70 new_desc.obj = std::move (new_obj);
71 new_desc.type = type;
73 m_objects.push_back (std::move (new_desc));
76 void
77 py_ui_out::do_end (ui_out_type type)
79 if (m_error.has_value ())
80 return;
82 object_desc new_obj = std::move (current ());
83 m_objects.pop_back ();
84 add_field (new_obj.field_name.c_str (), new_obj.obj);
87 void
88 py_ui_out::do_field_signed (int fldno, int width, ui_align align,
89 const char *fldname, LONGEST value,
90 const ui_file_style &style)
92 if (m_error.has_value ())
93 return;
95 gdbpy_ref<> val = gdb_py_object_from_longest (value);
96 add_field (fldname, val);
99 void
100 py_ui_out::do_field_unsigned (int fldno, int width, ui_align align,
101 const char *fldname, ULONGEST value)
103 if (m_error.has_value ())
104 return;
106 gdbpy_ref<> val = gdb_py_object_from_ulongest (value);
107 add_field (fldname, val);
110 void
111 py_ui_out::do_field_string (int fldno, int width, ui_align align,
112 const char *fldname, const char *string,
113 const ui_file_style &style)
115 if (m_error.has_value ())
116 return;
118 gdbpy_ref<> val = host_string_to_python_string (string);
119 add_field (fldname, val);
122 void
123 py_ui_out::do_field_fmt (int fldno, int width, ui_align align,
124 const char *fldname, const ui_file_style &style,
125 const char *format, va_list args)
127 if (m_error.has_value ())
128 return;
130 std::string str = string_vprintf (format, args);
131 do_field_string (fldno, width, align, fldname, str.c_str (), style);
134 /* Implementation of the gdb.execute_mi command. */
136 PyObject *
137 gdbpy_execute_mi_command (PyObject *self, PyObject *args, PyObject *kw)
139 gdb::unique_xmalloc_ptr<char> mi_command;
140 std::vector<gdb::unique_xmalloc_ptr<char>> arg_strings;
142 Py_ssize_t n_args = PyTuple_Size (args);
143 if (n_args < 0)
144 return nullptr;
146 if (n_args == 0)
148 PyErr_SetString (PyExc_TypeError,
149 _("gdb.execute_mi requires command argument"));
150 return nullptr;
153 for (Py_ssize_t i = 0; i < n_args; ++i)
155 /* Note this returns a borrowed reference. */
156 PyObject *arg = PyTuple_GetItem (args, i);
157 if (arg == nullptr)
158 return nullptr;
159 gdb::unique_xmalloc_ptr<char> str = python_string_to_host_string (arg);
160 if (str == nullptr)
161 return nullptr;
162 if (i == 0)
163 mi_command = std::move (str);
164 else
165 arg_strings.push_back (std::move (str));
168 py_ui_out uiout;
172 scoped_restore save_uiout = make_scoped_restore (&current_uiout, &uiout);
173 auto parser = std::make_unique<mi_parse> (std::move (mi_command),
174 std::move (arg_strings));
175 mi_execute_command (parser.get ());
177 catch (const gdb_exception &except)
179 return gdbpy_handle_gdb_exception (nullptr, except);
182 return uiout.result ().release ();
185 /* Convert KEY_OBJ into a string that can be used as a field name in MI
186 output. KEY_OBJ must be a Python string object, and must only contain
187 characters suitable for use as an MI field name.
189 If KEY_OBJ is not a string, or if KEY_OBJ contains invalid characters,
190 then an error is thrown. Otherwise, KEY_OBJ is converted to a string
191 and returned. */
193 static gdb::unique_xmalloc_ptr<char>
194 py_object_to_mi_key (PyObject *key_obj)
196 /* The key must be a string. */
197 if (!PyUnicode_Check (key_obj))
199 gdbpy_ref<> key_repr (PyObject_Repr (key_obj));
200 gdb::unique_xmalloc_ptr<char> key_repr_string;
201 if (key_repr != nullptr)
202 key_repr_string = python_string_to_target_string (key_repr.get ());
203 if (key_repr_string == nullptr)
204 gdbpy_handle_exception ();
206 gdbpy_error (_("non-string object used as key: %s"),
207 key_repr_string.get ());
210 gdb::unique_xmalloc_ptr<char> key_string
211 = python_string_to_target_string (key_obj);
212 if (key_string == nullptr)
213 gdbpy_handle_exception ();
215 /* Predicate function, returns true if NAME is a valid field name for use
216 in MI result output, otherwise, returns false. */
217 auto is_valid_key_name = [] (const char *name) -> bool
219 gdb_assert (name != nullptr);
221 if (*name == '\0' || !isalpha (*name))
222 return false;
224 for (; *name != '\0'; ++name)
225 if (!isalnum (*name) && *name != '_' && *name != '-')
226 return false;
228 return true;
231 if (!is_valid_key_name (key_string.get ()))
233 if (*key_string.get () == '\0')
234 gdbpy_error (_("Invalid empty key in MI result"));
235 else
236 gdbpy_error (_("Invalid key in MI result: %s"), key_string.get ());
239 return key_string;
242 /* Serialize RESULT and print it in MI format to the current_uiout.
243 FIELD_NAME is used as the name of this result field.
245 RESULT can be a dictionary, a sequence, an iterator, or an object that
246 can be converted to a string, these are converted to the matching MI
247 output format (dictionaries as tuples, sequences and iterators as lists,
248 and strings as named fields).
250 If anything goes wrong while formatting the output then an error is
251 thrown.
253 This function is the recursive inner core of serialize_mi_result, and
254 should only be called from that function. */
256 static void
257 serialize_mi_result_1 (PyObject *result, const char *field_name)
259 struct ui_out *uiout = current_uiout;
261 if (PyDict_Check (result))
263 PyObject *key, *value;
264 Py_ssize_t pos = 0;
265 ui_out_emit_tuple tuple_emitter (uiout, field_name);
266 while (PyDict_Next (result, &pos, &key, &value))
268 gdb::unique_xmalloc_ptr<char> key_string
269 (py_object_to_mi_key (key));
270 serialize_mi_result_1 (value, key_string.get ());
273 else if (PySequence_Check (result) && !PyUnicode_Check (result))
275 ui_out_emit_list list_emitter (uiout, field_name);
276 Py_ssize_t len = PySequence_Size (result);
277 if (len == -1)
278 gdbpy_handle_exception ();
279 for (Py_ssize_t i = 0; i < len; ++i)
281 gdbpy_ref<> item (PySequence_ITEM (result, i));
282 if (item == nullptr)
283 gdbpy_handle_exception ();
284 serialize_mi_result_1 (item.get (), nullptr);
287 else if (PyIter_Check (result))
289 gdbpy_ref<> item;
290 ui_out_emit_list list_emitter (uiout, field_name);
291 while (true)
293 item.reset (PyIter_Next (result));
294 if (item == nullptr)
296 if (PyErr_Occurred () != nullptr)
297 gdbpy_handle_exception ();
298 break;
300 serialize_mi_result_1 (item.get (), nullptr);
303 else
305 if (PyLong_Check (result))
307 int overflow = 0;
308 gdb_py_longest val = gdb_py_long_as_long_and_overflow (result,
309 &overflow);
310 if (PyErr_Occurred () != nullptr)
311 gdbpy_handle_exception ();
312 if (overflow == 0)
314 uiout->field_signed (field_name, val);
315 return;
317 /* Fall through to the string case on overflow. */
320 gdb::unique_xmalloc_ptr<char> string (gdbpy_obj_to_string (result));
321 if (string == nullptr)
322 gdbpy_handle_exception ();
323 uiout->field_string (field_name, string.get ());
327 /* See python-internal.h. */
329 void
330 serialize_mi_results (PyObject *results)
332 gdb_assert (PyDict_Check (results));
334 PyObject *key, *value;
335 Py_ssize_t pos = 0;
336 while (PyDict_Next (results, &pos, &key, &value))
338 gdb::unique_xmalloc_ptr<char> key_string
339 (py_object_to_mi_key (key));
340 serialize_mi_result_1 (value, key_string.get ());
344 /* See python-internal.h. */
346 PyObject *
347 gdbpy_notify_mi (PyObject *self, PyObject *args, PyObject *kwargs)
349 static const char *keywords[] = { "name", "data", nullptr };
350 char *name = nullptr;
351 PyObject *data = Py_None;
353 if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "s|O", keywords,
354 &name, &data))
355 return nullptr;
357 /* Validate notification name. */
358 const int name_len = strlen (name);
359 if (name_len == 0)
361 PyErr_SetString (PyExc_ValueError, _("MI notification name is empty."));
362 return nullptr;
364 for (int i = 0; i < name_len; i++)
366 if (!isalnum (name[i]) && name[i] != '-')
368 PyErr_Format
369 (PyExc_ValueError,
370 _("MI notification name contains invalid character: %c."),
371 name[i]);
372 return nullptr;
376 /* Validate additional data. */
377 if (!(data == Py_None || PyDict_Check (data)))
379 PyErr_Format
380 (PyExc_ValueError,
381 _("MI notification data must be either None or a dictionary, not %s"),
382 Py_TYPE (data)->tp_name);
383 return nullptr;
386 SWITCH_THRU_ALL_UIS ()
388 struct mi_interp *mi = as_mi_interp (top_level_interpreter ());
390 if (mi == nullptr)
391 continue;
393 target_terminal::scoped_restore_terminal_state term_state;
394 target_terminal::ours_for_output ();
396 gdb_printf (mi->event_channel, "%s", name);
397 if (data != Py_None)
399 ui_out *mi_uiout = mi->interp_ui_out ();
400 ui_out_redirect_pop redir (mi_uiout, mi->event_channel);
401 scoped_restore restore_uiout
402 = make_scoped_restore (&current_uiout, mi_uiout);
404 serialize_mi_results (data);
406 gdb_flush (mi->event_channel);
409 Py_RETURN_NONE;