From: Tom Tromey Date: Mon, 21 Oct 2019 17:21:14 +0000 (-0600) Subject: Style disassembly in the TUI X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1df2f9ef6cae23a08a50a3b2f33ce2664ce9ae9e;p=binutils-gdb.git Style disassembly in the TUI This patch changes the TUI disassembly window to style its contents. The styling should be identical to what is seen in the CLI. This involved a bit of rearrangement, so that the source and disassembly windows could share both the copy_source_line utility function, and the ability to react to changes in "set style enabled". This version introduces a new function to strip the styling from the address string when computing the length. As a byproduct, it also removes the unused "insn_size" computation from tui_disasm_window::set_contents. gdb/ChangeLog 2019-11-05 Tom Tromey * tui/tui-source.h (struct tui_source_window): Inline constructor. Remove destructor. : Move to superclass. * tui/tui-winsource.h (tui_copy_source_line): Declare. (struct tui_source_window_base): Move private members to end. : Move from tui_source_window. * tui/tui-winsource.c (tui_copy_source_line): Move from tui-source.c. Rename from copy_source_line. Add special handling for negative line number. (tui_source_window_base::style_changed): Move from tui_source_window. (tui_source_window_base): Register observer. (~tui_source_window_base): New. * tui/tui-source.c (copy_source_line): Move to tui-winsource.c; rename. (tui_source_window::set_contents): Use tui_copy_source_line. (tui_source_window::tui_source_window): Move to tui-source.h. (tui_source_window::~tui_source_window): Remove. (tui_source_window::style_changed): Move to superclass. * tui/tui-disasm.c (tui_disassemble): Create string file with styling, when possible. Add "addr_size" parameter. (tui_disasm_window::set_contents): Use tui_copy_source_line. Don't compute maximum size. (len_without_escapes): New function Change-Id: I8722635eeecbbb1633d943a65b856404c2d467b0 --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0c05afeb13c..00d21fac1e7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,30 @@ +2019-11-05 Tom Tromey + + * tui/tui-source.h (struct tui_source_window): Inline + constructor. Remove destructor. + : Move to superclass. + * tui/tui-winsource.h (tui_copy_source_line): Declare. + (struct tui_source_window_base): Move private members to end. + : Move from tui_source_window. + * tui/tui-winsource.c (tui_copy_source_line): Move from + tui-source.c. Rename from copy_source_line. Add special handling + for negative line number. + (tui_source_window_base::style_changed): Move from + tui_source_window. + (tui_source_window_base): Register observer. + (~tui_source_window_base): New. + * tui/tui-source.c (copy_source_line): Move to tui-winsource.c; + rename. + (tui_source_window::set_contents): Use tui_copy_source_line. + (tui_source_window::tui_source_window): Move to tui-source.h. + (tui_source_window::~tui_source_window): Remove. + (tui_source_window::style_changed): Move to superclass. + * tui/tui-disasm.c (tui_disassemble): Create string file with + styling, when possible. Add "addr_size" parameter. + (tui_disasm_window::set_contents): Use tui_copy_source_line. + Don't compute maximum size. + (len_without_escapes): New function + 2019-11-05 Tom Tromey * tui/tui-winsource.h (struct tui_source_element) : Now a diff --git a/gdb/tui/tui-disasm.c b/gdb/tui/tui-disasm.c index 91c9845f5dc..71783266391 100644 --- a/gdb/tui/tui-disasm.c +++ b/gdb/tui/tui-disasm.c @@ -39,6 +39,7 @@ #include "tui/tui-source.h" #include "progspace.h" #include "objfiles.h" +#include "cli/cli-style.h" #include "gdb_curses.h" @@ -49,15 +50,47 @@ struct tui_asm_line std::string insn; }; +/* Helper function to find the number of characters in STR, skipping + any ANSI escape sequences. */ +static size_t +len_without_escapes (const std::string &str) +{ + size_t len = 0; + const char *ptr = str.c_str (); + char c; + + while ((c = *ptr++) != '\0') + { + if (c == '\033') + { + ui_file_style style; + size_t n_read; + if (style.parse (ptr, &n_read)) + ptr += n_read; + else + { + /* Shouldn't happen, but just skip the ESC if it somehow + does. */ + ++ptr; + } + } + else + ++len; + } + return len; +} + /* Function to set the disassembly window's content. Disassemble count lines starting at pc. Return address of the count'th instruction after pc. */ static CORE_ADDR tui_disassemble (struct gdbarch *gdbarch, std::vector &asm_lines, - CORE_ADDR pc, int pos, int count) + CORE_ADDR pc, int pos, int count, + size_t *addr_size = nullptr) { - string_file gdb_dis_out; + bool term_out = source_styling && gdb_stdout->can_emit_style_escape (); + string_file gdb_dis_out (term_out); /* Now construct each line. */ for (int i = 0; i < count; ++i) @@ -68,6 +101,17 @@ tui_disassemble (struct gdbarch *gdbarch, gdb_dis_out.clear (); + if (addr_size != nullptr) + { + size_t new_size; + + if (term_out) + new_size = len_without_escapes (asm_lines[pos + i].addr_string); + else + new_size = asm_lines[pos + i].addr_string.size (); + *addr_size = std::max (*addr_size, new_size); + } + pc = pc + gdb_print_insn (gdbarch, pc, &gdb_dis_out, NULL); asm_lines[pos + i].insn = std::move (gdb_dis_out.string ()); @@ -164,8 +208,7 @@ tui_disasm_window::set_contents (struct gdbarch *arch, struct tui_locator_window *locator = tui_locator_win_info_ptr (); int tab_len = tui_tab_width; int insn_pos; - int addr_size, insn_size; - + gdb_assert (line_or_addr.loa == LOA_ADDRESS); CORE_ADDR pc = line_or_addr.u.addr; if (pc == 0) @@ -182,23 +225,8 @@ tui_disasm_window::set_contents (struct gdbarch *arch, /* Get temporary table that will hold all strings (addr & insn). */ std::vector asm_lines (max_lines); - - tui_disassemble (gdbarch, asm_lines, pc, 0, max_lines); - - /* Determine maximum address- and instruction lengths. */ - addr_size = 0; - insn_size = 0; - for (i = 0; i < max_lines; i++) - { - size_t len = asm_lines[i].addr_string.size (); - - if (len > addr_size) - addr_size = len; - - len = asm_lines[i].insn.size (); - if (len > insn_size) - insn_size = len; - } + size_t addr_size = 0; + tui_disassemble (gdbarch, asm_lines, pc, 0, max_lines, &addr_size); /* Align instructions to the same column. */ insn_pos = (1 + (addr_size / tab_len)) * tab_len; @@ -215,11 +243,8 @@ tui_disasm_window::set_contents (struct gdbarch *arch, - asm_lines[i].addr_string.size ()) + asm_lines[i].insn); - /* Now copy the line taking the offset into account. */ - if (line.size () > offset) - src->line = line.substr (offset, line_width); - else - src->line.clear (); + const char *ptr = line.c_str (); + src->line = tui_copy_source_line (&ptr, -1, offset, line_width); src->line_or_addr.loa = LOA_ADDRESS; src->line_or_addr.u.addr = asm_lines[i].addr; diff --git a/gdb/tui/tui-source.c b/gdb/tui/tui-source.c index f956645d898..915f9e36315 100644 --- a/gdb/tui/tui-source.c +++ b/gdb/tui/tui-source.c @@ -37,90 +37,6 @@ #include "tui/tui-source.h" #include "gdb_curses.h" -/* A helper function for tui_set_source_content that extracts some - source text from PTR. LINE_NO is the line number; FIRST_COL is the - first column to extract, and LINE_WIDTH is the number of characters - to display. Returns a string holding the desired text. */ - -static std::string -copy_source_line (const char **ptr, int line_no, int first_col, - int line_width) -{ - const char *lineptr = *ptr; - - /* Init the line with the line number. */ - std::string result = string_printf ("%-6d", line_no); - int len = result.size (); - len = len - ((len / tui_tab_width) * tui_tab_width); - result.append (len, ' '); - - int column = 0; - char c; - do - { - int skip_bytes; - - c = *lineptr; - if (c == '\033' && skip_ansi_escape (lineptr, &skip_bytes)) - { - /* We always have to preserve escapes. */ - result.append (lineptr, lineptr + skip_bytes); - lineptr += skip_bytes; - continue; - } - - ++lineptr; - ++column; - - auto process_tab = [&] () - { - int max_tab_len = tui_tab_width; - - --column; - for (int j = column % max_tab_len; - j < max_tab_len && column < first_col + line_width; - column++, j++) - if (column >= first_col) - result.push_back (' '); - }; - - /* We have to process all the text in order to pick up all the - escapes. */ - if (column <= first_col || column > first_col + line_width) - { - if (c == '\t') - process_tab (); - continue; - } - - if (c == '\n' || c == '\r' || c == '\0') - { - /* Nothing. */ - } - else if (c < 040 && c != '\t') - { - result.push_back ('^'); - result.push_back (c + 0100); - } - else if (c == 0177) - { - result.push_back ('^'); - result.push_back ('?'); - } - else if (c == '\t') - process_tab (); - else - result.push_back (c); - } - while (c != '\0' && c != '\n' && c != '\r'); - - if (c == '\r' && *lineptr == '\n') - ++lineptr; - *ptr = lineptr; - - return result; -} - /* Function to display source in the source window. */ enum tui_status tui_source_window::set_contents (struct gdbarch *arch, @@ -171,8 +87,9 @@ tui_source_window::set_contents (struct gdbarch *arch, std::string text; if (*iter != '\0') - text = copy_source_line (&iter, cur_line_no, horizontal_offset, - line_width); + text = tui_copy_source_line (&iter, cur_line_no, + horizontal_offset, + line_width); /* Set whether element is the execution point and whether there is a break point on it. */ @@ -249,26 +166,6 @@ tui_source_window::do_scroll_vertical (int num_to_scroll) } } -tui_source_window::tui_source_window () - : tui_source_window_base (SRC_WIN) -{ - gdb::observers::source_styling_changed.attach - (std::bind (&tui_source_window::style_changed, this), - m_observable); -} - -tui_source_window::~tui_source_window () -{ - gdb::observers::source_styling_changed.detach (m_observable); -} - -void -tui_source_window::style_changed () -{ - if (tui_active && is_visible ()) - refill (); -} - bool tui_source_window::location_matches_p (struct bp_location *loc, int line_no) { diff --git a/gdb/tui/tui-source.h b/gdb/tui/tui-source.h index 3ef737c56e9..a2b7754e7ee 100644 --- a/gdb/tui/tui-source.h +++ b/gdb/tui/tui-source.h @@ -31,8 +31,10 @@ struct symtab; struct tui_source_window : public tui_source_window_base { - tui_source_window (); - ~tui_source_window (); + tui_source_window () + : tui_source_window_base (SRC_WIN) + { + } DISABLE_COPY_AND_ASSIGN (tui_source_window); @@ -70,17 +72,12 @@ protected: private: - void style_changed (); - /* Answer whether a particular line number or address is displayed in the current source window. */ bool line_is_displayed (int line) const; /* It is the resolved form as returned by symtab_to_fullname. */ gdb::unique_xmalloc_ptr m_fullname; - - /* A token used to register and unregister an observer. */ - gdb::observers::token m_observable; }; #endif /* TUI_TUI_SOURCE_H */ diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c index 5d0bcb47b11..3ca723c8b26 100644 --- a/gdb/tui/tui-winsource.c +++ b/gdb/tui/tui-winsource.c @@ -65,7 +65,98 @@ tui_display_main () } } +/* See tui-winsource.h. */ + +std::string +tui_copy_source_line (const char **ptr, int line_no, int first_col, + int line_width) +{ + const char *lineptr = *ptr; + + /* Init the line with the line number. */ + std::string result; + + if (line_no > 0) + { + result = string_printf ("%-6d", line_no); + int len = result.size (); + len = len - ((len / tui_tab_width) * tui_tab_width); + result.append (len, ' '); + } + + int column = 0; + char c; + do + { + int skip_bytes; + + c = *lineptr; + if (c == '\033' && skip_ansi_escape (lineptr, &skip_bytes)) + { + /* We always have to preserve escapes. */ + result.append (lineptr, lineptr + skip_bytes); + lineptr += skip_bytes; + continue; + } + + ++lineptr; + ++column; + + auto process_tab = [&] () + { + int max_tab_len = tui_tab_width; + + --column; + for (int j = column % max_tab_len; + j < max_tab_len && column < first_col + line_width; + column++, j++) + if (column >= first_col) + result.push_back (' '); + }; + + /* We have to process all the text in order to pick up all the + escapes. */ + if (column <= first_col || column > first_col + line_width) + { + if (c == '\t') + process_tab (); + continue; + } + + if (c == '\n' || c == '\r' || c == '\0') + { + /* Nothing. */ + } + else if (c < 040 && c != '\t') + { + result.push_back ('^'); + result.push_back (c + 0100); + } + else if (c == 0177) + { + result.push_back ('^'); + result.push_back ('?'); + } + else if (c == '\t') + process_tab (); + else + result.push_back (c); + } + while (c != '\0' && c != '\n' && c != '\r'); + + if (c == '\r' && *lineptr == '\n') + ++lineptr; + *ptr = lineptr; + return result; +} + +void +tui_source_window_base::style_changed () +{ + if (tui_active && is_visible ()) + refill (); +} /* Function to display source in the source window. This function initializes the horizontal scroll to 0. */ @@ -253,8 +344,16 @@ tui_source_window_base::tui_source_window_base (enum tui_win_type type) gdb_assert (type == SRC_WIN || type == DISASSEM_WIN); start_line_or_addr.loa = LOA_ADDRESS; start_line_or_addr.u.addr = 0; + + gdb::observers::source_styling_changed.attach + (std::bind (&tui_source_window::style_changed, this), + m_observable); } +tui_source_window_base::~tui_source_window_base () +{ + gdb::observers::source_styling_changed.detach (m_observable); +} /* See tui-data.h. */ diff --git a/gdb/tui/tui-winsource.h b/gdb/tui/tui-winsource.h index 185d3dd5e0a..7c3c626add1 100644 --- a/gdb/tui/tui-winsource.h +++ b/gdb/tui/tui-winsource.h @@ -74,11 +74,9 @@ struct tui_source_element struct tui_source_window_base : public tui_win_info { -private: - void show_source_content (); - protected: explicit tui_source_window_base (enum tui_win_type type); + ~tui_source_window_base (); DISABLE_COPY_AND_ASSIGN (tui_source_window_base); @@ -140,6 +138,16 @@ public: struct gdbarch *gdbarch = nullptr; std::vector content; + +private: + + void show_source_content (); + + /* Called when the user "set style enabled" setting is changed. */ + void style_changed (); + + /* A token used to register and unregister an observer. */ + gdb::observers::token m_observable; }; @@ -227,6 +235,16 @@ extern void tui_update_source_windows_with_addr (struct gdbarch *, CORE_ADDR); extern void tui_update_source_windows_with_line (struct symtab *, int); +/* Extract some source text from PTR. LINE_NO is the line number. If + it is positive, it is printed at the start of the line. FIRST_COL + is the first column to extract, and LINE_WIDTH is the number of + characters to display. Returns a string holding the desired text. + PTR is updated to point to the start of the next line. */ + +extern std::string tui_copy_source_line (const char **ptr, + int line_no, int first_col, + int line_width); + /* Constant definitions. */ #define SCROLL_THRESHOLD 2 /* Threshold for lazy scroll. */