]> Git Repo - binutils.git/blobdiff - gdb/python/py-function.c
* python/py-arch.c (gdbpy_initialize_arch): Return 'int'.
[binutils.git] / gdb / python / py-function.c
index d472f033e6cb628d46fb62375bd1869ad972e583..57cdfaefdd9b5f1720b91ed0385604b3054ccd88 100644 (file)
@@ -1,6 +1,6 @@
 /* Convenience functions implemented in Python.
 
-   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2008-2013 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -29,7 +29,8 @@
 #include "expression.h"
 #include "language.h"
 
-static PyTypeObject fnpy_object_type;
+static PyTypeObject fnpy_object_type
+    CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("PyObject");
 
 \f
 
@@ -38,13 +39,17 @@ convert_values_to_python (int argc, struct value **argv)
 {
   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);
     }
@@ -57,30 +62,87 @@ static struct value *
 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);
@@ -103,7 +165,9 @@ fnpy_call (struct gdbarch *gdbarch, const struct language_defn *language,
 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);
@@ -111,8 +175,21 @@ fnpy_init (PyObject *self, PyObject *args, PyObject *kwds)
   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."));
@@ -123,22 +200,23 @@ fnpy_init (PyObject *self, PyObject *args, PyObject *kwds)
 
 /* 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*/
@@ -175,5 +253,4 @@ static PyTypeObject fnpy_object_type =
   0,                             /* tp_dictoffset */
   fnpy_init,                     /* tp_init */
   0,                             /* tp_alloc */
-  PyType_GenericNew              /* tp_new */
 };
This page took 0.033066 seconds and 4 git commands to generate.