/* Convenience functions implemented in Python.
- Copyright (C) 2008-2017 Free Software Foundation, Inc.
+ Copyright (C) 2008-2022 Free Software Foundation, Inc.
This file is part of GDB.
#include "completer.h"
#include "expression.h"
#include "language.h"
-#include "py-ref.h"
extern PyTypeObject fnpy_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("PyObject");
\f
-static PyObject *
+/* Return a reference to a tuple ARGC elements long. Each element of the
+ tuple is a PyObject converted from the corresponding element of ARGV. */
+
+static gdbpy_ref<>
convert_values_to_python (int argc, struct value **argv)
{
int i;
- gdbpy_ref result (PyTuple_New (argc));
+ gdbpy_ref<> result (PyTuple_New (argc));
if (result == NULL)
return NULL;
for (i = 0; i < argc; ++i)
{
- gdbpy_ref elt (value_to_value_object (argv[i]));
+ gdbpy_ref<> elt (value_to_value_object (argv[i]));
if (elt == NULL)
return NULL;
PyTuple_SetItem (result.get (), i, elt.release ());
}
- return result.release ();
+ return result;
}
/* Call a Python function object's invoke method. */
fnpy_call (struct gdbarch *gdbarch, const struct language_defn *language,
void *cookie, int argc, struct value **argv)
{
- struct value *value = NULL;
- /* 'result' must be set to NULL, this initially indicates whether
- the function was called, or not. */
- gdbpy_ref result;
-
+ /* The gdbpy_enter object needs to be placed first, so that it's the last to
+ be destroyed. */
gdbpy_enter enter_py (gdbarch, language);
+ struct value *value;
+ gdbpy_ref<> result;
+ gdbpy_ref<> args = convert_values_to_python (argc, argv);
- gdbpy_ref args (convert_values_to_python (argc, argv));
/* convert_values_to_python can return NULL on error. If we
encounter this, do not call the function, but allow the Python ->
error code conversion below to deal with the Python exception.
if (args != NULL)
{
- gdbpy_ref callable (PyObject_GetAttrString ((PyObject *) cookie,
- "invoke"));
+ gdbpy_ref<> callable (PyObject_GetAttrString ((PyObject *) cookie,
+ "invoke"));
if (callable == NULL)
error (_("No method named 'invoke' in object."));
}
if (result == NULL)
- {
- PyObject *ptype, *pvalue, *ptraceback;
-
- PyErr_Fetch (&ptype, &pvalue, &ptraceback);
-
- /* Try to fetch an error message contained within ptype, pvalue.
- When fetching the error message we need to make our own copy,
- we no longer own ptype, pvalue after the call to PyErr_Restore. */
-
- gdb::unique_xmalloc_ptr<char>
- msg (gdbpy_exception_to_string (ptype, pvalue));
-
- if (msg == NULL)
- {
- /* An error occurred computing the string representation of the
- error message. This is rare, but we should inform the user. */
-
- printf_filtered (_("An error occurred in a Python "
- "convenience function\n"
- "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 (!PyErr_GivenExceptionMatches (ptype, gdbpy_gdberror_exc)
- || msg == NULL || *msg == '\0')
- {
- PyErr_Restore (ptype, pvalue, ptraceback);
- gdbpy_print_stack ();
- if (msg != NULL && *msg != '\0')
- error (_("Error occurred in Python convenience function: %s"),
- msg.get ());
- else
- error (_("Error occurred in Python convenience function."));
- }
- else
- {
- Py_XDECREF (ptype);
- Py_XDECREF (pvalue);
- Py_XDECREF (ptraceback);
- error ("%s", msg.get ());
- }
- }
+ gdbpy_handle_exception ();
value = convert_value_from_python (result.get ());
if (value == NULL)
if (! PyArg_ParseTuple (args, "s", &name))
return -1;
- Py_INCREF (self);
+
+ gdbpy_ref<> self_ref = gdbpy_ref<>::new_reference (self);
if (PyObject_HasAttrString (self, "__doc__"))
{
- gdbpy_ref ds_obj (PyObject_GetAttrString (self, "__doc__"));
+ gdbpy_ref<> ds_obj (PyObject_GetAttrString (self, "__doc__"));
if (ds_obj != NULL)
{
if (gdbpy_is_string (ds_obj.get ()))
{
docstring = python_string_to_host_string (ds_obj.get ());
if (docstring == NULL)
- {
- Py_DECREF (self);
- return -1;
- }
+ return -1;
}
}
}
if (! docstring)
docstring.reset (xstrdup (_("This function is not documented.")));
- add_internal_function (name, docstring.release (), fnpy_call, self);
+ add_internal_function (make_unique_xstrdup (name), std::move (docstring),
+ fnpy_call, self_ref.release ());
return 0;
}