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