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