/* General utility routines for GDB/Python.

   Copyright (C) 2008-2026 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 "top.h"
#include "charset.h"
#include "value.h"
#include "python-internal.h"

/* Converts a Python 8-bit string to a unicode string object.  Assumes the
   8-bit string is in the host charset.  If an error occurs during conversion,
   returns NULL with a python exception set.

   As an added bonus, the functions accepts a unicode string and returns it
   right away, so callers don't need to check which kind of string they've
   got.  In Python 3, all strings are Unicode so this case is always the
   one that applies.

   If the given object is not one of the mentioned string types, NULL is
   returned, with the TypeError python exception set.  */
gdbpy_ref<>
python_string_to_unicode (PyObject *obj)
{
  PyObject *unicode_str;

  /* If obj is already a unicode string, just return it.
     I wish life was always that simple...  */
  if (PyUnicode_Check (obj))
    {
      unicode_str = obj;
      Py_INCREF (obj);
    }
  else
    {
      PyErr_SetString (PyExc_TypeError,
		       _("Expected a string object."));
      unicode_str = NULL;
    }

  return gdbpy_ref<> (unicode_str);
}

/* Returns a newly allocated string with the contents of the given unicode
   string object converted to CHARSET.  If an error occurs during the
   conversion, NULL will be returned and a python exception will be
   set.  */
static gdb::unique_xmalloc_ptr<char>
unicode_to_encoded_string (PyObject *unicode_str, const char *charset)
{
  /* Translate string to named charset.  */
  gdbpy_ref<> string (PyUnicode_AsEncodedString (unicode_str, charset, NULL));
  if (string == NULL)
    return NULL;

  return gdb::unique_xmalloc_ptr<char>
    (xstrdup (PyBytes_AsString (string.get ())));
}

/* Returns a PyObject with the contents of the given unicode string
   object converted to a named charset.  If an error occurs during
   the conversion, NULL will be returned and a python exception will
   be set.  */
static gdbpy_ref<>
unicode_to_encoded_python_string (PyObject *unicode_str, const char *charset)
{
  /* Translate string to named charset.  */
  return gdbpy_ref<> (PyUnicode_AsEncodedString (unicode_str, charset, NULL));
}

/* Returns a newly allocated string with the contents of the given
   unicode string object converted to the target's charset.  If an
   error occurs during the conversion, NULL will be returned and a
   python exception will be set.  */
gdb::unique_xmalloc_ptr<char>
unicode_to_target_string (PyObject *unicode_str)
{
  return (unicode_to_encoded_string
	  (unicode_str,
	   target_charset (gdbpy_enter::get_gdbarch ())));
}

/* Returns a PyObject with the contents of the given unicode string
   object converted to the target's charset.  If an error occurs
   during the conversion, NULL will be returned and a python exception
   will be set.  */
static gdbpy_ref<>
unicode_to_target_python_string (PyObject *unicode_str)
{
  return (unicode_to_encoded_python_string
	  (unicode_str,
	   target_charset (gdbpy_enter::get_gdbarch ())));
}

/* Converts a python string (8-bit or unicode) to a target string in
   the target's charset.  Returns NULL on error, with a python
   exception set.  */
gdb::unique_xmalloc_ptr<char>
python_string_to_target_string (PyObject *obj)
{
  gdbpy_ref<> str = python_string_to_unicode (obj);
  if (str == NULL)
    return NULL;

  return unicode_to_target_string (str.get ());
}

/* Converts a python string (8-bit or unicode) to a target string in the
   target's charset.  Returns NULL on error, with a python exception
   set.

   In Python 3, the returned object is a "bytes" object (not a string).  */
gdbpy_ref<>
python_string_to_target_python_string (PyObject *obj)
{
  gdbpy_ref<> str = python_string_to_unicode (obj);
  if (str == NULL)
    return str;

  return unicode_to_target_python_string (str.get ());
}

/* Converts a python string (8-bit or unicode) to a target string in
   the host's charset.  Returns NULL on error, with a python exception
   set.  */
gdb::unique_xmalloc_ptr<char>
python_string_to_host_string (PyObject *obj)
{
  gdbpy_ref<> str = python_string_to_unicode (obj);
  if (str == NULL)
    return NULL;

  return unicode_to_encoded_string (str.get (), host_charset ());
}

/* See python/python-internal.h.  */

gdbpy_ref<>
host_string_to_python_string (std::string_view str)
{
  return gdbpy_ref<> (PyUnicode_Decode (str.data (), str.size (),
					host_charset (), nullptr));
}

/* Return true if OBJ is a Python string or unicode object, false
   otherwise.  */

int
gdbpy_is_string (PyObject *obj)
{
  return PyUnicode_Check (obj);
}

/* Return the string representation of OBJ, i.e., str (obj).
   If the result is NULL a python error occurred, the caller must clear it.  */

gdb::unique_xmalloc_ptr<char>
gdbpy_obj_to_string (PyObject *obj)
{
  gdbpy_ref<> str_obj (PyObject_Str (obj));

  if (str_obj != NULL)
    return python_string_to_host_string (str_obj.get ());

  return NULL;
}

/* See python-internal.h.  */

gdb::unique_xmalloc_ptr<char>
gdbpy_err_fetch::to_string () const
{
  /* There are a few cases to consider.
     For example:
     value is a string when PyErr_SetString is used.
     value is not a string when raise "foo" is used, instead it is None
     and type is "foo".
     So the algorithm we use is to print `str (value)' if it's not
     None, otherwise we print `str (type)'.
     Using str (aka PyObject_Str) will fetch the error message from
     gdb.GdbError ("message").  */

  gdbpy_ref<> value = this->value ();
  if (value.get () != nullptr && value.get () != Py_None)
    return gdbpy_obj_to_string (value.get ());
  else
    return gdbpy_obj_to_string (this->type ().get ());
}

/* See python-internal.h.  */

gdb::unique_xmalloc_ptr<char>
gdbpy_err_fetch::type_to_string () const
{
  return gdbpy_obj_to_string (this->type ().get ());
}

/* Convert a GDB exception to the appropriate Python exception.

   This sets the Python error indicator.  */

void
gdbpy_convert_exception (const struct gdb_exception &exception)
{
  PyObject *exc_class;

  if (exception.reason == RETURN_QUIT)
    exc_class = PyExc_KeyboardInterrupt;
  else if (exception.reason == RETURN_FORCED_QUIT)
    quit_force (NULL, 0);
  else if (exception.error == MEMORY_ERROR)
    exc_class = gdbpy_gdb_memory_error;
  else
    exc_class = gdbpy_gdb_error;

  PyErr_Format (exc_class, "%s", exception.what ());
}

/* Converts OBJ to a CORE_ADDR value.

   Returns 0 on success or -1 on failure, with a Python exception set.
*/

int
get_addr_from_python (PyObject *obj, CORE_ADDR *addr)
{
  if (gdbpy_is_value_object (obj))
    {

      try
	{
	  *addr = value_as_address (value_object_to_value (obj));
	}
      catch (const gdb_exception &except)
	{
	  return gdbpy_handle_gdb_exception (-1, except);
	}
    }
  else
    {
      gdbpy_ref<> num (PyNumber_Long (obj));
      gdb_py_ulongest val;

      if (num == NULL)
	return -1;

      val = gdb_py_long_as_ulongest (num.get ());
      if (PyErr_Occurred ())
	return -1;

      if (sizeof (val) > sizeof (CORE_ADDR) && ((CORE_ADDR) val) != val)
	{
	  PyErr_SetString (PyExc_ValueError,
			   _("Overflow converting to address."));
	  return -1;
	}

      *addr = val;
    }

  return 0;
}

/* Convert a LONGEST to the appropriate Python object -- either an
   integer object or a long object, depending on its value.  */

gdbpy_ref<>
gdb_py_object_from_longest (LONGEST l)
{
  if (sizeof (l) > sizeof (long))
    return gdbpy_ref<> (PyLong_FromLongLong (l));
  return gdbpy_ref<> (PyLong_FromLong (l));
}

/* Convert a ULONGEST to the appropriate Python object -- either an
   integer object or a long object, depending on its value.  */

gdbpy_ref<>
gdb_py_object_from_ulongest (ULONGEST l)
{
  if (sizeof (l) > sizeof (unsigned long))
    return gdbpy_ref<> (PyLong_FromUnsignedLongLong (l));
  return gdbpy_ref<> (PyLong_FromUnsignedLong (l));
}

/* Like PyLong_AsLong, but returns 0 on failure, 1 on success, and puts
   the value into an out parameter.  */

int
gdb_py_int_as_long (PyObject *obj, long *result)
{
  *result = PyLong_AsLong (obj);
  return ! (*result == -1 && PyErr_Occurred ());
}



/* Generic implementation of the getter for the __dict__ attribute for objects
   having a dictionary.  The CLOSURE argument is unused.  */

PyObject *
gdb_py_generic_dict_getter (PyObject *self,
			    void *closure ATTRIBUTE_UNUSED)
{
  PyObject **py_dict_ptr = gdbpy_dict_wrapper::compute_addr (self);
  PyObject *py_dict = *py_dict_ptr;
  if (py_dict == nullptr)
    {
      PyErr_SetString (PyExc_AttributeError,
		       "This object has no __dict__");
      return nullptr;
    }
  return Py_NewRef (py_dict);
}

/* Generic attribute getter function similar to PyObject_GenericGetAttr () but
   that should be used when the object has a dictionary __dict__.  */
PyObject *
gdb_py_generic_getattro (PyObject *self, PyObject *attr)
{
  PyObject *value = PyObject_GenericGetAttr (self, attr);
  if (value != nullptr)
    return value;

  if (! PyErr_ExceptionMatches (PyExc_AttributeError))
    return nullptr;

  gdbpy_ref<> dict (gdb_py_generic_dict_getter (self, nullptr));
  if (dict == nullptr)
    return nullptr;

  /* Clear previous AttributeError set by PyObject_GenericGetAttr when it
     did not find the attribute, and try to get the attribute from __dict__.  */
  PyErr_Clear();

  value = PyDict_GetItemWithError (dict.get (), attr);
  if (value != nullptr)
    return Py_NewRef (value);

  /* If PyDict_GetItemWithError() returns NULL because an error occurred, it
     sets an exception.  Propagate it by returning NULL.  */
  if (PyErr_Occurred () != nullptr)
    return nullptr;

  /* If the key is not found, PyDict_GetItemWithError() returns NULL without
     setting an exception.  Failing to set one here would later result in:
       <class 'SystemError'>: error return without exception set
     Therefore, we must explicitly raise an AttributeError in this case.  */
  PyErr_Format (PyExc_AttributeError,
		"'%s' object has no attribute '%s'",
		gdbpy_py_obj_tp_name (self),
		PyUnicode_AsUTF8AndSize (attr, nullptr));
  return nullptr;
}

/* Generic attribute setter function similar to PyObject_GenericSetAttr () but
   that should be used when the object has a dictionary __dict__.  */
int
gdb_py_generic_setattro (PyObject *self, PyObject *attr, PyObject *value)
{
  if (PyObject_GenericSetAttr (self, attr, value) == 0)
    return 0;

  if (! PyErr_ExceptionMatches (PyExc_AttributeError))
    return -1;

  gdbpy_ref<> dict (gdb_py_generic_dict_getter (self, nullptr));
  if (dict == nullptr)
    return -1;

  /* Clear previous AttributeError set by PyObject_GenericGetAttr() when it
     did not find the attribute, and try to set the attribute into __dict__.  */
  PyErr_Clear();

  /* Set the new value.
     Note: the old value is managed by PyDict_SetItem(), so no need to get
     a borrowed reference on it and decrement its reference counter before
     setting a new value.  */
  return PyDict_SetItem (dict.get (), attr, value);
}



/* Like PyModule_AddObject, but does not steal a reference to
   OBJECT.  */

int
gdb_pymodule_addobject (PyObject *mod, const char *name, PyObject *object)
{
  int result;

  Py_INCREF (object);
  result = PyModule_AddObject (mod, name, object);
  if (result < 0)
    Py_DECREF (object);
  return result;
}

/* See python-internal.h.  */

void
gdbpy_error (const char *fmt, ...)
{
  va_list ap;
  va_start (ap, fmt);
  std::string str = string_vprintf (fmt, ap);
  va_end (ap);

  const char *msg = str.c_str ();
  if (msg != nullptr && *msg != '\0')
    error (_("Error occurred in Python: %s"), msg);
  else
    error (_("Error occurred in Python."));
}

/* Handle a Python exception when the special gdb.GdbError treatment
   is desired.  This should only be called when an exception is set.
   If the exception is a gdb.GdbError, throw a gdb exception with the
   exception text.  For other exceptions, print the Python stack and
   then throw a gdb exception.  */

void
gdbpy_handle_exception ()
{
  gdbpy_err_fetch fetched_error;
  gdb::unique_xmalloc_ptr<char> msg = fetched_error.to_string ();

  if (msg == NULL)
    {
      /* An error occurred computing the string representation of the
	 error message.  This is rare, but we should inform the user.  */
      gdb_printf (_("An error occurred in Python "
		    "and then another occurred computing the "
		    "error message.\n"));
      gdbpy_print_stack ();
    }

  /* Don't print the stack for gdb.GdbError exceptions.
     It is generally used to flag user errors.

     We also don't want to print "Error occurred in Python command"
     for user errors.  However, a missing message for gdb.GdbError
     exceptions is arguably a bug, so we flag it as such.  */

  if (fetched_error.type_matches (PyExc_KeyboardInterrupt))
    throw_quit ("Quit");
  else if (fetched_error.type_matches (PyExc_SystemExit))
    {
      gdbpy_ref<> value = fetched_error.value ();
      gdbpy_ref<> code (PyObject_GetAttrString (value.get (), "code"));
      int exit_arg;

      if (code.get () == Py_None)
	{
	  /* CODE == None: exit status is 0.  */
	  exit_arg = 0;
	}
      else if (code.get () != nullptr && PyLong_Check (code.get ()))
	{
	  /* CODE == integer: exit status is aforementioned integer.  */
	  exit_arg = PyLong_AsLong (code.get ());
	}
      else
	{
	  if (code.get () == nullptr)
	    gdbpy_print_stack ();

	  /* Otherwise: exit status is 1, print code to stderr.  */
	  if (msg != nullptr)
	    gdb_printf (gdb_stderr, "%s\n", msg.get ());
	  exit_arg = 1;
	}

      quit_force (&exit_arg, 0);
    }
  else if (! fetched_error.type_matches (gdbpy_gdberror_exc)
	   || msg == NULL || *msg == '\0')
    {
      fetched_error.restore ();
      gdbpy_print_stack ();
      if (msg != NULL && *msg != '\0')
	error (_("Error occurred in Python: %s"), msg.get ());
      else
	error (_("Error occurred in Python."));
    }
  else
    error ("%s", msg.get ());
}

/* See python-internal.h.  */

gdb::unique_xmalloc_ptr<char>
gdbpy_fix_doc_string_indentation (gdb::unique_xmalloc_ptr<char> doc)
{
  /* A structure used to track the white-space information on each line of
     DOC.  */
  struct line_whitespace
  {
    /* Constructor.  OFFSET is the offset from the start of DOC, WS_COUNT
       is the number of whitespace characters starting at OFFSET.  */
    line_whitespace (size_t offset, int ws_count)
      : m_offset (offset),
	m_ws_count (ws_count)
    { /* Nothing.  */ }

    /* The offset from the start of DOC.  */
    size_t offset () const
    { return m_offset; }

    /* The number of white-space characters at the start of this line.  */
    int ws () const
    { return m_ws_count; }

  private:
    /* The offset from the start of DOC to the first character of this
       line.  */
    size_t m_offset;

    /* White space count on this line, the first character of this
       whitespace is at OFFSET.  */
    int m_ws_count;
  };

  /* Count the number of white-space character starting at TXT.  We
     currently only count true single space characters, things like tabs,
     newlines, etc are not counted.  */
  auto count_whitespace = [] (const char *txt) -> int
  {
    int count = 0;

    while (*txt == ' ')
      {
	++txt;
	++count;
      }

    return count;
  };

  /* In MIN_WHITESPACE we track the smallest number of whitespace
     characters seen at the start of a line (that has actual content), this
     is the number of characters that we can delete off all lines without
     altering the relative indentation of all lines in DOC.

     The first line often has no indentation, but instead starts immediates
     after the 3-quotes marker within the Python doc string, so, if the
     first line has zero white-space then we just ignore it, and don't set
     MIN_WHITESPACE to zero.

     Lines without any content should (ideally) have no white-space at
     all, but if they do then they might have an artificially low number
     (user left a single stray space at the start of an otherwise blank
     line), we don't consider lines without content when updating the
     MIN_WHITESPACE value.  */
  std::optional<int> min_whitespace;

  /* The index into WS_INFO at which the processing of DOC can be
     considered "all done", that is, after this point there are no further
     lines with useful content and we should just stop.  */
  std::optional<size_t> all_done_idx;

  /* White-space information for each line in DOC.  */
  std::vector<line_whitespace> ws_info;

  /* Now look through DOC and collect the required information.  */
  const char *tmp = doc.get ();
  while (*tmp != '\0')
    {
      /* Add an entry for the offset to the start of this line, and how
	 much white-space there is at the start of this line.  */
      size_t offset = tmp - doc.get ();
      int ws_count = count_whitespace (tmp);
      ws_info.emplace_back (offset, ws_count);

      /* Skip over the white-space.  */
      tmp += ws_count;

      /* Remember where the content of this line starts, and skip forward
	 to either the end of this line (newline) or the end of the DOC
	 string (null character), whichever comes first.  */
      const char *content_start = tmp;
      while (*tmp != '\0' && *tmp != '\n')
	++tmp;

      /* If this is not the first line, and if this line has some content,
	 then update MIN_WHITESPACE, this reflects the smallest number of
	 whitespace characters we can delete from all lines without
	 impacting the relative indentation of all the lines of DOC.  */
      if (offset > 0 && tmp > content_start)
	{
	  if (!min_whitespace.has_value ())
	    min_whitespace = ws_count;
	  else
	    min_whitespace = std::min (*min_whitespace, ws_count);
	}

      /* Each time we encounter a line that has some content we update
	 ALL_DONE_IDX to be the index of the next line.  If the last lines
	 of DOC don't contain any content then ALL_DONE_IDX will be left
	 pointing at an earlier line.  When we rewrite DOC, when we reach
	 ALL_DONE_IDX then we can stop, the allows us to trim any blank
	 lines from the end of DOC.  */
      if (tmp > content_start)
	all_done_idx = ws_info.size ();

      /* If we reached a newline then skip forward to the start of the next
	 line.  The other possibility at this point is that we're at the
	 very end of the DOC string (null terminator).  */
      if (*tmp == '\n')
	++tmp;
    }

  /* We found no lines with content, fail safe by just returning the
     original documentation string.  */
  if (!all_done_idx.has_value () || !min_whitespace.has_value ())
    return doc;

  /* Setup DST and SRC, both pointing into the DOC string.  We're going to
     rewrite DOC in-place, as we only ever make DOC shorter (by removing
     white-space), thus we know this will not overflow.  */
  char *dst = doc.get ();
  char *src = doc.get ();

  /* Array indices used with DST, SRC, and WS_INFO respectively.  */
  size_t dst_offset = 0;
  size_t src_offset = 0;
  size_t ws_info_offset = 0;

  /* Now, walk over the source string, this is the original DOC.  */
  while (src[src_offset] != '\0')
    {
      /* If we are at the start of the next line (in WS_INFO), then we may
	 need to skip some white-space characters.  */
      if (src_offset == ws_info[ws_info_offset].offset ())
	{
	  /* If a line has leading white-space then we need to skip over
	     some number of characters now.  */
	  if (ws_info[ws_info_offset].ws () > 0)
	    {
	      /* If the line is entirely white-space then we skip all of
		 the white-space, the next character to copy will be the
		 newline or null character.  Otherwise, we skip the just
		 some portion of the leading white-space.  */
	      if (src[src_offset + ws_info[ws_info_offset].ws ()] == '\n'
		  || src[src_offset + ws_info[ws_info_offset].ws ()] == '\0')
		src_offset += ws_info[ws_info_offset].ws ();
	      else
		src_offset += std::min (*min_whitespace,
					ws_info[ws_info_offset].ws ());

	      /* If we skipped white-space, and are now at the end of the
		 input, then we're done.  */
	      if (src[src_offset] == '\0')
		break;
	    }
	  if (ws_info_offset < (ws_info.size () - 1))
	    ++ws_info_offset;
	  if (ws_info_offset > *all_done_idx)
	    break;
	}

      /* Don't copy a newline to the start of the DST string, this would
	 result in a leading blank line.  But in all other cases, copy the
	 next character into the destination string.  */
      if ((dst_offset > 0 || src[src_offset] != '\n'))
	{
	  dst[dst_offset] = src[src_offset];
	  ++dst_offset;
	}

      /* Move to the next source character.  */
      ++src_offset;
    }

  /* Remove the trailing newline character(s), and ensure we have a null
     terminator in place.  */
  while (dst_offset > 1 && dst[dst_offset - 1] == '\n')
    --dst_offset;
  dst[dst_offset] = '\0';

  return doc;
}

/* See python-internal.h.  */

PyObject *
gdb_py_invalid_object_repr (PyObject *self)
{
  return PyUnicode_FromFormat ("<%s (invalid)>", gdbpy_py_obj_tp_name (self));
}
