Simplify TUI boxing
[platform/upstream/binutils.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->handle != NULL && 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       win->is_visible = false;
431     }
432 }
433
434
435 void
436 tui_data_window::erase_data_content (const char *prompt)
437 {
438   werase (handle);
439   check_and_display_highlight_if_needed ();
440   if (prompt != NULL)
441     {
442       int half_width = (width - 2) / 2;
443       int x_pos;
444
445       if (strlen (prompt) >= half_width)
446         x_pos = 1;
447       else
448         x_pos = half_width - strlen (prompt);
449       mvwaddstr (handle, (height / 2), x_pos, (char *) prompt);
450     }
451   wrefresh (handle);
452 }
453
454 /* See tui-regs.h.  */
455
456 void
457 tui_data_window::display_all_data ()
458 {
459   if (regs_content.empty ())
460     erase_data_content (NO_DATA_STRING);
461   else
462     {
463       erase_data_content (NULL);
464       delete_data_content_windows ();
465       check_and_display_highlight_if_needed ();
466       display_registers_from (0);
467     }
468 }
469
470
471 /* Function to redisplay the contents of the data window.  */
472 void
473 tui_data_window::refresh_all ()
474 {
475   erase_data_content (NULL);
476   if (!regs_content.empty ())
477     {
478       int first_element = first_data_item_displayed ();
479
480       if (first_element >= 0)   /* Re-use existing windows.  */
481         {
482           int first_line = (-1);
483
484           if (first_element < regs_content.size ())
485             first_line = line_from_reg_element_no (first_element);
486
487           if (first_line >= 0)
488             {
489               erase_data_content (NULL);
490               display_registers_from_line (first_line);
491             }
492         }
493     }
494 }
495
496
497 /* Scroll the data window vertically forward or backward.  */
498 void
499 tui_data_window::do_scroll_vertical (int num_to_scroll)
500 {
501   int first_element_no;
502   int first_line = (-1);
503
504   first_element_no = first_data_item_displayed ();
505   if (first_element_no < regs_content.size ())
506     first_line = line_from_reg_element_no (first_element_no);
507   else
508     { /* Calculate the first line from the element number which is in
509         the general data content.  */
510     }
511
512   if (first_line >= 0)
513     {
514       first_line += num_to_scroll;
515       erase_data_content (NULL);
516       delete_data_content_windows ();
517       display_registers_from_line (first_line);
518     }
519 }
520
521 /* See tui-regs.h.  */
522
523 void
524 tui_data_window::set_new_height (int height)
525 {
526   /* Delete all data item windows.  */
527   for (auto &&win : regs_content)
528     {
529       tui_delete_win (win->handle);
530       win->handle = NULL;
531     }
532 }
533
534 /* See tui-regs.h.  */
535
536 void
537 tui_data_window::do_make_visible_with_new_height ()
538 {
539   display_all_data ();
540 }
541
542 /* See tui-regs.h.  */
543
544 void
545 tui_data_window::refresh_window ()
546 {
547   tui_gen_win_info::refresh_window ();
548   for (auto &&win : regs_content)
549     {
550       if (win != NULL)
551         win->refresh_window ();
552     }
553 }
554
555 /* This function check all displayed registers for changes in values,
556    given a particular frame.  If the values have changed, they are
557    updated with the new value and highlighted.  */
558 void
559 tui_check_register_values (struct frame_info *frame)
560 {
561   if (TUI_DATA_WIN != NULL
562       && TUI_DATA_WIN->is_visible)
563     {
564       if (TUI_DATA_WIN->regs_content.empty ()
565           && TUI_DATA_WIN->display_regs)
566         tui_show_registers (TUI_DATA_WIN->current_group);
567       else
568         {
569           for (auto &&data_item_win_ptr : TUI_DATA_WIN->regs_content)
570             {
571               int was_hilighted;
572
573               was_hilighted = data_item_win_ptr->highlight;
574
575               tui_get_register (frame, data_item_win_ptr.get (),
576                                 data_item_win_ptr->item_no,
577                                 &data_item_win_ptr->highlight);
578
579               if (data_item_win_ptr->highlight || was_hilighted)
580                 tui_display_register (data_item_win_ptr.get ());
581             }
582         }
583     }
584 }
585
586 /* Display a register in a window.  If hilite is TRUE, then the value
587    will be displayed in reverse video.  */
588 static void
589 tui_display_register (struct tui_data_item_window *data)
590 {
591   if (data->handle != NULL)
592     {
593       int i;
594
595       if (data->highlight)
596         /* We ignore the return value, casting it to void in order to avoid
597            a compiler warning.  The warning itself was introduced by a patch
598            to ncurses 5.7 dated 2009-08-29, changing this macro to expand
599            to code that causes the compiler to generate an unused-value
600            warning.  */
601         (void) wstandout (data->handle);
602       
603       wmove (data->handle, 0, 0);
604       for (i = 1; i < data->width; i++)
605         waddch (data->handle, ' ');
606       wmove (data->handle, 0, 0);
607       if (data->content)
608         waddstr (data->handle, data->content);
609
610       if (data->highlight)
611         /* We ignore the return value, casting it to void in order to avoid
612            a compiler warning.  The warning itself was introduced by a patch
613            to ncurses 5.7 dated 2009-08-29, changing this macro to expand
614            to code that causes the compiler to generate an unused-value
615            warning.  */
616         (void) wstandend (data->handle);
617       data->refresh_window ();
618     }
619 }
620
621 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
622    around behaviour.  Returns the next register group, or NULL if the
623    register window is not currently being displayed.  */
624
625 static struct reggroup *
626 tui_reg_next (struct reggroup *current_group, struct gdbarch *gdbarch)
627 {
628   struct reggroup *group = NULL;
629
630   if (current_group != NULL)
631     {
632       group = reggroup_next (gdbarch, current_group);
633       if (group == NULL)
634         group = reggroup_next (gdbarch, NULL);
635     }
636   return group;
637 }
638
639 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
640    around behaviour.  Returns the previous register group, or NULL if the
641    register window is not currently being displayed.  */
642
643 static struct reggroup *
644 tui_reg_prev (struct reggroup *current_group, struct gdbarch *gdbarch)
645 {
646   struct reggroup *group = NULL;
647
648   if (current_group != NULL)
649     {
650       group = reggroup_prev (gdbarch, current_group);
651       if (group == NULL)
652         group = reggroup_prev (gdbarch, NULL);
653     }
654   return group;
655 }
656
657 /* Implement the 'tui reg' command.  Changes the register group displayed
658    in the tui register window.  Displays the tui register window if it is
659    not already on display.  */
660
661 static void
662 tui_reg_command (const char *args, int from_tty)
663 {
664   struct gdbarch *gdbarch = get_current_arch ();
665
666   if (args != NULL)
667     {
668       struct reggroup *group, *match = NULL;
669       size_t len = strlen (args);
670
671       /* Make sure the curses mode is enabled.  */
672       tui_enable ();
673
674       /* Make sure the register window is visible.  If not, select an
675          appropriate layout.  We need to do this before trying to run the
676          'next' or 'prev' commands.  */
677       if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible)
678         tui_reg_layout ();
679
680       struct reggroup *current_group = NULL;
681       if (TUI_DATA_WIN != NULL)
682         current_group = TUI_DATA_WIN->current_group;
683       if (strncmp (args, "next", len) == 0)
684         match = tui_reg_next (current_group, gdbarch);
685       else if (strncmp (args, "prev", len) == 0)
686         match = tui_reg_prev (current_group, gdbarch);
687
688       /* This loop matches on the initial part of a register group
689          name.  If this initial part in ARGS matches only one register
690          group then the switch is made.  */
691       for (group = reggroup_next (gdbarch, NULL);
692            group != NULL;
693            group = reggroup_next (gdbarch, group))
694         {
695           if (strncmp (reggroup_name (group), args, len) == 0)
696             {
697               if (match != NULL)
698                 error (_("ambiguous register group name '%s'"), args);
699               match = group;
700             }
701         }
702
703       if (match == NULL)
704         error (_("unknown register group '%s'"), args);
705
706       tui_show_registers (match);
707     }
708   else
709     {
710       struct reggroup *group;
711       int first;
712
713       printf_unfiltered (_("\"tui reg\" must be followed by the name of "
714                            "either a register group,\nor one of 'next' "
715                            "or 'prev'.  Known register groups are:\n"));
716
717       for (first = 1, group = reggroup_next (gdbarch, NULL);
718            group != NULL;
719            first = 0, group = reggroup_next (gdbarch, group))
720         {
721           if (!first)
722             printf_unfiltered (", ");
723           printf_unfiltered ("%s", reggroup_name (group));
724         }
725
726       printf_unfiltered ("\n");
727     }
728 }
729
730 /* Complete names of register groups, and add the special "prev" and "next"
731    names.  */
732
733 static void
734 tui_reggroup_completer (struct cmd_list_element *ignore,
735                         completion_tracker &tracker,
736                         const char *text, const char *word)
737 {
738   static const char *extra[] = { "next", "prev", NULL };
739   size_t len = strlen (word);
740   const char **tmp;
741
742   reggroup_completer (ignore, tracker, text, word);
743
744   /* XXXX use complete_on_enum instead?  */
745   for (tmp = extra; *tmp != NULL; ++tmp)
746     {
747       if (strncmp (word, *tmp, len) == 0)
748         tracker.add_completion (make_unique_xstrdup (*tmp));
749     }
750 }
751
752 /* Get the register from the frame and return a printable
753    representation of it.  */
754
755 static char *
756 tui_register_format (struct frame_info *frame, int regnum)
757 {
758   struct gdbarch *gdbarch = get_frame_arch (frame);
759
760   string_file stream;
761
762   scoped_restore save_pagination
763     = make_scoped_restore (&pagination_enabled, 0);
764   scoped_restore save_stdout
765     = make_scoped_restore (&gdb_stdout, &stream);
766
767   gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
768
769   /* Remove the possible \n.  */
770   std::string &str = stream.string ();
771   if (!str.empty () && str.back () == '\n')
772     str.resize (str.size () - 1);
773
774   /* Expand tabs into spaces, since ncurses on MS-Windows doesn't.  */
775   return tui_expand_tabs (str.c_str (), 0);
776 }
777
778 /* Get the register value from the given frame and format it for the
779    display.  When changep is set, check if the new register value has
780    changed with respect to the previous call.  */
781 static void
782 tui_get_register (struct frame_info *frame,
783                   struct tui_data_item_window *data, 
784                   int regnum, bool *changedp)
785 {
786   if (changedp)
787     *changedp = false;
788   if (target_has_registers)
789     {
790       char *prev_content = data->content;
791
792       data->content = tui_register_format (frame, regnum);
793
794       if (changedp != NULL
795           && strcmp (prev_content, data->content) != 0)
796         *changedp = true;
797
798       xfree (prev_content);
799     }
800 }
801
802 void
803 _initialize_tui_regs (void)
804 {
805   struct cmd_list_element **tuicmd, *cmd;
806
807   tuicmd = tui_get_cmd_list ();
808
809   cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
810 TUI command to control the register window."), tuicmd);
811   set_cmd_completer (cmd, tui_reggroup_completer);
812 }