@@ -66,6 +66,13 @@ struct cmdpy_object
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;
+
+ /* If the prefix is created with add_set_show=True, then these are the
+ commands and sublists. */
+ struct cmd_list_element *set_cmd;
+ struct cmd_list_element *show_cmd;
+ struct cmd_list_element *set_list;
+ struct cmd_list_element *show_list;
};
typedef struct cmdpy_object cmdpy_object;
@@ -110,6 +117,11 @@ cmdpy_destroyer (struct cmd_list_element *self, void *context)
xfree ((char *) self->doc);
xfree ((char *) self->prefixname);
+ /* TODO(dje): What to do if this was a prefix command?
+ GDB itself doesn't really properly support deleting prefix commands.
+ We'll want to free the set/show commands and sub/set/show lists.
+ Until then, keep the set/show prefixes Just In Case. */
+
do_cleanups (cleanup);
}
@@ -424,6 +436,29 @@ cmdpy_completer (struct cmd_list_element *command,
return result;
}
+/* Command function for prefix "set" commands. */
+
+static void
+cmdpy_set_cmd (struct cmd_list_element *command, char *args, int from_tty)
+{
+ cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command);
+
+ /* TODO(dje): Remove extra space in the quoted name. */
+ printf_filtered (_("\"%s\" must be followed by the name"
+ " of a set command.\n"), command->prefixname);
+ help_list (obj->set_list, command->prefixname, all_commands, gdb_stdout);
+}
+
+/* Command function for prefix "show" commands. */
+
+static void
+cmdpy_show_cmd (struct cmd_list_element *command, char *args, int from_tty)
+{
+ cmdpy_object *obj = (cmdpy_object *) get_cmd_context (command);
+
+ cmd_show_list (obj->show_list, from_tty, "");
+}
+
/* Helper for cmdpy_init which locates the command list to use and
pulls out the command name.
@@ -435,6 +470,7 @@ cmdpy_completer (struct cmd_list_element *command,
*sub-commands.
START_LIST is the list in which the search starts.
+ To search from the top, pass "cmdlist".
This function returns the xmalloc()d name of the new command. On
error sets the Python error and returns NULL. */
@@ -486,7 +522,7 @@ gdbpy_parse_command_name (const char *name,
prefix_text2 = prefix_text;
elt = lookup_cmd_1 (&prefix_text2, *start_list, NULL, 1);
- if (elt == NULL || elt == CMD_LIST_AMBIGUOUS)
+ if (elt == NULL || elt == CMD_LIST_AMBIGUOUS || *prefix_text2 != '\0')
{
PyErr_Format (PyExc_RuntimeError, _("Could not find command prefix %s."),
prefix_text);
@@ -511,7 +547,8 @@ gdbpy_parse_command_name (const char *name,
/* Object initializer; sets up gdb-side structures for command.
- Use: __init__(NAME, COMMAND_CLASS [, COMPLETER_CLASS][, PREFIX]]).
+ Use: __init__(NAME, COMMAND_CLASS
+ [, COMPLETER_CLASS [, PREFIX [, ADD_SET_SHOW]]])
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
@@ -526,6 +563,8 @@ gdbpy_parse_command_name (const char *name,
If PREFIX is True, then this command is a prefix command.
+ If ADD_SET_SHOW is True, then set/show commands are added to this prefix.
+
The documentation for the command is taken from the doc string for
the python class. */
@@ -541,8 +580,9 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
struct cmd_list_element **cmd_list;
char *cmd_name, *pfx_name;
static char *keywords[] = { "name", "command_class", "completer_class",
- "prefix", NULL };
+ "prefix", "add_set_show", NULL };
PyObject *is_prefix = NULL;
+ PyObject *add_set_show = NULL;
int cmp;
if (obj->command)
@@ -554,9 +594,9 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
return -1;
}
- if (! PyArg_ParseTupleAndKeywords (args, kw, "si|iO",
- keywords, &name, &cmdtype,
- &completetype, &is_prefix))
+ if (! PyArg_ParseTupleAndKeywords (args, kw, "si|iOO",
+ keywords, &name, &cmdtype, &completetype,
+ &is_prefix, &add_set_show))
return -1;
if (cmdtype != no_class && cmdtype != class_run
@@ -614,6 +654,16 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
return -1;
}
}
+
+ /* Error check the add_set_show parameter now, so there are less things to
+ have to free if there's an error. We won't use it until later. */
+ if (add_set_show != NULL && PyObject_IsTrue (add_set_show) < 0)
+ {
+ xfree (cmd_name);
+ xfree (pfx_name);
+ return -1;
+ }
+
if (PyObject_HasAttr (self, gdbpy_doc_cst))
{
PyObject *ds_obj = PyObject_GetAttr (self, gdbpy_doc_cst);
@@ -667,6 +717,28 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
if (completetype == -1)
set_cmd_completer_handle_brkchars (cmd,
cmdpy_completer_handle_brkchars);
+
+ if (add_set_show != NULL && PyObject_IsTrue (add_set_show))
+ {
+ obj->set_cmd
+ = add_prefix_cmd ("set", (enum command_class) cmdtype, NULL,
+ xstrprintf (_("\
+Set GDB parameters for use with the %scommand."), pfx_name),
+ &obj->set_list,
+ concat (pfx_name, "set ", NULL),
+ 0/*allow-unknown*/, &obj->sub_list);
+ obj->set_cmd->func = cmdpy_set_cmd;
+ set_cmd_context (obj->set_cmd, self);
+ obj->show_cmd
+ = add_prefix_cmd ("show", (enum command_class) cmdtype, NULL,
+ xstrprintf (_("\
+Show GDB parameters for use with the %scommand."), pfx_name),
+ &obj->show_list,
+ concat (pfx_name, "show ", NULL),
+ 0/*allow-unknown*/, &obj->sub_list);
+ obj->show_cmd->func = cmdpy_show_cmd;
+ set_cmd_context (obj->show_cmd, self);
+ }
}
if (except.reason < 0)
{
@@ -631,41 +631,48 @@ compute_enum_values (parmpy_object *self, PyObject *enum_values)
/* Object initializer; sets up gdb-side structures for command.
- Use: __init__(NAME, CMDCLASS, PARMCLASS, [ENUM])
+ Use: __init__(NAME, CMD_CLASS, PARAM_CLASS, [ENUM_VALUES [,PREFIX]])
NAME is the name of the parameter. 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_*
+ CMD_CLASS is the kind of command. It should be one of the COMMAND_*
constants defined in the gdb module.
- PARMCLASS is the type of the parameter. It should be one of the
+ PARAM_CLASS is the type of the parameter. It should be one of the
PARAM_* constants defined in the gdb module.
- If PARMCLASS is PARAM_ENUM, then the final argument should be a
+ If PARAM_CLASS is PARAM_ENUM, then ENUM_VALUES should be a
collection of strings. These strings are the valid values for this
parameter.
+ If PREFIX is provided, the parameter is added to the prefix's set/show
+ commands, which must have been already created.
+
The documentation for the parameter is taken from the doc string
for the python class.
Returns -1 on error, with a python exception set. */
static int
-parmpy_init (PyObject *self, PyObject *args, PyObject *kwds)
+parmpy_init (PyObject *self, PyObject *args, PyObject *kw)
{
+ static char *keywords[] = { "name", "command_class", "param_class",
+ "enum_values", "prefix", NULL };
parmpy_object *obj = (parmpy_object *) self;
const char *name;
char *set_doc, *show_doc, *doc;
char *cmd_name;
int parmclass, cmdtype;
PyObject *enum_values = NULL;
+ const char *prefix = NULL;
struct cmd_list_element **set_list, **show_list;
volatile struct gdb_exception except;
- if (! PyArg_ParseTuple (args, "sii|O", &name, &cmdtype, &parmclass,
- &enum_values))
+ if (! PyArg_ParseTupleAndKeywords (args, kw, "sii|Os", keywords,
+ &name, &cmdtype, &parmclass,
+ &enum_values, &prefix))
return -1;
if (cmdtype != no_class && cmdtype != class_run
@@ -707,15 +714,29 @@ parmpy_init (PyObject *self, PyObject *args, PyObject *kwds)
obj->type = (enum var_types) parmclass;
memset (&obj->value, 0, sizeof (obj->value));
- cmd_name = gdbpy_parse_command_name (name, &set_list,
- &setlist);
+ if (prefix != NULL)
+ {
+ char *tmp_name = concat (prefix, " set ", name, NULL);
- if (! cmd_name)
+ cmd_name = gdbpy_parse_command_name (tmp_name, &set_list, &cmdlist);
+ xfree (tmp_name);
+ }
+ else
+ cmd_name = gdbpy_parse_command_name (name, &set_list, &setlist);
+ if (cmd_name == NULL)
return -1;
xfree (cmd_name);
- cmd_name = gdbpy_parse_command_name (name, &show_list,
- &showlist);
- if (! cmd_name)
+
+ if (prefix != NULL)
+ {
+ char *tmp_name = concat (prefix, " show ", name, NULL);
+
+ cmd_name = gdbpy_parse_command_name (tmp_name, &show_list, &cmdlist);
+ xfree (tmp_name);
+ }
+ else
+ cmd_name = gdbpy_parse_command_name (name, &show_list, &showlist);
+ if (cmd_name == NULL)
return -1;
set_doc = get_doc_string (self, set_doc_cst);
@@ -178,3 +178,39 @@ gdb_test "python print (test_param.value)" "False" "Test parameter value"
gdb_test "help show print test-param" "State of the Test Parameter.*" "Test show help"
gdb_test "help set print test-param" "Set the state of the Test Parameter.*" "Test set help"
gdb_test "help set print" "set print test-param -- Set the state of the Test Parameter.*" "Test general help"
+
+# Test set/show added to a prefix command.
+gdb_py_test_multiple "Prefix with set/show" \
+ "python" "" \
+ "class prefix_with_setshow_cmd (gdb.Command):" "" \
+ " def __init__ (self):" "" \
+ " super (prefix_with_setshow_cmd, self).__init__ (\"my-prefix\", gdb.COMMAND_OBSCURE, prefix=True, add_set_show=True)" "" \
+ "prefix_with_setshow_cmd ()" "" \
+ "end" ""
+gdb_py_test_multiple "Prefixed parameter" \
+ "python" "" \
+ "class PrefixedParam (gdb.Parameter):" "" \
+ " \"\"\"When set, my-param does something useful. When disabled, does nothing.\"\"\"" "" \
+ " show_doc = \"Show the state of the boolean my-param\"" ""\
+ " set_doc = \"Set the state of the boolean my-param\"" "" \
+ " def get_show_string (self, pvalue):" ""\
+ " return \"The state of my-param is \" + pvalue" ""\
+ " def get_set_string (self):" ""\
+ " val = \"on\"" ""\
+ " if (self.value == False):" ""\
+ " val = \"off\"" ""\
+ " return \"my-param has been set to \" + val" ""\
+ " def __init__ (self):" "" \
+ " super (PrefixedParam, self).__init__ (\"my-param\", gdb.COMMAND_DATA, gdb.PARAM_BOOLEAN, prefix=\"my-prefix\")" "" \
+ " self.value = True" "" \
+ "prefixed_param = PrefixedParam ()" ""\
+ "end"
+
+gdb_test "help my-prefix" \
+ "Set GDB parameters for use with the my-prefix command.*Show GDB parameters for use with the my-prefix command.*"
+gdb_test "my-prefix show my-param" "The state of my-param is on"
+gdb_test "my-prefix set my-param off" "my-param has been set to off"
+gdb_test "my-prefix show my-param" "The state of my-param is off"
+gdb_test "my-prefix show" "my-param: *The state of my-param is off"
+gdb_test "help my-prefix set" "my-prefix set my-param.*"
+gdb_test "help my-prefix set my-param" "Set the state of the boolean my-param\[\r\n\]*When set, my-param does something useful. When disabled, does nothing."