2007-05-31 Markus Deuling <deuling@de.ibm.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 past
118    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 problem.  */
166   display_info->display_regs = TRUE;
167
168   if (target_has_registers && target_has_stack && target_has_memory)
169     {
170       ret = tui_show_register_group (current_gdbarch, group,
171                                      get_current_frame (),
172                                      group == display_info->current_group);
173     }
174   if (ret == TUI_FAILURE)
175     {
176       display_info->current_group = 0;
177       tui_erase_data_content (NO_REGS_STRING);
178     }
179   else
180     {
181       int i;
182
183       /* Clear all notation of changed values */
184       for (i = 0; i < display_info->regs_content_count; i++)
185         {
186           struct tui_gen_win_info *data_item_win;
187           struct tui_win_element *win;
188
189           data_item_win = &display_info->regs_content[i]
190             ->which_element.data_window;
191           win = (struct tui_win_element *) data_item_win->content[0];
192           win->which_element.data.highlight = FALSE;
193         }
194       display_info->current_group = group;
195       tui_display_all_data ();
196     }
197 }
198
199
200 /* Set the data window to display the registers of the register group
201    using the given frame.  Values are refreshed only when refresh_values_only
202    is TRUE.  */
203
204 static enum tui_status
205 tui_show_register_group (struct gdbarch *gdbarch, struct reggroup *group,
206                          struct frame_info *frame, int refresh_values_only)
207 {
208   enum tui_status ret = TUI_FAILURE;
209   int nr_regs;
210   int allocated_here = FALSE;
211   int regnum, pos;
212   char title[80];
213   struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
214
215   /* Make a new title showing which group we display.  */
216   snprintf (title, sizeof (title) - 1, "Register group: %s",
217             reggroup_name (group));
218   xfree (TUI_DATA_WIN->generic.title);
219   TUI_DATA_WIN->generic.title = xstrdup (title);
220
221   /* See how many registers must be displayed.  */
222   nr_regs = 0;
223   for (regnum = 0;
224        regnum < gdbarch_num_regs (current_gdbarch)
225                 + gdbarch_num_pseudo_regs (current_gdbarch);
226        regnum++)
227     {
228       /* Must be in the group and have a name.  */
229       if (gdbarch_register_reggroup_p (gdbarch, regnum, group)
230           && gdbarch_register_name (gdbarch, regnum) != 0)
231         nr_regs++;
232     }
233
234   if (display_info->regs_content_count > 0 && !refresh_values_only)
235     {
236       tui_free_data_content (display_info->regs_content,
237                              display_info->regs_content_count);
238       display_info->regs_content_count = 0;
239     }
240
241   if (display_info->regs_content_count <= 0)
242     {
243       display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN);
244       allocated_here = TRUE;
245       refresh_values_only = FALSE;
246     }
247
248   if (display_info->regs_content != (tui_win_content) NULL)
249     {
250       if (!refresh_values_only || allocated_here)
251         {
252           TUI_DATA_WIN->generic.content = (void*) NULL;
253           TUI_DATA_WIN->generic.content_size = 0;
254           tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs);
255           display_info->regs_content
256             = (tui_win_content) TUI_DATA_WIN->generic.content;
257           display_info->regs_content_count = nr_regs;
258         }
259
260       /* Now set the register names and values */
261       pos = 0;
262       for (regnum = 0;
263            regnum < gdbarch_num_regs (current_gdbarch)
264                     + gdbarch_num_pseudo_regs (current_gdbarch);
265            regnum++)
266         {
267           struct tui_gen_win_info *data_item_win;
268           struct tui_data_element *data;
269           const char *name;
270
271           if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
272             continue;
273
274           name = gdbarch_register_name (gdbarch, regnum);
275           if (name == 0)
276             continue;
277
278           data_item_win =
279             &display_info->regs_content[pos]->which_element.data_window;
280           data =
281             &((struct tui_win_element *) data_item_win->content[0])->which_element.data;
282           if (data)
283             {
284               if (!refresh_values_only)
285                 {
286                   data->item_no = regnum;
287                   data->name = name;
288                   data->highlight = FALSE;
289                 }
290               if (data->value == (void*) NULL)
291                 data->value = (void*) xmalloc (MAX_REGISTER_SIZE);
292
293               tui_get_register (gdbarch, frame, data, regnum, 0);
294             }
295           pos++;
296         }
297
298       TUI_DATA_WIN->generic.content_size =
299         display_info->regs_content_count + display_info->data_content_count;
300       ret = TUI_SUCCESS;
301     }
302
303   return ret;
304 }
305
306 /* Function to display the registers in the content from
307    'start_element_no' until the end of the register content or the end
308    of the display height.  No checking for displaying past the end of
309    the registers is done here.  */
310 void
311 tui_display_registers_from (int start_element_no)
312 {
313   struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
314
315   if (display_info->regs_content != (tui_win_content) NULL &&
316       display_info->regs_content_count > 0)
317     {
318       int i = start_element_no;
319       int j, value_chars_wide, item_win_width, cur_y;
320
321       int max_len = 0;
322       for (i = 0; i < display_info->regs_content_count; i++)
323         {
324           struct tui_data_element *data;
325           struct tui_gen_win_info *data_item_win;
326           char *p;
327           int len;
328
329           data_item_win = &display_info->regs_content[i]->which_element.data_window;
330           data = &((struct tui_win_element *)
331                    data_item_win->content[0])->which_element.data;
332           len = 0;
333           p = data->content;
334           if (p != 0)
335             while (*p)
336               {
337                 if (*p++ == '\t')
338                   len = 8 * ((len / 8) + 1);
339                 else
340                   len++;
341               }
342
343           if (len > max_len)
344             max_len = len;
345         }
346       item_win_width = max_len + 1;
347       i = start_element_no;
348
349       display_info->regs_column_count =
350         (TUI_DATA_WIN->generic.width - 2) / item_win_width;
351       if (display_info->regs_column_count == 0)
352         display_info->regs_column_count = 1;
353       item_win_width =
354         (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count;
355
356       /*
357          ** Now create each data "sub" window, and write the display into it.
358        */
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,
429              ** and the element_no causes us to scroll past the end of the
430              ** registers, adjust what element to really start the display at.
431            */
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         {                       /*
456                                    ** If we must display regs (force_display is true), then make
457                                    ** sure that we don't display off the end of the registers.
458                                  */
459           if (line_no >= tui_last_regs_line_no ())
460             {
461               if ((line = tui_line_from_reg_element_no (
462                  TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
463                 line = 0;
464             }
465           else
466             line = line_no;
467         }
468       else
469         line = line_no;
470
471       element_no = tui_first_reg_element_no_inline (line);
472       if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
473         tui_display_reg_element_at_line (element_no, line);
474       else
475         line = (-1);
476
477       return line;
478     }
479
480   return (-1);                  /* nothing was displayed */
481 }
482
483
484 /* This function check all displayed registers for changes in values,
485    given a particular frame.  If the values have changed, they are
486    updated with the new value and highlighted.  */
487 void
488 tui_check_register_values (struct frame_info *frame)
489 {
490   if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
491     {
492       struct tui_data_info *display_info
493         = &TUI_DATA_WIN->detail.data_display_info;
494
495       if (display_info->regs_content_count <= 0 && display_info->display_regs)
496         tui_show_registers (display_info->current_group);
497       else
498         {
499           int i, j;
500
501           for (i = 0; (i < display_info->regs_content_count); i++)
502             {
503               struct tui_data_element *data;
504               struct tui_gen_win_info *data_item_win_ptr;
505               int was_hilighted;
506
507               data_item_win_ptr = &display_info->regs_content[i]->
508                 which_element.data_window;
509               data = &((struct tui_win_element *)
510                        data_item_win_ptr->content[0])->which_element.data;
511               was_hilighted = data->highlight;
512
513               tui_get_register (current_gdbarch, frame, data,
514                                 data->item_no, &data->highlight);
515
516               if (data->highlight || was_hilighted)
517                 {
518                   tui_display_register (data, data_item_win_ptr);
519                 }
520             }
521         }
522     }
523 }
524
525 /* Display a register in a window.  If hilite is TRUE,
526    then the value will be displayed in reverse video  */
527 static void
528 tui_display_register (struct tui_data_element *data,
529                       struct tui_gen_win_info *win_info)
530 {
531   if (win_info->handle != (WINDOW *) NULL)
532     {
533       int i;
534
535       if (data->highlight)
536         wstandout (win_info->handle);
537       
538       wmove (win_info->handle, 0, 0);
539       for (i = 1; i < win_info->width; i++)
540         waddch (win_info->handle, ' ');
541       wmove (win_info->handle, 0, 0);
542       if (data->content)
543         waddstr (win_info->handle, data->content);
544
545       if (data->highlight)
546         wstandend (win_info->handle);
547       tui_refresh_win (win_info);
548     }
549 }
550
551 static void
552 tui_reg_next_command (char *arg, int from_tty)
553 {
554   if (TUI_DATA_WIN != 0)
555     {
556       struct reggroup *group
557         = TUI_DATA_WIN->detail.data_display_info.current_group;
558
559       group = reggroup_next (current_gdbarch, group);
560       if (group == 0)
561         group = reggroup_next (current_gdbarch, 0);
562
563       if (group)
564         tui_show_registers (group);
565     }
566 }
567
568 static void
569 tui_reg_float_command (char *arg, int from_tty)
570 {
571   tui_show_registers (float_reggroup);
572 }
573
574 static void
575 tui_reg_general_command (char *arg, int from_tty)
576 {
577   tui_show_registers (general_reggroup);
578 }
579
580 static void
581 tui_reg_system_command (char *arg, int from_tty)
582 {
583   tui_show_registers (system_reggroup);
584 }
585
586 static struct cmd_list_element *tuireglist;
587
588 static void
589 tui_reg_command (char *args, int from_tty)
590 {
591   printf_unfiltered (_("\"tui reg\" must be followed by the name of a "
592                      "tui reg command.\n"));
593   help_list (tuireglist, "tui reg ", -1, gdb_stdout);
594 }
595
596 void
597 _initialize_tui_regs (void)
598 {
599   struct cmd_list_element **tuicmd;
600
601   tuicmd = tui_get_cmd_list ();
602
603   add_prefix_cmd ("reg", class_tui, tui_reg_command,
604                   _("TUI commands to control the register window."),
605                   &tuireglist, "tui reg ", 0,
606                   tuicmd);
607
608   add_cmd ("float", class_tui, tui_reg_float_command,
609            _("Display only floating point registers."),
610            &tuireglist);
611   add_cmd ("general", class_tui, tui_reg_general_command,
612            _("Display only general registers."),
613            &tuireglist);
614   add_cmd ("system", class_tui, tui_reg_system_command,
615            _("Display only system registers."),
616            &tuireglist);
617   add_cmd ("next", class_tui, tui_reg_next_command,
618            _("Display next register group."),
619            &tuireglist);
620
621   if (xdb_commands)
622     {
623       add_com ("fr", class_tui, tui_reg_float_command,
624                _("Display only floating point registers\n"));
625       add_com ("gr", class_tui, tui_reg_general_command,
626                _("Display only general registers\n"));
627       add_com ("sr", class_tui, tui_reg_system_command,
628                _("Display only special registers\n"));
629       add_com ("+r", class_tui, tui_scroll_regs_forward_command,
630                _("Scroll the registers window forward\n"));
631       add_com ("-r", class_tui, tui_scroll_regs_backward_command,
632                _("Scroll the register window backward\n"));
633     }
634 }
635
636
637 /*****************************************
638 ** STATIC LOCAL FUNCTIONS                 **
639 ******************************************/
640
641 extern int pagination_enabled;
642
643 static void
644 tui_restore_gdbout (void *ui)
645 {
646   ui_file_delete (gdb_stdout);
647   gdb_stdout = (struct ui_file*) ui;
648   pagination_enabled = 1;
649 }
650
651 /* Get the register from the frame and make a printable representation
652    of it in the data element.  */
653 static void
654 tui_register_format (struct gdbarch *gdbarch, struct frame_info *frame,
655                      struct tui_data_element *data_element, int regnum)
656 {
657   struct ui_file *stream;
658   struct ui_file *old_stdout;
659   const char *name;
660   struct cleanup *cleanups;
661   char *p, *s;
662   int pos;
663   struct type *type = register_type (gdbarch, regnum);
664
665   name = gdbarch_register_name (gdbarch, regnum);
666   if (name == 0)
667     {
668       return;
669     }
670   
671   pagination_enabled = 0;
672   old_stdout = gdb_stdout;
673   stream = tui_sfileopen (256);
674   gdb_stdout = stream;
675   cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
676   if (TYPE_VECTOR (type) != 0 && 0)
677     {
678       gdb_byte buf[MAX_REGISTER_SIZE];
679       int len;
680
681       len = register_size (current_gdbarch, regnum);
682       fprintf_filtered (stream, "%-14s ", name);
683       get_frame_register (frame, regnum, buf);
684       print_scalar_formatted (buf, type, 'f', len, stream);
685     }
686   else
687     {
688       gdbarch_print_registers_info (current_gdbarch, stream,
689                                     frame, regnum, 1);
690     }
691
692   /* Save formatted output in the buffer.  */
693   p = tui_file_get_strbuf (stream);
694
695   /* Remove the possible \n.  */
696   s = strrchr (p, '\n');
697   if (s && s[1] == 0)
698     *s = 0;
699
700   xfree (data_element->content);
701   data_element->content = xstrdup (p);
702   do_cleanups (cleanups);
703 }
704
705 /* Get the register value from the given frame and format it for
706    the display.  When changep is set, check if the new register value
707    has changed with respect to the previous call.  */
708 static enum tui_status
709 tui_get_register (struct gdbarch *gdbarch, struct frame_info *frame,
710                   struct tui_data_element *data, int regnum, int *changedp)
711 {
712   enum tui_status ret = TUI_FAILURE;
713
714   if (changedp)
715     *changedp = FALSE;
716   if (target_has_registers)
717     {
718       gdb_byte buf[MAX_REGISTER_SIZE];
719       get_frame_register (frame, regnum, buf);
720
721       if (changedp)
722         {
723           int size = register_size (gdbarch, regnum);
724           char *old = (char*) data->value;
725           int i;
726
727           for (i = 0; i < size; i++)
728             if (buf[i] != old[i])
729               {
730                 *changedp = TRUE;
731                 old[i] = buf[i];
732               }
733         }
734
735       /* Reformat the data content if the value changed.  */
736       if (changedp == 0 || *changedp == TRUE)
737         tui_register_format (gdbarch, frame, data, regnum);
738
739       ret = TUI_SUCCESS;
740     }
741   return ret;
742 }
743
744 static void
745 tui_scroll_regs_forward_command (char *arg, int from_tty)
746 {
747   tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1);
748 }
749
750
751 static void
752 tui_scroll_regs_backward_command (char *arg, int from_tty)
753 {
754   tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1);
755 }