2005-02-11 Andrew Cagney <cagney@gnu.org>
[external/binutils.git] / gdb / tui / tui-regs.c
1 /* TUI display registers in window.
2
3    Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
4    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., 59 Temple Place - Suite 330,
23    Boston, MA 02111-1307, 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; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
224     {
225       /* Must be in the group and have a name.  */
226       if (gdbarch_register_reggroup_p (gdbarch, regnum, group)
227           && gdbarch_register_name (gdbarch, regnum) != 0)
228         nr_regs++;
229     }
230
231   if (display_info->regs_content_count > 0 && !refresh_values_only)
232     {
233       tui_free_data_content (display_info->regs_content,
234                              display_info->regs_content_count);
235       display_info->regs_content_count = 0;
236     }
237
238   if (display_info->regs_content_count <= 0)
239     {
240       display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN);
241       allocated_here = TRUE;
242       refresh_values_only = FALSE;
243     }
244
245   if (display_info->regs_content != (tui_win_content) NULL)
246     {
247       if (!refresh_values_only || allocated_here)
248         {
249           TUI_DATA_WIN->generic.content = (void*) NULL;
250           TUI_DATA_WIN->generic.content_size = 0;
251           tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs);
252           display_info->regs_content
253             = (tui_win_content) TUI_DATA_WIN->generic.content;
254           display_info->regs_content_count = nr_regs;
255         }
256
257       /* Now set the register names and values */
258       pos = 0;
259       for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
260         {
261           struct tui_gen_win_info *data_item_win;
262           struct tui_data_element *data;
263           const char *name;
264
265           if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
266             continue;
267
268           name = gdbarch_register_name (gdbarch, regnum);
269           if (name == 0)
270             continue;
271
272           data_item_win =
273             &display_info->regs_content[pos]->which_element.data_window;
274           data =
275             &((struct tui_win_element *) data_item_win->content[0])->which_element.data;
276           if (data)
277             {
278               if (!refresh_values_only)
279                 {
280                   data->item_no = regnum;
281                   data->name = name;
282                   data->highlight = FALSE;
283                 }
284               if (data->value == (void*) NULL)
285                 data->value = (void*) xmalloc (MAX_REGISTER_SIZE);
286
287               tui_get_register (gdbarch, frame, data, regnum, 0);
288             }
289           pos++;
290         }
291
292       TUI_DATA_WIN->generic.content_size =
293         display_info->regs_content_count + display_info->data_content_count;
294       ret = TUI_SUCCESS;
295     }
296
297   return ret;
298 }
299
300 /* Function to display the registers in the content from
301    'start_element_no' until the end of the register content or the end
302    of the display height.  No checking for displaying past the end of
303    the registers is done here.  */
304 void
305 tui_display_registers_from (int start_element_no)
306 {
307   struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
308
309   if (display_info->regs_content != (tui_win_content) NULL &&
310       display_info->regs_content_count > 0)
311     {
312       int i = start_element_no;
313       int j, value_chars_wide, item_win_width, cur_y;
314
315       int max_len = 0;
316       for (i = 0; i < display_info->regs_content_count; i++)
317         {
318           struct tui_data_element *data;
319           struct tui_gen_win_info *data_item_win;
320           char *p;
321           int len;
322
323           data_item_win = &display_info->regs_content[i]->which_element.data_window;
324           data = &((struct tui_win_element *)
325                    data_item_win->content[0])->which_element.data;
326           len = 0;
327           p = data->content;
328           if (p != 0)
329             while (*p)
330               {
331                 if (*p++ == '\t')
332                   len = 8 * ((len / 8) + 1);
333                 else
334                   len++;
335               }
336
337           if (len > max_len)
338             max_len = len;
339         }
340       item_win_width = max_len + 1;
341       i = start_element_no;
342
343       display_info->regs_column_count =
344         (TUI_DATA_WIN->generic.width - 2) / item_win_width;
345       if (display_info->regs_column_count == 0)
346         display_info->regs_column_count = 1;
347       item_win_width =
348         (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count;
349
350       /*
351          ** Now create each data "sub" window, and write the display into it.
352        */
353       cur_y = 1;
354       while (i < display_info->regs_content_count &&
355              cur_y <= TUI_DATA_WIN->generic.viewport_height)
356         {
357           for (j = 0;
358                (j < display_info->regs_column_count &&
359                 i < display_info->regs_content_count); j++)
360             {
361               struct tui_gen_win_info * data_item_win;
362               struct tui_data_element * data_element_ptr;
363
364               /* create the window if necessary */
365               data_item_win = &display_info->regs_content[i]
366                 ->which_element.data_window;
367               data_element_ptr = &((struct tui_win_element *)
368                                  data_item_win->content[0])->which_element.data;
369               if (data_item_win->handle != (WINDOW*) NULL
370                   && (data_item_win->height != 1
371                       || data_item_win->width != item_win_width
372                       || data_item_win->origin.x != (item_win_width * j) + 1
373                       || data_item_win->origin.y != cur_y))
374                 {
375                   tui_delete_win (data_item_win->handle);
376                   data_item_win->handle = 0;
377                 }
378                   
379               if (data_item_win->handle == (WINDOW *) NULL)
380                 {
381                   data_item_win->height = 1;
382                   data_item_win->width = item_win_width;
383                   data_item_win->origin.x = (item_win_width * j) + 1;
384                   data_item_win->origin.y = cur_y;
385                   tui_make_window (data_item_win, DONT_BOX_WINDOW);
386                   scrollok (data_item_win->handle, FALSE);
387                 }
388               touchwin (data_item_win->handle);
389
390               /* Get the printable representation of the register
391                  and display it.  */
392               tui_display_register (data_element_ptr, data_item_win);
393               i++;              /* next register */
394             }
395           cur_y++;              /* next row; */
396         }
397     }
398 }
399
400
401 /* Function to display the registers in the content from
402    'start_element_no' on 'start_line_no' until the end of the register
403    content or the end of the display height.  This function checks
404    that we won't display off the end of the register display.  */
405 void
406 tui_display_reg_element_at_line (int start_element_no, int start_line_no)
407 {
408   if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL &&
409       TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
410     {
411       int element_no = start_element_no;
412
413       if (start_element_no != 0 && start_line_no != 0)
414         {
415           int last_line_no, first_line_on_last_page;
416
417           last_line_no = tui_last_regs_line_no ();
418           first_line_on_last_page = last_line_no - (TUI_DATA_WIN->generic.height - 2);
419           if (first_line_on_last_page < 0)
420             first_line_on_last_page = 0;
421           /*
422              ** If there is no other data displayed except registers,
423              ** and the element_no causes us to scroll past the end of the
424              ** registers, adjust what element to really start the display at.
425            */
426           if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0 &&
427               start_line_no > first_line_on_last_page)
428             element_no = tui_first_reg_element_no_inline (first_line_on_last_page);
429         }
430       tui_display_registers_from (element_no);
431     }
432 }
433
434
435
436 /* Function to display the registers starting at line line_no in the
437    data window.  Answers the line number that the display actually
438    started from.  If nothing is displayed (-1) is returned.  */
439 int
440 tui_display_registers_from_line (int line_no, int force_display)
441 {
442   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
443     {
444       int line, element_no;
445
446       if (line_no < 0)
447         line = 0;
448       else if (force_display)
449         {                       /*
450                                    ** If we must display regs (force_display is true), then make
451                                    ** sure that we don't display off the end of the registers.
452                                  */
453           if (line_no >= tui_last_regs_line_no ())
454             {
455               if ((line = tui_line_from_reg_element_no (
456                  TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
457                 line = 0;
458             }
459           else
460             line = line_no;
461         }
462       else
463         line = line_no;
464
465       element_no = tui_first_reg_element_no_inline (line);
466       if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
467         tui_display_reg_element_at_line (element_no, line);
468       else
469         line = (-1);
470
471       return line;
472     }
473
474   return (-1);                  /* nothing was displayed */
475 }
476
477
478 /* This function check all displayed registers for changes in values,
479    given a particular frame.  If the values have changed, they are
480    updated with the new value and highlighted.  */
481 void
482 tui_check_register_values (struct frame_info *frame)
483 {
484   if (TUI_DATA_WIN != NULL && TUI_DATA_WIN->generic.is_visible)
485     {
486       struct tui_data_info *display_info
487         = &TUI_DATA_WIN->detail.data_display_info;
488
489       if (display_info->regs_content_count <= 0 && display_info->display_regs)
490         tui_show_registers (display_info->current_group);
491       else
492         {
493           int i, j;
494
495           for (i = 0; (i < display_info->regs_content_count); i++)
496             {
497               struct tui_data_element *data;
498               struct tui_gen_win_info *data_item_win_ptr;
499               int was_hilighted;
500
501               data_item_win_ptr = &display_info->regs_content[i]->
502                 which_element.data_window;
503               data = &((struct tui_win_element *)
504                        data_item_win_ptr->content[0])->which_element.data;
505               was_hilighted = data->highlight;
506
507               tui_get_register (current_gdbarch, frame, data,
508                                 data->item_no, &data->highlight);
509
510               if (data->highlight || was_hilighted)
511                 {
512                   tui_display_register (data, data_item_win_ptr);
513                 }
514             }
515         }
516     }
517 }
518
519 /* Display a register in a window.  If hilite is TRUE,
520    then the value will be displayed in reverse video  */
521 static void
522 tui_display_register (struct tui_data_element *data,
523                       struct tui_gen_win_info *win_info)
524 {
525   if (win_info->handle != (WINDOW *) NULL)
526     {
527       int i;
528
529       if (data->highlight)
530         wstandout (win_info->handle);
531       
532       wmove (win_info->handle, 0, 0);
533       for (i = 1; i < win_info->width; i++)
534         waddch (win_info->handle, ' ');
535       wmove (win_info->handle, 0, 0);
536       if (data->content)
537         waddstr (win_info->handle, data->content);
538
539       if (data->highlight)
540         wstandend (win_info->handle);
541       tui_refresh_win (win_info);
542     }
543 }
544
545 static void
546 tui_reg_next_command (char *arg, int from_tty)
547 {
548   if (TUI_DATA_WIN != 0)
549     {
550       struct reggroup *group
551         = TUI_DATA_WIN->detail.data_display_info.current_group;
552
553       group = reggroup_next (current_gdbarch, group);
554       if (group == 0)
555         group = reggroup_next (current_gdbarch, 0);
556
557       if (group)
558         tui_show_registers (group);
559     }
560 }
561
562 static void
563 tui_reg_float_command (char *arg, int from_tty)
564 {
565   tui_show_registers (float_reggroup);
566 }
567
568 static void
569 tui_reg_general_command (char *arg, int from_tty)
570 {
571   tui_show_registers (general_reggroup);
572 }
573
574 static void
575 tui_reg_system_command (char *arg, int from_tty)
576 {
577   tui_show_registers (system_reggroup);
578 }
579
580 static struct cmd_list_element *tuireglist;
581
582 static void
583 tui_reg_command (char *args, int from_tty)
584 {
585   printf_unfiltered (_("\"tui reg\" must be followed by the name of a "
586                      "tui reg command.\n"));
587   help_list (tuireglist, "tui reg ", -1, gdb_stdout);
588 }
589
590 void
591 _initialize_tui_regs (void)
592 {
593   struct cmd_list_element **tuicmd;
594
595   tuicmd = tui_get_cmd_list ();
596
597   add_prefix_cmd ("reg", class_tui, tui_reg_command,
598                   "TUI commands to control the register window.",
599                   &tuireglist, "tui reg ", 0,
600                   tuicmd);
601
602   add_cmd ("float", class_tui, tui_reg_float_command,
603            "Display only floating point registers\n",
604            &tuireglist);
605   add_cmd ("general", class_tui, tui_reg_general_command,
606            "Display only general registers\n",
607            &tuireglist);
608   add_cmd ("system", class_tui, tui_reg_system_command,
609            "Display only system registers\n",
610            &tuireglist);
611   add_cmd ("next", class_tui, tui_reg_next_command,
612            "Display next register group\n",
613            &tuireglist);
614
615   if (xdb_commands)
616     {
617       add_com ("fr", class_tui, tui_reg_float_command,
618                "Display only floating point registers\n");
619       add_com ("gr", class_tui, tui_reg_general_command,
620                "Display only general registers\n");
621       add_com ("sr", class_tui, tui_reg_system_command,
622                "Display only special registers\n");
623       add_com ("+r", class_tui, tui_scroll_regs_forward_command,
624                "Scroll the registers window forward\n");
625       add_com ("-r", class_tui, tui_scroll_regs_backward_command,
626                "Scroll the register window backward\n");
627     }
628 }
629
630
631 /*****************************************
632 ** STATIC LOCAL FUNCTIONS                 **
633 ******************************************/
634
635 extern int pagination_enabled;
636
637 static void
638 tui_restore_gdbout (void *ui)
639 {
640   ui_file_delete (gdb_stdout);
641   gdb_stdout = (struct ui_file*) ui;
642   pagination_enabled = 1;
643 }
644
645 /* Get the register from the frame and make a printable representation
646    of it in the data element.  */
647 static void
648 tui_register_format (struct gdbarch *gdbarch, struct frame_info *frame,
649                      struct tui_data_element *data_element, int regnum)
650 {
651   struct ui_file *stream;
652   struct ui_file *old_stdout;
653   const char *name;
654   struct cleanup *cleanups;
655   char *p, *s;
656   int pos;
657   struct type *type = gdbarch_register_type (gdbarch, regnum);
658
659   name = gdbarch_register_name (gdbarch, regnum);
660   if (name == 0)
661     {
662       return;
663     }
664   
665   pagination_enabled = 0;
666   old_stdout = gdb_stdout;
667   stream = tui_sfileopen (256);
668   gdb_stdout = stream;
669   cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
670   if (TYPE_VECTOR (type) != 0 && 0)
671     {
672       char buf[MAX_REGISTER_SIZE];
673       int len;
674
675       len = register_size (current_gdbarch, regnum);
676       fprintf_filtered (stream, "%-14s ", name);
677       get_frame_register (frame, regnum, buf);
678       print_scalar_formatted (buf, type, 'f', len, stream);
679     }
680   else
681     {
682       gdbarch_print_registers_info (current_gdbarch, stream,
683                                     frame, regnum, 1);
684     }
685
686   /* Save formatted output in the buffer.  */
687   p = tui_file_get_strbuf (stream);
688
689   /* Remove the possible \n.  */
690   s = strrchr (p, '\n');
691   if (s && s[1] == 0)
692     *s = 0;
693
694   xfree (data_element->content);
695   data_element->content = xstrdup (p);
696   do_cleanups (cleanups);
697 }
698
699 /* Get the register value from the given frame and format it for
700    the display.  When changep is set, check if the new register value
701    has changed with respect to the previous call.  */
702 static enum tui_status
703 tui_get_register (struct gdbarch *gdbarch, struct frame_info *frame,
704                   struct tui_data_element *data, int regnum, int *changedp)
705 {
706   enum tui_status ret = TUI_FAILURE;
707
708   if (changedp)
709     *changedp = FALSE;
710   if (target_has_registers)
711     {
712       char buf[MAX_REGISTER_SIZE];
713
714       get_frame_register (frame, regnum, buf);
715       /* NOTE: cagney/2003-03-13: This is bogus.  It is refering to
716          the register cache and not the frame which could have pulled
717          the register value off the stack.  */
718       if (register_cached (regnum) >= 0)
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           ret = TUI_SUCCESS;
738         }
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 }