From patchwork Tue Jan 10 14:28:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Guitton X-Patchwork-Id: 18842 Received: (qmail 130414 invoked by alias); 10 Jan 2017 14:28:08 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 130404 invoked by uid 89); 10 Jan 2017 14:28:07 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=guile, disp, *text, 1016, 7 X-HELO: smtp.eu.adacore.com Received: from mel.act-europe.fr (HELO smtp.eu.adacore.com) (194.98.77.210) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 10 Jan 2017 14:28:06 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id 37A7882FC8; Tue, 10 Jan 2017 15:28:04 +0100 (CET) Received: from smtp.eu.adacore.com ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id VmKyNreiGnSX; Tue, 10 Jan 2017 15:28:04 +0100 (CET) Received: from chelles.act-europe.fr (chelles.act-europe.fr [10.10.0.160]) by smtp.eu.adacore.com (Postfix) with ESMTP id 2440282FBF; Tue, 10 Jan 2017 15:28:04 +0100 (CET) Received: by chelles.act-europe.fr (Postfix, from userid 560) id 20EAD1EA0067; Tue, 10 Jan 2017 15:28:04 +0100 (CET) From: Jerome Guitton To: gdb-patches@sourceware.org Cc: Jerome Guitton Subject: [RFA] completion in command definition Date: Tue, 10 Jan 2017 15:28:01 +0100 Message-Id: <1484058481-6378-1-git-send-email-guitton@adacore.com> When defining a new macro, "command" is not recognized as an aliased for "commands": (gdb) define breakmain Type commands for definition of "breakmain". End with a line saying just "end". >break main >command >echo "IN MAIN\n" >end (gdb) There is a special case for while-stepping, where 'ws' and 'stepping' are recognized explicitely. We could add "command" to the list as well. I'd rather use cli-decode though. Patch in attachment, with a test, tested in x86-linux. OK to apply? gdb/ChangeLog: * cli/cli-decode.c (find_command_name_length): Make it global. * cli/cli-decode.h (find_command_name_length): Declare. * cli/cli-script.c (command_name_equals, line_first_arg): New functions. (process_next_line): Use cli-decode to parse command names. gdb/testsuite/ChangeLog: * gdb.base/define.exp: Add test for completion in command definition. --- gdb/cli/cli-decode.c | 2 +- gdb/cli/cli-decode.h | 1 + gdb/cli/cli-script.c | 66 +++++++++++++++++++++---------------- gdb/testsuite/gdb.base/define.exp | 21 ++++++++++++ 4 files changed, 61 insertions(+), 29 deletions(-) diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c index d59fe9b..b15ddb5 100644 --- a/gdb/cli/cli-decode.c +++ b/gdb/cli/cli-decode.c @@ -1255,7 +1255,7 @@ find_cmd (const char *command, int len, struct cmd_list_element *clist, return found; } -static int +int find_command_name_length (const char *text) { const char *p = text; diff --git a/gdb/cli/cli-decode.h b/gdb/cli/cli-decode.h index e5ab839..83bc34a 100644 --- a/gdb/cli/cli-decode.h +++ b/gdb/cli/cli-decode.h @@ -253,4 +253,5 @@ extern const char * const auto_boolean_enums[]; extern int cli_user_command_p (struct cmd_list_element *); +extern int find_command_name_length (const char *); #endif /* !defined (CLI_DECODE_H) */ diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c index 6f44d52..338d726 100644 --- a/gdb/cli/cli-script.c +++ b/gdb/cli/cli-script.c @@ -904,6 +904,28 @@ read_next_line (void) return command_line_input (prompt_ptr, from_tty, "commands"); } +/* Return non-zero if CMD's name is NAME. */ + +static int +command_name_equals (struct cmd_list_element *cmd, char *name) +{ + return cmd + && cmd != CMD_LIST_AMBIGUOUS + && strcmp (cmd->name, name) == 0; +} + +/* Given an input line P, skip the command and return a pointer to the + first argument. */ + +static char * +line_first_arg (char *p) +{ + char *first_arg = p + find_command_name_length (p); + while (first_arg != '\0' && isspace (*first_arg)) + first_arg++; + return first_arg; +} + /* Process one input line. If the command is an "end", return such an indication to the caller. If PARSE_COMMANDS is true, strip leading whitespace (trailing whitespace is always stripped) in the line, @@ -919,6 +941,9 @@ process_next_line (char *p, struct command_line **command, int parse_commands, char *p_end; char *p_start; int not_handled = 0; + char *cmd_name = p; + struct cmd_list_element *last_line = 0; + struct cmd_list_element *cmd; /* Not sure what to do here. */ if (p == NULL) @@ -938,9 +963,11 @@ process_next_line (char *p, struct command_line **command, int parse_commands, We also permit whitespace before end and after. */ if (p_end - p_start == 3 && startswith (p_start, "end")) return end_command; - + if (parse_commands) { + cmd = lookup_cmd_1 ((const char **) &cmd_name, cmdlist, &last_line, 1); + /* If commands are parsed, we skip initial spaces. Otherwise, which is the case for Python commands and documentation (see the 'document' command), spaces are preserved. */ @@ -958,9 +985,7 @@ process_next_line (char *p, struct command_line **command, int parse_commands, /* Check for while, if, break, continue, etc and build a new command line structure for them. */ - if ((p_end - p >= 14 && startswith (p, "while-stepping")) - || (p_end - p >= 8 && startswith (p, "stepping")) - || (p_end - p >= 2 && startswith (p, "ws"))) + if (command_name_equals (cmd, "while-stepping")) { /* Because validate_actionline and encode_action lookup command's line as command, we need the line to @@ -975,40 +1000,25 @@ process_next_line (char *p, struct command_line **command, int parse_commands, not. */ *command = build_command_line (while_stepping_control, p); } - else if (p_end - p > 5 && startswith (p, "while")) + else if (command_name_equals (cmd, "while")) { - char *first_arg; - - first_arg = p + 5; - while (first_arg < p_end && isspace (*first_arg)) - first_arg++; - *command = build_command_line (while_control, first_arg); + *command = build_command_line (while_control, line_first_arg (p)); } - else if (p_end - p > 2 && startswith (p, "if")) + else if (command_name_equals (cmd, "if")) { - char *first_arg; - - first_arg = p + 2; - while (first_arg < p_end && isspace (*first_arg)) - first_arg++; - *command = build_command_line (if_control, first_arg); + *command = build_command_line (if_control, line_first_arg (p)); } - else if (p_end - p >= 8 && startswith (p, "commands")) + else if (command_name_equals (cmd, "commands")) { - char *first_arg; - - first_arg = p + 8; - while (first_arg < p_end && isspace (*first_arg)) - first_arg++; - *command = build_command_line (commands_control, first_arg); + *command = build_command_line (commands_control, line_first_arg (p)); } - else if (p_end - p == 6 && startswith (p, "python")) + else if (command_name_equals (cmd, "python")) { /* Note that we ignore the inline "python command" form here. */ *command = build_command_line (python_control, ""); } - else if (p_end - p == 6 && startswith (p, "compile")) + else if (command_name_equals (cmd, "compile")) { /* Note that we ignore the inline "compile command" form here. */ @@ -1016,7 +1026,7 @@ process_next_line (char *p, struct command_line **command, int parse_commands, (*command)->control_u.compile.scope = COMPILE_I_INVALID_SCOPE; } - else if (p_end - p == 5 && startswith (p, "guile")) + else if (command_name_equals (cmd, "guile")) { /* Note that we ignore the inline "guile command" form here. */ *command = build_command_line (guile_control, ""); diff --git a/gdb/testsuite/gdb.base/define.exp b/gdb/testsuite/gdb.base/define.exp index 59203ec..355a7bc 100644 --- a/gdb/testsuite/gdb.base/define.exp +++ b/gdb/testsuite/gdb.base/define.exp @@ -147,6 +147,27 @@ gdb_test_multiple "define ifnospace" "define user command: ifnospace" \ gdb_test "ifnospace" ".*hi there.*" "test ifnospace is parsed correctly" +# Verify that the command parser properly handle completion. + +gdb_test_multiple "define breakmain" "define user command: breakmain" \ +{ + -re "Type commands for definition of \"breakmain\".\r\nEnd with a line saying just \"end\".\r\n>$" \ + { + gdb_test_multiple "break main\ncommand\necho\nend\nend" "send body of breakmain" \ + { + -re "$gdb_prompt $"\ + {pass "define user command: breakmain"} + } + } +} + +gdb_test "breakmain" ".*Breakpoint 2.*" "test command completion in define" + +gdb_test "info break 2" \ + "Num Type\[ \]+Disp Enb Address\[ \]+What.* +\[0-9\]+\[\t \]+breakpoint keep y.* in main at .* +\[\t \]+echo.*" + # Verify that the command parser doesn't require a space after an 'while' # command in a user defined function. #