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