From: Daniel Jacobowitz Date: Wed, 14 Jan 2009 20:40:09 +0000 (+0000) Subject: * NEWS: Document "define" for prefixed commands. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=adb483feb8b53555613d1165a6c6de4bdc1a5160;p=binutils-gdb.git * 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 05662356915..04022f90652 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,16 @@ +2009-01-14 Daniel Jacobowitz + + * 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 * mingw-ser.c (console_select_thread): Add return to make diff --git a/gdb/NEWS b/gdb/NEWS index 4532f9e0bdb..027ab027672 100644 --- a/gdb/NEWS +++ b/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, diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c index d3694e43481..4d9c4f385da 100644 --- a/gdb/cli/cli-cmds.c +++ b/gdb/cli/cli-cmds.c @@ -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); } } } diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c index b4bc8cf1056..d71d516975d 100644 --- a/gdb/cli/cli-decode.c +++ b/gdb/cli/cli-decode.c @@ -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); } } diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c index 835d29ca2bd..a7f56d053b1 100644 --- a/gdb/cli/cli-script.c +++ b/gdb/cli/cli-script.c @@ -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) +/* 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. */ + +static struct cmd_list_element ** +validate_comname (char **comname) { - char *p; + struct cmd_list_element **list = &cmdlist; + char *p, *last_word; - if (comname == 0) + 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); diff --git a/gdb/cli/cli-script.h b/gdb/cli/cli-script.h index dafd3da8fc8..c65223fe03c 100644 --- a/gdb/cli/cli-script.h +++ b/gdb/cli/cli-script.h @@ -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 */ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index a729066c11a..f768eb2ed8e 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2009-01-14 Daniel Jacobowitz + + * gdb.texinfo (Define, Hooks): Document prefix command support. + 2009-01-14 Joseph Myers Carlos O'Donell diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 817b96b9b6d..583d96c85d6 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -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). diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index c8266764330..0795f587acd 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-01-14 Daniel Jacobowitz + + * 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 * gdb.fortran/derived-type.exp: New variables int4 and real4. Match diff --git a/gdb/testsuite/gdb.base/define.exp b/gdb/testsuite/gdb.base/define.exp index bce5bdb35d0..3ef27ae0918 100644 --- a/gdb/testsuite/gdb.base/define.exp +++ b/gdb/testsuite/gdb.base/define.exp @@ -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 - - - - - - diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp index 201e1c5f16e..a0c9b391cd4 100644 --- a/gdb/testsuite/gdb.python/python.exp +++ b/gdb/testsuite/gdb.python/python.exp @@ -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" "" \