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