Use "bool" in tui_data_window::show_register_group
[deliverable/binutils-gdb.git] / gdb / tui / tui-regs.c
CommitLineData
f377b406 1/* TUI display registers in window.
f33c6cbf 2
42a4f53d 3 Copyright (C) 1998-2019 Free Software Foundation, Inc.
f33c6cbf 4
f377b406 5 Contributed by Hewlett-Packard Company.
c906108c 6
f377b406 7 This file is part of GDB.
c906108c 8
f377b406
SC
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
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
f377b406
SC
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
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
21
22#include "defs.h"
e17c207e 23#include "arch-utils.h"
d7b2e967
AC
24#include "tui/tui.h"
25#include "tui/tui-data.h"
c906108c
SS
26#include "symtab.h"
27#include "gdbtypes.h"
28#include "gdbcmd.h"
29#include "frame.h"
bc77de56 30#include "regcache.h"
c906108c
SS
31#include "inferior.h"
32#include "target.h"
d7b2e967
AC
33#include "tui/tui-layout.h"
34#include "tui/tui-win.h"
d7b2e967
AC
35#include "tui/tui-wingeneral.h"
36#include "tui/tui-file.h"
2c0b251b 37#include "tui/tui-regs.h"
312809f8 38#include "tui/tui-io.h"
10f59415 39#include "reggroups.h"
79a45b7d 40#include "valprint.h"
51f0e40d 41#include "completer.h"
c906108c 42
6a83354a 43#include "gdb_curses.h"
96ec9981 44
1a4f81dd
TT
45/* Get the register from the frame and return a printable
46 representation of it. */
47
b9ad3686 48static gdb::unique_xmalloc_ptr<char>
1a4f81dd
TT
49tui_register_format (struct frame_info *frame, int regnum)
50{
51 struct gdbarch *gdbarch = get_frame_arch (frame);
5eccfcc2 52
1a4f81dd
TT
53 string_file stream;
54
55 scoped_restore save_pagination
56 = make_scoped_restore (&pagination_enabled, 0);
57 scoped_restore save_stdout
58 = make_scoped_restore (&gdb_stdout, &stream);
59
60 gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
61
62 /* Remove the possible \n. */
63 std::string &str = stream.string ();
64 if (!str.empty () && str.back () == '\n')
65 str.resize (str.size () - 1);
66
67 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
b9ad3686 68 return tui_expand_tabs (str.c_str ());
1a4f81dd
TT
69}
70
71/* Get the register value from the given frame and format it for the
72 display. When changep is set, check if the new register value has
73 changed with respect to the previous call. */
74static void
75tui_get_register (struct frame_info *frame,
76 struct tui_data_item_window *data,
77 int regnum, bool *changedp)
78{
79 if (changedp)
80 *changedp = false;
81 if (target_has_registers)
82 {
b9ad3686
TT
83 gdb::unique_xmalloc_ptr<char> new_content
84 = tui_register_format (frame, regnum);
1a4f81dd
TT
85
86 if (changedp != NULL
b9ad3686 87 && strcmp (data->content.get (), new_content.get ()) != 0)
1a4f81dd
TT
88 *changedp = true;
89
b9ad3686 90 data->content = std::move (new_content);
1a4f81dd
TT
91 }
92}
96bd6233
TT
93
94/* See tui-regs.h. */
95
c906108c 96int
0b5ec218 97tui_data_window::last_regs_line_no () const
c906108c 98{
0670413d
TT
99 int num_lines = regs_content.size () / regs_column_count;
100 if (regs_content.size () % regs_column_count)
101 num_lines++;
6ba8e26f 102 return num_lines;
55fb0713 103}
c906108c 104
18ab23af 105/* See tui-regs.h. */
c906108c 106
c906108c 107int
3b23c5f2 108tui_data_window::line_from_reg_element_no (int element_no) const
c906108c 109{
3b23c5f2 110 if (element_no < regs_content.size ())
c906108c
SS
111 {
112 int i, line = (-1);
113
114 i = 1;
115 while (line == (-1))
116 {
3b23c5f2 117 if (element_no < regs_column_count * i)
c906108c
SS
118 line = i - 1;
119 else
120 i++;
121 }
122
123 return line;
124 }
125 else
126 return (-1);
55fb0713 127}
c906108c 128
18ab23af 129/* See tui-regs.h. */
c906108c 130
c906108c 131int
baff0c28 132tui_data_window::first_reg_element_no_inline (int line_no) const
c906108c 133{
baff0c28
TT
134 if (line_no * regs_column_count <= regs_content.size ())
135 return ((line_no + 1) * regs_column_count) - regs_column_count;
c906108c
SS
136 else
137 return (-1);
55fb0713 138}
c906108c 139
10f59415
SC
140/* Show the registers of the given group in the data window
141 and refresh the window. */
c906108c 142void
ca02d7c8 143tui_data_window::show_registers (struct reggroup *group)
c906108c 144{
10f59415
SC
145 if (group == 0)
146 group = general_reggroup;
c906108c 147
10f59415 148 if (target_has_registers && target_has_stack && target_has_memory)
c906108c 149 {
ca02d7c8
TT
150 show_register_group (group, get_selected_frame (NULL),
151 group == current_group);
368c1354 152
1cc6d956 153 /* Clear all notation of changed values. */
ca02d7c8 154 for (auto &&data_item_win : regs_content)
fa4dc567 155 data_item_win.highlight = false;
ca02d7c8 156 current_group = group;
18bb55c7 157 rerender ();
c906108c 158 }
368c1354
TT
159 else
160 {
ca02d7c8
TT
161 current_group = 0;
162 erase_data_content (_("[ Register Values Unavailable ]"));
368c1354 163 }
55fb0713 164}
c906108c
SS
165
166
10f59415 167/* Set the data window to display the registers of the register group
1cc6d956 168 using the given frame. Values are refreshed only when
b5457826 169 refresh_values_only is true. */
10f59415 170
ca02d7c8
TT
171void
172tui_data_window::show_register_group (struct reggroup *group,
173 struct frame_info *frame,
b5457826 174 bool refresh_values_only)
10f59415 175{
5eccfcc2 176 struct gdbarch *gdbarch = get_frame_arch (frame);
10f59415 177 int nr_regs;
10f59415 178 int regnum, pos;
10f59415
SC
179
180 /* Make a new title showing which group we display. */
ab0e1f1a 181 title = string_printf ("Register group: %s", reggroup_name (group));
10f59415
SC
182
183 /* See how many registers must be displayed. */
184 nr_regs = 0;
f6efe3f8 185 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
10f59415 186 {
d20c1c3f
PA
187 const char *name;
188
189 /* Must be in the group. */
190 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
191 continue;
192
193 /* If the register name is empty, it is undefined for this
194 processor, so don't display anything. */
195 name = gdbarch_register_name (gdbarch, regnum);
196 if (name == 0 || *name == '\0')
197 continue;
198
199 nr_regs++;
10f59415
SC
200 }
201
fa4dc567 202 regs_content.resize (nr_regs);
10f59415 203
21e1c91e
TT
204 /* Now set the register names and values. */
205 pos = 0;
206 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
10f59415 207 {
21e1c91e
TT
208 struct tui_data_item_window *data_item_win;
209 const char *name;
10f59415 210
21e1c91e
TT
211 /* Must be in the group. */
212 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
213 continue;
10f59415 214
21e1c91e
TT
215 /* If the register name is empty, it is undefined for this
216 processor, so don't display anything. */
217 name = gdbarch_register_name (gdbarch, regnum);
218 if (name == 0 || *name == '\0')
219 continue;
10f59415 220
fa4dc567 221 data_item_win = &regs_content[pos];
21e1c91e
TT
222 if (data_item_win)
223 {
224 if (!refresh_values_only)
225 {
226 data_item_win->item_no = regnum;
227 data_item_win->name = name;
228 data_item_win->highlight = false;
229 }
230 tui_get_register (frame, data_item_win, regnum, 0);
231 }
232 pos++;
233 }
10f59415
SC
234}
235
18ab23af 236/* See tui-regs.h. */
517e9505 237
c906108c 238void
517e9505 239tui_data_window::display_registers_from (int start_element_no)
c906108c 240{
0670413d
TT
241 int j, item_win_width, cur_y;
242
243 int max_len = 0;
244 for (auto &&data_item_win : regs_content)
c906108c 245 {
0670413d
TT
246 const char *p;
247 int len;
10f59415 248
0670413d
TT
249 len = 0;
250 p = data_item_win.content.get ();
251 if (p != 0)
252 len = strlen (p);
253
254 if (len > max_len)
255 max_len = len;
256 }
257 item_win_width = max_len + 1;
258 int i = start_element_no;
259
260 regs_column_count = (width - 2) / item_win_width;
261 if (regs_column_count == 0)
262 regs_column_count = 1;
263 item_win_width = (width - 2) / regs_column_count;
264
265 /* Now create each data "sub" window, and write the display into
266 it. */
267 cur_y = 1;
268 while (i < regs_content.size ()
269 && cur_y <= viewport_height)
270 {
271 for (j = 0;
272 j < regs_column_count && i < regs_content.size ();
273 j++)
c906108c 274 {
0670413d 275 /* Create the window if necessary. */
cdaa6eb4
TT
276 regs_content[i].resize (1, item_win_width,
277 (item_win_width * j) + 1, cur_y);
0670413d 278 i++; /* Next register. */
c906108c 279 }
0670413d 280 cur_y++; /* Next row. */
c906108c 281 }
55fb0713 282}
c906108c 283
18ab23af 284/* See tui-regs.h. */
c906108c 285
aca2dd16
TT
286void
287tui_data_window::display_reg_element_at_line (int start_element_no,
288 int start_line_no)
c906108c 289{
0670413d 290 int element_no = start_element_no;
c906108c 291
0670413d
TT
292 if (start_element_no != 0 && start_line_no != 0)
293 {
294 int last_line_no, first_line_on_last_page;
295
296 last_line_no = last_regs_line_no ();
297 first_line_on_last_page = last_line_no - (height - 2);
298 if (first_line_on_last_page < 0)
299 first_line_on_last_page = 0;
300
301 /* If the element_no causes us to scroll past the end of the
302 registers, adjust what element to really start the
303 display at. */
304 if (start_line_no > first_line_on_last_page)
305 element_no = first_reg_element_no_inline (first_line_on_last_page);
c906108c 306 }
0670413d 307 display_registers_from (element_no);
6ba8e26f 308}
c906108c 309
18ab23af 310/* See tui-regs.h. */
c906108c 311
c906108c 312int
517e9505 313tui_data_window::display_registers_from_line (int line_no)
c906108c 314{
0670413d
TT
315 int element_no;
316
317 if (line_no < 0)
318 line_no = 0;
319 else
320 {
321 /* Make sure that we don't display off the end of the
322 registers. */
323 if (line_no >= last_regs_line_no ())
80cb6c27 324 {
0670413d
TT
325 line_no = line_from_reg_element_no (regs_content.size () - 1);
326 if (line_no < 0)
327 line_no = 0;
c906108c 328 }
c906108c
SS
329 }
330
0670413d
TT
331 element_no = first_reg_element_no_inline (line_no);
332 if (element_no < regs_content.size ())
333 display_reg_element_at_line (element_no, line_no);
334 else
335 line_no = (-1);
336
337 return line_no;
55fb0713 338}
c906108c
SS
339
340
18ab23af
TT
341/* Answer the index first element displayed. If none are displayed,
342 then return (-1). */
343int
344tui_data_window::first_data_item_displayed ()
345{
346 for (int i = 0; i < regs_content.size (); i++)
347 {
348 struct tui_gen_win_info *data_item_win;
349
fa4dc567 350 data_item_win = &regs_content[i];
2d83e710 351 if (data_item_win->is_visible ())
18ab23af
TT
352 return i;
353 }
354
355 return -1;
356}
357
358/* See tui-regs.h. */
359
360void
361tui_data_window::delete_data_content_windows ()
362{
363 for (auto &&win : regs_content)
364 {
fa4dc567
TT
365 tui_delete_win (win.handle);
366 win.handle = NULL;
18ab23af
TT
367 }
368}
369
370
371void
372tui_data_window::erase_data_content (const char *prompt)
373{
374 werase (handle);
b4ef5aeb 375 check_and_display_highlight_if_needed ();
18ab23af
TT
376 if (prompt != NULL)
377 {
378 int half_width = (width - 2) / 2;
379 int x_pos;
380
381 if (strlen (prompt) >= half_width)
382 x_pos = 1;
383 else
384 x_pos = half_width - strlen (prompt);
385 mvwaddstr (handle, (height / 2), x_pos, (char *) prompt);
386 }
387 wrefresh (handle);
388}
389
390/* See tui-regs.h. */
391
392void
18bb55c7 393tui_data_window::rerender ()
18ab23af
TT
394{
395 if (regs_content.empty ())
1f6d2f10 396 erase_data_content (_("[ Register Values Unavailable ]"));
18ab23af
TT
397 else
398 {
399 erase_data_content (NULL);
400 delete_data_content_windows ();
18ab23af
TT
401 display_registers_from (0);
402 }
403}
404
405
18ab23af
TT
406/* Scroll the data window vertically forward or backward. */
407void
408tui_data_window::do_scroll_vertical (int num_to_scroll)
409{
410 int first_element_no;
411 int first_line = (-1);
412
413 first_element_no = first_data_item_displayed ();
414 if (first_element_no < regs_content.size ())
415 first_line = line_from_reg_element_no (first_element_no);
416 else
417 { /* Calculate the first line from the element number which is in
418 the general data content. */
419 }
420
421 if (first_line >= 0)
422 {
423 first_line += num_to_scroll;
424 erase_data_content (NULL);
425 delete_data_content_windows ();
426 display_registers_from_line (first_line);
427 }
428}
429
430/* See tui-regs.h. */
431
18ab23af
TT
432void
433tui_data_window::refresh_window ()
434{
435 tui_gen_win_info::refresh_window ();
436 for (auto &&win : regs_content)
fa4dc567 437 win.refresh_window ();
18ab23af
TT
438}
439
55fb0713
AC
440/* This function check all displayed registers for changes in values,
441 given a particular frame. If the values have changed, they are
442 updated with the new value and highlighted. */
c906108c 443void
63356bfd 444tui_data_window::check_register_values (struct frame_info *frame)
c906108c 445{
100c2bf3 446 if (regs_content.empty ())
ca02d7c8 447 show_registers (current_group);
63356bfd 448 else
c906108c 449 {
fa4dc567 450 for (auto &&data_item_win : regs_content)
c906108c 451 {
63356bfd 452 int was_hilighted;
c906108c 453
fa4dc567 454 was_hilighted = data_item_win.highlight;
10f59415 455
fa4dc567
TT
456 tui_get_register (frame, &data_item_win,
457 data_item_win.item_no,
458 &data_item_win.highlight);
10f59415 459
fa4dc567 460 if (data_item_win.highlight || was_hilighted)
cdaa6eb4 461 data_item_win.rerender ();
c906108c
SS
462 }
463 }
55fb0713 464}
c906108c 465
1cc6d956
MS
466/* Display a register in a window. If hilite is TRUE, then the value
467 will be displayed in reverse video. */
cdaa6eb4
TT
468void
469tui_data_item_window::rerender ()
10f59415 470{
cdaa6eb4
TT
471 int i;
472
473 scrollok (handle, FALSE);
474 if (highlight)
475 /* We ignore the return value, casting it to void in order to avoid
476 a compiler warning. The warning itself was introduced by a patch
477 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
478 to code that causes the compiler to generate an unused-value
479 warning. */
480 (void) wstandout (handle);
10f59415 481
cdaa6eb4
TT
482 wmove (handle, 0, 0);
483 for (i = 1; i < width; i++)
484 waddch (handle, ' ');
485 wmove (handle, 0, 0);
486 if (content)
487 waddstr (handle, content.get ());
488
489 if (highlight)
490 /* We ignore the return value, casting it to void in order to avoid
491 a compiler warning. The warning itself was introduced by a patch
492 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
493 to code that causes the compiler to generate an unused-value
494 warning. */
495 (void) wstandend (handle);
496 refresh_window ();
497}
498
499void
500tui_data_item_window::refresh_window ()
501{
502 if (handle != nullptr)
503 {
504 /* This seems to be needed because the data items are nested
505 windows, which according to the ncurses man pages aren't well
506 supported. */
507 touchwin (handle);
508 wrefresh (handle);
10f59415
SC
509 }
510}
511
51f0e40d
AB
512/* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
513 around behaviour. Returns the next register group, or NULL if the
514 register window is not currently being displayed. */
515
516static struct reggroup *
fe3eaf1c 517tui_reg_next (struct reggroup *current_group, struct gdbarch *gdbarch)
c906108c 518{
51f0e40d 519 struct reggroup *group = NULL;
e17c207e 520
fe3eaf1c 521 if (current_group != NULL)
10f59415 522 {
fe3eaf1c 523 group = reggroup_next (gdbarch, current_group);
b75c69bb
AB
524 if (group == NULL)
525 group = reggroup_next (gdbarch, NULL);
10f59415 526 }
51f0e40d 527 return group;
10f59415
SC
528}
529
51f0e40d
AB
530/* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
531 around behaviour. Returns the previous register group, or NULL if the
532 register window is not currently being displayed. */
55b40027 533
51f0e40d 534static struct reggroup *
fe3eaf1c 535tui_reg_prev (struct reggroup *current_group, struct gdbarch *gdbarch)
55b40027 536{
51f0e40d 537 struct reggroup *group = NULL;
55b40027 538
fe3eaf1c 539 if (current_group != NULL)
55b40027 540 {
fe3eaf1c 541 group = reggroup_prev (gdbarch, current_group);
55b40027
AB
542 if (group == NULL)
543 group = reggroup_prev (gdbarch, NULL);
55b40027 544 }
51f0e40d 545 return group;
55b40027
AB
546}
547
42cc14a7
TT
548/* A helper function to display the register window in the appropriate
549 way. */
550
551static void
552tui_reg_layout ()
553{
554 enum tui_layout_type cur_layout = tui_current_layout ();
555 enum tui_layout_type new_layout;
556 if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND)
557 new_layout = SRC_DATA_COMMAND;
558 else
559 new_layout = DISASSEM_DATA_COMMAND;
560 tui_set_layout (new_layout);
561}
562
51f0e40d
AB
563/* Implement the 'tui reg' command. Changes the register group displayed
564 in the tui register window. Displays the tui register window if it is
565 not already on display. */
c906108c 566
10f59415 567static void
e2d8ae16 568tui_reg_command (const char *args, int from_tty)
10f59415 569{
51f0e40d 570 struct gdbarch *gdbarch = get_current_arch ();
c906108c 571
51f0e40d
AB
572 if (args != NULL)
573 {
574 struct reggroup *group, *match = NULL;
575 size_t len = strlen (args);
576
577 /* Make sure the curses mode is enabled. */
578 tui_enable ();
579
580 /* Make sure the register window is visible. If not, select an
581 appropriate layout. We need to do this before trying to run the
582 'next' or 'prev' commands. */
2d83e710 583 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible ())
0379b883 584 tui_reg_layout ();
51f0e40d 585
89df7f90 586 struct reggroup *current_group = TUI_DATA_WIN->get_current_group ();
51f0e40d 587 if (strncmp (args, "next", len) == 0)
fe3eaf1c 588 match = tui_reg_next (current_group, gdbarch);
51f0e40d 589 else if (strncmp (args, "prev", len) == 0)
fe3eaf1c 590 match = tui_reg_prev (current_group, gdbarch);
51f0e40d
AB
591
592 /* This loop matches on the initial part of a register group
593 name. If this initial part in ARGS matches only one register
594 group then the switch is made. */
595 for (group = reggroup_next (gdbarch, NULL);
596 group != NULL;
597 group = reggroup_next (gdbarch, group))
598 {
599 if (strncmp (reggroup_name (group), args, len) == 0)
600 {
601 if (match != NULL)
602 error (_("ambiguous register group name '%s'"), args);
603 match = group;
604 }
605 }
606
607 if (match == NULL)
608 error (_("unknown register group '%s'"), args);
609
ca02d7c8 610 TUI_DATA_WIN->show_registers (match);
51f0e40d
AB
611 }
612 else
613 {
614 struct reggroup *group;
615 int first;
616
617 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
618 "either a register group,\nor one of 'next' "
619 "or 'prev'. Known register groups are:\n"));
620
621 for (first = 1, group = reggroup_next (gdbarch, NULL);
622 group != NULL;
623 first = 0, group = reggroup_next (gdbarch, group))
624 {
625 if (!first)
626 printf_unfiltered (", ");
627 printf_unfiltered ("%s", reggroup_name (group));
628 }
629
630 printf_unfiltered ("\n");
631 }
10f59415
SC
632}
633
51f0e40d
AB
634/* Complete names of register groups, and add the special "prev" and "next"
635 names. */
c906108c 636
eb3ff9a5 637static void
51f0e40d 638tui_reggroup_completer (struct cmd_list_element *ignore,
eb3ff9a5 639 completion_tracker &tracker,
51f0e40d 640 const char *text, const char *word)
10f59415 641{
51f0e40d
AB
642 static const char *extra[] = { "next", "prev", NULL };
643 size_t len = strlen (word);
644 const char **tmp;
645
eb3ff9a5 646 reggroup_completer (ignore, tracker, text, word);
51f0e40d 647
eb3ff9a5 648 /* XXXX use complete_on_enum instead? */
51f0e40d
AB
649 for (tmp = extra; *tmp != NULL; ++tmp)
650 {
651 if (strncmp (word, *tmp, len) == 0)
b02f78f9 652 tracker.add_completion (make_unique_xstrdup (*tmp));
51f0e40d 653 }
10f59415 654}
c906108c 655
18ab23af
TT
656void
657_initialize_tui_regs (void)
658{
659 struct cmd_list_element **tuicmd, *cmd;
660
661 tuicmd = tui_get_cmd_list ();
662
663 cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
664TUI command to control the register window."), tuicmd);
665 set_cmd_completer (cmd, tui_reggroup_completer);
666}
This page took 2.368856 seconds and 4 git commands to generate.