Home | History | Annotate | Line # | Download | only in tui
tui-regs.c revision 1.8
      1  1.1  christos /* TUI display registers in window.
      2  1.1  christos 
      3  1.8  christos    Copyright (C) 1998-2019 Free Software Foundation, Inc.
      4  1.1  christos 
      5  1.1  christos    Contributed by Hewlett-Packard Company.
      6  1.1  christos 
      7  1.1  christos    This file is part of GDB.
      8  1.1  christos 
      9  1.1  christos    This program is free software; you can redistribute it and/or modify
     10  1.1  christos    it under the terms of the GNU General Public License as published by
     11  1.1  christos    the Free Software Foundation; either version 3 of the License, or
     12  1.1  christos    (at your option) any later version.
     13  1.1  christos 
     14  1.1  christos    This program is distributed in the hope that it will be useful,
     15  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  1.1  christos    GNU General Public License for more details.
     18  1.1  christos 
     19  1.1  christos    You should have received a copy of the GNU General Public License
     20  1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     21  1.1  christos 
     22  1.1  christos #include "defs.h"
     23  1.1  christos #include "arch-utils.h"
     24  1.1  christos #include "tui/tui.h"
     25  1.1  christos #include "tui/tui-data.h"
     26  1.1  christos #include "symtab.h"
     27  1.1  christos #include "gdbtypes.h"
     28  1.1  christos #include "gdbcmd.h"
     29  1.1  christos #include "frame.h"
     30  1.1  christos #include "regcache.h"
     31  1.1  christos #include "inferior.h"
     32  1.1  christos #include "target.h"
     33  1.1  christos #include "tui/tui-layout.h"
     34  1.1  christos #include "tui/tui-win.h"
     35  1.1  christos #include "tui/tui-windata.h"
     36  1.1  christos #include "tui/tui-wingeneral.h"
     37  1.1  christos #include "tui/tui-file.h"
     38  1.1  christos #include "tui/tui-regs.h"
     39  1.3  christos #include "tui/tui-io.h"
     40  1.1  christos #include "reggroups.h"
     41  1.1  christos #include "valprint.h"
     42  1.5  christos #include "completer.h"
     43  1.1  christos 
     44  1.1  christos #include "gdb_curses.h"
     45  1.1  christos 
     46  1.1  christos 
     47  1.1  christos /*****************************************
     48  1.1  christos ** STATIC LOCAL FUNCTIONS FORWARD DECLS    **
     49  1.1  christos ******************************************/
     50  1.1  christos static void
     51  1.1  christos tui_display_register (struct tui_data_element *data,
     52  1.1  christos                       struct tui_gen_win_info *win_info);
     53  1.1  christos 
     54  1.1  christos static enum tui_status tui_show_register_group (struct reggroup *group,
     55  1.1  christos 						struct frame_info *frame,
     56  1.1  christos 						int refresh_values_only);
     57  1.1  christos 
     58  1.1  christos static enum tui_status tui_get_register (struct frame_info *frame,
     59  1.1  christos 					 struct tui_data_element *data,
     60  1.1  christos 					 int regnum, int *changedp);
     61  1.1  christos 
     62  1.1  christos 
     63  1.1  christos 
     64  1.1  christos /*****************************************
     65  1.1  christos ** PUBLIC FUNCTIONS                     **
     66  1.1  christos ******************************************/
     67  1.1  christos 
     68  1.1  christos /* Answer the number of the last line in the regs display.  If there
     69  1.1  christos    are no registers (-1) is returned.  */
     70  1.1  christos int
     71  1.1  christos tui_last_regs_line_no (void)
     72  1.1  christos {
     73  1.1  christos   int num_lines = (-1);
     74  1.1  christos 
     75  1.1  christos   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
     76  1.1  christos     {
     77  1.1  christos       num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count /
     78  1.1  christos 		  TUI_DATA_WIN->detail.data_display_info.regs_column_count);
     79  1.1  christos       if (TUI_DATA_WIN->detail.data_display_info.regs_content_count %
     80  1.1  christos 	  TUI_DATA_WIN->detail.data_display_info.regs_column_count)
     81  1.1  christos 	num_lines++;
     82  1.1  christos     }
     83  1.1  christos   return num_lines;
     84  1.1  christos }
     85  1.1  christos 
     86  1.1  christos 
     87  1.1  christos /* Answer the line number that the register element at element_no is
     88  1.1  christos    on.  If element_no is greater than the number of register elements
     89  1.1  christos    there are, -1 is returned.  */
     90  1.1  christos int
     91  1.1  christos tui_line_from_reg_element_no (int element_no)
     92  1.1  christos {
     93  1.1  christos   if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
     94  1.1  christos     {
     95  1.1  christos       int i, line = (-1);
     96  1.1  christos 
     97  1.1  christos       i = 1;
     98  1.1  christos       while (line == (-1))
     99  1.1  christos 	{
    100  1.1  christos 	  if (element_no <
    101  1.1  christos 	      (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i))
    102  1.1  christos 	    line = i - 1;
    103  1.1  christos 	  else
    104  1.1  christos 	    i++;
    105  1.1  christos 	}
    106  1.1  christos 
    107  1.1  christos       return line;
    108  1.1  christos     }
    109  1.1  christos   else
    110  1.1  christos     return (-1);
    111  1.1  christos }
    112  1.1  christos 
    113  1.1  christos 
    114  1.1  christos /* Answer the index of the first element in line_no.  If line_no is
    115  1.1  christos    past the register area (-1) is returned.  */
    116  1.1  christos int
    117  1.1  christos tui_first_reg_element_no_inline (int line_no)
    118  1.1  christos {
    119  1.1  christos   if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
    120  1.1  christos       <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
    121  1.1  christos     return ((line_no + 1) *
    122  1.1  christos 	    TUI_DATA_WIN->detail.data_display_info.regs_column_count) -
    123  1.1  christos       TUI_DATA_WIN->detail.data_display_info.regs_column_count;
    124  1.1  christos   else
    125  1.1  christos     return (-1);
    126  1.1  christos }
    127  1.1  christos 
    128  1.1  christos 
    129  1.1  christos /* Show the registers of the given group in the data window
    130  1.1  christos    and refresh the window.  */
    131  1.1  christos void
    132  1.1  christos tui_show_registers (struct reggroup *group)
    133  1.1  christos {
    134  1.1  christos   enum tui_status ret = TUI_FAILURE;
    135  1.1  christos   struct tui_data_info *display_info;
    136  1.1  christos 
    137  1.1  christos   /* Make sure the curses mode is enabled.  */
    138  1.1  christos   tui_enable ();
    139  1.1  christos 
    140  1.1  christos   /* Make sure the register window is visible.  If not, select an
    141  1.1  christos      appropriate layout.  */
    142  1.1  christos   if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
    143  1.5  christos     tui_set_layout_by_name (DATA_NAME);
    144  1.1  christos 
    145  1.1  christos   display_info = &TUI_DATA_WIN->detail.data_display_info;
    146  1.1  christos   if (group == 0)
    147  1.1  christos     group = general_reggroup;
    148  1.1  christos 
    149  1.1  christos   /* Say that registers should be displayed, even if there is a
    150  1.1  christos      problem.  */
    151  1.1  christos   display_info->display_regs = TRUE;
    152  1.1  christos 
    153  1.1  christos   if (target_has_registers && target_has_stack && target_has_memory)
    154  1.1  christos     {
    155  1.1  christos       ret = tui_show_register_group (group, get_selected_frame (NULL),
    156  1.1  christos                                      group == display_info->current_group);
    157  1.1  christos     }
    158  1.1  christos   if (ret == TUI_FAILURE)
    159  1.1  christos     {
    160  1.1  christos       display_info->current_group = 0;
    161  1.1  christos       tui_erase_data_content (NO_REGS_STRING);
    162  1.1  christos     }
    163  1.1  christos   else
    164  1.1  christos     {
    165  1.1  christos       int i;
    166  1.1  christos 
    167  1.1  christos       /* Clear all notation of changed values.  */
    168  1.1  christos       for (i = 0; i < display_info->regs_content_count; i++)
    169  1.1  christos 	{
    170  1.1  christos 	  struct tui_gen_win_info *data_item_win;
    171  1.1  christos           struct tui_win_element *win;
    172  1.1  christos 
    173  1.1  christos 	  data_item_win = &display_info->regs_content[i]
    174  1.1  christos             ->which_element.data_window;
    175  1.5  christos           win = data_item_win->content[0];
    176  1.1  christos           win->which_element.data.highlight = FALSE;
    177  1.1  christos 	}
    178  1.1  christos       display_info->current_group = group;
    179  1.1  christos       tui_display_all_data ();
    180  1.1  christos     }
    181  1.1  christos }
    182  1.1  christos 
    183  1.1  christos 
    184  1.1  christos /* Set the data window to display the registers of the register group
    185  1.1  christos    using the given frame.  Values are refreshed only when
    186  1.1  christos    refresh_values_only is TRUE.  */
    187  1.1  christos 
    188  1.1  christos static enum tui_status
    189  1.1  christos tui_show_register_group (struct reggroup *group,
    190  1.1  christos                          struct frame_info *frame,
    191  1.1  christos 			 int refresh_values_only)
    192  1.1  christos {
    193  1.1  christos   struct gdbarch *gdbarch = get_frame_arch (frame);
    194  1.1  christos   enum tui_status ret = TUI_FAILURE;
    195  1.1  christos   int nr_regs;
    196  1.1  christos   int allocated_here = FALSE;
    197  1.1  christos   int regnum, pos;
    198  1.1  christos   char title[80];
    199  1.1  christos   struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
    200  1.1  christos 
    201  1.1  christos   /* Make a new title showing which group we display.  */
    202  1.1  christos   snprintf (title, sizeof (title) - 1, "Register group: %s",
    203  1.1  christos             reggroup_name (group));
    204  1.1  christos   xfree (TUI_DATA_WIN->generic.title);
    205  1.1  christos   TUI_DATA_WIN->generic.title = xstrdup (title);
    206  1.1  christos 
    207  1.1  christos   /* See how many registers must be displayed.  */
    208  1.1  christos   nr_regs = 0;
    209  1.8  christos   for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
    210  1.1  christos     {
    211  1.1  christos       const char *name;
    212  1.1  christos 
    213  1.1  christos       /* Must be in the group.  */
    214  1.1  christos       if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
    215  1.1  christos 	continue;
    216  1.1  christos 
    217  1.1  christos       /* If the register name is empty, it is undefined for this
    218  1.1  christos 	 processor, so don't display anything.  */
    219  1.1  christos       name = gdbarch_register_name (gdbarch, regnum);
    220  1.1  christos       if (name == 0 || *name == '\0')
    221  1.1  christos 	continue;
    222  1.1  christos 
    223  1.1  christos       nr_regs++;
    224  1.1  christos     }
    225  1.1  christos 
    226  1.1  christos   if (display_info->regs_content_count > 0 && !refresh_values_only)
    227  1.1  christos     {
    228  1.1  christos       tui_free_data_content (display_info->regs_content,
    229  1.1  christos                              display_info->regs_content_count);
    230  1.1  christos       display_info->regs_content_count = 0;
    231  1.1  christos     }
    232  1.1  christos 
    233  1.1  christos   if (display_info->regs_content_count <= 0)
    234  1.1  christos     {
    235  1.1  christos       display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN);
    236  1.1  christos       allocated_here = TRUE;
    237  1.1  christos       refresh_values_only = FALSE;
    238  1.1  christos     }
    239  1.1  christos 
    240  1.1  christos   if (display_info->regs_content != (tui_win_content) NULL)
    241  1.1  christos     {
    242  1.1  christos       if (!refresh_values_only || allocated_here)
    243  1.1  christos 	{
    244  1.6  christos 	  TUI_DATA_WIN->generic.content = NULL;
    245  1.1  christos 	  TUI_DATA_WIN->generic.content_size = 0;
    246  1.1  christos 	  tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs);
    247  1.8  christos 	  display_info->regs_content = TUI_DATA_WIN->generic.content;
    248  1.1  christos 	  display_info->regs_content_count = nr_regs;
    249  1.1  christos 	}
    250  1.1  christos 
    251  1.1  christos       /* Now set the register names and values.  */
    252  1.1  christos       pos = 0;
    253  1.8  christos       for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
    254  1.1  christos         {
    255  1.1  christos 	  struct tui_gen_win_info *data_item_win;
    256  1.1  christos           struct tui_data_element *data;
    257  1.1  christos           const char *name;
    258  1.1  christos 
    259  1.1  christos           /* Must be in the group.  */
    260  1.1  christos           if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
    261  1.1  christos             continue;
    262  1.1  christos 
    263  1.1  christos 	  /* If the register name is empty, it is undefined for this
    264  1.1  christos 	     processor, so don't display anything.  */
    265  1.1  christos 	  name = gdbarch_register_name (gdbarch, regnum);
    266  1.1  christos 	  if (name == 0 || *name == '\0')
    267  1.1  christos 	    continue;
    268  1.1  christos 
    269  1.1  christos 	  data_item_win =
    270  1.1  christos             &display_info->regs_content[pos]->which_element.data_window;
    271  1.5  christos           data = &data_item_win->content[0]->which_element.data;
    272  1.1  christos           if (data)
    273  1.1  christos             {
    274  1.1  christos               if (!refresh_values_only)
    275  1.1  christos                 {
    276  1.1  christos                   data->item_no = regnum;
    277  1.1  christos                   data->name = name;
    278  1.1  christos                   data->highlight = FALSE;
    279  1.1  christos                 }
    280  1.1  christos               tui_get_register (frame, data, regnum, 0);
    281  1.1  christos             }
    282  1.1  christos           pos++;
    283  1.1  christos 	}
    284  1.1  christos 
    285  1.1  christos       TUI_DATA_WIN->generic.content_size =
    286  1.1  christos 	display_info->regs_content_count + display_info->data_content_count;
    287  1.1  christos       ret = TUI_SUCCESS;
    288  1.1  christos     }
    289  1.1  christos 
    290  1.1  christos   return ret;
    291  1.1  christos }
    292  1.1  christos 
    293  1.1  christos /* Function to display the registers in the content from
    294  1.1  christos    'start_element_no' until the end of the register content or the end
    295  1.1  christos    of the display height.  No checking for displaying past the end of
    296  1.1  christos    the registers is done here.  */
    297  1.1  christos void
    298  1.1  christos tui_display_registers_from (int start_element_no)
    299  1.1  christos {
    300  1.1  christos   struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
    301  1.1  christos 
    302  1.1  christos   if (display_info->regs_content != (tui_win_content) NULL
    303  1.1  christos       && display_info->regs_content_count > 0)
    304  1.1  christos     {
    305  1.1  christos       int i = start_element_no;
    306  1.1  christos       int j, item_win_width, cur_y;
    307  1.1  christos 
    308  1.1  christos       int max_len = 0;
    309  1.1  christos       for (i = 0; i < display_info->regs_content_count; i++)
    310  1.1  christos         {
    311  1.1  christos           struct tui_data_element *data;
    312  1.1  christos           struct tui_gen_win_info *data_item_win;
    313  1.1  christos           char *p;
    314  1.1  christos           int len;
    315  1.1  christos 
    316  1.1  christos           data_item_win
    317  1.1  christos 	    = &display_info->regs_content[i]->which_element.data_window;
    318  1.5  christos           data = &data_item_win->content[0]->which_element.data;
    319  1.1  christos           len = 0;
    320  1.1  christos           p = data->content;
    321  1.1  christos           if (p != 0)
    322  1.1  christos             while (*p)
    323  1.1  christos               {
    324  1.1  christos                 if (*p++ == '\t')
    325  1.1  christos                   len = 8 * ((len / 8) + 1);
    326  1.1  christos                 else
    327  1.1  christos                   len++;
    328  1.1  christos               }
    329  1.1  christos 
    330  1.1  christos           if (len > max_len)
    331  1.1  christos             max_len = len;
    332  1.1  christos         }
    333  1.1  christos       item_win_width = max_len + 1;
    334  1.1  christos       i = start_element_no;
    335  1.1  christos 
    336  1.1  christos       display_info->regs_column_count =
    337  1.1  christos         (TUI_DATA_WIN->generic.width - 2) / item_win_width;
    338  1.1  christos       if (display_info->regs_column_count == 0)
    339  1.1  christos         display_info->regs_column_count = 1;
    340  1.1  christos       item_win_width =
    341  1.1  christos         (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count;
    342  1.1  christos 
    343  1.1  christos       /* Now create each data "sub" window, and write the display into
    344  1.1  christos 	 it.  */
    345  1.1  christos       cur_y = 1;
    346  1.1  christos       while (i < display_info->regs_content_count
    347  1.1  christos 	     && cur_y <= TUI_DATA_WIN->generic.viewport_height)
    348  1.1  christos 	{
    349  1.1  christos 	  for (j = 0;
    350  1.1  christos 	       j < display_info->regs_column_count
    351  1.1  christos 		 && i < display_info->regs_content_count;
    352  1.1  christos 	       j++)
    353  1.1  christos 	    {
    354  1.1  christos 	      struct tui_gen_win_info *data_item_win;
    355  1.1  christos 	      struct tui_data_element *data_element_ptr;
    356  1.1  christos 
    357  1.1  christos 	      /* Create the window if necessary.  */
    358  1.1  christos 	      data_item_win = &display_info->regs_content[i]
    359  1.1  christos                 ->which_element.data_window;
    360  1.5  christos 	      data_element_ptr = &data_item_win->content[0]->which_element.data;
    361  1.1  christos               if (data_item_win->handle != (WINDOW*) NULL
    362  1.1  christos                   && (data_item_win->height != 1
    363  1.1  christos                       || data_item_win->width != item_win_width
    364  1.1  christos                       || data_item_win->origin.x != (item_win_width * j) + 1
    365  1.1  christos                       || data_item_win->origin.y != cur_y))
    366  1.1  christos                 {
    367  1.1  christos                   tui_delete_win (data_item_win->handle);
    368  1.1  christos                   data_item_win->handle = 0;
    369  1.1  christos                 }
    370  1.1  christos 
    371  1.1  christos 	      if (data_item_win->handle == (WINDOW *) NULL)
    372  1.1  christos 		{
    373  1.1  christos 		  data_item_win->height = 1;
    374  1.1  christos 		  data_item_win->width = item_win_width;
    375  1.1  christos 		  data_item_win->origin.x = (item_win_width * j) + 1;
    376  1.1  christos 		  data_item_win->origin.y = cur_y;
    377  1.1  christos 		  tui_make_window (data_item_win, DONT_BOX_WINDOW);
    378  1.1  christos                   scrollok (data_item_win->handle, FALSE);
    379  1.1  christos 		}
    380  1.1  christos               touchwin (data_item_win->handle);
    381  1.1  christos 
    382  1.1  christos 	      /* Get the printable representation of the register
    383  1.1  christos                  and display it.  */
    384  1.1  christos               tui_display_register (data_element_ptr, data_item_win);
    385  1.1  christos 	      i++;		/* Next register.  */
    386  1.1  christos 	    }
    387  1.1  christos 	  cur_y++;		/* Next row.  */
    388  1.1  christos 	}
    389  1.1  christos     }
    390  1.1  christos }
    391  1.1  christos 
    392  1.1  christos 
    393  1.1  christos /* Function to display the registers in the content from
    394  1.1  christos    'start_element_no' on 'start_line_no' until the end of the register
    395  1.1  christos    content or the end of the display height.  This function checks
    396  1.1  christos    that we won't display off the end of the register display.  */
    397  1.1  christos static void
    398  1.1  christos tui_display_reg_element_at_line (int start_element_no,
    399  1.1  christos 				 int start_line_no)
    400  1.1  christos {
    401  1.1  christos   if (TUI_DATA_WIN->detail.data_display_info.regs_content
    402  1.1  christos       != (tui_win_content) NULL
    403  1.1  christos       && TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
    404  1.1  christos     {
    405  1.1  christos       int element_no = start_element_no;
    406  1.1  christos 
    407  1.1  christos       if (start_element_no != 0 && start_line_no != 0)
    408  1.1  christos 	{
    409  1.1  christos 	  int last_line_no, first_line_on_last_page;
    410  1.1  christos 
    411  1.1  christos 	  last_line_no = tui_last_regs_line_no ();
    412  1.1  christos 	  first_line_on_last_page
    413  1.1  christos 	    = last_line_no - (TUI_DATA_WIN->generic.height - 2);
    414  1.1  christos 	  if (first_line_on_last_page < 0)
    415  1.1  christos 	    first_line_on_last_page = 0;
    416  1.1  christos 
    417  1.1  christos 	  /* If there is no other data displayed except registers, and
    418  1.1  christos 	     the element_no causes us to scroll past the end of the
    419  1.1  christos 	     registers, adjust what element to really start the
    420  1.1  christos 	     display at.  */
    421  1.1  christos 	  if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0
    422  1.1  christos 	      && start_line_no > first_line_on_last_page)
    423  1.1  christos 	    element_no
    424  1.1  christos 	      = tui_first_reg_element_no_inline (first_line_on_last_page);
    425  1.1  christos 	}
    426  1.1  christos       tui_display_registers_from (element_no);
    427  1.1  christos     }
    428  1.1  christos }
    429  1.1  christos 
    430  1.1  christos 
    431  1.1  christos 
    432  1.1  christos /* Function to display the registers starting at line line_no in the
    433  1.1  christos    data window.  Answers the line number that the display actually
    434  1.1  christos    started from.  If nothing is displayed (-1) is returned.  */
    435  1.1  christos int
    436  1.1  christos tui_display_registers_from_line (int line_no,
    437  1.1  christos 				 int force_display)
    438  1.1  christos {
    439  1.1  christos   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
    440  1.1  christos     {
    441  1.1  christos       int line, element_no;
    442  1.1  christos 
    443  1.1  christos       if (line_no < 0)
    444  1.1  christos 	line = 0;
    445  1.1  christos       else if (force_display)
    446  1.1  christos 	{ /* If we must display regs (force_display is true), then
    447  1.1  christos 	     make sure that we don't display off the end of the
    448  1.1  christos 	     registers.  */
    449  1.1  christos 	  if (line_no >= tui_last_regs_line_no ())
    450  1.1  christos 	    {
    451  1.1  christos 	      if ((line = tui_line_from_reg_element_no (
    452  1.1  christos 		 TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
    453  1.1  christos 		line = 0;
    454  1.1  christos 	    }
    455  1.1  christos 	  else
    456  1.1  christos 	    line = line_no;
    457  1.1  christos 	}
    458  1.1  christos       else
    459  1.1  christos 	line = line_no;
    460  1.1  christos 
    461  1.1  christos       element_no = tui_first_reg_element_no_inline (line);
    462  1.1  christos       if (element_no
    463  1.1  christos 	  < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
    464  1.1  christos 	tui_display_reg_element_at_line (element_no, line);
    465  1.1  christos       else
    466  1.1  christos 	line = (-1);
    467  1.1  christos 
    468  1.1  christos       return line;
    469  1.1  christos     }
    470  1.1  christos 
    471  1.1  christos   return (-1);			/* Nothing was displayed.  */
    472  1.1  christos }
    473  1.1  christos 
    474  1.1  christos 
    475  1.1  christos /* This function check all displayed registers for changes in values,
    476  1.1  christos    given a particular frame.  If the values have changed, they are
    477  1.1  christos    updated with the new value and highlighted.  */
    478  1.1  christos void
    479  1.1  christos tui_check_register_values (struct frame_info *frame)
    480  1.1  christos {
    481  1.1  christos   if (TUI_DATA_WIN != NULL
    482  1.1  christos       && TUI_DATA_WIN->generic.is_visible)
    483  1.1  christos     {
    484  1.1  christos       struct tui_data_info *display_info
    485  1.1  christos         = &TUI_DATA_WIN->detail.data_display_info;
    486  1.1  christos 
    487  1.1  christos       if (display_info->regs_content_count <= 0
    488  1.1  christos 	  && display_info->display_regs)
    489  1.1  christos 	tui_show_registers (display_info->current_group);
    490  1.1  christos       else
    491  1.1  christos 	{
    492  1.1  christos 	  int i;
    493  1.1  christos 
    494  1.1  christos 	  for (i = 0; (i < display_info->regs_content_count); i++)
    495  1.1  christos 	    {
    496  1.1  christos 	      struct tui_data_element *data;
    497  1.1  christos 	      struct tui_gen_win_info *data_item_win_ptr;
    498  1.1  christos 	      int was_hilighted;
    499  1.1  christos 
    500  1.1  christos 	      data_item_win_ptr = &display_info->regs_content[i]->
    501  1.1  christos                 which_element.data_window;
    502  1.5  christos 	      data = &data_item_win_ptr->content[0]->which_element.data;
    503  1.1  christos 	      was_hilighted = data->highlight;
    504  1.1  christos 
    505  1.1  christos               tui_get_register (frame, data,
    506  1.1  christos                                 data->item_no, &data->highlight);
    507  1.1  christos 
    508  1.1  christos 	      if (data->highlight || was_hilighted)
    509  1.1  christos 		{
    510  1.1  christos                   tui_display_register (data, data_item_win_ptr);
    511  1.1  christos 		}
    512  1.1  christos 	    }
    513  1.1  christos 	}
    514  1.1  christos     }
    515  1.1  christos }
    516  1.1  christos 
    517  1.1  christos /* Display a register in a window.  If hilite is TRUE, then the value
    518  1.1  christos    will be displayed in reverse video.  */
    519  1.1  christos static void
    520  1.1  christos tui_display_register (struct tui_data_element *data,
    521  1.1  christos                       struct tui_gen_win_info *win_info)
    522  1.1  christos {
    523  1.1  christos   if (win_info->handle != (WINDOW *) NULL)
    524  1.1  christos     {
    525  1.1  christos       int i;
    526  1.1  christos 
    527  1.1  christos       if (data->highlight)
    528  1.1  christos 	/* We ignore the return value, casting it to void in order to avoid
    529  1.1  christos 	   a compiler warning.  The warning itself was introduced by a patch
    530  1.1  christos 	   to ncurses 5.7 dated 2009-08-29, changing this macro to expand
    531  1.1  christos 	   to code that causes the compiler to generate an unused-value
    532  1.1  christos 	   warning.  */
    533  1.1  christos 	(void) wstandout (win_info->handle);
    534  1.1  christos 
    535  1.1  christos       wmove (win_info->handle, 0, 0);
    536  1.1  christos       for (i = 1; i < win_info->width; i++)
    537  1.1  christos         waddch (win_info->handle, ' ');
    538  1.1  christos       wmove (win_info->handle, 0, 0);
    539  1.1  christos       if (data->content)
    540  1.1  christos         waddstr (win_info->handle, data->content);
    541  1.1  christos 
    542  1.1  christos       if (data->highlight)
    543  1.1  christos 	/* We ignore the return value, casting it to void in order to avoid
    544  1.1  christos 	   a compiler warning.  The warning itself was introduced by a patch
    545  1.1  christos 	   to ncurses 5.7 dated 2009-08-29, changing this macro to expand
    546  1.1  christos 	   to code that causes the compiler to generate an unused-value
    547  1.1  christos 	   warning.  */
    548  1.1  christos 	(void) wstandend (win_info->handle);
    549  1.1  christos       tui_refresh_win (win_info);
    550  1.1  christos     }
    551  1.1  christos }
    552  1.1  christos 
    553  1.5  christos /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
    554  1.5  christos    around behaviour.  Returns the next register group, or NULL if the
    555  1.5  christos    register window is not currently being displayed.  */
    556  1.5  christos 
    557  1.5  christos static struct reggroup *
    558  1.5  christos tui_reg_next (struct gdbarch *gdbarch)
    559  1.1  christos {
    560  1.5  christos   struct reggroup *group = NULL;
    561  1.1  christos 
    562  1.5  christos   if (TUI_DATA_WIN != NULL)
    563  1.1  christos     {
    564  1.5  christos       group = TUI_DATA_WIN->detail.data_display_info.current_group;
    565  1.1  christos       group = reggroup_next (gdbarch, group);
    566  1.5  christos       if (group == NULL)
    567  1.5  christos         group = reggroup_next (gdbarch, NULL);
    568  1.1  christos     }
    569  1.5  christos   return group;
    570  1.1  christos }
    571  1.1  christos 
    572  1.5  christos /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
    573  1.5  christos    around behaviour.  Returns the previous register group, or NULL if the
    574  1.5  christos    register window is not currently being displayed.  */
    575  1.5  christos 
    576  1.5  christos static struct reggroup *
    577  1.5  christos tui_reg_prev (struct gdbarch *gdbarch)
    578  1.1  christos {
    579  1.5  christos   struct reggroup *group = NULL;
    580  1.5  christos 
    581  1.5  christos   if (TUI_DATA_WIN != NULL)
    582  1.5  christos     {
    583  1.5  christos       group = TUI_DATA_WIN->detail.data_display_info.current_group;
    584  1.5  christos       group = reggroup_prev (gdbarch, group);
    585  1.5  christos       if (group == NULL)
    586  1.5  christos 	group = reggroup_prev (gdbarch, NULL);
    587  1.5  christos     }
    588  1.5  christos   return group;
    589  1.1  christos }
    590  1.1  christos 
    591  1.5  christos /* Implement the 'tui reg' command.  Changes the register group displayed
    592  1.5  christos    in the tui register window.  Displays the tui register window if it is
    593  1.5  christos    not already on display.  */
    594  1.5  christos 
    595  1.1  christos static void
    596  1.8  christos tui_reg_command (const char *args, int from_tty)
    597  1.1  christos {
    598  1.5  christos   struct gdbarch *gdbarch = get_current_arch ();
    599  1.5  christos 
    600  1.5  christos   if (args != NULL)
    601  1.5  christos     {
    602  1.5  christos       struct reggroup *group, *match = NULL;
    603  1.5  christos       size_t len = strlen (args);
    604  1.5  christos 
    605  1.5  christos       /* Make sure the curses mode is enabled.  */
    606  1.5  christos       tui_enable ();
    607  1.5  christos 
    608  1.5  christos       /* Make sure the register window is visible.  If not, select an
    609  1.5  christos 	 appropriate layout.  We need to do this before trying to run the
    610  1.5  christos 	 'next' or 'prev' commands.  */
    611  1.5  christos       if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
    612  1.5  christos 	tui_set_layout_by_name (DATA_NAME);
    613  1.5  christos 
    614  1.5  christos       if (strncmp (args, "next", len) == 0)
    615  1.5  christos 	match = tui_reg_next (gdbarch);
    616  1.5  christos       else if (strncmp (args, "prev", len) == 0)
    617  1.5  christos 	match = tui_reg_prev (gdbarch);
    618  1.5  christos 
    619  1.5  christos       /* This loop matches on the initial part of a register group
    620  1.5  christos 	 name.  If this initial part in ARGS matches only one register
    621  1.5  christos 	 group then the switch is made.  */
    622  1.5  christos       for (group = reggroup_next (gdbarch, NULL);
    623  1.5  christos 	   group != NULL;
    624  1.5  christos 	   group = reggroup_next (gdbarch, group))
    625  1.5  christos 	{
    626  1.5  christos 	  if (strncmp (reggroup_name (group), args, len) == 0)
    627  1.5  christos 	    {
    628  1.5  christos 	      if (match != NULL)
    629  1.5  christos 		error (_("ambiguous register group name '%s'"), args);
    630  1.5  christos 	      match = group;
    631  1.5  christos 	    }
    632  1.5  christos 	}
    633  1.5  christos 
    634  1.5  christos       if (match == NULL)
    635  1.5  christos 	error (_("unknown register group '%s'"), args);
    636  1.5  christos 
    637  1.5  christos       tui_show_registers (match);
    638  1.5  christos     }
    639  1.5  christos   else
    640  1.5  christos     {
    641  1.5  christos       struct reggroup *group;
    642  1.5  christos       int first;
    643  1.5  christos 
    644  1.5  christos       printf_unfiltered (_("\"tui reg\" must be followed by the name of "
    645  1.5  christos 			   "either a register group,\nor one of 'next' "
    646  1.5  christos 			   "or 'prev'.  Known register groups are:\n"));
    647  1.5  christos 
    648  1.5  christos       for (first = 1, group = reggroup_next (gdbarch, NULL);
    649  1.5  christos 	   group != NULL;
    650  1.5  christos 	   first = 0, group = reggroup_next (gdbarch, group))
    651  1.5  christos 	{
    652  1.5  christos 	  if (!first)
    653  1.5  christos 	    printf_unfiltered (", ");
    654  1.5  christos 	  printf_unfiltered ("%s", reggroup_name (group));
    655  1.5  christos 	}
    656  1.5  christos 
    657  1.5  christos       printf_unfiltered ("\n");
    658  1.5  christos     }
    659  1.1  christos }
    660  1.1  christos 
    661  1.5  christos /* Complete names of register groups, and add the special "prev" and "next"
    662  1.5  christos    names.  */
    663  1.5  christos 
    664  1.8  christos static void
    665  1.5  christos tui_reggroup_completer (struct cmd_list_element *ignore,
    666  1.8  christos 			completion_tracker &tracker,
    667  1.5  christos 			const char *text, const char *word)
    668  1.1  christos {
    669  1.5  christos   static const char *extra[] = { "next", "prev", NULL };
    670  1.5  christos   size_t len = strlen (word);
    671  1.5  christos   const char **tmp;
    672  1.5  christos 
    673  1.8  christos   reggroup_completer (ignore, tracker, text, word);
    674  1.1  christos 
    675  1.8  christos   /* XXXX use complete_on_enum instead?  */
    676  1.5  christos   for (tmp = extra; *tmp != NULL; ++tmp)
    677  1.5  christos     {
    678  1.5  christos       if (strncmp (word, *tmp, len) == 0)
    679  1.8  christos 	tracker.add_completion (gdb::unique_xmalloc_ptr<char> (xstrdup (*tmp)));
    680  1.5  christos     }
    681  1.1  christos }
    682  1.1  christos 
    683  1.1  christos void
    684  1.1  christos _initialize_tui_regs (void)
    685  1.1  christos {
    686  1.5  christos   struct cmd_list_element **tuicmd, *cmd;
    687  1.1  christos 
    688  1.1  christos   tuicmd = tui_get_cmd_list ();
    689  1.1  christos 
    690  1.5  christos   cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
    691  1.5  christos TUI command to control the register window."), tuicmd);
    692  1.5  christos   set_cmd_completer (cmd, tui_reggroup_completer);
    693  1.1  christos }
    694  1.1  christos 
    695  1.1  christos 
    696  1.1  christos /*****************************************
    697  1.1  christos ** STATIC LOCAL FUNCTIONS                 **
    698  1.1  christos ******************************************/
    699  1.1  christos 
    700  1.1  christos /* Get the register from the frame and return a printable
    701  1.1  christos    representation of it.  */
    702  1.1  christos 
    703  1.1  christos static char *
    704  1.1  christos tui_register_format (struct frame_info *frame, int regnum)
    705  1.1  christos {
    706  1.1  christos   struct gdbarch *gdbarch = get_frame_arch (frame);
    707  1.1  christos 
    708  1.7  christos   string_file stream;
    709  1.7  christos 
    710  1.8  christos   scoped_restore save_pagination
    711  1.8  christos     = make_scoped_restore (&pagination_enabled, 0);
    712  1.8  christos   scoped_restore save_stdout
    713  1.8  christos     = make_scoped_restore (&gdb_stdout, &stream);
    714  1.8  christos 
    715  1.7  christos   gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
    716  1.1  christos 
    717  1.1  christos   /* Remove the possible \n.  */
    718  1.7  christos   std::string &str = stream.string ();
    719  1.7  christos   if (!str.empty () && str.back () == '\n')
    720  1.7  christos     str.resize (str.size () - 1);
    721  1.1  christos 
    722  1.3  christos   /* Expand tabs into spaces, since ncurses on MS-Windows doesn't.  */
    723  1.8  christos   return tui_expand_tabs (str.c_str (), 0);
    724  1.1  christos }
    725  1.1  christos 
    726  1.1  christos /* Get the register value from the given frame and format it for the
    727  1.1  christos    display.  When changep is set, check if the new register value has
    728  1.1  christos    changed with respect to the previous call.  */
    729  1.1  christos static enum tui_status
    730  1.1  christos tui_get_register (struct frame_info *frame,
    731  1.1  christos                   struct tui_data_element *data,
    732  1.1  christos 		  int regnum, int *changedp)
    733  1.1  christos {
    734  1.1  christos   enum tui_status ret = TUI_FAILURE;
    735  1.1  christos 
    736  1.1  christos   if (changedp)
    737  1.1  christos     *changedp = FALSE;
    738  1.1  christos   if (target_has_registers)
    739  1.1  christos     {
    740  1.1  christos       char *prev_content = data->content;
    741  1.1  christos 
    742  1.1  christos       data->content = tui_register_format (frame, regnum);
    743  1.1  christos 
    744  1.1  christos       if (changedp != NULL
    745  1.1  christos 	  && strcmp (prev_content, data->content) != 0)
    746  1.1  christos 	*changedp = 1;
    747  1.1  christos 
    748  1.1  christos       xfree (prev_content);
    749  1.1  christos 
    750  1.1  christos       ret = TUI_SUCCESS;
    751  1.1  christos     }
    752  1.1  christos   return ret;
    753  1.1  christos }
    754