Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / gdb / tui / tui-regs.c
CommitLineData
f377b406 1/* TUI display registers in window.
f33c6cbf 2
88b9d363 3 Copyright (C) 1998-2022 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,
dda83cd7 115 struct tui_data_item_window *data,
1a4f81dd
TT
116 int regnum, bool *changedp)
117{
118 if (changedp)
119 *changedp = false;
9dccd06e 120 if (target_has_registers ())
1a4f81dd 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
9dccd06e 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 {
22b7b041 262 data_item_win->regno = regnum;
c9753adb 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 275 int max_len = 0;
80df3337 276 for (auto &&data_item_win : m_regs_content)
c906108c 277 {
7a02bab7 278 int len = data_item_win.content.size ();
0670413d
TT
279
280 if (len > max_len)
281 max_len = len;
282 }
7134f2eb 283 m_item_width = max_len + 1;
4cf28e91
HD
284
285 int i;
286 /* Mark register windows above the visible area. */
287 for (i = 0; i < start_element_no; i++)
288 m_regs_content[i].y = 0;
0670413d 289
7134f2eb 290 m_regs_column_count = (width - 2) / m_item_width;
80df3337
TT
291 if (m_regs_column_count == 0)
292 m_regs_column_count = 1;
7134f2eb 293 m_item_width = (width - 2) / m_regs_column_count;
0670413d
TT
294
295 /* Now create each data "sub" window, and write the display into
296 it. */
7134f2eb 297 int cur_y = 1;
1630140d 298 while (i < m_regs_content.size () && cur_y <= height - 2)
0670413d 299 {
7134f2eb 300 for (int j = 0;
80df3337 301 j < m_regs_column_count && i < m_regs_content.size ();
0670413d 302 j++)
c906108c 303 {
0670413d 304 /* Create the window if necessary. */
7134f2eb
TT
305 m_regs_content[i].x = (m_item_width * j) + 1;
306 m_regs_content[i].y = cur_y;
307 m_regs_content[i].visible = true;
308 m_regs_content[i].rerender (handle.get (), m_item_width);
0670413d 309 i++; /* Next register. */
c906108c 310 }
0670413d 311 cur_y++; /* Next row. */
c906108c 312 }
5fc2d6aa 313
4cf28e91
HD
314 /* Mark register windows below the visible area. */
315 for (; i < m_regs_content.size (); i++)
316 m_regs_content[i].y = 0;
317
5fc2d6aa 318 refresh_window ();
55fb0713 319}
c906108c 320
18ab23af 321/* See tui-regs.h. */
c906108c 322
aca2dd16
TT
323void
324tui_data_window::display_reg_element_at_line (int start_element_no,
325 int start_line_no)
c906108c 326{
0670413d 327 int element_no = start_element_no;
c906108c 328
0670413d
TT
329 if (start_element_no != 0 && start_line_no != 0)
330 {
331 int last_line_no, first_line_on_last_page;
332
333 last_line_no = last_regs_line_no ();
334 first_line_on_last_page = last_line_no - (height - 2);
335 if (first_line_on_last_page < 0)
336 first_line_on_last_page = 0;
337
338 /* If the element_no causes us to scroll past the end of the
339 registers, adjust what element to really start the
340 display at. */
341 if (start_line_no > first_line_on_last_page)
342 element_no = first_reg_element_no_inline (first_line_on_last_page);
c906108c 343 }
0670413d 344 display_registers_from (element_no);
6ba8e26f 345}
c906108c 346
18ab23af 347/* See tui-regs.h. */
c906108c 348
c906108c 349int
517e9505 350tui_data_window::display_registers_from_line (int line_no)
c906108c 351{
0670413d
TT
352 int element_no;
353
354 if (line_no < 0)
355 line_no = 0;
356 else
357 {
358 /* Make sure that we don't display off the end of the
359 registers. */
360 if (line_no >= last_regs_line_no ())
80cb6c27 361 {
80df3337 362 line_no = line_from_reg_element_no (m_regs_content.size () - 1);
0670413d
TT
363 if (line_no < 0)
364 line_no = 0;
c906108c 365 }
c906108c
SS
366 }
367
0670413d 368 element_no = first_reg_element_no_inline (line_no);
80df3337 369 if (element_no < m_regs_content.size ())
0670413d
TT
370 display_reg_element_at_line (element_no, line_no);
371 else
372 line_no = (-1);
373
374 return line_no;
55fb0713 375}
c906108c
SS
376
377
18ab23af
TT
378/* Answer the index first element displayed. If none are displayed,
379 then return (-1). */
380int
381tui_data_window::first_data_item_displayed ()
382{
80df3337 383 for (int i = 0; i < m_regs_content.size (); i++)
18ab23af 384 {
7134f2eb 385 if (m_regs_content[i].visible)
18ab23af
TT
386 return i;
387 }
388
389 return -1;
390}
391
392/* See tui-regs.h. */
393
394void
395tui_data_window::delete_data_content_windows ()
396{
7134f2eb
TT
397 for (auto &win : m_regs_content)
398 win.visible = false;
18ab23af
TT
399}
400
401
402void
403tui_data_window::erase_data_content (const char *prompt)
404{
7523da63 405 werase (handle.get ());
b4ef5aeb 406 check_and_display_highlight_if_needed ();
18ab23af
TT
407 if (prompt != NULL)
408 {
409 int half_width = (width - 2) / 2;
410 int x_pos;
411
412 if (strlen (prompt) >= half_width)
413 x_pos = 1;
414 else
415 x_pos = half_width - strlen (prompt);
7523da63 416 mvwaddstr (handle.get (), (height / 2), x_pos, (char *) prompt);
18ab23af 417 }
45bbae5c 418 tui_wrefresh (handle.get ());
18ab23af
TT
419}
420
421/* See tui-regs.h. */
422
423void
18bb55c7 424tui_data_window::rerender ()
18ab23af 425{
80df3337 426 if (m_regs_content.empty ())
1f6d2f10 427 erase_data_content (_("[ Register Values Unavailable ]"));
18ab23af
TT
428 else
429 {
430 erase_data_content (NULL);
431 delete_data_content_windows ();
18ab23af
TT
432 display_registers_from (0);
433 }
434}
435
436
18ab23af
TT
437/* Scroll the data window vertically forward or backward. */
438void
439tui_data_window::do_scroll_vertical (int num_to_scroll)
440{
441 int first_element_no;
442 int first_line = (-1);
443
444 first_element_no = first_data_item_displayed ();
80df3337 445 if (first_element_no < m_regs_content.size ())
18ab23af
TT
446 first_line = line_from_reg_element_no (first_element_no);
447 else
448 { /* Calculate the first line from the element number which is in
dda83cd7 449 the general data content. */
18ab23af
TT
450 }
451
452 if (first_line >= 0)
453 {
454 first_line += num_to_scroll;
455 erase_data_content (NULL);
456 delete_data_content_windows ();
457 display_registers_from_line (first_line);
458 }
459}
460
55fb0713
AC
461/* This function check all displayed registers for changes in values,
462 given a particular frame. If the values have changed, they are
463 updated with the new value and highlighted. */
c906108c 464void
63356bfd 465tui_data_window::check_register_values (struct frame_info *frame)
c906108c 466{
80df3337
TT
467 if (m_regs_content.empty ())
468 show_registers (m_current_group);
63356bfd 469 else
c906108c 470 {
80df3337 471 for (auto &&data_item_win : m_regs_content)
c906108c 472 {
63356bfd 473 int was_hilighted;
c906108c 474
fa4dc567 475 was_hilighted = data_item_win.highlight;
10f59415 476
fa4dc567 477 tui_get_register (frame, &data_item_win,
22b7b041 478 data_item_win.regno,
fa4dc567 479 &data_item_win.highlight);
10f59415 480
4cf28e91
HD
481 /* Register windows whose y == 0 are outside the visible area. */
482 if ((data_item_win.highlight || was_hilighted)
483 && data_item_win.y > 0)
7134f2eb 484 data_item_win.rerender (handle.get (), m_item_width);
c906108c
SS
485 }
486 }
7134f2eb
TT
487
488 tui_wrefresh (handle.get ());
55fb0713 489}
c906108c 490
1cc6d956
MS
491/* Display a register in a window. If hilite is TRUE, then the value
492 will be displayed in reverse video. */
cdaa6eb4 493void
7134f2eb 494tui_data_item_window::rerender (WINDOW *handle, int field_width)
10f59415 495{
cdaa6eb4
TT
496 if (highlight)
497 /* We ignore the return value, casting it to void in order to avoid
498 a compiler warning. The warning itself was introduced by a patch
499 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
500 to code that causes the compiler to generate an unused-value
501 warning. */
7134f2eb 502 (void) wstandout (handle);
10f59415 503
7134f2eb 504 mvwaddnstr (handle, y, x, content.c_str (), field_width - 1);
3537bc23
HD
505 if (content.size () < field_width)
506 waddstr (handle, n_spaces (field_width - content.size ()));
cdaa6eb4
TT
507
508 if (highlight)
509 /* We ignore the return value, casting it to void in order to avoid
510 a compiler warning. The warning itself was introduced by a patch
511 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
512 to code that causes the compiler to generate an unused-value
513 warning. */
7134f2eb 514 (void) wstandend (handle);
10f59415
SC
515}
516
51f0e40d
AB
517/* Helper for "tui reg next", wraps a call to REGGROUP_NEXT, but adds wrap
518 around behaviour. Returns the next register group, or NULL if the
519 register window is not currently being displayed. */
520
521static struct reggroup *
fe3eaf1c 522tui_reg_next (struct reggroup *current_group, struct gdbarch *gdbarch)
c906108c 523{
51f0e40d 524 struct reggroup *group = NULL;
e17c207e 525
fe3eaf1c 526 if (current_group != NULL)
10f59415 527 {
fe3eaf1c 528 group = reggroup_next (gdbarch, current_group);
b75c69bb 529 if (group == NULL)
dda83cd7 530 group = reggroup_next (gdbarch, NULL);
10f59415 531 }
51f0e40d 532 return group;
10f59415
SC
533}
534
51f0e40d
AB
535/* Helper for "tui reg prev", wraps a call to REGGROUP_PREV, but adds wrap
536 around behaviour. Returns the previous register group, or NULL if the
537 register window is not currently being displayed. */
55b40027 538
51f0e40d 539static struct reggroup *
fe3eaf1c 540tui_reg_prev (struct reggroup *current_group, struct gdbarch *gdbarch)
55b40027 541{
51f0e40d 542 struct reggroup *group = NULL;
55b40027 543
fe3eaf1c 544 if (current_group != NULL)
55b40027 545 {
fe3eaf1c 546 group = reggroup_prev (gdbarch, current_group);
55b40027
AB
547 if (group == NULL)
548 group = reggroup_prev (gdbarch, NULL);
55b40027 549 }
51f0e40d 550 return group;
55b40027
AB
551}
552
51f0e40d
AB
553/* Implement the 'tui reg' command. Changes the register group displayed
554 in the tui register window. Displays the tui register window if it is
555 not already on display. */
c906108c 556
10f59415 557static void
e2d8ae16 558tui_reg_command (const char *args, int from_tty)
10f59415 559{
51f0e40d 560 struct gdbarch *gdbarch = get_current_arch ();
c906108c 561
51f0e40d
AB
562 if (args != NULL)
563 {
564 struct reggroup *group, *match = NULL;
565 size_t len = strlen (args);
566
567 /* Make sure the curses mode is enabled. */
568 tui_enable ();
569
45bbae5c
TT
570 tui_suppress_output suppress;
571
51f0e40d
AB
572 /* Make sure the register window is visible. If not, select an
573 appropriate layout. We need to do this before trying to run the
574 'next' or 'prev' commands. */
2d83e710 575 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible ())
0dbc2fc7 576 tui_regs_layout ();
51f0e40d 577
89df7f90 578 struct reggroup *current_group = TUI_DATA_WIN->get_current_group ();
51f0e40d 579 if (strncmp (args, "next", len) == 0)
fe3eaf1c 580 match = tui_reg_next (current_group, gdbarch);
51f0e40d 581 else if (strncmp (args, "prev", len) == 0)
fe3eaf1c 582 match = tui_reg_prev (current_group, gdbarch);
51f0e40d
AB
583
584 /* This loop matches on the initial part of a register group
585 name. If this initial part in ARGS matches only one register
586 group then the switch is made. */
587 for (group = reggroup_next (gdbarch, NULL);
588 group != NULL;
589 group = reggroup_next (gdbarch, group))
590 {
591 if (strncmp (reggroup_name (group), args, len) == 0)
592 {
593 if (match != NULL)
594 error (_("ambiguous register group name '%s'"), args);
595 match = group;
596 }
597 }
598
599 if (match == NULL)
600 error (_("unknown register group '%s'"), args);
601
ca02d7c8 602 TUI_DATA_WIN->show_registers (match);
51f0e40d
AB
603 }
604 else
605 {
606 struct reggroup *group;
607 int first;
608
609 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
610 "either a register group,\nor one of 'next' "
611 "or 'prev'. Known register groups are:\n"));
612
613 for (first = 1, group = reggroup_next (gdbarch, NULL);
614 group != NULL;
615 first = 0, group = reggroup_next (gdbarch, group))
616 {
617 if (!first)
618 printf_unfiltered (", ");
619 printf_unfiltered ("%s", reggroup_name (group));
620 }
621
622 printf_unfiltered ("\n");
623 }
10f59415
SC
624}
625
51f0e40d
AB
626/* Complete names of register groups, and add the special "prev" and "next"
627 names. */
c906108c 628
eb3ff9a5 629static void
51f0e40d 630tui_reggroup_completer (struct cmd_list_element *ignore,
eb3ff9a5 631 completion_tracker &tracker,
51f0e40d 632 const char *text, const char *word)
10f59415 633{
ea68593b 634 static const char * const extra[] = { "next", "prev", NULL };
51f0e40d 635
eb3ff9a5 636 reggroup_completer (ignore, tracker, text, word);
51f0e40d 637
ea68593b 638 complete_on_enum (tracker, extra, text, word);
10f59415 639}
c906108c 640
6c265988 641void _initialize_tui_regs ();
18ab23af 642void
6c265988 643_initialize_tui_regs ()
18ab23af
TT
644{
645 struct cmd_list_element **tuicmd, *cmd;
646
647 tuicmd = tui_get_cmd_list ();
648
649 cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
283be8bf
TT
650TUI command to control the register window.\n\
651Usage: tui reg NAME\n\
652NAME is the name of the register group to display"), tuicmd);
18ab23af
TT
653 set_cmd_completer (cmd, tui_reggroup_completer);
654}
This page took 3.010781 seconds and 4 git commands to generate.