X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftui%2Ftui-regs.c;h=b3c7ce627b46de0d7a8c16026ac0e4ef9c7fadbf;hb=0f8d8876d98305671a19b5bf88f125d4d02c7e0f;hp=96b52d4b3f06949048a18889dbda135f8873b520;hpb=f57d151a994d668d681871f04cfd6e32a1c5ac33;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/tui/tui-regs.c b/gdb/tui/tui-regs.c index 96b52d4b3f..b3c7ce627b 100644 --- a/gdb/tui/tui-regs.c +++ b/gdb/tui/tui-regs.c @@ -1,7 +1,6 @@ /* TUI display registers in window. - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007 - Free Software Foundation, Inc. + Copyright (C) 1998-2019 Free Software Foundation, Inc. Contributed by Hewlett-Packard Company. @@ -9,7 +8,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -18,11 +17,10 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ #include "defs.h" +#include "arch-utils.h" #include "tui/tui.h" #include "tui/tui-data.h" #include "symtab.h" @@ -32,76 +30,67 @@ #include "regcache.h" #include "inferior.h" #include "target.h" -#include "gdb_string.h" #include "tui/tui-layout.h" #include "tui/tui-win.h" -#include "tui/tui-windata.h" #include "tui/tui-wingeneral.h" #include "tui/tui-file.h" +#include "tui/tui-regs.h" +#include "tui/tui-io.h" #include "reggroups.h" +#include "valprint.h" +#include "completer.h" #include "gdb_curses.h" +static void tui_display_register (struct tui_data_item_window *data); -/***************************************** -** STATIC LOCAL FUNCTIONS FORWARD DECLS ** -******************************************/ -static void -tui_display_register (struct tui_data_element *data, - struct tui_gen_win_info *win_info); +static void tui_show_register_group (tui_data_window *win_info, + struct reggroup *group, + struct frame_info *frame, + int refresh_values_only); -static enum tui_status -tui_show_register_group (struct gdbarch *gdbarch, struct reggroup *group, - struct frame_info *frame, int refresh_values_only); +static void tui_get_register (struct frame_info *frame, + struct tui_data_item_window *data, + int regnum, bool *changedp); -static enum tui_status -tui_get_register (struct gdbarch *gdbarch, struct frame_info *frame, - struct tui_data_element *data, int regnum, int *changedp); -static void tui_register_format - (struct gdbarch *, struct frame_info *, struct tui_data_element*, int); -static void tui_scroll_regs_forward_command (char *, int); -static void tui_scroll_regs_backward_command (char *, int); +/* See tui-regs.h. */ +tui_data_item_window::~tui_data_item_window () +{ + xfree (value); + xfree (content); +} -/***************************************** -** PUBLIC FUNCTIONS ** -******************************************/ +/* See tui-regs.h. */ -/* Answer the number of the last line in the regs display. If there - are no registers (-1) is returned. */ int -tui_last_regs_line_no (void) +tui_data_window::last_regs_line_no () const { int num_lines = (-1); - if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0) + if (!regs_content.empty ()) { - num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count / - TUI_DATA_WIN->detail.data_display_info.regs_column_count); - if (TUI_DATA_WIN->detail.data_display_info.regs_content_count % - TUI_DATA_WIN->detail.data_display_info.regs_column_count) + num_lines = regs_content.size () / regs_column_count; + if (regs_content.size () % regs_column_count) num_lines++; } return num_lines; } +/* See tui-regs.h. */ -/* Answer the line number that the register element at element_no is - on. If element_no is greater than the number of register elements - there are, -1 is returned. */ int -tui_line_from_reg_element_no (int element_no) +tui_data_window::line_from_reg_element_no (int element_no) const { - if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count) + if (element_no < regs_content.size ()) { int i, line = (-1); i = 1; while (line == (-1)) { - if (element_no < - (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i)) + if (element_no < regs_column_count * i) line = i - 1; else i++; @@ -113,33 +102,30 @@ tui_line_from_reg_element_no (int element_no) return (-1); } +/* See tui-regs.h. */ -/* Answer the index of the first element in line_no. If line_no is past - the register area (-1) is returned. */ int -tui_first_reg_element_no_inline (int line_no) +tui_data_window::first_reg_element_no_inline (int line_no) const { - if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) - <= TUI_DATA_WIN->detail.data_display_info.regs_content_count) - return ((line_no + 1) * - TUI_DATA_WIN->detail.data_display_info.regs_column_count) - - TUI_DATA_WIN->detail.data_display_info.regs_column_count; + if (line_no * regs_column_count <= regs_content.size ()) + return ((line_no + 1) * regs_column_count) - regs_column_count; else return (-1); } +/* A helper function to display the register window in the appropriate + way. */ -/* Answer the index of the last element in line_no. If line_no is - past the register area (-1) is returned. */ -int -tui_last_reg_element_no_in_line (int line_no) +static void +tui_reg_layout () { - if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <= - TUI_DATA_WIN->detail.data_display_info.regs_content_count) - return ((line_no + 1) * - TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1; + enum tui_layout_type cur_layout = tui_current_layout (); + enum tui_layout_type new_layout; + if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND) + new_layout = SRC_DATA_COMMAND; else - return (-1); + new_layout = DISASSEM_DATA_COMMAND; + tui_set_layout (new_layout); } /* Show the registers of the given group in the data window @@ -147,190 +133,143 @@ tui_last_reg_element_no_in_line (int line_no) void tui_show_registers (struct reggroup *group) { - enum tui_status ret = TUI_FAILURE; - struct tui_data_info *display_info; - /* Make sure the curses mode is enabled. */ tui_enable (); /* Make sure the register window is visible. If not, select an appropriate layout. */ - if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible) - tui_set_layout_for_display_command (DATA_NAME); + if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible ()) + tui_reg_layout (); - display_info = &TUI_DATA_WIN->detail.data_display_info; if (group == 0) group = general_reggroup; - /* Say that registers should be displayed, even if there is a problem. */ - display_info->display_regs = TRUE; + /* Say that registers should be displayed, even if there is a + problem. */ + TUI_DATA_WIN->display_regs = true; if (target_has_registers && target_has_stack && target_has_memory) { - ret = tui_show_register_group (current_gdbarch, group, - get_current_frame (), - group == display_info->current_group); - } - if (ret == TUI_FAILURE) - { - display_info->current_group = 0; - tui_erase_data_content (NO_REGS_STRING); - } - else - { - int i; + tui_show_register_group (TUI_DATA_WIN, group, get_selected_frame (NULL), + group == TUI_DATA_WIN->current_group); - /* Clear all notation of changed values */ - for (i = 0; i < display_info->regs_content_count; i++) + /* Clear all notation of changed values. */ + for (auto &&data_item_win : TUI_DATA_WIN->regs_content) { - struct tui_gen_win_info *data_item_win; - struct tui_win_element *win; - - data_item_win = &display_info->regs_content[i] - ->which_element.data_window; - win = (struct tui_win_element *) data_item_win->content[0]; - win->which_element.data.highlight = FALSE; + if (data_item_win != nullptr) + data_item_win->highlight = false; } - display_info->current_group = group; - tui_display_all_data (); + TUI_DATA_WIN->current_group = group; + TUI_DATA_WIN->display_all_data (); + } + else + { + TUI_DATA_WIN->current_group = 0; + TUI_DATA_WIN->erase_data_content (_("[ Register Values Unavailable ]")); } } /* Set the data window to display the registers of the register group - using the given frame. Values are refreshed only when refresh_values_only - is TRUE. */ + using the given frame. Values are refreshed only when + refresh_values_only is TRUE. */ -static enum tui_status -tui_show_register_group (struct gdbarch *gdbarch, struct reggroup *group, - struct frame_info *frame, int refresh_values_only) +static void +tui_show_register_group (tui_data_window *win_info, + struct reggroup *group, + struct frame_info *frame, + int refresh_values_only) { - enum tui_status ret = TUI_FAILURE; + struct gdbarch *gdbarch = get_frame_arch (frame); int nr_regs; - int allocated_here = FALSE; int regnum, pos; char title[80]; - struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info; /* Make a new title showing which group we display. */ snprintf (title, sizeof (title) - 1, "Register group: %s", reggroup_name (group)); - xfree (TUI_DATA_WIN->generic.title); - TUI_DATA_WIN->generic.title = xstrdup (title); + xfree (win_info->title); + win_info->title = xstrdup (title); /* See how many registers must be displayed. */ nr_regs = 0; - for (regnum = 0; - regnum < gdbarch_num_regs (current_gdbarch) - + gdbarch_num_pseudo_regs (current_gdbarch); - regnum++) + for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++) { - /* Must be in the group and have a name. */ - if (gdbarch_register_reggroup_p (gdbarch, regnum, group) - && gdbarch_register_name (gdbarch, regnum) != 0) - nr_regs++; - } + const char *name; - if (display_info->regs_content_count > 0 && !refresh_values_only) - { - tui_free_data_content (display_info->regs_content, - display_info->regs_content_count); - display_info->regs_content_count = 0; + /* Must be in the group. */ + if (!gdbarch_register_reggroup_p (gdbarch, regnum, group)) + continue; + + /* If the register name is empty, it is undefined for this + processor, so don't display anything. */ + name = gdbarch_register_name (gdbarch, regnum); + if (name == 0 || *name == '\0') + continue; + + nr_regs++; } - if (display_info->regs_content_count <= 0) + if (!refresh_values_only) + win_info->regs_content.clear (); + + if (nr_regs < win_info->regs_content.size ()) + win_info->regs_content.resize (nr_regs); + else { - display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN); - allocated_here = TRUE; - refresh_values_only = FALSE; + for (int i = win_info->regs_content.size (); i < nr_regs; ++i) + win_info->regs_content.emplace_back (new tui_data_item_window ()); } - if (display_info->regs_content != (tui_win_content) NULL) + /* Now set the register names and values. */ + pos = 0; + for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++) { - if (!refresh_values_only || allocated_here) - { - TUI_DATA_WIN->generic.content = (void*) NULL; - TUI_DATA_WIN->generic.content_size = 0; - tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs); - display_info->regs_content - = (tui_win_content) TUI_DATA_WIN->generic.content; - display_info->regs_content_count = nr_regs; - } + struct tui_data_item_window *data_item_win; + const char *name; - /* Now set the register names and values */ - pos = 0; - for (regnum = 0; - regnum < gdbarch_num_regs (current_gdbarch) - + gdbarch_num_pseudo_regs (current_gdbarch); - regnum++) - { - struct tui_gen_win_info *data_item_win; - struct tui_data_element *data; - const char *name; - - if (!gdbarch_register_reggroup_p (gdbarch, regnum, group)) - continue; - - name = gdbarch_register_name (gdbarch, regnum); - if (name == 0) - continue; - - data_item_win = - &display_info->regs_content[pos]->which_element.data_window; - data = - &((struct tui_win_element *) data_item_win->content[0])->which_element.data; - if (data) - { - if (!refresh_values_only) - { - data->item_no = regnum; - data->name = name; - data->highlight = FALSE; - } - if (data->value == (void*) NULL) - data->value = (void*) xmalloc (MAX_REGISTER_SIZE); + /* Must be in the group. */ + if (!gdbarch_register_reggroup_p (gdbarch, regnum, group)) + continue; - tui_get_register (gdbarch, frame, data, regnum, 0); - } - pos++; - } + /* If the register name is empty, it is undefined for this + processor, so don't display anything. */ + name = gdbarch_register_name (gdbarch, regnum); + if (name == 0 || *name == '\0') + continue; - TUI_DATA_WIN->generic.content_size = - display_info->regs_content_count + display_info->data_content_count; - ret = TUI_SUCCESS; + data_item_win = win_info->regs_content[pos].get (); + if (data_item_win) + { + if (!refresh_values_only) + { + data_item_win->item_no = regnum; + data_item_win->name = name; + data_item_win->highlight = false; + } + tui_get_register (frame, data_item_win, regnum, 0); + } + pos++; } - - return ret; } -/* Function to display the registers in the content from - 'start_element_no' until the end of the register content or the end - of the display height. No checking for displaying past the end of - the registers is done here. */ +/* See tui-regs.h. */ + void -tui_display_registers_from (int start_element_no) +tui_data_window::display_registers_from (int start_element_no) { - struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info; - - if (display_info->regs_content != (tui_win_content) NULL && - display_info->regs_content_count > 0) + if (!regs_content.empty ()) { - int i = start_element_no; - int j, value_chars_wide, item_win_width, cur_y; + int j, item_win_width, cur_y; int max_len = 0; - for (i = 0; i < display_info->regs_content_count; i++) + for (auto &&data_item_win : regs_content) { - struct tui_data_element *data; - struct tui_gen_win_info *data_item_win; char *p; int len; - data_item_win = &display_info->regs_content[i]->which_element.data_window; - data = &((struct tui_win_element *) - data_item_win->content[0])->which_element.data; len = 0; - p = data->content; + p = data_item_win->content; if (p != 0) while (*p) { @@ -344,35 +283,28 @@ tui_display_registers_from (int start_element_no) max_len = len; } item_win_width = max_len + 1; - i = start_element_no; - - display_info->regs_column_count = - (TUI_DATA_WIN->generic.width - 2) / item_win_width; - if (display_info->regs_column_count == 0) - display_info->regs_column_count = 1; - item_win_width = - (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count; - - /* - ** Now create each data "sub" window, and write the display into it. - */ + int i = start_element_no; + + regs_column_count = (width - 2) / item_win_width; + if (regs_column_count == 0) + regs_column_count = 1; + item_win_width = (width - 2) / regs_column_count; + + /* Now create each data "sub" window, and write the display into + it. */ cur_y = 1; - while (i < display_info->regs_content_count && - cur_y <= TUI_DATA_WIN->generic.viewport_height) + while (i < regs_content.size () + && cur_y <= viewport_height) { for (j = 0; - (j < display_info->regs_column_count && - i < display_info->regs_content_count); j++) + j < regs_column_count && i < regs_content.size (); + j++) { - struct tui_gen_win_info * data_item_win; - struct tui_data_element * data_element_ptr; - - /* create the window if necessary */ - data_item_win = &display_info->regs_content[i] - ->which_element.data_window; - data_element_ptr = &((struct tui_win_element *) - data_item_win->content[0])->which_element.data; - if (data_item_win->handle != (WINDOW*) NULL + struct tui_data_item_window *data_item_win; + + /* Create the window if necessary. */ + data_item_win = regs_content[i].get (); + if (data_item_win->handle != NULL && (data_item_win->height != 1 || data_item_win->width != item_win_width || data_item_win->origin.x != (item_win_width * j) + 1 @@ -382,37 +314,34 @@ tui_display_registers_from (int start_element_no) data_item_win->handle = 0; } - if (data_item_win->handle == (WINDOW *) NULL) + if (data_item_win->handle == NULL) { data_item_win->height = 1; data_item_win->width = item_win_width; data_item_win->origin.x = (item_win_width * j) + 1; data_item_win->origin.y = cur_y; - tui_make_window (data_item_win, DONT_BOX_WINDOW); + tui_make_window (data_item_win); scrollok (data_item_win->handle, FALSE); } touchwin (data_item_win->handle); /* Get the printable representation of the register and display it. */ - tui_display_register (data_element_ptr, data_item_win); - i++; /* next register */ + tui_display_register (data_item_win); + i++; /* Next register. */ } - cur_y++; /* next row; */ + cur_y++; /* Next row. */ } } } +/* See tui-regs.h. */ -/* Function to display the registers in the content from - 'start_element_no' on 'start_line_no' until the end of the register - content or the end of the display height. This function checks - that we won't display off the end of the register display. */ void -tui_display_reg_element_at_line (int start_element_no, int start_line_no) +tui_data_window::display_reg_element_at_line (int start_element_no, + int start_line_no) { - if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL && - TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0) + if (!regs_content.empty ()) { int element_no = start_element_no; @@ -420,66 +349,200 @@ tui_display_reg_element_at_line (int start_element_no, int start_line_no) { int last_line_no, first_line_on_last_page; - last_line_no = tui_last_regs_line_no (); - first_line_on_last_page = last_line_no - (TUI_DATA_WIN->generic.height - 2); + last_line_no = last_regs_line_no (); + first_line_on_last_page = last_line_no - (height - 2); if (first_line_on_last_page < 0) first_line_on_last_page = 0; - /* - ** If there is no other data displayed except registers, - ** and the element_no causes us to scroll past the end of the - ** registers, adjust what element to really start the display at. - */ - if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0 && - start_line_no > first_line_on_last_page) - element_no = tui_first_reg_element_no_inline (first_line_on_last_page); + + /* If the element_no causes us to scroll past the end of the + registers, adjust what element to really start the + display at. */ + if (start_line_no > first_line_on_last_page) + element_no = first_reg_element_no_inline (first_line_on_last_page); } - tui_display_registers_from (element_no); + display_registers_from (element_no); } } +/* See tui-regs.h. */ - -/* Function to display the registers starting at line line_no in the - data window. Answers the line number that the display actually - started from. If nothing is displayed (-1) is returned. */ int -tui_display_registers_from_line (int line_no, int force_display) +tui_data_window::display_registers_from_line (int line_no) { - if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0) + check_and_display_highlight_if_needed (); + if (!regs_content.empty ()) { - int line, element_no; + int element_no; if (line_no < 0) - line = 0; - else if (force_display) - { /* - ** If we must display regs (force_display is true), then make - ** sure that we don't display off the end of the registers. - */ - if (line_no >= tui_last_regs_line_no ()) + line_no = 0; + else + { + /* Make sure that we don't display off the end of the + registers. */ + if (line_no >= last_regs_line_no ()) { - if ((line = tui_line_from_reg_element_no ( - TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0) - line = 0; + line_no = line_from_reg_element_no (regs_content.size () - 1); + if (line_no < 0) + line_no = 0; } - else - line = line_no; } + + element_no = first_reg_element_no_inline (line_no); + if (element_no < regs_content.size ()) + display_reg_element_at_line (element_no, line_no); else - line = line_no; + line_no = (-1); + + return line_no; + } + + return (-1); /* Nothing was displayed. */ +} + + +/* Answer the index first element displayed. If none are displayed, + then return (-1). */ +int +tui_data_window::first_data_item_displayed () +{ + for (int i = 0; i < regs_content.size (); i++) + { + struct tui_gen_win_info *data_item_win; + + data_item_win = regs_content[i].get (); + if (data_item_win->is_visible ()) + return i; + } + + return -1; +} + +/* See tui-regs.h. */ + +void +tui_data_window::delete_data_content_windows () +{ + for (auto &&win : regs_content) + { + tui_delete_win (win->handle); + win->handle = NULL; + } +} - element_no = tui_first_reg_element_no_inline (line); - if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count) - tui_display_reg_element_at_line (element_no, line); + +void +tui_data_window::erase_data_content (const char *prompt) +{ + werase (handle); + check_and_display_highlight_if_needed (); + if (prompt != NULL) + { + int half_width = (width - 2) / 2; + int x_pos; + + if (strlen (prompt) >= half_width) + x_pos = 1; else - line = (-1); + x_pos = half_width - strlen (prompt); + mvwaddstr (handle, (height / 2), x_pos, (char *) prompt); + } + wrefresh (handle); +} - return line; +/* See tui-regs.h. */ + +void +tui_data_window::display_all_data () +{ + if (regs_content.empty ()) + erase_data_content (NO_DATA_STRING); + else + { + erase_data_content (NULL); + delete_data_content_windows (); + check_and_display_highlight_if_needed (); + display_registers_from (0); + } +} + + +/* Function to redisplay the contents of the data window. */ +void +tui_data_window::refresh_all () +{ + erase_data_content (NULL); + if (!regs_content.empty ()) + { + int first_element = first_data_item_displayed (); + + if (first_element >= 0) /* Re-use existing windows. */ + { + int first_line = (-1); + + if (first_element < regs_content.size ()) + first_line = line_from_reg_element_no (first_element); + + if (first_line >= 0) + { + erase_data_content (NULL); + display_registers_from_line (first_line); + } + } } +} - return (-1); /* nothing was displayed */ + +/* Scroll the data window vertically forward or backward. */ +void +tui_data_window::do_scroll_vertical (int num_to_scroll) +{ + int first_element_no; + int first_line = (-1); + + first_element_no = first_data_item_displayed (); + if (first_element_no < regs_content.size ()) + first_line = line_from_reg_element_no (first_element_no); + else + { /* Calculate the first line from the element number which is in + the general data content. */ + } + + if (first_line >= 0) + { + first_line += num_to_scroll; + erase_data_content (NULL); + delete_data_content_windows (); + display_registers_from_line (first_line); + } } +/* See tui-regs.h. */ + +void +tui_data_window::rerender () +{ + /* Delete all data item windows. */ + for (auto &&win : regs_content) + { + tui_delete_win (win->handle); + win->handle = NULL; + } + display_all_data (); +} + +/* See tui-regs.h. */ + +void +tui_data_window::refresh_window () +{ + tui_gen_win_info::refresh_window (); + for (auto &&win : regs_content) + { + if (win != NULL) + win->refresh_window (); + } +} /* This function check all displayed registers for changes in values, given a particular frame. If the values have changed, they are @@ -487,269 +550,253 @@ tui_display_registers_from_line (int line_no, int force_display) void tui_check_register_values (struct frame_info *frame) { - if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible) + if (TUI_DATA_WIN != NULL + && TUI_DATA_WIN->is_visible ()) { - struct tui_data_info *display_info - = &TUI_DATA_WIN->detail.data_display_info; - - if (display_info->regs_content_count <= 0 && display_info->display_regs) - tui_show_registers (display_info->current_group); + if (TUI_DATA_WIN->regs_content.empty () + && TUI_DATA_WIN->display_regs) + tui_show_registers (TUI_DATA_WIN->current_group); else { - int i, j; - - for (i = 0; (i < display_info->regs_content_count); i++) + for (auto &&data_item_win_ptr : TUI_DATA_WIN->regs_content) { - struct tui_data_element *data; - struct tui_gen_win_info *data_item_win_ptr; int was_hilighted; - data_item_win_ptr = &display_info->regs_content[i]-> - which_element.data_window; - data = &((struct tui_win_element *) - data_item_win_ptr->content[0])->which_element.data; - was_hilighted = data->highlight; + was_hilighted = data_item_win_ptr->highlight; - tui_get_register (current_gdbarch, frame, data, - data->item_no, &data->highlight); + tui_get_register (frame, data_item_win_ptr.get (), + data_item_win_ptr->item_no, + &data_item_win_ptr->highlight); - if (data->highlight || was_hilighted) - { - tui_display_register (data, data_item_win_ptr); - } + if (data_item_win_ptr->highlight || was_hilighted) + tui_display_register (data_item_win_ptr.get ()); } } } } -/* Display a register in a window. If hilite is TRUE, - then the value will be displayed in reverse video */ +/* Display a register in a window. If hilite is TRUE, then the value + will be displayed in reverse video. */ static void -tui_display_register (struct tui_data_element *data, - struct tui_gen_win_info *win_info) +tui_display_register (struct tui_data_item_window *data) { - if (win_info->handle != (WINDOW *) NULL) + if (data->handle != NULL) { int i; if (data->highlight) - wstandout (win_info->handle); + /* We ignore the return value, casting it to void in order to avoid + a compiler warning. The warning itself was introduced by a patch + to ncurses 5.7 dated 2009-08-29, changing this macro to expand + to code that causes the compiler to generate an unused-value + warning. */ + (void) wstandout (data->handle); - wmove (win_info->handle, 0, 0); - for (i = 1; i < win_info->width; i++) - waddch (win_info->handle, ' '); - wmove (win_info->handle, 0, 0); + wmove (data->handle, 0, 0); + for (i = 1; i < data->width; i++) + waddch (data->handle, ' '); + wmove (data->handle, 0, 0); if (data->content) - waddstr (win_info->handle, data->content); + waddstr (data->handle, data->content); if (data->highlight) - wstandend (win_info->handle); - tui_refresh_win (win_info); + /* We ignore the return value, casting it to void in order to avoid + a compiler warning. The warning itself was introduced by a patch + to ncurses 5.7 dated 2009-08-29, changing this macro to expand + to code that causes the compiler to generate an unused-value + warning. */ + (void) wstandend (data->handle); + data->refresh_window (); } } -static void -tui_reg_next_command (char *arg, int from_tty) -{ - if (TUI_DATA_WIN != 0) - { - struct reggroup *group - = TUI_DATA_WIN->detail.data_display_info.current_group; +/* 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. */ - group = reggroup_next (current_gdbarch, group); - if (group == 0) - group = reggroup_next (current_gdbarch, 0); +static struct reggroup * +tui_reg_next (struct reggroup *current_group, struct gdbarch *gdbarch) +{ + struct reggroup *group = NULL; - if (group) - tui_show_registers (group); + if (current_group != NULL) + { + group = reggroup_next (gdbarch, current_group); + if (group == NULL) + group = reggroup_next (gdbarch, NULL); } + return group; } -static void -tui_reg_float_command (char *arg, int from_tty) -{ - tui_show_registers (float_reggroup); -} +/* 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_general_command (char *arg, int from_tty) +static struct reggroup * +tui_reg_prev (struct reggroup *current_group, struct gdbarch *gdbarch) { - tui_show_registers (general_reggroup); -} + struct reggroup *group = NULL; -static void -tui_reg_system_command (char *arg, int from_tty) -{ - tui_show_registers (system_reggroup); + if (current_group != NULL) + { + group = reggroup_prev (gdbarch, current_group); + if (group == NULL) + group = reggroup_prev (gdbarch, NULL); + } + return group; } -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) +tui_reg_command (const 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 ", -1, gdb_stdout); -} + struct gdbarch *gdbarch = get_current_arch (); -void -_initialize_tui_regs (void) -{ - struct cmd_list_element **tuicmd; + 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->is_visible ()) + tui_reg_layout (); + + struct reggroup *current_group = TUI_DATA_WIN->current_group; + if (strncmp (args, "next", len) == 0) + match = tui_reg_next (current_group, gdbarch); + else if (strncmp (args, "prev", len) == 0) + match = tui_reg_prev (current_group, 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; + } + } - tuicmd = tui_get_cmd_list (); + if (match == NULL) + error (_("unknown register group '%s'"), args); - 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); - - if (xdb_commands) - { - add_com ("fr", class_tui, tui_reg_float_command, - _("Display only floating point registers\n")); - add_com ("gr", class_tui, tui_reg_general_command, - _("Display only general registers\n")); - add_com ("sr", class_tui, tui_reg_system_command, - _("Display only special registers\n")); - add_com ("+r", class_tui, tui_scroll_regs_forward_command, - _("Scroll the registers window forward\n")); - add_com ("-r", class_tui, tui_scroll_regs_backward_command, - _("Scroll the register window backward\n")); + tui_show_registers (match); } -} - + else + { + struct reggroup *group; + int first; -/***************************************** -** STATIC LOCAL FUNCTIONS ** -******************************************/ + 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")); -extern int pagination_enabled; + 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)); + } -static void -tui_restore_gdbout (void *ui) -{ - ui_file_delete (gdb_stdout); - gdb_stdout = (struct ui_file*) ui; - pagination_enabled = 1; + printf_unfiltered ("\n"); + } } -/* Get the register from the frame and make a printable representation - of it in the data element. */ +/* Complete names of register groups, and add the special "prev" and "next" + names. */ + static void -tui_register_format (struct gdbarch *gdbarch, struct frame_info *frame, - struct tui_data_element *data_element, int regnum) +tui_reggroup_completer (struct cmd_list_element *ignore, + completion_tracker &tracker, + const char *text, const char *word) { - struct ui_file *stream; - struct ui_file *old_stdout; - const char *name; - struct cleanup *cleanups; - char *p, *s; - int pos; - struct type *type = register_type (gdbarch, regnum); - - name = gdbarch_register_name (gdbarch, regnum); - if (name == 0) - { - return; - } - - pagination_enabled = 0; - old_stdout = gdb_stdout; - stream = tui_sfileopen (256); - gdb_stdout = stream; - cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout); - if (TYPE_VECTOR (type) != 0 && 0) - { - gdb_byte buf[MAX_REGISTER_SIZE]; - int len; + static const char *extra[] = { "next", "prev", NULL }; + size_t len = strlen (word); + const char **tmp; - len = register_size (current_gdbarch, regnum); - fprintf_filtered (stream, "%-14s ", name); - get_frame_register (frame, regnum, buf); - print_scalar_formatted (buf, type, 'f', len, stream); - } - else + reggroup_completer (ignore, tracker, text, word); + + /* XXXX use complete_on_enum instead? */ + for (tmp = extra; *tmp != NULL; ++tmp) { - gdbarch_print_registers_info (current_gdbarch, stream, - frame, regnum, 1); + if (strncmp (word, *tmp, len) == 0) + tracker.add_completion (make_unique_xstrdup (*tmp)); } +} + +/* Get the register from the frame and return a printable + representation of it. */ + +static char * +tui_register_format (struct frame_info *frame, int regnum) +{ + struct gdbarch *gdbarch = get_frame_arch (frame); + + string_file stream; + + scoped_restore save_pagination + = make_scoped_restore (&pagination_enabled, 0); + scoped_restore save_stdout + = make_scoped_restore (&gdb_stdout, &stream); - /* Save formatted output in the buffer. */ - p = tui_file_get_strbuf (stream); + gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1); /* Remove the possible \n. */ - s = strrchr (p, '\n'); - if (s && s[1] == 0) - *s = 0; + std::string &str = stream.string (); + if (!str.empty () && str.back () == '\n') + str.resize (str.size () - 1); - xfree (data_element->content); - data_element->content = xstrdup (p); - do_cleanups (cleanups); + /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */ + return tui_expand_tabs (str.c_str (), 0); } -/* Get the register value from the given frame and format it for - the display. When changep is set, check if the new register value - has changed with respect to the previous call. */ -static enum tui_status -tui_get_register (struct gdbarch *gdbarch, struct frame_info *frame, - struct tui_data_element *data, int regnum, int *changedp) +/* Get the register value from the given frame and format it for the + display. When changep is set, check if the new register value has + changed with respect to the previous call. */ +static void +tui_get_register (struct frame_info *frame, + struct tui_data_item_window *data, + int regnum, bool *changedp) { - enum tui_status ret = TUI_FAILURE; - if (changedp) - *changedp = FALSE; + *changedp = false; if (target_has_registers) { - gdb_byte buf[MAX_REGISTER_SIZE]; - get_frame_register (frame, regnum, buf); + char *prev_content = data->content; - if (changedp) - { - int size = register_size (gdbarch, regnum); - char *old = (char*) data->value; - int i; - - for (i = 0; i < size; i++) - if (buf[i] != old[i]) - { - *changedp = TRUE; - old[i] = buf[i]; - } - } + data->content = tui_register_format (frame, regnum); - /* Reformat the data content if the value changed. */ - if (changedp == 0 || *changedp == TRUE) - tui_register_format (gdbarch, frame, data, regnum); + if (changedp != NULL + && strcmp (prev_content, data->content) != 0) + *changedp = true; - ret = TUI_SUCCESS; + xfree (prev_content); } - return ret; } -static void -tui_scroll_regs_forward_command (char *arg, int from_tty) +void +_initialize_tui_regs (void) { - tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1); -} + struct cmd_list_element **tuicmd, *cmd; + tuicmd = tui_get_cmd_list (); -static void -tui_scroll_regs_backward_command (char *arg, int from_tty) -{ - tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1); + cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\ +TUI command to control the register window."), tuicmd); + set_cmd_completer (cmd, tui_reggroup_completer); }