From 01770bbde902e075e524b518ac6c1087a4cc1cfb Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Fri, 2 Dec 2016 19:17:13 +0000 Subject: Fix PR 20559 - "eval" command and $arg0...$arg9/$argc substitution It'd be handy to be able to iterate over command arguments in user-defined commands, in order to support optional arguments ($arg0..$argN). I thought I could make it work with "eval", but alas, it doesn't work currently. E.g., with: define test set $i = 0 while $i < $argc eval "print $arg%d", $i set $i = $i + 1 end end we get: (gdb) test 1 $1 = void (gdb) test 1 2 3 $2 = void $3 = void $4 = void (gdb) The problem is that "eval" doesn't do user-defined command arguments substitution after expanding its own argument. This patch fixes that, which makes the example above work: (gdb) test 1 $1 = 1 (gdb) test 1 2 3 $2 = 1 $3 = 2 $4 = 3 (gdb) New test included, similar the above, but also exercises expanding $argc. I think this is likely to simplify many scripts out there, so I'm adding an example to the manual and mentioning it in NEWS as well. gdb/ChangeLog: 2016-12-02 Pedro Alves PR cli/20559 * NEWS: Mention "eval" expands user-defined command arguments. * cli/cli-script.c (execute_control_command): Adjust to rename. (insert_args): Rename to ... (insert_user_defined_cmd_args): ... this, and make extern. * cli/cli-script.h (insert_user_defined_cmd_args): New declaration. * printcmd.c: Include "cli/cli-script.h". (eval_command): Call insert_user_defined_cmd_args. gdb/doc/ChangeLog: 2016-12-02 Pedro Alves PR cli/20559 * gdb.texinfo (Define): Add example of using "eval" to process a variable number of arguments. (Output) : Add anchor. gdb/testsuite/ChangeLog: 2016-12-02 Pedro Alves PR cli/20559 * gdb.base/commands.exp (user_defined_command_args_eval): New procedure. (top level): Call it. --- gdb/cli/cli-script.c | 19 ++++++++----------- gdb/cli/cli-script.h | 6 ++++++ 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'gdb/cli') diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c index ce4d8cb103b..15947a9a78a 100644 --- a/gdb/cli/cli-script.c +++ b/gdb/cli/cli-script.c @@ -41,8 +41,6 @@ recurse_read_control_structure (char * (*read_next_line_func) (void), void (*validator)(char *, void *), void *closure); -static std::string insert_args (const char *line); - static struct cleanup * setup_user_args (char *p); static char *read_next_line (void); @@ -455,7 +453,7 @@ execute_control_command (struct command_line *cmd) case simple_control: { /* A simple command, execute it and return. */ - std::string new_line = insert_args (cmd->line); + std::string new_line = insert_user_defined_cmd_args (cmd->line); execute_command (&new_line[0], 0); ret = cmd->control_type; break; @@ -486,7 +484,7 @@ execute_control_command (struct command_line *cmd) print_command_trace (buffer); /* Parse the loop control expression for the while statement. */ - std::string new_line = insert_args (cmd->line); + std::string new_line = insert_user_defined_cmd_args (cmd->line); expression_up expr = parse_expression (new_line.c_str ()); ret = simple_control; @@ -551,7 +549,7 @@ execute_control_command (struct command_line *cmd) print_command_trace (buffer); /* Parse the conditional for the if statement. */ - std::string new_line = insert_args (cmd->line); + std::string new_line = insert_user_defined_cmd_args (cmd->line); expression_up expr = parse_expression (new_line.c_str ()); current = NULL; @@ -591,7 +589,7 @@ execute_control_command (struct command_line *cmd) { /* Breakpoint commands list, record the commands in the breakpoint's command list and return. */ - std::string new_line = insert_args (cmd->line); + std::string new_line = insert_user_defined_cmd_args (cmd->line); ret = commands_from_control_command (new_line.c_str (), cmd); break; } @@ -782,13 +780,12 @@ locate_arg (const char *p) return NULL; } -/* Insert the user defined arguments stored in user_arg into the $arg - arguments found in line. */ +/* See cli-script.h. */ -static std::string -insert_args (const char *line) +std::string +insert_user_defined_cmd_args (const char *line) { - /* If we are not in a user-defined function, treat $argc, $arg0, et + /* If we are not in a user-defined command, treat $argc, $arg0, et cetera as normal convenience variables. */ if (user_args == NULL) return line; diff --git a/gdb/cli/cli-script.h b/gdb/cli/cli-script.h index 7db6e82e6ff..8920d44fde4 100644 --- a/gdb/cli/cli-script.h +++ b/gdb/cli/cli-script.h @@ -53,6 +53,12 @@ extern struct cleanup * extern void execute_user_command (struct cmd_list_element *c, char *args); +/* If we're in a user-defined command, replace any $argc/$argN + reference found in LINE with the arguments that were passed to the + command. Otherwise, treat $argc/$argN as normal convenience + variables. */ +extern std::string insert_user_defined_cmd_args (const char *line); + /* Exported to top.c */ extern void print_command_trace (const char *cmd); -- cgit v1.2.1