gdb/tui: Disassembler scrolling of very small programs
[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
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{
80df3337
TT
99 int num_lines = m_regs_content.size () / m_regs_column_count;
100 if (m_regs_content.size () % m_regs_column_count)
0670413d 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{
80df3337 110 if (element_no < m_regs_content.size ())
c906108c
SS
111 {
112 int i, line = (-1);
113
114 i = 1;
115 while (line == (-1))
116 {
80df3337 117 if (element_no < m_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{
80df3337
TT
134 if (line_no * m_regs_column_count <= m_regs_content.size ())
135 return ((line_no + 1) * m_regs_column_count) - m_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 150 show_register_group (group, get_selected_frame (NULL),
80df3337 151 group == m_current_group);
368c1354 152
1cc6d956 153 /* Clear all notation of changed values. */
80df3337 154 for (auto &&data_item_win : m_regs_content)
fa4dc567 155 data_item_win.highlight = false;
80df3337 156 m_current_group = group;
c906108c 157 }
368c1354
TT
158 else
159 {
80df3337 160 m_current_group = 0;
a31bff9d 161 m_regs_content.clear ();
368c1354 162 }
a31bff9d
TT
163
164 rerender ();
55fb0713 165}
c906108c
SS
166
167
10f59415 168/* Set the data window to display the registers of the register group
1cc6d956 169 using the given frame. Values are refreshed only when
b5457826 170 refresh_values_only is true. */
10f59415 171
ca02d7c8
TT
172void
173tui_data_window::show_register_group (struct reggroup *group,
174 struct frame_info *frame,
b5457826 175 bool refresh_values_only)
10f59415 176{
5eccfcc2 177 struct gdbarch *gdbarch = get_frame_arch (frame);
10f59415 178 int nr_regs;
10f59415 179 int regnum, pos;
10f59415
SC
180
181 /* Make a new title showing which group we display. */
ab0e1f1a 182 title = string_printf ("Register group: %s", reggroup_name (group));
10f59415
SC
183
184 /* See how many registers must be displayed. */
185 nr_regs = 0;
f6efe3f8 186 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
10f59415 187 {
d20c1c3f
PA
188 const char *name;
189
190 /* Must be in the group. */
191 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
192 continue;
193
194 /* If the register name is empty, it is undefined for this
195 processor, so don't display anything. */
196 name = gdbarch_register_name (gdbarch, regnum);
197 if (name == 0 || *name == '\0')
198 continue;
199
200 nr_regs++;
10f59415
SC
201 }
202
80df3337 203 m_regs_content.resize (nr_regs);
10f59415 204
21e1c91e
TT
205 /* Now set the register names and values. */
206 pos = 0;
207 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
10f59415 208 {
21e1c91e
TT
209 struct tui_data_item_window *data_item_win;
210 const char *name;
10f59415 211
21e1c91e
TT
212 /* Must be in the group. */
213 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
214 continue;
10f59415 215
21e1c91e
TT
216 /* If the register name is empty, it is undefined for this
217 processor, so don't display anything. */
218 name = gdbarch_register_name (gdbarch, regnum);
219 if (name == 0 || *name == '\0')
220 continue;
10f59415 221
80df3337 222 data_item_win = &m_regs_content[pos];
21e1c91e
TT
223 if (data_item_win)
224 {
225 if (!refresh_values_only)
226 {
227 data_item_win->item_no = regnum;
228 data_item_win->name = name;
229 data_item_win->highlight = false;
230 }
231 tui_get_register (frame, data_item_win, regnum, 0);
232 }
233 pos++;
234 }
10f59415
SC
235}
236
18ab23af 237/* See tui-regs.h. */
517e9505 238
c906108c 239void
517e9505 240tui_data_window::display_registers_from (int start_element_no)
c906108c 241{
0670413d
TT
242 int j, item_win_width, cur_y;
243
244 int max_len = 0;
80df3337 245 for (auto &&data_item_win : m_regs_content)
c906108c 246 {
0670413d
TT
247 const char *p;
248 int len;
10f59415 249
0670413d
TT
250 len = 0;
251 p = data_item_win.content.get ();
252 if (p != 0)
253 len = strlen (p);
254
255 if (len > max_len)
256 max_len = len;
257 }
258 item_win_width = max_len + 1;
259 int i = start_element_no;
260
80df3337
TT
261 m_regs_column_count = (width - 2) / item_win_width;
262 if (m_regs_column_count == 0)
263 m_regs_column_count = 1;
264 item_win_width = (width - 2) / m_regs_column_count;
0670413d
TT
265
266 /* Now create each data "sub" window, and write the display into
267 it. */
268 cur_y = 1;
1630140d 269 while (i < m_regs_content.size () && cur_y <= height - 2)
0670413d
TT
270 {
271 for (j = 0;
80df3337 272 j < m_regs_column_count && i < m_regs_content.size ();
0670413d 273 j++)
c906108c 274 {
0670413d 275 /* Create the window if necessary. */
80df3337
TT
276 m_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 {
80df3337 325 line_no = line_from_reg_element_no (m_regs_content.size () - 1);
0670413d
TT
326 if (line_no < 0)
327 line_no = 0;
c906108c 328 }
c906108c
SS
329 }
330
0670413d 331 element_no = first_reg_element_no_inline (line_no);
80df3337 332 if (element_no < m_regs_content.size ())
0670413d
TT
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{
80df3337 346 for (int i = 0; i < m_regs_content.size (); i++)
18ab23af
TT
347 {
348 struct tui_gen_win_info *data_item_win;
349
80df3337 350 data_item_win = &m_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{
80df3337 363 for (auto &&win : m_regs_content)
7523da63 364 win.handle.reset (nullptr);
18ab23af
TT
365}
366
367
368void
369tui_data_window::erase_data_content (const char *prompt)
370{
7523da63 371 werase (handle.get ());
b4ef5aeb 372 check_and_display_highlight_if_needed ();
18ab23af
TT
373 if (prompt != NULL)
374 {
375 int half_width = (width - 2) / 2;
376 int x_pos;
377
378 if (strlen (prompt) >= half_width)
379 x_pos = 1;
380 else
381 x_pos = half_width - strlen (prompt);
7523da63 382 mvwaddstr (handle.get (), (height / 2), x_pos, (char *) prompt);
18ab23af 383 }
45bbae5c 384 tui_wrefresh (handle.get ());
18ab23af
TT
385}
386
387/* See tui-regs.h. */
388
389void
18bb55c7 390tui_data_window::rerender ()
18ab23af 391{
80df3337 392 if (m_regs_content.empty ())
1f6d2f10 393 erase_data_content (_("[ Register Values Unavailable ]"));
18ab23af
TT
394 else
395 {
396 erase_data_content (NULL);
397 delete_data_content_windows ();
18ab23af
TT
398 display_registers_from (0);
399 }
400}
401
402
18ab23af
TT
403/* Scroll the data window vertically forward or backward. */
404void
405tui_data_window::do_scroll_vertical (int num_to_scroll)
406{
407 int first_element_no;
408 int first_line = (-1);
409
410 first_element_no = first_data_item_displayed ();
80df3337 411 if (first_element_no < m_regs_content.size ())
18ab23af
TT
412 first_line = line_from_reg_element_no (first_element_no);
413 else
414 { /* Calculate the first line from the element number which is in
415 the general data content. */
416 }
417
418 if (first_line >= 0)
419 {
420 first_line += num_to_scroll;
421 erase_data_content (NULL);
422 delete_data_content_windows ();
423 display_registers_from_line (first_line);
424 }
425}
426
427/* See tui-regs.h. */
428
18ab23af
TT
429void
430tui_data_window::refresh_window ()
431{
432 tui_gen_win_info::refresh_window ();
80df3337 433 for (auto &&win : m_regs_content)
fa4dc567 434 win.refresh_window ();
18ab23af
TT
435}
436
45bbae5c
TT
437void
438tui_data_window::no_refresh ()
439{
440 tui_gen_win_info::no_refresh ();
441 for (auto &&win : m_regs_content)
442 win.no_refresh ();
443}
444
55fb0713
AC
445/* This function check all displayed registers for changes in values,
446 given a particular frame. If the values have changed, they are
447 updated with the new value and highlighted. */
c906108c 448void
63356bfd 449tui_data_window::check_register_values (struct frame_info *frame)
c906108c 450{
80df3337
TT
451 if (m_regs_content.empty ())
452 show_registers (m_current_group);
63356bfd 453 else
c906108c 454 {
80df3337 455 for (auto &&data_item_win : m_regs_content)
c906108c 456 {
63356bfd 457 int was_hilighted;
c906108c 458
fa4dc567 459 was_hilighted = data_item_win.highlight;
10f59415 460
fa4dc567
TT
461 tui_get_register (frame, &data_item_win,
462 data_item_win.item_no,
463 &data_item_win.highlight);
10f59415 464
fa4dc567 465 if (data_item_win.highlight || was_hilighted)
cdaa6eb4 466 data_item_win.rerender ();
c906108c
SS
467 }
468 }
55fb0713 469}
c906108c 470
1cc6d956
MS
471/* Display a register in a window. If hilite is TRUE, then the value
472 will be displayed in reverse video. */
cdaa6eb4
TT
473void
474tui_data_item_window::rerender ()
10f59415 475{
cdaa6eb4
TT
476 int i;
477
7523da63 478 scrollok (handle.get (), FALSE);
cdaa6eb4
TT
479 if (highlight)
480 /* We ignore the return value, casting it to void in order to avoid
481 a compiler warning. The warning itself was introduced by a patch
482 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
483 to code that causes the compiler to generate an unused-value
484 warning. */
7523da63 485 (void) wstandout (handle.get ());
10f59415 486
7523da63 487 wmove (handle.get (), 0, 0);
cdaa6eb4 488 for (i = 1; i < width; i++)
7523da63
TT
489 waddch (handle.get (), ' ');
490 wmove (handle.get (), 0, 0);
cdaa6eb4 491 if (content)
7523da63 492 waddstr (handle.get (), content.get ());
cdaa6eb4
TT
493
494 if (highlight)
495 /* We ignore the return value, casting it to void in order to avoid
496 a compiler warning. The warning itself was introduced by a patch
497 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
498 to code that causes the compiler to generate an unused-value
499 warning. */
7523da63 500 (void) wstandend (handle.get ());
cdaa6eb4
TT
501 refresh_window ();
502}
503
504void
505tui_data_item_window::refresh_window ()
506{
507 if (handle != nullptr)
508 {
509 /* This seems to be needed because the data items are nested
510 windows, which according to the ncurses man pages aren't well
511 supported. */
7523da63 512 touchwin (handle.get ());
45bbae5c 513 tui_wrefresh (handle.get ());
10f59415
SC
514 }
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
AB
529 if (group == NULL)
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
42cc14a7
TT
553/* A helper function to display the register window in the appropriate
554 way. */
555
556static void
557tui_reg_layout ()
558{
559 enum tui_layout_type cur_layout = tui_current_layout ();
560 enum tui_layout_type new_layout;
561 if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND)
562 new_layout = SRC_DATA_COMMAND;
563 else
564 new_layout = DISASSEM_DATA_COMMAND;
565 tui_set_layout (new_layout);
566}
567
51f0e40d
AB
568/* Implement the 'tui reg' command. Changes the register group displayed
569 in the tui register window. Displays the tui register window if it is
570 not already on display. */
c906108c 571
10f59415 572static void
e2d8ae16 573tui_reg_command (const char *args, int from_tty)
10f59415 574{
51f0e40d 575 struct gdbarch *gdbarch = get_current_arch ();
c906108c 576
51f0e40d
AB
577 if (args != NULL)
578 {
579 struct reggroup *group, *match = NULL;
580 size_t len = strlen (args);
581
582 /* Make sure the curses mode is enabled. */
583 tui_enable ();
584
45bbae5c
TT
585 tui_suppress_output suppress;
586
51f0e40d
AB
587 /* Make sure the register window is visible. If not, select an
588 appropriate layout. We need to do this before trying to run the
589 'next' or 'prev' commands. */
2d83e710 590 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible ())
0379b883 591 tui_reg_layout ();
51f0e40d 592
89df7f90 593 struct reggroup *current_group = TUI_DATA_WIN->get_current_group ();
51f0e40d 594 if (strncmp (args, "next", len) == 0)
fe3eaf1c 595 match = tui_reg_next (current_group, gdbarch);
51f0e40d 596 else if (strncmp (args, "prev", len) == 0)
fe3eaf1c 597 match = tui_reg_prev (current_group, gdbarch);
51f0e40d
AB
598
599 /* This loop matches on the initial part of a register group
600 name. If this initial part in ARGS matches only one register
601 group then the switch is made. */
602 for (group = reggroup_next (gdbarch, NULL);
603 group != NULL;
604 group = reggroup_next (gdbarch, group))
605 {
606 if (strncmp (reggroup_name (group), args, len) == 0)
607 {
608 if (match != NULL)
609 error (_("ambiguous register group name '%s'"), args);
610 match = group;
611 }
612 }
613
614 if (match == NULL)
615 error (_("unknown register group '%s'"), args);
616
ca02d7c8 617 TUI_DATA_WIN->show_registers (match);
51f0e40d
AB
618 }
619 else
620 {
621 struct reggroup *group;
622 int first;
623
624 printf_unfiltered (_("\"tui reg\" must be followed by the name of "
625 "either a register group,\nor one of 'next' "
626 "or 'prev'. Known register groups are:\n"));
627
628 for (first = 1, group = reggroup_next (gdbarch, NULL);
629 group != NULL;
630 first = 0, group = reggroup_next (gdbarch, group))
631 {
632 if (!first)
633 printf_unfiltered (", ");
634 printf_unfiltered ("%s", reggroup_name (group));
635 }
636
637 printf_unfiltered ("\n");
638 }
10f59415
SC
639}
640
51f0e40d
AB
641/* Complete names of register groups, and add the special "prev" and "next"
642 names. */
c906108c 643
eb3ff9a5 644static void
51f0e40d 645tui_reggroup_completer (struct cmd_list_element *ignore,
eb3ff9a5 646 completion_tracker &tracker,
51f0e40d 647 const char *text, const char *word)
10f59415 648{
51f0e40d
AB
649 static const char *extra[] = { "next", "prev", NULL };
650 size_t len = strlen (word);
651 const char **tmp;
652
eb3ff9a5 653 reggroup_completer (ignore, tracker, text, word);
51f0e40d 654
eb3ff9a5 655 /* XXXX use complete_on_enum instead? */
51f0e40d
AB
656 for (tmp = extra; *tmp != NULL; ++tmp)
657 {
658 if (strncmp (word, *tmp, len) == 0)
b02f78f9 659 tracker.add_completion (make_unique_xstrdup (*tmp));
51f0e40d 660 }
10f59415 661}
c906108c 662
6c265988 663void _initialize_tui_regs ();
18ab23af 664void
6c265988 665_initialize_tui_regs ()
18ab23af
TT
666{
667 struct cmd_list_element **tuicmd, *cmd;
668
669 tuicmd = tui_get_cmd_list ();
670
671 cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
672TUI command to control the register window."), tuicmd);
673 set_cmd_completer (cmd, tui_reggroup_completer);
674}
This page took 2.075837 seconds and 4 git commands to generate.