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 /* A helper function to display the register window in the appropriate
158 enum tui_layout_type cur_layout
= tui_current_layout ();
159 enum tui_layout_type new_layout
;
160 if (cur_layout
== SRC_COMMAND
|| cur_layout
== SRC_DATA_COMMAND
)
161 new_layout
= SRC_DATA_COMMAND
;
163 new_layout
= DISASSEM_DATA_COMMAND
;
164 tui_set_layout (new_layout
);
167 /* Show the registers of the given group in the data window
168 and refresh the window. */
170 tui_show_registers (struct reggroup
*group
)
172 /* Make sure the curses mode is enabled. */
175 /* Make sure the register window is visible. If not, select an
176 appropriate layout. */
177 if (TUI_DATA_WIN
== NULL
|| !TUI_DATA_WIN
->is_visible ())
181 group
= general_reggroup
;
183 /* Say that registers should be displayed, even if there is a
185 TUI_DATA_WIN
->display_regs
= true;
187 if (target_has_registers
&& target_has_stack
&& target_has_memory
)
189 tui_show_register_group (TUI_DATA_WIN
, group
, get_selected_frame (NULL
),
190 group
== TUI_DATA_WIN
->current_group
);
192 /* Clear all notation of changed values. */
193 for (auto &&data_item_win
: TUI_DATA_WIN
->regs_content
)
195 if (data_item_win
!= nullptr)
196 data_item_win
->highlight
= false;
198 TUI_DATA_WIN
->current_group
= group
;
199 TUI_DATA_WIN
->display_all_data ();
203 TUI_DATA_WIN
->current_group
= 0;
204 TUI_DATA_WIN
->erase_data_content (_("[ Register Values Unavailable ]"));
209 /* Set the data window to display the registers of the register group
210 using the given frame. Values are refreshed only when
211 refresh_values_only is TRUE. */
214 tui_show_register_group (tui_data_window
*win_info
,
215 struct reggroup
*group
,
216 struct frame_info
*frame
,
217 int refresh_values_only
)
219 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
224 /* Make a new title showing which group we display. */
225 snprintf (title
, sizeof (title
) - 1, "Register group: %s",
226 reggroup_name (group
));
227 xfree (win_info
->title
);
228 win_info
->title
= xstrdup (title
);
230 /* See how many registers must be displayed. */
232 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
236 /* Must be in the group. */
237 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
240 /* If the register name is empty, it is undefined for this
241 processor, so don't display anything. */
242 name
= gdbarch_register_name (gdbarch
, regnum
);
243 if (name
== 0 || *name
== '\0')
249 if (!refresh_values_only
)
250 win_info
->regs_content
.clear ();
252 if (nr_regs
< win_info
->regs_content
.size ())
253 win_info
->regs_content
.resize (nr_regs
);
256 for (int i
= win_info
->regs_content
.size (); i
< nr_regs
; ++i
)
257 win_info
->regs_content
.emplace_back (new tui_data_item_window ());
260 /* Now set the register names and values. */
262 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
264 struct tui_data_item_window
*data_item_win
;
267 /* Must be in the group. */
268 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
271 /* If the register name is empty, it is undefined for this
272 processor, so don't display anything. */
273 name
= gdbarch_register_name (gdbarch
, regnum
);
274 if (name
== 0 || *name
== '\0')
277 data_item_win
= win_info
->regs_content
[pos
].get ();
280 if (!refresh_values_only
)
282 data_item_win
->item_no
= regnum
;
283 data_item_win
->name
= name
;
284 data_item_win
->highlight
= false;
286 tui_get_register (frame
, data_item_win
, regnum
, 0);
292 /* See tui-regs.h. */
295 tui_data_window::display_registers_from (int start_element_no
)
297 if (!regs_content
.empty ())
299 int j
, item_win_width
, cur_y
;
302 for (auto &&data_item_win
: regs_content
)
308 p
= data_item_win
->content
.get ();
315 item_win_width
= max_len
+ 1;
316 int i
= start_element_no
;
318 regs_column_count
= (width
- 2) / item_win_width
;
319 if (regs_column_count
== 0)
320 regs_column_count
= 1;
321 item_win_width
= (width
- 2) / regs_column_count
;
323 /* Now create each data "sub" window, and write the display into
326 while (i
< regs_content
.size ()
327 && cur_y
<= viewport_height
)
330 j
< regs_column_count
&& i
< regs_content
.size ();
333 struct tui_data_item_window
*data_item_win
;
335 /* Create the window if necessary. */
336 data_item_win
= regs_content
[i
].get ();
337 if (data_item_win
->handle
!= NULL
338 && (data_item_win
->height
!= 1
339 || data_item_win
->width
!= item_win_width
340 || data_item_win
->origin
.x
!= (item_win_width
* j
) + 1
341 || data_item_win
->origin
.y
!= cur_y
))
343 tui_delete_win (data_item_win
->handle
);
344 data_item_win
->handle
= 0;
347 if (data_item_win
->handle
== NULL
)
349 data_item_win
->height
= 1;
350 data_item_win
->width
= item_win_width
;
351 data_item_win
->origin
.x
= (item_win_width
* j
) + 1;
352 data_item_win
->origin
.y
= cur_y
;
353 tui_make_window (data_item_win
);
354 scrollok (data_item_win
->handle
, FALSE
);
356 touchwin (data_item_win
->handle
);
358 /* Get the printable representation of the register
360 tui_display_register (data_item_win
);
361 i
++; /* Next register. */
363 cur_y
++; /* Next row. */
368 /* See tui-regs.h. */
371 tui_data_window::display_reg_element_at_line (int start_element_no
,
374 if (!regs_content
.empty ())
376 int element_no
= start_element_no
;
378 if (start_element_no
!= 0 && start_line_no
!= 0)
380 int last_line_no
, first_line_on_last_page
;
382 last_line_no
= last_regs_line_no ();
383 first_line_on_last_page
= last_line_no
- (height
- 2);
384 if (first_line_on_last_page
< 0)
385 first_line_on_last_page
= 0;
387 /* If the element_no causes us to scroll past the end of the
388 registers, adjust what element to really start the
390 if (start_line_no
> first_line_on_last_page
)
391 element_no
= first_reg_element_no_inline (first_line_on_last_page
);
393 display_registers_from (element_no
);
397 /* See tui-regs.h. */
400 tui_data_window::display_registers_from_line (int line_no
)
402 check_and_display_highlight_if_needed ();
403 if (!regs_content
.empty ())
411 /* Make sure that we don't display off the end of the
413 if (line_no
>= last_regs_line_no ())
415 line_no
= line_from_reg_element_no (regs_content
.size () - 1);
421 element_no
= first_reg_element_no_inline (line_no
);
422 if (element_no
< regs_content
.size ())
423 display_reg_element_at_line (element_no
, line_no
);
430 return (-1); /* Nothing was displayed. */
434 /* Answer the index first element displayed. If none are displayed,
437 tui_data_window::first_data_item_displayed ()
439 for (int i
= 0; i
< regs_content
.size (); i
++)
441 struct tui_gen_win_info
*data_item_win
;
443 data_item_win
= regs_content
[i
].get ();
444 if (data_item_win
->is_visible ())
451 /* See tui-regs.h. */
454 tui_data_window::delete_data_content_windows ()
456 for (auto &&win
: regs_content
)
458 tui_delete_win (win
->handle
);
465 tui_data_window::erase_data_content (const char *prompt
)
468 check_and_display_highlight_if_needed ();
471 int half_width
= (width
- 2) / 2;
474 if (strlen (prompt
) >= half_width
)
477 x_pos
= half_width
- strlen (prompt
);
478 mvwaddstr (handle
, (height
/ 2), x_pos
, (char *) prompt
);
483 /* See tui-regs.h. */
486 tui_data_window::display_all_data ()
488 if (regs_content
.empty ())
489 erase_data_content (NO_DATA_STRING
);
492 erase_data_content (NULL
);
493 delete_data_content_windows ();
494 check_and_display_highlight_if_needed ();
495 display_registers_from (0);
500 /* Function to redisplay the contents of the data window. */
502 tui_data_window::refresh_all ()
504 erase_data_content (NULL
);
505 if (!regs_content
.empty ())
507 int first_element
= first_data_item_displayed ();
509 if (first_element
>= 0) /* Re-use existing windows. */
511 int first_line
= (-1);
513 if (first_element
< regs_content
.size ())
514 first_line
= line_from_reg_element_no (first_element
);
518 erase_data_content (NULL
);
519 display_registers_from_line (first_line
);
526 /* Scroll the data window vertically forward or backward. */
528 tui_data_window::do_scroll_vertical (int num_to_scroll
)
530 int first_element_no
;
531 int first_line
= (-1);
533 first_element_no
= first_data_item_displayed ();
534 if (first_element_no
< regs_content
.size ())
535 first_line
= line_from_reg_element_no (first_element_no
);
537 { /* Calculate the first line from the element number which is in
538 the general data content. */
543 first_line
+= num_to_scroll
;
544 erase_data_content (NULL
);
545 delete_data_content_windows ();
546 display_registers_from_line (first_line
);
550 /* See tui-regs.h. */
553 tui_data_window::rerender ()
555 /* Delete all data item windows. */
556 for (auto &&win
: regs_content
)
558 tui_delete_win (win
->handle
);
564 /* See tui-regs.h. */
567 tui_data_window::refresh_window ()
569 tui_gen_win_info::refresh_window ();
570 for (auto &&win
: regs_content
)
573 win
->refresh_window ();
577 /* This function check all displayed registers for changes in values,
578 given a particular frame. If the values have changed, they are
579 updated with the new value and highlighted. */
581 tui_check_register_values (struct frame_info
*frame
)
583 if (TUI_DATA_WIN
!= NULL
584 && TUI_DATA_WIN
->is_visible ())
586 if (TUI_DATA_WIN
->regs_content
.empty ()
587 && TUI_DATA_WIN
->display_regs
)
588 tui_show_registers (TUI_DATA_WIN
->current_group
);
591 for (auto &&data_item_win_ptr
: TUI_DATA_WIN
->regs_content
)
595 was_hilighted
= data_item_win_ptr
->highlight
;
597 tui_get_register (frame
, data_item_win_ptr
.get (),
598 data_item_win_ptr
->item_no
,
599 &data_item_win_ptr
->highlight
);
601 if (data_item_win_ptr
->highlight
|| was_hilighted
)
602 tui_display_register (data_item_win_ptr
.get ());
608 /* Display a register in a window. If hilite is TRUE, then the value
609 will be displayed in reverse video. */
611 tui_display_register (struct tui_data_item_window
*data
)
613 if (data
->handle
!= NULL
)
618 /* We ignore the return value, casting it to void in order to avoid
619 a compiler warning. The warning itself was introduced by a patch
620 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
621 to code that causes the compiler to generate an unused-value
623 (void) wstandout (data
->handle
);
625 wmove (data
->handle
, 0, 0);
626 for (i
= 1; i
< data
->width
; i
++)
627 waddch (data
->handle
, ' ');
628 wmove (data
->handle
, 0, 0);
630 waddstr (data
->handle
, data
->content
.get ());
633 /* We ignore the return value, casting it to void in order to avoid
634 a compiler warning. The warning itself was introduced by a patch
635 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
636 to code that causes the compiler to generate an unused-value
638 (void) wstandend (data
->handle
);
639 data
->refresh_window ();
643 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
644 around behaviour. Returns the next register group, or NULL if the
645 register window is not currently being displayed. */
647 static struct reggroup
*
648 tui_reg_next (struct reggroup
*current_group
, struct gdbarch
*gdbarch
)
650 struct reggroup
*group
= NULL
;
652 if (current_group
!= NULL
)
654 group
= reggroup_next (gdbarch
, current_group
);
656 group
= reggroup_next (gdbarch
, NULL
);
661 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
662 around behaviour. Returns the previous register group, or NULL if the
663 register window is not currently being displayed. */
665 static struct reggroup
*
666 tui_reg_prev (struct reggroup
*current_group
, struct gdbarch
*gdbarch
)
668 struct reggroup
*group
= NULL
;
670 if (current_group
!= NULL
)
672 group
= reggroup_prev (gdbarch
, current_group
);
674 group
= reggroup_prev (gdbarch
, NULL
);
679 /* Implement the 'tui reg' command. Changes the register group displayed
680 in the tui register window. Displays the tui register window if it is
681 not already on display. */
684 tui_reg_command (const char *args
, int from_tty
)
686 struct gdbarch
*gdbarch
= get_current_arch ();
690 struct reggroup
*group
, *match
= NULL
;
691 size_t len
= strlen (args
);
693 /* Make sure the curses mode is enabled. */
696 /* Make sure the register window is visible. If not, select an
697 appropriate layout. We need to do this before trying to run the
698 'next' or 'prev' commands. */
699 if (TUI_DATA_WIN
== NULL
|| !TUI_DATA_WIN
->is_visible ())
702 struct reggroup
*current_group
= TUI_DATA_WIN
->current_group
;
703 if (strncmp (args
, "next", len
) == 0)
704 match
= tui_reg_next (current_group
, gdbarch
);
705 else if (strncmp (args
, "prev", len
) == 0)
706 match
= tui_reg_prev (current_group
, gdbarch
);
708 /* This loop matches on the initial part of a register group
709 name. If this initial part in ARGS matches only one register
710 group then the switch is made. */
711 for (group
= reggroup_next (gdbarch
, NULL
);
713 group
= reggroup_next (gdbarch
, group
))
715 if (strncmp (reggroup_name (group
), args
, len
) == 0)
718 error (_("ambiguous register group name '%s'"), args
);
724 error (_("unknown register group '%s'"), args
);
726 tui_show_registers (match
);
730 struct reggroup
*group
;
733 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
734 "either a register group,\nor one of 'next' "
735 "or 'prev'. Known register groups are:\n"));
737 for (first
= 1, group
= reggroup_next (gdbarch
, NULL
);
739 first
= 0, group
= reggroup_next (gdbarch
, group
))
742 printf_unfiltered (", ");
743 printf_unfiltered ("%s", reggroup_name (group
));
746 printf_unfiltered ("\n");
750 /* Complete names of register groups, and add the special "prev" and "next"
754 tui_reggroup_completer (struct cmd_list_element
*ignore
,
755 completion_tracker
&tracker
,
756 const char *text
, const char *word
)
758 static const char *extra
[] = { "next", "prev", NULL
};
759 size_t len
= strlen (word
);
762 reggroup_completer (ignore
, tracker
, text
, word
);
764 /* XXXX use complete_on_enum instead? */
765 for (tmp
= extra
; *tmp
!= NULL
; ++tmp
)
767 if (strncmp (word
, *tmp
, len
) == 0)
768 tracker
.add_completion (make_unique_xstrdup (*tmp
));
773 _initialize_tui_regs (void)
775 struct cmd_list_element
**tuicmd
, *cmd
;
777 tuicmd
= tui_get_cmd_list ();
779 cmd
= add_cmd ("reg", class_tui
, tui_reg_command
, _("\
780 TUI command to control the register window."), tuicmd
);
781 set_cmd_completer (cmd
, tui_reggroup_completer
);