1 /* TUI display registers in window.
3 Copyright (C) 1998-2022 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 /* A subclass of string_file that expands tab characters. */
46 class tab_expansion_file
: public string_file
50 tab_expansion_file () = default;
52 void write (const char *buf
, long length_buf
) override
;
60 tab_expansion_file::write (const char *buf
, long length_buf
)
62 for (long i
= 0; i
< length_buf
; ++i
)
68 string_file::write (" ", 1);
71 while ((m_column
% 8) != 0);
75 string_file::write (&buf
[i
], 1);
84 /* Get the register from the frame and return a printable
85 representation of it. */
88 tui_register_format (struct frame_info
*frame
, int regnum
)
90 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
92 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
93 tab_expansion_file stream
;
95 scoped_restore save_pagination
96 = make_scoped_restore (&pagination_enabled
, 0);
97 scoped_restore save_stdout
98 = make_scoped_restore (&gdb_stdout
, &stream
);
100 gdbarch_print_registers_info (gdbarch
, &stream
, frame
, regnum
, 1);
102 /* Remove the possible \n. */
103 std::string str
= stream
.release ();
104 if (!str
.empty () && str
.back () == '\n')
105 str
.resize (str
.size () - 1);
110 /* Get the register value from the given frame and format it for the
111 display. When changep is set, check if the new register value has
112 changed with respect to the previous call. */
114 tui_get_register (struct frame_info
*frame
,
115 struct tui_data_item_window
*data
,
116 int regnum
, bool *changedp
)
120 if (target_has_registers ())
122 std::string new_content
= tui_register_format (frame
, regnum
);
124 if (changedp
!= NULL
&& data
->content
!= new_content
)
127 data
->content
= std::move (new_content
);
131 /* See tui-regs.h. */
134 tui_data_window::last_regs_line_no () const
136 int num_lines
= m_regs_content
.size () / m_regs_column_count
;
137 if (m_regs_content
.size () % m_regs_column_count
)
142 /* See tui-regs.h. */
145 tui_data_window::line_from_reg_element_no (int element_no
) const
147 if (element_no
< m_regs_content
.size ())
154 if (element_no
< m_regs_column_count
* i
)
166 /* See tui-regs.h. */
169 tui_data_window::first_reg_element_no_inline (int line_no
) const
171 if (line_no
* m_regs_column_count
<= m_regs_content
.size ())
172 return ((line_no
+ 1) * m_regs_column_count
) - m_regs_column_count
;
177 /* Show the registers of the given group in the data window
178 and refresh the window. */
180 tui_data_window::show_registers (const reggroup
*group
)
183 group
= general_reggroup
;
185 if (target_has_registers () && target_has_stack () && target_has_memory ())
187 show_register_group (group
, get_selected_frame (NULL
),
188 group
== m_current_group
);
190 /* Clear all notation of changed values. */
191 for (auto &&data_item_win
: m_regs_content
)
192 data_item_win
.highlight
= false;
193 m_current_group
= group
;
198 m_regs_content
.clear ();
205 /* Set the data window to display the registers of the register group
206 using the given frame. Values are refreshed only when
207 refresh_values_only is true. */
210 tui_data_window::show_register_group (const reggroup
*group
,
211 struct frame_info
*frame
,
212 bool refresh_values_only
)
214 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
218 /* Make a new title showing which group we display. */
219 title
= string_printf ("Register group: %s", group
->name ());
221 /* See how many registers must be displayed. */
223 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
227 /* Must be in the group. */
228 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
231 /* If the register name is empty, it is undefined for this
232 processor, so don't display anything. */
233 name
= gdbarch_register_name (gdbarch
, regnum
);
234 if (name
== 0 || *name
== '\0')
240 m_regs_content
.resize (nr_regs
);
242 /* Now set the register names and values. */
244 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
246 struct tui_data_item_window
*data_item_win
;
249 /* Must be in the group. */
250 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
253 /* If the register name is empty, it is undefined for this
254 processor, so don't display anything. */
255 name
= gdbarch_register_name (gdbarch
, regnum
);
256 if (name
== 0 || *name
== '\0')
259 data_item_win
= &m_regs_content
[pos
];
260 if (!refresh_values_only
)
262 data_item_win
->regno
= regnum
;
263 data_item_win
->highlight
= false;
265 tui_get_register (frame
, data_item_win
, regnum
, 0);
270 /* See tui-regs.h. */
273 tui_data_window::display_registers_from (int start_element_no
)
276 for (auto &&data_item_win
: m_regs_content
)
278 int len
= data_item_win
.content
.size ();
283 m_item_width
= max_len
+ 1;
286 /* Mark register windows above the visible area. */
287 for (i
= 0; i
< start_element_no
; i
++)
288 m_regs_content
[i
].y
= 0;
290 m_regs_column_count
= (width
- 2) / m_item_width
;
291 if (m_regs_column_count
== 0)
292 m_regs_column_count
= 1;
293 m_item_width
= (width
- 2) / m_regs_column_count
;
295 /* Now create each data "sub" window, and write the display into
298 while (i
< m_regs_content
.size () && cur_y
<= height
- 2)
301 j
< m_regs_column_count
&& i
< m_regs_content
.size ();
304 /* Create the window if necessary. */
305 m_regs_content
[i
].x
= (m_item_width
* j
) + 1;
306 m_regs_content
[i
].y
= cur_y
;
307 m_regs_content
[i
].visible
= true;
308 m_regs_content
[i
].rerender (handle
.get (), m_item_width
);
309 i
++; /* Next register. */
311 cur_y
++; /* Next row. */
314 /* Mark register windows below the visible area. */
315 for (; i
< m_regs_content
.size (); i
++)
316 m_regs_content
[i
].y
= 0;
321 /* See tui-regs.h. */
324 tui_data_window::display_reg_element_at_line (int start_element_no
,
327 int element_no
= start_element_no
;
329 if (start_element_no
!= 0 && start_line_no
!= 0)
331 int last_line_no
, first_line_on_last_page
;
333 last_line_no
= last_regs_line_no ();
334 first_line_on_last_page
= last_line_no
- (height
- 2);
335 if (first_line_on_last_page
< 0)
336 first_line_on_last_page
= 0;
338 /* If the element_no causes us to scroll past the end of the
339 registers, adjust what element to really start the
341 if (start_line_no
> first_line_on_last_page
)
342 element_no
= first_reg_element_no_inline (first_line_on_last_page
);
344 display_registers_from (element_no
);
347 /* See tui-regs.h. */
350 tui_data_window::display_registers_from_line (int line_no
)
358 /* Make sure that we don't display off the end of the
360 if (line_no
>= last_regs_line_no ())
362 line_no
= line_from_reg_element_no (m_regs_content
.size () - 1);
368 element_no
= first_reg_element_no_inline (line_no
);
369 if (element_no
< m_regs_content
.size ())
370 display_reg_element_at_line (element_no
, line_no
);
378 /* Answer the index first element displayed. If none are displayed,
381 tui_data_window::first_data_item_displayed ()
383 for (int i
= 0; i
< m_regs_content
.size (); i
++)
385 if (m_regs_content
[i
].visible
)
392 /* See tui-regs.h. */
395 tui_data_window::delete_data_content_windows ()
397 for (auto &win
: m_regs_content
)
403 tui_data_window::erase_data_content (const char *prompt
)
405 werase (handle
.get ());
406 check_and_display_highlight_if_needed ();
409 int half_width
= (width
- 2) / 2;
412 if (strlen (prompt
) >= half_width
)
415 x_pos
= half_width
- strlen (prompt
);
416 mvwaddstr (handle
.get (), (height
/ 2), x_pos
, (char *) prompt
);
418 tui_wrefresh (handle
.get ());
421 /* See tui-regs.h. */
424 tui_data_window::rerender ()
426 if (m_regs_content
.empty ())
427 erase_data_content (_("[ Register Values Unavailable ]"));
430 erase_data_content (NULL
);
431 delete_data_content_windows ();
432 display_registers_from (0);
437 /* Scroll the data window vertically forward or backward. */
439 tui_data_window::do_scroll_vertical (int num_to_scroll
)
441 int first_element_no
;
442 int first_line
= (-1);
444 first_element_no
= first_data_item_displayed ();
445 if (first_element_no
< m_regs_content
.size ())
446 first_line
= line_from_reg_element_no (first_element_no
);
448 { /* Calculate the first line from the element number which is in
449 the general data content. */
454 first_line
+= num_to_scroll
;
455 erase_data_content (NULL
);
456 delete_data_content_windows ();
457 display_registers_from_line (first_line
);
461 /* This function check all displayed registers for changes in values,
462 given a particular frame. If the values have changed, they are
463 updated with the new value and highlighted. */
465 tui_data_window::check_register_values (struct frame_info
*frame
)
467 if (m_regs_content
.empty ())
468 show_registers (m_current_group
);
471 for (auto &&data_item_win
: m_regs_content
)
475 was_hilighted
= data_item_win
.highlight
;
477 tui_get_register (frame
, &data_item_win
,
479 &data_item_win
.highlight
);
481 /* Register windows whose y == 0 are outside the visible area. */
482 if ((data_item_win
.highlight
|| was_hilighted
)
483 && data_item_win
.y
> 0)
484 data_item_win
.rerender (handle
.get (), m_item_width
);
488 tui_wrefresh (handle
.get ());
491 /* Display a register in a window. If hilite is TRUE, then the value
492 will be displayed in reverse video. */
494 tui_data_item_window::rerender (WINDOW
*handle
, int field_width
)
497 /* We ignore the return value, casting it to void in order to avoid
498 a compiler warning. The warning itself was introduced by a patch
499 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
500 to code that causes the compiler to generate an unused-value
502 (void) wstandout (handle
);
504 mvwaddnstr (handle
, y
, x
, content
.c_str (), field_width
- 1);
505 if (content
.size () < field_width
)
506 waddstr (handle
, n_spaces (field_width
- content
.size ()));
509 /* We ignore the return value, casting it to void in order to avoid
510 a compiler warning. The warning itself was introduced by a patch
511 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
512 to code that causes the compiler to generate an unused-value
514 (void) wstandend (handle
);
517 /* Helper for "tui reg next", returns the next register group after
518 CURRENT_GROUP in the register group list for GDBARCH, with wrap around
521 If CURRENT_GROUP is nullptr (e.g. if the tui register window has only
522 just been displayed and has no current group selected) or the currently
523 selected register group can't be found (e.g. if the architecture has
524 changed since the register window was last updated), then the first
525 register group will be returned. */
527 static const reggroup
*
528 tui_reg_next (const reggroup
*current_group
, struct gdbarch
*gdbarch
)
530 const std::vector
<const reggroup
*> &groups
= gdbarch_reggroups (gdbarch
);
531 auto it
= std::find (groups
.begin (), groups
.end (), current_group
);
532 if (it
!= groups
.end ())
534 if (it
== groups
.end ())
535 return groups
.front ();
539 /* Helper for "tui reg prev", returns the register group previous to
540 CURRENT_GROUP in the register group list for GDBARCH, with wrap around
543 If CURRENT_GROUP is nullptr (e.g. if the tui register window has only
544 just been displayed and has no current group selected) or the currently
545 selected register group can't be found (e.g. if the architecture has
546 changed since the register window was last updated), then the last
547 register group will be returned. */
549 static const reggroup
*
550 tui_reg_prev (const reggroup
*current_group
, struct gdbarch
*gdbarch
)
552 const std::vector
<const reggroup
*> &groups
= gdbarch_reggroups (gdbarch
);
553 auto it
= std::find (groups
.rbegin (), groups
.rend (), current_group
);
554 if (it
!= groups
.rend ())
556 if (it
== groups
.rend ())
557 return groups
.back ();
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 size_t len
= strlen (args
);
574 /* Make sure the curses mode is enabled. */
577 tui_suppress_output suppress
;
579 /* Make sure the register window is visible. If not, select an
580 appropriate layout. We need to do this before trying to run the
581 'next' or 'prev' commands. */
582 if (TUI_DATA_WIN
== NULL
|| !TUI_DATA_WIN
->is_visible ())
585 const reggroup
*match
= nullptr;
586 const reggroup
*current_group
= TUI_DATA_WIN
->get_current_group ();
587 if (strncmp (args
, "next", len
) == 0)
588 match
= tui_reg_next (current_group
, gdbarch
);
589 else if (strncmp (args
, "prev", len
) == 0)
590 match
= tui_reg_prev (current_group
, gdbarch
);
593 /* This loop matches on the initial part of a register group
594 name. If this initial part in ARGS matches only one register
595 group then the switch is made. */
596 for (const struct reggroup
*group
: gdbarch_reggroups (gdbarch
))
598 if (strncmp (group
->name (), args
, len
) == 0)
601 error (_("ambiguous register group name '%s'"), args
);
608 error (_("unknown register group '%s'"), args
);
610 TUI_DATA_WIN
->show_registers (match
);
614 gdb_printf (_("\"tui reg\" must be followed by the name of "
615 "either a register group,\nor one of 'next' "
616 "or 'prev'. Known register groups are:\n"));
619 for (const struct reggroup
*group
: gdbarch_reggroups (gdbarch
))
624 gdb_printf ("%s", group
->name ());
631 /* Complete names of register groups, and add the special "prev" and "next"
635 tui_reggroup_completer (struct cmd_list_element
*ignore
,
636 completion_tracker
&tracker
,
637 const char *text
, const char *word
)
639 static const char * const extra
[] = { "next", "prev", NULL
};
641 reggroup_completer (ignore
, tracker
, text
, word
);
643 complete_on_enum (tracker
, extra
, text
, word
);
646 void _initialize_tui_regs ();
648 _initialize_tui_regs ()
650 struct cmd_list_element
**tuicmd
, *cmd
;
652 tuicmd
= tui_get_cmd_list ();
654 cmd
= add_cmd ("reg", class_tui
, tui_reg_command
, _("\
655 TUI command to control the register window.\n\
656 Usage: tui reg NAME\n\
657 NAME is the name of the register group to display"), tuicmd
);
658 set_cmd_completer (cmd
, tui_reggroup_completer
);