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