/* Convenience functions implemented in Python.
- Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2008-2013 Free Software Foundation, Inc.
This file is part of GDB.
#include "expression.h"
#include "language.h"
-static PyTypeObject fnpy_object_type;
+static PyTypeObject fnpy_object_type
+ CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("PyObject");
\f
{
int i;
PyObject *result = PyTuple_New (argc);
+
+ if (! result)
+ return NULL;
+
for (i = 0; i < argc; ++i)
{
PyObject *elt = value_to_value_object (argv[i]);
if (! elt)
{
Py_DECREF (result);
- error (_("Could not convert value to Python object."));
+ return NULL;
}
PyTuple_SetItem (result, i, elt);
}
fnpy_call (struct gdbarch *gdbarch, const struct language_defn *language,
void *cookie, int argc, struct value **argv)
{
- int i;
struct value *value = NULL;
- PyObject *result, *callable, *args;
+ /* 'result' must be set to NULL, this initially indicates whether
+ the function was called, or not. */
+ PyObject *result = NULL;
+ PyObject *callable, *args;
struct cleanup *cleanup;
cleanup = ensure_python_env (gdbarch, language);
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.
+ Note, that this is different if the function simply does not
+ have arguments. */
- callable = PyObject_GetAttrString ((PyObject *) cookie, "invoke");
- if (! callable)
+ if (args)
{
+ callable = PyObject_GetAttrString ((PyObject *) cookie, "invoke");
+ if (! callable)
+ {
+ Py_DECREF (args);
+ error (_("No method named 'invoke' in object."));
+ }
+
+ result = PyObject_Call (callable, args, NULL);
+ Py_DECREF (callable);
Py_DECREF (args);
- error (_("No method named 'invoke' in object."));
}
- result = PyObject_Call (callable, args, NULL);
- Py_DECREF (callable);
- Py_DECREF (args);
-
if (!result)
{
- gdbpy_print_stack ();
- error (_("Error while executing Python code."));
+ PyObject *ptype, *pvalue, *ptraceback;
+ char *msg;
+
+ 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. */
+
+ msg = gdbpy_exception_to_string (ptype, pvalue);
+ make_cleanup (xfree, msg);
+
+ 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);
+ else
+ error (_("Error occurred in Python convenience function."));
+ }
+ else
+ {
+ Py_XDECREF (ptype);
+ Py_XDECREF (pvalue);
+ Py_XDECREF (ptraceback);
+ error ("%s", msg);
+ }
}
value = convert_value_from_python (result);
static int
fnpy_init (PyObject *self, PyObject *args, PyObject *kwds)
{
- char *name, *docstring = NULL;
+ const char *name;
+ char *docstring = NULL;
+
if (! PyArg_ParseTuple (args, "s", &name))
return -1;
Py_INCREF (self);
if (PyObject_HasAttrString (self, "__doc__"))
{
PyObject *ds_obj = PyObject_GetAttrString (self, "__doc__");
- if (ds_obj && gdbpy_is_string (ds_obj))
- docstring = python_string_to_host_string (ds_obj);
+ if (ds_obj != NULL)
+ {
+ if (gdbpy_is_string (ds_obj))
+ {
+ docstring = python_string_to_host_string (ds_obj);
+ if (docstring == NULL)
+ {
+ Py_DECREF (self);
+ Py_DECREF (ds_obj);
+ return -1;
+ }
+ }
+
+ Py_DECREF (ds_obj);
+ }
}
if (! docstring)
docstring = xstrdup (_("This function is not documented."));
/* Initialize internal function support. */
-void
+int
gdbpy_initialize_functions (void)
{
+ fnpy_object_type.tp_new = PyType_GenericNew;
if (PyType_Ready (&fnpy_object_type) < 0)
- return;
+ return -1;
Py_INCREF (&fnpy_object_type);
- PyModule_AddObject (gdb_module, "Function", (PyObject *) &fnpy_object_type);
+ return PyModule_AddObject (gdb_module, "Function",
+ (PyObject *) &fnpy_object_type);
}
\f
static PyTypeObject fnpy_object_type =
{
- PyObject_HEAD_INIT (NULL)
- 0, /*ob_size*/
+ PyVarObject_HEAD_INIT (NULL, 0)
"gdb.Function", /*tp_name*/
sizeof (PyObject), /*tp_basicsize*/
0, /*tp_itemsize*/
0, /* tp_dictoffset */
fnpy_init, /* tp_init */
0, /* tp_alloc */
- PyType_GenericNew /* tp_new */
};