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