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