[binutils-gdb] [gdb/testsuite] Handle unrecognized escape sequences better in tuiterm

Tom de Vries vries@sourceware.org
Sat Aug 16 07:18:36 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=06a53717f7c5abfd87165f3e5c7f55f9a8f512a7

commit 06a53717f7c5abfd87165f3e5c7f55f9a8f512a7
Author: Tom de Vries <tdevries@suse.de>
Date:   Sat Aug 16 09:18:45 2025 +0200

    [gdb/testsuite] Handle unrecognized escape sequences better in tuiterm
    
    When encountering an unrecognized escape sequence in Term::accept_gdb_output,
    a warning is issued:
    ...
    WARNING: timeout in accept_gdb_output
    ...
    and 0 is returned.
    
    Subsequent calls run into the same problem, so matching doesn't progress.
    
    Consequently, figuring out what the unrecognized escape sequence actually is
    depends on analyzing gdb's output as echoed into gdb.log.
    
    In the test added in this commit, gdb (well, a script gdb.tcl emulating gdb)
    outputs escape sequence "ESC ( B", which doesn't show up in recognizable form
    in gdb.log:
    ...
    foo^M^M
    ...
    and as mentioned the tuiterm screen only show:
    ...
    foo
    ...
    because matching doesn't progress beyond the unrecognized sequence.
    
    Fix this by rewriting accept_gdb_output to match gdb output using a phased
    approach that echoes unmatched escape sequences, giving us instead on the
    tuiterm screen:
    ...
    foo^[(B
    ...
    
    [ Since "ESC ( B" is now supported, the test-case has been updated to use
    "ESC ( % 5" instead. ]
    
    Tested on x86_64-linux.
    
    PR testsuite/33218
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33218

Diff:
---
 gdb/testsuite/gdb.tui/gdb.tcl       | 20 +++++++++
 gdb/testsuite/gdb.tui/tuiterm-2.exp | 28 +++++++++++++
 gdb/testsuite/lib/tuiterm.exp       | 83 +++++++++++++++++++++++++++++--------
 3 files changed, 114 insertions(+), 17 deletions(-)

diff --git a/gdb/testsuite/gdb.tui/gdb.tcl b/gdb/testsuite/gdb.tui/gdb.tcl
new file mode 100755
index 00000000000..ca207edb1c6
--- /dev/null
+++ b/gdb/testsuite/gdb.tui/gdb.tcl
@@ -0,0 +1,20 @@
+#!/usr/bin/env tclsh
+
+# Copyright 2025 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/>.
+
+puts "foo\033(%5"
+
+gets stdin
diff --git a/gdb/testsuite/gdb.tui/tuiterm-2.exp b/gdb/testsuite/gdb.tui/tuiterm-2.exp
index becb65ac553..a451834b640 100644
--- a/gdb/testsuite/gdb.tui/tuiterm-2.exp
+++ b/gdb/testsuite/gdb.tui/tuiterm-2.exp
@@ -151,3 +151,31 @@ with_override Term::accept_gdb_output test_accept_gdb_output {
 	}
     }
 }
+
+with_test_prefix "Unrecognized escape sequence" {
+    spawn $srcdir/$subdir/gdb.tcl
+    switch_gdb_spawn_id  $spawn_id
+
+    Term::_setup 4 20
+
+    save_vars timeout {
+	set timeout 1
+
+	set line { 0 0 20 1 }
+
+	# Parse "foo".
+	gdb_assert { [Term::wait_for_region_contents \
+			  {*}$line \
+			  [string_to_regexp "foo"]] } \
+	    "foo"
+
+	# Parse "\033(%5".
+	gdb_assert { ![Term::accept_gdb_output 0] } \
+	    "fail to parse escape sequence"
+	gdb_assert { [Term::wait_for_region_contents \
+			  {*}$line \
+			  [string_to_regexp "^\[(%5"]] } \
+	    "echoed escape sequence"
+    }
+    Term::dump_screen
+}
diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp
index d6220036242..a084b431c55 100644
--- a/gdb/testsuite/lib/tuiterm.exp
+++ b/gdb/testsuite/lib/tuiterm.exp
@@ -999,31 +999,86 @@ proc Term::_setup {rows cols} {
 
 # Accept some output from gdb and update the screen.
 # Return 1 if successful, or 0 if a timeout occurred.
-proc Term::accept_gdb_output { } {
+proc Term::accept_gdb_output { {warn 1} } {
     global expect_out
+
+    set ctls "\x07\x08\x0a\x0d"
+    set esc "\x1b"
+    set re_ctls "\[$ctls\]"
+    set re_others "\[^$esc$ctls\]"
+    set have_esc 0
     gdb_expect {
-	-re "^\[\x07\x08\x0a\x0d\]" {
+	-re ^$re_ctls {
 	    scan $expect_out(0,string) %c val
 	    set hexval [format "%02x" $val]
 	    _log "wait_for: _ctl_0x${hexval}"
 	    _ctl_0x${hexval}
 	}
-	-re "^\x1b(\[0-9a-zA-Z\])" {
+	-re "^$esc" {
+	    _log "wait_for: ESC"
+	    set have_esc 1
+	}
+	-re "^$re_others+" {
+	    _insert $expect_out(0,string)
+	}
+
+	timeout {
+	    # Assume a timeout means we somehow missed the
+	    # expected result, and carry on.
+	    warning "timeout in accept_gdb_output"
+	    dump_screen
+	    return 0
+	}
+    }
+
+    if { !$have_esc } {
+	return 1
+    }
+
+    set re_csi [string_to_regexp "\["]
+    set have_csi 0
+    gdb_expect {
+	-re "^(\[0-9a-zA-Z\])" {
 	    _log "wait_for: unsupported escape"
 	    error "unsupported escape"
 	}
-	-re "^\x1b(\[\\(\])(\[a-zA-Z\])" {
+	-re "^(\[\\(\])(\[a-zA-Z\])" {
 	    scan $expect_out(1,string) %c val
 	    set hexval [format "%02x" $val]
 	    set cmd $expect_out(2,string)
 	    eval _esc_0x${hexval}_$cmd
 	}
-	-re "^\x1b(\[=>\])" {
+	-re "^(\[=>\])" {
 	    scan $expect_out(1,string) %c val
 	    set hexval [format "%02x" $val]
 	    _esc_0x$hexval
 	}
-	-re "^\x1b\\\[(\\??)(\[0-9;\]*)(\[a-zA-Z@`\])" {
+	-re "^$re_csi" {
+	    _log "wait_for: CSI"
+	    set have_csi 1
+	}
+
+	timeout {
+	    # Assume a timeout means we somehow missed the
+	    # expected result, and carry on.
+	    if { $warn } {
+		warning "timeout in accept_gdb_output following ESC"
+		dump_screen
+	    }
+	    _insert "^\["
+	    return 0
+	}
+    }
+
+    if { !$have_csi } {
+	return 1
+    }
+
+    set re_csi_prefix {[?]}
+    set re_csi_args {[0-9;]}
+    set re_csi_cmd {[a-zA-Z@`]}
+    gdb_expect {
+	-re "^($re_csi_prefix?)($re_csi_args*)($re_csi_cmd)" {
 	    set prefix $expect_out(1,string)
 	    set cmd $expect_out(3,string)
 	    set params [split $expect_out(2,string) ";"]
@@ -1037,21 +1092,15 @@ proc Term::accept_gdb_output { } {
 		eval _csi_0x${hexval}_$cmd $params
 	    }
 	}
-	-re "^\x1b\\\[(\[0-9;\]*)(\[a-zA-Z@`\])" {
-	    set cmd $expect_out(2,string)
-	    set params [split $expect_out(1,string) ";"]
-	    _log "wait_for: _csi_$cmd <<<$expect_out(1,string)>>>"
-	    eval _csi_$cmd $params
-	}
-	-re "^\[^\x07\x08\x0a\x0d\x1b\]+" {
-	    _insert $expect_out(0,string)
-	}
 
 	timeout {
 	    # Assume a timeout means we somehow missed the
 	    # expected result, and carry on.
-	    warning "timeout in accept_gdb_output"
-	    dump_screen
+	    if { $warn } {
+		warning "timeout in accept_gdb_output following CSI"
+		dump_screen
+	    }
+	    _insert "^\[\["
 	    return 0
 	}
     }


More information about the Gdb-cvs mailing list