36973ff51aeb0630c626080f6a66d415a9919e5e
[deliverable/binutils-gdb.git] / gdb / tui / tui-regs.c
1 /* TUI display registers in window.
2
3 Copyright (C) 1998-2019 Free Software Foundation, Inc.
4
5 Contributed by Hewlett-Packard Company.
6
7 This file is part of GDB.
8
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.
13
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.
18
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/>. */
21
22 #include "defs.h"
23 #include "arch-utils.h"
24 #include "tui/tui.h"
25 #include "tui/tui-data.h"
26 #include "symtab.h"
27 #include "gdbtypes.h"
28 #include "gdbcmd.h"
29 #include "frame.h"
30 #include "regcache.h"
31 #include "inferior.h"
32 #include "target.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"
40 #include "valprint.h"
41 #include "completer.h"
42
43 #include "gdb_curses.h"
44
45 static void tui_display_register (struct tui_data_item_window *data);
46
47 static void tui_show_register_group (tui_data_window *win_info,
48 struct reggroup *group,
49 struct frame_info *frame,
50 int refresh_values_only);
51
52 static void tui_get_register (struct frame_info *frame,
53 struct tui_data_item_window *data,
54 int regnum, bool *changedp);
55
56
57 /* See tui-regs.h. */
58
59 tui_data_item_window::~tui_data_item_window ()
60 {
61 xfree (value);
62 xfree (content);
63 }
64
65 /* See tui-regs.h. */
66
67 int
68 tui_data_window::last_regs_line_no () const
69 {
70 int num_lines = (-1);
71
72 if (!regs_content.empty ())
73 {
74 num_lines = regs_content.size () / regs_column_count;
75 if (regs_content.size () % regs_column_count)
76 num_lines++;
77 }
78 return num_lines;
79 }
80
81 /* See tui-regs.h. */
82
83 int
84 tui_data_window::line_from_reg_element_no (int element_no) const
85 {
86 if (element_no < regs_content.size ())
87 {
88 int i, line = (-1);
89
90 i = 1;
91 while (line == (-1))
92 {
93 if (element_no < regs_column_count * i)
94 line = i - 1;
95 else
96 i++;
97 }
98
99 return line;
100 }
101 else
102 return (-1);
103 }
104
105 /* See tui-regs.h. */
106
107 int
108 tui_data_window::first_reg_element_no_inline (int line_no) const
109 {
110 if (line_no * regs_column_count <= regs_content.size ())
111 return ((line_no + 1) * regs_column_count) - regs_column_count;
112 else
113 return (-1);
114 }
115
116 /* A helper function to display the register window in the appropriate
117 way. */
118
119 static void
120 tui_reg_layout ()
121 {
122 enum tui_layout_type cur_layout = tui_current_layout ();
123 enum tui_layout_type new_layout;
124 if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND)
125 new_layout = SRC_DATA_COMMAND;
126 else
127 new_layout = DISASSEM_DATA_COMMAND;
128 tui_set_layout (new_layout);
129 }
130
131 /* Show the registers of the given group in the data window
132 and refresh the window. */
133 void
134 tui_show_registers (struct reggroup *group)
135 {
136 /* Make sure the curses mode is enabled. */
137 tui_enable ();
138
139 /* Make sure the register window is visible. If not, select an
140 appropriate layout. */
141 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible ())
142 tui_reg_layout ();
143
144 if (group == 0)
145 group = general_reggroup;
146
147 /* Say that registers should be displayed, even if there is a
148 problem. */
149 TUI_DATA_WIN->display_regs = true;
150
151 if (target_has_registers && target_has_stack && target_has_memory)
152 {
153 tui_show_register_group (TUI_DATA_WIN, group, get_selected_frame (NULL),
154 group == TUI_DATA_WIN->current_group);
155
156 /* Clear all notation of changed values. */
157 for (auto &&data_item_win : TUI_DATA_WIN->regs_content)
158 {
159 if (data_item_win != nullptr)
160 data_item_win->highlight = false;
161 }
162 TUI_DATA_WIN->current_group = group;
163 TUI_DATA_WIN->display_all_data ();
164 }
165 else
166 {
167 TUI_DATA_WIN->current_group = 0;
168 TUI_DATA_WIN->erase_data_content (NO_REGS_STRING);
169 }
170 }
171
172
173 /* Set the data window to display the registers of the register group
174 using the given frame. Values are refreshed only when
175 refresh_values_only is TRUE. */
176
177 static void
178 tui_show_register_group (tui_data_window *win_info,
179 struct reggroup *group,
180 struct frame_info *frame,
181 int refresh_values_only)
182 {
183 struct gdbarch *gdbarch = get_frame_arch (frame);
184 int nr_regs;
185 int regnum, pos;
186 char title[80];
187
188 /* Make a new title showing which group we display. */
189 snprintf (title, sizeof (title) - 1, "Register group: %s",
190 reggroup_name (group));
191 xfree (win_info->title);
192 win_info->title = xstrdup (title);
193
194 /* See how many registers must be displayed. */
195 nr_regs = 0;
196 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
197 {
198 const char *name;
199
200 /* Must be in the group. */
201 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
202 continue;
203
204 /* If the register name is empty, it is undefined for this
205 processor, so don't display anything. */
206 name = gdbarch_register_name (gdbarch, regnum);
207 if (name == 0 || *name == '\0')
208 continue;
209
210 nr_regs++;
211 }
212
213 if (!refresh_values_only)
214 win_info->regs_content.clear ();
215
216 if (nr_regs < win_info->regs_content.size ())
217 win_info->regs_content.resize (nr_regs);
218 else
219 {
220 for (int i = win_info->regs_content.size (); i < nr_regs; ++i)
221 win_info->regs_content.emplace_back (new tui_data_item_window ());
222 }
223
224 /* Now set the register names and values. */
225 pos = 0;
226 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
227 {
228 struct tui_data_item_window *data_item_win;
229 const char *name;
230
231 /* Must be in the group. */
232 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
233 continue;
234
235 /* If the register name is empty, it is undefined for this
236 processor, so don't display anything. */
237 name = gdbarch_register_name (gdbarch, regnum);
238 if (name == 0 || *name == '\0')
239 continue;
240
241 data_item_win = win_info->regs_content[pos].get ();
242 if (data_item_win)
243 {
244 if (!refresh_values_only)
245 {
246 data_item_win->item_no = regnum;
247 data_item_win->name = name;
248 data_item_win->highlight = false;
249 }
250 tui_get_register (frame, data_item_win, regnum, 0);
251 }
252 pos++;
253 }
254 }
255
256 /* See tui-regs.h. */
257
258 void
259 tui_data_window::display_registers_from (int start_element_no)
260 {
261 if (!regs_content.empty ())
262 {
263 int j, item_win_width, cur_y;
264
265 int max_len = 0;
266 for (auto &&data_item_win : regs_content)
267 {
268 char *p;
269 int len;
270
271 len = 0;
272 p = data_item_win->content;
273 if (p != 0)
274 while (*p)
275 {
276 if (*p++ == '\t')
277 len = 8 * ((len / 8) + 1);
278 else
279 len++;
280 }
281
282 if (len > max_len)
283 max_len = len;
284 }
285 item_win_width = max_len + 1;
286 int i = start_element_no;
287
288 regs_column_count = (width - 2) / item_win_width;
289 if (regs_column_count == 0)
290 regs_column_count = 1;
291 item_win_width = (width - 2) / regs_column_count;
292
293 /* Now create each data "sub" window, and write the display into
294 it. */
295 cur_y = 1;
296 while (i < regs_content.size ()
297 && cur_y <= viewport_height)
298 {
299 for (j = 0;
300 j < regs_column_count && i < regs_content.size ();
301 j++)
302 {
303 struct tui_data_item_window *data_item_win;
304
305 /* Create the window if necessary. */
306 data_item_win = regs_content[i].get ();
307 if (data_item_win->handle != NULL
308 && (data_item_win->height != 1
309 || data_item_win->width != item_win_width
310 || data_item_win->origin.x != (item_win_width * j) + 1
311 || data_item_win->origin.y != cur_y))
312 {
313 tui_delete_win (data_item_win->handle);
314 data_item_win->handle = 0;
315 }
316
317 if (data_item_win->handle == NULL)
318 {
319 data_item_win->height = 1;
320 data_item_win->width = item_win_width;
321 data_item_win->origin.x = (item_win_width * j) + 1;
322 data_item_win->origin.y = cur_y;
323 tui_make_window (data_item_win);
324 scrollok (data_item_win->handle, FALSE);
325 }
326 touchwin (data_item_win->handle);
327
328 /* Get the printable representation of the register
329 and display it. */
330 tui_display_register (data_item_win);
331 i++; /* Next register. */
332 }
333 cur_y++; /* Next row. */
334 }
335 }
336 }
337
338 /* See tui-regs.h. */
339
340 void
341 tui_data_window::display_reg_element_at_line (int start_element_no,
342 int start_line_no)
343 {
344 if (!regs_content.empty ())
345 {
346 int element_no = start_element_no;
347
348 if (start_element_no != 0 && start_line_no != 0)
349 {
350 int last_line_no, first_line_on_last_page;
351
352 last_line_no = last_regs_line_no ();
353 first_line_on_last_page = last_line_no - (height - 2);
354 if (first_line_on_last_page < 0)
355 first_line_on_last_page = 0;
356
357 /* If the element_no causes us to scroll past the end of the
358 registers, adjust what element to really start the
359 display at. */
360 if (start_line_no > first_line_on_last_page)
361 element_no = first_reg_element_no_inline (first_line_on_last_page);
362 }
363 display_registers_from (element_no);
364 }
365 }
366
367 /* See tui-regs.h. */
368
369 int
370 tui_data_window::display_registers_from_line (int line_no)
371 {
372 check_and_display_highlight_if_needed ();
373 if (!regs_content.empty ())
374 {
375 int element_no;
376
377 if (line_no < 0)
378 line_no = 0;
379 else
380 {
381 /* Make sure that we don't display off the end of the
382 registers. */
383 if (line_no >= last_regs_line_no ())
384 {
385 line_no = line_from_reg_element_no (regs_content.size () - 1);
386 if (line_no < 0)
387 line_no = 0;
388 }
389 }
390
391 element_no = first_reg_element_no_inline (line_no);
392 if (element_no < regs_content.size ())
393 display_reg_element_at_line (element_no, line_no);
394 else
395 line_no = (-1);
396
397 return line_no;
398 }
399
400 return (-1); /* Nothing was displayed. */
401 }
402
403
404 /* Answer the index first element displayed. If none are displayed,
405 then return (-1). */
406 int
407 tui_data_window::first_data_item_displayed ()
408 {
409 for (int i = 0; i < regs_content.size (); i++)
410 {
411 struct tui_gen_win_info *data_item_win;
412
413 data_item_win = regs_content[i].get ();
414 if (data_item_win->is_visible ())
415 return i;
416 }
417
418 return -1;
419 }
420
421 /* See tui-regs.h. */
422
423 void
424 tui_data_window::delete_data_content_windows ()
425 {
426 for (auto &&win : regs_content)
427 {
428 tui_delete_win (win->handle);
429 win->handle = NULL;
430 }
431 }
432
433
434 void
435 tui_data_window::erase_data_content (const char *prompt)
436 {
437 werase (handle);
438 check_and_display_highlight_if_needed ();
439 if (prompt != NULL)
440 {
441 int half_width = (width - 2) / 2;
442 int x_pos;
443
444 if (strlen (prompt) >= half_width)
445 x_pos = 1;
446 else
447 x_pos = half_width - strlen (prompt);
448 mvwaddstr (handle, (height / 2), x_pos, (char *) prompt);
449 }
450 wrefresh (handle);
451 }
452
453 /* See tui-regs.h. */
454
455 void
456 tui_data_window::display_all_data ()
457 {
458 if (regs_content.empty ())
459 erase_data_content (NO_DATA_STRING);
460 else
461 {
462 erase_data_content (NULL);
463 delete_data_content_windows ();
464 check_and_display_highlight_if_needed ();
465 display_registers_from (0);
466 }
467 }
468
469
470 /* Function to redisplay the contents of the data window. */
471 void
472 tui_data_window::refresh_all ()
473 {
474 erase_data_content (NULL);
475 if (!regs_content.empty ())
476 {
477 int first_element = first_data_item_displayed ();
478
479 if (first_element >= 0) /* Re-use existing windows. */
480 {
481 int first_line = (-1);
482
483 if (first_element < regs_content.size ())
484 first_line = line_from_reg_element_no (first_element);
485
486 if (first_line >= 0)
487 {
488 erase_data_content (NULL);
489 display_registers_from_line (first_line);
490 }
491 }
492 }
493 }
494
495
496 /* Scroll the data window vertically forward or backward. */
497 void
498 tui_data_window::do_scroll_vertical (int num_to_scroll)
499 {
500 int first_element_no;
501 int first_line = (-1);
502
503 first_element_no = first_data_item_displayed ();
504 if (first_element_no < regs_content.size ())
505 first_line = line_from_reg_element_no (first_element_no);
506 else
507 { /* Calculate the first line from the element number which is in
508 the general data content. */
509 }
510
511 if (first_line >= 0)
512 {
513 first_line += num_to_scroll;
514 erase_data_content (NULL);
515 delete_data_content_windows ();
516 display_registers_from_line (first_line);
517 }
518 }
519
520 /* See tui-regs.h. */
521
522 void
523 tui_data_window::rerender ()
524 {
525 /* Delete all data item windows. */
526 for (auto &&win : regs_content)
527 {
528 tui_delete_win (win->handle);
529 win->handle = NULL;
530 }
531 display_all_data ();
532 }
533
534 /* See tui-regs.h. */
535
536 void
537 tui_data_window::refresh_window ()
538 {
539 tui_gen_win_info::refresh_window ();
540 for (auto &&win : regs_content)
541 {
542 if (win != NULL)
543 win->refresh_window ();
544 }
545 }
546
547 /* This function check all displayed registers for changes in values,
548 given a particular frame. If the values have changed, they are
549 updated with the new value and highlighted. */
550 void
551 tui_check_register_values (struct frame_info *frame)
552 {
553 if (TUI_DATA_WIN != NULL
554 && TUI_DATA_WIN->is_visible ())
555 {
556 if (TUI_DATA_WIN->regs_content.empty ()
557 && TUI_DATA_WIN->display_regs)
558 tui_show_registers (TUI_DATA_WIN->current_group);
559 else
560 {
561 for (auto &&data_item_win_ptr : TUI_DATA_WIN->regs_content)
562 {
563 int was_hilighted;
564
565 was_hilighted = data_item_win_ptr->highlight;
566
567 tui_get_register (frame, data_item_win_ptr.get (),
568 data_item_win_ptr->item_no,
569 &data_item_win_ptr->highlight);
570
571 if (data_item_win_ptr->highlight || was_hilighted)
572 tui_display_register (data_item_win_ptr.get ());
573 }
574 }
575 }
576 }
577
578 /* Display a register in a window. If hilite is TRUE, then the value
579 will be displayed in reverse video. */
580 static void
581 tui_display_register (struct tui_data_item_window *data)
582 {
583 if (data->handle != NULL)
584 {
585 int i;
586
587 if (data->highlight)
588 /* We ignore the return value, casting it to void in order to avoid
589 a compiler warning. The warning itself was introduced by a patch
590 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
591 to code that causes the compiler to generate an unused-value
592 warning. */
593 (void) wstandout (data->handle);
594
595 wmove (data->handle, 0, 0);
596 for (i = 1; i < data->width; i++)
597 waddch (data->handle, ' ');
598 wmove (data->handle, 0, 0);
599 if (data->content)
600 waddstr (data->handle, data->content);
601
602 if (data->highlight)
603 /* We ignore the return value, casting it to void in order to avoid
604 a compiler warning. The warning itself was introduced by a patch
605 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
606 to code that causes the compiler to generate an unused-value
607 warning. */
608 (void) wstandend (data->handle);
609 data->refresh_window ();
610 }
611 }
612
613 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
614 around behaviour. Returns the next register group, or NULL if the
615 register window is not currently being displayed. */
616
617 static struct reggroup *
618 tui_reg_next (struct reggroup *current_group, struct gdbarch *gdbarch)
619 {
620 struct reggroup *group = NULL;
621
622 if (current_group != NULL)
623 {
624 group = reggroup_next (gdbarch, current_group);
625 if (group == NULL)
626 group = reggroup_next (gdbarch, NULL);
627 }
628 return group;
629 }
630
631 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
632 around behaviour. Returns the previous register group, or NULL if the
633 register window is not currently being displayed. */
634
635 static struct reggroup *
636 tui_reg_prev (struct reggroup *current_group, struct gdbarch *gdbarch)
637 {
638 struct reggroup *group = NULL;
639
640 if (current_group != NULL)
641 {
642 group = reggroup_prev (gdbarch, current_group);
643 if (group == NULL)
644 group = reggroup_prev (gdbarch, NULL);
645 }
646 return group;
647 }
648
649 /* Implement the 'tui reg' command. Changes the register group displayed
650 in the tui register window. Displays the tui register window if it is
651 not already on display. */
652
653 static void
654 tui_reg_command (const char *args, int from_tty)
655 {
656 struct gdbarch *gdbarch = get_current_arch ();
657
658 if (args != NULL)
659 {
660 struct reggroup *group, *match = NULL;
661 size_t len = strlen (args);
662
663 /* Make sure the curses mode is enabled. */
664 tui_enable ();
665
666 /* Make sure the register window is visible. If not, select an
667 appropriate layout. We need to do this before trying to run the
668 'next' or 'prev' commands. */
669 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible ())
670 tui_reg_layout ();
671
672 struct reggroup *current_group = NULL;
673 if (TUI_DATA_WIN != NULL)
674 current_group = TUI_DATA_WIN->current_group;
675 if (strncmp (args, "next", len) == 0)
676 match = tui_reg_next (current_group, gdbarch);
677 else if (strncmp (args, "prev", len) == 0)
678 match = tui_reg_prev (current_group, gdbarch);
679
680 /* This loop matches on the initial part of a register group
681 name. If this initial part in ARGS matches only one register
682 group then the switch is made. */
683 for (group = reggroup_next (gdbarch, NULL);
684 group != NULL;
685 group = reggroup_next (gdbarch, group))
686 {
687 if (strncmp (reggroup_name (group), args, len) == 0)
688 {
689 if (match != NULL)
690 error (_("ambiguous register group name '%s'"), args);
691 match = group;
692 }
693 }
694
695 if (match == NULL)
696 error (_("unknown register group '%s'"), args);
697
698 tui_show_registers (match);
699 }
700 else
701 {
702 struct reggroup *group;
703 int first;
704
705 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
706 "either a register group,\nor one of 'next' "
707 "or 'prev'. Known register groups are:\n"));
708
709 for (first = 1, group = reggroup_next (gdbarch, NULL);
710 group != NULL;
711 first = 0, group = reggroup_next (gdbarch, group))
712 {
713 if (!first)
714 printf_unfiltered (", ");
715 printf_unfiltered ("%s", reggroup_name (group));
716 }
717
718 printf_unfiltered ("\n");
719 }
720 }
721
722 /* Complete names of register groups, and add the special "prev" and "next"
723 names. */
724
725 static void
726 tui_reggroup_completer (struct cmd_list_element *ignore,
727 completion_tracker &tracker,
728 const char *text, const char *word)
729 {
730 static const char *extra[] = { "next", "prev", NULL };
731 size_t len = strlen (word);
732 const char **tmp;
733
734 reggroup_completer (ignore, tracker, text, word);
735
736 /* XXXX use complete_on_enum instead? */
737 for (tmp = extra; *tmp != NULL; ++tmp)
738 {
739 if (strncmp (word, *tmp, len) == 0)
740 tracker.add_completion (make_unique_xstrdup (*tmp));
741 }
742 }
743
744 /* Get the register from the frame and return a printable
745 representation of it. */
746
747 static char *
748 tui_register_format (struct frame_info *frame, int regnum)
749 {
750 struct gdbarch *gdbarch = get_frame_arch (frame);
751
752 string_file stream;
753
754 scoped_restore save_pagination
755 = make_scoped_restore (&pagination_enabled, 0);
756 scoped_restore save_stdout
757 = make_scoped_restore (&gdb_stdout, &stream);
758
759 gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
760
761 /* Remove the possible \n. */
762 std::string &str = stream.string ();
763 if (!str.empty () && str.back () == '\n')
764 str.resize (str.size () - 1);
765
766 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
767 return tui_expand_tabs (str.c_str (), 0);
768 }
769
770 /* Get the register value from the given frame and format it for the
771 display. When changep is set, check if the new register value has
772 changed with respect to the previous call. */
773 static void
774 tui_get_register (struct frame_info *frame,
775 struct tui_data_item_window *data,
776 int regnum, bool *changedp)
777 {
778 if (changedp)
779 *changedp = false;
780 if (target_has_registers)
781 {
782 char *prev_content = data->content;
783
784 data->content = tui_register_format (frame, regnum);
785
786 if (changedp != NULL
787 && strcmp (prev_content, data->content) != 0)
788 *changedp = true;
789
790 xfree (prev_content);
791 }
792 }
793
794 void
795 _initialize_tui_regs (void)
796 {
797 struct cmd_list_element **tuicmd, *cmd;
798
799 tuicmd = tui_get_cmd_list ();
800
801 cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
802 TUI command to control the register window."), tuicmd);
803 set_cmd_completer (cmd, tui_reggroup_completer);
804 }
This page took 0.048808 seconds and 4 git commands to generate.