9b396e429e25797298f7327e241e8090066bf733
[deliverable/binutils-gdb.git] / gdb / tui / tui-regs.c
1 /* TUI display registers in window.
2
3 Copyright (C) 1998-2019 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 #include "completer.h"
43
44 #include "gdb_curses.h"
45
46
47 /*****************************************
48 ** STATIC LOCAL FUNCTIONS FORWARD DECLS **
49 ******************************************/
50 static void tui_display_register (struct tui_data_item_window *data);
51
52 static void 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_item_window *data,
58 int regnum, bool *changedp);
59
60
61
62 /*****************************************
63 ** PUBLIC FUNCTIONS **
64 ******************************************/
65
66 /* See tui-data.h. */
67
68 int
69 tui_data_window::last_regs_line_no () const
70 {
71 int num_lines = (-1);
72
73 if (!regs_content.empty ())
74 {
75 num_lines = regs_content.size () / regs_column_count;
76 if (regs_content.size () % regs_column_count)
77 num_lines++;
78 }
79 return num_lines;
80 }
81
82 /* See tui-data.h. */
83
84 int
85 tui_data_window::line_from_reg_element_no (int element_no) const
86 {
87 if (element_no < regs_content.size ())
88 {
89 int i, line = (-1);
90
91 i = 1;
92 while (line == (-1))
93 {
94 if (element_no < regs_column_count * i)
95 line = i - 1;
96 else
97 i++;
98 }
99
100 return line;
101 }
102 else
103 return (-1);
104 }
105
106 /* See tui-data.h. */
107
108 int
109 tui_data_window::first_reg_element_no_inline (int line_no) const
110 {
111 if (line_no * regs_column_count <= regs_content.size ())
112 return ((line_no + 1) * regs_column_count) - regs_column_count;
113 else
114 return (-1);
115 }
116
117
118 /* Show the registers of the given group in the data window
119 and refresh the window. */
120 void
121 tui_show_registers (struct reggroup *group)
122 {
123 enum tui_status ret = TUI_FAILURE;
124
125 /* Make sure the curses mode is enabled. */
126 tui_enable ();
127
128 /* Make sure the register window is visible. If not, select an
129 appropriate layout. */
130 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible)
131 tui_set_layout_by_name (DATA_NAME);
132
133 if (group == 0)
134 group = general_reggroup;
135
136 /* Say that registers should be displayed, even if there is a
137 problem. */
138 TUI_DATA_WIN->display_regs = true;
139
140 if (target_has_registers && target_has_stack && target_has_memory)
141 {
142 tui_show_register_group (group, get_selected_frame (NULL),
143 group == TUI_DATA_WIN->current_group);
144 ret = TUI_SUCCESS;
145 }
146 if (ret == TUI_FAILURE)
147 {
148 TUI_DATA_WIN->current_group = 0;
149 TUI_DATA_WIN->erase_data_content (NO_REGS_STRING);
150 }
151 else
152 {
153 /* Clear all notation of changed values. */
154 for (auto &&data_item_win : TUI_DATA_WIN->regs_content)
155 {
156 if (data_item_win != nullptr)
157 data_item_win->highlight = false;
158 }
159 TUI_DATA_WIN->current_group = group;
160 TUI_DATA_WIN->display_all_data ();
161 }
162 }
163
164
165 /* Set the data window to display the registers of the register group
166 using the given frame. Values are refreshed only when
167 refresh_values_only is TRUE. */
168
169 static void
170 tui_show_register_group (struct reggroup *group,
171 struct frame_info *frame,
172 int refresh_values_only)
173 {
174 struct gdbarch *gdbarch = get_frame_arch (frame);
175 int nr_regs;
176 int regnum, pos;
177 char title[80];
178
179 /* Make a new title showing which group we display. */
180 snprintf (title, sizeof (title) - 1, "Register group: %s",
181 reggroup_name (group));
182 xfree (TUI_DATA_WIN->title);
183 TUI_DATA_WIN->title = xstrdup (title);
184
185 /* See how many registers must be displayed. */
186 nr_regs = 0;
187 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
188 {
189 const char *name;
190
191 /* Must be in the group. */
192 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
193 continue;
194
195 /* If the register name is empty, it is undefined for this
196 processor, so don't display anything. */
197 name = gdbarch_register_name (gdbarch, regnum);
198 if (name == 0 || *name == '\0')
199 continue;
200
201 nr_regs++;
202 }
203
204 if (!refresh_values_only)
205 TUI_DATA_WIN->regs_content.clear ();
206
207 if (nr_regs < TUI_DATA_WIN->regs_content.size ())
208 TUI_DATA_WIN->regs_content.resize (nr_regs);
209 else
210 {
211 for (int i = TUI_DATA_WIN->regs_content.size (); i < nr_regs; ++i)
212 TUI_DATA_WIN->regs_content.emplace_back (new tui_data_item_window ());
213 }
214
215 /* Now set the register names and values. */
216 pos = 0;
217 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
218 {
219 struct tui_data_item_window *data_item_win;
220 const char *name;
221
222 /* Must be in the group. */
223 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
224 continue;
225
226 /* If the register name is empty, it is undefined for this
227 processor, so don't display anything. */
228 name = gdbarch_register_name (gdbarch, regnum);
229 if (name == 0 || *name == '\0')
230 continue;
231
232 data_item_win = TUI_DATA_WIN->regs_content[pos].get ();
233 if (data_item_win)
234 {
235 if (!refresh_values_only)
236 {
237 data_item_win->item_no = regnum;
238 data_item_win->name = name;
239 data_item_win->highlight = false;
240 }
241 tui_get_register (frame, data_item_win, regnum, 0);
242 }
243 pos++;
244 }
245 }
246
247 /* Function to display the registers in the content from
248 'start_element_no' until the end of the register content or the end
249 of the display height. No checking for displaying past the end of
250 the registers is done here. */
251 void
252 tui_display_registers_from (int start_element_no)
253 {
254 if (!TUI_DATA_WIN->regs_content.empty ())
255 {
256 int j, item_win_width, cur_y;
257
258 int max_len = 0;
259 for (auto &&data_item_win : TUI_DATA_WIN->regs_content)
260 {
261 char *p;
262 int len;
263
264 len = 0;
265 p = data_item_win->content;
266 if (p != 0)
267 while (*p)
268 {
269 if (*p++ == '\t')
270 len = 8 * ((len / 8) + 1);
271 else
272 len++;
273 }
274
275 if (len > max_len)
276 max_len = len;
277 }
278 item_win_width = max_len + 1;
279 int i = start_element_no;
280
281 TUI_DATA_WIN->regs_column_count =
282 (TUI_DATA_WIN->width - 2) / item_win_width;
283 if (TUI_DATA_WIN->regs_column_count == 0)
284 TUI_DATA_WIN->regs_column_count = 1;
285 item_win_width =
286 (TUI_DATA_WIN->width - 2) / TUI_DATA_WIN->regs_column_count;
287
288 /* Now create each data "sub" window, and write the display into
289 it. */
290 cur_y = 1;
291 while (i < TUI_DATA_WIN->regs_content.size ()
292 && cur_y <= TUI_DATA_WIN->viewport_height)
293 {
294 for (j = 0;
295 j < TUI_DATA_WIN->regs_column_count
296 && i < TUI_DATA_WIN->regs_content.size ();
297 j++)
298 {
299 struct tui_data_item_window *data_item_win;
300
301 /* Create the window if necessary. */
302 data_item_win = TUI_DATA_WIN->regs_content[i].get ();
303 if (data_item_win->handle != NULL
304 && (data_item_win->height != 1
305 || data_item_win->width != item_win_width
306 || data_item_win->origin.x != (item_win_width * j) + 1
307 || data_item_win->origin.y != cur_y))
308 {
309 tui_delete_win (data_item_win->handle);
310 data_item_win->handle = 0;
311 }
312
313 if (data_item_win->handle == NULL)
314 {
315 data_item_win->height = 1;
316 data_item_win->width = item_win_width;
317 data_item_win->origin.x = (item_win_width * j) + 1;
318 data_item_win->origin.y = cur_y;
319 tui_make_window (data_item_win, DONT_BOX_WINDOW);
320 scrollok (data_item_win->handle, FALSE);
321 }
322 touchwin (data_item_win->handle);
323
324 /* Get the printable representation of the register
325 and display it. */
326 tui_display_register (data_item_win);
327 i++; /* Next register. */
328 }
329 cur_y++; /* Next row. */
330 }
331 }
332 }
333
334
335 /* Function to display the registers in the content from
336 'start_element_no' on 'start_line_no' until the end of the register
337 content or the end of the display height. This function checks
338 that we won't display off the end of the register display. */
339 static void
340 tui_display_reg_element_at_line (int start_element_no,
341 int start_line_no)
342 {
343 if (!TUI_DATA_WIN->regs_content.empty ())
344 {
345 int element_no = start_element_no;
346
347 if (start_element_no != 0 && start_line_no != 0)
348 {
349 int last_line_no, first_line_on_last_page;
350
351 last_line_no = TUI_DATA_WIN->last_regs_line_no ();
352 first_line_on_last_page
353 = last_line_no - (TUI_DATA_WIN->height - 2);
354 if (first_line_on_last_page < 0)
355 first_line_on_last_page = 0;
356
357 /* If the element_no causes us to scroll past the end of the
358 registers, adjust what element to really start the
359 display at. */
360 if (start_line_no > first_line_on_last_page)
361 element_no
362 = (TUI_DATA_WIN->first_reg_element_no_inline
363 (first_line_on_last_page));
364 }
365 tui_display_registers_from (element_no);
366 }
367 }
368
369
370
371 /* Function to display the registers starting at line line_no in the
372 data window. Answers the line number that the display actually
373 started from. If nothing is displayed (-1) is returned. */
374 int
375 tui_display_registers_from_line (int line_no)
376 {
377 tui_check_and_display_highlight_if_needed (TUI_DATA_WIN);
378 if (!TUI_DATA_WIN->regs_content.empty ())
379 {
380 int element_no;
381
382 if (line_no < 0)
383 line_no = 0;
384 else
385 {
386 /* Make sure that we don't display off the end of the
387 registers. */
388 if (line_no >= TUI_DATA_WIN->last_regs_line_no ())
389 {
390 if ((line_no = TUI_DATA_WIN->line_from_reg_element_no (
391 TUI_DATA_WIN->regs_content.size () - 1)) < 0)
392 line_no = 0;
393 }
394 }
395
396 element_no = TUI_DATA_WIN->first_reg_element_no_inline (line_no);
397 if (element_no < TUI_DATA_WIN->regs_content.size ())
398 tui_display_reg_element_at_line (element_no, line_no);
399 else
400 line_no = (-1);
401
402 return line_no;
403 }
404
405 return (-1); /* Nothing was displayed. */
406 }
407
408
409 /* This function check all displayed registers for changes in values,
410 given a particular frame. If the values have changed, they are
411 updated with the new value and highlighted. */
412 void
413 tui_check_register_values (struct frame_info *frame)
414 {
415 if (TUI_DATA_WIN != NULL
416 && TUI_DATA_WIN->is_visible)
417 {
418 if (TUI_DATA_WIN->regs_content.empty ()
419 && TUI_DATA_WIN->display_regs)
420 tui_show_registers (TUI_DATA_WIN->current_group);
421 else
422 {
423 for (auto &&data_item_win_ptr : TUI_DATA_WIN->regs_content)
424 {
425 int was_hilighted;
426
427 was_hilighted = data_item_win_ptr->highlight;
428
429 tui_get_register (frame, data_item_win_ptr.get (),
430 data_item_win_ptr->item_no,
431 &data_item_win_ptr->highlight);
432
433 if (data_item_win_ptr->highlight || was_hilighted)
434 tui_display_register (data_item_win_ptr.get ());
435 }
436 }
437 }
438 }
439
440 /* Display a register in a window. If hilite is TRUE, then the value
441 will be displayed in reverse video. */
442 static void
443 tui_display_register (struct tui_data_item_window *data)
444 {
445 if (data->handle != NULL)
446 {
447 int i;
448
449 if (data->highlight)
450 /* We ignore the return value, casting it to void in order to avoid
451 a compiler warning. The warning itself was introduced by a patch
452 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
453 to code that causes the compiler to generate an unused-value
454 warning. */
455 (void) wstandout (data->handle);
456
457 wmove (data->handle, 0, 0);
458 for (i = 1; i < data->width; i++)
459 waddch (data->handle, ' ');
460 wmove (data->handle, 0, 0);
461 if (data->content)
462 waddstr (data->handle, data->content);
463
464 if (data->highlight)
465 /* We ignore the return value, casting it to void in order to avoid
466 a compiler warning. The warning itself was introduced by a patch
467 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
468 to code that causes the compiler to generate an unused-value
469 warning. */
470 (void) wstandend (data->handle);
471 data->refresh_window ();
472 }
473 }
474
475 /* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
476 around behaviour. Returns the next register group, or NULL if the
477 register window is not currently being displayed. */
478
479 static struct reggroup *
480 tui_reg_next (struct gdbarch *gdbarch)
481 {
482 struct reggroup *group = NULL;
483
484 if (TUI_DATA_WIN != NULL)
485 {
486 group = TUI_DATA_WIN->current_group;
487 group = reggroup_next (gdbarch, group);
488 if (group == NULL)
489 group = reggroup_next (gdbarch, NULL);
490 }
491 return group;
492 }
493
494 /* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
495 around behaviour. Returns the previous register group, or NULL if the
496 register window is not currently being displayed. */
497
498 static struct reggroup *
499 tui_reg_prev (struct gdbarch *gdbarch)
500 {
501 struct reggroup *group = NULL;
502
503 if (TUI_DATA_WIN != NULL)
504 {
505 group = TUI_DATA_WIN->current_group;
506 group = reggroup_prev (gdbarch, group);
507 if (group == NULL)
508 group = reggroup_prev (gdbarch, NULL);
509 }
510 return group;
511 }
512
513 /* Implement the 'tui reg' command. Changes the register group displayed
514 in the tui register window. Displays the tui register window if it is
515 not already on display. */
516
517 static void
518 tui_reg_command (const char *args, int from_tty)
519 {
520 struct gdbarch *gdbarch = get_current_arch ();
521
522 if (args != NULL)
523 {
524 struct reggroup *group, *match = NULL;
525 size_t len = strlen (args);
526
527 /* Make sure the curses mode is enabled. */
528 tui_enable ();
529
530 /* Make sure the register window is visible. If not, select an
531 appropriate layout. We need to do this before trying to run the
532 'next' or 'prev' commands. */
533 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible)
534 tui_set_layout_by_name (DATA_NAME);
535
536 if (strncmp (args, "next", len) == 0)
537 match = tui_reg_next (gdbarch);
538 else if (strncmp (args, "prev", len) == 0)
539 match = tui_reg_prev (gdbarch);
540
541 /* This loop matches on the initial part of a register group
542 name. If this initial part in ARGS matches only one register
543 group then the switch is made. */
544 for (group = reggroup_next (gdbarch, NULL);
545 group != NULL;
546 group = reggroup_next (gdbarch, group))
547 {
548 if (strncmp (reggroup_name (group), args, len) == 0)
549 {
550 if (match != NULL)
551 error (_("ambiguous register group name '%s'"), args);
552 match = group;
553 }
554 }
555
556 if (match == NULL)
557 error (_("unknown register group '%s'"), args);
558
559 tui_show_registers (match);
560 }
561 else
562 {
563 struct reggroup *group;
564 int first;
565
566 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
567 "either a register group,\nor one of 'next' "
568 "or 'prev'. Known register groups are:\n"));
569
570 for (first = 1, group = reggroup_next (gdbarch, NULL);
571 group != NULL;
572 first = 0, group = reggroup_next (gdbarch, group))
573 {
574 if (!first)
575 printf_unfiltered (", ");
576 printf_unfiltered ("%s", reggroup_name (group));
577 }
578
579 printf_unfiltered ("\n");
580 }
581 }
582
583 /* Complete names of register groups, and add the special "prev" and "next"
584 names. */
585
586 static void
587 tui_reggroup_completer (struct cmd_list_element *ignore,
588 completion_tracker &tracker,
589 const char *text, const char *word)
590 {
591 static const char *extra[] = { "next", "prev", NULL };
592 size_t len = strlen (word);
593 const char **tmp;
594
595 reggroup_completer (ignore, tracker, text, word);
596
597 /* XXXX use complete_on_enum instead? */
598 for (tmp = extra; *tmp != NULL; ++tmp)
599 {
600 if (strncmp (word, *tmp, len) == 0)
601 tracker.add_completion (make_unique_xstrdup (*tmp));
602 }
603 }
604
605 void
606 _initialize_tui_regs (void)
607 {
608 struct cmd_list_element **tuicmd, *cmd;
609
610 tuicmd = tui_get_cmd_list ();
611
612 cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
613 TUI command to control the register window."), tuicmd);
614 set_cmd_completer (cmd, tui_reggroup_completer);
615 }
616
617
618 /*****************************************
619 ** STATIC LOCAL FUNCTIONS **
620 ******************************************/
621
622 /* Get the register from the frame and return a printable
623 representation of it. */
624
625 static char *
626 tui_register_format (struct frame_info *frame, int regnum)
627 {
628 struct gdbarch *gdbarch = get_frame_arch (frame);
629
630 string_file stream;
631
632 scoped_restore save_pagination
633 = make_scoped_restore (&pagination_enabled, 0);
634 scoped_restore save_stdout
635 = make_scoped_restore (&gdb_stdout, &stream);
636
637 gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
638
639 /* Remove the possible \n. */
640 std::string &str = stream.string ();
641 if (!str.empty () && str.back () == '\n')
642 str.resize (str.size () - 1);
643
644 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
645 return tui_expand_tabs (str.c_str (), 0);
646 }
647
648 /* Get the register value from the given frame and format it for the
649 display. When changep is set, check if the new register value has
650 changed with respect to the previous call. */
651 static enum tui_status
652 tui_get_register (struct frame_info *frame,
653 struct tui_data_item_window *data,
654 int regnum, bool *changedp)
655 {
656 enum tui_status ret = TUI_FAILURE;
657
658 if (changedp)
659 *changedp = false;
660 if (target_has_registers)
661 {
662 char *prev_content = data->content;
663
664 data->content = tui_register_format (frame, regnum);
665
666 if (changedp != NULL
667 && strcmp (prev_content, data->content) != 0)
668 *changedp = true;
669
670 xfree (prev_content);
671
672 ret = TUI_SUCCESS;
673 }
674 return ret;
675 }
This page took 0.044121 seconds and 4 git commands to generate.