[RFAv3 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP]

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

[RFAv3 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP]

Philippe Waroquiers

[RFAv3 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP]

RFAv3, handling the comments of Tom and Eli about RFAv2.
--------------------------------------------------------
* code changes:
  - reworked extract_arg_maybe_quoted to have it working the same way
    as gdb_argv. In another patch series, I will evaluate more in
    detail handling quoting/escaping inside extract_arg, by analysing
    all callers.
  - fixed (and tested) regression when NAMEREGEXP arg contains spaces.
  - replaced INFO_PRINT_ARGS_HELP by function info_print_args_help
    to make this gettext friendly.

  - instead of preg/treg regexp new arguments to iterate_over_block_arg_vars
    and iterate_over_block_local_vars, have preg/treg being part
    of the opaque cb_data, and do filtering inside do_print_variable_and_value.
  - no need anymore to include gdb_regex.h in various files or stack.h.
  - used preg/treg.has_value() instead of implicit conversion to boolean.
  - used *reg instead of &reg for an out parameter.
  - handled language specific type printing using set_language and RAII.
  - no new line after return type for function declaration.
 
* documentation changes:
  - handled the comments of Eli: rephrase two sentences as one,
    remove redundant blank before :.
  - quoting/backslash handling of TYPEREGEXP slightly updated according
    to the switch to gdb_argv quoting behaviour.


Changes between the first RFA and RFAv2:
---------------------------------------
The documentation parts were already reviewed by Eli, other parts
were not reviewed yet.
Compared to the first RFA, the changes are a rebase to the last trunk version,
the removal of an unused local variable, and some updates to the new
info_qt.exp test to ensure unicity of test names.

Changes between first RFA and  the RFC:
---------------------------------------
* Handled comments of Eli on the documentation.
* ChangeLog entries added in commit messages
* Test added.

Thanks.


This patch series adds flags and/or arguments
[-q] [-t TYPEREGEXP] [NAMEREGEXP] to the commands
  info [args|functions|locals|variables]

The additional arguments allow to more precisely specify what to print.
As these new features can usefully be combined with frame apply and thread
apply, the documentation gives examples combining the above
and the 'thread apply' and 'frame apply' commands.

Some examples:
* print functions returning an int:
    info functions -t '^int ('
* print local variables having pthread_t type
    info locals -t pthread_t
* print global variables having type 'struct addrinfo'
    info var -t 'struct addrinfo'
* print args that are likely file descriptors
    info arg -t int .*fd.*

Below examples are combined with the 'thread/frame apply' commands:

* Assuming lock_something_t is an RAII type, show all locks:
  thread apply all -s frame apply all -s info locals -q -t lock_something_t
 or shorter equivalent:
  tfaas i lo -q -t lock_something_t

* show frames and args having an arg with type matchin std::.*map
  so likely  std::map or std::unordered_map
  frame apply all -s info args -q std::.*map


The code, documentation, NEWS, test and ChangeLog are complete.


Reply | Threaded
Open this post in threaded view
|

[RFAv3 1/5] New cli-utils.h/.c function extract_info_print_args

Philippe Waroquiers
New cli-utils.h/.c function extract_info_print_args factorises
the extraction of the args '[-q] [-t TYPEREGEXP] [NAMEREGEXP]'.

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

As this function 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-09-23  Philippe Waroquiers  <[hidden email]>

        * cli-utils.c (extract_arg_maybe_quoted): New function.
        (extract_info_print_args): New function.
        (info_print_args_help): New function.
        * cli-utils.h (extract_arg_maybe_quoted): New function.
        (extract_info_print_args): New function.
        (info_print_args_help): New function.
---
 gdb/cli/cli-utils.c | 159 ++++++++++++++++++++++++++++++++++++++++++++
 gdb/cli/cli-utils.h |  15 +++++
 2 files changed, 174 insertions(+)

diff --git a/gdb/cli/cli-utils.c b/gdb/cli/cli-utils.c
index 98b7414991..ea4b4b6f61 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
@@ -125,6 +127,84 @@ get_number (char **pp)
   return result;
 }
 
+/* See documentation in cli-utils.h.  */
+
+void
+extract_info_print_args (const char* command,
+ const char **args,
+ bool *quiet,
+ std::string *regexp,
+ std::string *t_regexp)
+{
+  *quiet = false;
+  *regexp = "";
+  *t_regexp = "";
+
+  while (*args != NULL)
+    {
+      if (check_for_argument (args, "--", 2))
+ {
+  *args = skip_spaces (*args);
+  break;
+ }
+
+      if (check_for_argument (args, "-t", 2))
+ {
+  *t_regexp = extract_arg_maybe_quoted (args);
+  *args = skip_spaces (*args);
+  continue;
+ }
+
+      if (check_for_argument (args, "-q", 2))
+ {
+  *quiet = true;
+  *args = skip_spaces (*args);
+  continue;
+ }
+
+      if (**args != '-')
+ break;
+
+      std::string option = extract_arg (args);
+      error (_("Unrecognized option '%s' to %s command.  "
+       "Try \"help %s\"."), option.c_str (),
+     command, command);
+    }
+
+  if (*args != NULL && **args != '\000')
+    *regexp = *args;
+
+}
+
+/* See documentation in cli-utils.h.  */
+
+const char*
+info_print_args_help (const char* prefix,
+      const char* entity_kind)
+{
+  std::string h;
+
+  h = prefix;
+  h += _("If NAMEREGEXP is provided, only prints the ");
+  h += entity_kind;
+  h +=_(" whose name\n\
+matches NAMEREGEXP.\n\
+If -t TYPEREGEXP is provided, only prints the ");
+  h += entity_kind;
+  h +=_(" 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 ");
+  h += entity_kind;
+  h += _(" can be printed.\n\
+The flag -q disables the production of these headers and messages.");
+
+  return xstrdup (h.c_str ());
+}
+
+
+
 /* See documentation in cli-utils.h.  */
 
 number_or_range_parser::number_or_range_parser (const char *string)
@@ -282,6 +362,85 @@ 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)
+{
+  int squote = 0;
+  int dquote = 0;
+  int bsquote = 0;
+  std::string result = std::string ();
+
+  /* Find the start of the argument.  */
+  *arg = skip_spaces (*arg);
+
+  /* Parse *arg similarly to gdb_argv buildargv function.  */
+  while (**arg != '\0')
+    {
+      if (isspace (**arg) && !squote && !dquote && !bsquote)
+ {
+  break;
+ }
+      else
+ {
+  if (bsquote)
+    {
+      bsquote = 0;
+      result += **arg;
+    }
+  else if (**arg == '\\')
+    {
+      bsquote = 1;
+    }
+  else if (squote)
+    {
+      if (**arg == '\'')
+ {
+  squote = 0;
+ }
+      else
+ {
+  result += **arg;
+ }
+    }
+  else if (dquote)
+    {
+      if (**arg == '"')
+ {
+  dquote = 0;
+ }
+      else
+ {
+  result += **arg;
+ }
+    }
+  else
+    {
+      if (**arg == '\'')
+ {
+  squote = 1;
+ }
+      else if (**arg == '"')
+ {
+  dquote = 1;
+ }
+      else
+ {
+  result += **arg;
+ }
+    }
+  (*arg)++;
+ }
+    }
+
+  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..8ce8db1860 100644
--- a/gdb/cli/cli-utils.h
+++ b/gdb/cli/cli-utils.h
@@ -39,6 +39,21 @@ extern int get_number (const char **);
 
 extern int get_number (char **);
 
+/* Extract from args the arguments [-q] [-t TYPEREGEXP] [--] NAMEREGEXP.
+   Only the above flags are accepted.  Any other flag will raise an error.
+   COMMAND is used to produce the error message if an invalid flag is
+   given.  */
+extern void extract_info_print_args (const char* command,
+     const char **args,
+     bool *quiet,
+     std::string *regexp,
+     std::string *t_regexp);
+
+/* Builds the help string for a command documented by PREFIX,
+   followed by the extract_info_print_args help for ENTITY_KIND.  */
+extern 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.18.0

Reply | Threaded
Open this post in threaded view
|

[RFAv3 2/5] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables]

Philippe Waroquiers
In reply to this post by 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-09-23  Philippe Waroquiers  <[hidden email]>

        * 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/python/python.c |   4 +-
 gdb/stack.c         | 126 ++++++++++++++++++++++++++-----
 gdb/symtab.c        | 179 +++++++++++++++++++++++++++++++++++++-------
 gdb/symtab.h        |   7 +-
 4 files changed, 266 insertions(+), 50 deletions(-)

diff --git a/gdb/python/python.c b/gdb/python/python.c
index c16305b900..369c966cb6 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 40ff99b8fa..ab61d6dea0 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -89,8 +89,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,
@@ -1829,7 +1831,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);
@@ -2011,6 +2013,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;
@@ -2028,6 +2032,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)
     {
@@ -2043,14 +2055,37 @@ 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;
@@ -2058,18 +2093,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;
@@ -2085,14 +2124,27 @@ 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;
+
+  extract_info_print_args ("info locals", &args, &quiet, &regexp, &t_regexp);
   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);
 }
 
@@ -2121,7 +2173,6 @@ iterate_over_block_arg_vars (const struct block *b,
      symbol is double and the type of the LOC_LOCAL symbol is
      float).  There are also LOC_ARG/LOC_REGISTER pairs which
      are not combined in symbol-reading.  */
-
   sym2 = lookup_symbol_search_name (SYMBOL_SEARCH_NAME (sym),
     b, VAR_DOMAIN).symbol;
   (*cb) (SYMBOL_PRINT_NAME (sym), sym2, cb_data);
@@ -2131,29 +2182,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;
@@ -2165,14 +2232,27 @@ 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;
+
+  extract_info_print_args ("info args", &args, &quiet, &regexp, &t_regexp);
   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);
 }
 
@@ -2816,9 +2896,17 @@ on this backtrace."));
     _("All about selected stack frame, or frame at ADDR."));
   add_info_alias ("f", "frame", 1);
   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 04dd5e2648..01f6add940 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,41 @@ 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;
+
+  extract_info_print_args ("info variables", &args, &quiet, &regexp, &t_regexp);
+  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;
+
+  extract_info_print_args ("info functions", &args, &quiet, &regexp, &t_regexp);
+  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 +4811,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 +6013,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 399666b473..29240b4558 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"
@@ -2063,8 +2064,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.18.0

Reply | Threaded
Open this post in threaded view
|

[RFAv3 3/5] Document changes to info [args|functions|locals|variables]

Philippe Waroquiers
In reply to this post by Philippe Waroquiers
Document changes to info [args|functions|locals|variables]

gdb/doc/ChangeLog
2018-09-23  Philippe Waroquiers  <[hidden email]>

        * 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/gdb.texinfo | 121 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 109 insertions(+), 12 deletions(-)

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b5b6089153..cf4ffa2a94 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -7767,15 +7767,73 @@ architectures) that you specify in the @code{frame} command.
 @xref{Selection, ,Selecting a Frame}.
 
 @kindex info args
-@item info args
+@item info args [-q]
 Print the arguments of the selected frame, each on a separate line.
 
+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
+contain a match for regular expression @var{regexp}.
+
+If @var{type_regexp} is provided, print only the arguments whose
+types, as printed by the @code{whatis} command, contain a match
+for 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 it matches the two regexps.
+
 @item info locals
-@kindex info locals
+@kindex info locals [-q]
 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
+contain a match for regular expression @var{regexp}.
+
+If @var{type_regexp} is provided, print only the local variables whose
+types, as printed by the @code{whatis} command, contain a match
+for 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 it matches the two regexps.
+
+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
@@ -17857,32 +17915,71 @@ 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
+contain a match for 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, contain a match
+for 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 are returning
+an int.
+
+If both @var{regexp} and @var{type_regexp} are provided, a function
+is printed only if it matches the two regexps.
+
+
 @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
+contain a match for regular expression @var{regexp}.
+
+If @var{type_regexp} is provided, print only the variables whose
+types, as printed by the @code{whatis} command, contain a match
+for 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 it matches the two regexps.
 
 @kindex info classes
 @cindex Objective-C, classes and selectors
--
2.18.0

Reply | Threaded
Open this post in threaded view
|

[RFAv3 4/5] Announce changes in NEWS to info [args|functions|locals|variables]

Philippe Waroquiers
In reply to this post by Philippe Waroquiers
Announce changes in NEWS to info [args|functions|locals|variables]

gdb/ChangeLog
2018-09-23  Philippe Waroquiers  <[hidden email]>

        * NEWS: Mention changes to 'info [args|functions|locals|variables]'
---
 gdb/NEWS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/gdb/NEWS b/gdb/NEWS
index a1936ca1cc..669fd12ea7 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -61,6 +61,15 @@ info proc files
 
 * Changed commands
 
+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.18.0

Reply | Threaded
Open this post in threaded view
|

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

Philippe Waroquiers
In reply to this post by Philippe Waroquiers
Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP]

gdb/testsuite/ChangeLog
2018-09-23  Philippe Waroquiers  <[hidden email]>

        * gdb.base/info_qt.c: New file.
        * gdb.base/info_qt.exp: New file.
---
 gdb/testsuite/gdb.base/info_qt.c   |  81 ++++++++++
 gdb/testsuite/gdb.base/info_qt.exp | 234 +++++++++++++++++++++++++++++
 2 files changed, 315 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/gdb.base/info_qt.c b/gdb/testsuite/gdb.base/info_qt.c
new file mode 100644
index 0000000000..77c4ea8236
--- /dev/null
+++ b/gdb/testsuite/gdb.base/info_qt.c
@@ -0,0 +1,81 @@
+/* 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/>.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+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..3ece05c5e4
--- /dev/null
+++ b/gdb/testsuite/gdb.base/info_qt.exp
@@ -0,0 +1,234 @@
+# 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 that a macro using backtrace can be applied to all threads
+# and will continue for each thread even though an error may occur in
+# backtracing one of the threads.
+
+# Test 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 {
+    gdb_suppress_tests
+}
+set any "\[^\r\n\]*"
+set ws "\[ \t\]\+"
+set number "\[0-9]\+"
+
+
+############# test 'info functions'
+
+# test simple matching with name regexp
+foreach_with_prefix 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\\\);" \
+    ] \
+ "info functions info_fun"
+}
+
+# test simple matching with name regexp, but with -q to avoid the first header
+foreach_with_prefix 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\\\);" \
+    ] \
+ "info functions -q info_fun"
+}
+
+# test -q and no matching functions
+foreach_with_prefix cmd {
+    "info functions -q nowaythiscanmatch"
+    "info functions -q -- -q" } {
+    gdb_test $cmd "" "quiet info functions empty output"
+}
+
+# test with a type regexp
+foreach_with_prefix 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\\\);" \
+    ] \
+ "info functions -q info_fun"
+}
+
+# test with a non matching type regexp
+gdb_test "info functions -t ganze_Zahl -q info_fun" "" \
+    "quiet output info functions non matching type"
+
+
+############# test 'info variables'
+
+# test simple matching with name regexp
+foreach_with_prefix 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;" \
+    ] \
+ "info functions info_fun"
+}
+
+# test simple matching with name regexp, but with -q to avoid the first header
+
+# test -q and no matching variables
+foreach_with_prefix cmd {
+    "info variables -q nowaythiscanmatch"
+    "info variables -q -- -q" } {
+    gdb_test $cmd "" "quiet info variables empty output"
+}
+
+# test with a type regexp
+foreach_with_prefix 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;" \
+    ] \
+ "info variables -q -t entier info_fun"
+}
+
+# test with a non matching type regexp
+gdb_test "info variables -t ganze_Zahl -q info_at" "" \
+    "quiet output info variables non matching type"
+
+
+
+############# test 'info args' in function setup.
+
+gdb_test "frame 1" ".* in setup .*" "set frame 1 for info args"
+
+# test name regexp matching all
+foreach_with_prefix 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" \
+    ] \
+ "info args"
+}
+
+# test name regexp or type regexp matching some
+foreach_with_prefix cmd {
+    "info args -t int"
+    "info args arg_[ij]"} {
+    gdb_test $cmd \
+ [multi_line \
+     "arg_i = 3" \
+     "arg_j = 4" \
+    ] \
+ "info args"
+}
+
+gdb_test "info args nowaythiscanmatch" "No matching arguments." "non matching args"
+gdb_test "info args -q nowaythiscanmatch" "" "quiet non matching args"
+gdb_test "info args -q -t entier" "" "quiet non matching args with type"
+
+############# test 'info locals' in function setup.
+
+gdb_test "frame 1" ".* in setup .*" "set frame 1 for info locals"
+
+# test name regexp matching all
+foreach_with_prefix 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" \
+    ] \
+ "info locals"
+}
+
+# test name regexp or type regexp matching some
+foreach_with_prefix 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" \
+    ] \
+ "info args"
+}
+
+gdb_test "info locals nowaythiscanmatch" "No matching locals." "non matching locals"
+gdb_test "info locals -q nowaythiscanmatch" "" "quiet non matching locals"
+gdb_test "info locals -q -t ganze_Zahl loc" "" "quiet non matching locals with type"
+
+# verify that the rest of the args is taken as a 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.18.0

Reply | Threaded
Open this post in threaded view
|

Re: [RFAv3 4/5] Announce changes in NEWS to info [args|functions|locals|variables]

Eli Zaretskii
In reply to this post by Philippe Waroquiers
> From: Philippe Waroquiers <[hidden email]>
> Cc: Philippe Waroquiers <[hidden email]>
> Date: Sun, 23 Sep 2018 23:42:08 +0200
>
> Announce changes in NEWS to info [args|functions|locals|variables]
>
> gdb/ChangeLog
> 2018-09-23  Philippe Waroquiers  <[hidden email]>
>
>         * NEWS: Mention changes to 'info [args|functions|locals|variables]'

This is OK, thanks.
Reply | Threaded
Open this post in threaded view
|

Re: [RFAv3 3/5] Document changes to info [args|functions|locals|variables]

Eli Zaretskii
In reply to this post by Philippe Waroquiers
> From: Philippe Waroquiers <[hidden email]>
> Cc: Philippe Waroquiers <[hidden email]>
> Date: Sun, 23 Sep 2018 23:42:07 +0200
>
> Document changes to info [args|functions|locals|variables]
>
> gdb/doc/ChangeLog
> 2018-09-23  Philippe Waroquiers  <[hidden email]>
>
> * 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'.

Thanks, this is OK.
Reply | Threaded
Open this post in threaded view
|

Re: [RFAv3 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP]

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

On Sun, 2018-09-23 at 23:42 +0200, Philippe Waroquiers wrote:

> [RFAv3 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP]
>
> RFAv3, handling the comments of Tom and Eli about RFAv2.
> --------------------------------------------------------
> * code changes:
>   - reworked extract_arg_maybe_quoted to have it working the same way
>     as gdb_argv. In another patch series, I will evaluate more in
>     detail handling quoting/escaping inside extract_arg, by analysing
>     all callers.
>   - fixed (and tested) regression when NAMEREGEXP arg contains spaces.
>   - replaced INFO_PRINT_ARGS_HELP by function info_print_args_help
>     to make this gettext friendly.
>
>   - instead of preg/treg regexp new arguments to iterate_over_block_arg_vars
>     and iterate_over_block_local_vars, have preg/treg being part
>     of the opaque cb_data, and do filtering inside do_print_variable_and_value.
>   - no need anymore to include gdb_regex.h in various files or stack.h.
>   - used preg/treg.has_value() instead of implicit conversion to boolean.
>   - used *reg instead of &reg for an out parameter.
>   - handled language specific type printing using set_language and RAII.
>   - no new line after return type for function declaration.
>  
> * documentation changes:
>   - handled the comments of Eli: rephrase two sentences as one,
>     remove redundant blank before :.
>   - quoting/backslash handling of TYPEREGEXP slightly updated according
>     to the switch to gdb_argv quoting behaviour.
>
>
> Changes between the first RFA and RFAv2:
> ---------------------------------------
> The documentation parts were already reviewed by Eli, other parts
> were not reviewed yet.
> Compared to the first RFA, the changes are a rebase to the last trunk version,
> the removal of an unused local variable, and some updates to the new
> info_qt.exp test to ensure unicity of test names.
>
> Changes between first RFA and  the RFC:
> ---------------------------------------
> * Handled comments of Eli on the documentation.
> * ChangeLog entries added in commit messages
> * Test added.
>
> Thanks.
>
>
> This patch series adds flags and/or arguments
> [-q] [-t TYPEREGEXP] [NAMEREGEXP] to the commands
>   info [args|functions|locals|variables]
>
> The additional arguments allow to more precisely specify what to print.
> As these new features can usefully be combined with frame apply and thread
> apply, the documentation gives examples combining the above
> and the 'thread apply' and 'frame apply' commands.
>
> Some examples:
> * print functions returning an int:
>     info functions -t '^int ('
> * print local variables having pthread_t type
>     info locals -t pthread_t
> * print global variables having type 'struct addrinfo'
>     info var -t 'struct addrinfo'
> * print args that are likely file descriptors
>     info arg -t int .*fd.*
>
> Below examples are combined with the 'thread/frame apply' commands:
>
> * Assuming lock_something_t is an RAII type, show all locks:
>   thread apply all -s frame apply all -s info locals -q -t lock_something_t
>  or shorter equivalent:
>   tfaas i lo -q -t lock_something_t
>
> * show frames and args having an arg with type matchin std::.*map
>   so likely  std::map or std::unordered_map
>   frame apply all -s info args -q std::.*map
>
>
> The code, documentation, NEWS, test and ChangeLog are complete.
>
>
Reply | Threaded
Open this post in threaded view
|

PING^2 Re: [RFAv3 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP]

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

On Sun, 2018-09-23 at 23:42 +0200, Philippe Waroquiers wrote:

> [RFAv3 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP]
>
> RFAv3, handling the comments of Tom and Eli about RFAv2.
> --------------------------------------------------------
> * code changes:
>   - reworked extract_arg_maybe_quoted to have it working the same way
>     as gdb_argv. In another patch series, I will evaluate more in
>     detail handling quoting/escaping inside extract_arg, by analysing
>     all callers.
>   - fixed (and tested) regression when NAMEREGEXP arg contains spaces.
>   - replaced INFO_PRINT_ARGS_HELP by function info_print_args_help
>     to make this gettext friendly.
>
>   - instead of preg/treg regexp new arguments to iterate_over_block_arg_vars
>     and iterate_over_block_local_vars, have preg/treg being part
>     of the opaque cb_data, and do filtering inside do_print_variable_and_value.
>   - no need anymore to include gdb_regex.h in various files or stack.h.
>   - used preg/treg.has_value() instead of implicit conversion to boolean.
>   - used *reg instead of &reg for an out parameter.
>   - handled language specific type printing using set_language and RAII.
>   - no new line after return type for function declaration.
>  
> * documentation changes:
>   - handled the comments of Eli: rephrase two sentences as one,
>     remove redundant blank before :.
>   - quoting/backslash handling of TYPEREGEXP slightly updated according
>     to the switch to gdb_argv quoting behaviour.
>
>
> Changes between the first RFA and RFAv2:
> ---------------------------------------
> The documentation parts were already reviewed by Eli, other parts
> were not reviewed yet.
> Compared to the first RFA, the changes are a rebase to the last trunk version,
> the removal of an unused local variable, and some updates to the new
> info_qt.exp test to ensure unicity of test names.
>
> Changes between first RFA and  the RFC:
> ---------------------------------------
> * Handled comments of Eli on the documentation.
> * ChangeLog entries added in commit messages
> * Test added.
>
> Thanks.
>
>
> This patch series adds flags and/or arguments
> [-q] [-t TYPEREGEXP] [NAMEREGEXP] to the commands
>   info [args|functions|locals|variables]
>
> The additional arguments allow to more precisely specify what to print.
> As these new features can usefully be combined with frame apply and thread
> apply, the documentation gives examples combining the above
> and the 'thread apply' and 'frame apply' commands.
>
> Some examples:
> * print functions returning an int:
>     info functions -t '^int ('
> * print local variables having pthread_t type
>     info locals -t pthread_t
> * print global variables having type 'struct addrinfo'
>     info var -t 'struct addrinfo'
> * print args that are likely file descriptors
>     info arg -t int .*fd.*
>
> Below examples are combined with the 'thread/frame apply' commands:
>
> * Assuming lock_something_t is an RAII type, show all locks:
>   thread apply all -s frame apply all -s info locals -q -t lock_something_t
>  or shorter equivalent:
>   tfaas i lo -q -t lock_something_t
>
> * show frames and args having an arg with type matchin std::.*map
>   so likely  std::map or std::unordered_map
>   frame apply all -s info args -q std::.*map
>
>
> The code, documentation, NEWS, test and ChangeLog are complete.
>
>
Reply | Threaded
Open this post in threaded view
|

PING^3 Re: [RFAv3 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP]

Philippe Waroquiers
In reply to this post by Philippe Waroquiers
Some more comments ?
Thanks
Philippe

On Sun, 2018-09-23 at 23:42 +0200, Philippe Waroquiers wrote:

> [RFAv3 0/5] info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP]
>
> RFAv3, handling the comments of Tom and Eli about RFAv2.
> --------------------------------------------------------
> * code changes:
>   - reworked extract_arg_maybe_quoted to have it working the same way
>     as gdb_argv. In another patch series, I will evaluate more in
>     detail handling quoting/escaping inside extract_arg, by analysing
>     all callers.
>   - fixed (and tested) regression when NAMEREGEXP arg contains spaces.
>   - replaced INFO_PRINT_ARGS_HELP by function info_print_args_help
>     to make this gettext friendly.
>
>   - instead of preg/treg regexp new arguments to iterate_over_block_arg_vars
>     and iterate_over_block_local_vars, have preg/treg being part
>     of the opaque cb_data, and do filtering inside do_print_variable_and_value.
>   - no need anymore to include gdb_regex.h in various files or stack.h.
>   - used preg/treg.has_value() instead of implicit conversion to boolean.
>   - used *reg instead of &reg for an out parameter.
>   - handled language specific type printing using set_language and RAII.
>   - no new line after return type for function declaration.
>  
> * documentation changes:
>   - handled the comments of Eli: rephrase two sentences as one,
>     remove redundant blank before :.
>   - quoting/backslash handling of TYPEREGEXP slightly updated according
>     to the switch to gdb_argv quoting behaviour.
>
>
> Changes between the first RFA and RFAv2:
> ---------------------------------------
> The documentation parts were already reviewed by Eli, other parts
> were not reviewed yet.
> Compared to the first RFA, the changes are a rebase to the last trunk version,
> the removal of an unused local variable, and some updates to the new
> info_qt.exp test to ensure unicity of test names.
>
> Changes between first RFA and  the RFC:
> ---------------------------------------
> * Handled comments of Eli on the documentation.
> * ChangeLog entries added in commit messages
> * Test added.
>
> Thanks.
>
>
> This patch series adds flags and/or arguments
> [-q] [-t TYPEREGEXP] [NAMEREGEXP] to the commands
>   info [args|functions|locals|variables]
>
> The additional arguments allow to more precisely specify what to print.
> As these new features can usefully be combined with frame apply and thread
> apply, the documentation gives examples combining the above
> and the 'thread apply' and 'frame apply' commands.
>
> Some examples:
> * print functions returning an int:
>     info functions -t '^int ('
> * print local variables having pthread_t type
>     info locals -t pthread_t
> * print global variables having type 'struct addrinfo'
>     info var -t 'struct addrinfo'
> * print args that are likely file descriptors
>     info arg -t int .*fd.*
>
> Below examples are combined with the 'thread/frame apply' commands:
>
> * Assuming lock_something_t is an RAII type, show all locks:
>   thread apply all -s frame apply all -s info locals -q -t lock_something_t
>  or shorter equivalent:
>   tfaas i lo -q -t lock_something_t
>
> * show frames and args having an arg with type matchin std::.*map
>   so likely  std::map or std::unordered_map
>   frame apply all -s info args -q std::.*map
>
>
> The code, documentation, NEWS, test and ChangeLog are complete.
>
>
Reply | Threaded
Open this post in threaded view
|

Re: [RFAv3 1/5] New cli-utils.h/.c function extract_info_print_args

Pedro Alves-7
In reply to this post by Philippe Waroquiers
Hi Philippe,

Finally managed to read through the series.  

I have a few comments throughout the series, but nothing very serious.
Probably the next iteration will be good to go.
Apologies for the delay... :-/

On 09/23/2018 10:42 PM, Philippe Waroquiers wrote:

> New cli-utils.h/.c function extract_info_print_args factorises
> the extraction of the args '[-q] [-t TYPEREGEXP] [NAMEREGEXP]'.
>
> This function will be used by the commands
>   info [args|functions|locals|variables]
>
> As this function 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-09-23  Philippe Waroquiers  <[hidden email]>
>
> * cli-utils.c (extract_arg_maybe_quoted): New function.
> (extract_info_print_args): New function.
> (info_print_args_help): New function.
> * cli-utils.h (extract_arg_maybe_quoted): New function.
> (extract_info_print_args): New function.
> (info_print_args_help): New function.
> ---
>  gdb/cli/cli-utils.c | 159 ++++++++++++++++++++++++++++++++++++++++++++
>  gdb/cli/cli-utils.h |  15 +++++
>  2 files changed, 174 insertions(+)
>
> diff --git a/gdb/cli/cli-utils.c b/gdb/cli/cli-utils.c
> index 98b7414991..ea4b4b6f61 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
> @@ -125,6 +127,84 @@ get_number (char **pp)
>    return result;
>  }
>  
> +/* See documentation in cli-utils.h.  */
> +
> +void
> +extract_info_print_args (const char* command,


'*' should lean against "command":

  "const char *command"

It seems like this function has the same issue that
a function in the "frame apply" series had.  Namely,
that it isn't fit for iterative use, so that some command
using it could support other options.  Would it be possible
to adjust this in that direction?

> + const char **args,
> + bool *quiet,
> + std::string *regexp,
> + std::string *t_regexp)
> +{
> +  *quiet = false;
> +  *regexp = "";
> +  *t_regexp = "";
> +
> +  while (*args != NULL)
> +    {
> +      if (check_for_argument (args, "--", 2))
> + {
> +  *args = skip_spaces (*args);
> +  break;
> + }
> +
> +      if (check_for_argument (args, "-t", 2))
> + {
> +  *t_regexp = extract_arg_maybe_quoted (args);
> +  *args = skip_spaces (*args);
> +  continue;
> + }
> +
> +      if (check_for_argument (args, "-q", 2))
> + {
> +  *quiet = true;
> +  *args = skip_spaces (*args);
> +  continue;
> + }
> +
> +      if (**args != '-')
> + break;
> +
> +      std::string option = extract_arg (args);
> +      error (_("Unrecognized option '%s' to %s command.  "
> +       "Try \"help %s\"."), option.c_str (),
> +     command, command);
> +    }
> +
> +  if (*args != NULL && **args != '\000')
> +    *regexp = *args;
> +

Spurious empty line.


> +}
> +
> +/* See documentation in cli-utils.h.  */
> +
> +const char*
> +info_print_args_help (const char* prefix,
> +      const char* entity_kind)

Formatting, space on the left of '*'.

> +{
> +  std::string h;
> +
> +  h = prefix;
> +  h += _("If NAMEREGEXP is provided, only prints the ");
> +  h += entity_kind;
> +  h +=_(" whose name\n\
> +matches NAMEREGEXP.\n\
> +If -t TYPEREGEXP is provided, only prints the ");
> +  h += entity_kind;
> +  h +=_(" 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 ");
> +  h += entity_kind;
> +  h += _(" can be printed.\n\
> +The flag -q disables the production of these headers and messages.");
> +

Building a string in chunks like this is not very i18n-friendly,
because depending on the language, the position of the variables
may differ.  Also, harder for the translator to see how it all
fits together.  It's better to write it all as one string, and
use printf-style parameters.  It's also more readable in the code.
While at it, why return a copy of the string, instead of returning
the std::string directly?

Like so:

std::string
info_print_args_help (const char *prefix,
                      const char *entity_kind)
{
  return string_printf (_("\
%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);
}

Still not perfect, because the different uses of entity_kind
could end up translating differently (e.g., singular vs plural),
but better than before, I think.

> +  return xstrdup (h.c_str ());
> +}
> +
> +
> +
>  /* See documentation in cli-utils.h.  */
>  
>  number_or_range_parser::number_or_range_parser (const char *string)
> @@ -282,6 +362,85 @@ 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)
> +{
> +  int squote = 0;
> +  int dquote = 0;
> +  int bsquote = 0;

Use bool and true/false throughout the function.

> +  std::string result = std::string ();

Just write:

   std::string result;

I'd suggest doing:

 const char *p = *arg;

then work with p throughout the function, and then do
at the end:

 *arg = p;

That would avoid the double '**' throughout.


> +
> +  /* Find the start of the argument.  */
> +  *arg = skip_spaces (*arg);
> +
> +  /* Parse *arg similarly to gdb_argv buildargv function.  */
> +  while (**arg != '\0')
> +    {
> +      if (isspace (**arg) && !squote && !dquote && !bsquote)
> + {
> +  break;
> + }
> +      else
> + {
> +  if (bsquote)
> +    {
> +      bsquote = 0;
> +      result += **arg;
> +    }
> +  else if (**arg == '\\')
> +    {
> +      bsquote = 1;
> +    }
> +  else if (squote)
> +    {
> +      if (**arg == '\'')
> + {
> +  squote = 0;
> + }
> +      else
> + {
> +  result += **arg;
> + }

Drop the curly braces around a single line expression
(throughout):

      if (**arg == '\'')
        squote = 0;
      else
        result += **arg;


> +    }
> +  else if (dquote)
> +    {
> +      if (**arg == '"')
> + {
> +  dquote = 0;
> + }
> +      else
> + {
> +  result += **arg;
> + }
> +    }
> +  else
> +    {
> +      if (**arg == '\'')
> + {
> +  squote = 1;
> + }
> +      else if (**arg == '"')
> + {
> +  dquote = 1;
> + }
> +      else
> + {
> +  result += **arg;
> + }
> +    }
> +  (*arg)++;
> + }
> +    }
> +
> +  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..8ce8db1860 100644
> --- a/gdb/cli/cli-utils.h
> +++ b/gdb/cli/cli-utils.h
> @@ -39,6 +39,21 @@ extern int get_number (const char **);
>  
>  extern int get_number (char **);
>  
> +/* Extract from args the arguments [-q] [-t TYPEREGEXP] [--] NAMEREGEXP.

"from ARGS the"

> +   Only the above flags are accepted.  Any other flag will raise an error.
> +   COMMAND is used to produce the error message if an invalid flag is
> +   given.  */
> +extern void extract_info_print_args (const char* command,

"const char *command"

> +     const char **args,
> +     bool *quiet,
> +     std::string *regexp,
> +     std::string *t_regexp);
> +
> +/* Builds the help string for a command documented by PREFIX,
> +   followed by the extract_info_print_args help for ENTITY_KIND.  */
> +extern const char* info_print_args_help (const char* prefix,
> + const char* entity_kind);

space before *, and not after:

  "const char *info_print_args_help"

> +
>  /* 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
>

Thanks,
Pedro Alves
Reply | Threaded
Open this post in threaded view
|

Re: [RFAv3 2/5] Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables]

Pedro Alves-7
In reply to this post by Philippe Waroquiers
On 09/23/2018 10:42 PM, Philippe Waroquiers wrote:

> @@ -2043,14 +2055,37 @@ 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

Space between comment and function.

> +prepare_reg (const char *regexp, gdb::optional<compiled_regex> *reg)
> +{

> @@ -2121,7 +2173,6 @@ iterate_over_block_arg_vars (const struct block *b,
>       symbol is double and the type of the LOC_LOCAL symbol is
>       float).  There are also LOC_ARG/LOC_REGISTER pairs which
>       are not combined in symbol-reading.  */
> -
>    sym2 = lookup_symbol_search_name (SYMBOL_SEARCH_NAME (sym),
>      b, VAR_DOMAIN).symbol;
>    (*cb) (SYMBOL_PRINT_NAME (sym), sym2, cb_data);

Spurious change?

Really no further comments here.  :-)

Thanks,
Pedro Alves
Reply | Threaded
Open this post in threaded view
|

Re: [RFAv3 3/5] Document changes to info [args|functions|locals|variables]

Pedro Alves-7
In reply to this post by Philippe Waroquiers
A few small suggestions below.

On 09/23/2018 10:42 PM, Philippe Waroquiers wrote:

> Document changes to info [args|functions|locals|variables]
>
> gdb/doc/ChangeLog
> 2018-09-23  Philippe Waroquiers  <[hidden email]>
>
> * 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/gdb.texinfo | 121 +++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 109 insertions(+), 12 deletions(-)
>
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index b5b6089153..cf4ffa2a94 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -7767,15 +7767,73 @@ architectures) that you specify in the @code{frame} command.
>  @xref{Selection, ,Selecting a Frame}.
>  
>  @kindex info args
> -@item info args
> +@item info args [-q]
>  Print the arguments of the selected frame, each on a separate line.
>  
> +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
> +contain a match for regular expression @var{regexp}.

"contain a match for" gave me pause.  I'd suggest saying instead:

  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, contain a match
> +for regular expression @var{type_regexp}.

[....] 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 it matches the two regexps.
> +
>  @item info locals
> -@kindex info locals
> +@kindex info locals [-q]
>  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
> +contain a match for regular expression @var{regexp}.

Likewise.

> +
> +If @var{type_regexp} is provided, print only the local variables whose
> +types, as printed by the @code{whatis} command, contain a match
> +for 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 it matches the two regexps.

Likewise.

> +
> +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

Nice.  Thanks for the example.

> +
>  @end table
>  
>  @node Frame Apply
> @@ -17857,32 +17915,71 @@ 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
> +contain a match for 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, contain a match
> +for 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 are returning
> +an int.

s/are returning an int/return int/

Thanks,
Pedro Alves

> +
> +If both @var{regexp} and @var{type_regexp} are provided, a function
> +is printed only if it matches the two regexps.
> +
> +
>  @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
> +contain a match for regular expression @var{regexp}.
> +
> +If @var{type_regexp} is provided, print only the variables whose
> +types, as printed by the @code{whatis} command, contain a match
> +for 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 it matches the two regexps.
>  
>  @kindex info classes
>  @cindex Objective-C, classes and selectors
>
Reply | Threaded
Open this post in threaded view
|

Re: [RFAv3 5/5] Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP]

Pedro Alves-7
In reply to this post by Philippe Waroquiers
On 09/23/2018 10:42 PM, Philippe Waroquiers wrote:

> Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP]
>
> gdb/testsuite/ChangeLog
> 2018-09-23  Philippe Waroquiers  <[hidden email]>
>
>         * gdb.base/info_qt.c: New file.
>         * gdb.base/info_qt.exp: New file.
> ---
>  gdb/testsuite/gdb.base/info_qt.c   |  81 ++++++++++
>  gdb/testsuite/gdb.base/info_qt.exp | 234 +++++++++++++++++++++++++++++
>  2 files changed, 315 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/gdb.base/info_qt.c b/gdb/testsuite/gdb.base/info_qt.c
> new file mode 100644
> index 0000000000..77c4ea8236
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/info_qt.c
> @@ -0,0 +1,81 @@
> +/* 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/>.  */
> +
> +#include <stdio.h>
> +#include <stdlib.h>

Are these two needed?

> +
> +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..3ece05c5e4
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/info_qt.exp
> @@ -0,0 +1,234 @@
> +# 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 that a macro using backtrace can be applied to all threads
> +# and will continue for each thread even though an error may occur in
> +# backtracing one of the threads.

Err, nope, it does not, that was gdb.threads/threadapply.exp.  :-)

Please remove/update.

> +
> +# Test info [args|functions|locals|variables] [-q] [-t TYPEREGEXP] [NAMEREGEXP]

Add some empty line here.

> +standard_testfile
> +
> +if { [prepare_for_testing "failed to prepare" ${testfile}] } {
> +    return -1
> +}
> +
> +clean_restart ${binfile}
> +
> +if ![runto setup_done] then {
> +    gdb_suppress_tests

We don't use gdb_suppress_tests anymore (for years).  Please
fail/return instead.

> +}
> +set any "\[^\r\n\]*"
> +set ws "\[ \t\]\+"
> +set number "\[0-9]\+"
> +
> +
> +############# test 'info functions'
> +
> +# test simple matching with name regexp

Please write complete sentences starting with uppercase
and ending in a period.  Here and throughout.

> +foreach_with_prefix 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\\\);" \
> +    ] \
> + "info functions info_fun"
> +}
> +
> +# test simple matching with name regexp, but with -q to avoid the first header
> +foreach_with_prefix 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\\\);" \
> +    ] \
> + "info functions -q info_fun"
> +}
> +
> +# test -q and no matching functions
> +foreach_with_prefix cmd {
> +    "info functions -q nowaythiscanmatch"
> +    "info functions -q -- -q" } {
> +    gdb_test $cmd "" "quiet info functions empty output"

This matches any output before the gdb prompt.
Use gdb_test_no_output instead.

> +}
> +
> +# test with a type regexp
> +foreach_with_prefix 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\\\);" \
> +    ] \
> + "info functions -q info_fun"
> +}
> +
> +# test with a non matching type regexp
> +gdb_test "info functions -t ganze_Zahl -q info_fun" "" \
> +    "quiet output info functions non matching type"
> +
> +
> +############# test 'info variables'
> +
> +# test simple matching with name regexp
> +foreach_with_prefix 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;" \
> +    ] \
> + "info functions info_fun"
> +}
> +
> +# test simple matching with name regexp, but with -q to avoid the first header
> +
> +# test -q and no matching variables
> +foreach_with_prefix cmd {
> +    "info variables -q nowaythiscanmatch"
> +    "info variables -q -- -q" } {
> +    gdb_test $cmd "" "quiet info variables empty output"

gdb_test_no_output.

> +}
> +
> +# test with a type regexp
> +foreach_with_prefix 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;" \
> +    ] \
> + "info variables -q -t entier info_fun"
> +}
> +
> +# test with a non matching type regexp
> +gdb_test "info variables -t ganze_Zahl -q info_at" "" \
> +    "quiet output info variables non matching type"

gdb_test_no_output.


> +
> +
> +
> +############# test 'info args' in function setup.
> +
> +gdb_test "frame 1" ".* in setup .*" "set frame 1 for info args"
> +
> +# test name regexp matching all
> +foreach_with_prefix 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" \
> +    ] \
> + "info args"
> +}
> +
> +# test name regexp or type regexp matching some
> +foreach_with_prefix cmd {
> +    "info args -t int"
> +    "info args arg_[ij]"} {
> +    gdb_test $cmd \
> + [multi_line \
> +     "arg_i = 3" \
> +     "arg_j = 4" \
> +    ] \
> + "info args"
> +}

Duplicate test names.  

Consider sing  with_test_prefix to wrap groups of tests.

> +
> +gdb_test "info args nowaythiscanmatch" "No matching arguments." "non matching args"
> +gdb_test "info args -q nowaythiscanmatch" "" "quiet non matching args"
> +gdb_test "info args -q -t entier" "" "quiet non matching args with type"

gdb_test_no_output.

> +
> +############# test 'info locals' in function setup.
> +
> +gdb_test "frame 1" ".* in setup .*" "set frame 1 for info locals"
> +
> +# test name regexp matching all
> +foreach_with_prefix 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" \
> +    ] \
> + "info locals"
> +}
> +
> +# test name regexp or type regexp matching some
> +foreach_with_prefix 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" \
> +    ] \
> + "info args"
> +}

Note duplicate test name.

> +
> +gdb_test "info locals nowaythiscanmatch" "No matching locals." "non matching locals"
> +gdb_test "info locals -q nowaythiscanmatch" "" "quiet non matching locals"
> +gdb_test "info locals -q -t ganze_Zahl loc" "" "quiet non matching locals with type"

These last two match anything.  Use gdb_test_no_output instead.

> +
> +# verify that the rest of the args is taken as a 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"
>

Thanks,
Pedro Alves
Reply | Threaded
Open this post in threaded view
|

Re: [RFAv3 1/5] New cli-utils.h/.c function extract_info_print_args

Philippe Waroquiers
In reply to this post by Pedro Alves-7
On Mon, 2018-10-22 at 15:15 +0100, Pedro Alves wrote:
> Hi Philippe,
>
> Finally managed to read through the series.  
>
> I have a few comments throughout the series, but nothing very serious.
Thanks for the comments, I will submit a new version soon (once I have
double checked I properly handled all the comments).

One question below ...

> +/* See documentation in cli-utils.h.  */
> > +
> > +const char*
> > +info_print_args_help (const char* prefix,
> > +      const char* entity_kind)


> While at it, why return a copy of the string, instead of returning
> the std::string directly?
The returned value is used as argument to add_prefix_cmd,
that expects a char * that must stay valid when the std::string is destroyed.
So, at the call site, I cannot use info_print_args_help (...).c_str (),
as this gives a memory corruption (confirmed by valgrind).
So, I have done:
+const char *
+info_print_args_help (const char *prefix,
+                     const char *entity_kind)
+{
+  /*  Note : this returns a string allocated with xstrdup, as this
+      is typically used as argument to add_prefix_cmd, which needs a
+      string that stays valid after destruction of the std::string.  */
+  return xstrdup
+    (string_printf (_("\
+%sIf NAMEREGEXP is provided, only prints the %s whose name\n   \
....

 Does this sound ok, or is there a better way to do (e.g. at the call site) ?


Thanks

Philippe

Reply | Threaded
Open this post in threaded view
|

Re: [RFAv3 5/5] Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP]

Philippe Waroquiers
In reply to this post by Pedro Alves-7
On Mon, 2018-10-22 at 15:18 +0100, Pedro Alves wrote:
> On 09/23/2018 10:42 PM, Philippe Waroquiers wrote:

> > +############# test 'info args' in function setup.
> > +
> > +gdb_test "frame 1" ".* in setup .*" "set frame 1 for info args"
> > +
> > +# test name regexp matching all
> > +foreach_with_prefix 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" \
> > +    ] \
> > + "info args"
> > +}
> > +
> > +# test name regexp or type regexp matching some
> > +foreach_with_prefix cmd {
> > +    "info args -t int"
> > +    "info args arg_[ij]"} {
> > +    gdb_test $cmd \
> > + [multi_line \
> > +     "arg_i = 3" \
> > +     "arg_j = 4" \
> > +    ] \
> > + "info args"
> > +}
>
> Duplicate test names.  
>
> Consider sing  with_test_prefix to wrap groups of tests.

Doing
  make check RUNTESTFLAGS="gdb.base/info_qt.exp"
  cat gdb/testsuite/gdb.sum | grep "PASS" | sort | uniq -c | sort -n
shows only unique test names (thanks to foreach_with_prefix I think).

Is the 'with_test_prefix' aimed at removing duplication ?
Or is it to have 4 groups wrapping together all the tests of
   'info var'
   'info local'
   'info functions'
   'info args'
?

Thanks

Philippe


Reply | Threaded
Open this post in threaded view
|

Re: [RFAv3 1/5] New cli-utils.h/.c function extract_info_print_args

Pedro Alves-7
In reply to this post by Philippe Waroquiers
On 10/23/2018 10:59 PM, Philippe Waroquiers wrote:
> On Mon, 2018-10-22 at 15:15 +0100, Pedro Alves wrote:

>> +/* See documentation in cli-utils.h.  */
>>> +
>>> +const char*
>>> +info_print_args_help (const char* prefix,
>>> +      const char* entity_kind)
>
>
>> While at it, why return a copy of the string, instead of returning
>> the std::string directly?
> The returned value is used as argument to add_prefix_cmd,
> that expects a char * that must stay valid when the std::string is destroyed.
> So, at the call site, I cannot use info_print_args_help (...).c_str (),
> as this gives a memory corruption (confirmed by valgrind).

Ah.

> So, I have done:
> +const char *
> +info_print_args_help (const char *prefix,
> +                     const char *entity_kind)
> +{
> +  /*  Note : this returns a string allocated with xstrdup, as this
> +      is typically used as argument to add_prefix_cmd, which needs a
> +      string that stays valid after destruction of the std::string.  */
> +  return xstrdup
> +    (string_printf (_("\
> +%sIf NAMEREGEXP is provided, only prints the %s whose name\n   \
> ....
>
>  Does this sound ok, or is there a better way to do (e.g. at the call site) ?

Keep the function's interface, but use xstrprintf instead
of 'xstrdup + string_printf' then.

Thanks,
Pedro Alves
Reply | Threaded
Open this post in threaded view
|

Re: [RFAv3 5/5] Add a test case for info args|functions|locals|variables [-q] [-t TYPEREGEXP] [NAMEREGEXP]

Pedro Alves-7
In reply to this post by Philippe Waroquiers
On 10/23/2018 11:05 PM, Philippe Waroquiers wrote:

> On Mon, 2018-10-22 at 15:18 +0100, Pedro Alves wrote:
>> On 09/23/2018 10:42 PM, Philippe Waroquiers wrote:
>
>>> +############# test 'info args' in function setup.
>>> +
>>> +gdb_test "frame 1" ".* in setup .*" "set frame 1 for info args"
>>> +
>>> +# test name regexp matching all
>>> +foreach_with_prefix 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" \
>>> +    ] \
>>> + "info args"
>>> +}
>>> +
>>> +# test name regexp or type regexp matching some
>>> +foreach_with_prefix cmd {
>>> +    "info args -t int"
>>> +    "info args arg_[ij]"} {
>>> +    gdb_test $cmd \
>>> + [multi_line \
>>> +     "arg_i = 3" \
>>> +     "arg_j = 4" \
>>> +    ] \
>>> + "info args"
>>> +}
>>
>> Duplicate test names.  
>>
>> Consider sing  with_test_prefix to wrap groups of tests.
>
> Doing
>   make check RUNTESTFLAGS="gdb.base/info_qt.exp"
>   cat gdb/testsuite/gdb.sum | grep "PASS" | sort | uniq -c | sort -n
> shows only unique test names (thanks to foreach_with_prefix I think).
>

Ah, sorry, wasn't thinking / missed the foreach_with_prefix.

> Is the 'with_test_prefix' aimed at removing duplication ?
> Or is it to have 4 groups wrapping together all the tests of
>    'info var'
>    'info local'
>    'info functions'
>    'info args'
> ?
Yeah, it was kind of both.

You could use it to group parts of the testcase, like,
where you had:

 ############# test 'info args' in function setup.

You could wrap the related tests with with_test_prefix:

 # Test 'info args' in function setup.
 with_test_prefix "'info args' func setup" {
   ....

Then you don't need to add "for info args" "for info locals", etc.
to specific test names.


Also, with:

 # Test name regexp matching all.
 foreach_with_prefix 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" \
            ] \
        "info args"
 }

I take it you end up getting output like:

 cmd=info args: info args
 cmd=info args arg_: info args
 cmd=info args g: info args
 cmd=info args -- .*: info args

But if you wrote it like this instead:

 # Test name regexp matching all.
 with_test_prefix "name regexp matching all" {
   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" \
            ]
  }
 }

You'd get:

 name regexp matching all: info args
 name regexp matching all: info args arg_
 name regexp matching all: info args g
 name regexp matching all: info args -- .*

Which I'd think results in clearer grouping in the gdb.sum file?

Thanks,
Pedro Alves