[2/2,gdb/cli] Fix wrapping for TERM=ansi

Message ID 20230415060905.18498-1-tdevries@suse.de
State Superseded
Headers
Series None |

Commit Message

Tom de Vries April 15, 2023, 6:09 a.m. UTC
  [ This patch requires readline_hidden_col, introduced by this patch (
https://sourceware.org/pipermail/gdb-patches/2023-April/198877.html ). ]

Say we have:
...
$ echo $COLUMNS
40
...

With xterm, we claim to wrap after 40 chars:
...
$ TERM=xterm gdb
(gdb) show width
Number of characters gdb thinks are in a line is 40.
...

And with ansi, after 39 chars:
...
$ TERM=ansi gdb
(gdb) show width
Number of characters gdb thinks are in a line is 39.
...

Let's see if that's correct.  First, let's note that the prompt prefix
"(gdb) " is 6 chars long:
...
123456
(gdb)
...
so we'll tag on starting with 7.

Let's try with xterm:
...
$ TERM=xterm gdb
(gdb) 7890123456789012345678901234567890
123
...
That looks as expected, wrapping occurs after 40 chars.

Now, let's try with ansi:
...
$ TERM=ansi gdb
(gdb) 78901234567890123456789012345678
90123
...
It looks like wrapping occurred after 38 instead of 39 chars.

This is caused by:
- readline detecting the screen width: 40,
- readline substracting one from the screen width because the ansi terminal
  does not support autowrap, setting the readline screen width to 39,
- readline reporting 39 to gdb as screen width,
- gdb setting readline screen width to 39,
- again readline substracting one from the screen width, setting the readline
  screen width to 38.

Fix this by taking readline_hidden_cols into account in set_screen_size.

PR cli/30346
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30346

Tested on x86_64-linux.
---
 gdb/testsuite/gdb.base/wrap-line.exp | 104 +++++++++++++++++++++++++++
 gdb/utils.c                          |   2 +-
 2 files changed, 105 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.base/wrap-line.exp
  

Comments

Tom de Vries April 15, 2023, 8:10 a.m. UTC | #1
On 4/15/23 08:09, Tom de Vries via Gdb-patches wrote:
> [ This patch requires readline_hidden_col, introduced by this patch (
> https://sourceware.org/pipermail/gdb-patches/2023-April/198877.html ). ]

Hi,

I see I accidentally formatted this as a 2/2 patch.  The 1/2 is 
obviously the readline_hidden_cols part of the patch mentioned above.

I can submit that part separately, if anybody thinks that's a good idea, 
but for now I'm hoping aforementioned patch will get accepted, and 
there'll be no need.

Thanks,
- Tom
  
Tom de Vries May 2, 2023, 1:40 p.m. UTC | #2
On 4/15/23 10:10, Tom de Vries via Gdb-patches wrote:
> On 4/15/23 08:09, Tom de Vries via Gdb-patches wrote:
>> [ This patch requires readline_hidden_col, introduced by this patch (
>> https://sourceware.org/pipermail/gdb-patches/2023-April/198877.html ). ]
> 
> Hi,
> 
> I see I accidentally formatted this as a 2/2 patch.  The 1/2 is 
> obviously the readline_hidden_cols part of the patch mentioned above.
> 
> I can submit that part separately, if anybody thinks that's a good idea, 
> but for now I'm hoping aforementioned patch will get accepted, and 
> there'll be no need.
> 

I've submitted a v2 here ( 
https://sourceware.org/pipermail/gdb-patches/2023-May/199260.html ).

Changes v2 vs v1:
- no longer fixing this in set_screen_size, but instead in
   init_page_info.
- more extensive analysis in commit log, also covers PR cli/30411
   which is caused by the same root cause.
- came to the conclusion that "set width" is only supposed to be
   used to set the screen width, updated help text and doc to
   make that more clear.

Thanks,
- Tom
  

Patch

diff --git a/gdb/testsuite/gdb.base/wrap-line.exp b/gdb/testsuite/gdb.base/wrap-line.exp
new file mode 100644
index 00000000000..2c4828c905b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/wrap-line.exp
@@ -0,0 +1,104 @@ 
+# Copyright 2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Check that wrapping occurs at the expected location.
+
+# We set TERM on build, but we need to set it on host.  That only works if
+# build == host.
+require {!is_remote host}
+
+# Test both ansi (no auto-wrap) and xterm (auto-wrap).
+set terms {ansi xterm}
+
+foreach_with_prefix term $terms  {
+    save_vars { env(TERM) INTERNAL_GDBFLAGS } {
+
+	setenv TERM $term
+
+	# Let's use the width as determined by readline to get correct
+	# wrapping in the auto-wrap case.  Avoid "set width" argument.
+	set INTERNAL_GDBFLAGS \
+	    [string map {{-iex "set width 0"} ""} $INTERNAL_GDBFLAGS]
+
+	# Avoid "set width" in default_gdb_start.
+	gdb_exit
+	gdb_spawn
+    }
+
+    set test "initial prompt"
+    gdb_test_multiple "" $test {
+	-re "^$gdb_prompt $" {
+	    pass "$test"
+	}
+    }
+
+    if { ! [readline_is_used] } {
+	continue
+    }
+
+    set width 0
+    set show_width_re \
+	"Number of characters gdb thinks are in a line is ($decimal)\\."
+    gdb_test_multiple "show width" "" {
+	-re -wrap $show_width_re {
+	    set width $expect_out(1,string)
+	    pass $gdb_test_name
+	}
+    }
+
+    if { $width == 0 } {
+	continue
+    }
+
+    # New prompt, but avoid emitting a pass in order to avoid ending the line
+    # after the prompt in gdb.log.  This make it a bit easier in gdb.log to
+    # understand where wrapping occurred.
+    gdb_test_multiple "print 1" "" {
+	-re -wrap " = 1" {
+	}
+    }
+
+    # Take into account that the prompt also takes space.
+    set prefix [string length "(gdb) "]
+    set start [expr $prefix + 1]
+
+    # Print chars without wrapping.
+    set i $start
+    while { 1 } {
+	send_gdb [expr $i % 10]
+	if { $i == $width } {
+	    break
+	}
+	incr i
+    }
+
+    # Now print the first char we expect to wrap.
+    send_gdb "W"
+
+    # Generate a prompt.
+    send_gdb "\003"
+
+    # Note the difference between autowrap and no autowrap.  In the autowrap
+    # case, readline doesn't emit a '\n', the terminal takes care of that.
+    if { $term == "xterm" } {
+	# xterm, autowrap.
+	set re "^$start\[^\r\n\]* \rWQuit"
+    } else {
+	# ansi, no autowrap.
+	set re "^$start\[^\r\n\]*\r\n\rWQuit"
+    }
+
+    gdb_test "" $re "wrap"
+}
diff --git a/gdb/utils.c b/gdb/utils.c
index 82138a1fc2c..eda09cf9c6b 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -1228,7 +1228,7 @@  static void
 set_screen_size (void)
 {
   int rows = lines_per_page;
-  int cols = chars_per_line;
+  int cols = chars_per_line + readline_hidden_cols;
 
   /* If we get 0 or negative ROWS or COLS, treat as "infinite" size.
      A negative number can be seen here with the "set width/height"