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