py-function.c revision 1.7
1/* Convenience functions implemented in Python.
2
3   Copyright (C) 2008-2017 Free Software Foundation, Inc.
4
5   This file is part of GDB.
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20
21#include "defs.h"
22#include "value.h"
23#include "python-internal.h"
24#include "charset.h"
25#include "gdbcmd.h"
26#include "cli/cli-decode.h"
27#include "completer.h"
28#include "expression.h"
29#include "language.h"
30#include "py-ref.h"
31
32extern PyTypeObject fnpy_object_type
33    CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("PyObject");
34
35
36
37static PyObject *
38convert_values_to_python (int argc, struct value **argv)
39{
40  int i;
41  gdbpy_ref<> result (PyTuple_New (argc));
42
43  if (result == NULL)
44    return NULL;
45
46  for (i = 0; i < argc; ++i)
47    {
48      gdbpy_ref<> elt (value_to_value_object (argv[i]));
49      if (elt == NULL)
50	return NULL;
51      PyTuple_SetItem (result.get (), i, elt.release ());
52    }
53  return result.release ();
54}
55
56/* Call a Python function object's invoke method.  */
57
58static struct value *
59fnpy_call (struct gdbarch *gdbarch, const struct language_defn *language,
60	   void *cookie, int argc, struct value **argv)
61{
62  /* The gdbpy_enter object needs to be placed first, so that it's the last to
63     be destroyed.  */
64  gdbpy_enter enter_py (gdbarch, language);
65  struct value *value;
66  gdbpy_ref<> result;
67  gdbpy_ref<> args (convert_values_to_python (argc, argv));
68
69  /* convert_values_to_python can return NULL on error.  If we
70     encounter this, do not call the function, but allow the Python ->
71     error code conversion below to deal with the Python exception.
72     Note, that this is different if the function simply does not
73     have arguments.  */
74
75  if (args != NULL)
76    {
77      gdbpy_ref<> callable (PyObject_GetAttrString ((PyObject *) cookie,
78						    "invoke"));
79      if (callable == NULL)
80	error (_("No method named 'invoke' in object."));
81
82      result.reset (PyObject_Call (callable.get (), args.get (), NULL));
83    }
84
85  if (result == NULL)
86    {
87      PyObject *ptype, *pvalue, *ptraceback;
88
89      PyErr_Fetch (&ptype, &pvalue, &ptraceback);
90
91      /* Try to fetch an error message contained within ptype, pvalue.
92	 When fetching the error message we need to make our own copy,
93	 we no longer own ptype, pvalue after the call to PyErr_Restore.  */
94
95      gdb::unique_xmalloc_ptr<char>
96	msg (gdbpy_exception_to_string (ptype, pvalue));
97
98      if (msg == NULL)
99	{
100	  /* An error occurred computing the string representation of the
101	     error message.  This is rare, but we should inform the user.  */
102
103	  printf_filtered (_("An error occurred in a Python "
104			     "convenience function\n"
105			     "and then another occurred computing the "
106			     "error message.\n"));
107	  gdbpy_print_stack ();
108	}
109
110      /* Don't print the stack for gdb.GdbError exceptions.
111	 It is generally used to flag user errors.
112
113	 We also don't want to print "Error occurred in Python command"
114	 for user errors.  However, a missing message for gdb.GdbError
115	 exceptions is arguably a bug, so we flag it as such.  */
116
117      if (!PyErr_GivenExceptionMatches (ptype, gdbpy_gdberror_exc)
118	  || msg == NULL || *msg == '\0')
119	{
120	  PyErr_Restore (ptype, pvalue, ptraceback);
121	  gdbpy_print_stack ();
122	  if (msg != NULL && *msg != '\0')
123	    error (_("Error occurred in Python convenience function: %s"),
124		   msg.get ());
125	  else
126	    error (_("Error occurred in Python convenience function."));
127	}
128      else
129	{
130	  Py_XDECREF (ptype);
131	  Py_XDECREF (pvalue);
132	  Py_XDECREF (ptraceback);
133	  error ("%s", msg.get ());
134	}
135    }
136
137  value = convert_value_from_python (result.get ());
138  if (value == NULL)
139    {
140      gdbpy_print_stack ();
141      error (_("Error while executing Python code."));
142    }
143
144  return value;
145}
146
147/* Initializer for a Function object.  It takes one argument, the name
148   of the function.  */
149
150static int
151fnpy_init (PyObject *self, PyObject *args, PyObject *kwds)
152{
153  const char *name;
154  gdb::unique_xmalloc_ptr<char> docstring;
155
156  if (! PyArg_ParseTuple (args, "s", &name))
157    return -1;
158  Py_INCREF (self);
159
160  if (PyObject_HasAttrString (self, "__doc__"))
161    {
162      gdbpy_ref<> ds_obj (PyObject_GetAttrString (self, "__doc__"));
163      if (ds_obj != NULL)
164	{
165	  if (gdbpy_is_string (ds_obj.get ()))
166	    {
167	      docstring = python_string_to_host_string (ds_obj.get ());
168	      if (docstring == NULL)
169		{
170		  Py_DECREF (self);
171		  return -1;
172		}
173	    }
174	}
175    }
176  if (! docstring)
177    docstring.reset (xstrdup (_("This function is not documented.")));
178
179  add_internal_function (name, docstring.release (), fnpy_call, self);
180  return 0;
181}
182
183/* Initialize internal function support.  */
184
185int
186gdbpy_initialize_functions (void)
187{
188  fnpy_object_type.tp_new = PyType_GenericNew;
189  if (PyType_Ready (&fnpy_object_type) < 0)
190    return -1;
191
192  return gdb_pymodule_addobject (gdb_module, "Function",
193				 (PyObject *) &fnpy_object_type);
194}
195
196
197
198PyTypeObject fnpy_object_type =
199{
200  PyVarObject_HEAD_INIT (NULL, 0)
201  "gdb.Function",		  /*tp_name*/
202  sizeof (PyObject),		  /*tp_basicsize*/
203  0,				  /*tp_itemsize*/
204  0,				  /*tp_dealloc*/
205  0,				  /*tp_print*/
206  0,				  /*tp_getattr*/
207  0,				  /*tp_setattr*/
208  0,				  /*tp_compare*/
209  0,				  /*tp_repr*/
210  0,				  /*tp_as_number*/
211  0,				  /*tp_as_sequence*/
212  0,				  /*tp_as_mapping*/
213  0,				  /*tp_hash */
214  0,				  /*tp_call*/
215  0,				  /*tp_str*/
216  0,				  /*tp_getattro*/
217  0,				  /*tp_setattro*/
218  0,				  /*tp_as_buffer*/
219  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
220  "GDB function object",	  /* tp_doc */
221  0,				  /* tp_traverse */
222  0,				  /* tp_clear */
223  0,				  /* tp_richcompare */
224  0,				  /* tp_weaklistoffset */
225  0,				  /* tp_iter */
226  0,				  /* tp_iternext */
227  0,				  /* tp_methods */
228  0,				  /* tp_members */
229  0,				  /* tp_getset */
230  0,				  /* tp_base */
231  0,				  /* tp_dict */
232  0,				  /* tp_descr_get */
233  0,				  /* tp_descr_set */
234  0,				  /* tp_dictoffset */
235  fnpy_init,			  /* tp_init */
236  0,				  /* tp_alloc */
237};
238