2009-02-06  Tom Tromey  <tromey@redhat.com>

	* Makefile.in (SUBDIR_PYTHON_OBS): Add python-cmd.o.
	(SUBDIR_PYTHON_SRCS): Add python-cmd.c.
	(python-cmd.o): New target.
	* cli/cli-decode.c (set_cmd_completer): Add self parameter to
	completer prototype.
	(add_cmd): Initialize destroyer member of cmd_list_element. Use
	make_symbol_completion_list_fn as completer.
	(delete_cmd): Call destroyer if one is set.
	* cli/cli-decode.h (cmd_list_element): Add cmd parameter to
	completer member.  Add destroyer member.
	(set_cmd_completer): Add self parameter to
	completer prototype.
	* command.h (set_cmd_completer): Add cmd parameter to
	completer prototype.
	* completer.c (noop_completer, filename_completer,
	location_completer, expression_completer, command_completer): Adapt
	to new completer prototype.
	(complete_line_internal): Pass new parameter to completer function.
	* completer.h (noop_completer, filename_completer,
	location_completer, expression_completer, command_completer): Adapt
	prototypes to new completer prototype.
	* interps.c (interpreter_completer): Adapt to new completer
	prototype.
	* python/python-cmd.c: New file.
	* python/python-internal.h (gdbpy_initialize_commands): Add
	prototype.
	(gdbpy_doc_cst): Add forward declaration.
	* python/python.c (gdbpy_doc_cst): Declare.
	(_initialize_python): Call gdbpy_initialize_commands.  Initialize
	gdbpy_doc_cst.
	* symtab.c (make_symbol_completion_list_fn): New function.
	* symtab.h (make_symbol_completion_list_fn): Add prototype.

gdb/doc/
2009-02-06  Tom Tromey  <tromey@redhat.com>

	* gdb.texinfo (Python API): Add entry for Commands In Python.
	(Commands In Python): New node.

gdb/testsuite/
2009-02-06  Thiago Jung Bauermann  <bauerman@br.ibm.com>

	* gdb.python/python-cmd.exp: New file.
This commit is contained in:
Thiago Jung Bauermann 2009-02-06 21:33:59 +00:00
parent f073bbf7e0
commit d8906c6f0e
17 changed files with 943 additions and 20 deletions

View File

@ -1,3 +1,38 @@
2009-02-06 Tom Tromey <tromey@redhat.com>
* Makefile.in (SUBDIR_PYTHON_OBS): Add python-cmd.o.
(SUBDIR_PYTHON_SRCS): Add python-cmd.c.
(python-cmd.o): New target.
* cli/cli-decode.c (set_cmd_completer): Add self parameter to
completer prototype.
(add_cmd): Initialize destroyer member of cmd_list_element. Use
make_symbol_completion_list_fn as completer.
(delete_cmd): Call destroyer if one is set.
* cli/cli-decode.h (cmd_list_element): Add cmd parameter to
completer member. Add destroyer member.
(set_cmd_completer): Add self parameter to
completer prototype.
* command.h (set_cmd_completer): Add cmd parameter to
completer prototype.
* completer.c (noop_completer, filename_completer,
location_completer, expression_completer, command_completer): Adapt
to new completer prototype.
(complete_line_internal): Pass new parameter to completer function.
* completer.h (noop_completer, filename_completer,
location_completer, expression_completer, command_completer): Adapt
prototypes to new completer prototype.
* interps.c (interpreter_completer): Adapt to new completer
prototype.
* python/python-cmd.c: New file.
* python/python-internal.h (gdbpy_initialize_commands): Add
prototype.
(gdbpy_doc_cst): Add forward declaration.
* python/python.c (gdbpy_doc_cst): Declare.
(_initialize_python): Call gdbpy_initialize_commands. Initialize
gdbpy_doc_cst.
* symtab.c (make_symbol_completion_list_fn): New function.
* symtab.h (make_symbol_completion_list_fn): Add prototype.
2009-02-06 Pedro Alves <pedro@codesourcery.com>
* target.c (target_get_osdata): Check for equal or higher than

View File

@ -270,10 +270,12 @@ SUBDIR_TUI_CFLAGS= \
#
SUBDIR_PYTHON_OBS = \
python.o \
python-cmd.o \
python-utils.o \
python-value.o
SUBDIR_PYTHON_SRCS = \
python/python.c \
python/python-cmd.c \
python/python-utils.c \
python/python-value.c
SUBDIR_PYTHON_DEPS =
@ -1836,6 +1838,10 @@ python.o: $(srcdir)/python/python.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
$(POSTCOMPILE)
python-cmd.o: $(srcdir)/python/python-cmd.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-cmd.c
$(POSTCOMPILE)
python-utils.o: $(srcdir)/python/python-utils.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python-utils.c
$(POSTCOMPILE)

View File

@ -96,6 +96,8 @@ are treated as the standard definitions, regardless of context.
GDB now has support for scripting using Python. Whether this is
available is determined at configure time.
New GDB commands can now be written in Python.
* Ada tasking support
Ada tasks can now be inspected in GDB. The following commands have

View File

@ -132,7 +132,8 @@ cmd_type (struct cmd_list_element *cmd)
void
set_cmd_completer (struct cmd_list_element *cmd,
char **(*completer) (char *text, char *word))
char **(*completer) (struct cmd_list_element *self,
char *text, char *word))
{
cmd->completer = completer; /* Ok. */
}
@ -207,7 +208,8 @@ add_cmd (char *name, enum command_class class, void (*fun) (char *, int),
c->prefixname = NULL;
c->allow_unknown = 0;
c->abbrev_flag = 0;
set_cmd_completer (c, make_symbol_completion_list);
set_cmd_completer (c, make_symbol_completion_list_fn);
c->destroyer = NULL;
c->type = not_set_cmd;
c->var = NULL;
c->var_type = var_boolean;
@ -688,6 +690,8 @@ delete_cmd (char *name, struct cmd_list_element **list,
{
if (strcmp (iter->name, name) == 0)
{
if (iter->destroyer)
iter->destroyer (iter, iter->context);
if (iter->hookee_pre)
iter->hookee_pre->hook_pre = 0;
*prehook = iter->hook_pre;

View File

@ -167,7 +167,12 @@ struct cmd_list_element
returned relative to this position. For example, suppose TEXT is "foo"
and we want to complete to "foobar". If WORD is "oo", return
"oobar"; if WORD is "baz/foo", return "baz/foobar". */
char **(*completer) (char *text, char *word);
char **(*completer) (struct cmd_list_element *cmd, char *text, char *word);
/* Destruction routine for this command. If non-NULL, this is
called when this command instance is destroyed. This may be
used to finalize the CONTEXT field, if needed. */
void (*destroyer) (struct cmd_list_element *self, void *context);
/* Type of "set" or "show" command (or SET_NOT_SET if not "set"
or "show"). */
@ -242,7 +247,8 @@ extern void set_cmd_sfunc (struct cmd_list_element *cmd,
struct cmd_list_element * c));
extern void set_cmd_completer (struct cmd_list_element *cmd,
char **(*completer) (char *text, char *word));
char **(*completer) (struct cmd_list_element *self,
char *text, char *word));
/* HACK: cagney/2002-02-23: Code, mostly in tracepoints.c, grubs
around in cmd objects to test the value of the commands sfunc(). */

View File

@ -138,7 +138,8 @@ extern void set_cmd_sfunc (struct cmd_list_element *cmd,
cmd_sfunc_ftype *sfunc);
extern void set_cmd_completer (struct cmd_list_element *cmd,
char **(*completer) (char *text, char *word));
char **(*completer) (struct cmd_list_element *cmd,
char *text, char *word));
/* HACK: cagney/2002-02-23: Code, mostly in tracepoints.c, grubs
around in cmd objects to test the value of the commands sfunc(). */

View File

@ -105,14 +105,14 @@ readline_line_completion_function (const char *text, int matches)
/* This can be used for functions which don't want to complete on symbols
but don't want to complete on anything else either. */
char **
noop_completer (char *text, char *prefix)
noop_completer (struct cmd_list_element *ignore, char *text, char *prefix)
{
return NULL;
}
/* Complete on filenames. */
char **
filename_completer (char *text, char *word)
filename_completer (struct cmd_list_element *ignore, char *text, char *word)
{
int subsequent_name;
char **return_val;
@ -195,7 +195,7 @@ filename_completer (char *text, char *word)
This is intended to be used in commands that set breakpoints etc. */
char **
location_completer (char *text, char *word)
location_completer (struct cmd_list_element *ignore, char *text, char *word)
{
int n_syms = 0, n_files = 0;
char ** fn_list = NULL;
@ -412,7 +412,7 @@ add_struct_fields (struct type *type, int *nextp, char **output,
names, but some language parsers also have support for completing
field names. */
char **
expression_completer (char *text, char *word)
expression_completer (struct cmd_list_element *ignore, char *text, char *word)
{
struct type *type;
char *fieldname, *p;
@ -456,7 +456,7 @@ expression_completer (char *text, char *word)
;
/* Not ideal but it is what we used to do before... */
return location_completer (p, word);
return location_completer (ignore, p, word);
}
/* Here are some useful test cases for completion. FIXME: These should
@ -651,7 +651,7 @@ complete_line_internal (const char *text, char *line_buffer, int point,
p--)
;
}
list = (*c->completer) (p, word);
list = (*c->completer) (c, p, word);
}
}
else
@ -719,7 +719,7 @@ complete_line_internal (const char *text, char *line_buffer, int point,
p--)
;
}
list = (*c->completer) (p, word);
list = (*c->completer) (c, p, word);
}
}
}
@ -737,7 +737,7 @@ complete_line (const char *text, char *line_buffer, int point)
/* Complete on command names. Used by "help". */
char **
command_completer (char *text, char *word)
command_completer (struct cmd_list_element *ignore, char *text, char *word)
{
return complete_line_internal (word, text, strlen (text), 1);
}

View File

@ -21,15 +21,15 @@ extern char **complete_line (const char *text, char *line_buffer, int point);
extern char *readline_line_completion_function (const char *text, int matches);
extern char **noop_completer (char *, char *);
extern char **noop_completer (struct cmd_list_element *, char *, char *);
extern char **filename_completer (char *, char *);
extern char **filename_completer (struct cmd_list_element *, char *, char *);
extern char **expression_completer (char *, char *);
extern char **expression_completer (struct cmd_list_element *, char *, char *);
extern char **location_completer (char *, char *);
extern char **location_completer (struct cmd_list_element *, char *, char *);
extern char **command_completer (char *, char *);
extern char **command_completer (struct cmd_list_element *, char *, char *);
extern char *get_gdb_completer_quote_characters (void);

View File

@ -1,3 +1,8 @@
2009-02-06 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Python API): Add entry for Commands In Python.
(Commands In Python): New node.
2009-02-05 Tom Tromey <tromey@redhat.com>
* gdb.texinfo (Values From Inferior): Document Value.string.

View File

@ -18064,6 +18064,7 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
* Basic Python:: Basic Python Functions.
* Exception Handling::
* Values From Inferior::
* Commands In Python:: Implementing new commands in Python.
@end menu
@node Basic Python
@ -18246,6 +18247,259 @@ The optional @var{errors} argument is the same as the corresponding
argument to Python's @code{string.decode} method.
@end defmethod
@node Commands In Python
@subsubsection Commands In Python
@cindex commands in python
@cindex python commands
@tindex Command
@tindex gdb.Command
You can implement new @value{GDBN} CLI commands in Python. A CLI
command is implemented using an instance of the @code{gdb.Command}
class, most commonly using a subclass.
@defmethod Command __init__ name @var{command-class} @r{[}@var{completer-class} @var{prefix}@r{]}
The object initializer for @code{Command} registers the new command
with @value{GDBN}. This initializer is normally invoked from the
subclass' own @code{__init__} method.
@var{name} is the name of the command. If @var{name} consists of
multiple words, then the initial words are looked for as prefix
commands. In this case, if one of the prefix commands does not exist,
an exception is raised.
There is no support for multi-line commands.
@var{command-class} should be one of the @samp{COMMAND_} constants
defined below. This argument tells @value{GDBN} how to categorize the
new command in the help system.
@var{completer-class} is an optional argument. If given, it should be
one of the @samp{COMPLETE_} constants defined below. This argument
tells @value{GDBN} how to perform completion for this command. If not
given, @value{GDBN} will attempt to complete using the object's
@code{complete} method (see below); if no such method is found, an
error will occur when completion is attempted.
@var{prefix} is an optional argument. If @code{True}, then the new
command is a prefix command; sub-commands of this command may be
registered.
The help text for the new command is taken from the Python
documentation string for the command's class, if there is one. If no
documentation string is provided, the default value ``This command is
not documented.'' is used.
@end defmethod
@defmethod Command dont_repeat
By default, a @value{GDBN} command is repeated when the user enters a
blank line at the command prompt. A command can suppress this
behavior by invoking the @code{dont_repeat} method. This is similar
to the user command @code{dont-repeat}, see @ref{Define, dont-repeat}.
@end defmethod
@defmethod Command invoke argument from_tty
This method is called by @value{GDBN} when this command is invoked.
@var{argument} is a string. It is the argument to the command, after
leading and trailing whitespace has been stripped.
@var{from_tty} is a boolean argument. When true, this means that the
command was entered by the user at the terminal; when false it means
that the command came from elsewhere.
If this method throws an exception, it is turned into a @value{GDBN}
@code{error} call. Otherwise, the return value is ignored.
@end defmethod
@defmethod Command complete text word
This method is called by @value{GDBN} when the user attempts
completion on this command. All forms of completion are handled by
this method, that is, the @key{TAB} and @key{M-?} key bindings, and
the @code{complete} command.
The arguments @var{text} and @var{word} are both strings. @var{text}
holds the complete command line up to the cursor's location.
@var{word} holds the last word of the command line; this is computed
using a word-breaking heuristic.
The @code{complete} method can return several values:
@itemize @bullet
@item
If the return value is a sequence, the contents of the sequence are
used as the completions. It is up to @code{complete} to ensure that the
contents actually do complete the word. A zero-length sequence is
allowed, it means that there were no completions available. Only
string elements of the sequence are used; other elements in the
sequence are ignored.
@item
If the return value is one of the @samp{COMPLETE_} constants defined
below, then the corresponding @value{GDBN}-internal completion
function is invoked, and its result is used.
@item
All other results are treated as though there were no available
completions.
@end itemize
@end defmethod
When a new command is registered, it must be declared as a member of
some general class of commands. This is used to classify top-level
commands in the on-line help system; note that prefix commands are not
listed under their own category but rather that of their top-level
command. The available classifications are represented by constants
defined in the @code{gdb} module:
@table @code
@findex COMMAND_NONE
@findex gdb.COMMAND_NONE
@item COMMAND_NONE
The command does not belong to any particular class. A command in
this category will not be displayed in any of the help categories.
@findex COMMAND_RUNNING
@findex gdb.COMMAND_RUNNING
@item COMMAND_RUN
The command is related to running the inferior. For example,
@code{start}, @code{step}, and @code{continue} are in this category.
Type @code{help running} at the @value{GDBN} prompt to see a list of
commands in this category.
@findex COMMAND_DATA
@findex gdb.COMMAND_DATA
@item COMMAND_VARS
The command is related to data or variables. For example,
@code{call}, @code{find}, and @code{print} are in this category. Type
@code{help data} at the @value{GDBN} prompt to see a list of commands
in this category.
@findex COMMAND_STACK
@findex gdb.COMMAND_STACK
@item COMMAND_STACK
The command has to do with manipulation of the stack. For example,
@code{backtrace}, @code{frame}, and @code{return} are in this
category. Type @code{help stack} at the @value{GDBN} prompt to see a
list of commands in this category.
@findex COMMAND_FILES
@findex gdb.COMMAND_FILES
@item COMMAND_FILES
This class is used for file-related commands. For example,
@code{file}, @code{list} and @code{section} are in this category.
Type @code{help files} at the @value{GDBN} prompt to see a list of
commands in this category.
@findex COMMAND_SUPPORT
@findex gdb.COMMAND_SUPPORT
@item COMMAND_SUPPORT
This should be used for ``support facilities'', generally meaning
things that are useful to the user when interacting with @value{GDBN},
but not related to the state of the inferior. For example,
@code{help}, @code{make}, and @code{shell} are in this category. Type
@code{help support} at the @value{GDBN} prompt to see a list of
commands in this category.
@findex COMMAND_STATUS
@findex gdb.COMMAND_STATUS
@item COMMAND_INFO
The command is an @samp{info}-related command, that is, related to the
state of @value{GDBN} itself. For example, @code{info}, @code{macro},
and @code{show} are in this category. Type @code{help status} at the
@value{GDBN} prompt to see a list of commands in this category.
@findex COMMAND_BREAKPOINTS
@findex gdb.COMMAND_BREAKPOINTS
@item COMMAND_BREAKPOINT
The command has to do with breakpoints. For example, @code{break},
@code{clear}, and @code{delete} are in this category. Type @code{help
breakpoints} at the @value{GDBN} prompt to see a list of commands in
this category.
@findex COMMAND_TRACEPOINTS
@findex gdb.COMMAND_TRACEPOINTS
@item COMMAND_TRACE
The command has to do with tracepoints. For example, @code{trace},
@code{actions}, and @code{tfind} are in this category. Type
@code{help tracepoints} at the @value{GDBN} prompt to see a list of
commands in this category.
@findex COMMAND_OBSCURE
@findex gdb.COMMAND_OBSCURE
@item COMMAND_OBSCURE
The command is only used in unusual circumstances, or is not of
general interest to users. For example, @code{checkpoint},
@code{fork}, and @code{stop} are in this category. Type @code{help
obscure} at the @value{GDBN} prompt to see a list of commands in this
category.
@findex COMMAND_MAINTENANCE
@findex gdb.COMMAND_MAINTENANCE
@item COMMAND_MAINTENANCE
The command is only useful to @value{GDBN} maintainers. The
@code{maintenance} and @code{flushregs} commands are in this category.
Type @code{help internals} at the @value{GDBN} prompt to see a list of
commands in this category.
@end table
A new command can use a predefined completion function, either by
specifying it via an argument at initialization, or by returning it
from the @code{complete} method. These predefined completion
constants are all defined in the @code{gdb} module:
@table @code
@findex COMPLETE_NONE
@findex gdb.COMPLETE_NONE
@item COMPLETE_NONE
This constant means that no completion should be done.
@findex COMPLETE_FILENAME
@findex gdb.COMPLETE_FILENAME
@item COMPLETE_FILENAME
This constant means that filename completion should be performed.
@findex COMPLETE_LOCATION
@findex gdb.COMPLETE_LOCATION
@item COMPLETE_LOCATION
This constant means that location completion should be done.
@xref{Specify Location}.
@findex COMPLETE_COMMAND
@findex gdb.COMPLETE_COMMAND
@item COMPLETE_COMMAND
This constant means that completion should examine @value{GDBN}
command names.
@findex COMPLETE_SYMBOL
@findex gdb.COMPLETE_SYMBOL
@item COMPLETE_SYMBOL
This constant means that completion should be done using symbol names
as the source.
@end table
The following code snippet shows how a trivial CLI command can be
implemented in Python:
@smallexample
class HelloWorld (gdb.Command):
"""Greet the whole world."""
def __init__ (self):
super (HelloWorld, self).__init__ ("hello-world", gdb.COMMAND_OBSCURE)
def invoke (self, arg, from_tty):
print "Hello, World!"
HelloWorld ()
@end smallexample
The last line instantiates the class, and is necessary to trigger the
registration of the command with @value{GDBN}. Depending on how the
Python code is read into @value{GDBN}, you may need to import the
@code{gdb} module explicitly.
@node Interpreters
@chapter Command Interpreters
@cindex command interpreters

View File

@ -71,7 +71,8 @@ struct interp
/* Functions local to this file. */
static void initialize_interps (void);
static char **interpreter_completer (char *text, char *word);
static char **interpreter_completer (struct cmd_list_element *cmd,
char *text, char *word);
/* The magic initialization routine for this module. */
@ -416,7 +417,7 @@ interpreter_exec_cmd (char *args, int from_tty)
/* List the possible interpreters which could complete the given text. */
static char **
interpreter_completer (char *text, char *word)
interpreter_completer (struct cmd_list_element *ignore, char *text, char *word)
{
int alloced = 0;
int textlen;

585
gdb/python/python-cmd.c Normal file
View File

@ -0,0 +1,585 @@
/* gdb commands implemented in Python
Copyright (C) 2008, 2009 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 "value.h"
#include "exceptions.h"
#include "python-internal.h"
#include "charset.h"
#include "gdbcmd.h"
#include "cli/cli-decode.h"
#include "completer.h"
/* Struct representing built-in completion types. */
struct cmdpy_completer
{
/* Python symbol name. */
char *name;
/* Completion function. */
char **(*completer) (struct cmd_list_element *, char *, char *);
};
static struct cmdpy_completer completers[] =
{
{ "COMPLETE_NONE", noop_completer },
{ "COMPLETE_FILENAME", filename_completer },
{ "COMPLETE_LOCATION", location_completer },
{ "COMPLETE_COMMAND", command_completer },
{ "COMPLETE_SYMBOL", make_symbol_completion_list_fn },
};
#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;
};
typedef struct cmdpy_object cmdpy_object;
static PyTypeObject cmdpy_object_type;
/* 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)
{
cmdpy_object *cmd;
PyGILState_STATE state;
state = PyGILState_Ensure ();
/* Release our hold on the command object. */
cmd = (cmdpy_object *) context;
cmd->command = NULL;
Py_DECREF (cmd);
/* We allocated the name, doc string, and perhaps the prefix
name. */
xfree (self->name);
xfree (self->doc);
xfree (self->prefixname);
PyGILState_Release (state);
}
/* Called by gdb to invoke the command. */
static void
cmdpy_function (struct cmd_list_element *command, char *args, int from_tty)
{
cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command);
PyObject *argobj, *ttyobj, *result;
struct cleanup *cleanup;
PyGILState_STATE state;
state = PyGILState_Ensure ();
cleanup = make_cleanup_py_restore_gil (&state);
if (! obj)
error (_("Invalid invocation of Python command object."));
if (! PyObject_HasAttr ((PyObject *) obj, invoke_cst))
{
if (obj->command->prefixname)
{
/* A prefix command does not need an invoke method. */
do_cleanups (cleanup);
return;
}
error (_("Python command object missing 'invoke' method."));
}
if (! args)
args = "";
argobj = PyUnicode_Decode (args, strlen (args), host_charset (), NULL);
if (! argobj)
error (_("Could not convert arguments to Python string."));
ttyobj = from_tty ? Py_True : Py_False;
Py_INCREF (ttyobj);
result = PyObject_CallMethodObjArgs ((PyObject *) obj, invoke_cst, argobj,
ttyobj, NULL);
Py_DECREF (argobj);
Py_DECREF (ttyobj);
if (! result)
{
PyObject *ptype, *pvalue, *ptraceback;
char *s, *str;
PyErr_Fetch (&ptype, &pvalue, &ptraceback);
if (pvalue && PyString_Check (pvalue))
{
/* Make a temporary copy of the string data. */
char *s = PyString_AsString (pvalue);
char *copy = alloca (strlen (s) + 1);
strcpy (copy, s);
PyErr_Restore (ptype, pvalue, ptraceback);
gdbpy_print_stack ();
error (_("Error occurred in Python command: %s"), copy);
}
else
{
PyErr_Restore (ptype, pvalue, ptraceback);
gdbpy_print_stack ();
error (_("Error occurred in Python command."));
}
}
Py_DECREF (result);
do_cleanups (cleanup);
}
/* Called by gdb for command completion. */
static char **
cmdpy_completer (struct cmd_list_element *command, char *text, char *word)
{
cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command);
PyObject *textobj, *wordobj, *resultobj = NULL;
char **result = NULL;
struct cleanup *cleanup;
PyGILState_STATE state;
state = PyGILState_Ensure ();
cleanup = make_cleanup_py_restore_gil (&state);
if (! obj)
error (_("Invalid invocation of Python command object."));
if (! PyObject_HasAttr ((PyObject *) obj, complete_cst))
{
/* If there is no complete method, don't error -- instead, just
say that there are no completions. */
goto done;
}
textobj = PyUnicode_Decode (text, strlen (text), host_charset (), NULL);
if (! textobj)
error (_("Could not convert argument to Python string."));
wordobj = PyUnicode_Decode (word, strlen (word), host_charset (), NULL);
if (! wordobj)
error (_("Could not convert argument to Python string."));
resultobj = PyObject_CallMethodObjArgs ((PyObject *) obj, complete_cst,
textobj, wordobj, NULL);
Py_DECREF (textobj);
Py_DECREF (wordobj);
if (! resultobj)
{
/* Just swallow errors here. */
PyErr_Clear ();
goto done;
}
make_cleanup_py_decref (resultobj);
result = NULL;
if (PySequence_Check (resultobj))
{
Py_ssize_t i, len = PySequence_Size (resultobj);
Py_ssize_t out;
if (len < 0)
goto done;
result = (char **) xmalloc ((len + 1) * sizeof (char *));
for (i = out = 0; i < len; ++i)
{
int l;
PyObject *elt = PySequence_GetItem (resultobj, i);
if (elt == NULL || ! gdbpy_is_string (elt))
{
/* Skip problem elements. */
PyErr_Clear ();
continue;
}
result[out] = python_string_to_host_string (elt);
++out;
}
result[out] = NULL;
}
else if (PyInt_Check (resultobj))
{
/* User code may also return one of the completion constants,
thus requesting that sort of completion. */
long value = PyInt_AsLong (resultobj);
if (value >= 0 && value < (long) N_COMPLETERS)
result = completers[value].completer (command, text, word);
}
done:
do_cleanups (cleanup);
return result;
}
/* Helper for cmdpy_init which locates the command list to use and
pulls out the command name.
TEXT 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.
This function returns the xmalloc()d name of the new command. On
error sets the Python error and returns NULL. */
static char *
parse_command_name (char *text, struct cmd_list_element ***base_list)
{
struct cmd_list_element *elt;
int len = strlen (text);
int i, lastchar;
char *prefix_text;
char *result;
/* Skip trailing whitespace. */
for (i = len - 1; i >= 0 && (text[i] == ' ' || text[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 && (isalnum (text[i - 1])
|| text[i - 1] == '-'
|| text[i - 1] == '_');
--i)
;
result = xmalloc (lastchar - i + 2);
memcpy (result, &text[i], lastchar - i + 1);
result[lastchar - i + 1] = '\0';
/* Skip whitespace again. */
for (--i; i >= 0 && (text[i] == ' ' || text[i] == '\t'); --i)
;
if (i < 0)
{
*base_list = &cmdlist;
return result;
}
prefix_text = xmalloc (i + 2);
memcpy (prefix_text, text, i + 1);
prefix_text[i + 1] = '\0';
text = prefix_text;
elt = lookup_cmd_1 (&text, cmdlist, NULL, 1);
if (!elt || elt == (struct cmd_list_element *) -1)
{
PyErr_Format (PyExc_RuntimeError, _("could not find command prefix %s"),
prefix_text);
xfree (prefix_text);
xfree (result);
return NULL;
}
if (elt->prefixlist)
{
xfree (prefix_text);
*base_list = elt->prefixlist;
return result;
}
PyErr_Format (PyExc_RuntimeError, _("'%s' is not a prefix command"),
prefix_text);
xfree (prefix_text);
xfree (result);
return NULL;
}
/* Object initializer; sets up gdb-side structures for command.
Use: __init__(NAME, CMDCLASS, [COMPLETERCLASS, [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.
CMDCLASS is the kind of command. It should be one of the COMMAND_*
constants defined in the gdb module.
COMPLETERCLASS 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 *kwds)
{
cmdpy_object *obj = (cmdpy_object *) self;
char *name;
int cmdtype;
int completetype = -1;
char *docstring = NULL;
volatile struct gdb_exception except;
struct cmd_list_element **cmd_list;
char *cmd_name, *pfx_name;
PyObject *is_prefix = NULL;
int cmp;
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 (! PyArg_ParseTuple (args, "si|iO", &name, &cmdtype,
&completetype, &is_prefix))
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)
{
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;
}
cmd_name = parse_command_name (name, &cmd_list);
if (! cmd_name)
return -1;
pfx_name = NULL;
if (is_prefix != NULL)
{
cmp = PyObject_IsTrue (is_prefix);
if (cmp == 1)
{
int i, out;
/* Make a normalized form of the command name. */
pfx_name = xmalloc (strlen (name) + 2);
i = 0;
out = 0;
while (name[i])
{
/* Skip whitespace. */
while (name[i] == ' ' || name[i] == '\t')
++i;
/* Copy non-whitespace characters. */
while (name[i] && name[i] != ' ' && name[i] != '\t')
pfx_name[out++] = name[i++];
/* Add a single space after each word -- including the final
word. */
pfx_name[out++] = ' ';
}
pfx_name[out] = '\0';
}
else if (cmp < 0)
return -1;
}
if (PyObject_HasAttr (self, gdbpy_doc_cst))
{
PyObject *ds_obj = PyObject_GetAttr (self, gdbpy_doc_cst);
if (ds_obj && gdbpy_is_string (ds_obj))
docstring = python_string_to_host_string (ds_obj);
}
if (! docstring)
docstring = xstrdup (_("This command is not documented."));
Py_INCREF (self);
TRY_CATCH (except, RETURN_MASK_ALL)
{
struct cmd_list_element *cmd;
if (pfx_name)
{
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, (enum command_class) cmdtype,
NULL, docstring, &obj->sub_list,
pfx_name, allow_unknown, cmd_list);
}
else
cmd = add_cmd (cmd_name, (enum command_class) cmdtype, NULL,
docstring, cmd_list);
/* There appears to be no API to set this. */
cmd->func = cmdpy_function;
cmd->destroyer = cmdpy_destroyer;
obj->command = cmd;
set_cmd_context (cmd, self);
set_cmd_completer (cmd, ((completetype == -1) ? cmdpy_completer
: completers[completetype].completer));
}
if (except.reason < 0)
{
xfree (cmd_name);
xfree (docstring);
xfree (pfx_name);
Py_DECREF (self);
PyErr_Format (except.reason == RETURN_QUIT
? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
"%s", except.message);
return -1;
}
return 0;
}
/* Initialize the 'commands' code. */
void
gdbpy_initialize_commands (void)
{
int i;
if (PyType_Ready (&cmdpy_object_type) < 0)
return;
/* Note: alias and user are special; pseudo appears to be unused,
and there is no reason to expose tui or xdb, 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
|| 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)
return;
for (i = 0; i < N_COMPLETERS; ++i)
{
if (PyModule_AddIntConstant (gdb_module, completers[i].name, i) < 0)
return;
}
Py_INCREF (&cmdpy_object_type);
PyModule_AddObject (gdb_module, "Command",
(PyObject *) &cmdpy_object_type);
invoke_cst = PyString_FromString ("invoke");
complete_cst = PyString_FromString ("complete");
}
static PyMethodDef cmdpy_object_methods[] =
{
{ "dont_repeat", cmdpy_dont_repeat, METH_NOARGS,
"Prevent command repetition when user enters empty line." },
{ 0 }
};
static PyTypeObject cmdpy_object_type =
{
PyObject_HEAD_INIT (NULL)
0, /*ob_size*/
"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 */
PyType_GenericNew /* tp_new */
};

View File

@ -70,6 +70,7 @@ PyObject *value_to_value_object (struct value *v);
struct value *convert_value_from_python (PyObject *obj);
void gdbpy_initialize_values (void);
void gdbpy_initialize_commands (void);
struct cleanup *make_cleanup_py_decref (PyObject *py);
struct cleanup *make_cleanup_py_restore_gil (PyGILState_STATE *state);
@ -94,4 +95,6 @@ char *python_string_to_host_string (PyObject *obj);
PyObject *target_string_to_unicode (const gdb_byte *str, int length);
int gdbpy_is_string (PyObject *obj);
extern PyObject *gdbpy_doc_cst;
#endif /* GDB_PYTHON_INTERNAL_H */

View File

@ -46,6 +46,8 @@ static PyMethodDef GdbMethods[];
PyObject *gdb_module;
PyObject *gdbpy_doc_cst;
/* Given a command_line, return a command string suitable for passing
to Python. Lines in the string are separated by newlines. The
return value is allocated using xmalloc and the caller is
@ -407,9 +409,12 @@ Enables or disables printing of Python stack traces."),
PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name);
gdbpy_initialize_values ();
gdbpy_initialize_commands ();
PyRun_SimpleString ("import gdb");
gdbpy_doc_cst = PyString_FromString ("__doc__");
/* Create a couple objects which are used for Python's stdout and
stderr. */
PyRun_SimpleString ("\

View File

@ -3890,6 +3890,16 @@ make_symbol_completion_list (char *text, char *word)
return current_language->la_make_symbol_completion_list (text, word);
}
/* Like make_symbol_completion_list, but suitable for use as a
completion function. */
char **
make_symbol_completion_list_fn (struct cmd_list_element *ignore,
char *text, char *word)
{
return make_symbol_completion_list (text, word);
}
/* Like make_symbol_completion_list, but returns a list of symbols
defined in a source file FILE. */

View File

@ -1238,6 +1238,8 @@ extern void select_source_symtab (struct symtab *);
extern char **default_make_symbol_completion_list (char *, char *);
extern char **make_symbol_completion_list (char *, char *);
extern char **make_symbol_completion_list_fn (struct cmd_list_element *,
char *, char *);
extern char **make_file_symbol_completion_list (char *, char *, char *);

View File

@ -1,3 +1,7 @@
2009-02-06 Thiago Jung Bauermann <bauerman@br.ibm.com>
* gdb.python/python-cmd.exp: New file.
2009-02-06 Tristan Gingold <gingold@adacore.com>
* gdb.arch/i386-sse.c (main): Replace call to puts by an nop asm.