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 /* Get the register from the frame and return a printable
46 representation of it. */
48 static gdb::unique_xmalloc_ptr
<char>
49 tui_register_format (struct frame_info
*frame
, int regnum
)
51 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
55 scoped_restore save_pagination
56 = make_scoped_restore (&pagination_enabled
, 0);
57 scoped_restore save_stdout
58 = make_scoped_restore (&gdb_stdout
, &stream
);
60 gdbarch_print_registers_info (gdbarch
, &stream
, frame
, regnum
, 1);
62 /* Remove the possible \n. */
63 std::string
&str
= stream
.string ();
64 if (!str
.empty () && str
.back () == '\n')
65 str
.resize (str
.size () - 1);
67 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
68 return tui_expand_tabs (str
.c_str ());
71 /* Get the register value from the given frame and format it for the
72 display. When changep is set, check if the new register value has
73 changed with respect to the previous call. */
75 tui_get_register (struct frame_info
*frame
,
76 struct tui_data_item_window
*data
,
77 int regnum
, bool *changedp
)
81 if (target_has_registers
)
83 gdb::unique_xmalloc_ptr
<char> new_content
84 = tui_register_format (frame
, regnum
);
87 && strcmp (data
->content
.get (), new_content
.get ()) != 0)
90 data
->content
= std::move (new_content
);
97 tui_data_window::last_regs_line_no () const
99 int num_lines
= regs_content
.size () / regs_column_count
;
100 if (regs_content
.size () % regs_column_count
)
105 /* See tui-regs.h. */
108 tui_data_window::line_from_reg_element_no (int element_no
) const
110 if (element_no
< regs_content
.size ())
117 if (element_no
< regs_column_count
* i
)
129 /* See tui-regs.h. */
132 tui_data_window::first_reg_element_no_inline (int line_no
) const
134 if (line_no
* regs_column_count
<= regs_content
.size ())
135 return ((line_no
+ 1) * regs_column_count
) - regs_column_count
;
140 /* Show the registers of the given group in the data window
141 and refresh the window. */
143 tui_data_window::show_registers (struct reggroup
*group
)
146 group
= general_reggroup
;
148 if (target_has_registers
&& target_has_stack
&& target_has_memory
)
150 show_register_group (group
, get_selected_frame (NULL
),
151 group
== current_group
);
153 /* Clear all notation of changed values. */
154 for (auto &&data_item_win
: regs_content
)
155 data_item_win
.highlight
= false;
156 current_group
= group
;
162 erase_data_content (_("[ Register Values Unavailable ]"));
167 /* Set the data window to display the registers of the register group
168 using the given frame. Values are refreshed only when
169 refresh_values_only is TRUE. */
172 tui_data_window::show_register_group (struct reggroup
*group
,
173 struct frame_info
*frame
,
174 int refresh_values_only
)
176 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
180 /* Make a new title showing which group we display. */
181 title
= string_printf ("Register group: %s", reggroup_name (group
));
183 /* See how many registers must be displayed. */
185 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
189 /* Must be in the group. */
190 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
193 /* If the register name is empty, it is undefined for this
194 processor, so don't display anything. */
195 name
= gdbarch_register_name (gdbarch
, regnum
);
196 if (name
== 0 || *name
== '\0')
202 regs_content
.resize (nr_regs
);
204 /* Now set the register names and values. */
206 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
208 struct tui_data_item_window
*data_item_win
;
211 /* Must be in the group. */
212 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
215 /* If the register name is empty, it is undefined for this
216 processor, so don't display anything. */
217 name
= gdbarch_register_name (gdbarch
, regnum
);
218 if (name
== 0 || *name
== '\0')
221 data_item_win
= ®s_content
[pos
];
224 if (!refresh_values_only
)
226 data_item_win
->item_no
= regnum
;
227 data_item_win
->name
= name
;
228 data_item_win
->highlight
= false;
230 tui_get_register (frame
, data_item_win
, regnum
, 0);
236 /* See tui-regs.h. */
239 tui_data_window::display_registers_from (int start_element_no
)
241 int j
, item_win_width
, cur_y
;
244 for (auto &&data_item_win
: regs_content
)
250 p
= data_item_win
.content
.get ();
257 item_win_width
= max_len
+ 1;
258 int i
= start_element_no
;
260 regs_column_count
= (width
- 2) / item_win_width
;
261 if (regs_column_count
== 0)
262 regs_column_count
= 1;
263 item_win_width
= (width
- 2) / regs_column_count
;
265 /* Now create each data "sub" window, and write the display into
268 while (i
< regs_content
.size ()
269 && cur_y
<= viewport_height
)
272 j
< regs_column_count
&& i
< regs_content
.size ();
275 /* Create the window if necessary. */
276 regs_content
[i
].resize (1, item_win_width
,
277 (item_win_width
* j
) + 1, cur_y
);
278 i
++; /* Next register. */
280 cur_y
++; /* Next row. */
284 /* See tui-regs.h. */
287 tui_data_window::display_reg_element_at_line (int start_element_no
,
290 int element_no
= start_element_no
;
292 if (start_element_no
!= 0 && start_line_no
!= 0)
294 int last_line_no
, first_line_on_last_page
;
296 last_line_no
= last_regs_line_no ();
297 first_line_on_last_page
= last_line_no
- (height
- 2);
298 if (first_line_on_last_page
< 0)
299 first_line_on_last_page
= 0;
301 /* If the element_no causes us to scroll past the end of the
302 registers, adjust what element to really start the
304 if (start_line_no
> first_line_on_last_page
)
305 element_no
= first_reg_element_no_inline (first_line_on_last_page
);
307 display_registers_from (element_no
);
310 /* See tui-regs.h. */
313 tui_data_window::display_registers_from_line (int line_no
)
321 /* Make sure that we don't display off the end of the
323 if (line_no
>= last_regs_line_no ())
325 line_no
= line_from_reg_element_no (regs_content
.size () - 1);
331 element_no
= first_reg_element_no_inline (line_no
);
332 if (element_no
< regs_content
.size ())
333 display_reg_element_at_line (element_no
, line_no
);
341 /* Answer the index first element displayed. If none are displayed,
344 tui_data_window::first_data_item_displayed ()
346 for (int i
= 0; i
< regs_content
.size (); i
++)
348 struct tui_gen_win_info
*data_item_win
;
350 data_item_win
= ®s_content
[i
];
351 if (data_item_win
->is_visible ())
358 /* See tui-regs.h. */
361 tui_data_window::delete_data_content_windows ()
363 for (auto &&win
: regs_content
)
365 tui_delete_win (win
.handle
);
372 tui_data_window::erase_data_content (const char *prompt
)
375 check_and_display_highlight_if_needed ();
378 int half_width
= (width
- 2) / 2;
381 if (strlen (prompt
) >= half_width
)
384 x_pos
= half_width
- strlen (prompt
);
385 mvwaddstr (handle
, (height
/ 2), x_pos
, (char *) prompt
);
390 /* See tui-regs.h. */
393 tui_data_window::rerender ()
395 if (regs_content
.empty ())
396 erase_data_content (_("[ Register Values Unavailable ]"));
399 erase_data_content (NULL
);
400 delete_data_content_windows ();
401 display_registers_from (0);
406 /* Function to redisplay the contents of the data window. */
408 tui_data_window::refresh_all ()
410 erase_data_content (NULL
);
411 if (!regs_content
.empty ())
413 int first_element
= first_data_item_displayed ();
415 if (first_element
>= 0) /* Re-use existing windows. */
417 int first_line
= (-1);
419 if (first_element
< regs_content
.size ())
420 first_line
= line_from_reg_element_no (first_element
);
423 display_registers_from_line (first_line
);
429 /* Scroll the data window vertically forward or backward. */
431 tui_data_window::do_scroll_vertical (int num_to_scroll
)
433 int first_element_no
;
434 int first_line
= (-1);
436 first_element_no
= first_data_item_displayed ();
437 if (first_element_no
< regs_content
.size ())
438 first_line
= line_from_reg_element_no (first_element_no
);
440 { /* Calculate the first line from the element number which is in
441 the general data content. */
446 first_line
+= num_to_scroll
;
447 erase_data_content (NULL
);
448 delete_data_content_windows ();
449 display_registers_from_line (first_line
);
453 /* See tui-regs.h. */
456 tui_data_window::refresh_window ()
458 tui_gen_win_info::refresh_window ();
459 for (auto &&win
: regs_content
)
460 win
.refresh_window ();
463 /* This function check all displayed registers for changes in values,
464 given a particular frame. If the values have changed, they are
465 updated with the new value and highlighted. */
467 tui_data_window::check_register_values (struct frame_info
*frame
)
469 if (regs_content
.empty ())
470 show_registers (current_group
);
473 for (auto &&data_item_win
: regs_content
)
477 was_hilighted
= data_item_win
.highlight
;
479 tui_get_register (frame
, &data_item_win
,
480 data_item_win
.item_no
,
481 &data_item_win
.highlight
);
483 if (data_item_win
.highlight
|| was_hilighted
)
484 data_item_win
.rerender ();
489 /* Display a register in a window. If hilite is TRUE, then the value
490 will be displayed in reverse video. */
492 tui_data_item_window::rerender ()
496 scrollok (handle
, FALSE
);
498 /* We ignore the return value, casting it to void in order to avoid
499 a compiler warning. The warning itself was introduced by a patch
500 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
501 to code that causes the compiler to generate an unused-value
503 (void) wstandout (handle
);
505 wmove (handle
, 0, 0);
506 for (i
= 1; i
< width
; i
++)
507 waddch (handle
, ' ');
508 wmove (handle
, 0, 0);
510 waddstr (handle
, content
.get ());
513 /* We ignore the return value, casting it to void in order to avoid
514 a compiler warning. The warning itself was introduced by a patch
515 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
516 to code that causes the compiler to generate an unused-value
518 (void) wstandend (handle
);
523 tui_data_item_window::refresh_window ()
525 if (handle
!= nullptr)
527 /* This seems to be needed because the data items are nested
528 windows, which according to the ncurses man pages aren't well
535 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
536 around behaviour. Returns the next register group, or NULL if the
537 register window is not currently being displayed. */
539 static struct reggroup
*
540 tui_reg_next (struct reggroup
*current_group
, struct gdbarch
*gdbarch
)
542 struct reggroup
*group
= NULL
;
544 if (current_group
!= NULL
)
546 group
= reggroup_next (gdbarch
, current_group
);
548 group
= reggroup_next (gdbarch
, NULL
);
553 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
554 around behaviour. Returns the previous register group, or NULL if the
555 register window is not currently being displayed. */
557 static struct reggroup
*
558 tui_reg_prev (struct reggroup
*current_group
, struct gdbarch
*gdbarch
)
560 struct reggroup
*group
= NULL
;
562 if (current_group
!= NULL
)
564 group
= reggroup_prev (gdbarch
, current_group
);
566 group
= reggroup_prev (gdbarch
, NULL
);
571 /* A helper function to display the register window in the appropriate
577 enum tui_layout_type cur_layout
= tui_current_layout ();
578 enum tui_layout_type new_layout
;
579 if (cur_layout
== SRC_COMMAND
|| cur_layout
== SRC_DATA_COMMAND
)
580 new_layout
= SRC_DATA_COMMAND
;
582 new_layout
= DISASSEM_DATA_COMMAND
;
583 tui_set_layout (new_layout
);
586 /* Implement the 'tui reg' command. Changes the register group displayed
587 in the tui register window. Displays the tui register window if it is
588 not already on display. */
591 tui_reg_command (const char *args
, int from_tty
)
593 struct gdbarch
*gdbarch
= get_current_arch ();
597 struct reggroup
*group
, *match
= NULL
;
598 size_t len
= strlen (args
);
600 /* Make sure the curses mode is enabled. */
603 /* Make sure the register window is visible. If not, select an
604 appropriate layout. We need to do this before trying to run the
605 'next' or 'prev' commands. */
606 if (TUI_DATA_WIN
== NULL
|| !TUI_DATA_WIN
->is_visible ())
609 struct reggroup
*current_group
= TUI_DATA_WIN
->get_current_group ();
610 if (strncmp (args
, "next", len
) == 0)
611 match
= tui_reg_next (current_group
, gdbarch
);
612 else if (strncmp (args
, "prev", len
) == 0)
613 match
= tui_reg_prev (current_group
, gdbarch
);
615 /* This loop matches on the initial part of a register group
616 name. If this initial part in ARGS matches only one register
617 group then the switch is made. */
618 for (group
= reggroup_next (gdbarch
, NULL
);
620 group
= reggroup_next (gdbarch
, group
))
622 if (strncmp (reggroup_name (group
), args
, len
) == 0)
625 error (_("ambiguous register group name '%s'"), args
);
631 error (_("unknown register group '%s'"), args
);
633 TUI_DATA_WIN
->show_registers (match
);
637 struct reggroup
*group
;
640 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
641 "either a register group,\nor one of 'next' "
642 "or 'prev'. Known register groups are:\n"));
644 for (first
= 1, group
= reggroup_next (gdbarch
, NULL
);
646 first
= 0, group
= reggroup_next (gdbarch
, group
))
649 printf_unfiltered (", ");
650 printf_unfiltered ("%s", reggroup_name (group
));
653 printf_unfiltered ("\n");
657 /* Complete names of register groups, and add the special "prev" and "next"
661 tui_reggroup_completer (struct cmd_list_element
*ignore
,
662 completion_tracker
&tracker
,
663 const char *text
, const char *word
)
665 static const char *extra
[] = { "next", "prev", NULL
};
666 size_t len
= strlen (word
);
669 reggroup_completer (ignore
, tracker
, text
, word
);
671 /* XXXX use complete_on_enum instead? */
672 for (tmp
= extra
; *tmp
!= NULL
; ++tmp
)
674 if (strncmp (word
, *tmp
, len
) == 0)
675 tracker
.add_completion (make_unique_xstrdup (*tmp
));
680 _initialize_tui_regs (void)
682 struct cmd_list_element
**tuicmd
, *cmd
;
684 tuicmd
= tui_get_cmd_list ();
686 cmd
= add_cmd ("reg", class_tui
, tui_reg_command
, _("\
687 TUI command to control the register window."), tuicmd
);
688 set_cmd_completer (cmd
, tui_reggroup_completer
);