Rationalize "backtrace" command line parsing

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.
This commit is contained in:
Tom Tromey 2017-04-23 10:54:33 -06:00
parent 07dca93f3b
commit ea3b06874c
4 changed files with 52 additions and 68 deletions

View 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.

View 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.

View 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.
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}.
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:
@item backtrace @var{n}
@itemx bt @var{n}
Similar, but print only the innermost @var{n} frames.
@table @code
@item @var{n}
@itemx @var{n}
Print only the innermost @var{n} frames, where @var{n} is a positive
number.
@item backtrace -@var{n}
@itemx bt -@var{n}
Similar, but print only the outermost @var{n} frames.
@item -@var{n}
@itemx -@var{n}
Print only the outermost @var{n} frames, where @var{n} is a positive
number.
@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 full
Print the values of the local variables also. This can be combined
with a number to limit the number of frames shown.
@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}
@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

View 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]);
}
/* Not a recognized argument, so stop. */
arg = save_arg;
done = true;
}
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 ();
}
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