From patchwork Thu Apr 19 19:15:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 26864 Received: (qmail 46823 invoked by alias); 19 Apr 2018 19:16:06 -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 46458 invoked by uid 89); 19 Apr 2018 19:15:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=13857 X-HELO: gateway32.websitewelcome.com Received: from gateway32.websitewelcome.com (HELO gateway32.websitewelcome.com) (192.185.145.107) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 19 Apr 2018 19:15:50 +0000 Received: from cm12.websitewelcome.com (cm12.websitewelcome.com [100.42.49.8]) by gateway32.websitewelcome.com (Postfix) with ESMTP id B3DD4299A85 for ; Thu, 19 Apr 2018 14:15:48 -0500 (CDT) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with SMTP id 9F24fnzmMlAdr9F24fOtbY; Thu, 19 Apr 2018 14:15:48 -0500 X-Authority-Reason: nr=8 Received: from 97-122-176-117.hlrn.qwest.net ([97.122.176.117]:44916 helo=bapiya.Home) by box5379.bluehost.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.89_1) (envelope-from ) id 1f9F24-0041O4-CL; Thu, 19 Apr 2018 14:15:48 -0500 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [RFA 5/8] Allow defining a user command inside a user command Date: Thu, 19 Apr 2018 13:15:36 -0600 Message-Id: <20180419191539.661-6-tom@tromey.com> In-Reply-To: <20180419191539.661-1-tom@tromey.com> References: <20180419191539.661-1-tom@tromey.com> X-BWhitelist: no X-Source-L: No X-Exim-ID: 1f9F24-0041O4-CL X-Source-Sender: 97-122-176-117.hlrn.qwest.net (bapiya.Home) [97.122.176.117]:44916 X-Source-Auth: tom+tromey.com X-Email-Count: 6 X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTM3OS5ibHVlaG9zdC5jb20= X-Local-Domain: yes PR gdb/11750 concerns defining a command inside a user commnad, like: define outer define inner echo hi\n end end This patch adds this capability to gdb. 2018-04-19 Tom Tromey PR gdb/11750: * cli/cli-script.h (enum command_control_type) : New constant. * cli/cli-script.c (multi_line_command_p): Handle define_control. (build_command_line, execute_control_command_1) (process_next_line): Likewise. (do_define_command): New function, extracted from define_command. (define_command): Use it. testsuite/ChangeLog 2018-04-19 Tom Tromey PR gdb/11750: * gdb.base/define.exp: Test defining a user command inside a user command. * gdb.base/commands.exp (define_if_without_arg_test): Test "define". --- gdb/ChangeLog | 11 +++++++++ gdb/cli/cli-script.c | 49 ++++++++++++++++++++++++++++++------- gdb/cli/cli-script.h | 1 + gdb/testsuite/ChangeLog | 7 ++++++ gdb/testsuite/gdb.base/commands.exp | 4 +-- gdb/testsuite/gdb.base/define.exp | 8 ++++++ 6 files changed, 69 insertions(+), 11 deletions(-) diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c index 36740b97ad..624a3bda68 100644 --- a/gdb/cli/cli-script.c +++ b/gdb/cli/cli-script.c @@ -44,6 +44,9 @@ recurse_read_control_structure (char * (*read_next_line_func) (void), void (*validator)(char *, void *), void *closure); +static void do_define_command (const char *comname, int from_tty, + const counted_command_line *commands); + static char *read_next_line (void); /* Level of control structure when reading. */ @@ -122,6 +125,7 @@ multi_line_command_p (enum command_control_type type) case compile_control: case python_control: case guile_control: + case define_control: return 1; default: return 0; @@ -135,8 +139,9 @@ static struct command_line * build_command_line (enum command_control_type type, const char *args) { if ((args == NULL || *args == '\0') - && (type == if_control || type == while_control)) - error (_("if/while commands require arguments.")); + && (type == if_control || type == while_control + || type == define_control)) + error (_("if/while/define commands require arguments.")); gdb_assert (args != NULL); return new struct command_line (type, xstrdup (args)); @@ -611,6 +616,12 @@ execute_control_command_1 (struct command_line *cmd) ret = simple_control; break; + case define_control: + print_command_trace ("define %s", cmd->line); + do_define_command (cmd->line, 0, &cmd->body_list_0); + ret = simple_control; + break; + case python_control: case guile_control: { @@ -960,6 +971,8 @@ process_next_line (char *p, struct command_line **command, int parse_commands, { *command = build_command_line (commands_control, line_first_arg (p)); } + else if (command_name_equals (cmd, "define")) + *command = build_command_line (define_control, line_first_arg (p)); else if (command_name_equals (cmd, "python") && !inline_cmd) { /* Note that we ignore the inline "python command" form @@ -1303,8 +1316,15 @@ user_defined_command (const char *ignore, int from_tty) { } +/* Define a user-defined command. If COMMANDS is NULL, then this is + an interactive call and the commands will be read from the user. + Otherwise, it is a "define" command in a script and the commands + are provided. In the non-interactive case, various prompts and + warnings are disabled. */ + static void -define_command (const char *comname, int from_tty) +do_define_command (const char *comname, int from_tty, + const counted_command_line *commands) { enum cmd_hook_type { @@ -1331,7 +1351,7 @@ define_command (const char *comname, int from_tty) if (c && strcmp (comname, c->name) != 0) c = 0; - if (c) + if (c && commands == nullptr) { int q; @@ -1365,7 +1385,7 @@ define_command (const char *comname, int from_tty) hookc = lookup_cmd (&tem, *list, "", -1, 0); if (hookc && strcmp (comname + hook_name_size, hookc->name) != 0) hookc = 0; - if (!hookc) + if (!hookc && commands == nullptr) { warning (_("Your new `%s' command does not " "hook any existing command."), @@ -1377,10 +1397,15 @@ define_command (const char *comname, int from_tty) comname = xstrdup (comname); - std::string prompt - = string_printf ("Type commands for definition of \"%s\".", comfull); - counted_command_line cmds = read_command_lines (prompt.c_str (), from_tty, - 1, 0, 0); + counted_command_line cmds; + if (commands == nullptr) + { + std::string prompt + = string_printf ("Type commands for definition of \"%s\".", comfull); + cmds = read_command_lines (prompt.c_str (), from_tty, 1, 0, 0); + } + else + cmds = *commands; newc = add_cmd (comname, class_user, user_defined_command, (c && c->theclass == class_user) @@ -1410,6 +1435,12 @@ define_command (const char *comname, int from_tty) } static void +define_command (const char *comname, int from_tty) +{ + do_define_command (comname, from_tty, nullptr); +} + +static void document_command (const char *comname, int from_tty) { struct cmd_list_element *c, **list; diff --git a/gdb/cli/cli-script.h b/gdb/cli/cli-script.h index 7e5f94c0ad..0bd0d597ae 100644 --- a/gdb/cli/cli-script.h +++ b/gdb/cli/cli-script.h @@ -42,6 +42,7 @@ enum command_control_type compile_control, guile_control, while_stepping_control, + define_control, invalid_control }; diff --git a/gdb/testsuite/gdb.base/commands.exp b/gdb/testsuite/gdb.base/commands.exp index b33e5124ec..f2f2b5d87c 100644 --- a/gdb/testsuite/gdb.base/commands.exp +++ b/gdb/testsuite/gdb.base/commands.exp @@ -1014,7 +1014,7 @@ proc_with_prefix redefine_backtrace_test {} { # Test using "if" and "while" without args when building a command list. proc define_if_without_arg_test {} { - foreach cmd {if while} { + foreach cmd {if while define} { set test "define some_command_$cmd" gdb_test_multiple $test $test { -re "End with" { @@ -1022,7 +1022,7 @@ proc define_if_without_arg_test {} { } } - gdb_test "$cmd" "if/while commands require arguments." "type $cmd without args" + gdb_test "$cmd" "if/while/define commands require arguments." "type $cmd without args" } } diff --git a/gdb/testsuite/gdb.base/define.exp b/gdb/testsuite/gdb.base/define.exp index f82a9efdff..e4064b7afc 100644 --- a/gdb/testsuite/gdb.base/define.exp +++ b/gdb/testsuite/gdb.base/define.exp @@ -298,5 +298,13 @@ gdb_test_multiple "set prompt \\(gdb\\) " "reset gdb_prompt" { } } +gdb_test_multiple "define do-define" "" { + -re "Type commands for definition of \"do-define\".\r\nEnd with a line saying just \"end\".\r\n>$" { + gdb_test "define do-printit\necho here\\n\nend\nend" "" "define do-define" + } +} +gdb_test_no_output "do-define" "invoke do-define" +gdb_test "do-printit" "here" "invoke do-printit" + gdb_exit return 0