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