gdb, testsuite: Fix return value in gdb.base/foll-fork.exp
[binutils-gdb.git] / gdb / tui / tui-regs.c
blob8db269181237695ab221362e4ccab71cacf10095
1 /* TUI display registers in window.
3 Copyright (C) 1998-2024 Free Software Foundation, Inc.
5 Contributed by Hewlett-Packard Company.
7 This file is part of GDB.
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.
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.
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/>. */
22 #include "arch-utils.h"
23 #include "tui/tui.h"
24 #include "tui/tui-data.h"
25 #include "symtab.h"
26 #include "gdbtypes.h"
27 #include "cli/cli-cmds.h"
28 #include "frame.h"
29 #include "regcache.h"
30 #include "inferior.h"
31 #include "target.h"
32 #include "tui/tui-layout.h"
33 #include "tui/tui-win.h"
34 #include "tui/tui-wingeneral.h"
35 #include "tui/tui-file.h"
36 #include "tui/tui-regs.h"
37 #include "tui/tui-io.h"
38 #include "reggroups.h"
39 #include "valprint.h"
40 #include "completer.h"
42 #include "gdb_curses.h"
44 /* A subclass of string_file that expands tab characters. */
45 class tab_expansion_file : public string_file
47 public:
49 tab_expansion_file () = default;
51 void write (const char *buf, long length_buf) override;
53 private:
55 int m_column = 0;
58 void
59 tab_expansion_file::write (const char *buf, long length_buf)
61 for (long i = 0; i < length_buf; ++i)
63 if (buf[i] == '\t')
67 string_file::write (" ", 1);
68 ++m_column;
70 while ((m_column % 8) != 0);
72 else
74 string_file::write (&buf[i], 1);
75 if (buf[i] == '\n')
76 m_column = 0;
77 else
78 ++m_column;
83 /* Get the register from the frame and return a printable
84 representation of it. */
86 static std::string
87 tui_register_format (const frame_info_ptr &frame, int regnum)
89 struct gdbarch *gdbarch = get_frame_arch (frame);
91 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
92 tab_expansion_file stream;
93 gdbarch_print_registers_info (gdbarch, &stream, frame, regnum, 1);
95 /* Remove the possible \n. */
96 std::string str = stream.release ();
97 if (!str.empty () && str.back () == '\n')
98 str.pop_back ();
100 return str;
103 /* Compute the register value from the given frame and format it for
104 the display. update 'content' and set 'highlight' if the contents
105 changed. */
106 void
107 tui_register_info::update (const frame_info_ptr &frame)
109 std::string new_content = tui_register_format (frame, m_regno);
110 highlight = content != new_content;
111 content = std::move (new_content);
114 /* See tui-regs.h. */
117 tui_data_window::last_regs_line_no () const
119 int num_lines = m_regs_content.size () / m_regs_column_count;
120 if (m_regs_content.size () % m_regs_column_count)
121 num_lines++;
122 return num_lines;
125 /* See tui-regs.h. */
128 tui_data_window::line_from_reg_element_no (int element_no) const
130 if (element_no < m_regs_content.size ())
132 int i, line = (-1);
134 i = 1;
135 while (line == (-1))
137 if (element_no < m_regs_column_count * i)
138 line = i - 1;
139 else
140 i++;
143 return line;
145 else
146 return (-1);
149 /* See tui-regs.h. */
152 tui_data_window::first_reg_element_no_inline (int line_no) const
154 if (line_no * m_regs_column_count <= m_regs_content.size ())
155 return ((line_no + 1) * m_regs_column_count) - m_regs_column_count;
156 else
157 return (-1);
160 /* Show the registers of the given group in the data window
161 and refresh the window. */
162 void
163 tui_data_window::set_register_group (const reggroup *group)
165 update_register_data (group);
166 rerender ();
169 /* Set the data window to display the registers of the register group
170 using the given frame. */
172 void
173 tui_data_window::update_register_data (const reggroup *group)
175 if (group == nullptr)
176 group = general_reggroup;
178 if (!target_has_registers ()
179 || !target_has_stack ()
180 || !target_has_memory ())
182 set_title (_("Registers"));
183 m_current_group = nullptr;
184 m_gdbarch = nullptr;
185 m_regs_content.clear ();
186 return;
189 frame_info_ptr frame = get_selected_frame (nullptr);
190 struct gdbarch *gdbarch = get_frame_arch (frame);
192 if (m_current_group == group && m_gdbarch == gdbarch)
194 /* Nothing to do here. */
195 return;
198 m_current_group = group;
199 m_gdbarch = gdbarch;
201 /* Make a new title showing which group we display. */
202 this->set_title (string_printf ("Register group: %s", group->name ()));
204 /* Create the registers. */
205 m_regs_content.clear ();
207 for (int regnum = 0;
208 regnum < gdbarch_num_cooked_regs (gdbarch);
209 regnum++)
211 /* Must be in the group. */
212 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
213 continue;
215 /* If the register name is empty, it is undefined for this
216 processor, so don't display anything. */
217 const char *name = gdbarch_register_name (gdbarch, regnum);
218 if (*name == '\0')
219 continue;
221 m_regs_content.emplace_back (regnum, frame);
225 /* See tui-regs.h. */
227 void
228 tui_data_window::display_registers_from (int start_element_no)
230 werase (handle.get ());
231 check_and_display_highlight_if_needed ();
233 /* In case the regs window is not boxed, we'll write the last char in the
234 last line here, causing a scroll, so prevent that. */
235 scrollok (handle.get (), FALSE);
237 int max_len = 0;
238 for (auto &&data_item_win : m_regs_content)
240 int len = data_item_win.content.size ();
242 if (len > max_len)
243 max_len = len;
245 m_item_width = max_len + 1;
247 int i;
248 /* Mark register windows above the visible area. */
249 for (i = 0; i < start_element_no; i++)
250 m_regs_content[i].y = 0;
252 m_regs_column_count = (width - box_size ()) / m_item_width;
253 if (m_regs_column_count == 0)
254 m_regs_column_count = 1;
255 m_item_width = (width - box_size ()) / m_regs_column_count;
257 /* Now create each data "sub" window, and write the display into
258 it. */
259 int cur_y = box_width ();
260 while (i < m_regs_content.size () && cur_y <= height - box_size ())
262 for (int j = 0;
263 j < m_regs_column_count && i < m_regs_content.size ();
264 j++)
266 /* Create the window if necessary. */
267 m_regs_content[i].x = box_width () + (m_item_width * j);
268 m_regs_content[i].y = cur_y;
269 m_regs_content[i].rerender (handle.get (), m_item_width);
270 i++; /* Next register. */
272 cur_y++; /* Next row. */
275 /* Mark register windows below the visible area. */
276 for (; i < m_regs_content.size (); i++)
277 m_regs_content[i].y = 0;
279 refresh_window ();
282 /* See tui-regs.h. */
284 void
285 tui_data_window::display_reg_element_at_line (int start_element_no,
286 int start_line_no)
288 int element_no = start_element_no;
290 if (start_element_no != 0 && start_line_no != 0)
292 int last_line_no, first_line_on_last_page;
294 last_line_no = last_regs_line_no ();
295 first_line_on_last_page = last_line_no - (height - box_size ());
296 if (first_line_on_last_page < 0)
297 first_line_on_last_page = 0;
299 /* If the element_no causes us to scroll past the end of the
300 registers, adjust what element to really start the
301 display at. */
302 if (start_line_no > first_line_on_last_page)
303 element_no = first_reg_element_no_inline (first_line_on_last_page);
305 display_registers_from (element_no);
308 /* See tui-regs.h. */
311 tui_data_window::display_registers_from_line (int line_no)
313 int element_no;
315 if (line_no < 0)
316 line_no = 0;
317 else
319 /* Make sure that we don't display off the end of the
320 registers. */
321 if (line_no >= last_regs_line_no ())
323 line_no = line_from_reg_element_no (m_regs_content.size () - 1);
324 if (line_no < 0)
325 line_no = 0;
329 element_no = first_reg_element_no_inline (line_no);
330 if (element_no < m_regs_content.size ())
331 display_reg_element_at_line (element_no, line_no);
332 else
333 line_no = (-1);
335 return line_no;
339 /* Answer the index first element displayed. If none are displayed,
340 then return (-1). */
342 tui_data_window::first_data_item_displayed ()
344 for (int i = 0; i < m_regs_content.size (); i++)
346 if (m_regs_content[i].visible ())
347 return i;
350 return -1;
353 void
354 tui_data_window::erase_data_content ()
356 center_string (_("[ Register Values Unavailable ]"));
359 /* See tui-regs.h. */
361 void
362 tui_data_window::rerender ()
364 if (m_regs_content.empty ())
365 erase_data_content ();
366 else
367 display_registers_from (0);
368 tui_wrefresh (handle.get ());
372 /* Scroll the data window vertically forward or backward. */
373 void
374 tui_data_window::do_scroll_vertical (int num_to_scroll)
376 int first_element_no;
377 int first_line = (-1);
379 first_element_no = first_data_item_displayed ();
380 if (first_element_no < m_regs_content.size ())
381 first_line = line_from_reg_element_no (first_element_no);
382 else
383 { /* Calculate the first line from the element number which is in
384 the general data content. */
387 if (first_line >= 0)
389 first_line += num_to_scroll;
390 display_registers_from_line (first_line);
394 /* This function check all displayed registers for changes in values,
395 given a particular frame. If the values have changed, they are
396 updated with the new value and highlighted. */
397 void
398 tui_data_window::check_register_values (const frame_info_ptr &frame)
400 if (frame == nullptr)
401 set_register_group (nullptr);
402 else
404 /* If the frame architecture changed, we need to reset the
405 register group. */
406 struct gdbarch *gdbarch = get_frame_arch (frame);
407 if (gdbarch != m_gdbarch)
408 set_register_group (nullptr);
409 else
411 for (tui_register_info &data_item_win : m_regs_content)
413 bool was_hilighted = data_item_win.highlight;
415 data_item_win.update (frame);
417 /* Register windows whose y == 0 are outside the visible area. */
418 if ((data_item_win.highlight || was_hilighted)
419 && data_item_win.visible ())
420 data_item_win.rerender (handle.get (), m_item_width);
423 tui_wrefresh (handle.get ());
427 /* Display a register in a window. If hilite is TRUE, then the value
428 will be displayed in reverse video. */
429 void
430 tui_register_info::rerender (WINDOW *handle, int field_width)
432 if (highlight)
433 /* We ignore the return value, casting it to void in order to avoid
434 a compiler warning. The warning itself was introduced by a patch
435 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
436 to code that causes the compiler to generate an unused-value
437 warning. */
438 (void) wstandout (handle);
440 mvwaddnstr (handle, y, x, content.c_str (), field_width - 1);
441 if (content.size () < field_width)
442 waddstr (handle, n_spaces (field_width - content.size ()));
444 if (highlight)
445 /* We ignore the return value, casting it to void in order to avoid
446 a compiler warning. The warning itself was introduced by a patch
447 to ncurses 5.7 dated 2009-08-29, changing this macro to expand
448 to code that causes the compiler to generate an unused-value
449 warning. */
450 (void) wstandend (handle);
453 /* Helper for "tui reg next", returns the next register group after
454 CURRENT_GROUP in the register group list for GDBARCH, with wrap around
455 behaviour.
457 If CURRENT_GROUP is nullptr (e.g. if the tui register window has only
458 just been displayed and has no current group selected) or the currently
459 selected register group can't be found (e.g. if the architecture has
460 changed since the register window was last updated), then the first
461 register group will be returned. */
463 static const reggroup *
464 tui_reg_next (const reggroup *current_group, struct gdbarch *gdbarch)
466 const std::vector<const reggroup *> &groups = gdbarch_reggroups (gdbarch);
467 auto it = std::find (groups.begin (), groups.end (), current_group);
468 if (it != groups.end ())
469 it++;
470 if (it == groups.end ())
471 return groups.front ();
472 return *it;
475 /* Helper for "tui reg prev", returns the register group previous to
476 CURRENT_GROUP in the register group list for GDBARCH, with wrap around
477 behaviour.
479 If CURRENT_GROUP is nullptr (e.g. if the tui register window has only
480 just been displayed and has no current group selected) or the currently
481 selected register group can't be found (e.g. if the architecture has
482 changed since the register window was last updated), then the last
483 register group will be returned. */
485 static const reggroup *
486 tui_reg_prev (const reggroup *current_group, struct gdbarch *gdbarch)
488 const std::vector<const reggroup *> &groups = gdbarch_reggroups (gdbarch);
489 auto it = std::find (groups.rbegin (), groups.rend (), current_group);
490 if (it != groups.rend ())
491 it++;
492 if (it == groups.rend ())
493 return groups.back ();
494 return *it;
497 /* Implement the 'tui reg' command. Changes the register group displayed
498 in the tui register window. Displays the tui register window if it is
499 not already on display. */
501 static void
502 tui_reg_command (const char *args, int from_tty)
504 struct gdbarch *gdbarch = get_current_arch ();
506 if (args != NULL)
508 size_t len = strlen (args);
510 /* Make sure the curses mode is enabled. */
511 tui_enable ();
513 tui_suppress_output suppress;
515 /* Make sure the register window is visible. If not, select an
516 appropriate layout. We need to do this before trying to run the
517 'next' or 'prev' commands. */
518 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible ())
519 tui_regs_layout ();
521 const reggroup *match = nullptr;
522 const reggroup *current_group = TUI_DATA_WIN->get_current_group ();
523 if (strncmp (args, "next", len) == 0)
524 match = tui_reg_next (current_group, gdbarch);
525 else if (strncmp (args, "prev", len) == 0)
526 match = tui_reg_prev (current_group, gdbarch);
527 else
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 (const struct reggroup *group : gdbarch_reggroups (gdbarch))
534 if (strncmp (group->name (), args, len) == 0)
536 if (match != NULL)
537 error (_("ambiguous register group name '%s'"), args);
538 match = group;
543 if (match == NULL)
544 error (_("unknown register group '%s'"), args);
546 TUI_DATA_WIN->set_register_group (match);
548 else
550 gdb_printf (_("\"tui reg\" must be followed by the name of "
551 "either a register group,\nor one of 'next' "
552 "or 'prev'. Known register groups are:\n"));
554 bool first = true;
555 for (const struct reggroup *group : gdbarch_reggroups (gdbarch))
557 if (!first)
558 gdb_printf (", ");
559 first = false;
560 gdb_printf ("%s", group->name ());
563 gdb_printf ("\n");
567 /* Complete names of register groups, and add the special "prev" and "next"
568 names. */
570 static void
571 tui_reggroup_completer (struct cmd_list_element *ignore,
572 completion_tracker &tracker,
573 const char *text, const char *word)
575 static const char * const extra[] = { "next", "prev", NULL };
577 reggroup_completer (ignore, tracker, text, word);
579 complete_on_enum (tracker, extra, text, word);
582 void _initialize_tui_regs ();
583 void
584 _initialize_tui_regs ()
586 struct cmd_list_element **tuicmd, *cmd;
588 tuicmd = tui_get_cmd_list ();
590 cmd = add_cmd ("reg", class_tui, tui_reg_command, _("\
591 TUI command to control the register window.\n\
592 Usage: tui reg NAME\n\
593 NAME is the name of the register group to display"), tuicmd);
594 set_cmd_completer (cmd, tui_reggroup_completer);