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-windata.h"
36 #include "tui/tui-wingeneral.h"
37 #include "tui/tui-file.h"
38 #include "tui/tui-regs.h"
39 #include "tui/tui-io.h"
40 #include "reggroups.h"
42 #include "completer.h"
44 #include "gdb_curses.h"
47 /*****************************************
48 ** STATIC LOCAL FUNCTIONS FORWARD DECLS **
49 ******************************************/
50 static void tui_display_register (struct tui_data_item_window
*data
);
52 static void tui_show_register_group (tui_data_window
*win_info
,
53 struct reggroup
*group
,
54 struct frame_info
*frame
,
55 int refresh_values_only
);
57 static enum tui_status
tui_get_register (struct frame_info
*frame
,
58 struct tui_data_item_window
*data
,
59 int regnum
, bool *changedp
);
63 /*****************************************
64 ** PUBLIC FUNCTIONS **
65 ******************************************/
70 tui_data_window::last_regs_line_no () const
74 if (!regs_content
.empty ())
76 num_lines
= regs_content
.size () / regs_column_count
;
77 if (regs_content
.size () % regs_column_count
)
86 tui_data_window::line_from_reg_element_no (int element_no
) const
88 if (element_no
< regs_content
.size ())
95 if (element_no
< regs_column_count
* i
)
107 /* See tui-data.h. */
110 tui_data_window::first_reg_element_no_inline (int line_no
) const
112 if (line_no
* regs_column_count
<= regs_content
.size ())
113 return ((line_no
+ 1) * regs_column_count
) - regs_column_count
;
119 /* Show the registers of the given group in the data window
120 and refresh the window. */
122 tui_show_registers (struct reggroup
*group
)
124 enum tui_status ret
= TUI_FAILURE
;
126 /* Make sure the curses mode is enabled. */
129 /* Make sure the register window is visible. If not, select an
130 appropriate layout. */
131 if (TUI_DATA_WIN
== NULL
|| !TUI_DATA_WIN
->is_visible
)
132 tui_set_layout_by_name (DATA_NAME
);
135 group
= general_reggroup
;
137 /* Say that registers should be displayed, even if there is a
139 TUI_DATA_WIN
->display_regs
= true;
141 if (target_has_registers
&& target_has_stack
&& target_has_memory
)
143 tui_show_register_group (TUI_DATA_WIN
, group
, get_selected_frame (NULL
),
144 group
== TUI_DATA_WIN
->current_group
);
147 if (ret
== TUI_FAILURE
)
149 TUI_DATA_WIN
->current_group
= 0;
150 TUI_DATA_WIN
->erase_data_content (NO_REGS_STRING
);
154 /* Clear all notation of changed values. */
155 for (auto &&data_item_win
: TUI_DATA_WIN
->regs_content
)
157 if (data_item_win
!= nullptr)
158 data_item_win
->highlight
= false;
160 TUI_DATA_WIN
->current_group
= group
;
161 TUI_DATA_WIN
->display_all_data ();
166 /* Set the data window to display the registers of the register group
167 using the given frame. Values are refreshed only when
168 refresh_values_only is TRUE. */
171 tui_show_register_group (tui_data_window
*win_info
,
172 struct reggroup
*group
,
173 struct frame_info
*frame
,
174 int refresh_values_only
)
176 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
181 /* Make a new title showing which group we display. */
182 snprintf (title
, sizeof (title
) - 1, "Register group: %s",
183 reggroup_name (group
));
184 xfree (win_info
->title
);
185 win_info
->title
= xstrdup (title
);
187 /* See how many registers must be displayed. */
189 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
193 /* Must be in the group. */
194 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
197 /* If the register name is empty, it is undefined for this
198 processor, so don't display anything. */
199 name
= gdbarch_register_name (gdbarch
, regnum
);
200 if (name
== 0 || *name
== '\0')
206 if (!refresh_values_only
)
207 win_info
->regs_content
.clear ();
209 if (nr_regs
< win_info
->regs_content
.size ())
210 win_info
->regs_content
.resize (nr_regs
);
213 for (int i
= win_info
->regs_content
.size (); i
< nr_regs
; ++i
)
214 win_info
->regs_content
.emplace_back (new tui_data_item_window ());
217 /* Now set the register names and values. */
219 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
221 struct tui_data_item_window
*data_item_win
;
224 /* Must be in the group. */
225 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
228 /* If the register name is empty, it is undefined for this
229 processor, so don't display anything. */
230 name
= gdbarch_register_name (gdbarch
, regnum
);
231 if (name
== 0 || *name
== '\0')
234 data_item_win
= win_info
->regs_content
[pos
].get ();
237 if (!refresh_values_only
)
239 data_item_win
->item_no
= regnum
;
240 data_item_win
->name
= name
;
241 data_item_win
->highlight
= false;
243 tui_get_register (frame
, data_item_win
, regnum
, 0);
249 /* See tui-data.h. */
252 tui_data_window::display_registers_from (int start_element_no
)
254 if (!regs_content
.empty ())
256 int j
, item_win_width
, cur_y
;
259 for (auto &&data_item_win
: regs_content
)
265 p
= data_item_win
->content
;
270 len
= 8 * ((len
/ 8) + 1);
278 item_win_width
= max_len
+ 1;
279 int i
= start_element_no
;
281 regs_column_count
= (width
- 2) / item_win_width
;
282 if (regs_column_count
== 0)
283 regs_column_count
= 1;
284 item_win_width
= (width
- 2) / regs_column_count
;
286 /* Now create each data "sub" window, and write the display into
289 while (i
< regs_content
.size ()
290 && cur_y
<= viewport_height
)
293 j
< regs_column_count
&& i
< regs_content
.size ();
296 struct tui_data_item_window
*data_item_win
;
298 /* Create the window if necessary. */
299 data_item_win
= regs_content
[i
].get ();
300 if (data_item_win
->handle
!= NULL
301 && (data_item_win
->height
!= 1
302 || data_item_win
->width
!= item_win_width
303 || data_item_win
->origin
.x
!= (item_win_width
* j
) + 1
304 || data_item_win
->origin
.y
!= cur_y
))
306 tui_delete_win (data_item_win
->handle
);
307 data_item_win
->handle
= 0;
310 if (data_item_win
->handle
== NULL
)
312 data_item_win
->height
= 1;
313 data_item_win
->width
= item_win_width
;
314 data_item_win
->origin
.x
= (item_win_width
* j
) + 1;
315 data_item_win
->origin
.y
= cur_y
;
316 tui_make_window (data_item_win
, DONT_BOX_WINDOW
);
317 scrollok (data_item_win
->handle
, FALSE
);
319 touchwin (data_item_win
->handle
);
321 /* Get the printable representation of the register
323 tui_display_register (data_item_win
);
324 i
++; /* Next register. */
326 cur_y
++; /* Next row. */
331 /* See tui-data.h. */
334 tui_data_window::display_reg_element_at_line (int start_element_no
,
337 if (!regs_content
.empty ())
339 int element_no
= start_element_no
;
341 if (start_element_no
!= 0 && start_line_no
!= 0)
343 int last_line_no
, first_line_on_last_page
;
345 last_line_no
= last_regs_line_no ();
346 first_line_on_last_page
= last_line_no
- (height
- 2);
347 if (first_line_on_last_page
< 0)
348 first_line_on_last_page
= 0;
350 /* If the element_no causes us to scroll past the end of the
351 registers, adjust what element to really start the
353 if (start_line_no
> first_line_on_last_page
)
354 element_no
= first_reg_element_no_inline (first_line_on_last_page
);
356 display_registers_from (element_no
);
360 /* See tui-data.h. */
363 tui_data_window::display_registers_from_line (int line_no
)
365 tui_check_and_display_highlight_if_needed (this);
366 if (!regs_content
.empty ())
374 /* Make sure that we don't display off the end of the
376 if (line_no
>= last_regs_line_no ())
378 line_no
= line_from_reg_element_no (regs_content
.size () - 1);
384 element_no
= first_reg_element_no_inline (line_no
);
385 if (element_no
< regs_content
.size ())
386 display_reg_element_at_line (element_no
, line_no
);
393 return (-1); /* Nothing was displayed. */
397 /* This function check all displayed registers for changes in values,
398 given a particular frame. If the values have changed, they are
399 updated with the new value and highlighted. */
401 tui_check_register_values (struct frame_info
*frame
)
403 if (TUI_DATA_WIN
!= NULL
404 && TUI_DATA_WIN
->is_visible
)
406 if (TUI_DATA_WIN
->regs_content
.empty ()
407 && TUI_DATA_WIN
->display_regs
)
408 tui_show_registers (TUI_DATA_WIN
->current_group
);
411 for (auto &&data_item_win_ptr
: TUI_DATA_WIN
->regs_content
)
415 was_hilighted
= data_item_win_ptr
->highlight
;
417 tui_get_register (frame
, data_item_win_ptr
.get (),
418 data_item_win_ptr
->item_no
,
419 &data_item_win_ptr
->highlight
);
421 if (data_item_win_ptr
->highlight
|| was_hilighted
)
422 tui_display_register (data_item_win_ptr
.get ());
428 /* Display a register in a window. If hilite is TRUE, then the value
429 will be displayed in reverse video. */
431 tui_display_register (struct tui_data_item_window
*data
)
433 if (data
->handle
!= NULL
)
438 /* We ignore the return value, casting it to void in order to avoid
439 a compiler warning. The warning itself was introduced by a patch
440 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
441 to code that causes the compiler to generate an unused-value
443 (void) wstandout (data
->handle
);
445 wmove (data
->handle
, 0, 0);
446 for (i
= 1; i
< data
->width
; i
++)
447 waddch (data
->handle
, ' ');
448 wmove (data
->handle
, 0, 0);
450 waddstr (data
->handle
, data
->content
);
453 /* We ignore the return value, casting it to void in order to avoid
454 a compiler warning. The warning itself was introduced by a patch
455 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
456 to code that causes the compiler to generate an unused-value
458 (void) wstandend (data
->handle
);
459 data
->refresh_window ();
463 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
464 around behaviour. Returns the next register group, or NULL if the
465 register window is not currently being displayed. */
467 static struct reggroup
*
468 tui_reg_next (struct gdbarch
*gdbarch
)
470 struct reggroup
*group
= NULL
;
472 if (TUI_DATA_WIN
!= NULL
)
474 group
= TUI_DATA_WIN
->current_group
;
475 group
= reggroup_next (gdbarch
, group
);
477 group
= reggroup_next (gdbarch
, NULL
);
482 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
483 around behaviour. Returns the previous register group, or NULL if the
484 register window is not currently being displayed. */
486 static struct reggroup
*
487 tui_reg_prev (struct gdbarch
*gdbarch
)
489 struct reggroup
*group
= NULL
;
491 if (TUI_DATA_WIN
!= NULL
)
493 group
= TUI_DATA_WIN
->current_group
;
494 group
= reggroup_prev (gdbarch
, group
);
496 group
= reggroup_prev (gdbarch
, NULL
);
501 /* Implement the 'tui reg' command. Changes the register group displayed
502 in the tui register window. Displays the tui register window if it is
503 not already on display. */
506 tui_reg_command (const char *args
, int from_tty
)
508 struct gdbarch
*gdbarch
= get_current_arch ();
512 struct reggroup
*group
, *match
= NULL
;
513 size_t len
= strlen (args
);
515 /* Make sure the curses mode is enabled. */
518 /* Make sure the register window is visible. If not, select an
519 appropriate layout. We need to do this before trying to run the
520 'next' or 'prev' commands. */
521 if (TUI_DATA_WIN
== NULL
|| !TUI_DATA_WIN
->is_visible
)
522 tui_set_layout_by_name (DATA_NAME
);
524 if (strncmp (args
, "next", len
) == 0)
525 match
= tui_reg_next (gdbarch
);
526 else if (strncmp (args
, "prev", len
) == 0)
527 match
= tui_reg_prev (gdbarch
);
529 /* This loop matches on the initial part of a register group
530 name. If this initial part in ARGS matches only one register
531 group then the switch is made. */
532 for (group
= reggroup_next (gdbarch
, NULL
);
534 group
= reggroup_next (gdbarch
, group
))
536 if (strncmp (reggroup_name (group
), args
, len
) == 0)
539 error (_("ambiguous register group name '%s'"), args
);
545 error (_("unknown register group '%s'"), args
);
547 tui_show_registers (match
);
551 struct reggroup
*group
;
554 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
555 "either a register group,\nor one of 'next' "
556 "or 'prev'. Known register groups are:\n"));
558 for (first
= 1, group
= reggroup_next (gdbarch
, NULL
);
560 first
= 0, group
= reggroup_next (gdbarch
, group
))
563 printf_unfiltered (", ");
564 printf_unfiltered ("%s", reggroup_name (group
));
567 printf_unfiltered ("\n");
571 /* Complete names of register groups, and add the special "prev" and "next"
575 tui_reggroup_completer (struct cmd_list_element
*ignore
,
576 completion_tracker
&tracker
,
577 const char *text
, const char *word
)
579 static const char *extra
[] = { "next", "prev", NULL
};
580 size_t len
= strlen (word
);
583 reggroup_completer (ignore
, tracker
, text
, word
);
585 /* XXXX use complete_on_enum instead? */
586 for (tmp
= extra
; *tmp
!= NULL
; ++tmp
)
588 if (strncmp (word
, *tmp
, len
) == 0)
589 tracker
.add_completion (make_unique_xstrdup (*tmp
));
594 _initialize_tui_regs (void)
596 struct cmd_list_element
**tuicmd
, *cmd
;
598 tuicmd
= tui_get_cmd_list ();
600 cmd
= add_cmd ("reg", class_tui
, tui_reg_command
, _("\
601 TUI command to control the register window."), tuicmd
);
602 set_cmd_completer (cmd
, tui_reggroup_completer
);
606 /*****************************************
607 ** STATIC LOCAL FUNCTIONS **
608 ******************************************/
610 /* Get the register from the frame and return a printable
611 representation of it. */
614 tui_register_format (struct frame_info
*frame
, int regnum
)
616 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
620 scoped_restore save_pagination
621 = make_scoped_restore (&pagination_enabled
, 0);
622 scoped_restore save_stdout
623 = make_scoped_restore (&gdb_stdout
, &stream
);
625 gdbarch_print_registers_info (gdbarch
, &stream
, frame
, regnum
, 1);
627 /* Remove the possible \n. */
628 std::string
&str
= stream
.string ();
629 if (!str
.empty () && str
.back () == '\n')
630 str
.resize (str
.size () - 1);
632 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
633 return tui_expand_tabs (str
.c_str (), 0);
636 /* Get the register value from the given frame and format it for the
637 display. When changep is set, check if the new register value has
638 changed with respect to the previous call. */
639 static enum tui_status
640 tui_get_register (struct frame_info
*frame
,
641 struct tui_data_item_window
*data
,
642 int regnum
, bool *changedp
)
644 enum tui_status ret
= TUI_FAILURE
;
648 if (target_has_registers
)
650 char *prev_content
= data
->content
;
652 data
->content
= tui_register_format (frame
, regnum
);
655 && strcmp (prev_content
, data
->content
) != 0)
658 xfree (prev_content
);