[RFAv2 0/3] new args [-dirname | -basename] [--] [REGEXP] to info sources

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

[RFAv2 0/3] new args [-dirname | -basename] [--] [REGEXP] to info sources

Philippe Waroquiers
This patch series adds the arguments [-dirname | -basename] [--] [REGEXP] to
the command "info sources".

Currently, info sources shows the name of all source files.
For big programs, the list can be very long, which means the prompt
to continue kicks in.

These optional new arguments allow to have a more selective way to print
the source file names.

This is the second version of the patch series.

Compared to the first version:
  * As suggested by Tom, the command now uses the new cli option -OPT
    framework.  Options -dirname and -basename are replacing -d and -b.
  * gdb/testsuite/gdb.base/info_sources.exp changed to test the new
    options names, using short or longer parts of the option names.
  * The documentation and NEWS have been updated accordingly.
    The comments given by Eli were also handled.


Reply | Threaded
Open this post in threaded view
|

[RFAv2 1/3] New "info sources" args [-dirname | -basename] [--] [REGEXP]

Philippe Waroquiers
gdb/ChangeLog

2019-06-16  Philippe Waroquiers  <[hidden email]>

        * symtab.c (filename_partial_match_opts): New struct type.
        (struct output_source_filename_data): New members
        regexp, c_regexp, partial_match.
        (output_source_filename): Use new members to decide to print file.
        (info_sources_option_defs): New variable.
        (make_info_sources_options_def_group, print_info_sources_header,
        info_sources_command_completer):
        New functions.
        (info_sources_command): Read new optional arguments.
        (_initialize_symtab): Update info sources help.
---
 gdb/symtab.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 150 insertions(+), 8 deletions(-)

diff --git a/gdb/symtab.c b/gdb/symtab.c
index 4920d94a24..854af63651 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -4114,10 +4114,28 @@ operator_chars (const char *p, const char **end)
 }
 
 
+/* What part to match in a file name.  */
+
+struct filename_partial_match_opts
+{
+  /* Only match the directory name part.   */
+  int dirname = false;
+
+  /* Only match the basename part.  */
+  int basename = false;
+};
+
 /* Data structure to maintain printing state for output_source_filename.  */
 
 struct output_source_filename_data
 {
+  /* Output only filenames matching REGEXP.  */
+  std::string regexp;
+  gdb::optional<compiled_regex> c_regexp;
+  /* Possibly only match a part of the filename.  */
+  filename_partial_match_opts partial_match;
+
+
   /* Cache of what we've seen so far.  */
   struct filename_seen_cache *filename_seen_cache;
 
@@ -4149,7 +4167,27 @@ output_source_filename (const char *name,
       return;
     }
 
-  /* No; print it and reset *FIRST.  */
+  /* Does it match data->regexp?  */
+  if (data->c_regexp.has_value ())
+    {
+      const char *to_match;
+      std::string dirname;
+
+      if (data->partial_match.dirname)
+ {
+  dirname = ldirname (name);
+  to_match = dirname.c_str ();
+ }
+      else if (data->partial_match.basename)
+ to_match = lbasename (name);
+      else
+ to_match = name;
+
+      if (data->c_regexp->exec (to_match, 0, NULL, 0) != 0)
+ return;
+    }
+
+  /* Print it and reset *FIRST.  */
   if (! data->first)
     printf_filtered (", ");
   data->first = 0;
@@ -4168,8 +4206,73 @@ output_partial_symbol_filename (const char *filename, const char *fullname,
   (struct output_source_filename_data *) data);
 }
 
+using isrc_flag_option_def
+  = gdb::option::flag_option_def<filename_partial_match_opts>;
+
+static const gdb::option::option_def info_sources_option_defs[] = {
+
+  isrc_flag_option_def {
+    "dirname",
+    [] (filename_partial_match_opts *opts) { return &opts->dirname; },
+    N_("Show only the files having a dirname matching REGEXP."),
+  },
+
+  isrc_flag_option_def {
+    "basename",
+    [] (filename_partial_match_opts *opts) { return &opts->basename; },
+    N_("Show only the files having a basename matching REGEXP."),
+  },
+
+};
+
+/* Create an option_def_group for the "info sources" options, with
+   ISRC_OPTS as context.  */
+
+static inline gdb::option::option_def_group
+make_info_sources_options_def_group (filename_partial_match_opts *isrc_opts)
+{
+  return {{info_sources_option_defs}, isrc_opts};
+}
+
+/* Prints the header message for the source files that will be printed
+   with the matching info present in DATA.  SYMBOL_MSG is a message
+   that tells what will or has been done with the symbols of the
+   matching source files.  */
+
+static void
+print_info_sources_header (const char *symbol_msg,
+   const struct output_source_filename_data *data)
+{
+  printf_filtered ("Source files ");
+  if (!data->regexp.empty ())
+    {
+      if (data->partial_match.dirname)
+ printf_filtered ("(dirname ");
+      else if (data->partial_match.basename)
+ printf_filtered ("(basename ");
+      else
+ printf_filtered ("(filename ");
+      printf_filtered ("matching regular expression \"%s\") ",
+       data->regexp.c_str ());
+    }
+  printf_filtered ("for which symbols %s:\n\n", symbol_msg);
+}
+
+/* Completer for "info sources".  */
+
+static void
+info_sources_command_completer (cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char *word)
+{
+  const auto group = make_info_sources_options_def_group (nullptr);
+  if (gdb::option::complete_options
+      (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
+    return;
+}
+
 static void
-info_sources_command (const char *ignore, int from_tty)
+info_sources_command (const char *args, int from_tty)
 {
   struct output_source_filename_data data;
 
@@ -4180,11 +4283,37 @@ info_sources_command (const char *ignore, int from_tty)
 
   filename_seen_cache filenames_seen;
 
-  data.filename_seen_cache = &filenames_seen;
+  auto group = make_info_sources_options_def_group (&data.partial_match);
+
+  gdb::option::process_options
+    (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group);
 
-  printf_filtered ("Source files for which symbols have been read in:\n\n");
+  if (args != NULL && *args != '\000')
+    data.regexp = args;
 
+  data.filename_seen_cache = &filenames_seen;
   data.first = 1;
+
+  if (data.partial_match.dirname && data.partial_match.basename)
+    error (_("You cannot give both -basename and -dirname to 'info sources'."));
+  if ((data.partial_match.dirname || data.partial_match.basename)
+      && data.regexp.empty ())
+     error (_("Missing REGEXP for 'info sources'."));
+
+  if (data.regexp.empty ())
+    data.c_regexp.reset ();
+  else
+    {
+      int cflags = REG_NOSUB;
+#ifdef HAVE_CASE_INSENSITIVE_FILE_SYSTEM
+      cflags |= REG_ICASE;
+#endif
+      data.c_regexp.emplace (data.regexp.c_str (), cflags,
+     _("Invalid regexp"));
+    }
+
+  print_info_sources_header ("have been read in", &data);
+
   for (objfile *objfile : current_program_space->objfiles ())
     {
       for (compunit_symtab *cu : objfile->compunits ())
@@ -4199,8 +4328,7 @@ info_sources_command (const char *ignore, int from_tty)
     }
   printf_filtered ("\n\n");
 
-  printf_filtered ("Source files for which symbols "
-   "will be read in on demand:\n\n");
+  print_info_sources_header ("will be read in on demand", &data);
 
   filenames_seen.clear ();
   data.first = 1;
@@ -6008,6 +6136,8 @@ symbol_set_symtab (struct symbol *symbol, struct symtab *symtab)
 void
 _initialize_symtab (void)
 {
+  struct cmd_list_element *c;
+
   initialize_ordinary_address_classes ();
 
   add_info ("variables", info_variables_command,
@@ -6042,8 +6172,20 @@ Prints the functions.\n"),
   add_info ("types", info_types_command,
     _("All type names, or those matching REGEXP."));
 
-  add_info ("sources", info_sources_command,
-    _("Source files in the program."));
+  const auto info_sources_opts = make_info_sources_options_def_group (nullptr);
+
+  static std::string info_sources_help
+    = gdb::option::build_help (_("\
+All source files in the program or those matching REGEXP.\n\
+Usage: info sources [OPTION]... [REGEXP]\n\
+By default, REGEXP is used to match anywhere in the filename.\n\
+\n\
+Options:\n\
+%OPTIONS%"),
+       info_sources_opts);
+
+  c = add_info ("sources", info_sources_command, info_sources_help.c_str ());
+  set_cmd_completer_handle_brkchars (c, info_sources_command_completer);
 
   add_com ("rbreak", class_breakpoint, rbreak_command,
    _("Set a breakpoint for all functions matching REGEXP."));
--
2.20.1

Reply | Threaded
Open this post in threaded view
|

[RFAv2 2/3] New test for 'info sources [-dirname | -basename] [--] [REGEXP]'.

Philippe Waroquiers
In reply to this post by Philippe Waroquiers
gdb/testsuite/ChangeLog

2019-06-16  Philippe Waroquiers  <[hidden email]>

        * gdb.base/info_sources.exp: New file.
        * gdb.base/info_sources.c: New file.
        * gdb.base/info_sources_base.c: New file.
---
 gdb/testsuite/gdb.base/info_sources.c      | 23 ++++++
 gdb/testsuite/gdb.base/info_sources.exp    | 89 ++++++++++++++++++++++
 gdb/testsuite/gdb.base/info_sources_base.c |  5 ++
 3 files changed, 117 insertions(+)
 create mode 100644 gdb/testsuite/gdb.base/info_sources.c
 create mode 100644 gdb/testsuite/gdb.base/info_sources.exp
 create mode 100644 gdb/testsuite/gdb.base/info_sources_base.c

diff --git a/gdb/testsuite/gdb.base/info_sources.c b/gdb/testsuite/gdb.base/info_sources.c
new file mode 100644
index 0000000000..75fab6df70
--- /dev/null
+++ b/gdb/testsuite/gdb.base/info_sources.c
@@ -0,0 +1,23 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2019 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/>.  */
+
+extern void some_other_func (void);
+int main ()
+{
+  some_other_func ();
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/info_sources.exp b/gdb/testsuite/gdb.base/info_sources.exp
new file mode 100644
index 0000000000..76d9b7373b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/info_sources.exp
@@ -0,0 +1,89 @@
+# Copyright 2019 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/>.
+
+# Test 'info sources [-d | -b] [--] [REGEẌ]'
+
+standard_testfile .c info_sources_base.c
+
+if {[prepare_for_testing $testfile.exp $testfile \
+ [list $srcfile $srcfile2] debug]} {
+    untested $testfile.exp
+    return -1
+}
+
+# Executes "info sources " $args.
+# EXPECT_SEEN_INFO_SOURCES 1 indicates that the source file info_sources.c must be seen
+# in the output.  Similarly, EXPECT_SEEN_INFO_SOURCES_BASE indicates that the source file
+# info_sources_base.c must be seen in the output.
+proc test_info_sources {args expect_seen_info_sources expect_seen_info_sources_base} {
+    global gdb_prompt
+
+    set seen_info_sources 0
+    set seen_info_sources_base 0
+    set cmd [concat "info sources " $args]
+    gdb_test_multiple $cmd $cmd {
+ -re "^\[^,\]*info_sources.c(, |\[\r\n\]+)" {
+    set seen_info_sources 1
+    exp_continue
+ }
+ -re "^\[^,\]*info_sources_base.c(, |\[\r\n\]+)" {
+    set seen_info_sources_base 1
+    exp_continue
+ }
+ -re ", " {
+    exp_continue
+ }
+ -re "$gdb_prompt $" {
+    if {$seen_info_sources == $expect_seen_info_sources \
+    && $seen_info_sources_base == $expect_seen_info_sources_base} {
+ pass $cmd
+    } else {
+ fail $cmd
+    }
+ }
+    }
+}
+
+if ![runto_main] {
+    untested $testfile.exp
+    return -1
+}
+gdb_test "break some_other_func" ""
+
+gdb_test "continue"
+
+# List both files with no regexp:
+test_info_sources "" 1 1
+# Same but with option terminator:
+test_info_sources "--" 1 1
+
+# List both files with regexp matching anywhere in the filenames:
+test_info_sources "info_sources" 1 1
+test_info_sources "gdb.base" 1 1
+
+# List both files with regexp matching the filename basenames:
+test_info_sources "-b info_sources" 1 1
+test_info_sources "-b -- info_sources" 1 1
+
+# List only the file with basename matching regexp:
+test_info_sources "-b base" 0 1
+
+# List the files with dirname matching regexp:
+test_info_sources "-d base" 1 1
+
+# Test non matching regexp, with option terminator:
+test_info_sources "-b -- -d" 0 0
+test_info_sources "-d -- -d" 0 0
+
diff --git a/gdb/testsuite/gdb.base/info_sources_base.c b/gdb/testsuite/gdb.base/info_sources_base.c
new file mode 100644
index 0000000000..a4c03a0341
--- /dev/null
+++ b/gdb/testsuite/gdb.base/info_sources_base.c
@@ -0,0 +1,5 @@
+void some_other_func (void)
+{
+  return;
+}
+
--
2.20.1

Reply | Threaded
Open this post in threaded view
|

[RFAv2 3/3] NEWS and documentation for info sources [-dirname | -basename] [--] [REGEXP].

Philippe Waroquiers
In reply to this post by Philippe Waroquiers
gdb/ChangeLog
2019-06-16  Philippe Waroquiers  <[hidden email]>

        * NEWS: Mention changes to "info sources" command.

gdb/doc/ChangeLog
2019-06-16  Philippe Waroquiers  <[hidden email]>

        * gdb.texinfo (Symbols): Document new args -dirname and -basename
        of "info sources" command.
---
 gdb/NEWS                                |  9 +++++++++
 gdb/doc/gdb.texinfo                     |  9 +++++++++
 gdb/testsuite/gdb.base/info_sources.exp | 13 ++++++++++---
 3 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 2cc82e8656..b890b50ccd 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -102,6 +102,12 @@ apropos [-v] REGEXP
   of matching commands and to use the highlight style to mark
   the documentation parts matching REGEXP.
 
+info sources [-dirname | -basename] [--] [REGEXP]
+  This command has now optional arguments to only print the files
+  whose names match REGEXP.  The arguments -dirname and -basename
+  allow to restrict matching respectively to the dirname and basename
+  parts of the files.
+
 show style
   The "show style" and its subcommands are now styling
   a style name in their output using its own style, to help
@@ -177,6 +183,9 @@ maint show test-options-completion-result
       -past-main [on|off]
       -past-entry [on|off]
 
+  ** The new "info sources" options -dirname and -basename options
+     are using the standard '-OPT' infrastructure.
+
    All options above can also be abbreviated.  The argument of boolean
    (on/off) options can be 0/1 too, and also the argument is assumed
    "on" if omitted.  This allows writing compact command invocations,
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9a0320e5d8..6ec0a2c916 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -18428,6 +18428,15 @@ Print the names of all source files in your program for which there is
 debugging information, organized into two lists: files whose symbols
 have already been read, and files whose symbols will be read when needed.
 
+@item info sources [-dirname | -basename] [--] [@var{regexp}]
+Like @samp{info sources}, but only print the names of the files
+matching the provided @var{regexp}.
+By default, the @var{regexp} is used to match anywhere in the filename.
+If -dirname, only files having a dirname matching @var{regexp} are shown.
+If -basename, only files having a basename matching @var{regexp} are shown.
+The matching is case-sensitive, except on operating systems that
+have case-insensitive filesystem (e.g., MS-Windows).
+
 @kindex info functions
 @item info functions [-q]
 Print the names and data types of all defined functions.
diff --git a/gdb/testsuite/gdb.base/info_sources.exp b/gdb/testsuite/gdb.base/info_sources.exp
index 76d9b7373b..0fe5fb68f1 100644
--- a/gdb/testsuite/gdb.base/info_sources.exp
+++ b/gdb/testsuite/gdb.base/info_sources.exp
@@ -73,17 +73,24 @@ test_info_sources "--" 1 1
 test_info_sources "info_sources" 1 1
 test_info_sources "gdb.base" 1 1
 
-# List both files with regexp matching the filename basenames:
+# List both files with regexp matching the filename basenames,
+# using various parts of the -basename option:
 test_info_sources "-b info_sources" 1 1
 test_info_sources "-b -- info_sources" 1 1
+test_info_sources "-ba info_sources" 1 1
+test_info_sources "-base -- info_sources" 1 1
+test_info_sources "-basena info_sources" 1 1
+test_info_sources "-basename -- info_sources" 1 1
 
 # List only the file with basename matching regexp:
 test_info_sources "-b base" 0 1
 
-# List the files with dirname matching regexp:
+# List the files with dirname matching regexp,
+# using various part of the -dirname option:
 test_info_sources "-d base" 1 1
+test_info_sources "-dir base" 1 1
+test_info_sources "-dirname base" 1 1
 
 # Test non matching regexp, with option terminator:
 test_info_sources "-b -- -d" 0 0
 test_info_sources "-d -- -d" 0 0
-
--
2.20.1

Reply | Threaded
Open this post in threaded view
|

Re: [RFAv2 3/3] NEWS and documentation for info sources [-dirname | -basename] [--] [REGEXP].

Eli Zaretskii
> From: Philippe Waroquiers <[hidden email]>
> Cc: Philippe Waroquiers <[hidden email]>
> Date: Sun, 16 Jun 2019 22:38:04 +0200
>
> +@item info sources [-dirname | -basename] [--] [@var{regexp}]
> +Like @samp{info sources}, but only print the names of the files
> +matching the provided @var{regexp}.
> +By default, the @var{regexp} is used to match anywhere in the filename.
> +If -dirname, only files having a dirname matching @var{regexp} are shown.
> +If -basename, only files having a basename matching @var{regexp} are shown.

"-dirname" and "-basename" should be in @code.

Otherwise the documentation is OK, thanks.
Reply | Threaded
Open this post in threaded view
|

PING Re: [RFAv2 0/3] new args [-dirname | -basename] [--] [REGEXP] to info sources

Philippe Waroquiers
In reply to this post by Philippe Waroquiers
Ping ?

Thanks

Philippe

On Sun, 2019-06-16 at 22:38 +0200, Philippe Waroquiers wrote:

> This patch series adds the arguments [-dirname | -basename] [--] [REGEXP] to
> the command "info sources".
>
> Currently, info sources shows the name of all source files.
> For big programs, the list can be very long, which means the prompt
> to continue kicks in.
>
> These optional new arguments allow to have a more selective way to print
> the source file names.
>
> This is the second version of the patch series.
>
> Compared to the first version:
>   * As suggested by Tom, the command now uses the new cli option -OPT
>     framework.  Options -dirname and -basename are replacing -d and -b.
>   * gdb/testsuite/gdb.base/info_sources.exp changed to test the new
>     options names, using short or longer parts of the option names.
>   * The documentation and NEWS have been updated accordingly.
>     The comments given by Eli were also handled.
>
>
Reply | Threaded
Open this post in threaded view
|

Re: [RFAv2 1/3] New "info sources" args [-dirname | -basename] [--] [REGEXP]

Tom Tromey-2
In reply to this post by Philippe Waroquiers
>>>>> "Philippe" == Philippe Waroquiers <[hidden email]> writes:

Philippe> gdb/ChangeLog
Philippe> 2019-06-16  Philippe Waroquiers  <[hidden email]>

This commit probably needs a bit of intro text.

Philippe> +static void
Philippe> +print_info_sources_header (const char *symbol_msg,
Philippe> +   const struct output_source_filename_data *data)
Philippe> +{
Philippe> +  printf_filtered ("Source files ");
Philippe> +  if (!data->regexp.empty ())
Philippe> +    {
Philippe> +      if (data->partial_match.dirname)
Philippe> + printf_filtered ("(dirname ");
Philippe> +      else if (data->partial_match.basename)
Philippe> + printf_filtered ("(basename ");
Philippe> +      else
Philippe> + printf_filtered ("(filename ");
Philippe> +      printf_filtered ("matching regular expression \"%s\") ",
Philippe> +       data->regexp.c_str ());
Philippe> +    }
Philippe> +  printf_filtered ("for which symbols %s:\n\n", symbol_msg);

This sort of approach isn't very i18n-friendly.  I think we've been
trying to avoid introducing new code like this, in hopes that maybe
somebody will provide gdb translations some day.

One idea might be to separate the main text from the parenthetical text,
so like:

  printf_filtered (_("Source files for which symbols have been read in"));
  if (blah)
    printf_filtered (_("(dirname matching regular expression \"%s\")"), dirname);
  ...
  printf_filtered (_(":\n"));

The "if"s could be factored into a helper function.

Otherwise this patch seems good to me.  Thanks for doing this.

Tom
Reply | Threaded
Open this post in threaded view
|

Re: [RFAv2 2/3] New test for 'info sources [-dirname | -basename] [--] [REGEXP]'.

Tom Tromey-2
In reply to this post by Philippe Waroquiers
>>>>> "Philippe" == Philippe Waroquiers <[hidden email]> writes:

Philippe> gdb/testsuite/ChangeLog
Philippe> 2019-06-16  Philippe Waroquiers  <[hidden email]>

Intro text.

Philippe> diff --git a/gdb/testsuite/gdb.base/info_sources_base.c b/gdb/testsuite/gdb.base/info_sources_base.c
Philippe> new file mode 100644
Philippe> index 0000000000..a4c03a0341
Philippe> --- /dev/null
Philippe> +++ b/gdb/testsuite/gdb.base/info_sources_base.c
Philippe> @@ -0,0 +1,5 @@
Philippe> +void some_other_func (void)
Philippe> +{
Philippe> +  return;
Philippe> +}

I think all new files should have the copyright header.

Tom
Reply | Threaded
Open this post in threaded view
|

Re: [RFAv2 1/3] New "info sources" args [-dirname | -basename] [--] [REGEXP]

Philippe Waroquiers
In reply to this post by Tom Tromey-2
On Wed, 2019-07-24 at 13:14 -0600, Tom Tromey wrote:

> One idea might be to separate the main text from the parenthetical text,
> so like:
>
>   printf_filtered (_("Source files for which symbols have been read in"));
>   if (blah)
>     printf_filtered (_("(dirname matching regular expression \"%s\")"), dirname);
>   ...
>   printf_filtered (_(":\n"));
>
> The "if"s could be factored into a helper function.
>
> Otherwise this patch seems good to me.  Thanks for doing this.
Thanks for the review.

Pushed after fixing the above, adding a copyright header that was missing
in a test file.

Philippe