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