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 /* Get the register from the frame and return a printable
53 representation of it. */
55 static gdb::unique_xmalloc_ptr
<char>
56 tui_register_format (struct frame_info
*frame
, int regnum
)
58 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
62 scoped_restore save_pagination
63 = make_scoped_restore (&pagination_enabled
, 0);
64 scoped_restore save_stdout
65 = make_scoped_restore (&gdb_stdout
, &stream
);
67 gdbarch_print_registers_info (gdbarch
, &stream
, frame
, regnum
, 1);
69 /* Remove the possible \n. */
70 std::string
&str
= stream
.string ();
71 if (!str
.empty () && str
.back () == '\n')
72 str
.resize (str
.size () - 1);
74 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
75 return tui_expand_tabs (str
.c_str ());
78 /* Get the register value from the given frame and format it for the
79 display. When changep is set, check if the new register value has
80 changed with respect to the previous call. */
82 tui_get_register (struct frame_info
*frame
,
83 struct tui_data_item_window
*data
,
84 int regnum
, bool *changedp
)
88 if (target_has_registers
)
90 gdb::unique_xmalloc_ptr
<char> new_content
91 = tui_register_format (frame
, regnum
);
94 && strcmp (data
->content
.get (), new_content
.get ()) != 0)
97 data
->content
= std::move (new_content
);
101 /* See tui-regs.h. */
104 tui_data_window::last_regs_line_no () const
106 int num_lines
= (-1);
108 if (!regs_content
.empty ())
110 num_lines
= regs_content
.size () / regs_column_count
;
111 if (regs_content
.size () % regs_column_count
)
117 /* See tui-regs.h. */
120 tui_data_window::line_from_reg_element_no (int element_no
) const
122 if (element_no
< regs_content
.size ())
129 if (element_no
< regs_column_count
* i
)
141 /* See tui-regs.h. */
144 tui_data_window::first_reg_element_no_inline (int line_no
) const
146 if (line_no
* regs_column_count
<= regs_content
.size ())
147 return ((line_no
+ 1) * regs_column_count
) - regs_column_count
;
152 /* Show the registers of the given group in the data window
153 and refresh the window. */
155 tui_show_registers (struct reggroup
*group
)
158 group
= general_reggroup
;
160 /* Say that registers should be displayed, even if there is a
162 TUI_DATA_WIN
->display_regs
= true;
164 if (target_has_registers
&& target_has_stack
&& target_has_memory
)
166 tui_show_register_group (TUI_DATA_WIN
, group
, get_selected_frame (NULL
),
167 group
== TUI_DATA_WIN
->current_group
);
169 /* Clear all notation of changed values. */
170 for (auto &&data_item_win
: TUI_DATA_WIN
->regs_content
)
172 if (data_item_win
!= nullptr)
173 data_item_win
->highlight
= false;
175 TUI_DATA_WIN
->current_group
= group
;
176 TUI_DATA_WIN
->display_all_data ();
180 TUI_DATA_WIN
->current_group
= 0;
181 TUI_DATA_WIN
->erase_data_content (_("[ Register Values Unavailable ]"));
186 /* Set the data window to display the registers of the register group
187 using the given frame. Values are refreshed only when
188 refresh_values_only is TRUE. */
191 tui_show_register_group (tui_data_window
*win_info
,
192 struct reggroup
*group
,
193 struct frame_info
*frame
,
194 int refresh_values_only
)
196 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
201 /* Make a new title showing which group we display. */
202 snprintf (title
, sizeof (title
) - 1, "Register group: %s",
203 reggroup_name (group
));
204 xfree (win_info
->title
);
205 win_info
->title
= xstrdup (title
);
207 /* See how many registers must be displayed. */
209 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
213 /* Must be in the group. */
214 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
217 /* If the register name is empty, it is undefined for this
218 processor, so don't display anything. */
219 name
= gdbarch_register_name (gdbarch
, regnum
);
220 if (name
== 0 || *name
== '\0')
226 if (!refresh_values_only
)
227 win_info
->regs_content
.clear ();
229 if (nr_regs
< win_info
->regs_content
.size ())
230 win_info
->regs_content
.resize (nr_regs
);
233 for (int i
= win_info
->regs_content
.size (); i
< nr_regs
; ++i
)
234 win_info
->regs_content
.emplace_back (new tui_data_item_window ());
237 /* Now set the register names and values. */
239 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
241 struct tui_data_item_window
*data_item_win
;
244 /* Must be in the group. */
245 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
248 /* If the register name is empty, it is undefined for this
249 processor, so don't display anything. */
250 name
= gdbarch_register_name (gdbarch
, regnum
);
251 if (name
== 0 || *name
== '\0')
254 data_item_win
= win_info
->regs_content
[pos
].get ();
257 if (!refresh_values_only
)
259 data_item_win
->item_no
= regnum
;
260 data_item_win
->name
= name
;
261 data_item_win
->highlight
= false;
263 tui_get_register (frame
, data_item_win
, regnum
, 0);
269 /* See tui-regs.h. */
272 tui_data_window::display_registers_from (int start_element_no
)
274 if (!regs_content
.empty ())
276 int j
, item_win_width
, cur_y
;
279 for (auto &&data_item_win
: regs_content
)
285 p
= data_item_win
->content
.get ();
292 item_win_width
= max_len
+ 1;
293 int i
= start_element_no
;
295 regs_column_count
= (width
- 2) / item_win_width
;
296 if (regs_column_count
== 0)
297 regs_column_count
= 1;
298 item_win_width
= (width
- 2) / regs_column_count
;
300 /* Now create each data "sub" window, and write the display into
303 while (i
< regs_content
.size ()
304 && cur_y
<= viewport_height
)
307 j
< regs_column_count
&& i
< regs_content
.size ();
310 struct tui_data_item_window
*data_item_win
;
312 /* Create the window if necessary. */
313 data_item_win
= regs_content
[i
].get ();
314 if (data_item_win
->handle
!= NULL
315 && (data_item_win
->height
!= 1
316 || data_item_win
->width
!= item_win_width
317 || data_item_win
->origin
.x
!= (item_win_width
* j
) + 1
318 || data_item_win
->origin
.y
!= cur_y
))
320 tui_delete_win (data_item_win
->handle
);
321 data_item_win
->handle
= 0;
324 if (data_item_win
->handle
== NULL
)
326 data_item_win
->height
= 1;
327 data_item_win
->width
= item_win_width
;
328 data_item_win
->origin
.x
= (item_win_width
* j
) + 1;
329 data_item_win
->origin
.y
= cur_y
;
330 tui_make_window (data_item_win
);
331 scrollok (data_item_win
->handle
, FALSE
);
333 touchwin (data_item_win
->handle
);
335 /* Get the printable representation of the register
337 tui_display_register (data_item_win
);
338 i
++; /* Next register. */
340 cur_y
++; /* Next row. */
345 /* See tui-regs.h. */
348 tui_data_window::display_reg_element_at_line (int start_element_no
,
351 if (!regs_content
.empty ())
353 int element_no
= start_element_no
;
355 if (start_element_no
!= 0 && start_line_no
!= 0)
357 int last_line_no
, first_line_on_last_page
;
359 last_line_no
= last_regs_line_no ();
360 first_line_on_last_page
= last_line_no
- (height
- 2);
361 if (first_line_on_last_page
< 0)
362 first_line_on_last_page
= 0;
364 /* If the element_no causes us to scroll past the end of the
365 registers, adjust what element to really start the
367 if (start_line_no
> first_line_on_last_page
)
368 element_no
= first_reg_element_no_inline (first_line_on_last_page
);
370 display_registers_from (element_no
);
374 /* See tui-regs.h. */
377 tui_data_window::display_registers_from_line (int line_no
)
379 check_and_display_highlight_if_needed ();
380 if (!regs_content
.empty ())
388 /* Make sure that we don't display off the end of the
390 if (line_no
>= last_regs_line_no ())
392 line_no
= line_from_reg_element_no (regs_content
.size () - 1);
398 element_no
= first_reg_element_no_inline (line_no
);
399 if (element_no
< regs_content
.size ())
400 display_reg_element_at_line (element_no
, line_no
);
407 return (-1); /* Nothing was displayed. */
411 /* Answer the index first element displayed. If none are displayed,
414 tui_data_window::first_data_item_displayed ()
416 for (int i
= 0; i
< regs_content
.size (); i
++)
418 struct tui_gen_win_info
*data_item_win
;
420 data_item_win
= regs_content
[i
].get ();
421 if (data_item_win
->is_visible ())
428 /* See tui-regs.h. */
431 tui_data_window::delete_data_content_windows ()
433 for (auto &&win
: regs_content
)
435 tui_delete_win (win
->handle
);
442 tui_data_window::erase_data_content (const char *prompt
)
445 check_and_display_highlight_if_needed ();
448 int half_width
= (width
- 2) / 2;
451 if (strlen (prompt
) >= half_width
)
454 x_pos
= half_width
- strlen (prompt
);
455 mvwaddstr (handle
, (height
/ 2), x_pos
, (char *) prompt
);
460 /* See tui-regs.h. */
463 tui_data_window::display_all_data ()
465 if (regs_content
.empty ())
466 erase_data_content (NO_DATA_STRING
);
469 erase_data_content (NULL
);
470 delete_data_content_windows ();
471 check_and_display_highlight_if_needed ();
472 display_registers_from (0);
477 /* Function to redisplay the contents of the data window. */
479 tui_data_window::refresh_all ()
481 erase_data_content (NULL
);
482 if (!regs_content
.empty ())
484 int first_element
= first_data_item_displayed ();
486 if (first_element
>= 0) /* Re-use existing windows. */
488 int first_line
= (-1);
490 if (first_element
< regs_content
.size ())
491 first_line
= line_from_reg_element_no (first_element
);
495 erase_data_content (NULL
);
496 display_registers_from_line (first_line
);
503 /* Scroll the data window vertically forward or backward. */
505 tui_data_window::do_scroll_vertical (int num_to_scroll
)
507 int first_element_no
;
508 int first_line
= (-1);
510 first_element_no
= first_data_item_displayed ();
511 if (first_element_no
< regs_content
.size ())
512 first_line
= line_from_reg_element_no (first_element_no
);
514 { /* Calculate the first line from the element number which is in
515 the general data content. */
520 first_line
+= num_to_scroll
;
521 erase_data_content (NULL
);
522 delete_data_content_windows ();
523 display_registers_from_line (first_line
);
527 /* See tui-regs.h. */
530 tui_data_window::rerender ()
532 /* Delete all data item windows. */
533 for (auto &&win
: regs_content
)
535 tui_delete_win (win
->handle
);
541 /* See tui-regs.h. */
544 tui_data_window::refresh_window ()
546 tui_gen_win_info::refresh_window ();
547 for (auto &&win
: regs_content
)
550 win
->refresh_window ();
554 /* This function check all displayed registers for changes in values,
555 given a particular frame. If the values have changed, they are
556 updated with the new value and highlighted. */
558 tui_data_window::check_register_values (struct frame_info
*frame
)
560 if (regs_content
.empty () && display_regs
)
561 tui_show_registers (current_group
);
564 for (auto &&data_item_win_ptr
: regs_content
)
568 was_hilighted
= data_item_win_ptr
->highlight
;
570 tui_get_register (frame
, data_item_win_ptr
.get (),
571 data_item_win_ptr
->item_no
,
572 &data_item_win_ptr
->highlight
);
574 if (data_item_win_ptr
->highlight
|| was_hilighted
)
575 tui_display_register (data_item_win_ptr
.get ());
580 /* Display a register in a window. If hilite is TRUE, then the value
581 will be displayed in reverse video. */
583 tui_display_register (struct tui_data_item_window
*data
)
585 if (data
->handle
!= NULL
)
590 /* We ignore the return value, casting it to void in order to avoid
591 a compiler warning. The warning itself was introduced by a patch
592 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
593 to code that causes the compiler to generate an unused-value
595 (void) wstandout (data
->handle
);
597 wmove (data
->handle
, 0, 0);
598 for (i
= 1; i
< data
->width
; i
++)
599 waddch (data
->handle
, ' ');
600 wmove (data
->handle
, 0, 0);
602 waddstr (data
->handle
, data
->content
.get ());
605 /* We ignore the return value, casting it to void in order to avoid
606 a compiler warning. The warning itself was introduced by a patch
607 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
608 to code that causes the compiler to generate an unused-value
610 (void) wstandend (data
->handle
);
611 data
->refresh_window ();
615 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
616 around behaviour. Returns the next register group, or NULL if the
617 register window is not currently being displayed. */
619 static struct reggroup
*
620 tui_reg_next (struct reggroup
*current_group
, struct gdbarch
*gdbarch
)
622 struct reggroup
*group
= NULL
;
624 if (current_group
!= NULL
)
626 group
= reggroup_next (gdbarch
, current_group
);
628 group
= reggroup_next (gdbarch
, NULL
);
633 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
634 around behaviour. Returns the previous register group, or NULL if the
635 register window is not currently being displayed. */
637 static struct reggroup
*
638 tui_reg_prev (struct reggroup
*current_group
, struct gdbarch
*gdbarch
)
640 struct reggroup
*group
= NULL
;
642 if (current_group
!= NULL
)
644 group
= reggroup_prev (gdbarch
, current_group
);
646 group
= reggroup_prev (gdbarch
, NULL
);
651 /* A helper function to display the register window in the appropriate
657 enum tui_layout_type cur_layout
= tui_current_layout ();
658 enum tui_layout_type new_layout
;
659 if (cur_layout
== SRC_COMMAND
|| cur_layout
== SRC_DATA_COMMAND
)
660 new_layout
= SRC_DATA_COMMAND
;
662 new_layout
= DISASSEM_DATA_COMMAND
;
663 tui_set_layout (new_layout
);
666 /* Implement the 'tui reg' command. Changes the register group displayed
667 in the tui register window. Displays the tui register window if it is
668 not already on display. */
671 tui_reg_command (const char *args
, int from_tty
)
673 struct gdbarch
*gdbarch
= get_current_arch ();
677 struct reggroup
*group
, *match
= NULL
;
678 size_t len
= strlen (args
);
680 /* Make sure the curses mode is enabled. */
683 /* Make sure the register window is visible. If not, select an
684 appropriate layout. We need to do this before trying to run the
685 'next' or 'prev' commands. */
686 if (TUI_DATA_WIN
== NULL
|| !TUI_DATA_WIN
->is_visible ())
689 struct reggroup
*current_group
= TUI_DATA_WIN
->current_group
;
690 if (strncmp (args
, "next", len
) == 0)
691 match
= tui_reg_next (current_group
, gdbarch
);
692 else if (strncmp (args
, "prev", len
) == 0)
693 match
= tui_reg_prev (current_group
, gdbarch
);
695 /* This loop matches on the initial part of a register group
696 name. If this initial part in ARGS matches only one register
697 group then the switch is made. */
698 for (group
= reggroup_next (gdbarch
, NULL
);
700 group
= reggroup_next (gdbarch
, group
))
702 if (strncmp (reggroup_name (group
), args
, len
) == 0)
705 error (_("ambiguous register group name '%s'"), args
);
711 error (_("unknown register group '%s'"), args
);
713 tui_show_registers (match
);
717 struct reggroup
*group
;
720 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
721 "either a register group,\nor one of 'next' "
722 "or 'prev'. Known register groups are:\n"));
724 for (first
= 1, group
= reggroup_next (gdbarch
, NULL
);
726 first
= 0, group
= reggroup_next (gdbarch
, group
))
729 printf_unfiltered (", ");
730 printf_unfiltered ("%s", reggroup_name (group
));
733 printf_unfiltered ("\n");
737 /* Complete names of register groups, and add the special "prev" and "next"
741 tui_reggroup_completer (struct cmd_list_element
*ignore
,
742 completion_tracker
&tracker
,
743 const char *text
, const char *word
)
745 static const char *extra
[] = { "next", "prev", NULL
};
746 size_t len
= strlen (word
);
749 reggroup_completer (ignore
, tracker
, text
, word
);
751 /* XXXX use complete_on_enum instead? */
752 for (tmp
= extra
; *tmp
!= NULL
; ++tmp
)
754 if (strncmp (word
, *tmp
, len
) == 0)
755 tracker
.add_completion (make_unique_xstrdup (*tmp
));
760 _initialize_tui_regs (void)
762 struct cmd_list_element
**tuicmd
, *cmd
;
764 tuicmd
= tui_get_cmd_list ();
766 cmd
= add_cmd ("reg", class_tui
, tui_reg_command
, _("\
767 TUI command to control the register window."), tuicmd
);
768 set_cmd_completer (cmd
, tui_reggroup_completer
);