
This commit makes the gdb.Command.complete methods more verbose when it comes to error handling. Previous to this commit if any commands implemented in Python implemented the complete method, and if there were any errors encountered when calling that complete method, then GDB would silently hide the error and continue as if there were no completions. This makes is difficult to debug any errors encountered when writing completion methods, and encourages the idea that Python extensions can be broken, and GDB will just silently work around them. I don't think this is a good idea. GDB should encourage extensions to be written correctly, and robustly, and one way in which GDB can (I think) support this, is by pointing out when an extension goes wrong. In this commit I've gone through the Python command completion code, and added calls to gdbpy_print_stack() or gdbpy_print_stack_or_quit() in places where we were either clearing the Python error, or, in some cases, just not handling the error at all. One thing I have not changed is in cmdpy_completer (py-cmd.c) where we process the list of completions returned from the Command.complete method; this routine includes a call to gdbpy_is_string to check a possible completion is a string, if not the completion is ignored. I was tempted to remove this check, attempt to complete each result to a string, and display an error if the conversion fails. After all, returning anything but a string is surely a mistake by the extension author. However, the docs clearly say that only strings within the returned list will be considered as completions. Anything else is ignored. As such, and to avoid (what I think is pretty unlikely) breakage of existing code, I've retained the gdbpy_is_string check. After the gdbpy_is_string check we call python_string_to_host_string, if this call fails then I do now print the error, where before we ignored the error. I think this is OK; if GDB thinks something is a string, but still can't convert it to a string, then I think it's OK to display the error in that case. Another case which I was a little unsure about was in cmdpy_completer_helper, and the call to PyObject_CallMethodObjArgs, which is when we actually call Command.complete. Previously, if this call resulted in an exception then we would ignore this and just pretend there were no completions. Of all the changes, this is possibly the one with the biggest potential for breaking existing scripts, but also, is, I think, the most useful change. If the user code is wrong in some way, such that an exception is raised, then previously the user would have no obvious feedback about this breakage. Now GDB will print the exception for them, making it, I think, much easier to debug their extension. But, if there is user code in the wild that relies on raising an exception as a means to indicate there are no completions .... well, that code is going to break after this commit. I think we can live with this though, the exceptions means no completions thing was never documented behaviour. I also added a new error() call if the PyObject_CallMethodObjArgs call raises an exception. This causes the completion mechanism within GDB to stop. Within GDB the completion code is called twice, the first time to compute the work break characters, and then a second time to compute the actual completions. If PyObject_CallMethodObjArgs raises an exception when computing the word break character, and we print it by calling gdbpy_print_stack_or_quit(), but then carry on as if PyObject_CallMethodObjArgs had returns no completions, GDB will call the Python completion code again, which results in another call to PyObject_CallMethodObjArgs, which might raise the same exception again. This results in the Python exception being printed twice. By throwing a C++ exception after the failed PyObject_CallMethodObjArgs call, the completion mechanism is aborted, and no completions are offered. But importantly, the Python exception is only printed once. I think this gives a much better user experience. I've added some tests to cover this case, as I think this is the most likely case that a user will run into. Approved-By: Tom Tromey <tom@tromey.com>
699 lines
20 KiB
C
699 lines
20 KiB
C
/* gdb commands implemented in Python
|
||
|
||
Copyright (C) 2008-2023 Free Software Foundation, Inc.
|
||
|
||
This file is part of GDB.
|
||
|
||
This program is free software; you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation; either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||
|
||
|
||
#include "defs.h"
|
||
#include "arch-utils.h"
|
||
#include "value.h"
|
||
#include "python-internal.h"
|
||
#include "charset.h"
|
||
#include "gdbcmd.h"
|
||
#include "cli/cli-decode.h"
|
||
#include "completer.h"
|
||
#include "language.h"
|
||
|
||
/* Struct representing built-in completion types. */
|
||
struct cmdpy_completer
|
||
{
|
||
/* Python symbol name. */
|
||
const char *name;
|
||
/* Completion function. */
|
||
completer_ftype *completer;
|
||
};
|
||
|
||
static const struct cmdpy_completer completers[] =
|
||
{
|
||
{ "COMPLETE_NONE", noop_completer },
|
||
{ "COMPLETE_FILENAME", filename_completer },
|
||
{ "COMPLETE_LOCATION", location_completer },
|
||
{ "COMPLETE_COMMAND", command_completer },
|
||
{ "COMPLETE_SYMBOL", symbol_completer },
|
||
{ "COMPLETE_EXPRESSION", expression_completer },
|
||
};
|
||
|
||
#define N_COMPLETERS (sizeof (completers) / sizeof (completers[0]))
|
||
|
||
/* A gdb command. For the time being only ordinary commands (not
|
||
set/show commands) are allowed. */
|
||
struct cmdpy_object
|
||
{
|
||
PyObject_HEAD
|
||
|
||
/* The corresponding gdb command object, or NULL if the command is
|
||
no longer installed. */
|
||
struct cmd_list_element *command;
|
||
|
||
/* A prefix command requires storage for a list of its sub-commands.
|
||
A pointer to this is passed to add_prefix_command, and to add_cmd
|
||
for sub-commands of that prefix. If this Command is not a prefix
|
||
command, then this field is unused. */
|
||
struct cmd_list_element *sub_list;
|
||
};
|
||
|
||
extern PyTypeObject cmdpy_object_type
|
||
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("cmdpy_object");
|
||
|
||
/* Constants used by this module. */
|
||
static PyObject *invoke_cst;
|
||
static PyObject *complete_cst;
|
||
|
||
|
||
|
||
/* Python function which wraps dont_repeat. */
|
||
static PyObject *
|
||
cmdpy_dont_repeat (PyObject *self, PyObject *args)
|
||
{
|
||
dont_repeat ();
|
||
Py_RETURN_NONE;
|
||
}
|
||
|
||
|
||
|
||
/* Called if the gdb cmd_list_element is destroyed. */
|
||
|
||
static void
|
||
cmdpy_destroyer (struct cmd_list_element *self, void *context)
|
||
{
|
||
gdbpy_enter enter_py;
|
||
|
||
/* Release our hold on the command object. */
|
||
gdbpy_ref<cmdpy_object> cmd ((cmdpy_object *) context);
|
||
cmd->command = NULL;
|
||
}
|
||
|
||
/* Called by gdb to invoke the command. */
|
||
|
||
static void
|
||
cmdpy_function (const char *args, int from_tty, cmd_list_element *command)
|
||
{
|
||
cmdpy_object *obj = (cmdpy_object *) command->context ();
|
||
|
||
gdbpy_enter enter_py;
|
||
|
||
if (! obj)
|
||
error (_("Invalid invocation of Python command object."));
|
||
if (! PyObject_HasAttr ((PyObject *) obj, invoke_cst))
|
||
{
|
||
if (obj->command->is_prefix ())
|
||
{
|
||
/* A prefix command does not need an invoke method. */
|
||
return;
|
||
}
|
||
error (_("Python command object missing 'invoke' method."));
|
||
}
|
||
|
||
if (! args)
|
||
args = "";
|
||
gdbpy_ref<> argobj (PyUnicode_Decode (args, strlen (args), host_charset (),
|
||
NULL));
|
||
if (argobj == NULL)
|
||
{
|
||
gdbpy_print_stack ();
|
||
error (_("Could not convert arguments to Python string."));
|
||
}
|
||
|
||
gdbpy_ref<> ttyobj (PyBool_FromLong (from_tty));
|
||
gdbpy_ref<> result (PyObject_CallMethodObjArgs ((PyObject *) obj, invoke_cst,
|
||
argobj.get (), ttyobj.get (),
|
||
NULL));
|
||
|
||
if (result == NULL)
|
||
gdbpy_handle_exception ();
|
||
}
|
||
|
||
/* 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.
|
||
|
||
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 a reference to the PyObject representing the
|
||
Python method call. */
|
||
|
||
static gdbpy_ref<>
|
||
cmdpy_completer_helper (struct cmd_list_element *command,
|
||
const char *text, const char *word)
|
||
{
|
||
cmdpy_object *obj = (cmdpy_object *) command->context ();
|
||
|
||
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;
|
||
}
|
||
|
||
gdbpy_ref<> textobj (PyUnicode_Decode (text, strlen (text), host_charset (),
|
||
NULL));
|
||
if (textobj == NULL)
|
||
{
|
||
gdbpy_print_stack ();
|
||
error (_("Could not convert argument to Python string."));
|
||
}
|
||
|
||
gdbpy_ref<> wordobj;
|
||
if (word == NULL)
|
||
{
|
||
/* "brkchars" phase. */
|
||
wordobj = gdbpy_ref<>::new_reference (Py_None);
|
||
}
|
||
else
|
||
{
|
||
wordobj.reset (PyUnicode_Decode (word, strlen (word), host_charset (),
|
||
NULL));
|
||
if (wordobj == NULL)
|
||
{
|
||
gdbpy_print_stack ();
|
||
error (_("Could not convert argument to Python string."));
|
||
}
|
||
}
|
||
|
||
gdbpy_ref<> resultobj (PyObject_CallMethodObjArgs ((PyObject *) obj,
|
||
complete_cst,
|
||
textobj.get (),
|
||
wordobj.get (), NULL));
|
||
|
||
/* Check if an exception was raised by the Command.complete method. */
|
||
if (resultobj == nullptr)
|
||
{
|
||
gdbpy_print_stack_or_quit ();
|
||
error (_("exception raised during Command.complete method"));
|
||
}
|
||
|
||
return resultobj;
|
||
}
|
||
|
||
/* Python function called to determine the break characters of a
|
||
certain completer. We are only interested in knowing if the
|
||
completer registered by the user will return one of the integer
|
||
codes (see COMPLETER_* symbols). */
|
||
|
||
static void
|
||
cmdpy_completer_handle_brkchars (struct cmd_list_element *command,
|
||
completion_tracker &tracker,
|
||
const char *text, const char *word)
|
||
{
|
||
gdbpy_enter enter_py;
|
||
|
||
/* Calling our helper to obtain a reference to the PyObject of the Python
|
||
function. */
|
||
gdbpy_ref<> resultobj = cmdpy_completer_helper (command, text, word);
|
||
|
||
/* Check if there was an error. */
|
||
if (resultobj == NULL)
|
||
return;
|
||
|
||
if (PyLong_Check (resultobj.get ()))
|
||
{
|
||
/* User code may also return one of the completion constants,
|
||
thus requesting that sort of completion. We are only
|
||
interested in this kind of return. */
|
||
long value;
|
||
|
||
if (!gdb_py_int_as_long (resultobj.get (), &value))
|
||
gdbpy_print_stack ();
|
||
else if (value >= 0 && value < (long) N_COMPLETERS)
|
||
{
|
||
completer_handle_brkchars_ftype *brkchars_fn;
|
||
|
||
/* This is the core of this function. Depending on which
|
||
completer type the Python function returns, we have to
|
||
adjust the break characters accordingly. */
|
||
brkchars_fn = (completer_handle_brkchars_func_for_completer
|
||
(completers[value].completer));
|
||
brkchars_fn (command, tracker, text, word);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Called by gdb for command completion. */
|
||
|
||
static void
|
||
cmdpy_completer (struct cmd_list_element *command,
|
||
completion_tracker &tracker,
|
||
const char *text, const char *word)
|
||
{
|
||
gdbpy_enter enter_py;
|
||
|
||
/* Calling our helper to obtain a reference to the PyObject of the Python
|
||
function. */
|
||
gdbpy_ref<> 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. */
|
||
if (resultobj == NULL)
|
||
return;
|
||
|
||
if (PyLong_Check (resultobj.get ()))
|
||
{
|
||
/* User code may also return one of the completion constants,
|
||
thus requesting that sort of completion. */
|
||
long value;
|
||
|
||
if (! gdb_py_int_as_long (resultobj.get (), &value))
|
||
gdbpy_print_stack ();
|
||
else if (value >= 0 && value < (long) N_COMPLETERS)
|
||
completers[value].completer (command, tracker, text, word);
|
||
}
|
||
else if (PySequence_Check (resultobj.get ()))
|
||
{
|
||
gdbpy_ref<> iter (PyObject_GetIter (resultobj.get ()));
|
||
|
||
if (iter == NULL)
|
||
{
|
||
gdbpy_print_stack ();
|
||
return;
|
||
}
|
||
|
||
while (true)
|
||
{
|
||
gdbpy_ref<> elt (PyIter_Next (iter.get ()));
|
||
if (elt == NULL)
|
||
{
|
||
if (PyErr_Occurred() != nullptr)
|
||
gdbpy_print_stack ();
|
||
break;
|
||
}
|
||
|
||
if (! gdbpy_is_string (elt.get ()))
|
||
{
|
||
/* Skip problem elements. */
|
||
continue;
|
||
}
|
||
|
||
gdb::unique_xmalloc_ptr<char>
|
||
item (python_string_to_host_string (elt.get ()));
|
||
if (item == NULL)
|
||
{
|
||
gdbpy_print_stack ();
|
||
continue;
|
||
}
|
||
tracker.add_completion (std::move (item));
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Helper for cmdpy_init which locates the command list to use and
|
||
pulls out the command name.
|
||
|
||
NAME is the command name list. The final word in the list is the
|
||
name of the new command. All earlier words must be existing prefix
|
||
commands.
|
||
|
||
*BASE_LIST is set to the final prefix command's list of
|
||
*sub-commands.
|
||
|
||
START_LIST is the list in which the search starts.
|
||
|
||
This function returns the name of the new command. On error sets the Python
|
||
error and returns NULL. */
|
||
|
||
gdb::unique_xmalloc_ptr<char>
|
||
gdbpy_parse_command_name (const char *name,
|
||
struct cmd_list_element ***base_list,
|
||
struct cmd_list_element **start_list)
|
||
{
|
||
struct cmd_list_element *elt;
|
||
int len = strlen (name);
|
||
int i, lastchar;
|
||
const char *prefix_text2;
|
||
|
||
/* Skip trailing whitespace. */
|
||
for (i = len - 1; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i)
|
||
;
|
||
if (i < 0)
|
||
{
|
||
PyErr_SetString (PyExc_RuntimeError, _("No command name found."));
|
||
return NULL;
|
||
}
|
||
lastchar = i;
|
||
|
||
/* Find first character of the final word. */
|
||
for (; i > 0 && valid_cmd_char_p (name[i - 1]); --i)
|
||
;
|
||
|
||
gdb::unique_xmalloc_ptr<char> result ((char *) xmalloc (lastchar - i + 2));
|
||
memcpy (result.get (), &name[i], lastchar - i + 1);
|
||
result.get ()[lastchar - i + 1] = '\0';
|
||
|
||
/* Skip whitespace again. */
|
||
for (--i; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i)
|
||
;
|
||
if (i < 0)
|
||
{
|
||
*base_list = start_list;
|
||
return result;
|
||
}
|
||
|
||
std::string prefix_text (name, i + 1);
|
||
|
||
prefix_text2 = prefix_text.c_str ();
|
||
elt = lookup_cmd_1 (&prefix_text2, *start_list, NULL, NULL, 1);
|
||
if (elt == NULL || elt == CMD_LIST_AMBIGUOUS)
|
||
{
|
||
PyErr_Format (PyExc_RuntimeError, _("Could not find command prefix %s."),
|
||
prefix_text.c_str ());
|
||
return NULL;
|
||
}
|
||
|
||
if (elt->is_prefix ())
|
||
{
|
||
*base_list = elt->subcommands;
|
||
return result;
|
||
}
|
||
|
||
PyErr_Format (PyExc_RuntimeError, _("'%s' is not a prefix command."),
|
||
prefix_text.c_str ());
|
||
return NULL;
|
||
}
|
||
|
||
/* Object initializer; sets up gdb-side structures for command.
|
||
|
||
Use: __init__(NAME, COMMAND_CLASS [, COMPLETER_CLASS][, PREFIX]]).
|
||
|
||
NAME is the name of the command. It may consist of multiple words,
|
||
in which case the final word is the name of the new command, and
|
||
earlier words must be prefix commands.
|
||
|
||
COMMAND_CLASS is the kind of command. It should be one of the COMMAND_*
|
||
constants defined in the gdb module.
|
||
|
||
COMPLETER_CLASS is the kind of completer. If not given, the
|
||
"complete" method will be used. Otherwise, it should be one of the
|
||
COMPLETE_* constants defined in the gdb module.
|
||
|
||
If PREFIX is True, then this command is a prefix command.
|
||
|
||
The documentation for the command is taken from the doc string for
|
||
the python class. */
|
||
|
||
static int
|
||
cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
|
||
{
|
||
cmdpy_object *obj = (cmdpy_object *) self;
|
||
const char *name;
|
||
int cmdtype;
|
||
int completetype = -1;
|
||
struct cmd_list_element **cmd_list;
|
||
static const char *keywords[] = { "name", "command_class", "completer_class",
|
||
"prefix", NULL };
|
||
PyObject *is_prefix_obj = NULL;
|
||
bool is_prefix = false;
|
||
|
||
if (obj->command)
|
||
{
|
||
/* Note: this is apparently not documented in Python. We return
|
||
0 for success, -1 for failure. */
|
||
PyErr_Format (PyExc_RuntimeError,
|
||
_("Command object already initialized."));
|
||
return -1;
|
||
}
|
||
|
||
if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "si|iO",
|
||
keywords, &name, &cmdtype,
|
||
&completetype, &is_prefix_obj))
|
||
return -1;
|
||
|
||
if (cmdtype != no_class && cmdtype != class_run
|
||
&& cmdtype != class_vars && cmdtype != class_stack
|
||
&& cmdtype != class_files && cmdtype != class_support
|
||
&& cmdtype != class_info && cmdtype != class_breakpoint
|
||
&& cmdtype != class_trace && cmdtype != class_obscure
|
||
&& cmdtype != class_maintenance && cmdtype != class_user
|
||
&& cmdtype != class_tui)
|
||
{
|
||
PyErr_Format (PyExc_RuntimeError, _("Invalid command class argument."));
|
||
return -1;
|
||
}
|
||
|
||
if (completetype < -1 || completetype >= (int) N_COMPLETERS)
|
||
{
|
||
PyErr_Format (PyExc_RuntimeError,
|
||
_("Invalid completion type argument."));
|
||
return -1;
|
||
}
|
||
|
||
gdb::unique_xmalloc_ptr<char> cmd_name
|
||
= gdbpy_parse_command_name (name, &cmd_list, &cmdlist);
|
||
if (cmd_name == nullptr)
|
||
return -1;
|
||
|
||
if (is_prefix_obj != NULL)
|
||
{
|
||
int cmp = PyObject_IsTrue (is_prefix_obj);
|
||
if (cmp < 0)
|
||
return -1;
|
||
|
||
is_prefix = cmp > 0;
|
||
}
|
||
|
||
gdb::unique_xmalloc_ptr<char> docstring = nullptr;
|
||
if (PyObject_HasAttr (self, gdbpy_doc_cst))
|
||
{
|
||
gdbpy_ref<> ds_obj (PyObject_GetAttr (self, gdbpy_doc_cst));
|
||
|
||
if (ds_obj != NULL && gdbpy_is_string (ds_obj.get ()))
|
||
{
|
||
docstring = python_string_to_host_string (ds_obj.get ());
|
||
if (docstring == nullptr)
|
||
return -1;
|
||
docstring = gdbpy_fix_doc_string_indentation (std::move (docstring));
|
||
}
|
||
}
|
||
if (docstring == nullptr)
|
||
docstring = make_unique_xstrdup (_("This command is not documented."));
|
||
|
||
gdbpy_ref<> self_ref = gdbpy_ref<>::new_reference (self);
|
||
|
||
try
|
||
{
|
||
struct cmd_list_element *cmd;
|
||
|
||
if (is_prefix)
|
||
{
|
||
int allow_unknown;
|
||
|
||
/* If we have our own "invoke" method, then allow unknown
|
||
sub-commands. */
|
||
allow_unknown = PyObject_HasAttr (self, invoke_cst);
|
||
cmd = add_prefix_cmd (cmd_name.get (),
|
||
(enum command_class) cmdtype,
|
||
NULL, docstring.release (), &obj->sub_list,
|
||
allow_unknown, cmd_list);
|
||
}
|
||
else
|
||
cmd = add_cmd (cmd_name.get (), (enum command_class) cmdtype,
|
||
docstring.release (), cmd_list);
|
||
|
||
/* If successful, the above takes ownership of the name, since we set
|
||
name_allocated, so release it. */
|
||
cmd_name.release ();
|
||
|
||
/* There appears to be no API to set this. */
|
||
cmd->func = cmdpy_function;
|
||
cmd->destroyer = cmdpy_destroyer;
|
||
cmd->doc_allocated = 1;
|
||
cmd->name_allocated = 1;
|
||
|
||
obj->command = cmd;
|
||
cmd->set_context (self_ref.release ());
|
||
set_cmd_completer (cmd, ((completetype == -1) ? cmdpy_completer
|
||
: completers[completetype].completer));
|
||
if (completetype == -1)
|
||
set_cmd_completer_handle_brkchars (cmd,
|
||
cmdpy_completer_handle_brkchars);
|
||
}
|
||
catch (const gdb_exception &except)
|
||
{
|
||
gdbpy_convert_exception (except);
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
/* Initialize the 'commands' code. */
|
||
|
||
static int CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION
|
||
gdbpy_initialize_commands (void)
|
||
{
|
||
int i;
|
||
|
||
cmdpy_object_type.tp_new = PyType_GenericNew;
|
||
if (PyType_Ready (&cmdpy_object_type) < 0)
|
||
return -1;
|
||
|
||
/* Note: alias and user are special. */
|
||
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
|
||
|| PyModule_AddIntConstant (gdb_module, "COMMAND_STACK", class_stack) < 0
|
||
|| PyModule_AddIntConstant (gdb_module, "COMMAND_FILES", class_files) < 0
|
||
|| PyModule_AddIntConstant (gdb_module, "COMMAND_SUPPORT",
|
||
class_support) < 0
|
||
|| PyModule_AddIntConstant (gdb_module, "COMMAND_STATUS", class_info) < 0
|
||
|| PyModule_AddIntConstant (gdb_module, "COMMAND_BREAKPOINTS",
|
||
class_breakpoint) < 0
|
||
|| PyModule_AddIntConstant (gdb_module, "COMMAND_TRACEPOINTS",
|
||
class_trace) < 0
|
||
|| PyModule_AddIntConstant (gdb_module, "COMMAND_OBSCURE",
|
||
class_obscure) < 0
|
||
|| PyModule_AddIntConstant (gdb_module, "COMMAND_MAINTENANCE",
|
||
class_maintenance) < 0
|
||
|| PyModule_AddIntConstant (gdb_module, "COMMAND_USER", class_user) < 0
|
||
|| PyModule_AddIntConstant (gdb_module, "COMMAND_TUI", class_tui) < 0)
|
||
return -1;
|
||
|
||
for (i = 0; i < N_COMPLETERS; ++i)
|
||
{
|
||
if (PyModule_AddIntConstant (gdb_module, completers[i].name, i) < 0)
|
||
return -1;
|
||
}
|
||
|
||
if (gdb_pymodule_addobject (gdb_module, "Command",
|
||
(PyObject *) &cmdpy_object_type) < 0)
|
||
return -1;
|
||
|
||
invoke_cst = PyUnicode_FromString ("invoke");
|
||
if (invoke_cst == NULL)
|
||
return -1;
|
||
complete_cst = PyUnicode_FromString ("complete");
|
||
if (complete_cst == NULL)
|
||
return -1;
|
||
|
||
return 0;
|
||
}
|
||
|
||
GDBPY_INITIALIZE_FILE (gdbpy_initialize_commands);
|
||
|
||
|
||
|
||
static PyMethodDef cmdpy_object_methods[] =
|
||
{
|
||
{ "dont_repeat", cmdpy_dont_repeat, METH_NOARGS,
|
||
"Prevent command repetition when user enters empty line." },
|
||
|
||
{ 0 }
|
||
};
|
||
|
||
PyTypeObject cmdpy_object_type =
|
||
{
|
||
PyVarObject_HEAD_INIT (NULL, 0)
|
||
"gdb.Command", /*tp_name*/
|
||
sizeof (cmdpy_object), /*tp_basicsize*/
|
||
0, /*tp_itemsize*/
|
||
0, /*tp_dealloc*/
|
||
0, /*tp_print*/
|
||
0, /*tp_getattr*/
|
||
0, /*tp_setattr*/
|
||
0, /*tp_compare*/
|
||
0, /*tp_repr*/
|
||
0, /*tp_as_number*/
|
||
0, /*tp_as_sequence*/
|
||
0, /*tp_as_mapping*/
|
||
0, /*tp_hash */
|
||
0, /*tp_call*/
|
||
0, /*tp_str*/
|
||
0, /*tp_getattro*/
|
||
0, /*tp_setattro*/
|
||
0, /*tp_as_buffer*/
|
||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
|
||
"GDB command object", /* tp_doc */
|
||
0, /* tp_traverse */
|
||
0, /* tp_clear */
|
||
0, /* tp_richcompare */
|
||
0, /* tp_weaklistoffset */
|
||
0, /* tp_iter */
|
||
0, /* tp_iternext */
|
||
cmdpy_object_methods, /* tp_methods */
|
||
0, /* tp_members */
|
||
0, /* tp_getset */
|
||
0, /* tp_base */
|
||
0, /* tp_dict */
|
||
0, /* tp_descr_get */
|
||
0, /* tp_descr_set */
|
||
0, /* tp_dictoffset */
|
||
cmdpy_init, /* tp_init */
|
||
0, /* tp_alloc */
|
||
};
|
||
|
||
|
||
|
||
/* Utility to build a buildargv-like result from ARGS.
|
||
This intentionally parses arguments the way libiberty/argv.c:buildargv
|
||
does. It splits up arguments in a reasonable way, and we want a standard
|
||
way of parsing arguments. Several gdb commands use buildargv to parse their
|
||
arguments. Plus we want to be able to write compatible python
|
||
implementations of gdb commands. */
|
||
|
||
PyObject *
|
||
gdbpy_string_to_argv (PyObject *self, PyObject *args)
|
||
{
|
||
const char *input;
|
||
|
||
if (!PyArg_ParseTuple (args, "s", &input))
|
||
return NULL;
|
||
|
||
gdbpy_ref<> py_argv (PyList_New (0));
|
||
if (py_argv == NULL)
|
||
return NULL;
|
||
|
||
/* buildargv uses NULL to represent an empty argument list, but we can't use
|
||
that in Python. Instead, if ARGS is "" then return an empty list.
|
||
This undoes the NULL -> "" conversion that cmdpy_function does. */
|
||
|
||
if (*input != '\0')
|
||
{
|
||
gdb_argv c_argv (input);
|
||
|
||
for (char *arg : c_argv)
|
||
{
|
||
gdbpy_ref<> argp (PyUnicode_FromString (arg));
|
||
|
||
if (argp == NULL
|
||
|| PyList_Append (py_argv.get (), argp.get ()) < 0)
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
return py_argv.release ();
|
||
}
|