From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31203 invoked by alias); 18 Nov 2008 18:52:00 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 31141 invoked by uid 306); 18 Nov 2008 18:51:59 -0000 Date: Tue, 18 Nov 2008 18:52:00 -0000 Message-ID: <20081118185159.31120.qmail@sourceware.org> From: tromey@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] archer-tromey-python: gdb X-Git-Refname: refs/heads/archer-tromey-python X-Git-Reftype: branch X-Git-Oldrev: 01af16dc305d029f7bc580ec848b60b7f2b2a880 X-Git-Newrev: 4b2ca6c6e0e86a0a2ad45b873a3c1b75993a2f08 X-SW-Source: 2008-q4/txt/msg00122.txt.bz2 List-Id: The branch, archer-tromey-python has been updated via 4b2ca6c6e0e86a0a2ad45b873a3c1b75993a2f08 (commit) from 01af16dc305d029f7bc580ec848b60b7f2b2a880 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 4b2ca6c6e0e86a0a2ad45b873a3c1b75993a2f08 Author: Tom Tromey Date: Tue Nov 18 11:51:36 2008 -0700 gdb * python/python-cmd.c (struct cmdpy_object) : New field. (cmdpy_init): Allow prefix commands. (cmdpy_destroyer): Free the prefix name. (cmdpy_function): Handle prefix commands. gdb/doc * gdb.texinfo (Commands In Python): Document prefix commands. ----------------------------------------------------------------------- Summary of changes: gdb/ChangeLog | 7 ++++ gdb/doc/ChangeLog | 4 ++ gdb/doc/gdb.texinfo | 9 ++++-- gdb/python/python-cmd.c | 76 ++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 82 insertions(+), 14 deletions(-) First 500 lines of diff: diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c5fa878..7fb7b12 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,12 @@ 2008-11-18 Tom Tromey + * python/python-cmd.c (struct cmdpy_object) : New field. + (cmdpy_init): Allow prefix commands. + (cmdpy_destroyer): Free the prefix name. + (cmdpy_function): Handle prefix commands. + +2008-11-18 Tom Tromey + * python/python-internal.h (gdbpy_doc_cst): Declare. * python/python-cmd.c (cmdpy_init): Use gdbpy_doc_cst. Don't set tp_new or tp_init. diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 385bbca..b0a8038 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,5 +1,9 @@ 2008-11-18 Tom Tromey + * gdb.texinfo (Commands In Python): Document prefix commands. + +2008-11-18 Tom Tromey + * gdb.texinfo (Parameters In Python): Document set_doc, show_doc. 2008-11-16 Tom Tromey diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 9446ce4..1231ab3 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -18308,7 +18308,7 @@ 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}@r{]} +@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. @@ -18318,8 +18318,7 @@ 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. Currently, there is also -no way to define new prefix commands. +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 @@ -18332,6 +18331,10 @@ 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 there is no documentation string, a default value is used. diff --git a/gdb/python/python-cmd.c b/gdb/python/python-cmd.c index 91cdc7f..014274b 100644 --- a/gdb/python/python-cmd.c +++ b/gdb/python/python-cmd.c @@ -54,8 +54,10 @@ struct cmdpy_object /* The corresponding gdb command object, or NULL if the command is no longer installed. */ - /* It isn't clear if we will ever care about this. */ struct cmd_list_element *command; + + /* For a prefix command, this is the list of sub-commands. */ + struct cmd_list_element *sub_list; }; typedef struct cmdpy_object cmdpy_object; @@ -92,9 +94,11 @@ cmdpy_destroyer (struct cmd_list_element *self, void *context) cmd->command = NULL; Py_DECREF (cmd); - /* We allocated the name and doc string. */ + /* We allocated the name, doc string, and perhaps the prefix + name. */ xfree (self->name); xfree (self->doc); + xfree (self->prefixname); PyGILState_Release (state); } @@ -114,7 +118,15 @@ cmdpy_function (struct cmd_list_element *command, char *args, int from_tty) if (! obj) error (_("Invalid invocation of Python command object.")); if (! PyObject_HasAttr ((PyObject *) obj, invoke_cst)) - error (_("Python command object missing 'invoke' method.")); + { + 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) { @@ -327,7 +339,7 @@ gdbpy_parse_command_name (char *text, struct cmd_list_element ***base_list, /* Object initializer; sets up gdb-side structures for command. - Use: __init__(NAME, CMDCLASS, [COMPLETERCLASS]). + 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 @@ -340,6 +352,8 @@ gdbpy_parse_command_name (char *text, struct cmd_list_element ***base_list, "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. @@ -354,7 +368,8 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kwds) char *docstring = NULL; volatile struct gdb_exception except; struct cmd_list_element **cmd_list; - char *cmd_name; + char *cmd_name, *pfx_name; + PyObject *is_prefix = NULL; if (obj->command) { @@ -365,7 +380,8 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kwds) return -1; } - if (! PyArg_ParseTuple (args, "si|i", &name, &cmdtype, &completetype)) + if (! PyArg_ParseTuple (args, "si|iO", &name, &cmdtype, + &completetype, &is_prefix)) return -1; if (cmdtype != no_class && cmdtype != class_run @@ -389,6 +405,31 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kwds) if (! cmd_name) return -1; + pfx_name = NULL; + if (is_prefix == Py_True) + { + 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'; + } + if (PyObject_HasAttr (self, gdbpy_doc_cst)) { PyObject *ds_obj = PyObject_GetAttr (self, gdbpy_doc_cst); @@ -402,11 +443,23 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kwds) TRY_CATCH (except, RETURN_MASK_ALL) { - struct cmd_list_element *cmd = add_cmd (cmd_name, - (enum command_class) cmdtype, - NULL, - docstring, - cmd_list); + 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; @@ -420,6 +473,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kwds) { xfree (cmd_name); xfree (docstring); + xfree (pfx_name); Py_DECREF (self); PyErr_Format (except.reason == RETURN_QUIT ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, hooks/post-receive -- Repository for Project Archer.