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