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