gdb: Convert frame_show_address to return a bool
[deliverable/binutils-gdb.git] / gdb / stack.c
index f7df7a40d10e6140e4bbd2da68c0daef9461ccd7..5af00c708e45eb6d21f9a21fd5e2d6da6c7912de 100644 (file)
@@ -54,6 +54,7 @@
 #include "observable.h"
 #include "gdbsupport/def-vector.h"
 #include "cli/cli-option.h"
+#include "cli/cli-style.h"
 
 /* The possible choices of "set print frame-arguments", and the value
    of this setting.  */
 const char print_frame_arguments_all[] = "all";
 const char print_frame_arguments_scalars[] = "scalars";
 const char print_frame_arguments_none[] = "none";
+const char print_frame_arguments_presence[] = "presence";
 
 static const char *const print_frame_arguments_choices[] =
 {
   print_frame_arguments_all,
   print_frame_arguments_scalars,
   print_frame_arguments_none,
+  print_frame_arguments_presence,
   NULL
 };
 
+/* The possible choices of "set print frame-info", and the value
+   of this setting.  */
+
+const char print_frame_info_auto[] = "auto";
+const char print_frame_info_source_line[] = "source-line";
+const char print_frame_info_location[] = "location";
+const char print_frame_info_source_and_location[] = "source-and-location";
+const char print_frame_info_location_and_address[] = "location-and-address";
+const char print_frame_info_short_location[] = "short-location";
+
+static const char *const print_frame_info_choices[] =
+{
+  print_frame_info_auto,
+  print_frame_info_source_line,
+  print_frame_info_location,
+  print_frame_info_source_and_location,
+  print_frame_info_location_and_address,
+  print_frame_info_short_location,
+  NULL
+};
+
+/* print_frame_info_print_what[i] maps a choice to the corresponding
+   print_what enum.  */
+static const gdb::optional<enum print_what> print_frame_info_print_what[] =
+  {{}, /* Empty value for "auto".  */
+   SRC_LINE, LOCATION, SRC_AND_LOC, LOC_AND_ADDRESS, SHORT_LOCATION};
+
 /* The possible choices of "set print entry-values", and the value
    of this setting.  */
 
@@ -110,8 +140,8 @@ static const gdb::option::option_def frame_print_option_defs[] = {
     print_entry_values_choices,
     [] (frame_print_options *opt) { return &opt->print_entry_values; },
     NULL, /* show_cmd_cb */
-    N_("Set printing of function arguments at function entry"),
-    N_("Show printing of function arguments at function entry"),
+    N_("Set printing of function arguments at function entry."),
+    N_("Show printing of function arguments at function entry."),
     N_("GDB can sometimes determine the values of function arguments at entry,\n\
 in addition to their current values.  This option tells GDB whether\n\
 to print the current value, the value at entry (marked as val@entry),\n\
@@ -123,8 +153,8 @@ or both.  Note that one or both of these values may be <optimized out>."),
     print_frame_arguments_choices,
     [] (frame_print_options *opt) { return &opt->print_frame_arguments; },
     NULL, /* show_cmd_cb */
-    N_("Set printing of non-scalar frame arguments"),
-    N_("Show printing of non-scalar frame arguments"),
+    N_("Set printing of non-scalar frame arguments."),
+    N_("Show printing of non-scalar frame arguments."),
     NULL /* help_doc */
   },
 
@@ -137,15 +167,26 @@ or both.  Note that one or both of these values may be <optimized out>."),
     N_("If set, frame arguments are printed in raw form, bypassing any\n\
 pretty-printers for that value.")
   },
+
+  enum_option_def {
+    "frame-info",
+    print_frame_info_choices,
+    [] (frame_print_options *opt) { return &opt->print_frame_info; },
+    NULL, /* show_cmd_cb */
+    N_("Set printing of frame information."),
+    N_("Show printing of frame information."),
+    NULL /* help_doc */
+  }
+
 };
 
 /* Options for the "backtrace" command.  */
 
 struct backtrace_cmd_options
 {
-  int full = 0;
-  int no_filters = 0;
-  int hide = 0;
+  bool full = false;
+  bool no_filters = false;
+  bool hide = false;
 };
 
 using bt_flag_option_def
@@ -209,10 +250,9 @@ static struct symtab *last_displayed_symtab = 0;
 static int last_displayed_line = 0;
 \f
 
-/* Return 1 if we should display the address in addition to the location,
-   because we are in the middle of a statement.  */
+/* See stack.h.  */
 
-static int
+bool
 frame_show_address (struct frame_info *frame,
                    struct symtab_and_line sal)
 {
@@ -227,7 +267,7 @@ frame_show_address (struct frame_info *frame,
        gdb_assert (inline_skipped_frames (inferior_thread ()) > 0);
       else
        gdb_assert (get_frame_type (get_next_frame (frame)) == INLINE_FRAME);
-      return 0;
+      return false;
     }
 
   return get_frame_pc (frame) != sal.pc;
@@ -257,7 +297,7 @@ print_stack_frame (struct frame_info *frame, int print_level,
                   int set_current_sal)
 {
 
-  /* For mi, alway print location and address.  */
+  /* For mi, always print location and address.  */
   if (current_uiout->is_mi_like_p ())
     print_what = LOC_AND_ADDRESS;
 
@@ -309,7 +349,7 @@ print_frame_nameless_args (struct frame_info *frame, long start, int num,
    read in.
 
    Errors are printed as if they would be the parameter value.  Use zeroed ARG
-   iff it should not be printed accoring to user settings.  */
+   iff it should not be printed according to user settings.  */
 
 static void
 print_frame_arg (const frame_print_options &fp_opts,
@@ -342,16 +382,20 @@ print_frame_arg (const frame_print_options &fp_opts,
   if (arg->entry_kind == print_entry_values_only
       || arg->entry_kind == print_entry_values_compact)
     stb.puts ("@entry");
-  uiout->field_stream ("name", stb, ui_out_style_kind::VARIABLE);
+  uiout->field_stream ("name", stb, variable_name_style.style ());
   annotate_arg_name_end ();
   uiout->text ("=");
 
+  ui_file_style style;
   if (!arg->val && !arg->error)
     uiout->text ("...");
   else
     {
       if (arg->error)
-       stb.printf (_("<error reading variable: %s>"), arg->error);
+       {
+         stb.printf (_("<error reading variable: %s>"), arg->error.get ());
+         style = metadata_style.style ();
+       }
       else
        {
          try
@@ -388,11 +432,12 @@ print_frame_arg (const frame_print_options &fp_opts,
            {
              stb.printf (_("<error reading variable: %s>"),
                          except.what ());
+             style = metadata_style.style ();
            }
        }
     }
 
-  uiout->field_stream ("value", stb);
+  uiout->field_stream ("value", stb, style);
 }
 
 /* Read in inferior function local SYM at FRAME into ARGP.  Caller is
@@ -413,13 +458,12 @@ read_frame_local (struct symbol *sym, struct frame_info *frame,
     }
   catch (const gdb_exception_error &except)
     {
-      argp->error = xstrdup (except.what ());
+      argp->error.reset (xstrdup (except.what ()));
     }
 }
 
-/* Read in inferior function parameter SYM at FRAME into ARGP.  Caller is
-   responsible for xfree of ARGP->ERROR.  This function never throws an
-   exception.  */
+/* Read in inferior function parameter SYM at FRAME into ARGP.  This
+   function never throws an exception.  */
 
 void
 read_frame_arg (const frame_print_options &fp_opts,
@@ -587,7 +631,7 @@ read_frame_arg (const frame_print_options &fp_opts,
 
   argp->sym = sym;
   argp->val = val;
-  argp->error = val_error ? xstrdup (val_error) : NULL;
+  argp->error.reset (val_error ? xstrdup (val_error) : NULL);
   if (!val && !val_error)
     argp->entry_kind = print_entry_values_only;
   else if ((fp_opts.print_entry_values == print_entry_values_compact
@@ -602,7 +646,7 @@ read_frame_arg (const frame_print_options &fp_opts,
 
   entryargp->sym = sym;
   entryargp->val = entryval;
-  entryargp->error = entryval_error ? xstrdup (entryval_error) : NULL;
+  entryargp->error.reset (entryval_error ? xstrdup (entryval_error) : NULL);
   if (!entryval && !entryval_error)
     entryargp->entry_kind = print_entry_values_no;
   else
@@ -631,9 +675,14 @@ print_frame_args (const frame_print_options &fp_opts,
   long highest_offset = -1;
   /* Number of ints of arguments that we have printed so far.  */
   int args_printed = 0;
+  /* True if we should print arg names.  If false, we only indicate
+     the presence of arguments by printing ellipsis.  */
+  bool print_names
+    = fp_opts.print_frame_arguments != print_frame_arguments_presence;
   /* True if we should print arguments, false otherwise.  */
   bool print_args
-    = fp_opts.print_frame_arguments != print_frame_arguments_none;
+    = (print_names
+       && fp_opts.print_frame_arguments != print_frame_arguments_none);
 
   if (func)
     {
@@ -653,6 +702,13 @@ print_frame_args (const frame_print_options &fp_opts,
          if (!SYMBOL_IS_ARGUMENT (sym))
            continue;
 
+         if (!print_names)
+           {
+             uiout->text ("...");
+             first = 0;
+             break;
+           }
+
          switch (SYMBOL_CLASS (sym))
            {
            case LOC_ARG:
@@ -759,10 +815,8 @@ print_frame_args (const frame_print_options &fp_opts,
 
          if (!print_args)
            {
-             memset (&arg, 0, sizeof (arg));
              arg.sym = sym;
              arg.entry_kind = print_entry_values_no;
-             memset (&entryarg, 0, sizeof (entryarg));
              entryarg.sym = sym;
              entryarg.entry_kind = print_entry_values_no;
            }
@@ -783,9 +837,6 @@ print_frame_args (const frame_print_options &fp_opts,
              print_frame_arg (fp_opts, &entryarg);
            }
 
-         xfree (arg.error);
-         xfree (entryarg.error);
-
          first = 0;
        }
     }
@@ -801,8 +852,11 @@ print_frame_args (const frame_print_options &fp_opts,
       else
        start = highest_offset;
 
-      print_frame_nameless_args (frame, start, num - args_printed,
-                                first, stream);
+      if (!print_names && !first && num > 0)
+       uiout->text ("...");
+      else
+       print_frame_nameless_args (frame, start, num - args_printed,
+                                  first, stream);
     }
 }
 
@@ -859,13 +913,54 @@ do_gdb_disassembly (struct gdbarch *gdbarch,
     }
 }
 
+/* Converts the PRINT_FRAME_INFO choice to an optional enum print_what.
+   Value not present indicates to the caller to use default values
+   specific to the command being executed.  */
+
+static gdb::optional<enum print_what>
+print_frame_info_to_print_what (const char *print_frame_info)
+{
+  for (int i = 0; print_frame_info_choices[i] != NULL; i++)
+    if (print_frame_info == print_frame_info_choices[i])
+      return print_frame_info_print_what[i];
+
+  internal_error (__FILE__, __LINE__,
+                 "Unexpected print frame-info value `%s'.",
+                 print_frame_info);
+}
+
+/* Print the PC from FRAME, plus any flags, to UIOUT.  */
+
+static void
+print_pc (struct ui_out *uiout, struct gdbarch *gdbarch, frame_info *frame,
+         CORE_ADDR pc)
+{
+  uiout->field_core_addr ("addr", gdbarch, pc);
+
+  std::string flags = gdbarch_get_pc_address_flags (gdbarch, frame, pc);
+  if (!flags.empty ())
+  {
+    uiout->text (" [");
+    uiout->field_string ("addr_flags", flags);
+    uiout->text ("]");
+  }
+}
+
+/* See stack.h.  */
+
+void
+get_user_print_what_frame_info (gdb::optional<enum print_what> *what)
+{
+  *what
+    = print_frame_info_to_print_what
+        (user_frame_print_options.print_frame_info);
+}
+
 /* Print information about frame FRAME.  The output is format according
-   to PRINT_LEVEL and PRINT_WHAT and PRINT_ARGS.  The meaning of
-   PRINT_WHAT is:
-   
-   SRC_LINE: Print only source line.
-   LOCATION: Print only location.
-   SRC_AND_LOC: Print location and source line.
+   to PRINT_LEVEL and PRINT_WHAT and PRINT_ARGS.  For the meaning of
+   PRINT_WHAT, see enum print_what comments in frame.h.
+   Note that PRINT_WHAT is overridden if FP_OPTS.print_frame_info
+   != print_frame_info_auto.
 
    Used in "where" output, and to emit breakpoint or step
    messages.  */
@@ -881,6 +976,13 @@ print_frame_info (const frame_print_options &fp_opts,
   int location_print;
   struct ui_out *uiout = current_uiout;
 
+  if (!current_uiout->is_mi_like_p ()
+      && fp_opts.print_frame_info != print_frame_info_auto)
+    {
+      /* Use the specific frame information desired by the user.  */
+      print_what = *print_frame_info_to_print_what (fp_opts.print_frame_info);
+    }
+
   if (get_frame_type (frame) == DUMMY_FRAME
       || get_frame_type (frame) == SIGTRAMP_FRAME
       || get_frame_type (frame) == ARCH_FRAME)
@@ -895,14 +997,13 @@ print_frame_info (const frame_print_options &fp_opts,
       if (print_level)
         {
           uiout->text ("#");
-          uiout->field_fmt_int (2, ui_left, "level",
-                               frame_relative_level (frame));
+          uiout->field_fmt_signed (2, ui_left, "level",
+                                  frame_relative_level (frame));
         }
       if (uiout->is_mi_like_p ())
         {
           annotate_frame_address ();
-          uiout->field_core_addr ("addr",
-                                 gdbarch, get_frame_pc (frame));
+         print_pc (uiout, gdbarch, frame, get_frame_pc (frame));
           annotate_frame_address_end ();
         }
 
@@ -910,18 +1011,18 @@ print_frame_info (const frame_print_options &fp_opts,
         {
           annotate_function_call ();
           uiout->field_string ("func", "<function called from gdb>",
-                              ui_out_style_kind::FUNCTION);
+                              metadata_style.style ());
        }
       else if (get_frame_type (frame) == SIGTRAMP_FRAME)
         {
          annotate_signal_handler_caller ();
           uiout->field_string ("func", "<signal handler called>",
-                              ui_out_style_kind::FUNCTION);
+                              metadata_style.style ());
         }
       else if (get_frame_type (frame) == ARCH_FRAME)
         {
           uiout->field_string ("func", "<cross-architecture call>",
-                              ui_out_style_kind::FUNCTION);
+                              metadata_style.style ());
        }
       uiout->text ("\n");
       annotate_frame_end ();
@@ -944,10 +1045,10 @@ print_frame_info (const frame_print_options &fp_opts,
      to get the line containing FRAME->pc.  */
   symtab_and_line sal = find_frame_sal (frame);
 
-  location_print = (print_what == LOCATION 
+  location_print = (print_what == LOCATION
+                   || print_what == SRC_AND_LOC
                    || print_what == LOC_AND_ADDRESS
-                   || print_what == SRC_AND_LOC);
-
+                   || print_what == SHORT_LOCATION);
   if (location_print || !sal.symtab)
     print_frame (fp_opts, frame, print_level, print_what, print_args, sal);
 
@@ -986,8 +1087,7 @@ print_frame_info (const frame_print_options &fp_opts,
             ability to decide for themselves if it is desired.  */
          if (opts.addressprint && mid_statement)
            {
-             uiout->field_core_addr ("addr",
-                                     gdbarch, get_frame_pc (frame));
+             print_pc (uiout, gdbarch, frame, get_frame_pc (frame));
              uiout->text ("\t");
            }
 
@@ -1135,66 +1235,25 @@ find_frame_funname (struct frame_info *frame, enum language *funlang,
   func = get_frame_function (frame);
   if (func)
     {
-      /* In certain pathological cases, the symtabs give the wrong
-         function (when we are in the first function in a file which
-         is compiled without debugging symbols, the previous function
-         is compiled with debugging symbols, and the "foo.o" symbol
-         that is supposed to tell us where the file with debugging
-         symbols ends has been truncated by ar because it is longer
-         than 15 characters).  This also occurs if the user uses asm()
-         to create a function but not stabs for it (in a file compiled
-         with -g).
-
-         So look in the minimal symbol tables as well, and if it comes
-         up with a larger address for the function use that instead.
-         I don't think this can ever cause any problems; there
-         shouldn't be any minimal symbols in the middle of a function;
-         if this is ever changed many parts of GDB will need to be
-         changed (and we'll create a find_pc_minimal_function or some
-         such).  */
+      const char *print_name = SYMBOL_PRINT_NAME (func);
 
-      struct bound_minimal_symbol msymbol;
-
-      /* Don't attempt to do this for inlined functions, which do not
-        have a corresponding minimal symbol.  */
-      if (!block_inlined_p (SYMBOL_BLOCK_VALUE (func)))
-       msymbol
-         = lookup_minimal_symbol_by_pc (get_frame_address_in_block (frame));
-      else
-       memset (&msymbol, 0, sizeof (msymbol));
-
-      if (msymbol.minsym != NULL
-         && (BMSYMBOL_VALUE_ADDRESS (msymbol)
-             > BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (func))))
+      *funlang = SYMBOL_LANGUAGE (func);
+      if (funcp)
+       *funcp = func;
+      if (*funlang == language_cplus)
        {
-         /* We also don't know anything about the function besides
-            its address and name.  */
-         func = 0;
-         funname.reset (xstrdup (MSYMBOL_PRINT_NAME (msymbol.minsym)));
-         *funlang = MSYMBOL_LANGUAGE (msymbol.minsym);
+         /* It seems appropriate to use SYMBOL_PRINT_NAME() here,
+            to display the demangled name that we already have
+            stored in the symbol table, but we stored a version
+            with DMGL_PARAMS turned on, and here we don't want to
+            display parameters.  So remove the parameters.  */
+         funname = cp_remove_params (print_name);
        }
-      else
-       {
-         const char *print_name = SYMBOL_PRINT_NAME (func);
 
-         *funlang = SYMBOL_LANGUAGE (func);
-         if (funcp)
-           *funcp = func;
-         if (*funlang == language_cplus)
-           {
-             /* It seems appropriate to use SYMBOL_PRINT_NAME() here,
-                to display the demangled name that we already have
-                stored in the symbol table, but we stored a version
-                with DMGL_PARAMS turned on, and here we don't want to
-                display parameters.  So remove the parameters.  */
-             funname = cp_remove_params (print_name);
-           }
-
-         /* If we didn't hit the C++ case above, set *funname
-            here.  */
-         if (funname == NULL)
-           funname.reset (xstrdup (print_name));
-       }
+      /* If we didn't hit the C++ case above, set *funname
+        here.  */
+      if (funname == NULL)
+       funname.reset (xstrdup (print_name));
     }
   else
     {
@@ -1243,8 +1302,8 @@ print_frame (const frame_print_options &fp_opts,
     if (print_level)
       {
        uiout->text ("#");
-       uiout->field_fmt_int (2, ui_left, "level",
-                             frame_relative_level (frame));
+       uiout->field_fmt_signed (2, ui_left, "level",
+                                frame_relative_level (frame));
       }
     get_user_print_options (&opts);
     if (opts.addressprint)
@@ -1254,10 +1313,10 @@ print_frame (const frame_print_options &fp_opts,
        {
          annotate_frame_address ();
          if (pc_p)
-           uiout->field_core_addr ("addr", gdbarch, pc);
+           print_pc (uiout, gdbarch, frame, pc);
          else
            uiout->field_string ("addr", "<unavailable>",
-                                ui_out_style_kind::ADDRESS);
+                                metadata_style.style ());
          annotate_frame_address_end ();
          uiout->text (" in ");
        }
@@ -1266,7 +1325,7 @@ print_frame (const frame_print_options &fp_opts,
     string_file stb;
     fprintf_symbol_filtered (&stb, funname ? funname.get () : "??",
                             funlang, DMGL_ANSI);
-    uiout->field_stream ("func", stb, ui_out_style_kind::FUNCTION);
+    uiout->field_stream ("func", stb, function_name_style.style ());
     uiout->wrap_hint ("   ");
     annotate_frame_args ();
 
@@ -1299,7 +1358,7 @@ print_frame (const frame_print_options &fp_opts,
        QUIT;
       }
     uiout->text (")");
-    if (sal.symtab)
+    if (print_what != SHORT_LOCATION && sal.symtab)
       {
        const char *filename_display;
       
@@ -1308,7 +1367,8 @@ print_frame (const frame_print_options &fp_opts,
        uiout->wrap_hint ("   ");
        uiout->text (" at ");
        annotate_frame_source_file ();
-       uiout->field_string ("file", filename_display, ui_out_style_kind::FILE);
+       uiout->field_string ("file", filename_display,
+                            file_name_style.style ());
        if (uiout->is_mi_like_p ())
          {
            const char *fullname = symtab_to_fullname (sal.symtab);
@@ -1318,11 +1378,12 @@ print_frame (const frame_print_options &fp_opts,
        annotate_frame_source_file_end ();
        uiout->text (":");
        annotate_frame_source_line ();
-       uiout->field_int ("line", sal.line);
+       uiout->field_signed ("line", sal.line);
        annotate_frame_source_end ();
       }
 
-    if (pc_p && (funname == NULL || sal.symtab == NULL))
+    if (print_what != SHORT_LOCATION
+       && pc_p && (funname == NULL || sal.symtab == NULL))
       {
        char *lib = solib_name_from_address (get_frame_program_space (frame),
                                             get_frame_pc (frame));
@@ -1332,7 +1393,7 @@ print_frame (const frame_print_options &fp_opts,
            annotate_frame_where ();
            uiout->wrap_hint ("  ");
            uiout->text (" from ");
-           uiout->field_string ("from", lib);
+           uiout->field_string ("from", lib, file_name_style.style ());
          }
       }
     if (uiout->is_mi_like_p ())
@@ -1452,7 +1513,7 @@ info_frame_command_core (struct frame_info *fi, bool selected_frame_p)
   if (frame_pc_p)
     fputs_filtered (paddress (gdbarch, get_frame_pc (fi)), gdb_stdout);
   else
-    fputs_filtered ("<unavailable>", gdb_stdout);
+    fputs_styled ("<unavailable>", metadata_style.style (), gdb_stdout);
 
   wrap_here ("   ");
   if (funname)
@@ -1463,8 +1524,11 @@ info_frame_command_core (struct frame_info *fi, bool selected_frame_p)
     }
   wrap_here ("   ");
   if (sal.symtab)
-    printf_filtered (" (%s:%d)", symtab_to_filename_for_display (sal.symtab),
-                    sal.line);
+    printf_filtered
+      (" (%ps:%d)",
+       styled_string (file_name_style.style (),
+                     symtab_to_filename_for_display (sal.symtab)),
+       sal.line);
   puts_filtered ("; ");
   wrap_here ("    ");
   printf_filtered ("saved %s = ", pc_regname);
@@ -1489,8 +1553,9 @@ info_frame_command_core (struct frame_info *fi, bool selected_frame_p)
              val_print_not_saved (gdb_stdout);
              break;
            default:
-             fprintf_filtered (gdb_stdout, _("<error: %s>"),
-                               ex.what ());
+             fprintf_styled (gdb_stdout, metadata_style.style (),
+                             _("<error: %s>"),
+                             ex.what ());
              break;
            }
        }
@@ -1932,8 +1997,12 @@ backtrace_command_1 (const frame_print_options &fp_opts,
        arg_type = CLI_SCALAR_VALUES;
       else if (fp_opts.print_frame_arguments == print_frame_arguments_all)
        arg_type = CLI_ALL_VALUES;
-      else
+      else if (fp_opts.print_frame_arguments == print_frame_arguments_presence)
+       arg_type = CLI_PRESENCE;
+      else if (fp_opts.print_frame_arguments == print_frame_arguments_none)
        arg_type = NO_VALUES;
+      else
+       gdb_assert (0);
 
       result = apply_ext_lang_frame_filter (get_current_frame (), flags,
                                            arg_type, current_uiout,
@@ -2359,24 +2428,79 @@ print_frame_local_vars (struct frame_info *frame,
     }
 }
 
-void
-info_locals_command (const char *args, int from_tty)
+/* Structure to hold the values of the options used by the 'info
+   variables' command and other similar commands.  These correspond to the
+   -q and -t options.  */
+
+struct info_print_options
 {
-  std::string regexp;
-  std::string t_regexp;
   bool quiet = false;
+  char *type_regexp = nullptr;
+
+  ~info_print_options ()
+  {
+    xfree (type_regexp);
+  }
+};
+
+/* The options used by the 'info locals' and 'info args' commands.  */
+
+static const gdb::option::option_def info_print_options_defs[] = {
+  gdb::option::boolean_option_def<info_print_options> {
+    "q",
+    [] (info_print_options *opt) { return &opt->quiet; },
+    nullptr, /* show_cmd_cb */
+    nullptr /* set_doc */
+  },
+
+  gdb::option::string_option_def<info_print_options> {
+    "t",
+    [] (info_print_options *opt) { return &opt->type_regexp; },
+    nullptr, /* show_cmd_cb */
+    nullptr /* set_doc */
+  }
+};
 
-  while (args != NULL
-        && extract_info_print_args (&args, &quiet, &regexp, &t_regexp))
-    ;
+/* Returns the option group used by 'info locals' and 'info args'
+   commands.  */
 
-  if (args != NULL)
-    report_unrecognized_option_error ("info locals", args);
+static gdb::option::option_def_group
+make_info_print_options_def_group (info_print_options *opts)
+{
+  return {{info_print_options_defs}, opts};
+}
+
+/* Command completer for 'info locals' and 'info args'.  */
+
+static void
+info_print_command_completer (struct cmd_list_element *ignore,
+                             completion_tracker &tracker,
+                             const char *text, const char * /* word */)
+{
+  const auto group
+    = make_info_print_options_def_group (nullptr);
+  if (gdb::option::complete_options
+      (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
+    return;
+
+  const char *word = advance_to_expression_complete_word_point (tracker, text);
+  symbol_completer (ignore, tracker, text, word);
+}
+
+/* Implement the 'info locals' command.  */
+
+void
+info_locals_command (const char *args, int from_tty)
+{
+  info_print_options opts;
+  auto grp = make_info_print_options_def_group (&opts);
+  gdb::option::process_options
+    (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
+  if (args != nullptr && *args == '\0')
+    args = nullptr;
 
   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 (),
+                         opts.quiet, args, opts.type_regexp,
                          0, gdb_stdout);
 }
 
@@ -2474,26 +2598,20 @@ print_frame_arg_vars (struct frame_info *frame,
     }
 }
 
+/* Implement the 'info args' command.  */
+
 void
 info_args_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 args", args);
-
+  info_print_options opts;
+  auto grp = make_info_print_options_def_group (&opts);
+  gdb::option::process_options
+    (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
+  if (args != nullptr && *args == '\0')
+    args = nullptr;
 
   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);
+                       opts.quiet, args, opts.type_regexp, gdb_stdout);
 }
 \f
 /* Return the symbol-block in which the selected frame is executing.
@@ -3244,7 +3362,7 @@ Options:\n\
   const auto frame_apply_opts
     = make_frame_apply_options_def_group (nullptr, nullptr);
 
-  static std::string frame_apply_cmd_help = gdb::option::build_help (N_("\
+  static std::string frame_apply_cmd_help = gdb::option::build_help (_("\
 Apply a command to a number of frames.\n\
 Usage: frame apply COUNT [OPTION]... COMMAND\n\
 With a negative COUNT argument, applies the command on outermost -COUNT frames.\n"
@@ -3257,7 +3375,7 @@ With a negative COUNT argument, applies the command on outermost -COUNT frames.\
                        &frame_cmd_list);
   set_cmd_completer_handle_brkchars (cmd, frame_apply_cmd_completer);
 
-  static std::string frame_apply_all_cmd_help = gdb::option::build_help (N_("\
+  static std::string frame_apply_all_cmd_help = gdb::option::build_help (_("\
 Apply a command to all frames.\n\
 \n\
 Usage: frame apply all [OPTION]... COMMAND\n"
@@ -3269,7 +3387,7 @@ Usage: frame apply all [OPTION]... COMMAND\n"
                 &frame_apply_cmd_list);
   set_cmd_completer_handle_brkchars (cmd, frame_apply_all_cmd_completer);
 
-  static std::string frame_apply_level_cmd_help = gdb::option::build_help (N_("\
+  static std::string frame_apply_level_cmd_help = gdb::option::build_help (_("\
 Apply a command to a list of frames.\n\
 \n\
 Usage: frame apply level LEVEL... [OPTION]... COMMAND\n\
@@ -3299,7 +3417,7 @@ A single numerical argument specifies the frame to select."),
 
   add_cmd ("address", class_stack, &frame_cmd.address,
           _("\
-Select and print a stack frame by stack address\n\
+Select and print a stack frame by stack address.\n\
 \n\
 Usage: frame address STACK-ADDRESS"),
           &frame_cmd_list);
@@ -3376,12 +3494,13 @@ Usage: select-frame level LEVEL"),
     = make_backtrace_options_def_group (nullptr, nullptr, nullptr);
 
   static std::string backtrace_help
-    = gdb::option::build_help (N_("\
+    = gdb::option::build_help (_("\
 Print backtrace of all stack frames, or innermost COUNT frames.\n\
 Usage: backtrace [OPTION]... [QUALIFIER]... [COUNT | -COUNT]\n\
 \n\
 Options:\n\
-%OPTIONS%\
+%OPTIONS%\n\
+\n\
 For backward compatibility, the following qualifiers are supported:\n\
 \n\
    full       - same as -full option.\n\
@@ -3441,18 +3560,22 @@ Print information about a stack frame selected by level.\n\
 Usage: info frame level LEVEL"),
           &info_frame_cmd_list);
 
-  add_info ("locals", info_locals_command,
-           info_print_args_help (_("\
+  cmd = add_info ("locals", info_locals_command,
+                 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,
-           info_print_args_help (_("\
+                                       _("local variables"),
+                                       false));
+  set_cmd_completer_handle_brkchars (cmd, info_print_command_completer);
+  cmd = add_info ("args", info_args_command,
+                 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")));
+                                       _("argument variables"),
+                                       false));
+  set_cmd_completer_handle_brkchars (cmd, info_print_command_completer);
 
   if (dbx_commands)
     add_com ("func", class_stack, func_command, _("\
This page took 0.035017 seconds and 4 git commands to generate.