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 (struct reggroup
*group
,
53 struct frame_info
*frame
,
54 int refresh_values_only
);
56 static enum tui_status
tui_get_register (struct frame_info
*frame
,
57 struct tui_data_item_window
*data
,
58 int regnum
, bool *changedp
);
62 /*****************************************
63 ** PUBLIC FUNCTIONS **
64 ******************************************/
69 tui_data_window::last_regs_line_no () const
73 if (!regs_content
.empty ())
75 num_lines
= regs_content
.size () / regs_column_count
;
76 if (regs_content
.size () % regs_column_count
)
85 tui_data_window::line_from_reg_element_no (int element_no
) const
87 if (element_no
< regs_content
.size ())
94 if (element_no
< regs_column_count
* i
)
106 /* See tui-data.h. */
109 tui_data_window::first_reg_element_no_inline (int line_no
) const
111 if (line_no
* regs_column_count
<= regs_content
.size ())
112 return ((line_no
+ 1) * regs_column_count
) - regs_column_count
;
118 /* Show the registers of the given group in the data window
119 and refresh the window. */
121 tui_show_registers (struct reggroup
*group
)
123 enum tui_status ret
= TUI_FAILURE
;
125 /* Make sure the curses mode is enabled. */
128 /* Make sure the register window is visible. If not, select an
129 appropriate layout. */
130 if (TUI_DATA_WIN
== NULL
|| !TUI_DATA_WIN
->is_visible
)
131 tui_set_layout_by_name (DATA_NAME
);
134 group
= general_reggroup
;
136 /* Say that registers should be displayed, even if there is a
138 TUI_DATA_WIN
->display_regs
= true;
140 if (target_has_registers
&& target_has_stack
&& target_has_memory
)
142 tui_show_register_group (group
, get_selected_frame (NULL
),
143 group
== TUI_DATA_WIN
->current_group
);
146 if (ret
== TUI_FAILURE
)
148 TUI_DATA_WIN
->current_group
= 0;
149 TUI_DATA_WIN
->erase_data_content (NO_REGS_STRING
);
153 /* Clear all notation of changed values. */
154 for (auto &&data_item_win
: TUI_DATA_WIN
->regs_content
)
156 if (data_item_win
!= nullptr)
157 data_item_win
->highlight
= false;
159 TUI_DATA_WIN
->current_group
= group
;
160 TUI_DATA_WIN
->display_all_data ();
165 /* Set the data window to display the registers of the register group
166 using the given frame. Values are refreshed only when
167 refresh_values_only is TRUE. */
170 tui_show_register_group (struct reggroup
*group
,
171 struct frame_info
*frame
,
172 int refresh_values_only
)
174 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
179 /* Make a new title showing which group we display. */
180 snprintf (title
, sizeof (title
) - 1, "Register group: %s",
181 reggroup_name (group
));
182 xfree (TUI_DATA_WIN
->title
);
183 TUI_DATA_WIN
->title
= xstrdup (title
);
185 /* See how many registers must be displayed. */
187 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
191 /* Must be in the group. */
192 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
195 /* If the register name is empty, it is undefined for this
196 processor, so don't display anything. */
197 name
= gdbarch_register_name (gdbarch
, regnum
);
198 if (name
== 0 || *name
== '\0')
204 if (!refresh_values_only
)
205 TUI_DATA_WIN
->regs_content
.clear ();
207 if (nr_regs
< TUI_DATA_WIN
->regs_content
.size ())
208 TUI_DATA_WIN
->regs_content
.resize (nr_regs
);
211 for (int i
= TUI_DATA_WIN
->regs_content
.size (); i
< nr_regs
; ++i
)
212 TUI_DATA_WIN
->regs_content
.emplace_back (new tui_data_item_window ());
215 /* Now set the register names and values. */
217 for (regnum
= 0; regnum
< gdbarch_num_cooked_regs (gdbarch
); regnum
++)
219 struct tui_data_item_window
*data_item_win
;
222 /* Must be in the group. */
223 if (!gdbarch_register_reggroup_p (gdbarch
, regnum
, group
))
226 /* If the register name is empty, it is undefined for this
227 processor, so don't display anything. */
228 name
= gdbarch_register_name (gdbarch
, regnum
);
229 if (name
== 0 || *name
== '\0')
232 data_item_win
= TUI_DATA_WIN
->regs_content
[pos
].get ();
235 if (!refresh_values_only
)
237 data_item_win
->item_no
= regnum
;
238 data_item_win
->name
= name
;
239 data_item_win
->highlight
= false;
241 tui_get_register (frame
, data_item_win
, regnum
, 0);
247 /* See tui-data.h. */
250 tui_data_window::display_registers_from (int start_element_no
)
252 if (!regs_content
.empty ())
254 int j
, item_win_width
, cur_y
;
257 for (auto &&data_item_win
: regs_content
)
263 p
= data_item_win
->content
;
268 len
= 8 * ((len
/ 8) + 1);
276 item_win_width
= max_len
+ 1;
277 int i
= start_element_no
;
279 regs_column_count
= (width
- 2) / item_win_width
;
280 if (regs_column_count
== 0)
281 regs_column_count
= 1;
282 item_win_width
= (width
- 2) / regs_column_count
;
284 /* Now create each data "sub" window, and write the display into
287 while (i
< regs_content
.size ()
288 && cur_y
<= viewport_height
)
291 j
< regs_column_count
&& i
< regs_content
.size ();
294 struct tui_data_item_window
*data_item_win
;
296 /* Create the window if necessary. */
297 data_item_win
= regs_content
[i
].get ();
298 if (data_item_win
->handle
!= NULL
299 && (data_item_win
->height
!= 1
300 || data_item_win
->width
!= item_win_width
301 || data_item_win
->origin
.x
!= (item_win_width
* j
) + 1
302 || data_item_win
->origin
.y
!= cur_y
))
304 tui_delete_win (data_item_win
->handle
);
305 data_item_win
->handle
= 0;
308 if (data_item_win
->handle
== NULL
)
310 data_item_win
->height
= 1;
311 data_item_win
->width
= item_win_width
;
312 data_item_win
->origin
.x
= (item_win_width
* j
) + 1;
313 data_item_win
->origin
.y
= cur_y
;
314 tui_make_window (data_item_win
, DONT_BOX_WINDOW
);
315 scrollok (data_item_win
->handle
, FALSE
);
317 touchwin (data_item_win
->handle
);
319 /* Get the printable representation of the register
321 tui_display_register (data_item_win
);
322 i
++; /* Next register. */
324 cur_y
++; /* Next row. */
329 /* See tui-data.h. */
332 tui_data_window::display_reg_element_at_line (int start_element_no
,
335 if (!regs_content
.empty ())
337 int element_no
= start_element_no
;
339 if (start_element_no
!= 0 && start_line_no
!= 0)
341 int last_line_no
, first_line_on_last_page
;
343 last_line_no
= last_regs_line_no ();
344 first_line_on_last_page
= last_line_no
- (height
- 2);
345 if (first_line_on_last_page
< 0)
346 first_line_on_last_page
= 0;
348 /* If the element_no causes us to scroll past the end of the
349 registers, adjust what element to really start the
351 if (start_line_no
> first_line_on_last_page
)
352 element_no
= first_reg_element_no_inline (first_line_on_last_page
);
354 display_registers_from (element_no
);
358 /* See tui-data.h. */
361 tui_data_window::display_registers_from_line (int line_no
)
363 tui_check_and_display_highlight_if_needed (this);
364 if (!regs_content
.empty ())
372 /* Make sure that we don't display off the end of the
374 if (line_no
>= last_regs_line_no ())
376 line_no
= line_from_reg_element_no (regs_content
.size () - 1);
382 element_no
= first_reg_element_no_inline (line_no
);
383 if (element_no
< regs_content
.size ())
384 display_reg_element_at_line (element_no
, line_no
);
391 return (-1); /* Nothing was displayed. */
395 /* This function check all displayed registers for changes in values,
396 given a particular frame. If the values have changed, they are
397 updated with the new value and highlighted. */
399 tui_check_register_values (struct frame_info
*frame
)
401 if (TUI_DATA_WIN
!= NULL
402 && TUI_DATA_WIN
->is_visible
)
404 if (TUI_DATA_WIN
->regs_content
.empty ()
405 && TUI_DATA_WIN
->display_regs
)
406 tui_show_registers (TUI_DATA_WIN
->current_group
);
409 for (auto &&data_item_win_ptr
: TUI_DATA_WIN
->regs_content
)
413 was_hilighted
= data_item_win_ptr
->highlight
;
415 tui_get_register (frame
, data_item_win_ptr
.get (),
416 data_item_win_ptr
->item_no
,
417 &data_item_win_ptr
->highlight
);
419 if (data_item_win_ptr
->highlight
|| was_hilighted
)
420 tui_display_register (data_item_win_ptr
.get ());
426 /* Display a register in a window. If hilite is TRUE, then the value
427 will be displayed in reverse video. */
429 tui_display_register (struct tui_data_item_window
*data
)
431 if (data
->handle
!= NULL
)
436 /* We ignore the return value, casting it to void in order to avoid
437 a compiler warning. The warning itself was introduced by a patch
438 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
439 to code that causes the compiler to generate an unused-value
441 (void) wstandout (data
->handle
);
443 wmove (data
->handle
, 0, 0);
444 for (i
= 1; i
< data
->width
; i
++)
445 waddch (data
->handle
, ' ');
446 wmove (data
->handle
, 0, 0);
448 waddstr (data
->handle
, data
->content
);
451 /* We ignore the return value, casting it to void in order to avoid
452 a compiler warning. The warning itself was introduced by a patch
453 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
454 to code that causes the compiler to generate an unused-value
456 (void) wstandend (data
->handle
);
457 data
->refresh_window ();
461 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
462 around behaviour. Returns the next register group, or NULL if the
463 register window is not currently being displayed. */
465 static struct reggroup
*
466 tui_reg_next (struct gdbarch
*gdbarch
)
468 struct reggroup
*group
= NULL
;
470 if (TUI_DATA_WIN
!= NULL
)
472 group
= TUI_DATA_WIN
->current_group
;
473 group
= reggroup_next (gdbarch
, group
);
475 group
= reggroup_next (gdbarch
, NULL
);
480 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
481 around behaviour. Returns the previous register group, or NULL if the
482 register window is not currently being displayed. */
484 static struct reggroup
*
485 tui_reg_prev (struct gdbarch
*gdbarch
)
487 struct reggroup
*group
= NULL
;
489 if (TUI_DATA_WIN
!= NULL
)
491 group
= TUI_DATA_WIN
->current_group
;
492 group
= reggroup_prev (gdbarch
, group
);
494 group
= reggroup_prev (gdbarch
, NULL
);
499 /* Implement the 'tui reg' command. Changes the register group displayed
500 in the tui register window. Displays the tui register window if it is
501 not already on display. */
504 tui_reg_command (const char *args
, int from_tty
)
506 struct gdbarch
*gdbarch
= get_current_arch ();
510 struct reggroup
*group
, *match
= NULL
;
511 size_t len
= strlen (args
);
513 /* Make sure the curses mode is enabled. */
516 /* Make sure the register window is visible. If not, select an
517 appropriate layout. We need to do this before trying to run the
518 'next' or 'prev' commands. */
519 if (TUI_DATA_WIN
== NULL
|| !TUI_DATA_WIN
->is_visible
)
520 tui_set_layout_by_name (DATA_NAME
);
522 if (strncmp (args
, "next", len
) == 0)
523 match
= tui_reg_next (gdbarch
);
524 else if (strncmp (args
, "prev", len
) == 0)
525 match
= tui_reg_prev (gdbarch
);
527 /* This loop matches on the initial part of a register group
528 name. If this initial part in ARGS matches only one register
529 group then the switch is made. */
530 for (group
= reggroup_next (gdbarch
, NULL
);
532 group
= reggroup_next (gdbarch
, group
))
534 if (strncmp (reggroup_name (group
), args
, len
) == 0)
537 error (_("ambiguous register group name '%s'"), args
);
543 error (_("unknown register group '%s'"), args
);
545 tui_show_registers (match
);
549 struct reggroup
*group
;
552 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
553 "either a register group,\nor one of 'next' "
554 "or 'prev'. Known register groups are:\n"));
556 for (first
= 1, group
= reggroup_next (gdbarch
, NULL
);
558 first
= 0, group
= reggroup_next (gdbarch
, group
))
561 printf_unfiltered (", ");
562 printf_unfiltered ("%s", reggroup_name (group
));
565 printf_unfiltered ("\n");
569 /* Complete names of register groups, and add the special "prev" and "next"
573 tui_reggroup_completer (struct cmd_list_element
*ignore
,
574 completion_tracker
&tracker
,
575 const char *text
, const char *word
)
577 static const char *extra
[] = { "next", "prev", NULL
};
578 size_t len
= strlen (word
);
581 reggroup_completer (ignore
, tracker
, text
, word
);
583 /* XXXX use complete_on_enum instead? */
584 for (tmp
= extra
; *tmp
!= NULL
; ++tmp
)
586 if (strncmp (word
, *tmp
, len
) == 0)
587 tracker
.add_completion (make_unique_xstrdup (*tmp
));
592 _initialize_tui_regs (void)
594 struct cmd_list_element
**tuicmd
, *cmd
;
596 tuicmd
= tui_get_cmd_list ();
598 cmd
= add_cmd ("reg", class_tui
, tui_reg_command
, _("\
599 TUI command to control the register window."), tuicmd
);
600 set_cmd_completer (cmd
, tui_reggroup_completer
);
604 /*****************************************
605 ** STATIC LOCAL FUNCTIONS **
606 ******************************************/
608 /* Get the register from the frame and return a printable
609 representation of it. */
612 tui_register_format (struct frame_info
*frame
, int regnum
)
614 struct gdbarch
*gdbarch
= get_frame_arch (frame
);
618 scoped_restore save_pagination
619 = make_scoped_restore (&pagination_enabled
, 0);
620 scoped_restore save_stdout
621 = make_scoped_restore (&gdb_stdout
, &stream
);
623 gdbarch_print_registers_info (gdbarch
, &stream
, frame
, regnum
, 1);
625 /* Remove the possible \n. */
626 std::string
&str
= stream
.string ();
627 if (!str
.empty () && str
.back () == '\n')
628 str
.resize (str
.size () - 1);
630 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
631 return tui_expand_tabs (str
.c_str (), 0);
634 /* Get the register value from the given frame and format it for the
635 display. When changep is set, check if the new register value has
636 changed with respect to the previous call. */
637 static enum tui_status
638 tui_get_register (struct frame_info
*frame
,
639 struct tui_data_item_window
*data
,
640 int regnum
, bool *changedp
)
642 enum tui_status ret
= TUI_FAILURE
;
646 if (target_has_registers
)
648 char *prev_content
= data
->content
;
650 data
->content
= tui_register_format (frame
, regnum
);
653 && strcmp (prev_content
, data
->content
) != 0)
656 xfree (prev_content
);