X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Ftui%2Ftui-regs.c;h=48e78fc9dbc14755ee85e551fd299e7d64b0d56f;hb=8634b4628ea00a95ce3dfe8f9915724e8d710dad;hp=61918f82a9891e49a87f6dca7b33bbc8655263b9;hpb=63ed81829ea8819bc96b288f95230876b0060b14;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/tui/tui-regs.c b/gdb/tui/tui-regs.c index 61918f82a9..48e78fc9db 100644 --- a/gdb/tui/tui-regs.c +++ b/gdb/tui/tui-regs.c @@ -1,6 +1,6 @@ /* TUI display registers in window. - Copyright (C) 1998-2015 Free Software Foundation, Inc. + Copyright (C) 1998-2019 Free Software Foundation, Inc. Contributed by Hewlett-Packard Company. @@ -32,72 +32,89 @@ #include "target.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" +/* Get the register from the frame and return a printable + representation of it. */ -/***************************************** -** STATIC LOCAL FUNCTIONS FORWARD DECLS ** -******************************************/ -static void -tui_display_register (struct tui_data_element *data, - struct tui_gen_win_info *win_info); +static gdb::unique_xmalloc_ptr +tui_register_format (struct frame_info *frame, int regnum) +{ + struct gdbarch *gdbarch = get_frame_arch (frame); -static enum tui_status tui_show_register_group (struct reggroup *group, - struct frame_info *frame, - int refresh_values_only); + string_file stream; -static enum tui_status tui_get_register (struct frame_info *frame, - struct tui_data_element *data, - int regnum, int *changedp); + scoped_restore save_pagination + = make_scoped_restore (&pagination_enabled, 0); + scoped_restore save_stdout + = make_scoped_restore (&gdb_stdout, &stream); + gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1); + /* Remove the possible \n. */ + std::string &str = stream.string (); + if (!str.empty () && str.back () == '\n') + str.resize (str.size () - 1); -/***************************************** -** PUBLIC FUNCTIONS ** -******************************************/ + /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */ + return tui_expand_tabs (str.c_str ()); +} -/* 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) +/* 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) { - int num_lines = (-1); - - if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0) + if (changedp) + *changedp = false; + if (target_has_registers) { - 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++; + gdb::unique_xmalloc_ptr new_content + = tui_register_format (frame, regnum); + + if (changedp != NULL + && strcmp (data->content.get (), new_content.get ()) != 0) + *changedp = true; + + data->content = std::move (new_content); } +} + +/* See tui-regs.h. */ + +int +tui_data_window::last_regs_line_no () const +{ + int 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++; @@ -109,73 +126,40 @@ 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); } - /* Show the registers of the given group in the data window and refresh the window. */ void -tui_show_registers (struct reggroup *group) +tui_data_window::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); - - 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; - if (target_has_registers && target_has_stack && target_has_memory) { - ret = tui_show_register_group (group, get_selected_frame (NULL), - group == display_info->current_group); - } - if (ret == TUI_FAILURE) - { - display_info->current_group = 0; - tui_erase_data_content (NO_REGS_STRING); + show_register_group (group, get_selected_frame (NULL), + group == current_group); + + /* Clear all notation of changed values. */ + for (auto &&data_item_win : regs_content) + data_item_win.highlight = false; + current_group = group; + rerender (); } else { - int i; - - /* Clear all notation of changed values. */ - for (i = 0; i < display_info->regs_content_count; i++) - { - 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 = data_item_win->content[0]; - win->which_element.data.highlight = FALSE; - } - display_info->current_group = group; - tui_display_all_data (); + current_group = 0; + erase_data_content (_("[ Register Values Unavailable ]")); } } @@ -184,31 +168,21 @@ tui_show_registers (struct reggroup *group) using the given frame. Values are refreshed only when refresh_values_only is TRUE. */ -static enum tui_status -tui_show_register_group (struct reggroup *group, - struct frame_info *frame, - int refresh_values_only) +void +tui_data_window::show_register_group (struct reggroup *group, + struct frame_info *frame, + int refresh_values_only) { struct gdbarch *gdbarch = get_frame_arch (frame); - enum tui_status ret = TUI_FAILURE; 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); + title = string_printf ("Register group: %s", reggroup_name (group)); /* See how many registers must be displayed. */ nr_regs = 0; - for (regnum = 0; - regnum < gdbarch_num_regs (gdbarch) - + gdbarch_num_pseudo_regs (gdbarch); - regnum++) + for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++) { const char *name; @@ -225,487 +199,468 @@ tui_show_register_group (struct reggroup *group, nr_regs++; } - 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; - } + regs_content.resize (nr_regs); - if (display_info->regs_content_count <= 0) + /* Now set the register names and values. */ + pos = 0; + for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++) { - display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN); - allocated_here = TRUE; - refresh_values_only = FALSE; - } + struct tui_data_item_window *data_item_win; + const char *name; - if (display_info->regs_content != (tui_win_content) NULL) - { - 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; - } + /* Must be in the group. */ + if (!gdbarch_register_reggroup_p (gdbarch, regnum, group)) + continue; - /* Now set the register names and values. */ - pos = 0; - for (regnum = 0; - regnum < gdbarch_num_regs (gdbarch) - + gdbarch_num_pseudo_regs (gdbarch); - regnum++) - { - struct tui_gen_win_info *data_item_win; - struct tui_data_element *data; - const char *name; - - /* 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; - - data_item_win = - &display_info->regs_content[pos]->which_element.data_window; - data = &data_item_win->content[0]->which_element.data; - if (data) - { - if (!refresh_values_only) - { - data->item_no = regnum; - data->name = name; - data->highlight = FALSE; - } - tui_get_register (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 = ®s_content[pos]; + 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; + int j, item_win_width, cur_y; - if (display_info->regs_content != (tui_win_content) NULL - && display_info->regs_content_count > 0) + int max_len = 0; + for (auto &&data_item_win : regs_content) { - int i = start_element_no; - int j, item_win_width, cur_y; - - int max_len = 0; - for (i = 0; i < display_info->regs_content_count; i++) - { - 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 = &data_item_win->content[0]->which_element.data; - len = 0; - p = data->content; - if (p != 0) - while (*p) - { - if (*p++ == '\t') - len = 8 * ((len / 8) + 1); - else - len++; - } - - if (len > max_len) - 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. */ - cur_y = 1; - while (i < display_info->regs_content_count - && cur_y <= TUI_DATA_WIN->generic.viewport_height) + const char *p; + int len; + + len = 0; + p = data_item_win.content.get (); + if (p != 0) + len = strlen (p); + + if (len > max_len) + max_len = len; + } + item_win_width = max_len + 1; + 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 < regs_content.size () + && cur_y <= viewport_height) + { + for (j = 0; + j < regs_column_count && i < regs_content.size (); + j++) { - for (j = 0; - j < display_info->regs_column_count - && i < display_info->regs_content_count; - 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 = &data_item_win->content[0]->which_element.data; - if (data_item_win->handle != (WINDOW*) 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_delete_win (data_item_win->handle); - data_item_win->handle = 0; - } - - if (data_item_win->handle == (WINDOW *) 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); - 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. */ - } - cur_y++; /* Next row. */ + /* Create the window if necessary. */ + regs_content[i].resize (1, item_win_width, + (item_win_width * j) + 1, cur_y); + i++; /* Next register. */ } + 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. */ -static void -tui_display_reg_element_at_line (int start_element_no, - int start_line_no) +void +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) + int element_no = start_element_no; + + if (start_element_no != 0 && start_line_no != 0) { - int element_no = start_element_no; + int last_line_no, first_line_on_last_page; + + 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 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); + } + display_registers_from (element_no); +} + +/* See tui-regs.h. */ - if (start_element_no != 0 && start_line_no != 0) +int +tui_data_window::display_registers_from_line (int line_no) +{ + int element_no; + + if (line_no < 0) + line_no = 0; + else + { + /* Make sure that we don't display off the end of the + registers. */ + if (line_no >= last_regs_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); - 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); + line_no = line_from_reg_element_no (regs_content.size () - 1); + if (line_no < 0) + line_no = 0; } - tui_display_registers_from (element_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_no = (-1); + + return line_no; +} -/* 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. */ +/* Answer the index first element displayed. If none are displayed, + then return (-1). */ int -tui_display_registers_from_line (int line_no, - int force_display) +tui_data_window::first_data_item_displayed () { - if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0) + for (int i = 0; i < regs_content.size (); i++) { - int line, 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 ()) - { - if ((line = tui_line_from_reg_element_no ( - TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0) - line = 0; - } - else - line = line_no; - } - else - line = line_no; - - 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); - else - line = (-1); + struct tui_gen_win_info *data_item_win; - return line; + data_item_win = ®s_content[i]; + if (data_item_win->is_visible ()) + return i; } - return (-1); /* Nothing was displayed. */ + return -1; } +/* See tui-regs.h. */ -/* This function check all displayed registers for changes in values, - given a particular frame. If the values have changed, they are - updated with the new value and highlighted. */ void -tui_check_register_values (struct frame_info *frame) +tui_data_window::delete_data_content_windows () { - if (TUI_DATA_WIN != NULL - && TUI_DATA_WIN->generic.is_visible) + for (auto &&win : regs_content) { - struct tui_data_info *display_info - = &TUI_DATA_WIN->detail.data_display_info; + tui_delete_win (win.handle); + win.handle = NULL; + } +} - if (display_info->regs_content_count <= 0 - && display_info->display_regs) - tui_show_registers (display_info->current_group); - else - { - int i; - for (i = 0; (i < display_info->regs_content_count); i++) - { - 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 = &data_item_win_ptr->content[0]->which_element.data; - was_hilighted = data->highlight; - - tui_get_register (frame, data, - data->item_no, &data->highlight); - - if (data->highlight || was_hilighted) - { - tui_display_register (data, data_item_win_ptr); - } - } - } +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 + x_pos = half_width - strlen (prompt); + mvwaddstr (handle, (height / 2), x_pos, (char *) prompt); } + wrefresh (handle); } -/* 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) +/* See tui-regs.h. */ + +void +tui_data_window::rerender () { - if (win_info->handle != (WINDOW *) NULL) + if (regs_content.empty ()) + erase_data_content (_("[ Register Values Unavailable ]")); + else { - int i; - - if (data->highlight) - /* 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 (win_info->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); - if (data->content) - waddstr (win_info->handle, data->content); - - if (data->highlight) - /* 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 (win_info->handle); - tui_refresh_win (win_info); + erase_data_content (NULL); + delete_data_content_windows (); + display_registers_from (0); } } -static void -tui_reg_next_command (char *arg, int from_tty) + +/* Scroll the data window vertically forward or backward. */ +void +tui_data_window::do_scroll_vertical (int num_to_scroll) { - struct gdbarch *gdbarch = get_current_arch (); + 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 (TUI_DATA_WIN != 0) + if (first_line >= 0) { - struct reggroup *group - = TUI_DATA_WIN->detail.data_display_info.current_group; + first_line += num_to_scroll; + erase_data_content (NULL); + delete_data_content_windows (); + display_registers_from_line (first_line); + } +} - group = reggroup_next (gdbarch, group); - if (group == 0) - group = reggroup_next (gdbarch, 0); +/* See tui-regs.h. */ - if (group) - tui_show_registers (group); - } +void +tui_data_window::refresh_window () +{ + tui_gen_win_info::refresh_window (); + for (auto &&win : regs_content) + win.refresh_window (); } -static void -tui_reg_float_command (char *arg, int from_tty) +/* This function check all displayed registers for changes in values, + given a particular frame. If the values have changed, they are + updated with the new value and highlighted. */ +void +tui_data_window::check_register_values (struct frame_info *frame) { - tui_show_registers (float_reggroup); + if (regs_content.empty ()) + show_registers (current_group); + else + { + for (auto &&data_item_win : regs_content) + { + int was_hilighted; + + was_hilighted = data_item_win.highlight; + + tui_get_register (frame, &data_item_win, + data_item_win.item_no, + &data_item_win.highlight); + + if (data_item_win.highlight || was_hilighted) + data_item_win.rerender (); + } + } } -static void -tui_reg_general_command (char *arg, int from_tty) +/* Display a register in a window. If hilite is TRUE, then the value + will be displayed in reverse video. */ +void +tui_data_item_window::rerender () { - tui_show_registers (general_reggroup); + int i; + + scrollok (handle, FALSE); + if (highlight) + /* 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 (handle); + + wmove (handle, 0, 0); + for (i = 1; i < width; i++) + waddch (handle, ' '); + wmove (handle, 0, 0); + if (content) + waddstr (handle, content.get ()); + + if (highlight) + /* 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 (handle); + refresh_window (); } -static void -tui_reg_system_command (char *arg, int from_tty) +void +tui_data_item_window::refresh_window () { - tui_show_registers (system_reggroup); + if (handle != nullptr) + { + /* This seems to be needed because the data items are nested + windows, which according to the ncurses man pages aren't well + supported. */ + touchwin (handle); + wrefresh (handle); + } } -static struct cmd_list_element *tuireglist; +/* 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 void -tui_reg_command (char *args, int from_tty) +static struct reggroup * +tui_reg_next (struct reggroup *current_group, struct gdbarch *gdbarch) { - 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 reggroup *group = NULL; + + if (current_group != NULL) + { + group = reggroup_next (gdbarch, current_group); + if (group == NULL) + group = reggroup_next (gdbarch, NULL); + } + return group; } -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern initialize_file_ftype _initialize_tui_regs; +/* 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. */ -void -_initialize_tui_regs (void) +static struct reggroup * +tui_reg_prev (struct reggroup *current_group, struct gdbarch *gdbarch) { - struct cmd_list_element **tuicmd; + struct reggroup *group = NULL; - 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); + if (current_group != NULL) + { + group = reggroup_prev (gdbarch, current_group); + if (group == NULL) + group = reggroup_prev (gdbarch, NULL); + } + return group; } - -/***************************************** -** STATIC LOCAL FUNCTIONS ** -******************************************/ +/* A helper function to display the register window in the appropriate + way. */ static void -tui_restore_gdbout (void *ui) +tui_reg_layout () { - ui_file_delete (gdb_stdout); - gdb_stdout = (struct ui_file*) ui; - pagination_enabled = 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 + new_layout = DISASSEM_DATA_COMMAND; + tui_set_layout (new_layout); } -/* Get the register from the frame and return a printable - representation of it. */ +/* 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 char * -tui_register_format (struct frame_info *frame, int regnum) +static void +tui_reg_command (const char *args, int from_tty) { - struct gdbarch *gdbarch = get_frame_arch (frame); - struct ui_file *stream; - struct ui_file *old_stdout; - struct cleanup *cleanups; - char *p, *s; - char *ret; - - pagination_enabled = 0; - old_stdout = gdb_stdout; - stream = tui_sfileopen (256); - gdb_stdout = stream; - cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout); - gdbarch_print_registers_info (gdbarch, stream, frame, regnum, 1); - - /* Save formatted output in the buffer. */ - p = tui_file_get_strbuf (stream); + struct gdbarch *gdbarch = get_current_arch (); - /* Remove the possible \n. */ - s = strrchr (p, '\n'); - if (s && s[1] == 0) - *s = 0; + 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->get_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; + } + } - /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */ - ret = tui_expand_tabs (p, 0); + if (match == NULL) + error (_("unknown register group '%s'"), args); - do_cleanups (cleanups); + TUI_DATA_WIN->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)); + } - return ret; + printf_unfiltered ("\n"); + } } -/* 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 frame_info *frame, - struct tui_data_element *data, - int regnum, int *changedp) +/* Complete names of register groups, and add the special "prev" and "next" + names. */ + +static void +tui_reggroup_completer (struct cmd_list_element *ignore, + completion_tracker &tracker, + const char *text, const char *word) { - enum tui_status ret = TUI_FAILURE; + static const char *extra[] = { "next", "prev", NULL }; + size_t len = strlen (word); + const char **tmp; - if (changedp) - *changedp = FALSE; - if (target_has_registers) - { - char *prev_content = data->content; + reggroup_completer (ignore, tracker, text, word); - data->content = tui_register_format (frame, regnum); + /* XXXX use complete_on_enum instead? */ + for (tmp = extra; *tmp != NULL; ++tmp) + { + if (strncmp (word, *tmp, len) == 0) + tracker.add_completion (make_unique_xstrdup (*tmp)); + } +} - if (changedp != NULL - && strcmp (prev_content, data->content) != 0) - *changedp = 1; +void +_initialize_tui_regs (void) +{ + struct cmd_list_element **tuicmd, *cmd; - xfree (prev_content); + tuicmd = tui_get_cmd_list (); - ret = TUI_SUCCESS; - } - return ret; + cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\ +TUI command to control the register window."), tuicmd); + set_cmd_completer (cmd, tui_reggroup_completer); }