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