/* Python interface to MI commands

   Copyright (C) 2023 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#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.  */

class py_ui_out : public ui_out
{
public:

  py_ui_out ()
    : ui_out (fix_multi_location_breakpoint_output
	      | fix_breakpoint_script_output)
  {
    do_begin (ui_out_type_tuple, nullptr);
  }

  bool can_emit_style_escape () const override
  { return false; }

  bool do_is_mi_like_p () const override
  { return true; }

  /* Return the Python object that was created.  If a Python error
     occurred during the processing, set the Python error and return
     nullptr.  */
  PyObject *result ()
  {
    if (m_error.has_value ())
      {
	m_error->restore ();
	return nullptr;
      }
    return current ().obj.release ();
  }

protected:

  void do_progress_end () override { }
  void do_progress_start () override { }
  void do_progress_notify (const std::string &, const char *, double, double)
    override
  { }

  void do_table_begin (int nbrofcols, int nr_rows, const char *tblid) override
  {
    do_begin (ui_out_type_list, tblid);
  }
  void do_table_body () override
  { }
  void do_table_end () override
  {
    do_end (ui_out_type_list);
  }
  void do_table_header (int width, ui_align align,
			const std::string &col_name,
			const std::string &col_hdr) override
  { }

  void do_begin (ui_out_type type, const char *id) override;
  void do_end (ui_out_type type) override;

  void do_field_signed (int fldno, int width, ui_align align,
			const char *fldname, LONGEST value) override;
  void do_field_unsigned (int fldno, int width, ui_align align,
			  const char *fldname, ULONGEST value) override;

  void do_field_skip (int fldno, int width, ui_align align,
		      const char *fldname) override
  { }

  void do_field_string (int fldno, int width, ui_align align,
			const char *fldname, const char *string,
			const ui_file_style &style) override;
  void do_field_fmt (int fldno, int width, ui_align align,
		     const char *fldname, const ui_file_style &style,
		     const char *format, va_list args) override
    ATTRIBUTE_PRINTF (7, 0);

  void do_spaces (int numspaces) override
  { }

  void do_text (const char *string) override
  { }

  void do_message (const ui_file_style &style,
		   const char *format, va_list args)
    override ATTRIBUTE_PRINTF (3,0)
  { }

  void do_wrap_hint (int indent) override
  { }

  void do_flush () override
  { }

  void do_redirect (struct ui_file *outstream) override
  { }

private:

  /* When constructing Python objects, this class keeps a stack of
     objects being constructed.  Each such object has this type.  */
  struct object_desc
  {
    /* Name of the field (or empty for lists) that this object will
       eventually become.  */
    std::string field_name;
    /* The object under construction.  */
    gdbpy_ref<> obj;
    /* The type of structure being created.  Note that tables are
       treated as lists here.  */
    ui_out_type type;
  };

  /* The stack of objects being created.  */
  std::vector<object_desc> m_objects;

  /* If an error occurred, this holds the exception information for
     use by the 'release' method.  */
  gdb::optional<gdbpy_err_fetch> m_error;

  /* Return a reference to the object under construction.  */
  object_desc &current ()
  { return m_objects.back (); }

  /* Add a new field to the current object under construction.  */
  void add_field (const char *name, const gdbpy_ref<> &obj);
};

void
py_ui_out::add_field (const char *name, const gdbpy_ref<> &obj)
{
  if (obj == nullptr)
    {
      m_error.emplace ();
      return;
    }

  object_desc &desc = current ();
  if (desc.type == ui_out_type_list)
    {
      if (PyList_Append (desc.obj.get (), obj.get ()) < 0)
	m_error.emplace ();
    }
  else
    {
      if (PyDict_SetItemString (desc.obj.get (), name, obj.get ()) < 0)
	m_error.emplace ();
    }
}

void
py_ui_out::do_begin (ui_out_type type, const char *id)
{
  if (m_error.has_value ())
    return;

  gdbpy_ref<> new_obj (type == ui_out_type_list
		       ? PyList_New (0)
		       : PyDict_New ());
  if (new_obj == nullptr)
    {
      m_error.emplace ();
      return;
    }

  object_desc new_desc;
  if (id != nullptr)
    new_desc.field_name = id;
  new_desc.obj = std::move (new_obj);
  new_desc.type = type;

  m_objects.push_back (std::move (new_desc));
}

void
py_ui_out::do_end (ui_out_type type)
{
  if (m_error.has_value ())
    return;

  object_desc new_obj = std::move (current ());
  m_objects.pop_back ();
  add_field (new_obj.field_name.c_str (), new_obj.obj);
}

void
py_ui_out::do_field_signed (int fldno, int width, ui_align align,
			    const char *fldname, LONGEST value)
{
  if (m_error.has_value ())
    return;

  gdbpy_ref<> val = gdb_py_object_from_longest (value);
  add_field (fldname, val);
}

void
py_ui_out::do_field_unsigned (int fldno, int width, ui_align align,
			    const char *fldname, ULONGEST value)
{
  if (m_error.has_value ())
    return;

  gdbpy_ref<> val = gdb_py_object_from_ulongest (value);
  add_field (fldname, val);
}

void
py_ui_out::do_field_string (int fldno, int width, ui_align align,
			    const char *fldname, const char *string,
			    const ui_file_style &style)
{
  if (m_error.has_value ())
    return;

  gdbpy_ref<> val = host_string_to_python_string (string);
  add_field (fldname, val);
}

void
py_ui_out::do_field_fmt (int fldno, int width, ui_align align,
			 const char *fldname, const ui_file_style &style,
			 const char *format, va_list args)
{
  if (m_error.has_value ())
    return;

  std::string str = string_vprintf (format, args);
  do_field_string (fldno, width, align, fldname, str.c_str (), style);
}

/* Implementation of the gdb.execute_mi command.  */

PyObject *
gdbpy_execute_mi_command (PyObject *self, PyObject *args, PyObject *kw)
{
  gdb::unique_xmalloc_ptr<char> mi_command;
  std::vector<gdb::unique_xmalloc_ptr<char>> arg_strings;

  Py_ssize_t n_args = PyTuple_Size (args);
  if (n_args < 0)
    return nullptr;

  for (Py_ssize_t i = 0; i < n_args; ++i)
    {
      /* Note this returns a borrowed reference.  */
      PyObject *arg = PyTuple_GetItem (args, i);
      if (arg == nullptr)
	return nullptr;
      gdb::unique_xmalloc_ptr<char> str = python_string_to_host_string (arg);
      if (str == nullptr)
	return nullptr;
      if (i == 0)
	mi_command = std::move (str);
      else
	arg_strings.push_back (std::move (str));
    }

  py_ui_out uiout;

  try
    {
      scoped_restore save_uiout = make_scoped_restore (&current_uiout, &uiout);
      auto parser = gdb::make_unique<mi_parse> (std::move (mi_command),
						std::move (arg_strings));
      mi_execute_command (parser.get ());
    }
  catch (const gdb_exception &except)
    {
      gdbpy_convert_exception (except);
      return nullptr;
    }

  return uiout.result ();
}

/* Convert KEY_OBJ into a string that can be used as a field name in MI
   output.  KEY_OBJ must be a Python string object, and must only contain
   characters suitable for use as an MI field name.

   If KEY_OBJ is not a string, or if KEY_OBJ contains invalid characters,
   then an error is thrown.  Otherwise, KEY_OBJ is converted to a string
   and returned.  */

static gdb::unique_xmalloc_ptr<char>
py_object_to_mi_key (PyObject *key_obj)
{
  /* The key must be a string.  */
  if (!PyUnicode_Check (key_obj))
    {
      gdbpy_ref<> key_repr (PyObject_Repr (key_obj));
      gdb::unique_xmalloc_ptr<char> key_repr_string;
      if (key_repr != nullptr)
	key_repr_string = python_string_to_target_string (key_repr.get ());
      if (key_repr_string == nullptr)
	gdbpy_handle_exception ();

      gdbpy_error (_("non-string object used as key: %s"),
		   key_repr_string.get ());
    }

  gdb::unique_xmalloc_ptr<char> key_string
    = python_string_to_target_string (key_obj);
  if (key_string == nullptr)
    gdbpy_handle_exception ();

  /* Predicate function, returns true if NAME is a valid field name for use
     in MI result output, otherwise, returns false.  */
  auto is_valid_key_name = [] (const char *name) -> bool
  {
    gdb_assert (name != nullptr);

    if (*name == '\0' || !isalpha (*name))
      return false;

    for (; *name != '\0'; ++name)
      if (!isalnum (*name) && *name != '_' && *name != '-')
	return false;

    return true;
  };

  if (!is_valid_key_name (key_string.get ()))
    {
      if (*key_string.get () == '\0')
	gdbpy_error (_("Invalid empty key in MI result"));
      else
	gdbpy_error (_("Invalid key in MI result: %s"), key_string.get ());
    }

  return key_string;
}

/* Serialize RESULT and print it in MI format to the current_uiout.
   FIELD_NAME is used as the name of this result field.

   RESULT can be a dictionary, a sequence, an iterator, or an object that
   can be converted to a string, these are converted to the matching MI
   output format (dictionaries as tuples, sequences and iterators as lists,
   and strings as named fields).

   If anything goes wrong while formatting the output then an error is
   thrown.

   This function is the recursive inner core of serialize_mi_result, and
   should only be called from that function.  */

static void
serialize_mi_result_1 (PyObject *result, const char *field_name)
{
  struct ui_out *uiout = current_uiout;

  if (PyDict_Check (result))
    {
      PyObject *key, *value;
      Py_ssize_t pos = 0;
      ui_out_emit_tuple tuple_emitter (uiout, field_name);
      while (PyDict_Next (result, &pos, &key, &value))
	{
	  gdb::unique_xmalloc_ptr<char> key_string
	    (py_object_to_mi_key (key));
	  serialize_mi_result_1 (value, key_string.get ());
	}
    }
  else if (PySequence_Check (result) && !PyUnicode_Check (result))
    {
      ui_out_emit_list list_emitter (uiout, field_name);
      Py_ssize_t len = PySequence_Size (result);
      if (len == -1)
	gdbpy_handle_exception ();
      for (Py_ssize_t i = 0; i < len; ++i)
	{
	  gdbpy_ref<> item (PySequence_ITEM (result, i));
	  if (item == nullptr)
	    gdbpy_handle_exception ();
	  serialize_mi_result_1 (item.get (), nullptr);
	}
    }
  else if (PyIter_Check (result))
    {
      gdbpy_ref<> item;
      ui_out_emit_list list_emitter (uiout, field_name);
      while (true)
	{
	  item.reset (PyIter_Next (result));
	  if (item == nullptr)
	    {
	      if (PyErr_Occurred () != nullptr)
		gdbpy_handle_exception ();
	      break;
	    }
	  serialize_mi_result_1 (item.get (), nullptr);
	}
    }
  else
    {
      if (PyLong_Check (result))
	{
	  int overflow = 0;
	  gdb_py_longest val = gdb_py_long_as_long_and_overflow (result,
								 &overflow);
	  if (PyErr_Occurred () != nullptr)
	    gdbpy_handle_exception ();
	  if (overflow == 0)
	    {
	      uiout->field_signed (field_name, val);
	      return;
	    }
	  /* Fall through to the string case on overflow.  */
	}

      gdb::unique_xmalloc_ptr<char> string (gdbpy_obj_to_string (result));
      if (string == nullptr)
	gdbpy_handle_exception ();
      uiout->field_string (field_name, string.get ());
    }
}

/* See python-internal.h.  */

void
serialize_mi_results (PyObject *results)
{
  gdb_assert (PyDict_Check (results));

  PyObject *key, *value;
  Py_ssize_t pos = 0;
  while (PyDict_Next (results, &pos, &key, &value))
    {
      gdb::unique_xmalloc_ptr<char> key_string
	(py_object_to_mi_key (key));
      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;
}
