1 /* TUI display registers in window.
3 Copyright (C) 1998-2019 Free Software Foundation, Inc.
5 Contributed by Hewlett-Packard Company.
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 #include "arch-utils.h"
25 #include "tui/tui-data.h"
33 #include "tui/tui-layout.h"
34 #include "tui/tui-win.h"
35 #include "tui/tui-windata.h"
36 #include "tui/tui-wingeneral.h"
37 #include "tui/tui-file.h"
38 #include "tui/tui-regs.h"
39 #include "tui/tui-io.h"
40 #include "reggroups.h"
42 #include "completer.h"
44 #include "gdb_curses.h"
47 /*****************************************
48 ** STATIC LOCAL FUNCTIONS FORWARD DECLS **
49 ******************************************/
50 static void tui_display_register (struct tui_data_item_window *data);
52 static void tui_show_register_group (tui_data_window *win_info,
53 struct reggroup *group,
54 struct frame_info *frame,
55 int refresh_values_only);
57 static enum tui_status tui_get_register (struct frame_info *frame,
58 struct tui_data_item_window *data,
59 int regnum, bool *changedp);
63 /*****************************************
64 ** PUBLIC FUNCTIONS **
65 ******************************************/
70 tui_data_window::last_regs_line_no () const
74 if (!regs_content.empty ())
76 num_lines = regs_content.size () / regs_column_count;
77 if (regs_content.size () % regs_column_count)
86 tui_data_window::line_from_reg_element_no (int element_no) const
88 if (element_no < regs_content.size ())
95 if (element_no < regs_column_count * i)
107 /* See tui-data.h. */
110 tui_data_window::first_reg_element_no_inline (int line_no) const
112 if (line_no * regs_column_count <= regs_content.size ())
113 return ((line_no + 1) * regs_column_count) - regs_column_count;
119 /* Show the registers of the given group in the data window
120 and refresh the window. */
122 tui_show_registers (struct reggroup *group)
124 /* Make sure the curses mode is enabled. */
127 /* Make sure the register window is visible. If not, select an
128 appropriate layout. */
129 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible)
130 tui_set_layout_by_name (DATA_NAME);
133 group = general_reggroup;
135 /* Say that registers should be displayed, even if there is a
137 TUI_DATA_WIN->display_regs = true;
139 if (target_has_registers && target_has_stack && target_has_memory)
141 tui_show_register_group (TUI_DATA_WIN, group, get_selected_frame (NULL),
142 group == TUI_DATA_WIN->current_group);
144 /* Clear all notation of changed values. */
145 for (auto &&data_item_win : TUI_DATA_WIN->regs_content)
147 if (data_item_win != nullptr)
148 data_item_win->highlight = false;
150 TUI_DATA_WIN->current_group = group;
151 TUI_DATA_WIN->display_all_data ();
155 TUI_DATA_WIN->current_group = 0;
156 TUI_DATA_WIN->erase_data_content (NO_REGS_STRING);
161 /* Set the data window to display the registers of the register group
162 using the given frame. Values are refreshed only when
163 refresh_values_only is TRUE. */
166 tui_show_register_group (tui_data_window *win_info,
167 struct reggroup *group,
168 struct frame_info *frame,
169 int refresh_values_only)
171 struct gdbarch *gdbarch = get_frame_arch (frame);
176 /* Make a new title showing which group we display. */
177 snprintf (title, sizeof (title) - 1, "Register group: %s",
178 reggroup_name (group));
179 xfree (win_info->title);
180 win_info->title = xstrdup (title);
182 /* See how many registers must be displayed. */
184 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
188 /* Must be in the group. */
189 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
192 /* If the register name is empty, it is undefined for this
193 processor, so don't display anything. */
194 name = gdbarch_register_name (gdbarch, regnum);
195 if (name == 0 || *name == '\0')
201 if (!refresh_values_only)
202 win_info->regs_content.clear ();
204 if (nr_regs < win_info->regs_content.size ())
205 win_info->regs_content.resize (nr_regs);
208 for (int i = win_info->regs_content.size (); i < nr_regs; ++i)
209 win_info->regs_content.emplace_back (new tui_data_item_window ());
212 /* Now set the register names and values. */
214 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
216 struct tui_data_item_window *data_item_win;
219 /* Must be in the group. */
220 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
223 /* If the register name is empty, it is undefined for this
224 processor, so don't display anything. */
225 name = gdbarch_register_name (gdbarch, regnum);
226 if (name == 0 || *name == '\0')
229 data_item_win = win_info->regs_content[pos].get ();
232 if (!refresh_values_only)
234 data_item_win->item_no = regnum;
235 data_item_win->name = name;
236 data_item_win->highlight = false;
238 tui_get_register (frame, data_item_win, regnum, 0);
244 /* See tui-data.h. */
247 tui_data_window::display_registers_from (int start_element_no)
249 if (!regs_content.empty ())
251 int j, item_win_width, cur_y;
254 for (auto &&data_item_win : regs_content)
260 p = data_item_win->content;
265 len = 8 * ((len / 8) + 1);
273 item_win_width = max_len + 1;
274 int i = start_element_no;
276 regs_column_count = (width - 2) / item_win_width;
277 if (regs_column_count == 0)
278 regs_column_count = 1;
279 item_win_width = (width - 2) / regs_column_count;
281 /* Now create each data "sub" window, and write the display into
284 while (i < regs_content.size ()
285 && cur_y <= viewport_height)
288 j < regs_column_count && i < regs_content.size ();
291 struct tui_data_item_window *data_item_win;
293 /* Create the window if necessary. */
294 data_item_win = regs_content[i].get ();
295 if (data_item_win->handle != NULL
296 && (data_item_win->height != 1
297 || data_item_win->width != item_win_width
298 || data_item_win->origin.x != (item_win_width * j) + 1
299 || data_item_win->origin.y != cur_y))
301 tui_delete_win (data_item_win->handle);
302 data_item_win->handle = 0;
305 if (data_item_win->handle == NULL)
307 data_item_win->height = 1;
308 data_item_win->width = item_win_width;
309 data_item_win->origin.x = (item_win_width * j) + 1;
310 data_item_win->origin.y = cur_y;
311 tui_make_window (data_item_win, DONT_BOX_WINDOW);
312 scrollok (data_item_win->handle, FALSE);
314 touchwin (data_item_win->handle);
316 /* Get the printable representation of the register
318 tui_display_register (data_item_win);
319 i++; /* Next register. */
321 cur_y++; /* Next row. */
326 /* See tui-data.h. */
329 tui_data_window::display_reg_element_at_line (int start_element_no,
332 if (!regs_content.empty ())
334 int element_no = start_element_no;
336 if (start_element_no != 0 && start_line_no != 0)
338 int last_line_no, first_line_on_last_page;
340 last_line_no = last_regs_line_no ();
341 first_line_on_last_page = last_line_no - (height - 2);
342 if (first_line_on_last_page < 0)
343 first_line_on_last_page = 0;
345 /* If the element_no causes us to scroll past the end of the
346 registers, adjust what element to really start the
348 if (start_line_no > first_line_on_last_page)
349 element_no = first_reg_element_no_inline (first_line_on_last_page);
351 display_registers_from (element_no);
355 /* See tui-data.h. */
358 tui_data_window::display_registers_from_line (int line_no)
360 tui_check_and_display_highlight_if_needed (this);
361 if (!regs_content.empty ())
369 /* Make sure that we don't display off the end of the
371 if (line_no >= last_regs_line_no ())
373 line_no = line_from_reg_element_no (regs_content.size () - 1);
379 element_no = first_reg_element_no_inline (line_no);
380 if (element_no < regs_content.size ())
381 display_reg_element_at_line (element_no, line_no);
388 return (-1); /* Nothing was displayed. */
392 /* This function check all displayed registers for changes in values,
393 given a particular frame. If the values have changed, they are
394 updated with the new value and highlighted. */
396 tui_check_register_values (struct frame_info *frame)
398 if (TUI_DATA_WIN != NULL
399 && TUI_DATA_WIN->is_visible)
401 if (TUI_DATA_WIN->regs_content.empty ()
402 && TUI_DATA_WIN->display_regs)
403 tui_show_registers (TUI_DATA_WIN->current_group);
406 for (auto &&data_item_win_ptr : TUI_DATA_WIN->regs_content)
410 was_hilighted = data_item_win_ptr->highlight;
412 tui_get_register (frame, data_item_win_ptr.get (),
413 data_item_win_ptr->item_no,
414 &data_item_win_ptr->highlight);
416 if (data_item_win_ptr->highlight || was_hilighted)
417 tui_display_register (data_item_win_ptr.get ());
423 /* Display a register in a window. If hilite is TRUE, then the value
424 will be displayed in reverse video. */
426 tui_display_register (struct tui_data_item_window *data)
428 if (data->handle != NULL)
433 /* We ignore the return value, casting it to void in order to avoid
434 a compiler warning. The warning itself was introduced by a patch
435 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
436 to code that causes the compiler to generate an unused-value
438 (void) wstandout (data->handle);
440 wmove (data->handle, 0, 0);
441 for (i = 1; i < data->width; i++)
442 waddch (data->handle, ' ');
443 wmove (data->handle, 0, 0);
445 waddstr (data->handle, data->content);
448 /* We ignore the return value, casting it to void in order to avoid
449 a compiler warning. The warning itself was introduced by a patch
450 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
451 to code that causes the compiler to generate an unused-value
453 (void) wstandend (data->handle);
454 data->refresh_window ();
458 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
459 around behaviour. Returns the next register group, or NULL if the
460 register window is not currently being displayed. */
462 static struct reggroup *
463 tui_reg_next (struct gdbarch *gdbarch)
465 struct reggroup *group = NULL;
467 if (TUI_DATA_WIN != NULL)
469 group = TUI_DATA_WIN->current_group;
470 group = reggroup_next (gdbarch, group);
472 group = reggroup_next (gdbarch, NULL);
477 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
478 around behaviour. Returns the previous register group, or NULL if the
479 register window is not currently being displayed. */
481 static struct reggroup *
482 tui_reg_prev (struct gdbarch *gdbarch)
484 struct reggroup *group = NULL;
486 if (TUI_DATA_WIN != NULL)
488 group = TUI_DATA_WIN->current_group;
489 group = reggroup_prev (gdbarch, group);
491 group = reggroup_prev (gdbarch, NULL);
496 /* Implement the 'tui reg' command. Changes the register group displayed
497 in the tui register window. Displays the tui register window if it is
498 not already on display. */
501 tui_reg_command (const char *args, int from_tty)
503 struct gdbarch *gdbarch = get_current_arch ();
507 struct reggroup *group, *match = NULL;
508 size_t len = strlen (args);
510 /* Make sure the curses mode is enabled. */
513 /* Make sure the register window is visible. If not, select an
514 appropriate layout. We need to do this before trying to run the
515 'next' or 'prev' commands. */
516 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible)
517 tui_set_layout_by_name (DATA_NAME);
519 if (strncmp (args, "next", len) == 0)
520 match = tui_reg_next (gdbarch);
521 else if (strncmp (args, "prev", len) == 0)
522 match = tui_reg_prev (gdbarch);
524 /* This loop matches on the initial part of a register group
525 name. If this initial part in ARGS matches only one register
526 group then the switch is made. */
527 for (group = reggroup_next (gdbarch, NULL);
529 group = reggroup_next (gdbarch, group))
531 if (strncmp (reggroup_name (group), args, len) == 0)
534 error (_("ambiguous register group name '%s'"), args);
540 error (_("unknown register group '%s'"), args);
542 tui_show_registers (match);
546 struct reggroup *group;
549 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
550 "either a register group,\nor one of 'next' "
551 "or 'prev'. Known register groups are:\n"));
553 for (first = 1, group = reggroup_next (gdbarch, NULL);
555 first = 0, group = reggroup_next (gdbarch, group))
558 printf_unfiltered (", ");
559 printf_unfiltered ("%s", reggroup_name (group));
562 printf_unfiltered ("\n");
566 /* Complete names of register groups, and add the special "prev" and "next"
570 tui_reggroup_completer (struct cmd_list_element *ignore,
571 completion_tracker &tracker,
572 const char *text, const char *word)
574 static const char *extra[] = { "next", "prev", NULL };
575 size_t len = strlen (word);
578 reggroup_completer (ignore, tracker, text, word);
580 /* XXXX use complete_on_enum instead? */
581 for (tmp = extra; *tmp != NULL; ++tmp)
583 if (strncmp (word, *tmp, len) == 0)
584 tracker.add_completion (make_unique_xstrdup (*tmp));
589 _initialize_tui_regs (void)
591 struct cmd_list_element **tuicmd, *cmd;
593 tuicmd = tui_get_cmd_list ();
595 cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
596 TUI command to control the register window."), tuicmd);
597 set_cmd_completer (cmd, tui_reggroup_completer);
601 /*****************************************
602 ** STATIC LOCAL FUNCTIONS **
603 ******************************************/
605 /* Get the register from the frame and return a printable
606 representation of it. */
609 tui_register_format (struct frame_info *frame, int regnum)
611 struct gdbarch *gdbarch = get_frame_arch (frame);
615 scoped_restore save_pagination
616 = make_scoped_restore (&pagination_enabled, 0);
617 scoped_restore save_stdout
618 = make_scoped_restore (&gdb_stdout, &stream);
620 gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
622 /* Remove the possible \n. */
623 std::string &str = stream.string ();
624 if (!str.empty () && str.back () == '\n')
625 str.resize (str.size () - 1);
627 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
628 return tui_expand_tabs (str.c_str (), 0);
631 /* Get the register value from the given frame and format it for the
632 display. When changep is set, check if the new register value has
633 changed with respect to the previous call. */
634 static enum tui_status
635 tui_get_register (struct frame_info *frame,
636 struct tui_data_item_window *data,
637 int regnum, bool *changedp)
639 enum tui_status ret = TUI_FAILURE;
643 if (target_has_registers)
645 char *prev_content = data->content;
647 data->content = tui_register_format (frame, regnum);
650 && strcmp (prev_content, data->content) != 0)
653 xfree (prev_content);