Home | History | Annotate | Line # | Download | only in python
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 (&current_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 (&current_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