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-wingeneral.h"
36 #include "tui/tui-file.h"
37 #include "tui/tui-regs.h"
38 #include "tui/tui-io.h"
39 #include "reggroups.h"
41 #include "completer.h"
43 #include "gdb_curses.h"
45 static void tui_display_register (struct tui_data_item_window
*data
);
47 static void tui_show_register_group (tui_data_window
*win_info
,
48 struct reggroup
*group
,
49 struct frame_info
*frame
,
50 int refresh_values_only
);
52 static void tui_get_register (struct frame_info
*frame
,
53 struct tui_data_item_window
*data
,
54 int regnum
, bool *changedp
);
59 tui_data_item_window::~tui_data_item_window ()
68 tui_data_window::last_regs_line_no () const
72 if (!regs_content
.empty ())
74 num_lines
= regs_content
.size () / regs_column_count
;
75 if (regs_content
.size () % regs_column_count
)
84 tui_data_window::line_from_reg_element_no (int element_no
) const
86 if (element_no
< regs_content
.size ())
93 if (element_no
< regs_column_count
* i
)
105 /* See tui-regs.h. */
108 tui_data_window::first_reg_element_no_inline (int line_no
) const
110 if (line_no
* regs_column_count
<= regs_content
.size ())
111 return ((line_no
+ 1) * regs_column_count
) - regs_column_count
;
116 /* A helper function to display the register window in the appropriate
122 enum tui_layout_type cur_layout
= tui_current_layout ();
123 enum tui_layout_type new_layout
;
124 if (cur_layout
== SRC_COMMAND
|| cur_layout
== SRC_DATA_COMMAND
)
125 new_layout
= SRC_DATA_COMMAND
;
127 new_layout
= DISASSEM_DATA_COMMAND
;
128 tui_set_layout (new_layout
);
131 /* Show the registers of the given group in the data window
132 and refresh the window. */
134 tui_show_registers (struct reggroup
*group
)
136 /* Make sure the curses mode is enabled. */
139 /* Make sure the register window is visible. If not, select an
140 appropriate layout. */
141 if (TUI_DATA_WIN
== NULL
|| !TUI_DATA_WIN
->is_visible ())
145 group
= general_reggroup
;
147 /* Say that registers should be displayed, even if there is a
149 TUI_DATA_WIN
->display_regs
= true;
151 if (target_has_registers
&& target_has_stack
&& target_has_memory
)
153 tui_show_register_group (TUI_DATA_WIN
, group
, get_selected_frame (NULL
),
154 group
== TUI_DATA_WIN
->current_group
);
156 /* Clear all notation of changed values. */
157 for (auto &&data_item_win
: TUI_DATA_WIN
->regs_content
)
159 if (data_item_win
!= nullptr)
160 data_item_win
->highlight
= false;
162 TUI_DATA_WIN
->current_group
= group
;
163 TUI_DATA_WIN
->display_all_data ();
167 TUI_DATA_WIN
->current_group
= 0;
168 TUI_DATA_WIN
->erase_data_content (_("[ Register Values Unavailable ]"));
173 /* Set the data window to display the registers of the register group
174 using the given frame. Values are refreshed only when
175 refresh_values_only is TRUE. */
178 tui_show_register_group (tui_data_window
*win_info
,
179 struct reggroup
*group
,
180 struct frame_info
*frame
,
181 int refresh_values_only
)
183 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
188 /* Make a new title showing which group we display. */
189 snprintf (title
, sizeof (title
) - 1, "Register group: %s",
190 reggroup_name (group
));
191 xfree (win_info
->title
);
192 win_info
->title
= xstrdup (title
);
194 /* See how many registers must be displayed. */
196 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
200 /* Must be in the group. */
201 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
204 /* If the register name is empty, it is undefined for this
205 processor, so don't display anything. */
206 name
= gdbarch_register_name (gdbarch
, regnum
);
207 if (name
== 0 || *name
== '\0')
213 if (!refresh_values_only
)
214 win_info
->regs_content
.clear ();
216 if (nr_regs
< win_info
->regs_content
.size ())
217 win_info
->regs_content
.resize (nr_regs
);
220 for (int i
= win_info
->regs_content
.size (); i
< nr_regs
; ++i
)
221 win_info
->regs_content
.emplace_back (new tui_data_item_window ());
224 /* Now set the register names and values. */
226 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
228 struct tui_data_item_window
*data_item_win
;
231 /* Must be in the group. */
232 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
235 /* If the register name is empty, it is undefined for this
236 processor, so don't display anything. */
237 name
= gdbarch_register_name (gdbarch
, regnum
);
238 if (name
== 0 || *name
== '\0')
241 data_item_win
= win_info
->regs_content
[pos
].get ();
244 if (!refresh_values_only
)
246 data_item_win
->item_no
= regnum
;
247 data_item_win
->name
= name
;
248 data_item_win
->highlight
= false;
250 tui_get_register (frame
, data_item_win
, regnum
, 0);
256 /* See tui-regs.h. */
259 tui_data_window::display_registers_from (int start_element_no
)
261 if (!regs_content
.empty ())
263 int j
, item_win_width
, cur_y
;
266 for (auto &&data_item_win
: regs_content
)
272 p
= data_item_win
->content
;
277 len
= 8 * ((len
/ 8) + 1);
285 item_win_width
= max_len
+ 1;
286 int i
= start_element_no
;
288 regs_column_count
= (width
- 2) / item_win_width
;
289 if (regs_column_count
== 0)
290 regs_column_count
= 1;
291 item_win_width
= (width
- 2) / regs_column_count
;
293 /* Now create each data "sub" window, and write the display into
296 while (i
< regs_content
.size ()
297 && cur_y
<= viewport_height
)
300 j
< regs_column_count
&& i
< regs_content
.size ();
303 struct tui_data_item_window
*data_item_win
;
305 /* Create the window if necessary. */
306 data_item_win
= regs_content
[i
].get ();
307 if (data_item_win
->handle
!= NULL
308 && (data_item_win
->height
!= 1
309 || data_item_win
->width
!= item_win_width
310 || data_item_win
->origin
.x
!= (item_win_width
* j
) + 1
311 || data_item_win
->origin
.y
!= cur_y
))
313 tui_delete_win (data_item_win
->handle
);
314 data_item_win
->handle
= 0;
317 if (data_item_win
->handle
== NULL
)
319 data_item_win
->height
= 1;
320 data_item_win
->width
= item_win_width
;
321 data_item_win
->origin
.x
= (item_win_width
* j
) + 1;
322 data_item_win
->origin
.y
= cur_y
;
323 tui_make_window (data_item_win
);
324 scrollok (data_item_win
->handle
, FALSE
);
326 touchwin (data_item_win
->handle
);
328 /* Get the printable representation of the register
330 tui_display_register (data_item_win
);
331 i
++; /* Next register. */
333 cur_y
++; /* Next row. */
338 /* See tui-regs.h. */
341 tui_data_window::display_reg_element_at_line (int start_element_no
,
344 if (!regs_content
.empty ())
346 int element_no
= start_element_no
;
348 if (start_element_no
!= 0 && start_line_no
!= 0)
350 int last_line_no
, first_line_on_last_page
;
352 last_line_no
= last_regs_line_no ();
353 first_line_on_last_page
= last_line_no
- (height
- 2);
354 if (first_line_on_last_page
< 0)
355 first_line_on_last_page
= 0;
357 /* If the element_no causes us to scroll past the end of the
358 registers, adjust what element to really start the
360 if (start_line_no
> first_line_on_last_page
)
361 element_no
= first_reg_element_no_inline (first_line_on_last_page
);
363 display_registers_from (element_no
);
367 /* See tui-regs.h. */
370 tui_data_window::display_registers_from_line (int line_no
)
372 check_and_display_highlight_if_needed ();
373 if (!regs_content
.empty ())
381 /* Make sure that we don't display off the end of the
383 if (line_no
>= last_regs_line_no ())
385 line_no
= line_from_reg_element_no (regs_content
.size () - 1);
391 element_no
= first_reg_element_no_inline (line_no
);
392 if (element_no
< regs_content
.size ())
393 display_reg_element_at_line (element_no
, line_no
);
400 return (-1); /* Nothing was displayed. */
404 /* Answer the index first element displayed. If none are displayed,
407 tui_data_window::first_data_item_displayed ()
409 for (int i
= 0; i
< regs_content
.size (); i
++)
411 struct tui_gen_win_info
*data_item_win
;
413 data_item_win
= regs_content
[i
].get ();
414 if (data_item_win
->is_visible ())
421 /* See tui-regs.h. */
424 tui_data_window::delete_data_content_windows ()
426 for (auto &&win
: regs_content
)
428 tui_delete_win (win
->handle
);
435 tui_data_window::erase_data_content (const char *prompt
)
438 check_and_display_highlight_if_needed ();
441 int half_width
= (width
- 2) / 2;
444 if (strlen (prompt
) >= half_width
)
447 x_pos
= half_width
- strlen (prompt
);
448 mvwaddstr (handle
, (height
/ 2), x_pos
, (char *) prompt
);
453 /* See tui-regs.h. */
456 tui_data_window::display_all_data ()
458 if (regs_content
.empty ())
459 erase_data_content (NO_DATA_STRING
);
462 erase_data_content (NULL
);
463 delete_data_content_windows ();
464 check_and_display_highlight_if_needed ();
465 display_registers_from (0);
470 /* Function to redisplay the contents of the data window. */
472 tui_data_window::refresh_all ()
474 erase_data_content (NULL
);
475 if (!regs_content
.empty ())
477 int first_element
= first_data_item_displayed ();
479 if (first_element
>= 0) /* Re-use existing windows. */
481 int first_line
= (-1);
483 if (first_element
< regs_content
.size ())
484 first_line
= line_from_reg_element_no (first_element
);
488 erase_data_content (NULL
);
489 display_registers_from_line (first_line
);
496 /* Scroll the data window vertically forward or backward. */
498 tui_data_window::do_scroll_vertical (int num_to_scroll
)
500 int first_element_no
;
501 int first_line
= (-1);
503 first_element_no
= first_data_item_displayed ();
504 if (first_element_no
< regs_content
.size ())
505 first_line
= line_from_reg_element_no (first_element_no
);
507 { /* Calculate the first line from the element number which is in
508 the general data content. */
513 first_line
+= num_to_scroll
;
514 erase_data_content (NULL
);
515 delete_data_content_windows ();
516 display_registers_from_line (first_line
);
520 /* See tui-regs.h. */
523 tui_data_window::rerender ()
525 /* Delete all data item windows. */
526 for (auto &&win
: regs_content
)
528 tui_delete_win (win
->handle
);
534 /* See tui-regs.h. */
537 tui_data_window::refresh_window ()
539 tui_gen_win_info::refresh_window ();
540 for (auto &&win
: regs_content
)
543 win
->refresh_window ();
547 /* This function check all displayed registers for changes in values,
548 given a particular frame. If the values have changed, they are
549 updated with the new value and highlighted. */
551 tui_check_register_values (struct frame_info
*frame
)
553 if (TUI_DATA_WIN
!= NULL
554 && TUI_DATA_WIN
->is_visible ())
556 if (TUI_DATA_WIN
->regs_content
.empty ()
557 && TUI_DATA_WIN
->display_regs
)
558 tui_show_registers (TUI_DATA_WIN
->current_group
);
561 for (auto &&data_item_win_ptr
: TUI_DATA_WIN
->regs_content
)
565 was_hilighted
= data_item_win_ptr
->highlight
;
567 tui_get_register (frame
, data_item_win_ptr
.get (),
568 data_item_win_ptr
->item_no
,
569 &data_item_win_ptr
->highlight
);
571 if (data_item_win_ptr
->highlight
|| was_hilighted
)
572 tui_display_register (data_item_win_ptr
.get ());
578 /* Display a register in a window. If hilite is TRUE, then the value
579 will be displayed in reverse video. */
581 tui_display_register (struct tui_data_item_window
*data
)
583 if (data
->handle
!= NULL
)
588 /* We ignore the return value, casting it to void in order to avoid
589 a compiler warning. The warning itself was introduced by a patch
590 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
591 to code that causes the compiler to generate an unused-value
593 (void) wstandout (data
->handle
);
595 wmove (data
->handle
, 0, 0);
596 for (i
= 1; i
< data
->width
; i
++)
597 waddch (data
->handle
, ' ');
598 wmove (data
->handle
, 0, 0);
600 waddstr (data
->handle
, data
->content
);
603 /* We ignore the return value, casting it to void in order to avoid
604 a compiler warning. The warning itself was introduced by a patch
605 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
606 to code that causes the compiler to generate an unused-value
608 (void) wstandend (data
->handle
);
609 data
->refresh_window ();
613 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
614 around behaviour. Returns the next register group, or NULL if the
615 register window is not currently being displayed. */
617 static struct reggroup
*
618 tui_reg_next (struct reggroup
*current_group
, struct gdbarch
*gdbarch
)
620 struct reggroup
*group
= NULL
;
622 if (current_group
!= NULL
)
624 group
= reggroup_next (gdbarch
, current_group
);
626 group
= reggroup_next (gdbarch
, NULL
);
631 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
632 around behaviour. Returns the previous register group, or NULL if the
633 register window is not currently being displayed. */
635 static struct reggroup
*
636 tui_reg_prev (struct reggroup
*current_group
, struct gdbarch
*gdbarch
)
638 struct reggroup
*group
= NULL
;
640 if (current_group
!= NULL
)
642 group
= reggroup_prev (gdbarch
, current_group
);
644 group
= reggroup_prev (gdbarch
, NULL
);
649 /* Implement the 'tui reg' command. Changes the register group displayed
650 in the tui register window. Displays the tui register window if it is
651 not already on display. */
654 tui_reg_command (const char *args
, int from_tty
)
656 struct gdbarch
*gdbarch
= get_current_arch ();
660 struct reggroup
*group
, *match
= NULL
;
661 size_t len
= strlen (args
);
663 /* Make sure the curses mode is enabled. */
666 /* Make sure the register window is visible. If not, select an
667 appropriate layout. We need to do this before trying to run the
668 'next' or 'prev' commands. */
669 if (TUI_DATA_WIN
== NULL
|| !TUI_DATA_WIN
->is_visible ())
672 struct reggroup
*current_group
= TUI_DATA_WIN
->current_group
;
673 if (strncmp (args
, "next", len
) == 0)
674 match
= tui_reg_next (current_group
, gdbarch
);
675 else if (strncmp (args
, "prev", len
) == 0)
676 match
= tui_reg_prev (current_group
, gdbarch
);
678 /* This loop matches on the initial part of a register group
679 name. If this initial part in ARGS matches only one register
680 group then the switch is made. */
681 for (group
= reggroup_next (gdbarch
, NULL
);
683 group
= reggroup_next (gdbarch
, group
))
685 if (strncmp (reggroup_name (group
), args
, len
) == 0)
688 error (_("ambiguous register group name '%s'"), args
);
694 error (_("unknown register group '%s'"), args
);
696 tui_show_registers (match
);
700 struct reggroup
*group
;
703 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
704 "either a register group,\nor one of 'next' "
705 "or 'prev'. Known register groups are:\n"));
707 for (first
= 1, group
= reggroup_next (gdbarch
, NULL
);
709 first
= 0, group
= reggroup_next (gdbarch
, group
))
712 printf_unfiltered (", ");
713 printf_unfiltered ("%s", reggroup_name (group
));
716 printf_unfiltered ("\n");
720 /* Complete names of register groups, and add the special "prev" and "next"
724 tui_reggroup_completer (struct cmd_list_element
*ignore
,
725 completion_tracker
&tracker
,
726 const char *text
, const char *word
)
728 static const char *extra
[] = { "next", "prev", NULL
};
729 size_t len
= strlen (word
);
732 reggroup_completer (ignore
, tracker
, text
, word
);
734 /* XXXX use complete_on_enum instead? */
735 for (tmp
= extra
; *tmp
!= NULL
; ++tmp
)
737 if (strncmp (word
, *tmp
, len
) == 0)
738 tracker
.add_completion (make_unique_xstrdup (*tmp
));
742 /* Get the register from the frame and return a printable
743 representation of it. */
746 tui_register_format (struct frame_info
*frame
, int regnum
)
748 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
752 scoped_restore save_pagination
753 = make_scoped_restore (&pagination_enabled
, 0);
754 scoped_restore save_stdout
755 = make_scoped_restore (&gdb_stdout
, &stream
);
757 gdbarch_print_registers_info (gdbarch
, &stream
, frame
, regnum
, 1);
759 /* Remove the possible \n. */
760 std::string
&str
= stream
.string ();
761 if (!str
.empty () && str
.back () == '\n')
762 str
.resize (str
.size () - 1);
764 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
765 return tui_expand_tabs (str
.c_str (), 0);
768 /* Get the register value from the given frame and format it for the
769 display. When changep is set, check if the new register value has
770 changed with respect to the previous call. */
772 tui_get_register (struct frame_info
*frame
,
773 struct tui_data_item_window
*data
,
774 int regnum
, bool *changedp
)
778 if (target_has_registers
)
780 char *prev_content
= data
->content
;
782 data
->content
= tui_register_format (frame
, regnum
);
785 && strcmp (prev_content
, data
->content
) != 0)
788 xfree (prev_content
);
793 _initialize_tui_regs (void)
795 struct cmd_list_element
**tuicmd
, *cmd
;
797 tuicmd
= tui_get_cmd_list ();
799 cmd
= add_cmd ("reg", class_tui
, tui_reg_command
, _("\
800 TUI command to control the register window."), tuicmd
);
801 set_cmd_completer (cmd
, tui_reggroup_completer
);