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 ******************************************/
66 /* Answer the number of the last line in the regs display. If there
67 are no registers (-1) is returned. */
69 tui_last_regs_line_no (void)
73 if (!TUI_DATA_WIN->regs_content.empty ())
75 num_lines = (TUI_DATA_WIN->regs_content.size ()
76 / TUI_DATA_WIN->regs_column_count);
77 if (TUI_DATA_WIN->regs_content.size () % TUI_DATA_WIN->regs_column_count)
84 /* Answer the line number that the register element at element_no is
85 on. If element_no is greater than the number of register elements
86 there are, -1 is returned. */
88 tui_line_from_reg_element_no (int element_no)
90 if (element_no < TUI_DATA_WIN->regs_content.size ())
97 if (element_no < TUI_DATA_WIN->regs_column_count * i)
110 /* Answer the index of the first element in line_no. If line_no is
111 past the register area (-1) is returned. */
113 tui_first_reg_element_no_inline (int line_no)
115 if ((line_no * TUI_DATA_WIN->regs_column_count)
116 <= TUI_DATA_WIN->regs_content.size ())
117 return (((line_no + 1) * TUI_DATA_WIN->regs_column_count)
118 - TUI_DATA_WIN->regs_column_count);
124 /* Show the registers of the given group in the data window
125 and refresh the window. */
127 tui_show_registers (struct reggroup *group)
129 enum tui_status ret = TUI_FAILURE;
131 /* Make sure the curses mode is enabled. */
134 /* Make sure the register window is visible. If not, select an
135 appropriate layout. */
136 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible)
137 tui_set_layout_by_name (DATA_NAME);
140 group = general_reggroup;
142 /* Say that registers should be displayed, even if there is a
144 TUI_DATA_WIN->display_regs = true;
146 if (target_has_registers && target_has_stack && target_has_memory)
148 tui_show_register_group (group, get_selected_frame (NULL),
149 group == TUI_DATA_WIN->current_group);
152 if (ret == TUI_FAILURE)
154 TUI_DATA_WIN->current_group = 0;
155 tui_erase_data_content (NO_REGS_STRING);
159 /* Clear all notation of changed values. */
160 for (auto &&data_item_win : TUI_DATA_WIN->regs_content)
162 if (data_item_win != nullptr)
163 data_item_win->highlight = false;
165 TUI_DATA_WIN->current_group = group;
166 tui_display_all_data ();
171 /* Set the data window to display the registers of the register group
172 using the given frame. Values are refreshed only when
173 refresh_values_only is TRUE. */
176 tui_show_register_group (struct reggroup *group,
177 struct frame_info *frame,
178 int refresh_values_only)
180 struct gdbarch *gdbarch = get_frame_arch (frame);
185 /* Make a new title showing which group we display. */
186 snprintf (title, sizeof (title) - 1, "Register group: %s",
187 reggroup_name (group));
188 xfree (TUI_DATA_WIN->title);
189 TUI_DATA_WIN->title = xstrdup (title);
191 /* See how many registers must be displayed. */
193 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
197 /* Must be in the group. */
198 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
201 /* If the register name is empty, it is undefined for this
202 processor, so don't display anything. */
203 name = gdbarch_register_name (gdbarch, regnum);
204 if (name == 0 || *name == '\0')
210 if (!refresh_values_only)
211 TUI_DATA_WIN->regs_content.clear ();
213 if (nr_regs < TUI_DATA_WIN->regs_content.size ())
214 TUI_DATA_WIN->regs_content.resize (nr_regs);
217 for (int i = TUI_DATA_WIN->regs_content.size (); i < nr_regs; ++i)
218 TUI_DATA_WIN->regs_content.emplace_back (new tui_data_item_window ());
221 /* Now set the register names and values. */
223 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
225 struct tui_data_item_window *data_item_win;
228 /* Must be in the group. */
229 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
232 /* If the register name is empty, it is undefined for this
233 processor, so don't display anything. */
234 name = gdbarch_register_name (gdbarch, regnum);
235 if (name == 0 || *name == '\0')
238 data_item_win = TUI_DATA_WIN->regs_content[pos].get ();
241 if (!refresh_values_only)
243 data_item_win->item_no = regnum;
244 data_item_win->name = name;
245 data_item_win->highlight = false;
247 tui_get_register (frame, data_item_win, regnum, 0);
253 /* Function to display the registers in the content from
254 'start_element_no' until the end of the register content or the end
255 of the display height. No checking for displaying past the end of
256 the registers is done here. */
258 tui_display_registers_from (int start_element_no)
260 if (!TUI_DATA_WIN->regs_content.empty ())
262 int j, item_win_width, cur_y;
265 for (auto &&data_item_win : TUI_DATA_WIN->regs_content)
271 p = data_item_win->content;
276 len = 8 * ((len / 8) + 1);
284 item_win_width = max_len + 1;
285 int i = start_element_no;
287 TUI_DATA_WIN->regs_column_count =
288 (TUI_DATA_WIN->width - 2) / item_win_width;
289 if (TUI_DATA_WIN->regs_column_count == 0)
290 TUI_DATA_WIN->regs_column_count = 1;
292 (TUI_DATA_WIN->width - 2) / TUI_DATA_WIN->regs_column_count;
294 /* Now create each data "sub" window, and write the display into
297 while (i < TUI_DATA_WIN->regs_content.size ()
298 && cur_y <= TUI_DATA_WIN->viewport_height)
301 j < TUI_DATA_WIN->regs_column_count
302 && i < TUI_DATA_WIN->regs_content.size ();
305 struct tui_data_item_window *data_item_win;
307 /* Create the window if necessary. */
308 data_item_win = TUI_DATA_WIN->regs_content[i].get ();
309 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))
315 tui_delete_win (data_item_win->handle);
316 data_item_win->handle = 0;
319 if (data_item_win->handle == NULL)
321 data_item_win->height = 1;
322 data_item_win->width = item_win_width;
323 data_item_win->origin.x = (item_win_width * j) + 1;
324 data_item_win->origin.y = cur_y;
325 tui_make_window (data_item_win, DONT_BOX_WINDOW);
326 scrollok (data_item_win->handle, FALSE);
328 touchwin (data_item_win->handle);
330 /* Get the printable representation of the register
332 tui_display_register (data_item_win);
333 i++; /* Next register. */
335 cur_y++; /* Next row. */
341 /* Function to display the registers in the content from
342 'start_element_no' on 'start_line_no' until the end of the register
343 content or the end of the display height. This function checks
344 that we won't display off the end of the register display. */
346 tui_display_reg_element_at_line (int start_element_no,
349 if (!TUI_DATA_WIN->regs_content.empty ())
351 int element_no = start_element_no;
353 if (start_element_no != 0 && start_line_no != 0)
355 int last_line_no, first_line_on_last_page;
357 last_line_no = tui_last_regs_line_no ();
358 first_line_on_last_page
359 = last_line_no - (TUI_DATA_WIN->height - 2);
360 if (first_line_on_last_page < 0)
361 first_line_on_last_page = 0;
363 /* If the element_no causes us to scroll past the end of the
364 registers, adjust what element to really start the
366 if (start_line_no > first_line_on_last_page)
368 = tui_first_reg_element_no_inline (first_line_on_last_page);
370 tui_display_registers_from (element_no);
376 /* Function to display the registers starting at line line_no in the
377 data window. Answers the line number that the display actually
378 started from. If nothing is displayed (-1) is returned. */
380 tui_display_registers_from_line (int line_no,
383 if (!TUI_DATA_WIN->regs_content.empty ())
385 int line, element_no;
389 else if (force_display)
390 { /* If we must display regs (force_display is true), then
391 make sure that we don't display off the end of the
393 if (line_no >= tui_last_regs_line_no ())
395 if ((line = tui_line_from_reg_element_no (
396 TUI_DATA_WIN->regs_content.size () - 1)) < 0)
405 element_no = tui_first_reg_element_no_inline (line);
406 if (element_no < TUI_DATA_WIN->regs_content.size ())
407 tui_display_reg_element_at_line (element_no, line);
414 return (-1); /* Nothing was displayed. */
418 /* This function check all displayed registers for changes in values,
419 given a particular frame. If the values have changed, they are
420 updated with the new value and highlighted. */
422 tui_check_register_values (struct frame_info *frame)
424 if (TUI_DATA_WIN != NULL
425 && TUI_DATA_WIN->is_visible)
427 if (TUI_DATA_WIN->regs_content.empty ()
428 && TUI_DATA_WIN->display_regs)
429 tui_show_registers (TUI_DATA_WIN->current_group);
432 for (auto &&data_item_win_ptr : TUI_DATA_WIN->regs_content)
436 was_hilighted = data_item_win_ptr->highlight;
438 tui_get_register (frame, data_item_win_ptr.get (),
439 data_item_win_ptr->item_no,
440 &data_item_win_ptr->highlight);
442 if (data_item_win_ptr->highlight || was_hilighted)
443 tui_display_register (data_item_win_ptr.get ());
449 /* Display a register in a window. If hilite is TRUE, then the value
450 will be displayed in reverse video. */
452 tui_display_register (struct tui_data_item_window *data)
454 if (data->handle != NULL)
459 /* We ignore the return value, casting it to void in order to avoid
460 a compiler warning. The warning itself was introduced by a patch
461 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
462 to code that causes the compiler to generate an unused-value
464 (void) wstandout (data->handle);
466 wmove (data->handle, 0, 0);
467 for (i = 1; i < data->width; i++)
468 waddch (data->handle, ' ');
469 wmove (data->handle, 0, 0);
471 waddstr (data->handle, data->content);
474 /* We ignore the return value, casting it to void in order to avoid
475 a compiler warning. The warning itself was introduced by a patch
476 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
477 to code that causes the compiler to generate an unused-value
479 (void) wstandend (data->handle);
480 data->refresh_window ();
484 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
485 around behaviour. Returns the next register group, or NULL if the
486 register window is not currently being displayed. */
488 static struct reggroup *
489 tui_reg_next (struct gdbarch *gdbarch)
491 struct reggroup *group = NULL;
493 if (TUI_DATA_WIN != NULL)
495 group = TUI_DATA_WIN->current_group;
496 group = reggroup_next (gdbarch, group);
498 group = reggroup_next (gdbarch, NULL);
503 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
504 around behaviour. Returns the previous register group, or NULL if the
505 register window is not currently being displayed. */
507 static struct reggroup *
508 tui_reg_prev (struct gdbarch *gdbarch)
510 struct reggroup *group = NULL;
512 if (TUI_DATA_WIN != NULL)
514 group = TUI_DATA_WIN->current_group;
515 group = reggroup_prev (gdbarch, group);
517 group = reggroup_prev (gdbarch, NULL);
522 /* Implement the 'tui reg' command. Changes the register group displayed
523 in the tui register window. Displays the tui register window if it is
524 not already on display. */
527 tui_reg_command (const char *args, int from_tty)
529 struct gdbarch *gdbarch = get_current_arch ();
533 struct reggroup *group, *match = NULL;
534 size_t len = strlen (args);
536 /* Make sure the curses mode is enabled. */
539 /* Make sure the register window is visible. If not, select an
540 appropriate layout. We need to do this before trying to run the
541 'next' or 'prev' commands. */
542 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible)
543 tui_set_layout_by_name (DATA_NAME);
545 if (strncmp (args, "next", len) == 0)
546 match = tui_reg_next (gdbarch);
547 else if (strncmp (args, "prev", len) == 0)
548 match = tui_reg_prev (gdbarch);
550 /* This loop matches on the initial part of a register group
551 name. If this initial part in ARGS matches only one register
552 group then the switch is made. */
553 for (group = reggroup_next (gdbarch, NULL);
555 group = reggroup_next (gdbarch, group))
557 if (strncmp (reggroup_name (group), args, len) == 0)
560 error (_("ambiguous register group name '%s'"), args);
566 error (_("unknown register group '%s'"), args);
568 tui_show_registers (match);
572 struct reggroup *group;
575 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
576 "either a register group,\nor one of 'next' "
577 "or 'prev'. Known register groups are:\n"));
579 for (first = 1, group = reggroup_next (gdbarch, NULL);
581 first = 0, group = reggroup_next (gdbarch, group))
584 printf_unfiltered (", ");
585 printf_unfiltered ("%s", reggroup_name (group));
588 printf_unfiltered ("\n");
592 /* Complete names of register groups, and add the special "prev" and "next"
596 tui_reggroup_completer (struct cmd_list_element *ignore,
597 completion_tracker &tracker,
598 const char *text, const char *word)
600 static const char *extra[] = { "next", "prev", NULL };
601 size_t len = strlen (word);
604 reggroup_completer (ignore, tracker, text, word);
606 /* XXXX use complete_on_enum instead? */
607 for (tmp = extra; *tmp != NULL; ++tmp)
609 if (strncmp (word, *tmp, len) == 0)
610 tracker.add_completion (make_unique_xstrdup (*tmp));
615 _initialize_tui_regs (void)
617 struct cmd_list_element **tuicmd, *cmd;
619 tuicmd = tui_get_cmd_list ();
621 cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
622 TUI command to control the register window."), tuicmd);
623 set_cmd_completer (cmd, tui_reggroup_completer);
627 /*****************************************
628 ** STATIC LOCAL FUNCTIONS **
629 ******************************************/
631 /* Get the register from the frame and return a printable
632 representation of it. */
635 tui_register_format (struct frame_info *frame, int regnum)
637 struct gdbarch *gdbarch = get_frame_arch (frame);
641 scoped_restore save_pagination
642 = make_scoped_restore (&pagination_enabled, 0);
643 scoped_restore save_stdout
644 = make_scoped_restore (&gdb_stdout, &stream);
646 gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
648 /* Remove the possible \n. */
649 std::string &str = stream.string ();
650 if (!str.empty () && str.back () == '\n')
651 str.resize (str.size () - 1);
653 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
654 return tui_expand_tabs (str.c_str (), 0);
657 /* Get the register value from the given frame and format it for the
658 display. When changep is set, check if the new register value has
659 changed with respect to the previous call. */
660 static enum tui_status
661 tui_get_register (struct frame_info *frame,
662 struct tui_data_item_window *data,
663 int regnum, bool *changedp)
665 enum tui_status ret = TUI_FAILURE;
669 if (target_has_registers)
671 char *prev_content = data->content;
673 data->content = tui_register_format (frame, regnum);
676 && strcmp (prev_content, data->content) != 0)
679 xfree (prev_content);