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