]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/tui/tui-regs.c
* tui/tui-regs.c (tui_register_format): Remove dead code.
[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 2010, 2011 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 = &((struct tui_win_element *)
286 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, 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
335 = &display_info->regs_content[i]->which_element.data_window;
336 data = &((struct tui_win_element *)
337 data_item_win->content[0])->which_element.data;
338 len = 0;
339 p = data->content;
340 if (p != 0)
341 while (*p)
342 {
343 if (*p++ == '\t')
344 len = 8 * ((len / 8) + 1);
345 else
346 len++;
347 }
348
349 if (len > max_len)
350 max_len = len;
351 }
352 item_win_width = max_len + 1;
353 i = start_element_no;
354
355 display_info->regs_column_count =
356 (TUI_DATA_WIN->generic.width - 2) / item_win_width;
357 if (display_info->regs_column_count == 0)
358 display_info->regs_column_count = 1;
359 item_win_width =
360 (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count;
361
362 /* Now create each data "sub" window, and write the display into
363 it. */
364 cur_y = 1;
365 while (i < display_info->regs_content_count
366 && cur_y <= TUI_DATA_WIN->generic.viewport_height)
367 {
368 for (j = 0;
369 j < display_info->regs_column_count
370 && i < display_info->regs_content_count;
371 j++)
372 {
373 struct tui_gen_win_info *data_item_win;
374 struct tui_data_element *data_element_ptr;
375
376 /* Create the window if necessary. */
377 data_item_win = &display_info->regs_content[i]
378 ->which_element.data_window;
379 data_element_ptr = &((struct tui_win_element *)
380 data_item_win->content[0])->which_element.data;
381 if (data_item_win->handle != (WINDOW*) NULL
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 {
387 tui_delete_win (data_item_win->handle);
388 data_item_win->handle = 0;
389 }
390
391 if (data_item_win->handle == (WINDOW *) NULL)
392 {
393 data_item_win->height = 1;
394 data_item_win->width = item_win_width;
395 data_item_win->origin.x = (item_win_width * j) + 1;
396 data_item_win->origin.y = cur_y;
397 tui_make_window (data_item_win, DONT_BOX_WINDOW);
398 scrollok (data_item_win->handle, FALSE);
399 }
400 touchwin (data_item_win->handle);
401
402 /* Get the printable representation of the register
403 and display it. */
404 tui_display_register (data_element_ptr, data_item_win);
405 i++; /* Next register. */
406 }
407 cur_y++; /* Next row. */
408 }
409 }
410 }
411
412
413 /* Function to display the registers in the content from
414 'start_element_no' on 'start_line_no' until the end of the register
415 content or the end of the display height. This function checks
416 that we won't display off the end of the register display. */
417 static void
418 tui_display_reg_element_at_line (int start_element_no,
419 int start_line_no)
420 {
421 if (TUI_DATA_WIN->detail.data_display_info.regs_content
422 != (tui_win_content) NULL
423 && TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
424 {
425 int element_no = start_element_no;
426
427 if (start_element_no != 0 && start_line_no != 0)
428 {
429 int last_line_no, first_line_on_last_page;
430
431 last_line_no = tui_last_regs_line_no ();
432 first_line_on_last_page
433 = 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
444 = tui_first_reg_element_no_inline (first_line_on_last_page);
445 }
446 tui_display_registers_from (element_no);
447 }
448 }
449
450
451
452 /* Function to display the registers starting at line line_no in the
453 data window. Answers the line number that the display actually
454 started from. If nothing is displayed (-1) is returned. */
455 int
456 tui_display_registers_from_line (int line_no,
457 int force_display)
458 {
459 if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
460 {
461 int line, element_no;
462
463 if (line_no < 0)
464 line = 0;
465 else if (force_display)
466 { /* If we must display regs (force_display is true), then
467 make sure that we don't display off the end of the
468 registers. */
469 if (line_no >= tui_last_regs_line_no ())
470 {
471 if ((line = tui_line_from_reg_element_no (
472 TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
473 line = 0;
474 }
475 else
476 line = line_no;
477 }
478 else
479 line = line_no;
480
481 element_no = tui_first_reg_element_no_inline (line);
482 if (element_no
483 < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
484 tui_display_reg_element_at_line (element_no, line);
485 else
486 line = (-1);
487
488 return line;
489 }
490
491 return (-1); /* Nothing was displayed. */
492 }
493
494
495 /* This function check all displayed registers for changes in values,
496 given a particular frame. If the values have changed, they are
497 updated with the new value and highlighted. */
498 void
499 tui_check_register_values (struct frame_info *frame)
500 {
501 if (TUI_DATA_WIN != NULL
502 && TUI_DATA_WIN->generic.is_visible)
503 {
504 struct tui_data_info *display_info
505 = &TUI_DATA_WIN->detail.data_display_info;
506
507 if (display_info->regs_content_count <= 0
508 && display_info->display_regs)
509 tui_show_registers (display_info->current_group);
510 else
511 {
512 int i;
513
514 for (i = 0; (i < display_info->regs_content_count); i++)
515 {
516 struct tui_data_element *data;
517 struct tui_gen_win_info *data_item_win_ptr;
518 int was_hilighted;
519
520 data_item_win_ptr = &display_info->regs_content[i]->
521 which_element.data_window;
522 data = &((struct tui_win_element *)
523 data_item_win_ptr->content[0])->which_element.data;
524 was_hilighted = data->highlight;
525
526 tui_get_register (frame, data,
527 data->item_no, &data->highlight);
528
529 if (data->highlight || was_hilighted)
530 {
531 tui_display_register (data, data_item_win_ptr);
532 }
533 }
534 }
535 }
536 }
537
538 /* Display a register in a window. If hilite is TRUE, then the value
539 will be displayed in reverse video. */
540 static void
541 tui_display_register (struct tui_data_element *data,
542 struct tui_gen_win_info *win_info)
543 {
544 if (win_info->handle != (WINDOW *) NULL)
545 {
546 int i;
547
548 if (data->highlight)
549 /* We ignore the return value, casting it to void in order to avoid
550 a compiler warning. The warning itself was introduced by a patch
551 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
552 to code that causes the compiler to generate an unused-value
553 warning. */
554 (void) wstandout (win_info->handle);
555
556 wmove (win_info->handle, 0, 0);
557 for (i = 1; i < win_info->width; i++)
558 waddch (win_info->handle, ' ');
559 wmove (win_info->handle, 0, 0);
560 if (data->content)
561 waddstr (win_info->handle, data->content);
562
563 if (data->highlight)
564 /* We ignore the return value, casting it to void in order to avoid
565 a compiler warning. The warning itself was introduced by a patch
566 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
567 to code that causes the compiler to generate an unused-value
568 warning. */
569 (void) wstandend (win_info->handle);
570 tui_refresh_win (win_info);
571 }
572 }
573
574 static void
575 tui_reg_next_command (char *arg, int from_tty)
576 {
577 struct gdbarch *gdbarch = get_current_arch ();
578
579 if (TUI_DATA_WIN != 0)
580 {
581 struct reggroup *group
582 = TUI_DATA_WIN->detail.data_display_info.current_group;
583
584 group = reggroup_next (gdbarch, group);
585 if (group == 0)
586 group = reggroup_next (gdbarch, 0);
587
588 if (group)
589 tui_show_registers (group);
590 }
591 }
592
593 static void
594 tui_reg_float_command (char *arg, int from_tty)
595 {
596 tui_show_registers (float_reggroup);
597 }
598
599 static void
600 tui_reg_general_command (char *arg, int from_tty)
601 {
602 tui_show_registers (general_reggroup);
603 }
604
605 static void
606 tui_reg_system_command (char *arg, int from_tty)
607 {
608 tui_show_registers (system_reggroup);
609 }
610
611 static struct cmd_list_element *tuireglist;
612
613 static void
614 tui_reg_command (char *args, int from_tty)
615 {
616 printf_unfiltered (_("\"tui reg\" must be followed by the name of a "
617 "tui reg command.\n"));
618 help_list (tuireglist, "tui reg ", -1, gdb_stdout);
619 }
620
621 /* Provide a prototype to silence -Wmissing-prototypes. */
622 extern initialize_file_ftype _initialize_tui_regs;
623
624 void
625 _initialize_tui_regs (void)
626 {
627 struct cmd_list_element **tuicmd;
628
629 tuicmd = tui_get_cmd_list ();
630
631 add_prefix_cmd ("reg", class_tui, tui_reg_command,
632 _("TUI commands to control the register window."),
633 &tuireglist, "tui reg ", 0,
634 tuicmd);
635
636 add_cmd ("float", class_tui, tui_reg_float_command,
637 _("Display only floating point registers."),
638 &tuireglist);
639 add_cmd ("general", class_tui, tui_reg_general_command,
640 _("Display only general registers."),
641 &tuireglist);
642 add_cmd ("system", class_tui, tui_reg_system_command,
643 _("Display only system registers."),
644 &tuireglist);
645 add_cmd ("next", class_tui, tui_reg_next_command,
646 _("Display next register group."),
647 &tuireglist);
648
649 if (xdb_commands)
650 {
651 add_com ("fr", class_tui, tui_reg_float_command,
652 _("Display only floating point registers\n"));
653 add_com ("gr", class_tui, tui_reg_general_command,
654 _("Display only general registers\n"));
655 add_com ("sr", class_tui, tui_reg_system_command,
656 _("Display only special registers\n"));
657 add_com ("+r", class_tui, tui_scroll_regs_forward_command,
658 _("Scroll the registers window forward\n"));
659 add_com ("-r", class_tui, tui_scroll_regs_backward_command,
660 _("Scroll the register window backward\n"));
661 }
662 }
663
664
665 /*****************************************
666 ** STATIC LOCAL FUNCTIONS **
667 ******************************************/
668
669 extern int pagination_enabled;
670
671 static void
672 tui_restore_gdbout (void *ui)
673 {
674 ui_file_delete (gdb_stdout);
675 gdb_stdout = (struct ui_file*) ui;
676 pagination_enabled = 1;
677 }
678
679 /* Get the register from the frame and make a printable representation
680 of it in the data element. */
681 static void
682 tui_register_format (struct frame_info *frame,
683 struct tui_data_element *data_element,
684 int regnum)
685 {
686 struct gdbarch *gdbarch = get_frame_arch (frame);
687 struct ui_file *stream;
688 struct ui_file *old_stdout;
689 const char *name;
690 struct cleanup *cleanups;
691 char *p, *s;
692 struct type *type = register_type (gdbarch, regnum);
693
694 name = gdbarch_register_name (gdbarch, regnum);
695 if (name == 0)
696 {
697 return;
698 }
699
700 pagination_enabled = 0;
701 old_stdout = gdb_stdout;
702 stream = tui_sfileopen (256);
703 gdb_stdout = stream;
704 cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
705 gdbarch_print_registers_info (gdbarch, stream, frame, regnum, 1);
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 frame_info *frame,
725 struct tui_data_element *data,
726 int regnum, int *changedp)
727 {
728 enum tui_status ret = TUI_FAILURE;
729
730 if (changedp)
731 *changedp = FALSE;
732 if (target_has_registers)
733 {
734 gdb_byte buf[MAX_REGISTER_SIZE];
735
736 get_frame_register (frame, regnum, buf);
737 if (changedp)
738 {
739 struct gdbarch *gdbarch = get_frame_arch (frame);
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 (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 }