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