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 <palves@redhat.com> 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 <palves@redhat.com> PR cli/20559 * gdb.texinfo (Define): Add example of using "eval" to process a variable number of arguments. (Output) <eval>: Add anchor. gdb/testsuite/ChangeLog: 2016-12-02 Pedro Alves <palves@redhat.com> PR cli/20559 * gdb.base/commands.exp (user_defined_command_args_eval): New procedure. (top level): Call it.
This commit is contained in:
parent
7ed7e438bf
commit
01770bbde9
9 changed files with 102 additions and 11 deletions
|
@ -1,3 +1,15 @@
|
|||
2016-12-02 Pedro Alves <palves@redhat.com>
|
||||
|
||||
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.
|
||||
|
||||
2016-12-02 Tom Tromey <tom@tromey.com>
|
||||
|
||||
PR symtab/16264:
|
||||
|
|
12
gdb/NEWS
12
gdb/NEWS
|
@ -32,6 +32,18 @@
|
|||
|
||||
* Support for Java programs compiled with gcj has been removed.
|
||||
|
||||
* The "eval" command now expands user-defined command arguments.
|
||||
|
||||
This makes it easier to process a variable number of arguments:
|
||||
|
||||
define mycommand
|
||||
set $i = 0
|
||||
while $i < $argc
|
||||
eval "print $arg%d", $i
|
||||
set $i = $i + 1
|
||||
end
|
||||
end
|
||||
|
||||
* New targets
|
||||
|
||||
Synopsys ARC arc*-*-elf32
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2016-12-02 Pedro Alves <palves@redhat.com>
|
||||
|
||||
PR cli/20559
|
||||
* gdb.texinfo (Define): Add example of using "eval" to process a
|
||||
variable number of arguments.
|
||||
(Output) <eval>: Add anchor.
|
||||
|
||||
2016-11-30 Simon Marchi <simon.marchi@polymtl.ca>
|
||||
|
||||
* Makefile.in: Likewise.
|
||||
|
|
|
@ -24096,6 +24096,21 @@ define adder
|
|||
end
|
||||
@end smallexample
|
||||
|
||||
Combining with the @code{eval} command (@pxref{eval}) makes it easier
|
||||
to process a variable number of arguments:
|
||||
|
||||
@smallexample
|
||||
define adder
|
||||
set $i = 0
|
||||
set $sum = 0
|
||||
while $i < $argc
|
||||
eval "set $sum = $sum + $arg%d", $i
|
||||
set $i = $i + 1
|
||||
end
|
||||
print $sum
|
||||
end
|
||||
@end smallexample
|
||||
|
||||
@table @code
|
||||
|
||||
@kindex define
|
||||
|
@ -24526,6 +24541,7 @@ Here's an example of printing DFP types using the above conversion letters:
|
|||
printf "D32: %Hf - D64: %Df - D128: %DDf\n",1.2345df,1.2E10dd,1.2E1dl
|
||||
@end smallexample
|
||||
|
||||
@anchor{eval}
|
||||
@kindex eval
|
||||
@item eval @var{template}, @var{expressions}@dots{}
|
||||
Convert the values of one or more @var{expressions} under the control of
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "charset.h"
|
||||
#include "arch-utils.h"
|
||||
#include "cli/cli-utils.h"
|
||||
#include "cli/cli-script.h"
|
||||
#include "format.h"
|
||||
#include "source.h"
|
||||
|
||||
|
@ -2723,6 +2724,8 @@ eval_command (char *arg, int from_tty)
|
|||
|
||||
std::string expanded = ui_file_as_string (ui_out);
|
||||
|
||||
expanded = insert_user_defined_cmd_args (expanded.c_str ());
|
||||
|
||||
execute_command (&expanded[0], from_tty);
|
||||
|
||||
do_cleanups (cleanups);
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2016-12-02 Pedro Alves <palves@redhat.com>
|
||||
|
||||
PR cli/20559
|
||||
* gdb.base/commands.exp (user_defined_command_args_eval): New
|
||||
procedure.
|
||||
(top level): Call it.
|
||||
|
||||
2016-12-02 Luis Machado <lgustavo@codesourcery.com>
|
||||
|
||||
* gdb.base/ovldbreak.exp (take_gdb_out_of_choice_menu): Restore
|
||||
|
|
|
@ -352,6 +352,36 @@ proc_with_prefix user_defined_command_test {} {
|
|||
"display user-defined empty command"
|
||||
}
|
||||
|
||||
# Test that "eval" in a user-defined command expands $argc/$argN.
|
||||
|
||||
proc_with_prefix user_defined_command_args_eval {} {
|
||||
global gdb_prompt
|
||||
|
||||
gdb_test_multiple "define command_args_eval" \
|
||||
"define command_args_eval" {
|
||||
-re "End with" {
|
||||
pass "define"
|
||||
}
|
||||
}
|
||||
|
||||
# Make a command that constructs references to $argc and $argN via
|
||||
# eval.
|
||||
gdb_test \
|
||||
[multi_line \
|
||||
{eval "printf \"argc = %%d,\", $arg%c", 'c'} \
|
||||
{set $i = 0} \
|
||||
{while $i < $argc} \
|
||||
{ eval "printf \" %%d\", $arg%d", $i} \
|
||||
{ set $i = $i + 1} \
|
||||
{end} \
|
||||
{printf "\n"} \
|
||||
{end}] \
|
||||
"" \
|
||||
"enter commands"
|
||||
|
||||
gdb_test "command_args_eval 1 2 3" "argc = 3, 1 2 3" "execute command"
|
||||
}
|
||||
|
||||
proc_with_prefix watchpoint_command_test {} {
|
||||
global gdb_prompt
|
||||
|
||||
|
@ -882,6 +912,7 @@ if_while_breakpoint_command_test
|
|||
infrun_breakpoint_command_test
|
||||
breakpoint_command_test
|
||||
user_defined_command_test
|
||||
user_defined_command_args_eval
|
||||
watchpoint_command_test
|
||||
test_command_prompt_position
|
||||
deprecated_command_test
|
||||
|
|
Loading…
Add table
Reference in a new issue