diff options
-rw-r--r-- | gdb/ChangeLog | 19 | ||||
-rw-r--r-- | gdb/ada-lang.c | 48 | ||||
-rw-r--r-- | gdb/source.c | 62 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/page.exp | 14 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/style.exp | 18 | ||||
-rw-r--r-- | gdb/ui-style.h | 10 | ||||
-rw-r--r-- | gdb/utils.c | 92 |
8 files changed, 193 insertions, 75 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 326113a..eb3bc0b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,22 @@ +2019-02-17 Tom Tromey <tom@tromey.com> + + * ada-lang.c (user_select_syms): Use filtered printing. + * utils.c (wrap_style): New global. + (desired_style): Remove. + (emit_style_escape): Add stream parameter. + (set_output_style, reset_terminal_style, prompt_for_continue): + Update. + (flush_wrap_buffer): Only flush gdb_stdout. + (wrap_here): Set wrap_style. + (fputs_maybe_filtered): Clear the wrap buffer on exception. Don't + treat escape sequences as a character. Change when wrap buffer is + flushed. + (fputs_styled): Do not set the output style when the default is + requested. + * ui-style.h (struct ui_file_style) <is_default>: New method. + * source.c (print_source_lines_base): Emit escape sequences in one + piece. + 2019-02-17 Joel Brobecker <brobecker@adacore.com> * gdbtypes.c (type_align): Handle TYPE_CODE_RANGE the same as diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 66df1d1..a6fadc8 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -3903,16 +3903,16 @@ user_select_syms (struct block_symbol *syms, int nsyms, int max_results) error (_("\ canceled because the command is ambiguous\n\ See set/show multiple-symbol.")); - + /* If select_mode is "all", then return all possible symbols. Only do that if more than one symbol can be selected, of course. Otherwise, display the menu as usual. */ if (select_mode == multiple_symbols_all && max_results > 1) return nsyms; - printf_unfiltered (_("[0] cancel\n")); + printf_filtered (_("[0] cancel\n")); if (max_results > 1) - printf_unfiltered (_("[1] all\n")); + printf_filtered (_("[1] all\n")); sort_choices (syms, nsyms); @@ -3926,16 +3926,16 @@ See set/show multiple-symbol.")); struct symtab_and_line sal = find_function_start_sal (syms[i].symbol, 1); - printf_unfiltered ("[%d] ", i + first_choice); + printf_filtered ("[%d] ", i + first_choice); ada_print_symbol_signature (gdb_stdout, syms[i].symbol, &type_print_raw_options); if (sal.symtab == NULL) - printf_unfiltered (_(" at <no source file available>:%d\n"), - sal.line); + printf_filtered (_(" at <no source file available>:%d\n"), + sal.line); else - printf_unfiltered (_(" at %s:%d\n"), - symtab_to_filename_for_display (sal.symtab), - sal.line); + printf_filtered (_(" at %s:%d\n"), + symtab_to_filename_for_display (sal.symtab), + sal.line); continue; } else @@ -3951,37 +3951,37 @@ See set/show multiple-symbol.")); if (SYMBOL_LINE (syms[i].symbol) != 0 && symtab != NULL) { - printf_unfiltered ("[%d] ", i + first_choice); + printf_filtered ("[%d] ", i + first_choice); ada_print_symbol_signature (gdb_stdout, syms[i].symbol, &type_print_raw_options); - printf_unfiltered (_(" at %s:%d\n"), - symtab_to_filename_for_display (symtab), - SYMBOL_LINE (syms[i].symbol)); + printf_filtered (_(" at %s:%d\n"), + symtab_to_filename_for_display (symtab), + SYMBOL_LINE (syms[i].symbol)); } else if (is_enumeral && TYPE_NAME (SYMBOL_TYPE (syms[i].symbol)) != NULL) { - printf_unfiltered (("[%d] "), i + first_choice); + printf_filtered (("[%d] "), i + first_choice); ada_print_type (SYMBOL_TYPE (syms[i].symbol), NULL, gdb_stdout, -1, 0, &type_print_raw_options); - printf_unfiltered (_("'(%s) (enumeral)\n"), - SYMBOL_PRINT_NAME (syms[i].symbol)); + printf_filtered (_("'(%s) (enumeral)\n"), + SYMBOL_PRINT_NAME (syms[i].symbol)); } else { - printf_unfiltered ("[%d] ", i + first_choice); + printf_filtered ("[%d] ", i + first_choice); ada_print_symbol_signature (gdb_stdout, syms[i].symbol, &type_print_raw_options); if (symtab != NULL) - printf_unfiltered (is_enumeral - ? _(" in %s (enumeral)\n") - : _(" at %s:?\n"), - symtab_to_filename_for_display (symtab)); + printf_filtered (is_enumeral + ? _(" in %s (enumeral)\n") + : _(" at %s:?\n"), + symtab_to_filename_for_display (symtab)); else - printf_unfiltered (is_enumeral - ? _(" (enumeral)\n") - : _(" at ?\n")); + printf_filtered (is_enumeral + ? _(" (enumeral)\n") + : _(" at ?\n")); } } } diff --git a/gdb/source.c b/gdb/source.c index c32b7c6..f99215f 100644 --- a/gdb/source.c +++ b/gdb/source.c @@ -1249,7 +1249,6 @@ static void print_source_lines_base (struct symtab *s, int line, int stopline, print_source_lines_flags flags) { - int c; scoped_fd desc; int noprint = 0; int nlines = stopline - line; @@ -1343,13 +1342,10 @@ print_source_lines_base (struct symtab *s, int line, int stopline, line, symtab_to_filename_for_display (s), s->nlines); const char *iter = lines.c_str (); - while (nlines-- > 0) + while (nlines-- > 0 && *iter != '\0') { char buf[20]; - c = *iter++; - if (c == '\0') - break; last_line_listed = current_source_line; if (flags & PRINT_SOURCE_LINES_FILENAME) { @@ -1358,33 +1354,55 @@ print_source_lines_base (struct symtab *s, int line, int stopline, } xsnprintf (buf, sizeof (buf), "%d\t", current_source_line++); uiout->text (buf); - do + + while (*iter != '\0') { - if (c < 040 && c != '\t' && c != '\n' && c != '\r' && c != '\033') + /* Find a run of characters that can be emitted at once. + This is done so that escape sequences are kept + together. */ + const char *start = iter; + while (true) { - xsnprintf (buf, sizeof (buf), "^%c", c + 0100); - uiout->text (buf); + int skip_bytes; + + char c = *iter; + if (c == '\033' && skip_ansi_escape (iter, &skip_bytes)) + iter += skip_bytes; + else if (c < 040 && c != '\t') + break; + else if (c == 0177) + break; + else + ++iter; } - else if (c == 0177) - uiout->text ("^?"); - else if (c == '\r') + if (iter > start) { - /* Skip a \r character, but only before a \n. */ - if (*iter != '\n') - printf_filtered ("^%c", c + 0100); + std::string text (start, iter); + uiout->text (text.c_str ()); } - else + if (*iter == '\r') { - xsnprintf (buf, sizeof (buf), "%c", c); + /* Treat either \r or \r\n as a single newline. */ + ++iter; + if (*iter == '\n') + ++iter; + break; + } + else if (*iter == '\n') + { + ++iter; + break; + } + else if (*iter > 0 && *iter < 040) + { + xsnprintf (buf, sizeof (buf), "^%c", *iter + 0100); uiout->text (buf); } + else if (*iter == 0177) + uiout->text ("^?"); } - while (c != '\n' && (c = *iter++) != '\0'); - if (c == '\0') - break; + uiout->text ("\n"); } - if (!lines.empty() && lines.back () != '\n') - uiout->text ("\n"); } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index ee8c4d3..88c6a6c 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-02-17 Tom Tromey <tom@tromey.com> + + * gdb.base/style.exp: Add line-wrapping tests. + * gdb.base/page.exp: Add test for quitting during pagination. + 2019-02-17 Joel Brobecker <brobecker@adacore.com> * gdb.ada/big_packed_array: New testcase. diff --git a/gdb/testsuite/gdb.base/page.exp b/gdb/testsuite/gdb.base/page.exp index 7461591..10ebf0d 100644 --- a/gdb/testsuite/gdb.base/page.exp +++ b/gdb/testsuite/gdb.base/page.exp @@ -80,6 +80,20 @@ gdb_expect_list "paged count remainder" "${gdb_prompt} " { 11 } +set fours [string repeat 4 40] +set str "1\\n2\\n3\\n$fours\\n5\\n" + +# Avoid some confusing output from readline. +gdb_test_no_output "set editing off" + +gdb_test_no_output "set width 30" +send_gdb "printf \"$str\"\n" +gdb_expect_list "paged count for interrupt" \ + ".*$pagination_prompt" \ + [list 1\r\n 2\r\n 3\r\n 444444444444444444444444444444] + +gdb_test "q" "Quit" "quit while paging" + gdb_exit return 0 diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp index 78d04b0..010d959 100644 --- a/gdb/testsuite/gdb.base/style.exp +++ b/gdb/testsuite/gdb.base/style.exp @@ -45,6 +45,24 @@ save_vars { env(TERM) } { gdb_test "print &main" " = .* \033\\\[34m$hex\033\\\[m <$main_expr>" + # Regression test for a bug where line-wrapping would occur at the + # wrong spot with styling. There were different bugs at different + # widths, so try two. + foreach width {20 30} { + gdb_test_no_output "set width $width" + # There was also a bug where the styling could be wrong in the + # line listing; this is why the words from the source code are + # spelled out in the final result line of the test. + gdb_test "frame" \ + [multi_line \ + "#0 *$main_expr.*$arg_expr.*" \ + ".*$arg_expr.*" \ + ".* at .*$file_expr.*" \ + "\[0-9\]+.*return.* break here .*" + ] \ + "frame when width=$width" + } + gdb_exit gdb_spawn diff --git a/gdb/ui-style.h b/gdb/ui-style.h index d719438..04a1d44 100644 --- a/gdb/ui-style.h +++ b/gdb/ui-style.h @@ -163,6 +163,16 @@ struct ui_file_style /* Return the ANSI escape sequence for this style. */ std::string to_ansi () const; + /* Return true if this style is the default style; false + otherwise. */ + bool is_default () const + { + return (m_foreground == NONE + && m_background == NONE + && m_intensity == NORMAL + && !m_reverse); + } + /* Return true if this style specified reverse display; false otherwise. */ bool is_reverse () const diff --git a/gdb/utils.c b/gdb/utils.c index 6fb5736..ec26196 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -72,6 +72,7 @@ #include <algorithm> #include "common/pathstuff.h" #include "cli/cli-style.h" +#include "common/scope-exit.h" void (*deprecated_error_begin_hook) (void); @@ -1282,6 +1283,9 @@ static const char *wrap_indent; /* Column number on the screen where wrap_buffer begins, or 0 if wrapping is not in effect. */ static int wrap_column; + +/* The style applied at the time that wrap_here was called. */ +static ui_file_style wrap_style; /* Initialize the number of lines per page and chars per line. */ @@ -1427,21 +1431,19 @@ set_screen_width_and_height (int width, int height) static ui_file_style applied_style; -/* The currently desired style. This can differ from the applied - style when showing the pagination prompt. */ - -static ui_file_style desired_style; - -/* Emit an ANSI style escape for STYLE to the wrap buffer. */ +/* Emit an ANSI style escape for STYLE. If STREAM is nullptr, emit to + the wrap buffer; otherwise emit to STREAM. */ static void -emit_style_escape (const ui_file_style &style) +emit_style_escape (const ui_file_style &style, + struct ui_file *stream = nullptr) { - if (applied_style == style) - return; applied_style = style; - wrap_buffer.append (style.to_ansi ()); + if (stream == nullptr) + wrap_buffer.append (style.to_ansi ()); + else + fputs_unfiltered (style.to_ansi ().c_str (), stream); } /* See utils.h. */ @@ -1465,11 +1467,11 @@ can_emit_style_escape (struct ui_file *stream) static void set_output_style (struct ui_file *stream, const ui_file_style &style) { - if (!can_emit_style_escape (stream) - || style == desired_style) + if (!can_emit_style_escape (stream)) return; - desired_style = style; + /* Note that we don't pass STREAM here, because we want to emit to + the wrap buffer, not directly to STREAM. */ emit_style_escape (style); } @@ -1482,9 +1484,8 @@ reset_terminal_style (struct ui_file *stream) { /* Force the setting, regardless of what we think the setting might already be. */ - desired_style = ui_file_style (); - applied_style = desired_style; - wrap_buffer.append (desired_style.to_ansi ()); + applied_style = ui_file_style (); + wrap_buffer.append (applied_style.to_ansi ()); } } @@ -1504,7 +1505,8 @@ prompt_for_continue (void) bool disable_pagination = pagination_disabled_for_command; /* Clear the current styling. */ - emit_style_escape (ui_file_style ()); + if (can_emit_style_escape (gdb_stdout)) + emit_style_escape (ui_file_style (), gdb_stdout); if (annotation_level > 1) printf_unfiltered (("\n\032\032pre-prompt-for-continue\n")); @@ -1551,7 +1553,8 @@ prompt_for_continue (void) pagination_disabled_for_command = disable_pagination; /* Restore the current styling. */ - emit_style_escape (desired_style); + if (can_emit_style_escape (gdb_stdout)) + emit_style_escape (applied_style); dont_repeat (); /* Forget prev cmd -- CR won't repeat it. */ } @@ -1589,7 +1592,7 @@ reinitialize_more_filter (void) static void flush_wrap_buffer (struct ui_file *stream) { - if (!wrap_buffer.empty ()) + if (stream == gdb_stdout && !wrap_buffer.empty ()) { fputs_unfiltered (wrap_buffer.c_str (), stream); wrap_buffer.clear (); @@ -1644,6 +1647,7 @@ wrap_here (const char *indent) wrap_indent = ""; else wrap_indent = indent; + wrap_style = applied_style; } } @@ -1743,6 +1747,14 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream, return; } + auto buffer_clearer + = make_scope_exit ([&] () + { + wrap_buffer.clear (); + wrap_column = 0; + wrap_indent = ""; + }); + /* Go through and output each character. Show line extension when this is necessary; prompt user for new page when this is necessary. */ @@ -1759,6 +1771,8 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream, while (*lineptr && *lineptr != '\n') { + int skip_bytes; + /* Print a single line. */ if (*lineptr == '\t') { @@ -1769,6 +1783,14 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream, chars_printed = ((chars_printed >> 3) + 1) << 3; lineptr++; } + else if (*lineptr == '\033' + && skip_ansi_escape (lineptr, &skip_bytes)) + { + wrap_buffer.append (lineptr, skip_bytes); + /* Note that we don't consider this a character, so we + don't increment chars_printed here. */ + lineptr += skip_bytes; + } else { wrap_buffer.push_back (*lineptr); @@ -1782,15 +1804,18 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream, chars_printed = 0; lines_printed++; - /* If we aren't actually wrapping, don't output newline -- - if chars_per_line is right, we probably just overflowed - anyway; if it's wrong, let us keep going. */ if (wrap_column) { - emit_style_escape (ui_file_style ()); - flush_wrap_buffer (stream); + if (can_emit_style_escape (stream)) + emit_style_escape (ui_file_style (), stream); + /* If we aren't actually wrapping, don't output + newline -- if chars_per_line is right, we + probably just overflowed anyway; if it's wrong, + let us keep going. */ fputc_unfiltered ('\n', stream); } + else + flush_wrap_buffer (stream); /* Possible new page. Note that PAGINATION_DISABLED_FOR_COMMAND might be set during @@ -1803,8 +1828,8 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream, if (wrap_column) { fputs_unfiltered (wrap_indent, stream); - emit_style_escape (desired_style); - flush_wrap_buffer (stream); + if (can_emit_style_escape (stream)) + emit_style_escape (wrap_style, stream); /* FIXME, this strlen is what prevents wrap_indent from containing tabs. However, if we recurse to print it and count its chars, we risk trouble if wrap_indent is @@ -1828,6 +1853,8 @@ fputs_maybe_filtered (const char *linebuffer, struct ui_file *stream, lineptr++; } } + + buffer_clearer.release (); } void @@ -1842,9 +1869,16 @@ void fputs_styled (const char *linebuffer, const ui_file_style &style, struct ui_file *stream) { - set_output_style (stream, style); - fputs_maybe_filtered (linebuffer, stream, 1); - set_output_style (stream, ui_file_style ()); + /* This just makes it so we emit somewhat fewer escape + sequences. */ + if (style.is_default ()) + fputs_maybe_filtered (linebuffer, stream, 1); + else + { + set_output_style (stream, style); + fputs_maybe_filtered (linebuffer, stream, 1); + set_output_style (stream, ui_file_style ()); + } } int |