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".
This commit is contained in:
parent
295dc222a7
commit
7a2c85f259
@ -1,3 +1,14 @@
|
||||
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.
|
||||
|
||||
2018-05-04 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* tracepoint.c (actions_command): Update.
|
||||
|
@ -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)
|
||||
@ -1409,6 +1439,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)
|
||||
{
|
||||
|
@ -42,6 +42,7 @@ enum command_control_type
|
||||
compile_control,
|
||||
guile_control,
|
||||
while_stepping_control,
|
||||
define_control,
|
||||
invalid_control
|
||||
};
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
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".
|
||||
|
||||
2018-05-04 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
Pedro Alves <palves@redhat.com>
|
||||
|
||||
|
@ -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" "$cmd command requires an argument." "type $cmd without args"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user