Skip to content

Commit a008792

Browse files
committed
Fix pager bugs with style output
I believe this fixes all the pager output problems with styling that Philippe pointed out, plus at least one more. The patch is somewhat hard to reason about, so you may wish to give it a try. Even writing the tests was hard. This removes the style caching, because it was difficult to keep the style cache correct in all cases. Since this would cause more style escapes to be emitted, instead it changes fputs_styled to try to avoid unnecessary changes. Another bug was that the wrap buffer was not flushed in the case where wrap_column==0. In the old (pre-patch series) code, characters were directly emitted in this case; so flushing the wrap buffer here restores this behavior. On error the wrap buffer must be emptied. Otherwise, interrupting output can leave characters in the buffer that will be emitted later. As discussed on gdb-patches, this fixes the ada-lang.c problem where filtered and unfiltered printing were mixed. Now user_select_syms uses filtered printing, which is what its callees were already doing. Finally, it was possible for source line highlighting to be garbled (and invalid escape sequences emitted) if the pager was invoked at the wrong spot. To fix this, the patch arranges for source line escapes to always be emitted as a unit. gdb/ChangeLog 2019-02-17 Tom Tromey <[email protected]> * 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. gdb/testsuite/ChangeLog 2019-02-17 Tom Tromey <[email protected]> * gdb.base/style.exp: Add line-wrapping tests. * gdb.base/page.exp: Add test for quitting during pagination.
1 parent 75ba10d commit a008792

File tree

8 files changed

+193
-75
lines changed

8 files changed

+193
-75
lines changed

gdb/ChangeLog

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
2019-02-17 Tom Tromey <[email protected]>
2+
3+
* ada-lang.c (user_select_syms): Use filtered printing.
4+
* utils.c (wrap_style): New global.
5+
(desired_style): Remove.
6+
(emit_style_escape): Add stream parameter.
7+
(set_output_style, reset_terminal_style, prompt_for_continue):
8+
Update.
9+
(flush_wrap_buffer): Only flush gdb_stdout.
10+
(wrap_here): Set wrap_style.
11+
(fputs_maybe_filtered): Clear the wrap buffer on exception. Don't
12+
treat escape sequences as a character. Change when wrap buffer is
13+
flushed.
14+
(fputs_styled): Do not set the output style when the default is
15+
requested.
16+
* ui-style.h (struct ui_file_style) <is_default>: New method.
17+
* source.c (print_source_lines_base): Emit escape sequences in one
18+
piece.
19+
120
2019-02-17 Joel Brobecker <[email protected]>
221

322
* gdbtypes.c (type_align): Handle TYPE_CODE_RANGE the same as

gdb/ada-lang.c

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3903,16 +3903,16 @@ user_select_syms (struct block_symbol *syms, int nsyms, int max_results)
39033903
error (_("\
39043904
canceled because the command is ambiguous\n\
39053905
See set/show multiple-symbol."));
3906-
3906+
39073907
/* If select_mode is "all", then return all possible symbols.
39083908
Only do that if more than one symbol can be selected, of course.
39093909
Otherwise, display the menu as usual. */
39103910
if (select_mode == multiple_symbols_all && max_results > 1)
39113911
return nsyms;
39123912

3913-
printf_unfiltered (_("[0] cancel\n"));
3913+
printf_filtered (_("[0] cancel\n"));
39143914
if (max_results > 1)
3915-
printf_unfiltered (_("[1] all\n"));
3915+
printf_filtered (_("[1] all\n"));
39163916

39173917
sort_choices (syms, nsyms);
39183918

@@ -3926,16 +3926,16 @@ See set/show multiple-symbol."));
39263926
struct symtab_and_line sal =
39273927
find_function_start_sal (syms[i].symbol, 1);
39283928

3929-
printf_unfiltered ("[%d] ", i + first_choice);
3929+
printf_filtered ("[%d] ", i + first_choice);
39303930
ada_print_symbol_signature (gdb_stdout, syms[i].symbol,
39313931
&type_print_raw_options);
39323932
if (sal.symtab == NULL)
3933-
printf_unfiltered (_(" at <no source file available>:%d\n"),
3934-
sal.line);
3933+
printf_filtered (_(" at <no source file available>:%d\n"),
3934+
sal.line);
39353935
else
3936-
printf_unfiltered (_(" at %s:%d\n"),
3937-
symtab_to_filename_for_display (sal.symtab),
3938-
sal.line);
3936+
printf_filtered (_(" at %s:%d\n"),
3937+
symtab_to_filename_for_display (sal.symtab),
3938+
sal.line);
39393939
continue;
39403940
}
39413941
else
@@ -3951,37 +3951,37 @@ See set/show multiple-symbol."));
39513951

39523952
if (SYMBOL_LINE (syms[i].symbol) != 0 && symtab != NULL)
39533953
{
3954-
printf_unfiltered ("[%d] ", i + first_choice);
3954+
printf_filtered ("[%d] ", i + first_choice);
39553955
ada_print_symbol_signature (gdb_stdout, syms[i].symbol,
39563956
&type_print_raw_options);
3957-
printf_unfiltered (_(" at %s:%d\n"),
3958-
symtab_to_filename_for_display (symtab),
3959-
SYMBOL_LINE (syms[i].symbol));
3957+
printf_filtered (_(" at %s:%d\n"),
3958+
symtab_to_filename_for_display (symtab),
3959+
SYMBOL_LINE (syms[i].symbol));
39603960
}
39613961
else if (is_enumeral
39623962
&& TYPE_NAME (SYMBOL_TYPE (syms[i].symbol)) != NULL)
39633963
{
3964-
printf_unfiltered (("[%d] "), i + first_choice);
3964+
printf_filtered (("[%d] "), i + first_choice);
39653965
ada_print_type (SYMBOL_TYPE (syms[i].symbol), NULL,
39663966
gdb_stdout, -1, 0, &type_print_raw_options);
3967-
printf_unfiltered (_("'(%s) (enumeral)\n"),
3968-
SYMBOL_PRINT_NAME (syms[i].symbol));
3967+
printf_filtered (_("'(%s) (enumeral)\n"),
3968+
SYMBOL_PRINT_NAME (syms[i].symbol));
39693969
}
39703970
else
39713971
{
3972-
printf_unfiltered ("[%d] ", i + first_choice);
3972+
printf_filtered ("[%d] ", i + first_choice);
39733973
ada_print_symbol_signature (gdb_stdout, syms[i].symbol,
39743974
&type_print_raw_options);
39753975

39763976
if (symtab != NULL)
3977-
printf_unfiltered (is_enumeral
3978-
? _(" in %s (enumeral)\n")
3979-
: _(" at %s:?\n"),
3980-
symtab_to_filename_for_display (symtab));
3977+
printf_filtered (is_enumeral
3978+
? _(" in %s (enumeral)\n")
3979+
: _(" at %s:?\n"),
3980+
symtab_to_filename_for_display (symtab));
39813981
else
3982-
printf_unfiltered (is_enumeral
3983-
? _(" (enumeral)\n")
3984-
: _(" at ?\n"));
3982+
printf_filtered (is_enumeral
3983+
? _(" (enumeral)\n")
3984+
: _(" at ?\n"));
39853985
}
39863986
}
39873987
}

gdb/source.c

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,7 +1249,6 @@ static void
12491249
print_source_lines_base (struct symtab *s, int line, int stopline,
12501250
print_source_lines_flags flags)
12511251
{
1252-
int c;
12531252
scoped_fd desc;
12541253
int noprint = 0;
12551254
int nlines = stopline - line;
@@ -1343,13 +1342,10 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
13431342
line, symtab_to_filename_for_display (s), s->nlines);
13441343

13451344
const char *iter = lines.c_str ();
1346-
while (nlines-- > 0)
1345+
while (nlines-- > 0 && *iter != '\0')
13471346
{
13481347
char buf[20];
13491348

1350-
c = *iter++;
1351-
if (c == '\0')
1352-
break;
13531349
last_line_listed = current_source_line;
13541350
if (flags & PRINT_SOURCE_LINES_FILENAME)
13551351
{
@@ -1358,33 +1354,55 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
13581354
}
13591355
xsnprintf (buf, sizeof (buf), "%d\t", current_source_line++);
13601356
uiout->text (buf);
1361-
do
1357+
1358+
while (*iter != '\0')
13621359
{
1363-
if (c < 040 && c != '\t' && c != '\n' && c != '\r' && c != '\033')
1360+
/* Find a run of characters that can be emitted at once.
1361+
This is done so that escape sequences are kept
1362+
together. */
1363+
const char *start = iter;
1364+
while (true)
13641365
{
1365-
xsnprintf (buf, sizeof (buf), "^%c", c + 0100);
1366-
uiout->text (buf);
1366+
int skip_bytes;
1367+
1368+
char c = *iter;
1369+
if (c == '\033' && skip_ansi_escape (iter, &skip_bytes))
1370+
iter += skip_bytes;
1371+
else if (c < 040 && c != '\t')
1372+
break;
1373+
else if (c == 0177)
1374+
break;
1375+
else
1376+
++iter;
13671377
}
1368-
else if (c == 0177)
1369-
uiout->text ("^?");
1370-
else if (c == '\r')
1378+
if (iter > start)
13711379
{
1372-
/* Skip a \r character, but only before a \n. */
1373-
if (*iter != '\n')
1374-
printf_filtered ("^%c", c + 0100);
1380+
std::string text (start, iter);
1381+
uiout->text (text.c_str ());
13751382
}
1376-
else
1383+
if (*iter == '\r')
13771384
{
1378-
xsnprintf (buf, sizeof (buf), "%c", c);
1385+
/* Treat either \r or \r\n as a single newline. */
1386+
++iter;
1387+
if (*iter == '\n')
1388+
++iter;
1389+
break;
1390+
}
1391+
else if (*iter == '\n')
1392+
{
1393+
++iter;
1394+
break;
1395+
}
1396+
else if (*iter > 0 && *iter < 040)
1397+
{
1398+
xsnprintf (buf, sizeof (buf), "^%c", *iter + 0100);
13791399
uiout->text (buf);
13801400
}
1401+
else if (*iter == 0177)
1402+
uiout->text ("^?");
13811403
}
1382-
while (c != '\n' && (c = *iter++) != '\0');
1383-
if (c == '\0')
1384-
break;
1404+
uiout->text ("\n");
13851405
}
1386-
if (!lines.empty() && lines.back () != '\n')
1387-
uiout->text ("\n");
13881406
}
13891407

13901408

gdb/testsuite/ChangeLog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2019-02-17 Tom Tromey <[email protected]>
2+
3+
* gdb.base/style.exp: Add line-wrapping tests.
4+
* gdb.base/page.exp: Add test for quitting during pagination.
5+
16
2019-02-17 Joel Brobecker <[email protected]>
27

38
* gdb.ada/big_packed_array: New testcase.

gdb/testsuite/gdb.base/page.exp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,20 @@ gdb_expect_list "paged count remainder" "${gdb_prompt} " {
8080
11
8181
}
8282

83+
set fours [string repeat 4 40]
84+
set str "1\\n2\\n3\\n$fours\\n5\\n"
85+
86+
# Avoid some confusing output from readline.
87+
gdb_test_no_output "set editing off"
88+
89+
gdb_test_no_output "set width 30"
90+
send_gdb "printf \"$str\"\n"
91+
gdb_expect_list "paged count for interrupt" \
92+
".*$pagination_prompt" \
93+
[list 1\r\n 2\r\n 3\r\n 444444444444444444444444444444]
94+
95+
gdb_test "q" "Quit" "quit while paging"
96+
8397
gdb_exit
8498
return 0
8599

gdb/testsuite/gdb.base/style.exp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,24 @@ save_vars { env(TERM) } {
4545

4646
gdb_test "print &main" " = .* \033\\\[34m$hex\033\\\[m <$main_expr>"
4747

48+
# Regression test for a bug where line-wrapping would occur at the
49+
# wrong spot with styling. There were different bugs at different
50+
# widths, so try two.
51+
foreach width {20 30} {
52+
gdb_test_no_output "set width $width"
53+
# There was also a bug where the styling could be wrong in the
54+
# line listing; this is why the words from the source code are
55+
# spelled out in the final result line of the test.
56+
gdb_test "frame" \
57+
[multi_line \
58+
"#0 *$main_expr.*$arg_expr.*" \
59+
".*$arg_expr.*" \
60+
".* at .*$file_expr.*" \
61+
"\[0-9\]+.*return.* break here .*"
62+
] \
63+
"frame when width=$width"
64+
}
65+
4866
gdb_exit
4967
gdb_spawn
5068

gdb/ui-style.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,16 @@ struct ui_file_style
163163
/* Return the ANSI escape sequence for this style. */
164164
std::string to_ansi () const;
165165

166+
/* Return true if this style is the default style; false
167+
otherwise. */
168+
bool is_default () const
169+
{
170+
return (m_foreground == NONE
171+
&& m_background == NONE
172+
&& m_intensity == NORMAL
173+
&& !m_reverse);
174+
}
175+
166176
/* Return true if this style specified reverse display; false
167177
otherwise. */
168178
bool is_reverse () const

0 commit comments

Comments
 (0)