/* gdb commands implemented in Python
- Copyright (C) 2008-2014 Free Software Foundation, Inc.
+ Copyright (C) 2008-2017 Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "arch-utils.h"
#include "value.h"
-#include "exceptions.h"
#include "python-internal.h"
#include "charset.h"
#include "gdbcmd.h"
#include "cli/cli-decode.h"
#include "completer.h"
#include "language.h"
+#include "py-ref.h"
/* Struct representing built-in completion types. */
struct cmdpy_completer
typedef struct cmdpy_object cmdpy_object;
-static PyTypeObject cmdpy_object_type
+extern PyTypeObject cmdpy_object_type
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("cmdpy_object");
/* Constants used by this module. */
cmdpy_destroyer (struct cmd_list_element *self, void *context)
{
cmdpy_object *cmd;
- struct cleanup *cleanup;
- cleanup = ensure_python_env (get_current_arch (), current_language);
+ gdbpy_enter enter_py (get_current_arch (), current_language);
/* Release our hold on the command object. */
cmd = (cmdpy_object *) context;
xfree ((char *) self->name);
xfree ((char *) self->doc);
xfree ((char *) self->prefixname);
-
- do_cleanups (cleanup);
}
/* Called by gdb to invoke the command. */
if (! result)
{
PyObject *ptype, *pvalue, *ptraceback;
- char *msg;
PyErr_Fetch (&ptype, &pvalue, &ptraceback);
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);
+ gdb::unique_xmalloc_ptr<char>
+ msg (gdbpy_exception_to_string (ptype, pvalue));
if (msg == NULL)
{
PyErr_Restore (ptype, pvalue, ptraceback);
gdbpy_print_stack ();
if (msg != NULL && *msg != '\0')
- error (_("Error occurred in Python command: %s"), msg);
+ error (_("Error occurred in Python command: %s"), msg.get ());
else
error (_("Error occurred in Python command."));
}
Py_XDECREF (ptype);
Py_XDECREF (pvalue);
Py_XDECREF (ptraceback);
- error ("%s", msg);
+ error ("%s", msg.get ());
}
}
/* Helper function for the Python command completers (both "pure"
completer and brkchar handler). This function takes COMMAND, TEXT
and WORD and tries to call the Python method for completion with
- these arguments. It also takes HANDLE_BRKCHARS_P, an argument to
- identify whether it is being called from the brkchar handler or
- from the "pure" completer. In the first case, it effectively calls
- the Python method for completion, and records the PyObject in a
- static variable (used as a "cache"). In the second case, it just
- returns that variable, without actually calling the Python method
- again. This saves us one Python method call.
-
- The reason for this two step dance is that we need to know the set
- of "brkchars" to use early on, before we actually try to perform
- the completion. But if a Python command supplies a "complete"
- method then we have to call that method first: it may return as its
- result the kind of completion to perform and that will in turn
- specify which brkchars to use. IOW, we need the result of the
- "complete" method before we actually perform the completion.
-
- It is important to mention that this function is built on the
- assumption that the calls to cmdpy_completer_handle_brkchars and
- cmdpy_completer will be subsequent with nothing intervening. This
- is true for our completer mechanism.
+ these arguments.
+
+ This function is usually called twice: once when we are figuring out
+ the break characters to be used, and another to perform the real
+ completion itself. The reason for this two step dance is that we
+ need to know the set of "brkchars" to use early on, before we
+ actually try to perform the completion. But if a Python command
+ supplies a "complete" method then we have to call that method
+ first: it may return as its result the kind of completion to
+ perform and that will in turn specify which brkchars to use. IOW,
+ we need the result of the "complete" method before we actually
+ perform the completion. The only situation when this function is
+ not called twice is when the user uses the "complete" command: in
+ this scenario, there is no call to determine the "brkchars".
+
+ Ideally, it would be nice to cache the result of the first call (to
+ determine the "brkchars") and return this value directly in the
+ second call (to perform the actual completion). However, due to
+ the peculiarity of the "complete" command mentioned above, it is
+ possible to put GDB in a bad state if you perform a TAB-completion
+ and then a "complete"-completion sequentially. Therefore, we just
+ recalculate everything twice for TAB-completions.
This function returns the PyObject representing the Python method
call. */
static PyObject *
cmdpy_completer_helper (struct cmd_list_element *command,
- const char *text, const char *word,
- int handle_brkchars_p)
+ const char *text, const char *word)
{
cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command);
PyObject *textobj, *wordobj;
- /* This static variable will server as a "cache" for us, in order to
- store the PyObject that results from calling the Python
- function. */
- static PyObject *resultobj = NULL;
+ PyObject *resultobj;
- if (handle_brkchars_p)
+ if (obj == NULL)
+ error (_("Invalid invocation of Python command object."));
+ if (!PyObject_HasAttr ((PyObject *) obj, complete_cst))
{
- /* If we were called to handle brkchars, it means this is the
- first function call of two that will happen in a row.
- Therefore, we need to call the completer ourselves, and cache
- the return value in the static variable RESULTOBJ. Then, in
- the second call, we can just use the value of RESULTOBJ to do
- our job. */
- if (resultobj != NULL)
- Py_DECREF (resultobj);
-
- resultobj = NULL;
- if (obj == NULL)
- error (_("Invalid invocation of Python command object."));
- if (!PyObject_HasAttr ((PyObject *) obj, complete_cst))
- {
- /* If there is no complete method, don't error. */
- return NULL;
- }
-
- textobj = PyUnicode_Decode (text, strlen (text), host_charset (), NULL);
- if (textobj == NULL)
- error (_("Could not convert argument to Python string."));
- wordobj = PyUnicode_Decode (word, sizeof (word), host_charset (), NULL);
- if (wordobj == NULL)
- {
- Py_DECREF (textobj);
- error (_("Could not convert argument to Python string."));
- }
+ /* If there is no complete method, don't error. */
+ return NULL;
+ }
- resultobj = PyObject_CallMethodObjArgs ((PyObject *) obj, complete_cst,
- textobj, wordobj, NULL);
+ textobj = PyUnicode_Decode (text, strlen (text), host_charset (), NULL);
+ if (textobj == NULL)
+ error (_("Could not convert argument to Python string."));
+ wordobj = PyUnicode_Decode (word, strlen (word), host_charset (), NULL);
+ if (wordobj == NULL)
+ {
Py_DECREF (textobj);
- Py_DECREF (wordobj);
- if (!resultobj)
- {
- /* Just swallow errors here. */
- PyErr_Clear ();
- }
+ error (_("Could not convert argument to Python string."));
+ }
- Py_XINCREF (resultobj);
+ resultobj = PyObject_CallMethodObjArgs ((PyObject *) obj, complete_cst,
+ textobj, wordobj, NULL);
+ Py_DECREF (textobj);
+ Py_DECREF (wordobj);
+ if (!resultobj)
+ {
+ /* Just swallow errors here. */
+ PyErr_Clear ();
}
+ Py_XINCREF (resultobj);
+
return resultobj;
}
const char *text, const char *word)
{
PyObject *resultobj = NULL;
- struct cleanup *cleanup;
- cleanup = ensure_python_env (get_current_arch (), current_language);
+ gdbpy_enter enter_py (get_current_arch (), current_language);
/* Calling our helper to obtain the PyObject of the Python
function. */
- resultobj = cmdpy_completer_helper (command, text, word, 1);
+ resultobj = cmdpy_completer_helper (command, text, word);
/* Check if there was an error. */
if (resultobj == NULL)
done:
- /* We do not call Py_XDECREF here because RESULTOBJ will be used in
- the subsequent call to cmdpy_completer function. */
- do_cleanups (cleanup);
+ Py_XDECREF (resultobj);
}
/* Called by gdb for command completion. */
{
PyObject *resultobj = NULL;
VEC (char_ptr) *result = NULL;
- struct cleanup *cleanup;
- cleanup = ensure_python_env (get_current_arch (), current_language);
+ gdbpy_enter enter_py (get_current_arch (), current_language);
/* Calling our helper to obtain the PyObject of the Python
function. */
- resultobj = cmdpy_completer_helper (command, text, word, 0);
+ resultobj = cmdpy_completer_helper (command, text, word);
/* If the result object of calling the Python function is NULL, it
means that there was an error. In this case, just give up and
while ((elt = PyIter_Next (iter)) != NULL)
{
- char *item;
if (! gdbpy_is_string (elt))
{
Py_DECREF (elt);
continue;
}
- item = python_string_to_host_string (elt);
+ gdb::unique_xmalloc_ptr<char>
+ item (python_string_to_host_string (elt));
Py_DECREF (elt);
if (item == NULL)
{
PyErr_Clear ();
continue;
}
- VEC_safe_push (char_ptr, result, item);
+ VEC_safe_push (char_ptr, result, item.release ());
}
Py_DECREF (iter);
done:
- do_cleanups (cleanup);
+ Py_XDECREF (resultobj);
return result;
}
|| name[i - 1] == '_');
--i)
;
- result = xmalloc (lastchar - i + 2);
+ result = (char *) xmalloc (lastchar - i + 2);
memcpy (result, &name[i], lastchar - i + 1);
result[lastchar - i + 1] = '\0';
return result;
}
- prefix_text = xmalloc (i + 2);
+ prefix_text = (char *) xmalloc (i + 2);
memcpy (prefix_text, name, i + 1);
prefix_text[i + 1] = '\0';
int cmdtype;
int completetype = -1;
char *docstring = NULL;
- volatile struct gdb_exception except;
struct cmd_list_element **cmd_list;
char *cmd_name, *pfx_name;
static char *keywords[] = { "name", "command_class", "completer_class",
int i, out;
/* Make a normalized form of the command name. */
- pfx_name = xmalloc (strlen (name) + 2);
+ pfx_name = (char *) xmalloc (strlen (name) + 2);
i = 0;
out = 0;
if (ds_obj && gdbpy_is_string (ds_obj))
{
- docstring = python_string_to_host_string (ds_obj);
+ docstring = python_string_to_host_string (ds_obj).release ();
if (docstring == NULL)
{
xfree (cmd_name);
Py_INCREF (self);
- TRY_CATCH (except, RETURN_MASK_ALL)
+ TRY
{
struct cmd_list_element *cmd;
set_cmd_completer_handle_brkchars (cmd,
cmdpy_completer_handle_brkchars);
}
- if (except.reason < 0)
+ CATCH (except, RETURN_MASK_ALL)
{
xfree (cmd_name);
xfree (docstring);
"%s", except.message);
return -1;
}
+ END_CATCH
+
return 0;
}
return -1;
/* Note: alias and user are special; pseudo appears to be unused,
- and there is no reason to expose tui or xdb, I think. */
+ and there is no reason to expose tui, I think. */
if (PyModule_AddIntConstant (gdb_module, "COMMAND_NONE", no_class) < 0
|| PyModule_AddIntConstant (gdb_module, "COMMAND_RUNNING", class_run) < 0
|| PyModule_AddIntConstant (gdb_module, "COMMAND_DATA", class_vars) < 0
{ 0 }
};
-static PyTypeObject cmdpy_object_type =
+PyTypeObject cmdpy_object_type =
{
PyVarObject_HEAD_INIT (NULL, 0)
"gdb.Command", /*tp_name*/
PyObject *
gdbpy_string_to_argv (PyObject *self, PyObject *args)
{
- PyObject *py_argv;
const char *input;
if (!PyArg_ParseTuple (args, "s", &input))
return NULL;
- py_argv = PyList_New (0);
+ gdbpy_ref py_argv (PyList_New (0));
if (py_argv == NULL)
return NULL;
for (i = 0; c_argv[i] != NULL; ++i)
{
- PyObject *argp = PyString_FromString (c_argv[i]);
+ gdbpy_ref argp (PyString_FromString (c_argv[i]));
if (argp == NULL
- || PyList_Append (py_argv, argp) < 0)
+ || PyList_Append (py_argv.get (), argp.get ()) < 0)
{
- Py_XDECREF (argp);
- Py_DECREF (py_argv);
freeargv (c_argv);
return NULL;
}
- Py_DECREF (argp);
}
freeargv (c_argv);
}
- return py_argv;
+ return py_argv.release ();
}