* NEWS: Document "define" for prefixed commands.
* cli/cli-cmds.c (show_user): Update calls to show_user_1. Call show_user_1 for prefix commands. * cli/cli-decode.c (help_cmd_list): Recurse for "help user-defined". * cli/cli-script.c (validate_comname): Rewrite to handle prefix commands. Return the containing command list. (define_command, document_command): Update to handle prefix commands. (show_user_1): Add prefix and name arguments. Handle prefix commands. * cli/cli-script.h (show_user_1): Update prototype. doc/ * gdb.texinfo (Define, Hooks): Document prefix command support. testsuite/ * gdb.base/define.exp: Test defining and hooking prefix commands. * gdb.python/python.exp: Update test for "show user" output.
This commit is contained in:
parent
a32d7317c7
commit
adb483feb8
11 changed files with 152 additions and 39 deletions
|
@ -1,3 +1,16 @@
|
|||
2009-01-14 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* NEWS: Document "define" for prefixed commands.
|
||||
* cli/cli-cmds.c (show_user): Update calls to show_user_1. Call
|
||||
show_user_1 for prefix commands.
|
||||
* cli/cli-decode.c (help_cmd_list): Recurse for "help user-defined".
|
||||
* cli/cli-script.c (validate_comname): Rewrite to handle prefix
|
||||
commands. Return the containing command list.
|
||||
(define_command, document_command): Update to handle prefix commands.
|
||||
(show_user_1): Add prefix and name arguments. Handle prefix
|
||||
commands.
|
||||
* cli/cli-script.h (show_user_1): Update prototype.
|
||||
|
||||
2009-01-14 Kai Tietz <kai.tietz@onevision.com>
|
||||
|
||||
* mingw-ser.c (console_select_thread): Add return to make
|
||||
|
|
3
gdb/NEWS
3
gdb/NEWS
|
@ -110,6 +110,9 @@ are treated as the standard definitions, regardless of context.
|
|||
task N
|
||||
Switch the context of debugging to task number N.
|
||||
|
||||
* Support for user-defined prefixed commands. The "define" command can
|
||||
add new commands to existing prefixes, e.g. "target".
|
||||
|
||||
* New commands
|
||||
|
||||
find [/size-char] [/max-count] start-address, end-address|+search-space-size,
|
||||
|
|
|
@ -1050,17 +1050,18 @@ show_user (char *args, int from_tty)
|
|||
|
||||
if (args)
|
||||
{
|
||||
c = lookup_cmd (&args, cmdlist, "", 0, 1);
|
||||
char *comname = args;
|
||||
c = lookup_cmd (&comname, cmdlist, "", 0, 1);
|
||||
if (c->class != class_user)
|
||||
error (_("Not a user command."));
|
||||
show_user_1 (c, gdb_stdout);
|
||||
show_user_1 (c, "", args, gdb_stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (c = cmdlist; c; c = c->next)
|
||||
{
|
||||
if (c->class == class_user)
|
||||
show_user_1 (c, gdb_stdout);
|
||||
if (c->class == class_user || c->prefixlist != NULL)
|
||||
show_user_1 (c, "", c->name, gdb_stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1052,6 +1052,10 @@ help_cmd_list (struct cmd_list_element *list, enum command_class class,
|
|||
{
|
||||
print_help_for_command (c, prefix, recurse, stream);
|
||||
}
|
||||
else if (c->abbrev_flag == 0 && recurse
|
||||
&& class == class_user && c->prefixlist != NULL)
|
||||
/* User-defined commands may be subcommands. */
|
||||
help_cmd_list (*c->prefixlist, class, c->prefixname, recurse, stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,8 +45,6 @@ static char *insert_args (char *line);
|
|||
|
||||
static struct cleanup * setup_user_args (char *p);
|
||||
|
||||
static void validate_comname (char *);
|
||||
|
||||
/* Level of control structure when reading. */
|
||||
static int control_level;
|
||||
|
||||
|
@ -1254,21 +1252,57 @@ copy_command_lines (struct command_line *cmds)
|
|||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
validate_comname (char *comname)
|
||||
{
|
||||
char *p;
|
||||
/* Validate that *COMNAME is a valid name for a command. Return the
|
||||
containing command list, in case it starts with a prefix command.
|
||||
The prefix must already exist. *COMNAME is advanced to point after
|
||||
any prefix, and a NUL character overwrites the space after the
|
||||
prefix. */
|
||||
|
||||
if (comname == 0)
|
||||
static struct cmd_list_element **
|
||||
validate_comname (char **comname)
|
||||
{
|
||||
struct cmd_list_element **list = &cmdlist;
|
||||
char *p, *last_word;
|
||||
|
||||
if (*comname == 0)
|
||||
error_no_arg (_("name of command to define"));
|
||||
|
||||
p = comname;
|
||||
/* Find the last word of the argument. */
|
||||
p = *comname + strlen (*comname);
|
||||
while (p > *comname && isspace (p[-1]))
|
||||
p--;
|
||||
while (p > *comname && !isspace (p[-1]))
|
||||
p--;
|
||||
last_word = p;
|
||||
|
||||
/* Find the corresponding command list. */
|
||||
if (last_word != *comname)
|
||||
{
|
||||
struct cmd_list_element *c;
|
||||
char saved_char, *tem = *comname;
|
||||
|
||||
/* Separate the prefix and the command. */
|
||||
saved_char = last_word[-1];
|
||||
last_word[-1] = '\0';
|
||||
|
||||
c = lookup_cmd (&tem, cmdlist, "", 0, 1);
|
||||
if (c->prefixlist == NULL)
|
||||
error (_("\"%s\" is not a prefix command."), *comname);
|
||||
|
||||
list = c->prefixlist;
|
||||
last_word[-1] = saved_char;
|
||||
*comname = last_word;
|
||||
}
|
||||
|
||||
p = *comname;
|
||||
while (*p)
|
||||
{
|
||||
if (!isalnum (*p) && *p != '-' && *p != '_')
|
||||
error (_("Junk in argument list: \"%s\""), p);
|
||||
p++;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/* This is just a placeholder in the command data structures. */
|
||||
|
@ -1288,9 +1322,8 @@ define_command (char *comname, int from_tty)
|
|||
CMD_POST_HOOK
|
||||
};
|
||||
struct command_line *cmds;
|
||||
struct cmd_list_element *c, *newc, *oldc, *hookc = 0;
|
||||
char *tem = comname;
|
||||
char *tem2;
|
||||
struct cmd_list_element *c, *newc, *oldc, *hookc = 0, **list;
|
||||
char *tem, *tem2, *comfull;
|
||||
char tmpbuf[MAX_TMPBUF];
|
||||
int hook_type = CMD_NO_HOOK;
|
||||
int hook_name_size = 0;
|
||||
|
@ -1300,10 +1333,12 @@ define_command (char *comname, int from_tty)
|
|||
#define HOOK_POST_STRING "hookpost-"
|
||||
#define HOOK_POST_LEN 9
|
||||
|
||||
validate_comname (comname);
|
||||
comfull = comname;
|
||||
list = validate_comname (&comname);
|
||||
|
||||
/* Look it up, and verify that we got an exact match. */
|
||||
c = lookup_cmd (&tem, cmdlist, "", -1, 1);
|
||||
tem = comname;
|
||||
c = lookup_cmd (&tem, *list, "", -1, 1);
|
||||
if (c && strcmp (comname, c->name) != 0)
|
||||
c = 0;
|
||||
|
||||
|
@ -1337,13 +1372,13 @@ define_command (char *comname, int from_tty)
|
|||
{
|
||||
/* Look up cmd it hooks, and verify that we got an exact match. */
|
||||
tem = comname + hook_name_size;
|
||||
hookc = lookup_cmd (&tem, cmdlist, "", -1, 0);
|
||||
hookc = lookup_cmd (&tem, *list, "", -1, 0);
|
||||
if (hookc && strcmp (comname + hook_name_size, hookc->name) != 0)
|
||||
hookc = 0;
|
||||
if (!hookc)
|
||||
{
|
||||
warning (_("Your new `%s' command does not hook any existing command."),
|
||||
comname);
|
||||
comfull);
|
||||
if (!query ("Proceed? "))
|
||||
error (_("Not confirmed."));
|
||||
}
|
||||
|
@ -1357,7 +1392,7 @@ define_command (char *comname, int from_tty)
|
|||
if (isupper (*tem))
|
||||
*tem = tolower (*tem);
|
||||
|
||||
sprintf (tmpbuf, "Type commands for definition of \"%s\".", comname);
|
||||
sprintf (tmpbuf, "Type commands for definition of \"%s\".", comfull);
|
||||
cmds = read_command_lines (tmpbuf, from_tty, 1);
|
||||
|
||||
if (c && c->class == class_user)
|
||||
|
@ -1365,7 +1400,7 @@ define_command (char *comname, int from_tty)
|
|||
|
||||
newc = add_cmd (comname, class_user, user_defined_command,
|
||||
(c && c->class == class_user)
|
||||
? c->doc : savestring ("User-defined.", 13), &cmdlist);
|
||||
? c->doc : savestring ("User-defined.", 13), list);
|
||||
newc->user_commands = cmds;
|
||||
|
||||
/* If this new command is a hook, then mark both commands as being
|
||||
|
@ -1393,18 +1428,20 @@ void
|
|||
document_command (char *comname, int from_tty)
|
||||
{
|
||||
struct command_line *doclines;
|
||||
struct cmd_list_element *c;
|
||||
char *tem = comname;
|
||||
struct cmd_list_element *c, **list;
|
||||
char *tem, *comfull;
|
||||
char tmpbuf[128];
|
||||
|
||||
validate_comname (comname);
|
||||
comfull = comname;
|
||||
list = validate_comname (&comname);
|
||||
|
||||
c = lookup_cmd (&tem, cmdlist, "", 0, 1);
|
||||
tem = comname;
|
||||
c = lookup_cmd (&tem, *list, "", 0, 1);
|
||||
|
||||
if (c->class != class_user)
|
||||
error (_("Command \"%s\" is built-in."), comname);
|
||||
error (_("Command \"%s\" is built-in."), comfull);
|
||||
|
||||
sprintf (tmpbuf, "Type documentation for \"%s\".", comname);
|
||||
sprintf (tmpbuf, "Type documentation for \"%s\".", comfull);
|
||||
doclines = read_command_lines (tmpbuf, from_tty, 0);
|
||||
|
||||
if (c->doc)
|
||||
|
@ -1505,17 +1542,29 @@ script_from_file (FILE *stream, char *file)
|
|||
do_cleanups (old_cleanups);
|
||||
}
|
||||
|
||||
/* Print the definition of user command C to STREAM. Or, if C is a
|
||||
prefix command, show the definitions of all user commands under C
|
||||
(recursively). PREFIX and NAME combined are the name of the
|
||||
current command. */
|
||||
void
|
||||
show_user_1 (struct cmd_list_element *c, struct ui_file *stream)
|
||||
show_user_1 (struct cmd_list_element *c, char *prefix, char *name,
|
||||
struct ui_file *stream)
|
||||
{
|
||||
struct command_line *cmdlines;
|
||||
|
||||
if (c->prefixlist != NULL)
|
||||
{
|
||||
char *prefixname = c->prefixname;
|
||||
for (c = *c->prefixlist; c != NULL; c = c->next)
|
||||
if (c->class == class_user || c->prefixlist != NULL)
|
||||
show_user_1 (c, prefixname, c->name, gdb_stdout);
|
||||
return;
|
||||
}
|
||||
|
||||
cmdlines = c->user_commands;
|
||||
if (!cmdlines)
|
||||
return;
|
||||
fputs_filtered ("User command ", stream);
|
||||
fputs_filtered (c->name, stream);
|
||||
fputs_filtered (":\n", stream);
|
||||
fprintf_filtered (stream, "User command \"%s%s\":\n", prefix, name);
|
||||
|
||||
print_command_lines (uiout, cmdlines, 1);
|
||||
fputs_filtered ("\n", stream);
|
||||
|
|
|
@ -33,7 +33,8 @@ extern void while_command (char *arg, int from_tty);
|
|||
|
||||
extern void if_command (char *arg, int from_tty);
|
||||
|
||||
extern void show_user_1 (struct cmd_list_element *c, struct ui_file *stream);
|
||||
extern void show_user_1 (struct cmd_list_element *c, char *prefix,
|
||||
char *name, struct ui_file *stream);
|
||||
|
||||
/* Exported to gdb/breakpoint.c */
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2009-01-14 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* gdb.texinfo (Define, Hooks): Document prefix command support.
|
||||
|
||||
2009-01-14 Joseph Myers <joseph@codesourcery.com>
|
||||
Carlos O'Donell <carlos@codesourcery.com>
|
||||
|
||||
|
|
|
@ -17573,6 +17573,10 @@ end
|
|||
@item define @var{commandname}
|
||||
Define a command named @var{commandname}. If there is already a command
|
||||
by that name, you are asked to confirm that you want to redefine it.
|
||||
@var{commandname} may be a bare command name consisting of letters,
|
||||
numbers, dashes, and underscores. It may also start with any predefined
|
||||
prefix command. For example, @samp{define target my-target} creates
|
||||
a user-defined @samp{target my-target} command.
|
||||
|
||||
The definition of the command is made up of other @value{GDBN} command lines,
|
||||
which are given following the @code{define} command. The end of these
|
||||
|
@ -17707,6 +17711,10 @@ not for command aliases; you should define a hook for the basic command
|
|||
name, e.g.@: @code{backtrace} rather than @code{bt}.
|
||||
@c FIXME! So how does Joe User discover whether a command is an alias
|
||||
@c or not?
|
||||
You can hook a multi-word command by adding @code{hook-} or
|
||||
@code{hookpost-} to the last word of the command, e.g.@:
|
||||
@samp{define target hook-remote} to add a hook to @samp{target remote}.
|
||||
|
||||
If an error occurs during the execution of your hook, execution of
|
||||
@value{GDBN} commands stops and @value{GDBN} issues a prompt
|
||||
(before the command that you actually typed had a chance to run).
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2009-01-14 Daniel Jacobowitz <dan@codesourcery.com>
|
||||
|
||||
* gdb.base/define.exp: Test defining and hooking prefix commands.
|
||||
* gdb.python/python.exp: Update test for "show user" output.
|
||||
|
||||
2009-01-07 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* gdb.fortran/derived-type.exp: New variables int4 and real4. Match
|
||||
|
|
|
@ -346,6 +346,37 @@ gdb_expect {
|
|||
timeout {fail "(timeout) define hook undefined command: bar"}
|
||||
}
|
||||
|
||||
# Test creation of an additional target subcommand.
|
||||
gdb_test_multiple "define target testsuite" "" {
|
||||
-re "Type commands for definition of \"target testsuite\".\r\nEnd with a line saying just \"end\".\r\n>$" {
|
||||
gdb_test "printf \"hello\\n\"\nend" "" "define target testsuite"
|
||||
}
|
||||
}
|
||||
gdb_test_multiple "document target testsuite" "" {
|
||||
-re "Type documentation for \"target testsuite\".\r\nEnd with a line saying just \"end\".\r\n>$" {
|
||||
gdb_test "A test target.\nend" "" "document target testsuite"
|
||||
}
|
||||
}
|
||||
|
||||
gdb_test "help target" ".*A test target.*"
|
||||
gdb_test "target testsuite" "hello"
|
||||
gdb_test "show user target testsuite" "User command \"target testsuite\":\r\n printf \"hello\\\\n\"\r\n"
|
||||
|
||||
# We should even be able to hook subcommands.
|
||||
gdb_test_multiple "define target hook-testsuite" "" {
|
||||
-re "Type commands for definition of \"target hook-testsuite\".\r\nEnd with a line saying just \"end\".\r\n>$" {
|
||||
gdb_test "printf \"one\\n\"\nend" "" "define target hook-testsuite"
|
||||
}
|
||||
}
|
||||
|
||||
gdb_test_multiple "define target hookpost-testsuite" "" {
|
||||
-re "Type commands for definition of \"target hookpost-testsuite\".\r\nEnd with a line saying just \"end\".\r\n>$" {
|
||||
gdb_test "printf \"two\\n\"\nend" "" "define target hookpost-testsuite"
|
||||
}
|
||||
}
|
||||
|
||||
gdb_test "target testsuite" "one\r\nhello\r\ntwo" "target testsuite with hooks"
|
||||
|
||||
# This is a quasi-define command: Verify that the user can redefine
|
||||
# GDB's gdb_prompt.
|
||||
#
|
||||
|
@ -367,9 +398,3 @@ gdb_expect {
|
|||
|
||||
gdb_exit
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ gdb_py_test_multiple "show python command" \
|
|||
"print 23" "" \
|
||||
"end" "" \
|
||||
"end" "" \
|
||||
"show user zzq" "User command zzq:.* python.*print 23.* end"
|
||||
"show user zzq" "User command \"zzq\":.* python.*print 23.* end"
|
||||
|
||||
gdb_py_test_multiple "indented multi-line python command" \
|
||||
"python" "" \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue