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