Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables]
authorPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Sun, 1 Jul 2018 20:56:56 +0000 (22:56 +0200)
committerPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Sat, 27 Oct 2018 11:47:45 +0000 (13:47 +0200)
Add [-q] [-t TYPEREGEXP] [NAMEREGEXP] args to info [args|functions|locals|variables]

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

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

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

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

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

* stack.c (print_variable_and_value_data): Add preg and treg.
(print_frame_local_vars): Add quiet, regexp and t_regexp arguments,
and update callers.
(print_frame_arg_vars): Likewise.
(prepare_reg): New function.
(info_locals_command): Extract info print args and use them.
(info_args_command): Likewise.
(_initialize_stack): Modify on-line help.
* symtab.c (treg_matches_sym_type_name): New function.
(search_symbols): New arg t_regexp.
(symtab_symbol_info): New args quiet, regexp, t_regexp.
(info_variables_command): Extract info print args and use them.
(info_functions_command): Likewise.
(info_types_command): Update call to symtab_symbol_info.
(_initialize_symtab): Modify on-line help.
* symtab.h (treg_matches_sym_type_name): New function.
(search_symbols): New t_regexp arg.

gdb/ChangeLog
gdb/python/python.c
gdb/stack.c
gdb/symtab.c
gdb/symtab.h

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