This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 2/2] gdb: Allow parenthesis to group arguments to user-defined commands


When calling a user-defined command then currently, arguments are
whitespace separated.  This means that it is impossible to pass a
single argument that contains a whitespace.

The exception to the no whitespace rule is strings, a string argument,
enclosed in double, or single quotes, can contain whitespace.

However, if a user wants to reference, for example, a type name that
contains a space, as in these examples:

   user_command *((unsigned long long *) some_pointer)

   user_command {unsigned long long}some_pointer

then this will not work, as the whitespace between 'unsigned' and
'long', as well as the whitespace between 'long' and 'long', will mean
GDB interprets this as many arguments.

The solution proposed in this patch is to allow parenthesis to be used
to group arguments, so the use could now write:

   user_command (*((unsigned long long *) some_pointer))

   user_command ({unsigned long long}some_pointer)

And GDB will interpret these as a single argument.

gdb/ChangeLog:

	* cli/cli-script.c (user_args::user_args): Allow parenthesis to
	group arguments.

gdb/testsuite/ChangeLog:

	* gdb.base/commands.exp (args_with_whitespace): New proc, which is
	added to the list of procs to call.
	* gdb.base/run.c (global_var): Defined global.

gdb/doc/ChangeLog:

	* gdb.texinfo (Define): Additional documentation about argument
	syntax.
---
 gdb/ChangeLog                       |  5 ++++
 gdb/cli/cli-script.c                |  8 +++++-
 gdb/doc/ChangeLog                   |  5 ++++
 gdb/doc/gdb.texinfo                 | 54 +++++++++++++++++++++++++++++++++----
 gdb/testsuite/ChangeLog             |  6 +++++
 gdb/testsuite/gdb.base/commands.exp | 36 +++++++++++++++++++++++++
 gdb/testsuite/gdb.base/run.c        |  3 +++
 7 files changed, 111 insertions(+), 6 deletions(-)

diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index 6f31a400197..fd80ab9fbcf 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -758,6 +758,7 @@ user_args::user_args (const char *command_line)
       int squote = 0;
       int dquote = 0;
       int bsquote = 0;
+      int pdepth = 0;
 
       /* Strip whitespace.  */
       while (*p == ' ' || *p == '\t')
@@ -769,7 +770,8 @@ user_args::user_args (const char *command_line)
       /* Get to the end of this argument.  */
       while (*p)
 	{
-	  if (((*p == ' ' || *p == '\t')) && !squote && !dquote && !bsquote)
+	  if (((*p == ' ' || *p == '\t'))
+	      && !squote && !dquote && !bsquote && pdepth == 0)
 	    break;
 	  else
 	    {
@@ -793,6 +795,10 @@ user_args::user_args (const char *command_line)
 		    squote = 1;
 		  else if (*p == '"')
 		    dquote = 1;
+		  else if (*p == '(')
+		    pdepth++;
+		  else if (*p == ')')
+		    pdepth--;
 		}
 	      p++;
 	    }
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 433a2698a92..11cbef97b8f 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -25219,14 +25219,58 @@
 
 @noindent
 This defines the command @code{adder}, which prints the sum of
-its three arguments.  Note the arguments are text substitutions, so they may
-reference variables, use complex expressions, or even perform inferior
-functions calls.
+its three arguments.
+
+The arguments to user-defined commands are text substitutions, so they
+may reference variables, use complex expressions, or even perform
+inferior functions calls.  Each argument is separated with whitespace,
+so in the previous example three arguments were passed.  The following
+example also passes three arguments, though the arguments are more
+complex:
+
+@smallexample
+adder 10+1 10+2 10+3
+@end smallexample
+
+@noindent
+However, if whitespace were added around the @code{+} characters, then
+9 arguments would be passed, @code{adder} only uses the first 3 of
+these arguments, and the others would be silently ignored:
+
+@smallexample
+adder 10 + 1 10 + 2 10 + 3
+@end smallexample
+
+@noindent
+Parenthesis can be uses to group complex expressions that include
+whitespace into a single argument, so the previous example can be
+modified to pass just 3 arguments again, like this:
+
+@smallexample
+adder (10 + 1) (10 + 2) (10 + 3)
+@end smallexample
+
+@noindent
+The parenthesis are passed through as part of the argument, so the
+previous example causes @value{GDBN} to evaluate:
+
+@smallexample
+print (10 + 1) + (10 + 2) + (10 + 3)
+@end smallexample
+
+@noindent
+Nested parenthesis are also allowed within an argument, in the
+following example 3 arguments are still passed:
+
+@smallexample
+adder (10 + 1) (10 + (1 + 1)) (10 + (1 + (1 + 1)))
+@end smallexample
 
 @cindex argument count in user-defined commands
 @cindex how many arguments (user-defined commands)
-In addition, @code{$argc} may be used to find out how many arguments have
-been passed.
+@noindent
+Within a user-defined command @code{$argc} may be used to find out how
+many arguments have been passed.
 
 @smallexample
 define adder
diff --git a/gdb/testsuite/gdb.base/commands.exp b/gdb/testsuite/gdb.base/commands.exp
index 7ce33fdefa9..42ffd6fa0af 100644
--- a/gdb/testsuite/gdb.base/commands.exp
+++ b/gdb/testsuite/gdb.base/commands.exp
@@ -1125,6 +1125,41 @@ proc_with_prefix backslash_in_multi_line_command_test {} {
     gdb_test "print 1" "" "run command"
 }
 
+proc_with_prefix args_with_whitespace {} {
+    gdb_test_multiple "define show_args" "define show_args" {
+	-re "End with"  {
+	    pass "define show_args"
+	}
+    }
+
+    # This test should alternate between 0xdeadbeef and 0xfeedface two times.
+    gdb_test \
+	[multi_line_input \
+	     {printf "nargs=%d:", $argc} \
+	     {set $i = 0} \
+	     {while $i < $argc} \
+	     {printf " "} \
+	     {eval "echo '$arg%d'", $i} \
+	     {set $i = $i + 1} \
+	     {end} \
+	     {printf "\n"} \
+	     {end}] \
+	"" \
+	"enter commands"
+
+    gdb_test "show_args 1 2 3" \
+	"nargs=3: '1' '2' '3'"
+
+    gdb_test "show_args 1 (1 + 1) (1 + (1 + 1))" \
+	"nargs=3: '1' '\\(1 \\+ 1\\)' '\\(1 \\+ \\(1 \\+ 1\\)\\)'"
+
+    gdb_test "show_args ({unsigned long long} &global_var)" \
+	"nargs=1: '\\({unsigned long long} &global_var\\)'"
+
+    gdb_test "show_args (*((unsigned long long *) &global_var))" \
+	"nargs=1: '\\(\\*\\(\\(unsigned long long \\*\\) &global_var\\)\\)'"
+}
+
 gdbvar_simple_if_test
 gdbvar_simple_while_test
 gdbvar_complex_if_while_test
@@ -1154,5 +1189,6 @@ backslash_in_multi_line_command_test
 define_if_without_arg_test
 loop_break_test
 loop_continue_test
+args_with_whitespace
 # This one should come last, as it redefines "backtrace".
 redefine_backtrace_test
diff --git a/gdb/testsuite/gdb.base/run.c b/gdb/testsuite/gdb.base/run.c
index 614b018260d..d89bad78bb4 100644
--- a/gdb/testsuite/gdb.base/run.c
+++ b/gdb/testsuite/gdb.base/run.c
@@ -8,6 +8,9 @@
 
 #include "../lib/unbuffer_output.c"
 
+/* Used by commands.exp test script.  */
+volatile unsigned long long global_var = 34;
+
 int factorial (int);
 
 int
-- 
2.14.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]