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
= m_regs_content
.size () / m_regs_column_count
;
100 if (m_regs_content
.size () % m_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
< m_regs_content
.size ())
117 if (element_no
< m_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
* m_regs_column_count
<= m_regs_content
.size ())
135 return ((line_no
+ 1) * m_regs_column_count
) - m_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
== m_current_group
);
153 /* Clear all notation of changed values. */
154 for (auto &&data_item_win
: m_regs_content
)
155 data_item_win
.highlight
= false;
156 m_current_group
= group
;
161 m_regs_content
.clear ();
168 /* Set the data window to display the registers of the register group
169 using the given frame. Values are refreshed only when
170 refresh_values_only is true. */
173 tui_data_window::show_register_group (struct reggroup
*group
,
174 struct frame_info
*frame
,
175 bool refresh_values_only
)
177 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
181 /* Make a new title showing which group we display. */
182 title
= string_printf ("Register group: %s", reggroup_name (group
));
184 /* See how many registers must be displayed. */
186 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
190 /* Must be in the group. */
191 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
194 /* If the register name is empty, it is undefined for this
195 processor, so don't display anything. */
196 name
= gdbarch_register_name (gdbarch
, regnum
);
197 if (name
== 0 || *name
== '\0')
203 m_regs_content
.resize (nr_regs
);
205 /* Now set the register names and values. */
207 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
209 struct tui_data_item_window
*data_item_win
;
212 /* Must be in the group. */
213 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
216 /* If the register name is empty, it is undefined for this
217 processor, so don't display anything. */
218 name
= gdbarch_register_name (gdbarch
, regnum
);
219 if (name
== 0 || *name
== '\0')
222 data_item_win
= &m_regs_content
[pos
];
225 if (!refresh_values_only
)
227 data_item_win
->item_no
= regnum
;
228 data_item_win
->name
= name
;
229 data_item_win
->highlight
= false;
231 tui_get_register (frame
, data_item_win
, regnum
, 0);
237 /* See tui-regs.h. */
240 tui_data_window::display_registers_from (int start_element_no
)
242 int j
, item_win_width
, cur_y
;
245 for (auto &&data_item_win
: m_regs_content
)
251 p
= data_item_win
.content
.get ();
258 item_win_width
= max_len
+ 1;
259 int i
= start_element_no
;
261 m_regs_column_count
= (width
- 2) / item_win_width
;
262 if (m_regs_column_count
== 0)
263 m_regs_column_count
= 1;
264 item_win_width
= (width
- 2) / m_regs_column_count
;
266 /* Now create each data "sub" window, and write the display into
269 while (i
< m_regs_content
.size ()
270 && cur_y
<= viewport_height
)
273 j
< m_regs_column_count
&& i
< m_regs_content
.size ();
276 /* Create the window if necessary. */
277 m_regs_content
[i
].resize (1, item_win_width
,
278 (item_win_width
* j
) + 1, cur_y
);
279 i
++; /* Next register. */
281 cur_y
++; /* Next row. */
285 /* See tui-regs.h. */
288 tui_data_window::display_reg_element_at_line (int start_element_no
,
291 int element_no
= start_element_no
;
293 if (start_element_no
!= 0 && start_line_no
!= 0)
295 int last_line_no
, first_line_on_last_page
;
297 last_line_no
= last_regs_line_no ();
298 first_line_on_last_page
= last_line_no
- (height
- 2);
299 if (first_line_on_last_page
< 0)
300 first_line_on_last_page
= 0;
302 /* If the element_no causes us to scroll past the end of the
303 registers, adjust what element to really start the
305 if (start_line_no
> first_line_on_last_page
)
306 element_no
= first_reg_element_no_inline (first_line_on_last_page
);
308 display_registers_from (element_no
);
311 /* See tui-regs.h. */
314 tui_data_window::display_registers_from_line (int line_no
)
322 /* Make sure that we don't display off the end of the
324 if (line_no
>= last_regs_line_no ())
326 line_no
= line_from_reg_element_no (m_regs_content
.size () - 1);
332 element_no
= first_reg_element_no_inline (line_no
);
333 if (element_no
< m_regs_content
.size ())
334 display_reg_element_at_line (element_no
, line_no
);
342 /* Answer the index first element displayed. If none are displayed,
345 tui_data_window::first_data_item_displayed ()
347 for (int i
= 0; i
< m_regs_content
.size (); i
++)
349 struct tui_gen_win_info
*data_item_win
;
351 data_item_win
= &m_regs_content
[i
];
352 if (data_item_win
->is_visible ())
359 /* See tui-regs.h. */
362 tui_data_window::delete_data_content_windows ()
364 for (auto &&win
: m_regs_content
)
365 win
.handle
.reset (nullptr);
370 tui_data_window::erase_data_content (const char *prompt
)
372 werase (handle
.get ());
373 check_and_display_highlight_if_needed ();
376 int half_width
= (width
- 2) / 2;
379 if (strlen (prompt
) >= half_width
)
382 x_pos
= half_width
- strlen (prompt
);
383 mvwaddstr (handle
.get (), (height
/ 2), x_pos
, (char *) prompt
);
385 wrefresh (handle
.get ());
388 /* See tui-regs.h. */
391 tui_data_window::rerender ()
393 if (m_regs_content
.empty ())
394 erase_data_content (_("[ Register Values Unavailable ]"));
397 erase_data_content (NULL
);
398 delete_data_content_windows ();
399 display_registers_from (0);
404 /* Scroll the data window vertically forward or backward. */
406 tui_data_window::do_scroll_vertical (int num_to_scroll
)
408 int first_element_no
;
409 int first_line
= (-1);
411 first_element_no
= first_data_item_displayed ();
412 if (first_element_no
< m_regs_content
.size ())
413 first_line
= line_from_reg_element_no (first_element_no
);
415 { /* Calculate the first line from the element number which is in
416 the general data content. */
421 first_line
+= num_to_scroll
;
422 erase_data_content (NULL
);
423 delete_data_content_windows ();
424 display_registers_from_line (first_line
);
428 /* See tui-regs.h. */
431 tui_data_window::refresh_window ()
433 tui_gen_win_info::refresh_window ();
434 for (auto &&win
: m_regs_content
)
435 win
.refresh_window ();
438 /* This function check all displayed registers for changes in values,
439 given a particular frame. If the values have changed, they are
440 updated with the new value and highlighted. */
442 tui_data_window::check_register_values (struct frame_info
*frame
)
444 if (m_regs_content
.empty ())
445 show_registers (m_current_group
);
448 for (auto &&data_item_win
: m_regs_content
)
452 was_hilighted
= data_item_win
.highlight
;
454 tui_get_register (frame
, &data_item_win
,
455 data_item_win
.item_no
,
456 &data_item_win
.highlight
);
458 if (data_item_win
.highlight
|| was_hilighted
)
459 data_item_win
.rerender ();
464 /* Display a register in a window. If hilite is TRUE, then the value
465 will be displayed in reverse video. */
467 tui_data_item_window::rerender ()
471 scrollok (handle
.get (), FALSE
);
473 /* We ignore the return value, casting it to void in order to avoid
474 a compiler warning. The warning itself was introduced by a patch
475 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
476 to code that causes the compiler to generate an unused-value
478 (void) wstandout (handle
.get ());
480 wmove (handle
.get (), 0, 0);
481 for (i
= 1; i
< width
; i
++)
482 waddch (handle
.get (), ' ');
483 wmove (handle
.get (), 0, 0);
485 waddstr (handle
.get (), content
.get ());
488 /* We ignore the return value, casting it to void in order to avoid
489 a compiler warning. The warning itself was introduced by a patch
490 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
491 to code that causes the compiler to generate an unused-value
493 (void) wstandend (handle
.get ());
498 tui_data_item_window::refresh_window ()
500 if (handle
!= nullptr)
502 /* This seems to be needed because the data items are nested
503 windows, which according to the ncurses man pages aren't well
505 touchwin (handle
.get ());
506 wrefresh (handle
.get ());
510 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
511 around behaviour. Returns the next register group, or NULL if the
512 register window is not currently being displayed. */
514 static struct reggroup
*
515 tui_reg_next (struct reggroup
*current_group
, struct gdbarch
*gdbarch
)
517 struct reggroup
*group
= NULL
;
519 if (current_group
!= NULL
)
521 group
= reggroup_next (gdbarch
, current_group
);
523 group
= reggroup_next (gdbarch
, NULL
);
528 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
529 around behaviour. Returns the previous register group, or NULL if the
530 register window is not currently being displayed. */
532 static struct reggroup
*
533 tui_reg_prev (struct reggroup
*current_group
, struct gdbarch
*gdbarch
)
535 struct reggroup
*group
= NULL
;
537 if (current_group
!= NULL
)
539 group
= reggroup_prev (gdbarch
, current_group
);
541 group
= reggroup_prev (gdbarch
, NULL
);
546 /* A helper function to display the register window in the appropriate
552 enum tui_layout_type cur_layout
= tui_current_layout ();
553 enum tui_layout_type new_layout
;
554 if (cur_layout
== SRC_COMMAND
|| cur_layout
== SRC_DATA_COMMAND
)
555 new_layout
= SRC_DATA_COMMAND
;
557 new_layout
= DISASSEM_DATA_COMMAND
;
558 tui_set_layout (new_layout
);
561 /* Implement the 'tui reg' command. Changes the register group displayed
562 in the tui register window. Displays the tui register window if it is
563 not already on display. */
566 tui_reg_command (const char *args
, int from_tty
)
568 struct gdbarch
*gdbarch
= get_current_arch ();
572 struct reggroup
*group
, *match
= NULL
;
573 size_t len
= strlen (args
);
575 /* Make sure the curses mode is enabled. */
578 /* Make sure the register window is visible. If not, select an
579 appropriate layout. We need to do this before trying to run the
580 'next' or 'prev' commands. */
581 if (TUI_DATA_WIN
== NULL
|| !TUI_DATA_WIN
->is_visible ())
584 struct reggroup
*current_group
= TUI_DATA_WIN
->get_current_group ();
585 if (strncmp (args
, "next", len
) == 0)
586 match
= tui_reg_next (current_group
, gdbarch
);
587 else if (strncmp (args
, "prev", len
) == 0)
588 match
= tui_reg_prev (current_group
, gdbarch
);
590 /* This loop matches on the initial part of a register group
591 name. If this initial part in ARGS matches only one register
592 group then the switch is made. */
593 for (group
= reggroup_next (gdbarch
, NULL
);
595 group
= reggroup_next (gdbarch
, group
))
597 if (strncmp (reggroup_name (group
), args
, len
) == 0)
600 error (_("ambiguous register group name '%s'"), args
);
606 error (_("unknown register group '%s'"), args
);
608 TUI_DATA_WIN
->show_registers (match
);
612 struct reggroup
*group
;
615 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
616 "either a register group,\nor one of 'next' "
617 "or 'prev'. Known register groups are:\n"));
619 for (first
= 1, group
= reggroup_next (gdbarch
, NULL
);
621 first
= 0, group
= reggroup_next (gdbarch
, group
))
624 printf_unfiltered (", ");
625 printf_unfiltered ("%s", reggroup_name (group
));
628 printf_unfiltered ("\n");
632 /* Complete names of register groups, and add the special "prev" and "next"
636 tui_reggroup_completer (struct cmd_list_element
*ignore
,
637 completion_tracker
&tracker
,
638 const char *text
, const char *word
)
640 static const char *extra
[] = { "next", "prev", NULL
};
641 size_t len
= strlen (word
);
644 reggroup_completer (ignore
, tracker
, text
, word
);
646 /* XXXX use complete_on_enum instead? */
647 for (tmp
= extra
; *tmp
!= NULL
; ++tmp
)
649 if (strncmp (word
, *tmp
, len
) == 0)
650 tracker
.add_completion (make_unique_xstrdup (*tmp
));
655 _initialize_tui_regs (void)
657 struct cmd_list_element
**tuicmd
, *cmd
;
659 tuicmd
= tui_get_cmd_list ();
661 cmd
= add_cmd ("reg", class_tui
, tui_reg_command
, _("\
662 TUI command to control the register window."), tuicmd
);
663 set_cmd_completer (cmd
, tui_reggroup_completer
);