public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PUSHED 5/5] Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP]
  2018-10-27 12:44 [PUSHED 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers
                   ` (3 preceding siblings ...)
  2018-10-27 12:44 ` [PUSHED 3/5] Document changes " Philippe Waroquiers
@ 2018-10-27 12:44 ` Philippe Waroquiers
  4 siblings, 0 replies; 8+ messages in thread
From: Philippe Waroquiers @ 2018-10-27 12:44 UTC (permalink / raw)
  To: gdb-patches; +Cc: Philippe Waroquiers

Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP]

gdb/testsuite/ChangeLog
2018-10-27  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.base/info_qt.c: New file.
	* gdb.base/info_qt.exp: New file.
---
 gdb/testsuite/ChangeLog            |   5 +
 gdb/testsuite/gdb.base/info_qt.c   |  78 +++++++++
 gdb/testsuite/gdb.base/info_qt.exp | 243 +++++++++++++++++++++++++++++
 3 files changed, 326 insertions(+)
 create mode 100644 gdb/testsuite/gdb.base/info_qt.c
 create mode 100644 gdb/testsuite/gdb.base/info_qt.exp

diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index a8c83d792c..cf0da029e4 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-10-27  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
+
+	* gdb.base/info_qt.c: New file.
+	* gdb.base/info_qt.exp: New file.
+
 2018-10-26  Pedro Franco de Carvalho  <pedromfc@linux.ibm.com>
 
 	* gdb.arch/powerpc-htm-regs.c: New file.
diff --git a/gdb/testsuite/gdb.base/info_qt.c b/gdb/testsuite/gdb.base/info_qt.c
new file mode 100644
index 0000000000..479557124f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/info_qt.c
@@ -0,0 +1,78 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2018 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+typedef int entier;
+
+int info_qt_inc = 0;
+entier info_qt_ent = 0;
+
+static void
+setup_done (void)
+{
+}
+
+static void
+setup (char arg_c, int arg_i, int arg_j)
+{
+  char loc_arg_c = arg_c;
+  int loc_arg_i = arg_i;
+  int loc_arg_j = arg_j;
+
+  info_qt_inc += loc_arg_c + loc_arg_i + loc_arg_j;
+  setup_done ();
+}
+
+void info_fun1 (void)
+{
+  info_qt_inc++;
+  info_qt_ent++;
+}
+
+int info_fun2 (char c)
+{
+  info_qt_inc += c;
+  return info_qt_inc;
+}
+
+int info_fun2bis (char c)
+{
+  info_qt_inc += c;
+  return info_qt_inc;
+}
+
+entier info_fun2xxx (char arg_c, int arg_i, int arg_j)
+{
+  info_qt_inc += arg_c + arg_i + arg_j;
+  return info_qt_inc;
+}
+
+entier info_fun2yyy (char arg_c, int arg_i, int arg_j)
+{
+  setup (arg_c, arg_i, arg_j);
+  info_qt_inc += arg_c + arg_i + arg_j;
+  return info_qt_inc;
+}
+
+int
+main (int argc, char **argv, char **envp)
+{
+  info_fun1 ();
+  (void) info_fun2 ('a');
+  (void) info_fun2bis ('b');
+  (void) info_fun2xxx ('c', 1, 2);
+  (void) info_fun2yyy ('d', 3, 4);
+}
diff --git a/gdb/testsuite/gdb.base/info_qt.exp b/gdb/testsuite/gdb.base/info_qt.exp
new file mode 100644
index 0000000000..ab0872973a
--- /dev/null
+++ b/gdb/testsuite/gdb.base/info_qt.exp
@@ -0,0 +1,243 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2018 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+# This test verifies the TYPEREGEXP and NAMEREGEXP matching logic
+# in the commands
+#   info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP].
+
+
+standard_testfile
+
+if { [prepare_for_testing "failed to prepare" ${testfile}] } {
+    return -1
+}
+
+clean_restart ${binfile}
+
+if ![runto setup_done] then {
+    fail "can't run to setup_done"
+    return 0
+}
+
+set any "\[^\r\n\]*"
+set ws "\[ \t\]\+"
+set number "\[0-9]\+"
+
+
+############# Test 'info functions'.
+
+with_test_prefix "info functions nameregexp" {
+    foreach cmd {
+	"info functions info_fun"
+	"info functions -- info_fun"
+	"info functions ^info_fun" } {
+	    gdb_test $cmd \
+		[multi_line \
+		     "All functions matching regular expression \".*info_fun.*\":" \
+		     "" \
+		     "File .*info_qt.c:" \
+		     "${number}:	void info_fun1\\\(void\\\);" \
+		     "${number}:	int info_fun2\\\(char\\\);" \
+		     "${number}:	int info_fun2bis\\\(char\\\);" \
+		     "${number}:	entier info_fun2xxx\\\(char, int, int\\\);" \
+		     "${number}:	entier info_fun2yyy\\\(char, int, int\\\);" \
+		    ]
+    }
+}
+
+with_test_prefix "info functions nameregexp quiet" {
+    foreach cmd {
+	"info functions -q info_fun"
+	"info functions -q -- info_fun" } {
+	    gdb_test $cmd \
+		[multi_line \
+		     "" \
+		     "File .*info_qt.c:" \
+		     "${number}:	void info_fun1\\\(void\\\);" \
+		     "${number}:	int info_fun2\\\(char\\\);" \
+		     "${number}:	int info_fun2bis\\\(char\\\);" \
+		     "${number}:	entier info_fun2xxx\\\(char, int, int\\\);" \
+		     "${number}:	entier info_fun2yyy\\\(char, int, int\\\);" \
+		    ]
+	}
+}
+
+with_test_prefix "info functions nameregexp quiet no match" {
+    foreach cmd {
+	"info functions -q nowaythiscanmatch"
+	"info functions -q -- -q" } {
+	    gdb_test_no_output $cmd
+	}
+}
+
+with_test_prefix "info functions typeregexp nameregexp" {
+    foreach cmd {
+	"info functions -t entier -q info_fun"
+	"info functions -q -t 'entier (' -- info_fun"
+	"info functions -q -t '(char, int, int)' -- info_fun"
+	"info functions -q -t 'entier (char, int, int)' -- info_fun" } {
+	    gdb_test $cmd \
+		[multi_line \
+		     "" \
+		     "File .*info_qt.c:" \
+		     "${number}:	entier info_fun2xxx\\\(char, int, int\\\);" \
+		     "${number}:	entier info_fun2yyy\\\(char, int, int\\\);" \
+		    ]
+	}
+}
+
+with_test_prefix "info functions typeregexp nameregexp no match" {
+    gdb_test_no_output "info functions -t ganze_Zahl -q info_fun" \
+	"quiet output info functions no matching type"
+}
+
+############# Test 'info variables'.
+
+with_test_prefix "info variables nameregexp" {
+    foreach cmd {
+	"info variables info_qt"
+	"info variables -- info_qt"
+	"info variables ^info_qt" } {
+	    gdb_test $cmd \
+		[multi_line \
+		     "All variables matching regular expression \".*info_qt.*\":" \
+		     "" \
+		     "File .*info_qt.c:" \
+		     "${number}:	entier info_qt_ent;" \
+		     "${number}:	int info_qt_inc;" \
+		    ]
+	}
+}
+
+with_test_prefix "info variables nameregexp quiet no match" {
+    foreach cmd {
+	"info variables -q nowaythiscanmatch"
+	"info variables -q -- -q" } {
+	    gdb_test_no_output $cmd
+	}
+}
+
+with_test_prefix "info variables typeregexp nameregexp quiet" {
+    foreach cmd {
+	"info variables -t entier -q info_qt"
+	"info variables -q -t entier -- info_qt" } {
+	    gdb_test $cmd \
+		[multi_line \
+		     "" \
+		     "File .*info_qt.c:" \
+		     "${number}:	entier info_qt_ent;" \
+		    ]
+	}
+}
+
+with_test_prefix "info variables typeregexp nameregexp quiet no match" {
+    gdb_test_no_output "info variables -t ganze_Zahl -q info_at" \
+	"quiet output info variables no matching type"
+}
+
+
+
+############# Test 'info args' in function setup.
+
+gdb_test "frame 1" ".* in setup .*" "set frame 1 for info args"
+
+with_test_prefix "info args matching all args" {
+    foreach cmd {
+	"info args"
+	"info args arg_"
+	"info args g"
+	"info args -- .*" } {
+	    gdb_test $cmd \
+		[multi_line \
+		     "arg_c = 100 'd'" \
+		     "arg_i = 3" \
+		     "arg_j = 4" \
+		    ]
+	}
+}
+
+with_test_prefix "info args matching some args" {
+    foreach cmd {
+	"info args -t int"
+	"info args arg_[ij]"} {
+	    gdb_test $cmd \
+		[multi_line \
+		     "arg_i = 3" \
+		     "arg_j = 4" \
+		    ]
+	}
+}
+
+with_test_prefix "info args no match" {
+    gdb_test "info args nowaythiscanmatch" "No matching arguments." "no matching args"
+    gdb_test_no_output "info args -q nowaythiscanmatch" "quiet no matching args"
+    gdb_test_no_output "info args -q -t entier" "quiet no matching args with type"
+}
+
+############# Test 'info locals' in function setup.
+
+gdb_test "frame 1" ".* in setup .*" "set frame 1 for info locals"
+
+with_test_prefix "info locals matching all locals" {
+    foreach cmd {
+	"info locals"
+	"info locals loc_arg_"
+	"info locals g"
+	"info locals -- .*" } {
+	    gdb_test $cmd \
+		[multi_line \
+		     "loc_arg_c = 100 'd'" \
+		     "loc_arg_i = 3" \
+		     "loc_arg_j = 4" \
+		    ]
+	}
+}
+
+with_test_prefix "info locals matching some locals" {
+    foreach cmd {
+	"info locals -t int"
+	"info locals arg_[ij]"
+	"info locals loc_arg_[ij]"} {
+	    gdb_test $cmd \
+		[multi_line \
+		     "loc_arg_i = 3" \
+		     "loc_arg_j = 4" \
+		    ]
+	}
+}
+
+with_test_prefix "info locals no match" {
+    gdb_test "info locals nowaythiscanmatch" "No matching locals." "no matching locals"
+    gdb_test_no_output "info locals -q nowaythiscanmatch" "quiet no matching locals"
+    gdb_test_no_output "info locals -q -t ganze_Zahl loc" "quiet no matching locals with type"
+}
+
+# Verify that the rest of the args is taken as a single regexp.
+with_test_prefix "rest of args as single regexp" {
+    gdb_test "info functions abc def" \
+	"All functions matching regular expression \\\"abc def\\\":" \
+	"single regexp"
+
+    gdb_test "info functions -t uvw abc def" \
+	"All functions matching regular expression \\\"abc def\\\" with type matching regulation expression \\\"uvw\\\":" \
+	"-t noquote single regexp"
+
+    gdb_test "info functions -t 'uvw xyz' abc def" \
+	"All functions matching regular expression \\\"abc def\\\" with type matching regulation expression \\\"uvw xyz\\\":" \
+	"-t quote single regexp"
+}
-- 
2.19.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PUSHED 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP]
@ 2018-10-27 12:44 Philippe Waroquiers
  2018-10-27 12:44 ` [PUSHED 4/5] Announce changes in NEWS to info [args|functions|locals|variables] Philippe Waroquiers
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Philippe Waroquiers @ 2018-10-27 12:44 UTC (permalink / raw)
  To: gdb-patches

Many thanks to Eli, Pedro and Tom for the several reviews.

Philippe


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PUSHED 4/5] Announce changes in NEWS to info [args|functions|locals|variables]
  2018-10-27 12:44 [PUSHED 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers
@ 2018-10-27 12:44 ` Philippe Waroquiers
  2018-10-27 12:44 ` [PUSHED 1/5] New cli-utils.h/.c function extract_info_print_args Philippe Waroquiers
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Philippe Waroquiers @ 2018-10-27 12:44 UTC (permalink / raw)
  To: gdb-patches; +Cc: Philippe Waroquiers

Announce changes in NEWS to info [args|functions|locals|variables]

gdb/ChangeLog
2018-10-27  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* NEWS: Mention changes to 'info [args|functions|locals|variables]'
---
 gdb/ChangeLog | 4 ++++
 gdb/NEWS      | 9 +++++++++
 2 files changed, 13 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d105e74dc5..e9491358fa 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,7 @@
+2018-10-27  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
+
+	* NEWS: Mention changes to 'info [args|functions|locals|variables]'
+
 2018-10-27  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
 
 	* stack.c (print_variable_and_value_data): Add preg and treg.
diff --git a/gdb/NEWS b/gdb/NEWS
index 6b00cd8f9f..7fe588dabb 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -86,6 +86,15 @@ target extended-remote FILENAME
   If FILENAME is a Unix domain socket, GDB will attempt to connect
   to this socket instead of opening FILENAME as a character device.
 
+info args [-q] [-t TYPEREGEXP] [NAMEREGEXP]
+info functions [-q] [-t TYPEREGEXP] [NAMEREGEXP]
+info locals [-q] [-t TYPEREGEXP] [NAMEREGEXP]
+info variables [-q] [-t TYPEREGEXP] [NAMEREGEXP]
+  These commands can now print only the searched entities
+  matching the provided regexp(s), giving a condition
+  on the entity names or entity types.  The flag -q disables
+  printing headers or informations messages.
+
 thread apply [all | COUNT | -COUNT] [FLAG]... COMMAND
   The 'thread apply' command accepts new FLAG arguments.
   FLAG arguments allow to control what output to produce and how to handle
-- 
2.19.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PUSHED 1/5] New cli-utils.h/.c function extract_info_print_args
  2018-10-27 12:44 [PUSHED 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers
  2018-10-27 12:44 ` [PUSHED 4/5] Announce changes in NEWS to info [args|functions|locals|variables] Philippe Waroquiers
@ 2018-10-27 12:44 ` Philippe Waroquiers
  2018-10-27 12:44 ` [PUSHED 2/5] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables] Philippe Waroquiers
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Philippe Waroquiers @ 2018-10-27 12:44 UTC (permalink / raw)
  To: gdb-patches; +Cc: Philippe Waroquiers

New cli-utils.h/.c function extract_info_print_args factorizes
the extraction of the args '[-q] [-t TYPEREGEXP] [NAMEREGEXP]'.
New cli-utils.h/.c function report_unrecognized_option_error
factorizes reporting an unknown option for a command.

These functions will be used by the commands
  info [args|functions|locals|variables]

As extract_info_print_args will be used for 'info functions|variables' which
already have the NAMEREGEXP arg, it provides a backward compatible
behaviour.

cli-utils.c has a new static function extract_arg_maybe_quoted
that extracts an argument, possibly quoted.  The behaviour of this
function is similar to the parsing done by gdb_argv.

gdb/ChangeLog
2018-10-27  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* cli-utils.c (extract_arg_maybe_quoted): New function.
	(extract_info_print_args): New function.
	(info_print_args_help): New function.
	(report_unrecognized_option_error): New function.
	* cli-utils.h (extract_arg_maybe_quoted): New function.
	(extract_info_print_args): New function.
	(info_print_args_help): New function.
	(report_unrecognized_option_error): New function.
---
 gdb/ChangeLog       |  11 ++++
 gdb/cli/cli-utils.c | 129 ++++++++++++++++++++++++++++++++++++++++++++
 gdb/cli/cli-utils.h |  30 +++++++++++
 3 files changed, 170 insertions(+)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1f8e958c9a..ea033a798f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,14 @@
+2018-10-27  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
+
+	* cli-utils.c (extract_arg_maybe_quoted): New function.
+	(extract_info_print_args): New function.
+	(info_print_args_help): New function.
+	(report_unrecognized_option_error): New function.
+	* cli-utils.h (extract_arg_maybe_quoted): New function.
+	(extract_info_print_args): New function.
+	(info_print_args_help): New function.
+	(report_unrecognized_option_error): New function.
+
 2018-10-26  Tom Tromey  <tom@tromey.com>
 
 	* dwarf2read.c (recursively_compute_inclusions): Use std::vector.
diff --git a/gdb/cli/cli-utils.c b/gdb/cli/cli-utils.c
index 30ee4450f9..73315996ad 100644
--- a/gdb/cli/cli-utils.c
+++ b/gdb/cli/cli-utils.c
@@ -23,6 +23,8 @@
 
 #include <ctype.h>
 
+static std::string extract_arg_maybe_quoted (const char **arg);
+
 /* See documentation in cli-utils.h.  */
 
 int
@@ -128,6 +130,70 @@ get_number (char **pp)
 
 /* See documentation in cli-utils.h.  */
 
+bool
+extract_info_print_args (const char **args,
+			 bool *quiet,
+			 std::string *regexp,
+			 std::string *t_regexp)
+{
+  /* Check for NAMEREGEXP or -- NAMEREGEXP.  */
+  if (**args != '-' || check_for_argument (args, "--", 2))
+    {
+      *args = skip_spaces (*args);
+      *regexp = *args;
+      *args = NULL;
+      return true;
+    }
+
+  if (check_for_argument (args, "-t", 2))
+    {
+      *t_regexp = extract_arg_maybe_quoted (args);
+      *args = skip_spaces (*args);
+      return true;
+    }
+
+  if (check_for_argument (args, "-q", 2))
+    {
+      *quiet = true;
+      *args = skip_spaces (*args);
+      return true;
+    }
+
+  return false;
+}
+
+/* See documentation in cli-utils.h.  */
+
+void
+report_unrecognized_option_error (const char *command, const char *args)
+{
+  std::string option = extract_arg (&args);
+
+  error (_("Unrecognized option '%s' to %s command.  "
+	   "Try \"help %s\"."), option.c_str (),
+	 command, command);
+}
+
+/* See documentation in cli-utils.h.  */
+
+const char *
+info_print_args_help (const char *prefix,
+		      const char *entity_kind)
+{
+  return xstrprintf (_("\
+%sIf NAMEREGEXP is provided, only prints the %s whose name\n\
+matches NAMEREGEXP.\n\
+If -t TYPEREGEXP is provided, only prints the %s whose type\n\
+matches TYPEREGEXP.  Note that the matching is done with the type\n\
+printed by the 'whatis' command.\n\
+By default, the command might produce headers and/or messages indicating\n\
+why no %s can be printed.\n\
+The flag -q disables the production of these headers and messages."),
+		     prefix, entity_kind, entity_kind, entity_kind);
+}
+
+/* See documentation in cli-utils.h.  */
+
 number_or_range_parser::number_or_range_parser (const char *string)
 {
   init (string);
@@ -283,6 +349,69 @@ remove_trailing_whitespace (const char *start, const char *s)
   return s;
 }
 
+/* A helper function to extract an argument from *ARG.  An argument is
+   delimited by whitespace, but it can also be optionally quoted.
+   The quoting and special characters are handled similarly to
+   the parsing done by gdb_argv.
+   The return value is empty if no argument was found.  */
+
+static std::string
+extract_arg_maybe_quoted (const char **arg)
+{
+  bool squote = false;
+  bool dquote = false;
+  bool bsquote = false;
+  std::string result;
+  const char *p = *arg;
+
+  /* Find the start of the argument.  */
+  p = skip_spaces (p);
+
+  /* Parse p similarly to gdb_argv buildargv function.  */
+  while (*p != '\0')
+    {
+      if (isspace (*p) && !squote && !dquote && !bsquote)
+	  break;
+      else
+	{
+	  if (bsquote)
+	    {
+	      bsquote = false;
+	      result += *p;
+	    }
+	  else if (*p == '\\')
+	      bsquote = true;
+	  else if (squote)
+	    {
+	      if (*p == '\'')
+		  squote = false;
+	      else
+		  result += *p;
+	    }
+	  else if (dquote)
+	    {
+	      if (*p == '"')
+		  dquote = false;
+	      else
+		  result += *p;
+	    }
+	  else
+	    {
+	      if (*p == '\'')
+		  squote = true;
+	      else if (*p == '"')
+		  dquote = true;
+	      else
+		  result += *p;
+	    }
+	  p++;
+	}
+    }
+
+  *arg = p;
+  return result;
+}
+
 /* See documentation in cli-utils.h.  */
 
 std::string
diff --git a/gdb/cli/cli-utils.h b/gdb/cli/cli-utils.h
index fa7d02d719..f591ba14d6 100644
--- a/gdb/cli/cli-utils.h
+++ b/gdb/cli/cli-utils.h
@@ -39,6 +39,36 @@ extern int get_number (const char **);
 
 extern int get_number (char **);
 
+/* Extract from ARGS the arguments [-q] [-t TYPEREGEXP] [--] NAMEREGEXP.
+
+   The caller is responsible to initialize *QUIET to false, *REGEXP
+   and *T_REGEXP to "".
+   extract_info_print_args can then be called iteratively to search
+   for valid arguments, as part of a 'main parsing loop' searching for
+   -q/-t/-- arguments together with other flags and options.
+
+   Returns true and updates *ARGS + one of *QUIET, *REGEXP, *T_REGEXP if
+   it finds a valid argument.
+   Returns false if no valid argument is found at the beginning of ARGS.  */
+
+extern bool extract_info_print_args (const char **args,
+				     bool *quiet,
+				     std::string *regexp,
+				     std::string *t_regexp);
+
+/* Throws an error telling the user that ARGS starts with an option
+   unrecognized by COMMAND.  */
+
+extern void report_unrecognized_option_error (const char *command,
+					      const char *args);
+
+
+/* Builds the help string for a command documented by PREFIX,
+   followed by the extract_info_print_args help for ENTITY_KIND.  */
+
+const char *info_print_args_help (const char *prefix,
+				  const char *entity_kind);
+
 /* Parse a number or a range.
    A number will be of the form handled by get_number.
    A range will be of the form <number1> - <number2>, and
-- 
2.19.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PUSHED 3/5] Document changes to info [args|functions|locals|variables]
  2018-10-27 12:44 [PUSHED 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers
                   ` (2 preceding siblings ...)
  2018-10-27 12:44 ` [PUSHED 2/5] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables] Philippe Waroquiers
@ 2018-10-27 12:44 ` Philippe Waroquiers
  2018-10-27 12:44 ` [PUSHED 5/5] Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers
  4 siblings, 0 replies; 8+ messages in thread
From: Philippe Waroquiers @ 2018-10-27 12:44 UTC (permalink / raw)
  To: gdb-patches; +Cc: Philippe Waroquiers

Document changes to info [args|functions|locals|variables]

gdb/doc/ChangeLog
2018-10-27  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.texinfo (Information About a Frame): Document changes
	to 'info args' and 'info locals'.
	(Examining the Symbol Table): Document changes to 'info functions'
	and 'info variables'.
---
 gdb/doc/ChangeLog   |   7 +++
 gdb/doc/gdb.texinfo | 125 +++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 120 insertions(+), 12 deletions(-)

diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index abcdbda5d4..8804e81ffa 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,10 @@
+2018-10-27  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
+
+	* gdb.texinfo (Information About a Frame): Document changes
+	to 'info args' and 'info locals'.
+	(Examining the Symbol Table): Document changes to 'info functions'
+	and 'info variables'.
+
 2018-10-26  Pedro Franco de Carvalho  <pedromfc@linux.ibm.com>
 
 	* gdb.texinfo (PowerPC Features): Describe new features
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index c49a7745f8..8c1e618973 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -7830,15 +7830,75 @@ same as for the @command{frame} command (@pxref{Selection, ,Selecting
 a Frame}).  The selected frame remains unchanged by this command.
 
 @kindex info args
-@item info args
+@item info args [-q]
 Print the arguments of the selected frame, each on a separate line.
 
-@item info locals
+The optional flag @samp{-q}, which stands for @samp{quiet}, disables
+printing header information and messages explaining why no argument
+have been printed.
+
+@item info args [-q] [-t @var{type_regexp}] [@var{regexp}]
+Like @kbd{info args}, but only print the arguments selected
+with the provided regexp(s).
+
+If @var{regexp} is provided, print only the arguments whose names
+match the regular expression @var{regexp}.
+
+If @var{type_regexp} is provided, print only the arguments whose
+types, as printed by the @code{whatis} command, match
+the regular expression @var{type_regexp}.
+If @var{type_regexp} contains space(s), it should be enclosed in
+quote characters.  If needed, use backslash to escape the meaning
+of special characters or quotes.
+
+If both @var{regexp} and @var{type_regexp} are provided, an argument
+is printed only if its name matches @var{regexp} and its type matches
+@var{type_regexp}.
+
+@item info locals [-q]
 @kindex info locals
 Print the local variables of the selected frame, each on a separate
 line.  These are all variables (declared either static or automatic)
 accessible at the point of execution of the selected frame.
 
+The optional flag @samp{-q}, which stands for @samp{quiet}, disables
+printing header information and messages explaining why no local variables
+have been printed.
+
+@item info locals [-q] [-t @var{type_regexp}] [@var{regexp}]
+Like @kbd{info locals}, but only print the local variables selected
+with the provided regexp(s).
+
+If @var{regexp} is provided, print only the local variables whose names
+match the regular expression @var{regexp}.
+
+If @var{type_regexp} is provided, print only the local variables whose
+types, as printed by the @code{whatis} command, match
+the regular expression @var{type_regexp}.
+If @var{type_regexp} contains space(s), it should be enclosed in
+quote characters.  If needed, use backslash to escape the meaning
+of special characters or quotes.
+
+If both @var{regexp} and @var{type_regexp} are provided, a local variable
+is printed only if its name matches @var{regexp} and its type matches
+@var{type_regexp}.
+
+The command @kbd{info locals -q -t @var{type_regexp}} can usefully be
+combined with the commands @kbd{frame apply} and @kbd{thread apply}.
+For example, your program might use Resource Acquisition Is
+Initialization types (RAII) such as @code{lock_something_t}: each
+local variable of type @code{lock_something_t} automatically places a
+lock that is destroyed when the variable goes out of scope.  You can
+then list all acquired locks in your program by doing
+@smallexample
+thread apply all -s frame apply all -s info locals -q -t lock_something_t
+@end smallexample
+@noindent
+or the equivalent shorter form
+@smallexample
+tfaas i lo -q -t lock_something_t
+@end smallexample
+
 @end table
 
 @node Frame Apply
@@ -17920,32 +17980,73 @@ debugging information, organized into two lists: files whose symbols
 have already been read, and files whose symbols will be read when needed.
 
 @kindex info functions
-@item info functions
+@item info functions [-q]
 Print the names and data types of all defined functions.
 Similarly to @samp{info types}, this command groups its output by source
 files and annotates each function definition with its source line
 number.
 
-@item info functions @var{regexp}
-Like @samp{info functions}, but only print the names and data types of
-functions whose names contain a match for regular expression
-@var{regexp}.  Thus, @samp{info fun step} finds all functions whose
+The optional flag @samp{-q}, which stands for @samp{quiet}, disables
+printing header information and messages explaining why no functions
+have been printed.
+
+@item info functions [-q] [-t @var{type_regexp}] [@var{regexp}]
+Like @samp{info functions}, but only print the names and data types
+of the functions selected with the provided regexp(s).
+
+If @var{regexp} is provided, print only the functions whose names
+match the regular expression @var{regexp}.
+Thus, @samp{info fun step} finds all functions whose
 names include @code{step}; @samp{info fun ^step} finds those whose names
 start with @code{step}.  If a function name contains characters that
 conflict with the regular expression language (e.g.@:
 @samp{operator*()}), they may be quoted with a backslash.
 
+If @var{type_regexp} is provided, print only the functions whose
+types, as printed by the @code{whatis} command, match
+the regular expression @var{type_regexp}.
+If @var{type_regexp} contains space(s), it should be enclosed in
+quote characters.  If needed, use backslash to escape the meaning
+of special characters or quotes.
+Thus, @samp{info fun -t '^int ('} finds the functions that return
+an integer; @samp{info fun -t '(.*int.*'} finds the functions that
+have an argument type containing int; @samp{info fun -t '^int (' ^step}
+finds the functions whose names start with @code{step} and that return
+int.
+
+If both @var{regexp} and @var{type_regexp} are provided, a function
+is printed only if its name matches @var{regexp} and its type matches
+@var{type_regexp}.
+
+
 @kindex info variables
-@item info variables
+@item info variables [-q]
 Print the names and data types of all variables that are defined
 outside of functions (i.e.@: excluding local variables).
 The printed variables are grouped by source files and annotated with
 their respective source line numbers.
 
-@item info variables @var{regexp}
-Like @kbd{info variables}, but only print the names and data types of
-non-local variables whose names contain a match for regular expression
-@var{regexp}.
+The optional flag @samp{-q}, which stands for @samp{quiet}, disables
+printing header information and messages explaining why no variables
+have been printed.
+
+@item info variables [-q] [-t @var{type_regexp}] [@var{regexp}]
+Like @kbd{info variables}, but only print the variables selected
+with the provided regexp(s).
+
+If @var{regexp} is provided, print only the variables whose names
+match the regular expression @var{regexp}.
+
+If @var{type_regexp} is provided, print only the variables whose
+types, as printed by the @code{whatis} command, match
+the regular expression @var{type_regexp}.
+If @var{type_regexp} contains space(s), it should be enclosed in
+quote characters.  If needed, use backslash to escape the meaning
+of special characters or quotes.
+
+If both @var{regexp} and @var{type_regexp} are provided, an argument
+is printed only if its name matches @var{regexp} and its type matches
+@var{type_regexp}.
 
 @kindex info classes
 @cindex Objective-C, classes and selectors
-- 
2.19.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PUSHED 2/5] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables]
  2018-10-27 12:44 [PUSHED 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers
  2018-10-27 12:44 ` [PUSHED 4/5] Announce changes in NEWS to info [args|functions|locals|variables] Philippe Waroquiers
  2018-10-27 12:44 ` [PUSHED 1/5] New cli-utils.h/.c function extract_info_print_args Philippe Waroquiers
@ 2018-10-27 12:44 ` Philippe Waroquiers
  2018-10-30 14:59   ` Tom de Vries
  2018-10-27 12:44 ` [PUSHED 3/5] Document changes " Philippe Waroquiers
  2018-10-27 12:44 ` [PUSHED 5/5] Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers
  4 siblings, 1 reply; 8+ messages in thread
From: Philippe Waroquiers @ 2018-10-27 12:44 UTC (permalink / raw)
  To: gdb-patches; +Cc: Philippe Waroquiers

Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables]

Main changes are:
* stack.c: Add two regexp preg and treg to print_variable_and_value_data
  and used them inside do_print_variable_and_value to filter the
  variables to print.

* symtab.h: Add a new function bool treg_matches_sym_type_name, that
  factorises type matching logic.

* symtab.c: Add type/name matching logic to 'info functions|variables'.

* stack.c : Add type/name matching logic to 'info args|locals'.

gdb/ChangeLog
2018-10-27  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* stack.c (print_variable_and_value_data): Add preg and treg.
	(print_frame_local_vars): Add quiet, regexp and t_regexp arguments,
	and update callers.
	(print_frame_arg_vars): Likewise.
	(prepare_reg): New function.
	(info_locals_command): Extract info print args and use them.
	(info_args_command): Likewise.
	(_initialize_stack): Modify on-line help.
	* symtab.c (treg_matches_sym_type_name): New function.
	(search_symbols): New arg t_regexp.
	(symtab_symbol_info): New args quiet, regexp, t_regexp.
	(info_variables_command): Extract info print args and use them.
	(info_functions_command): Likewise.
	(info_types_command): Update call to symtab_symbol_info.
	(_initialize_symtab): Modify on-line help.
	* symtab.h (treg_matches_sym_type_name): New function.
	(search_symbols): New t_regexp arg.
---
 gdb/ChangeLog       |  20 +++++
 gdb/python/python.c |   4 +-
 gdb/stack.c         | 139 +++++++++++++++++++++++++++-----
 gdb/symtab.c        | 191 +++++++++++++++++++++++++++++++++++++-------
 gdb/symtab.h        |   7 +-
 5 files changed, 312 insertions(+), 49 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ea033a798f..d105e74dc5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,23 @@
+2018-10-27  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
+
+	* stack.c (print_variable_and_value_data): Add preg and treg.
+	(print_frame_local_vars): Add quiet, regexp and t_regexp arguments,
+	and update callers.
+	(print_frame_arg_vars): Likewise.
+	(prepare_reg): New function.
+	(info_locals_command): Extract info print args and use them.
+	(info_args_command): Likewise.
+	(_initialize_stack): Modify on-line help.
+	* symtab.c (treg_matches_sym_type_name): New function.
+	(search_symbols): New arg t_regexp.
+	(symtab_symbol_info): New args quiet, regexp, t_regexp.
+	(info_variables_command): Extract info print args and use them.
+	(info_functions_command): Likewise.
+	(info_types_command): Update call to symtab_symbol_info.
+	(_initialize_symtab): Modify on-line help.
+	* symtab.h (treg_matches_sym_type_name): New function.
+	(search_symbols): New t_regexp arg.
+
 2018-10-27  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
 
 	* cli-utils.c (extract_arg_maybe_quoted): New function.
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 8fbce78469..348405e205 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -743,11 +743,11 @@ gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw)
     {
       const char **files = symtab_paths.vec.data ();
 
-      symbols = search_symbols (regex, FUNCTIONS_DOMAIN,
+      symbols = search_symbols (regex, FUNCTIONS_DOMAIN, NULL,
 				symtab_paths.vec.size (), files);
     }
   else
-    symbols = search_symbols (regex, FUNCTIONS_DOMAIN, 0, NULL);
+    symbols = search_symbols (regex, FUNCTIONS_DOMAIN, NULL, 0, NULL);
 
   /* Count the number of symbols (both symbols and optionally minimal
      symbols) so we can correctly check the throttle limit.  */
diff --git a/gdb/stack.c b/gdb/stack.c
index 87b493f790..abbaf5d4a7 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -88,8 +88,10 @@ const char *print_entry_values = print_entry_values_default;
 
 /* Prototypes for local functions.  */
 
-static void print_frame_local_vars (struct frame_info *, int,
-				    struct ui_file *);
+static void print_frame_local_vars (struct frame_info *frame,
+				    bool quiet,
+				    const char *regexp, const char *t_regexp,
+				    int num_tabs, struct ui_file *stream);
 
 static void print_frame (struct frame_info *frame, int print_level,
 			 enum print_what print_what,  int print_args,
@@ -1878,7 +1880,7 @@ backtrace_command_1 (const char *count_exp, frame_filter_flags flags,
 	    {
 	      struct frame_id frame_id = get_frame_id (fi);
 
-	      print_frame_local_vars (fi, 1, gdb_stdout);
+	      print_frame_local_vars (fi, false, NULL, NULL, 1, gdb_stdout);
 
 	      /* print_frame_local_vars invalidates FI.  */
 	      fi = frame_find_by_id (frame_id);
@@ -2060,6 +2062,8 @@ iterate_over_block_local_vars (const struct block *block,
 
 struct print_variable_and_value_data
 {
+  gdb::optional<compiled_regex> preg;
+  gdb::optional<compiled_regex> treg;
   struct frame_id frame_id;
   int num_tabs;
   struct ui_file *stream;
@@ -2077,6 +2081,14 @@ do_print_variable_and_value (const char *print_name,
     = (struct print_variable_and_value_data *) cb_data;
   struct frame_info *frame;
 
+  if (p->preg.has_value ()
+      && p->preg->exec (SYMBOL_NATURAL_NAME (sym), 0,
+			NULL, 0) != 0)
+    return;
+  if (p->treg.has_value ()
+      && !treg_matches_sym_type_name (*p->treg, sym))
+    return;
+
   frame = frame_find_by_id (p->frame_id);
   if (frame == NULL)
     {
@@ -2092,14 +2104,38 @@ do_print_variable_and_value (const char *print_name,
   p->values_printed = 1;
 }
 
+/* Prepares the regular expression REG from REGEXP.
+   If REGEXP is NULL, it results in an empty regular expression.  */
+
+static void
+prepare_reg (const char *regexp, gdb::optional<compiled_regex> *reg)
+{
+  if (regexp != NULL)
+    {
+      int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off
+				? REG_ICASE : 0);
+      reg->emplace (regexp, cflags, _("Invalid regexp"));
+    }
+  else
+    reg->reset ();
+}
+
 /* Print all variables from the innermost up to the function block of FRAME.
    Print them with values to STREAM indented by NUM_TABS.
+   If REGEXP is not NULL, only print local variables whose name
+   matches REGEXP.
+   If T_REGEXP is not NULL, only print local variables whose type
+   matches T_REGEXP.
+   If no local variables have been printed and !QUIET, prints a message
+   explaining why no local variables could be printed.
 
    This function will invalidate FRAME.  */
 
 static void
-print_frame_local_vars (struct frame_info *frame, int num_tabs,
-			struct ui_file *stream)
+print_frame_local_vars (struct frame_info *frame,
+			bool quiet,
+			const char *regexp, const char *t_regexp,
+			int num_tabs, struct ui_file *stream)
 {
   struct print_variable_and_value_data cb_data;
   const struct block *block;
@@ -2107,18 +2143,22 @@ print_frame_local_vars (struct frame_info *frame, int num_tabs,
 
   if (!get_frame_pc_if_available (frame, &pc))
     {
-      fprintf_filtered (stream,
-			_("PC unavailable, cannot determine locals.\n"));
+      if (!quiet)
+	fprintf_filtered (stream,
+			  _("PC unavailable, cannot determine locals.\n"));
       return;
     }
 
   block = get_frame_block (frame, 0);
   if (block == 0)
     {
-      fprintf_filtered (stream, "No symbol table info available.\n");
+      if (!quiet)
+	fprintf_filtered (stream, "No symbol table info available.\n");
       return;
     }
 
+  prepare_reg (regexp, &cb_data.preg);
+  prepare_reg (t_regexp, &cb_data.treg);
   cb_data.frame_id = get_frame_id (frame);
   cb_data.num_tabs = 4 * num_tabs;
   cb_data.stream = stream;
@@ -2134,14 +2174,33 @@ print_frame_local_vars (struct frame_info *frame, int num_tabs,
 				 do_print_variable_and_value,
 				 &cb_data);
 
-  if (!cb_data.values_printed)
-    fprintf_filtered (stream, _("No locals.\n"));
+  if (!cb_data.values_printed && !quiet)
+    {
+      if (regexp == NULL && t_regexp == NULL)
+	fprintf_filtered (stream, _("No locals.\n"));
+      else
+	fprintf_filtered (stream, _("No matching locals.\n"));
+    }
 }
 
 void
 info_locals_command (const char *args, int from_tty)
 {
+  std::string regexp;
+  std::string t_regexp;
+  bool quiet = false;
+
+  while (args != NULL
+	 && extract_info_print_args (&args, &quiet, &regexp, &t_regexp))
+    ;
+
+  if (args != NULL)
+    report_unrecognized_option_error ("info locals", args);
+
   print_frame_local_vars (get_selected_frame (_("No frame selected.")),
+			  quiet,
+			  regexp.empty () ? NULL : regexp.c_str (),
+			  t_regexp.empty () ? NULL : t_regexp.c_str (),
 			  0, gdb_stdout);
 }
 
@@ -2180,29 +2239,45 @@ iterate_over_block_arg_vars (const struct block *b,
 
 /* Print all argument variables of the function of FRAME.
    Print them with values to STREAM.
+   If REGEXP is not NULL, only print argument variables whose name
+   matches REGEXP.
+   If T_REGEXP is not NULL, only print argument variables whose type
+   matches T_REGEXP.
+   If no argument variables have been printed and !QUIET, prints a message
+   explaining why no argument variables could be printed.
 
    This function will invalidate FRAME.  */
 
 static void
-print_frame_arg_vars (struct frame_info *frame, struct ui_file *stream)
+print_frame_arg_vars (struct frame_info *frame,
+		      bool quiet,
+		      const char *regexp, const char *t_regexp,
+		      struct ui_file *stream)
 {
   struct print_variable_and_value_data cb_data;
   struct symbol *func;
   CORE_ADDR pc;
+  gdb::optional<compiled_regex> preg;
+  gdb::optional<compiled_regex> treg;
 
   if (!get_frame_pc_if_available (frame, &pc))
     {
-      fprintf_filtered (stream, _("PC unavailable, cannot determine args.\n"));
+      if (!quiet)
+	fprintf_filtered (stream,
+			  _("PC unavailable, cannot determine args.\n"));
       return;
     }
 
   func = get_frame_function (frame);
   if (func == NULL)
     {
-      fprintf_filtered (stream, _("No symbol table info available.\n"));
+      if (!quiet)
+	fprintf_filtered (stream, _("No symbol table info available.\n"));
       return;
     }
 
+  prepare_reg (regexp, &cb_data.preg);
+  prepare_reg (t_regexp, &cb_data.treg);
   cb_data.frame_id = get_frame_id (frame);
   cb_data.num_tabs = 0;
   cb_data.stream = stream;
@@ -2214,14 +2289,34 @@ print_frame_arg_vars (struct frame_info *frame, struct ui_file *stream)
   /* do_print_variable_and_value invalidates FRAME.  */
   frame = NULL;
 
-  if (!cb_data.values_printed)
-    fprintf_filtered (stream, _("No arguments.\n"));
+  if (!cb_data.values_printed && !quiet)
+    {
+      if (regexp == NULL && t_regexp == NULL)
+	fprintf_filtered (stream, _("No arguments.\n"));
+      else
+	fprintf_filtered (stream, _("No matching arguments.\n"));
+    }
 }
 
 void
-info_args_command (const char *ignore, int from_tty)
+info_args_command (const char *args, int from_tty)
 {
+  std::string regexp;
+  std::string t_regexp;
+  bool quiet;
+
+  while (args != NULL
+	 && extract_info_print_args (&args, &quiet, &regexp, &t_regexp))
+    ;
+
+  if (args != NULL)
+    report_unrecognized_option_error ("info args", args);
+
+
   print_frame_arg_vars (get_selected_frame (_("No frame selected.")),
+			quiet,
+			regexp.empty () ? NULL : regexp.c_str (),
+			t_regexp.empty () ? NULL : t_regexp.c_str (),
 			gdb_stdout);
 }
 \f
@@ -2994,9 +3089,17 @@ Usage: info frame level LEVEL"),
 	   &info_frame_cmd_list);
 
   add_info ("locals", info_locals_command,
-	    _("Local variables of current stack frame."));
+	    info_print_args_help (_("\
+All local variables of current stack frame or those matching REGEXPs.\n\
+Usage: info locals [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
+Prints the local variables of the current stack frame.\n"),
+				  _("local variables")));
   add_info ("args", info_args_command,
-	    _("Argument variables of current stack frame."));
+	    info_print_args_help (_("\
+All argument variables of current stack frame or those matching REGEXPs.\n\
+Usage: info args [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
+Prints the argument variables of the current stack frame.\n"),
+				  _("argument variables")));
 
   if (dbx_commands)
     add_com ("func", class_stack, func_command, _("\
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 2e48d6527e..cd27a75e8c 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -43,6 +43,7 @@
 #include "cli/cli-utils.h"
 #include "fnmatch.h"
 #include "hashtab.h"
+#include "typeprint.h"
 
 #include "gdb_obstack.h"
 #include "block.h"
@@ -4266,6 +4267,52 @@ symbol_search::compare_search_syms (const symbol_search &sym_a,
 		 SYMBOL_PRINT_NAME (sym_b.symbol));
 }
 
+/* Returns true if the type_name of symbol_type of SYM matches TREG.
+   If SYM has no symbol_type or symbol_name, returns false.  */
+
+bool
+treg_matches_sym_type_name (const compiled_regex &treg,
+			    const struct symbol *sym)
+{
+  struct type *sym_type;
+  std::string printed_sym_type_name;
+
+  if (symbol_lookup_debug > 1)
+    {
+      fprintf_unfiltered (gdb_stdlog,
+			  "treg_matches_sym_type_name\n     sym %s\n",
+			  SYMBOL_NATURAL_NAME (sym));
+    }
+
+  sym_type = SYMBOL_TYPE (sym);
+  if (sym_type == NULL)
+    return false;
+
+  if (language_mode == language_mode_auto)
+    {
+      scoped_restore_current_language l;
+
+      set_language (SYMBOL_LANGUAGE (sym));
+      printed_sym_type_name = type_to_string (sym_type);
+    }
+  else
+    printed_sym_type_name = type_to_string (sym_type);
+
+  if (symbol_lookup_debug > 1)
+    {
+      fprintf_unfiltered (gdb_stdlog,
+			  "     sym_type_name %s\n",
+			  printed_sym_type_name.c_str ());
+    }
+
+
+  if (printed_sym_type_name.empty ())
+    return false;
+
+  return treg.exec (printed_sym_type_name.c_str (), 0, NULL, 0) == 0;
+}
+
+
 /* Sort the symbols in RESULT and remove duplicates.  */
 
 static void
@@ -4281,7 +4328,9 @@ sort_search_symbols_remove_dups (std::vector<symbol_search> *result)
 
    Only symbols of KIND are searched:
    VARIABLES_DOMAIN - search all symbols, excluding functions, type names,
-                      and constants (enums)
+                      and constants (enums).
+		      if T_REGEXP is not NULL, only returns var that have
+		      a type matching regular expression T_REGEXP.
    FUNCTIONS_DOMAIN - search all functions
    TYPES_DOMAIN     - search all type names
    ALL_DOMAIN       - an internal error for this function
@@ -4292,6 +4341,7 @@ sort_search_symbols_remove_dups (std::vector<symbol_search> *result)
 
 std::vector<symbol_search>
 search_symbols (const char *regexp, enum search_domain kind,
+		const char *t_regexp,
 		int nfiles, const char *files[])
 {
   struct compunit_symtab *cust;
@@ -4317,6 +4367,7 @@ search_symbols (const char *regexp, enum search_domain kind,
   enum minimal_symbol_type ourtype4;
   std::vector<symbol_search> result;
   gdb::optional<compiled_regex> preg;
+  gdb::optional<compiled_regex> treg;
 
   gdb_assert (kind <= TYPES_DOMAIN);
 
@@ -4366,6 +4417,13 @@ search_symbols (const char *regexp, enum search_domain kind,
       preg.emplace (regexp, cflags, _("Invalid regexp"));
     }
 
+  if (t_regexp != NULL)
+    {
+      int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off
+				? REG_ICASE : 0);
+      treg.emplace (t_regexp, cflags, _("Invalid regexp"));
+    }
+
   /* Search through the partial symtabs *first* for all symbols
      matching the regexp.  That way we don't have to reproduce all of
      the machinery below.  */
@@ -4377,8 +4435,9 @@ search_symbols (const char *regexp, enum search_domain kind,
 			   lookup_name_info::match_any (),
 			   [&] (const char *symname)
 			   {
-			     return (!preg || preg->exec (symname,
-							  0, NULL, 0) == 0);
+			     return (!preg.has_value ()
+				     || preg->exec (symname,
+						    0, NULL, 0) == 0);
 			   },
 			   NULL,
 			   kind);
@@ -4413,7 +4472,7 @@ search_symbols (const char *regexp, enum search_domain kind,
 	    || MSYMBOL_TYPE (msymbol) == ourtype3
 	    || MSYMBOL_TYPE (msymbol) == ourtype4)
 	  {
-	    if (!preg
+	    if (!preg.has_value ()
 		|| preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
 			       NULL, 0) == 0)
 	      {
@@ -4452,7 +4511,7 @@ search_symbols (const char *regexp, enum search_domain kind,
 				       files, nfiles, 1))
 		     && file_matches (symtab_to_fullname (real_symtab),
 				      files, nfiles, 0)))
-		&& ((!preg
+		&& ((!preg.has_value ()
 		     || preg->exec (SYMBOL_NATURAL_NAME (sym), 0,
 				    NULL, 0) == 0)
 		    && ((kind == VARIABLES_DOMAIN
@@ -4464,9 +4523,13 @@ search_symbols (const char *regexp, enum search_domain kind,
 			    We only want to skip enums here.  */
 			 && !(SYMBOL_CLASS (sym) == LOC_CONST
 			      && (TYPE_CODE (SYMBOL_TYPE (sym))
-				  == TYPE_CODE_ENUM)))
-			|| (kind == FUNCTIONS_DOMAIN 
-			    && SYMBOL_CLASS (sym) == LOC_BLOCK)
+				  == TYPE_CODE_ENUM))
+			 && (!treg.has_value ()
+			     || treg_matches_sym_type_name (*treg, sym)))
+			|| (kind == FUNCTIONS_DOMAIN
+			    && SYMBOL_CLASS (sym) == LOC_BLOCK
+			    && (!treg.has_value ()
+				|| treg_matches_sym_type_name (*treg, sym)))
 			|| (kind == TYPES_DOMAIN
 			    && SYMBOL_CLASS (sym) == LOC_TYPEDEF))))
 	      {
@@ -4497,8 +4560,13 @@ search_symbols (const char *regexp, enum search_domain kind,
 	    || MSYMBOL_TYPE (msymbol) == ourtype3
 	    || MSYMBOL_TYPE (msymbol) == ourtype4)
 	  {
-	    if (!preg || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
-				     NULL, 0) == 0)
+	    /* If the user wants to see var matching a type regexp,
+	       then never give a minimal symbol.  */
+	    if (kind != VARIABLES_DOMAIN
+		&& !treg.has_value () /* minimal symbol has never a type ???? */
+		&& (!preg.has_value ()
+		    || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
+				   NULL, 0) == 0))
 	      {
 		/* For functions we can do a quick check of whether the
 		   symbol might be found via find_pc_symtab.  */
@@ -4599,7 +4667,9 @@ print_msymbol_info (struct bound_minimal_symbol msymbol)
    matches.  */
 
 static void
-symtab_symbol_info (const char *regexp, enum search_domain kind, int from_tty)
+symtab_symbol_info (bool quiet,
+		    const char *regexp, enum search_domain kind,
+		    const char *t_regexp, int from_tty)
 {
   static const char * const classnames[] =
     {"variable", "function", "type"};
@@ -4609,13 +4679,33 @@ symtab_symbol_info (const char *regexp, enum search_domain kind, int from_tty)
   gdb_assert (kind <= TYPES_DOMAIN);
 
   /* Must make sure that if we're interrupted, symbols gets freed.  */
-  std::vector<symbol_search> symbols = search_symbols (regexp, kind, 0, NULL);
+  std::vector<symbol_search> symbols = search_symbols (regexp, kind,
+						       t_regexp, 0, NULL);
 
-  if (regexp != NULL)
-    printf_filtered (_("All %ss matching regular expression \"%s\":\n"),
-		     classnames[kind], regexp);
-  else
-    printf_filtered (_("All defined %ss:\n"), classnames[kind]);
+  if (!quiet)
+    {
+      if (regexp != NULL)
+	{
+	  if (t_regexp != NULL)
+	    printf_filtered
+	      (_("All %ss matching regular expression \"%s\""
+		 " with type matching regulation expression \"%s\":\n"),
+	       classnames[kind], regexp, t_regexp);
+	  else
+	    printf_filtered (_("All %ss matching regular expression \"%s\":\n"),
+			     classnames[kind], regexp);
+	}
+      else
+	{
+	  if (t_regexp != NULL)
+	    printf_filtered
+	      (_("All defined %ss"
+		 " with type matching regulation expression \"%s\" :\n"),
+	       classnames[kind], t_regexp);
+	  else
+	    printf_filtered (_("All defined %ss:\n"), classnames[kind]);
+	}
+    }
 
   for (const symbol_search &p : symbols)
     {
@@ -4625,7 +4715,8 @@ symtab_symbol_info (const char *regexp, enum search_domain kind, int from_tty)
 	{
 	  if (first)
 	    {
-	      printf_filtered (_("\nNon-debugging symbols:\n"));
+	      if (!quiet)
+		printf_filtered (_("\nNon-debugging symbols:\n"));
 	      first = 0;
 	    }
 	  print_msymbol_info (p.msymbol);
@@ -4643,22 +4734,53 @@ symtab_symbol_info (const char *regexp, enum search_domain kind, int from_tty)
 }
 
 static void
-info_variables_command (const char *regexp, int from_tty)
+info_variables_command (const char *args, int from_tty)
 {
-  symtab_symbol_info (regexp, VARIABLES_DOMAIN, from_tty);
+  std::string regexp;
+  std::string t_regexp;
+  bool quiet = false;
+
+  while (args != NULL
+	 && extract_info_print_args (&args, &quiet, &regexp, &t_regexp))
+    ;
+
+  if (args != NULL)
+    report_unrecognized_option_error ("info variables", args);
+
+  symtab_symbol_info (quiet,
+		      regexp.empty () ? NULL : regexp.c_str (),
+		      VARIABLES_DOMAIN,
+		      t_regexp.empty () ? NULL : t_regexp.c_str (),
+		      from_tty);
 }
 
+
 static void
-info_functions_command (const char *regexp, int from_tty)
+info_functions_command (const char *args, int from_tty)
 {
-  symtab_symbol_info (regexp, FUNCTIONS_DOMAIN, from_tty);
+  std::string regexp;
+  std::string t_regexp;
+  bool quiet;
+
+  while (args != NULL
+	 && extract_info_print_args (&args, &quiet, &regexp, &t_regexp))
+    ;
+
+  if (args != NULL)
+    report_unrecognized_option_error ("info functions", args);
+
+  symtab_symbol_info (quiet,
+		      regexp.empty () ? NULL : regexp.c_str (),
+		      FUNCTIONS_DOMAIN,
+		      t_regexp.empty () ? NULL : t_regexp.c_str (),
+		      from_tty);
 }
 
 
 static void
 info_types_command (const char *regexp, int from_tty)
 {
-  symtab_symbol_info (regexp, TYPES_DOMAIN, from_tty);
+  symtab_symbol_info (false, regexp, TYPES_DOMAIN, NULL, from_tty);
 }
 
 /* Breakpoint all functions matching regular expression.  */
@@ -4701,6 +4823,7 @@ rbreak_command (const char *regexp, int from_tty)
 
   std::vector<symbol_search> symbols = search_symbols (regexp,
 						       FUNCTIONS_DOMAIN,
+						       NULL,
 						       nfiles, files);
 
   scoped_rbreak_breakpoints finalize;
@@ -5902,14 +6025,26 @@ _initialize_symtab (void)
   symbol_cache_key
     = register_program_space_data_with_cleanup (NULL, symbol_cache_cleanup);
 
-  add_info ("variables", info_variables_command, _("\
-All global and static variable names, or those matching REGEXP."));
+  add_info ("variables", info_variables_command,
+	    info_print_args_help (_("\
+All global and static variable names or those matching REGEXPs.\n\
+Usage: info variables [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
+Prints the global and static variables.\n"),
+				  _("global and static variables")));
   if (dbx_commands)
-    add_com ("whereis", class_info, info_variables_command, _("\
-All global and static variable names, or those matching REGEXP."));
+    add_com ("whereis", class_info, info_variables_command,
+	     info_print_args_help (_("\
+All global and static variable names, or those matching REGEXPs.\n\
+Usage: whereis [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
+Prints the global and static variables.\n"),
+				   _("global and static variables")));
 
   add_info ("functions", info_functions_command,
-	    _("All function names, or those matching REGEXP."));
+	    info_print_args_help (_("\
+All function names or those matching REGEXPs.\n\
+Usage: info functions [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
+Prints the functions.\n"),
+				  _("functions")));
 
   /* FIXME:  This command has at least the following problems:
      1.  It prints builtin types (in a very strange and confusing fashion).
diff --git a/gdb/symtab.h b/gdb/symtab.h
index b91ec12b29..e0b870135b 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -25,6 +25,7 @@
 #include <string>
 #include "gdb_vecs.h"
 #include "gdbtypes.h"
+#include "gdb_regex.h"
 #include "common/enum-flags.h"
 #include "common/function-view.h"
 #include "common/gdb_optional.h"
@@ -2057,8 +2058,12 @@ private:
 };
 
 extern std::vector<symbol_search> search_symbols (const char *,
-						  enum search_domain, int,
+						  enum search_domain,
+						  const char *,
+						  int,
 						  const char **);
+extern bool treg_matches_sym_type_name (const compiled_regex &treg,
+					const struct symbol *sym);
 
 /* The name of the ``main'' function.
    FIXME: cagney/2001-03-20: Can't make main_name() const since some
-- 
2.19.1

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PUSHED 2/5] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables]
  2018-10-27 12:44 ` [PUSHED 2/5] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables] Philippe Waroquiers
@ 2018-10-30 14:59   ` Tom de Vries
  2018-10-30 21:27     ` Philippe Waroquiers
  0 siblings, 1 reply; 8+ messages in thread
From: Tom de Vries @ 2018-10-30 14:59 UTC (permalink / raw)
  To: Philippe Waroquiers, gdb-patches; +Cc: Pedro Alves

On 10/27/18 2:44 PM, Philippe Waroquiers wrote:
> @@ -4497,8 +4560,13 @@ search_symbols (const char *regexp, enum search_domain kind,
>  	    || MSYMBOL_TYPE (msymbol) == ourtype3
>  	    || MSYMBOL_TYPE (msymbol) == ourtype4)
>  	  {
> -	    if (!preg || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
> -				     NULL, 0) == 0)
> +	    /* If the user wants to see var matching a type regexp,
> +	       then never give a minimal symbol.  */
> +	    if (kind != VARIABLES_DOMAIN
> +		&& !treg.has_value () /* minimal symbol has never a type ???? */
> +		&& (!preg.has_value ()
> +		    || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
> +				   NULL, 0) == 0))
>  	      {
>  		/* For functions we can do a quick check of whether the
>  		   symbol might be found via find_pc_symtab.  */

Hi,

Consider this testcase with minimal symbols:
...
$ cat test.c
static int var;

int
main (void)
{
  return 0;
}
$ gcc test.c
$
...

After this commit, I don't see "var":
...
$ gdb -batch a.out -ex "info var"
All defined variables:

File init.c:
24:     const int _IO_stdin_used;
...

while before this commit, I do see "var":
...
$ gdb -batch a.out -ex "info variables"
All defined variables:

File init.c:
24:     const int _IO_stdin_used;

Non-debugging symbols:
0x0000000000400534  __GNU_EH_FRAME_HDR
0x0000000000400624  __FRAME_END__
0x0000000000600e40  __frame_dummy_init_array_entry
0x0000000000600e40  __init_array_start
0x0000000000600e48  __do_global_dtors_aux_fini_array_entry
0x0000000000600e48  __init_array_end
0x0000000000600e50  _DYNAMIC
0x0000000000601000  _GLOBAL_OFFSET_TABLE_
0x0000000000601018  __data_start
0x0000000000601018  data_start
0x0000000000601020  __dso_handle
0x0000000000601028  __TMC_END__
0x0000000000601028  __bss_start
0x0000000000601028  _edata
0x0000000000601028  completed
0x000000000060102c  var
0x0000000000601030  _end
...

I think this is a regression.

Thanks,
- Tom

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PUSHED 2/5] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables]
  2018-10-30 14:59   ` Tom de Vries
@ 2018-10-30 21:27     ` Philippe Waroquiers
  0 siblings, 0 replies; 8+ messages in thread
From: Philippe Waroquiers @ 2018-10-30 21:27 UTC (permalink / raw)
  To: Tom de Vries, gdb-patches; +Cc: Pedro Alves

On Tue, 2018-10-30 at 15:59 +0100, Tom de Vries wrote:
> 
> After this commit, I don't see "var":
...
> I think this is a regression.
> 
Yes, thanks for the clear description of the regression.

I have just sent an RFA with a fix and a test case.

Philippe

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2018-10-30 21:27 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-27 12:44 [PUSHED 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers
2018-10-27 12:44 ` [PUSHED 4/5] Announce changes in NEWS to info [args|functions|locals|variables] Philippe Waroquiers
2018-10-27 12:44 ` [PUSHED 1/5] New cli-utils.h/.c function extract_info_print_args Philippe Waroquiers
2018-10-27 12:44 ` [PUSHED 2/5] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables] Philippe Waroquiers
2018-10-30 14:59   ` Tom de Vries
2018-10-30 21:27     ` Philippe Waroquiers
2018-10-27 12:44 ` [PUSHED 3/5] Document changes " Philippe Waroquiers
2018-10-27 12:44 ` [PUSHED 5/5] Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP] Philippe Waroquiers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).