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