Remove useless "if' from tui-regs.c
[deliverable/binutils-gdb.git] / gdb / tui / tui-regs.c
1 /* TUI display registers in window.
2
3 Copyright (C) 1998-2020 Free Software Foundation, Inc.
4
5 Contributed by Hewlett-Packard Company.
6
7 This file is part of GDB.
8
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.
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
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22 #include "defs.h"
23 #include "arch-utils.h"
24 #include "tui/tui.h"
25 #include "tui/tui-data.h"
26 #include "symtab.h"
27 #include "gdbtypes.h"
28 #include "gdbcmd.h"
29 #include "frame.h"
30 #include "regcache.h"
31 #include "inferior.h"
32 #include "target.h"
33 #include "tui/tui-layout.h"
34 #include "tui/tui-win.h"
35 #include "tui/tui-wingeneral.h"
36 #include "tui/tui-file.h"
37 #include "tui/tui-regs.h"
38 #include "tui/tui-io.h"
39 #include "reggroups.h"
40 #include "valprint.h"
41 #include "completer.h"
42
43 #include "gdb_curses.h"
44
45 /* A subclass of string_file that expands tab characters. */
46 class tab_expansion_file : public string_file
47 {
48 public:
49
50 tab_expansion_file () = default;
51
52 void write (const char *buf, long length_buf) override;
53
54 private:
55
56 int m_column = 0;
57 };
58
59 void
60 tab_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
84 /* Get the register from the frame and return a printable
85 representation of it. */
86
87 static std::string
88 tui_register_format (struct frame_info *frame, int regnum)
89 {
90 struct gdbarch *gdbarch = get_frame_arch (frame);
91
92 /* Expand tabs into spaces, since ncurses on MS-Windows doesn't. */
93 tab_expansion_file stream;
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
107 return str;
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. */
113 static void
114 tui_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 {
122 std::string new_content = tui_register_format (frame, regnum);
123
124 if (changedp != NULL && data->content != new_content)
125 *changedp = true;
126
127 data->content = std::move (new_content);
128 }
129 }
130
131 /* See tui-regs.h. */
132
133 int
134 tui_data_window::last_regs_line_no () const
135 {
136 int num_lines = m_regs_content.size () / m_regs_column_count;
137 if (m_regs_content.size () % m_regs_column_count)
138 num_lines++;
139 return num_lines;
140 }
141
142 /* See tui-regs.h. */
143
144 int
145 tui_data_window::line_from_reg_element_no (int element_no) const
146 {
147 if (element_no < m_regs_content.size ())
148 {
149 int i, line = (-1);
150
151 i = 1;
152 while (line == (-1))
153 {
154 if (element_no < m_regs_column_count * i)
155 line = i - 1;
156 else
157 i++;
158 }
159
160 return line;
161 }
162 else
163 return (-1);
164 }
165
166 /* See tui-regs.h. */
167
168 int
169 tui_data_window::first_reg_element_no_inline (int line_no) const
170 {
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;
173 else
174 return (-1);
175 }
176
177 /* Show the registers of the given group in the data window
178 and refresh the window. */
179 void
180 tui_data_window::show_registers (struct reggroup *group)
181 {
182 if (group == 0)
183 group = general_reggroup;
184
185 if (target_has_registers && target_has_stack && target_has_memory)
186 {
187 show_register_group (group, get_selected_frame (NULL),
188 group == m_current_group);
189
190 /* Clear all notation of changed values. */
191 for (auto &&data_item_win : m_regs_content)
192 data_item_win.highlight = false;
193 m_current_group = group;
194 }
195 else
196 {
197 m_current_group = 0;
198 m_regs_content.clear ();
199 }
200
201 rerender ();
202 }
203
204
205 /* Set the data window to display the registers of the register group
206 using the given frame. Values are refreshed only when
207 refresh_values_only is true. */
208
209 void
210 tui_data_window::show_register_group (struct reggroup *group,
211 struct frame_info *frame,
212 bool refresh_values_only)
213 {
214 struct gdbarch *gdbarch = get_frame_arch (frame);
215 int nr_regs;
216 int regnum, pos;
217
218 /* Make a new title showing which group we display. */
219 title = string_printf ("Register group: %s", reggroup_name (group));
220
221 /* See how many registers must be displayed. */
222 nr_regs = 0;
223 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
224 {
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++;
238 }
239
240 m_regs_content.resize (nr_regs);
241
242 /* Now set the register names and values. */
243 pos = 0;
244 for (regnum = 0; regnum < gdbarch_num_cooked_regs (gdbarch); regnum++)
245 {
246 struct tui_data_item_window *data_item_win;
247 const char *name;
248
249 /* Must be in the group. */
250 if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
251 continue;
252
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;
258
259 data_item_win = &m_regs_content[pos];
260 if (!refresh_values_only)
261 {
262 data_item_win->item_no = regnum;
263 data_item_win->highlight = false;
264 }
265 tui_get_register (frame, data_item_win, regnum, 0);
266 pos++;
267 }
268 }
269
270 /* See tui-regs.h. */
271
272 void
273 tui_data_window::display_registers_from (int start_element_no)
274 {
275 int j, item_win_width, cur_y;
276
277 int max_len = 0;
278 for (auto &&data_item_win : m_regs_content)
279 {
280 int len = data_item_win.content.size ();
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
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;
292
293 /* Now create each data "sub" window, and write the display into
294 it. */
295 cur_y = 1;
296 while (i < m_regs_content.size () && cur_y <= height - 2)
297 {
298 for (j = 0;
299 j < m_regs_column_count && i < m_regs_content.size ();
300 j++)
301 {
302 /* Create the window if necessary. */
303 m_regs_content[i].resize (1, item_win_width,
304 x + (item_win_width * j) + 1, y + cur_y);
305 i++; /* Next register. */
306 }
307 cur_y++; /* Next row. */
308 }
309 }
310
311 /* See tui-regs.h. */
312
313 void
314 tui_data_window::display_reg_element_at_line (int start_element_no,
315 int start_line_no)
316 {
317 int element_no = start_element_no;
318
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);
333 }
334 display_registers_from (element_no);
335 }
336
337 /* See tui-regs.h. */
338
339 int
340 tui_data_window::display_registers_from_line (int line_no)
341 {
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 ())
351 {
352 line_no = line_from_reg_element_no (m_regs_content.size () - 1);
353 if (line_no < 0)
354 line_no = 0;
355 }
356 }
357
358 element_no = first_reg_element_no_inline (line_no);
359 if (element_no < m_regs_content.size ())
360 display_reg_element_at_line (element_no, line_no);
361 else
362 line_no = (-1);
363
364 return line_no;
365 }
366
367
368 /* Answer the index first element displayed. If none are displayed,
369 then return (-1). */
370 int
371 tui_data_window::first_data_item_displayed ()
372 {
373 for (int i = 0; i < m_regs_content.size (); i++)
374 {
375 struct tui_gen_win_info *data_item_win;
376
377 data_item_win = &m_regs_content[i];
378 if (data_item_win->is_visible ())
379 return i;
380 }
381
382 return -1;
383 }
384
385 /* See tui-regs.h. */
386
387 void
388 tui_data_window::delete_data_content_windows ()
389 {
390 for (auto &&win : m_regs_content)
391 win.handle.reset (nullptr);
392 }
393
394
395 void
396 tui_data_window::erase_data_content (const char *prompt)
397 {
398 werase (handle.get ());
399 check_and_display_highlight_if_needed ();
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);
409 mvwaddstr (handle.get (), (height / 2), x_pos, (char *) prompt);
410 }
411 tui_wrefresh (handle.get ());
412 }
413
414 /* See tui-regs.h. */
415
416 void
417 tui_data_window::rerender ()
418 {
419 if (m_regs_content.empty ())
420 erase_data_content (_("[ Register Values Unavailable ]"));
421 else
422 {
423 erase_data_content (NULL);
424 delete_data_content_windows ();
425 display_registers_from (0);
426 }
427 }
428
429
430 /* Scroll the data window vertically forward or backward. */
431 void
432 tui_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 ();
438 if (first_element_no < m_regs_content.size ())
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
456 void
457 tui_data_window::refresh_window ()
458 {
459 tui_gen_win_info::refresh_window ();
460 for (auto &&win : m_regs_content)
461 win.refresh_window ();
462 }
463
464 void
465 tui_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
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. */
475 void
476 tui_data_window::check_register_values (struct frame_info *frame)
477 {
478 if (m_regs_content.empty ())
479 show_registers (m_current_group);
480 else
481 {
482 for (auto &&data_item_win : m_regs_content)
483 {
484 int was_hilighted;
485
486 was_hilighted = data_item_win.highlight;
487
488 tui_get_register (frame, &data_item_win,
489 data_item_win.item_no,
490 &data_item_win.highlight);
491
492 if (data_item_win.highlight || was_hilighted)
493 data_item_win.rerender ();
494 }
495 }
496 }
497
498 /* Display a register in a window. If hilite is TRUE, then the value
499 will be displayed in reverse video. */
500 void
501 tui_data_item_window::rerender ()
502 {
503 int i;
504
505 scrollok (handle.get (), FALSE);
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. */
512 (void) wstandout (handle.get ());
513
514 wmove (handle.get (), 0, 0);
515 for (i = 1; i < width; i++)
516 waddch (handle.get (), ' ');
517 wmove (handle.get (), 0, 0);
518 waddstr (handle.get (), content.c_str ());
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. */
526 (void) wstandend (handle.get ());
527 refresh_window ();
528 }
529
530 void
531 tui_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. */
538 touchwin (handle.get ());
539 tui_wrefresh (handle.get ());
540 }
541 }
542
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
547 static struct reggroup *
548 tui_reg_next (struct reggroup *current_group, struct gdbarch *gdbarch)
549 {
550 struct reggroup *group = NULL;
551
552 if (current_group != NULL)
553 {
554 group = reggroup_next (gdbarch, current_group);
555 if (group == NULL)
556 group = reggroup_next (gdbarch, NULL);
557 }
558 return group;
559 }
560
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. */
564
565 static struct reggroup *
566 tui_reg_prev (struct reggroup *current_group, struct gdbarch *gdbarch)
567 {
568 struct reggroup *group = NULL;
569
570 if (current_group != NULL)
571 {
572 group = reggroup_prev (gdbarch, current_group);
573 if (group == NULL)
574 group = reggroup_prev (gdbarch, NULL);
575 }
576 return group;
577 }
578
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. */
582
583 static void
584 tui_reg_command (const char *args, int from_tty)
585 {
586 struct gdbarch *gdbarch = get_current_arch ();
587
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
596 tui_suppress_output suppress;
597
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. */
601 if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->is_visible ())
602 tui_regs_layout ();
603
604 struct reggroup *current_group = TUI_DATA_WIN->get_current_group ();
605 if (strncmp (args, "next", len) == 0)
606 match = tui_reg_next (current_group, gdbarch);
607 else if (strncmp (args, "prev", len) == 0)
608 match = tui_reg_prev (current_group, gdbarch);
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
628 TUI_DATA_WIN->show_registers (match);
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 }
650 }
651
652 /* Complete names of register groups, and add the special "prev" and "next"
653 names. */
654
655 static void
656 tui_reggroup_completer (struct cmd_list_element *ignore,
657 completion_tracker &tracker,
658 const char *text, const char *word)
659 {
660 static const char * const extra[] = { "next", "prev", NULL };
661
662 reggroup_completer (ignore, tracker, text, word);
663
664 complete_on_enum (tracker, extra, text, word);
665 }
666
667 void _initialize_tui_regs ();
668 void
669 _initialize_tui_regs ()
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, _("\
676 TUI command to control the register window.\n\
677 Usage: tui reg NAME\n\
678 NAME is the name of the register group to display"), tuicmd);
679 set_cmd_completer (cmd, tui_reggroup_completer);
680 }
This page took 0.074967 seconds and 4 git commands to generate.