This is the mail archive of the
gdb-cvs@sourceware.org
mailing list for the GDB project.
[binutils-gdb] Fix PR 20559 - "eval" command and $arg0...$arg9/$argc substitution
- From: Pedro Alves <palves at sourceware dot org>
- To: gdb-cvs at sourceware dot org
- Date: 2 Dec 2016 19:23:57 -0000
- Subject: [binutils-gdb] Fix PR 20559 - "eval" command and $arg0...$arg9/$argc substitution
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=01770bbde902e075e524b518ac6c1087a4cc1cfb
commit 01770bbde902e075e524b518ac6c1087a4cc1cfb
Author: Pedro Alves <palves@redhat.com>
Date: Fri Dec 2 19:17:13 2016 +0000
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.
Diff:
---
gdb/ChangeLog | 12 ++++++++++++
gdb/NEWS | 12 ++++++++++++
gdb/cli/cli-script.c | 19 ++++++++-----------
gdb/cli/cli-script.h | 6 ++++++
gdb/doc/ChangeLog | 7 +++++++
gdb/doc/gdb.texinfo | 16 ++++++++++++++++
gdb/printcmd.c | 3 +++
gdb/testsuite/ChangeLog | 7 +++++++
gdb/testsuite/gdb.base/commands.exp | 31 +++++++++++++++++++++++++++++++
9 files changed, 102 insertions(+), 11 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 33d8243..2066268 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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:
diff --git a/gdb/NEWS b/gdb/NEWS
index a597405..4089124 100644
--- a/gdb/NEWS
+++ b/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
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index ce4d8cb..15947a9 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 7db6e82..8920d44 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);
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index dc8244c..18564b6 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -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.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6ad2754..f4dfac2 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -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
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index f434f5f..bab13fb 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -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);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 5a0330c..c6ee462 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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
diff --git a/gdb/testsuite/gdb.base/commands.exp b/gdb/testsuite/gdb.base/commands.exp
index 8c06e8c..3308a9b 100644
--- a/gdb/testsuite/gdb.base/commands.exp
+++ b/gdb/testsuite/gdb.base/commands.exp
@@ -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