From patchwork Tue Jun 2 10:11:11 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 7006 Received: (qmail 96950 invoked by alias); 2 Jun 2015 10:11:20 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 96940 invoked by uid 89); 2 Jun 2015 10:11:20 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.5 required=5.0 tests=AWL, BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW, UNSUBSCRIBE_BODY autolearn=no version=3.3.2 X-HELO: mail-wi0-f176.google.com Received: from mail-wi0-f176.google.com (HELO mail-wi0-f176.google.com) (209.85.212.176) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Tue, 02 Jun 2015 10:11:17 +0000 Received: by wizo1 with SMTP id o1so138037305wiz.1 for ; Tue, 02 Jun 2015 03:11:14 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-type:content-disposition:in-reply-to :user-agent; bh=QL2M+0V9L5FfDZcmPAdX0q/F6SCCVaFhBY0bQy1uAuw=; b=UaxhZXHh1kMr/vxWlTrmfkV1OeRps8QXIfpqEcFMMLQUxZ+OG/7FjgiMs3zFwHxxFS EbQ1qsjVgNoYRuVHQII1Fx+kRpthu8QU26zSKiQlYOoMpi87phvxhE5M5wn2qVxw9gQp +QJY3ktfsq0RHgyKhg4eSQ1JB9DOrgdsTFvFnCifxLO1ZRIIkfB80+S8OaiV5jiGluLu xjm5gxk73F6SHlFwQV+8SSNHxQ9Vnh638sicdMCsbSC2PTLtn9YQcDW3lqUdR4w3y3Fo AMRXPcMOU8g6Eg6m+CF+eOh4HmQMLJNbqXC0x+z2BjKuRM7FXYIH6xkrLICsppFaCenQ BJ+g== X-Gm-Message-State: ALoCoQmOZmaAvzNmyVL2kkltS7LAVZHD2w6ymzDXsc269jdb22yeZv6rhx5eN+U049EkqOGMBy5B X-Received: by 10.180.77.9 with SMTP id o9mr30233307wiw.52.1433239874386; Tue, 02 Jun 2015 03:11:14 -0700 (PDT) Received: from localhost (cust64-dsl91-135-5.idnet.net. [91.135.5.64]) by mx.google.com with ESMTPSA id dz4sm20814117wib.17.2015.06.02.03.11.12 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 02 Jun 2015 03:11:13 -0700 (PDT) Date: Tue, 2 Jun 2015 11:11:11 +0100 From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Pedro Alves Subject: Re: [PATCH 2/2] gdb: Rework command completion on 'tui reg'. Message-ID: <20150602101111.GO17330@embecosm.com> References: <58e17eaffc56924038a839aa42e00a96dc1832b5.1432246159.git.andrew.burgess@embecosm.com> <55607DF7.8040601@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <55607DF7.8040601@redhat.com> X-Editor: GNU Emacs [ http://www.gnu.org/software/emacs ] User-Agent: Mutt/1.5.23 (2014-03-12) X-IsSubscribed: yes Thanks for the review. I've reworked the patch to address all the issues raised. Here's the new version. --- 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. --- gdb/ChangeLog | 29 +++++++++ gdb/NEWS | 3 + gdb/completer.c | 79 +++++++++++++++++++------ gdb/completer.h | 3 + gdb/doc/ChangeLog | 5 ++ gdb/doc/gdb.texinfo | 47 ++++++++------- gdb/tui/tui-regs.c | 165 +++++++++++++++++++++++++++++++++------------------- 7 files changed, 233 insertions(+), 98 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index eca000f..bc1bd49 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,32 @@ +2015-06-01 Andrew Burgess + + * 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-02 Yao Qi * i386-linux-nat.c: Include linux-nat.h. diff --git a/gdb/NEWS b/gdb/NEWS index bbfb55d..2933e35 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -52,6 +52,9 @@ * GDB now supports the vector ABI on S/390 GNU/Linux targets. +* 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. diff --git a/gdb/completer.c b/gdb/completer.c index c8c0e4c..a0be935 100644 --- a/gdb/completer.c +++ b/gdb/completer.c @@ -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,86 @@ 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 on a register names (when WITH_REGISTERS is true) and/or + reggroup names (when WITH_REGGROUPS) is true. One, or both of + WITH_REGISTERS and WITH_REGGROUPS must be true. */ + +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; - gdbarch = get_frame_arch (get_selected_frame (NULL)); + gdb_assert ((targets & (complete_register_names + | complete_reggroup_names)) != 0); + gdbarch = get_current_arch (); - 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. */ diff --git a/gdb/completer.h b/gdb/completer.h index 56e1a2b..6c1f257 100644 --- a/gdb/completer.h +++ b/gdb/completer.h @@ -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); diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 171d30e..24555c2 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2015-06-01 Andrew Burgess + + * gdb.texinfo (TUI Commands): Bring all 'tui reg' commands into a + single table entry. + 2015-05-27 Doug Evans * gdb.texinfo (Debugging Output): Mention set/show debug dwarf-line. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 9ea846a..f927eff 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -25009,27 +25009,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. - -@item tui reg general -Show the general registers in the register window. - -@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. +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 avaiable 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 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 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 diff --git a/gdb/tui/tui-regs.c b/gdb/tui/tui-regs.c index 6ac3c2b..a61fadb 100644 --- a/gdb/tui/tui-regs.c +++ b/gdb/tui/tui-regs.c @@ -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); -} +/* 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_general_command (char *arg, int from_tty) +tui_reg_command (char *args, int from_tty) { - tui_show_registers (general_reggroup); -} + struct gdbarch *gdbarch = get_current_arch (); -static void -tui_reg_system_command (char *arg, int from_tty) -{ - tui_show_registers (system_reggroup); + 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"); + } } -static struct cmd_list_element *tuireglist; +/* Complete names of register groups, and add the special "prev" and "next" + names. */ -static void -tui_reg_command (char *args, int from_tty) +static VEC (char_ptr) * +tui_reggroup_completer (struct cmd_list_element *ignore, + const char *text, const char *word) { - 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); + 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); }