diff options
author | Tom Tromey <tom@tromey.com> | 2018-04-18 16:10:59 -0600 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2018-05-04 15:58:07 -0600 |
commit | 7a2c85f25977ff9b11728ba85b1417538e22c246 (patch) | |
tree | 941f548ed63c2bd4099110d92ff7d4089d88a9d1 /gdb/cli | |
parent | 295dc222a712b700d9afa7e2462a68b866b120e1 (diff) | |
download | gdb-7a2c85f25977ff9b11728ba85b1417538e22c246.zip gdb-7a2c85f25977ff9b11728ba85b1417538e22c246.tar.gz gdb-7a2c85f25977ff9b11728ba85b1417538e22c246.tar.bz2 |
Allow defining a user command inside a user command
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.
ChangeLog
2018-05-04 Tom Tromey <tom@tromey.com>
PR gdb/11750:
* cli/cli-script.h (enum command_control_type) <define_control>:
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-05-04 Tom Tromey <tom@tromey.com>
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".
Diffstat (limited to 'gdb/cli')
-rw-r--r-- | gdb/cli/cli-script.c | 56 | ||||
-rw-r--r-- | gdb/cli/cli-script.h | 1 |
2 files changed, 47 insertions, 10 deletions
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c index 36740b9..d679e04 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; @@ -134,9 +138,15 @@ multi_line_command_p (enum command_control_type type) 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.")); + if (args == NULL || *args == '\0') + { + if (type == if_control) + error (_("if command requires an argument.")); + else if (type == while_control) + error (_("while command requires an argument.")); + else if (type == define_control) + error (_("define command requires an argument.")); + } gdb_assert (args != NULL); return new struct command_line (type, xstrdup (args)); @@ -611,6 +621,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 +976,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 +1321,15 @@ user_defined_command (const char *ignore, int from_tty) { } +/* Define a user-defined command. If COMMANDS is NULL, then this is a + top-level call and the commands will be read using + read_command_lines. Otherwise, it is a "define" command in an + existing command and the commands are provided. In the + non-top-level 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 +1356,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 +1390,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 +1402,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 +1440,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 7e5f94c..0bd0d59 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 }; |