gdb: Rework command completion on 'tui reg'.

We previously specified a few known register groups for the 'tui reg'
command.  Other register groups could be accessed, but only by using the
'tui reg next' command and cycling through all the groups.

This commit removes the hard coded sub-commands of 'tui reg' and instead
adds dynamic completion of sub-commands based on the architecturally
defined register groups, giving immediate access to all available
register groups.

There is still the 'next' and 'prev' commands for cycling through the
register groups if that's wanted.

The new code maintains the ability to only enter partial names for
register groups, which is something we got for free when using the
standard sub-command mechanism.

The register (and register group) completer has been changed to use
get_current_arch rather than using the architecture of the currently
selected frame.  When the target is running, this is equivalent,
however, when the target is not running, using get_current_arch will
provide results from the default architecture.

gdb/ChangeLog:

	* completer.c: Add arch-utils.h include.
	(enum reg_completer_targets): New enum.
	(reg_or_group_completer_1): New function containing old
	reg_or_group_completer, add and use new parameter to control what
	is completed on.  Use get_current_arch rather than architecture of
	currently selected frame.
	(reg_or_group_completer): Call new reg_or_group_completer_1.
	(reggroup_completer): Call new reg_or_group_completer_1.
	* completer.h (reggroup_completer): Add declaration.
	* tui/tui-regs.c: Add 'completer.h' include.
	(tui_reg_next_command): Renamed to...
	(tui_reg_next): ...this.  Adjust parameters and return rather than
	display new group.
	(tui_reg_prev_command): Renamed to...
	(tui_reg_prev): ...this.  Adjust parameters and return rather than
	display new group.
	(tui_reg_float_command): Delete.
	(tui_reg_general_command): Delete.
	(tui_reg_system_command): Delete.
	(tui_reg_command): Rewrite to perform switching of register group.
	Add header comment.
	(tuireglist): Remove.
	(tui_reggroup_completer): New function.
	(_initialize_tui_regs): Remove 'tui reg' sub-commands, update
	creation of 'tui reg' command.
	* NEWS: Add comment about 'tui reg' changes.

gdb/doc/ChangeLog:

	* gdb.texinfo (TUI Commands): Bring all 'tui reg' commands into a
	single table entry.
This commit is contained in:
Andrew Burgess 2015-05-26 23:23:23 +01:00
parent 644dbd876c
commit 51f0e40d65
7 changed files with 234 additions and 103 deletions

View File

@ -1,3 +1,32 @@
2015-06-13 Andrew Burgess <andrew.burgess@embecosm.com>
* completer.c: Add arch-utils.h include.
(enum reg_completer_targets): New enum.
(reg_or_group_completer_1): New function containing old
reg_or_group_completer, add and use new parameter to control what
is completed on. Use get_current_arch rather than architecture of
currently selected frame.
(reg_or_group_completer): Call new reg_or_group_completer_1.
(reggroup_completer): Call new reg_or_group_completer_1.
* completer.h (reggroup_completer): Add declaration.
* tui/tui-regs.c: Add 'completer.h' include.
(tui_reg_next_command): Renamed to...
(tui_reg_next): ...this. Adjust parameters and return rather than
display new group.
(tui_reg_prev_command): Renamed to...
(tui_reg_prev): ...this. Adjust parameters and return rather than
display new group.
(tui_reg_float_command): Delete.
(tui_reg_general_command): Delete.
(tui_reg_system_command): Delete.
(tui_reg_command): Rewrite to perform switching of register group.
Add header comment.
(tuireglist): Remove.
(tui_reggroup_completer): New function.
(_initialize_tui_regs): Remove 'tui reg' sub-commands, update
creation of 'tui reg' command.
* NEWS: Add comment about 'tui reg' changes.
2015-06-12 Simon Marchi <simon.marchi@ericsson.com>
* target.c (target_read): Consider addressable unit size when

View File

@ -59,6 +59,9 @@
containers as simply as "gdb -p PID" or "gdbserver --attach PID".
See "New remote packets" below.
* The "tui reg" command now provides completion for all of the
available register groups, including target specific groups.
* Guile Scripting
** Memory ports can now be unbuffered.

View File

@ -26,6 +26,7 @@
#include "target.h"
#include "reggroups.h"
#include "user-regs.h"
#include "arch-utils.h"
#include "cli/cli-decode.h"
@ -969,44 +970,82 @@ signal_completer (struct cmd_list_element *ignore,
return return_val;
}
/* Complete on a register or reggroup. */
/* Bit-flags for selecting what the register and/or register-group
completer should complete on. */
VEC (char_ptr) *
reg_or_group_completer (struct cmd_list_element *ignore,
const char *text, const char *word)
enum reg_completer_targets
{
complete_register_names = 0x1,
complete_reggroup_names = 0x2
};
/* Complete register names and/or reggroup names based on the value passed
in TARGETS. At least one bit in TARGETS must be set. */
static VEC (char_ptr) *
reg_or_group_completer_1 (struct cmd_list_element *ignore,
const char *text, const char *word,
enum reg_completer_targets targets)
{
VEC (char_ptr) *result = NULL;
size_t len = strlen (word);
struct gdbarch *gdbarch;
struct reggroup *group;
const char *name;
int i;
if (!target_has_registers)
return result;
gdb_assert ((targets & (complete_register_names
| complete_reggroup_names)) != 0);
gdbarch = get_current_arch ();
gdbarch = get_frame_arch (get_selected_frame (NULL));
for (i = 0;
(name = user_reg_map_regnum_to_name (gdbarch, i)) != NULL;
i++)
if ((targets & complete_register_names) != 0)
{
if (*name != '\0' && strncmp (word, name, len) == 0)
VEC_safe_push (char_ptr, result, xstrdup (name));
int i;
for (i = 0;
(name = user_reg_map_regnum_to_name (gdbarch, i)) != NULL;
i++)
{
if (*name != '\0' && strncmp (word, name, len) == 0)
VEC_safe_push (char_ptr, result, xstrdup (name));
}
}
for (group = reggroup_next (gdbarch, NULL);
group != NULL;
group = reggroup_next (gdbarch, group))
if ((targets & complete_reggroup_names) != 0)
{
name = reggroup_name (group);
if (strncmp (word, name, len) == 0)
VEC_safe_push (char_ptr, result, xstrdup (name));
struct reggroup *group;
for (group = reggroup_next (gdbarch, NULL);
group != NULL;
group = reggroup_next (gdbarch, group))
{
name = reggroup_name (group);
if (strncmp (word, name, len) == 0)
VEC_safe_push (char_ptr, result, xstrdup (name));
}
}
return result;
}
/* Perform completion on register and reggroup names. */
VEC (char_ptr) *
reg_or_group_completer (struct cmd_list_element *ignore,
const char *text, const char *word)
{
return reg_or_group_completer_1 (ignore, text, word,
(complete_register_names
| complete_reggroup_names));
}
/* Perform completion on reggroup names. */
VEC (char_ptr) *
reggroup_completer (struct cmd_list_element *ignore,
const char *text, const char *word)
{
return reg_or_group_completer_1 (ignore, text, word,
complete_reggroup_names);
}
/* Get the list of chars that are considered as word breaks
for the current command. */

View File

@ -96,6 +96,9 @@ extern VEC (char_ptr) *signal_completer (struct cmd_list_element *,
extern VEC (char_ptr) *reg_or_group_completer (struct cmd_list_element *,
const char *, const char *);
extern VEC (char_ptr) *reggroup_completer (struct cmd_list_element *,
const char *, const char *);
extern char *get_gdb_completer_quote_characters (void);
extern char *gdb_completion_word_break_characters (void);

View File

@ -1,3 +1,8 @@
2015-06-13 Andrew Burgess <andrew.burgess@embecosm.com>
* gdb.texinfo (TUI Commands): Bring all 'tui reg' commands into a
single table entry.
2015-06-10 Walfred Tedeschi <walfred.tedeschi@intel.com>
* gdb.textinfo (i386): Fix "@end table" end and "@table" placement.

View File

@ -25038,27 +25038,34 @@ Make the command window active for scrolling.
@kindex refresh
Refresh the screen. This is similar to typing @kbd{C-L}.
@item tui reg float
@item tui reg @var{group}
@kindex tui reg
Show the floating point registers in the register window.
Changes the register group displayed in the tui register window to
@var{group}. If the register window is not currently displayed this
command will cause the register window to be displayed. The list of
register groups, as well as their order is target specific. The
following groups are available on most targets:
@table @code
@item next
Repeatedly selecting this group will cause the display to cycle
through all of the available register groups.
@item tui reg general
Show the general registers in the register window.
@item prev
Repeatedly selecting this group will cause the display to cycle
through all of the available register groups in the reverse order to
@var{next}.
@item tui reg next
Show the next register group. The list of register groups as well as
their order is target specific. The predefined register groups are the
following: @code{general}, @code{float}, @code{system}, @code{vector},
@code{all}, @code{save}, @code{restore}.
@item tui reg prev
Show the previous register group. The list of register groups as well
as their order is target specific. The predefined register groups are
the following: @code{general}, @code{float}, @code{system},
@code{vector}, @code{all}, @code{save}, @code{restore}.
@item tui reg system
Show the system registers in the register window.
@item general
Display the general registers.
@item float
Display the floating point registers.
@item system
Display the system registers.
@item vector
Display the vector registers.
@item all
Display all registers.
@end table
@item update
@kindex update

View File

@ -39,6 +39,7 @@
#include "tui/tui-io.h"
#include "reggroups.h"
#include "valprint.h"
#include "completer.h"
#include "gdb_curses.h"
@ -556,74 +557,135 @@ tui_display_register (struct tui_data_element *data,
}
}
static void
tui_reg_next_command (char *arg, int from_tty)
/* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
around behaviour. Returns the next register group, or NULL if the
register window is not currently being displayed. */
static struct reggroup *
tui_reg_next (struct gdbarch *gdbarch)
{
struct gdbarch *gdbarch = get_current_arch ();
struct reggroup *group = NULL;
if (TUI_DATA_WIN != NULL)
{
struct reggroup *group
= TUI_DATA_WIN->detail.data_display_info.current_group;
group = TUI_DATA_WIN->detail.data_display_info.current_group;
group = reggroup_next (gdbarch, group);
if (group == NULL)
group = reggroup_next (gdbarch, NULL);
if (group != NULL)
tui_show_registers (group);
}
return group;
}
/* Implementation of the "tui reg prev" command. Cycle the register group
displayed in the tui REG window, moving backwards through the list of
available register groups. */
/* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
around behaviour. Returns the previous register group, or NULL if the
register window is not currently being displayed. */
static void
tui_reg_prev_command (char *arg, int from_tty)
static struct reggroup *
tui_reg_prev (struct gdbarch *gdbarch)
{
struct gdbarch *gdbarch = get_current_arch ();
struct reggroup *group = NULL;
if (TUI_DATA_WIN != NULL)
{
struct reggroup *group
= TUI_DATA_WIN->detail.data_display_info.current_group;
group = TUI_DATA_WIN->detail.data_display_info.current_group;
group = reggroup_prev (gdbarch, group);
if (group == NULL)
group = reggroup_prev (gdbarch, NULL);
if (group != NULL)
tui_show_registers (group);
}
return group;
}
static void
tui_reg_float_command (char *arg, int from_tty)
{
tui_show_registers (float_reggroup);
}
static void
tui_reg_general_command (char *arg, int from_tty)
{
tui_show_registers (general_reggroup);
}
static void
tui_reg_system_command (char *arg, int from_tty)
{
tui_show_registers (system_reggroup);
}
static struct cmd_list_element *tuireglist;
/* Implement the 'tui reg' command. Changes the register group displayed
in the tui register window. Displays the tui register window if it is
not already on display. */
static void
tui_reg_command (char *args, int from_tty)
{
printf_unfiltered (_("\"tui reg\" must be followed by the name of a "
"tui reg command.\n"));
help_list (tuireglist, "tui reg ", all_commands, gdb_stdout);
struct gdbarch *gdbarch = get_current_arch ();
if (args != NULL)
{
struct reggroup *group, *match = NULL;
size_t len = strlen (args);
/* Make sure the curses mode is enabled. */
tui_enable ();
/* Make sure the register window is visible. If not, select an
appropriate layout. We need to do this before trying to run the
'next' or 'prev' commands. */
if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
tui_set_layout_by_name (DATA_NAME);
if (strncmp (args, "next", len) == 0)
match = tui_reg_next (gdbarch);
else if (strncmp (args, "prev", len) == 0)
match = tui_reg_prev (gdbarch);
/* This loop matches on the initial part of a register group
name. If this initial part in ARGS matches only one register
group then the switch is made. */
for (group = reggroup_next (gdbarch, NULL);
group != NULL;
group = reggroup_next (gdbarch, group))
{
if (strncmp (reggroup_name (group), args, len) == 0)
{
if (match != NULL)
error (_("ambiguous register group name '%s'"), args);
match = group;
}
}
if (match == NULL)
error (_("unknown register group '%s'"), args);
tui_show_registers (match);
}
else
{
struct reggroup *group;
int first;
printf_unfiltered (_("\"tui reg\" must be followed by the name of "
"either a register group,\nor one of 'next' "
"or 'prev'. Known register groups are:\n"));
for (first = 1, group = reggroup_next (gdbarch, NULL);
group != NULL;
first = 0, group = reggroup_next (gdbarch, group))
{
if (!first)
printf_unfiltered (", ");
printf_unfiltered ("%s", reggroup_name (group));
}
printf_unfiltered ("\n");
}
}
/* Complete names of register groups, and add the special "prev" and "next"
names. */
static VEC (char_ptr) *
tui_reggroup_completer (struct cmd_list_element *ignore,
const char *text, const char *word)
{
VEC (char_ptr) *result = NULL;
static const char *extra[] = { "next", "prev", NULL };
size_t len = strlen (word);
const char **tmp;
result = reggroup_completer (ignore, text, word);
for (tmp = extra; *tmp != NULL; ++tmp)
{
if (strncmp (word, *tmp, len) == 0)
VEC_safe_push (char_ptr, result, xstrdup (*tmp));
}
return result;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
@ -632,30 +694,13 @@ extern initialize_file_ftype _initialize_tui_regs;
void
_initialize_tui_regs (void)
{
struct cmd_list_element **tuicmd;
struct cmd_list_element **tuicmd, *cmd;
tuicmd = tui_get_cmd_list ();
add_prefix_cmd ("reg", class_tui, tui_reg_command,
_("TUI commands to control the register window."),
&tuireglist, "tui reg ", 0,
tuicmd);
add_cmd ("float", class_tui, tui_reg_float_command,
_("Display only floating point registers."),
&tuireglist);
add_cmd ("general", class_tui, tui_reg_general_command,
_("Display only general registers."),
&tuireglist);
add_cmd ("system", class_tui, tui_reg_system_command,
_("Display only system registers."),
&tuireglist);
add_cmd ("next", class_tui, tui_reg_next_command,
_("Display next register group."),
&tuireglist);
add_cmd ("prev", class_tui, tui_reg_prev_command,
_("Display previous register group."),
&tuireglist);
cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
TUI command to control the register window."), tuicmd);
set_cmd_completer (cmd, tui_reggroup_completer);
}