Rationalize "backtrace" command line parsing
authorTom Tromey <tom@tromey.com>
Sun, 23 Apr 2017 16:54:33 +0000 (10:54 -0600)
committerTom Tromey <tom@tromey.com>
Tue, 27 Mar 2018 03:57:09 +0000 (21:57 -0600)
The backtrace command has peculiar command-line parsing.  In
particular, it splits the command line, then loops over the arguments.
If it sees a word it recognizes, like "full", it effectively drops
this word from the argument vector.  Then, it pastes together the
remaining arguments, passing them on to backtrace_command_1, which in
turn passes the resulting string to parse_and_eval_long.

The documentation doesn't mention the parse_and_eval_long at all, so
it is a bit of a hidden feature that you can "bt 3*2".  The strange
algorithm above also means you can "bt 3 * no-filters 2" and get 6
frames...

This patch changes backtrace's command line parsing to be a bit more
rational.  Now, special words like "full" are only recognized at the
start of the command.

This also updates the documentation to describe the various bt options
individually.

gdb/ChangeLog
2018-03-26  Tom Tromey  <tom@tromey.com>

* stack.c (backtrace_command): Rewrite command line parsing.

gdb/doc/ChangeLog
2018-03-26  Tom Tromey  <tom@tromey.com>

* gdb.texinfo (Backtrace): Describe options individually.

gdb/ChangeLog
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/stack.c

index 47e6cff..532826c 100644 (file)
@@ -1,3 +1,7 @@
+2018-03-26  Tom Tromey  <tom@tromey.com>
+
+       * stack.c (backtrace_command): Rewrite command line parsing.
+
 2018-03-26  Simon Marchi  <simon.marchi@ericsson.com>
 
        * dwarf2read.c (DEF_VEC_I(offset_type)): Remove.
index 2441f15..413e456 100644 (file)
@@ -1,3 +1,7 @@
+2018-03-26  Tom Tromey  <tom@tromey.com>
+
+       * gdb.texinfo (Backtrace): Describe options individually.
+
 2018-03-19  Tom Tromey  <tom@tromey.com>
 
        * observer.texi: Remove.
index 74e0fdb..28254c9 100644 (file)
@@ -7307,45 +7307,43 @@ frame (frame zero), followed by its caller (frame one), and on up the
 stack.
 
 @anchor{backtrace-command}
-@table @code
 @kindex backtrace
 @kindex bt @r{(@code{backtrace})}
-@item backtrace
-@itemx bt
-Print a backtrace of the entire stack: one line per frame for all
-frames in the stack.
-
-You can stop the backtrace at any time by typing the system interrupt
-character, normally @kbd{Ctrl-c}.
-
-@item backtrace @var{n}
-@itemx bt @var{n}
-Similar, but print only the innermost @var{n} frames.
-
-@item backtrace -@var{n}
-@itemx bt -@var{n}
-Similar, but print only the outermost @var{n} frames.
-
-@item backtrace full
-@itemx bt full
-@itemx bt full @var{n}
-@itemx bt full -@var{n}
-Print the values of the local variables also.  As described above,
-@var{n} specifies the number of frames to print.
-
-@item backtrace no-filters
-@itemx bt no-filters
-@itemx bt no-filters @var{n}
-@itemx bt no-filters -@var{n}
-@itemx bt no-filters full
-@itemx bt no-filters full @var{n}
-@itemx bt no-filters full -@var{n}
+To print a backtrace of the entire stack, use the @code{backtrace}
+command, or its alias @code{bt}.  This command will print one line per
+frame for frames in the stack.  By default, all stack frames are
+printed.  You can stop the backtrace at any time by typing the system
+interrupt character, normally @kbd{Ctrl-c}.
+
+@table @code
+@item backtrace [@var{args}@dots{}]
+@itemx bt [@var{args}@dots{}]
+Print the backtrace of the entire stack.  The optional @var{args} can
+be one of the following:
+
+@table @code
+@item @var{n}
+@itemx @var{n}
+Print only the innermost @var{n} frames, where @var{n} is a positive
+number.
+
+@item -@var{n}
+@itemx -@var{n}
+Print only the outermost @var{n} frames, where @var{n} is a positive
+number.
+
+@item full
+Print the values of the local variables also.  This can be combined
+with a number to limit the number of frames shown.
+
+@item no-filters
 Do not run Python frame filters on this backtrace.  @xref{Frame
 Filter API}, for more information.  Additionally use @ref{disable
 frame-filter all} to turn off all frame filters.  This is only
 relevant when @value{GDBN} has been configured with @code{Python}
 support.
 @end table
+@end table
 
 @kindex where
 @kindex info stack
index aad8fcd..13af659 100644 (file)
@@ -1850,61 +1850,39 @@ backtrace_command_1 (const char *count_exp, int show_locals, int no_filters,
 static void
 backtrace_command (const char *arg, int from_tty)
 {
-  int fulltrace_arg = -1, arglen = 0, argc = 0, no_filters  = -1;
-  int user_arg = 0;
+  bool fulltrace = false;
+  bool filters = true;
 
-  std::string reconstructed_arg;
   if (arg)
     {
-      char **argv;
-      int i;
+      bool done = false;
 
-      gdb_argv built_argv (arg);
-      argv = built_argv.get ();
-      argc = 0;
-      for (i = 0; argv[i]; i++)
+      while (!done)
        {
-         unsigned int j;
+         const char *save_arg = arg;
+         std::string this_arg = extract_arg (&arg);
 
-         for (j = 0; j < strlen (argv[i]); j++)
-           argv[i][j] = TOLOWER (argv[i][j]);
+         if (this_arg.empty ())
+           break;
 
-         if (no_filters < 0 && subset_compare (argv[i], "no-filters"))
-           no_filters = argc;
+         if (subset_compare (this_arg.c_str (), "no-filters"))
+           filters = false;
+         else if (subset_compare (this_arg.c_str (), "full"))
+           fulltrace = true;
          else
            {
-             if (fulltrace_arg < 0 && subset_compare (argv[i], "full"))
-               fulltrace_arg = argc;
-             else
-               {
-                 user_arg++;
-                 arglen += strlen (argv[i]);
-               }
-           }
-         argc++;
-       }
-      arglen += user_arg;
-      if (fulltrace_arg >= 0 || no_filters >= 0)
-       {
-         if (arglen > 0)
-           {
-             for (i = 0; i < argc; i++)
-               {
-                 if (i != fulltrace_arg && i != no_filters)
-                   {
-                     reconstructed_arg += argv[i];
-                     reconstructed_arg += " ";
-                   }
-               }
-             arg = reconstructed_arg.c_str ();
+             /* Not a recognized argument, so stop.  */
+             arg = save_arg;
+             done = true;
            }
-         else
-           arg = NULL;
        }
+
+      if (*arg == '\0')
+       arg = NULL;
     }
 
-  backtrace_command_1 (arg, fulltrace_arg >= 0 /* show_locals */,
-                      no_filters >= 0 /* no frame-filters */, from_tty);
+  backtrace_command_1 (arg, fulltrace /* show_locals */,
+                      !filters /* no frame-filters */, from_tty);
 }
 
 /* Iterate over the local variables of a block B, calling CB with