diff options
Diffstat (limited to 'gdb/testsuite/lib')
60 files changed, 1809 insertions, 1071 deletions
diff --git a/gdb/testsuite/lib/aarch64-scalable.exp b/gdb/testsuite/lib/aarch64-scalable.exp index 2ba7d15..c9f2463 100644 --- a/gdb/testsuite/lib/aarch64-scalable.exp +++ b/gdb/testsuite/lib/aarch64-scalable.exp @@ -1,4 +1,4 @@ -# Copyright 2023-2024 Free Software Foundation, Inc. +# Copyright 2023-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 diff --git a/gdb/testsuite/lib/aarch64-test-sme.c b/gdb/testsuite/lib/aarch64-test-sme.c index 2925b48..c5d7a8a 100644 --- a/gdb/testsuite/lib/aarch64-test-sme.c +++ b/gdb/testsuite/lib/aarch64-test-sme.c @@ -1,6 +1,6 @@ /* This testcase is part of GDB, the GNU debugger. - Copyright 2023-2024 Free Software Foundation, Inc. + Copyright 2023-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 diff --git a/gdb/testsuite/lib/aarch64-test-sve.c b/gdb/testsuite/lib/aarch64-test-sve.c index d558a40..3eed754 100644 --- a/gdb/testsuite/lib/aarch64-test-sve.c +++ b/gdb/testsuite/lib/aarch64-test-sve.c @@ -1,6 +1,6 @@ /* This testcase is part of GDB, the GNU debugger. - Copyright 2023-2024 Free Software Foundation, Inc. + Copyright 2023-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 diff --git a/gdb/testsuite/lib/aarch64.exp b/gdb/testsuite/lib/aarch64.exp index 602120a..ef64489 100644 --- a/gdb/testsuite/lib/aarch64.exp +++ b/gdb/testsuite/lib/aarch64.exp @@ -1,4 +1,4 @@ -# Copyright 2023-2024 Free Software Foundation, Inc. +# Copyright 2023-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 diff --git a/gdb/testsuite/lib/ada.exp b/gdb/testsuite/lib/ada.exp index 0a1231b..37bed85 100644 --- a/gdb/testsuite/lib/ada.exp +++ b/gdb/testsuite/lib/ada.exp @@ -1,4 +1,4 @@ -# Copyright 2004-2024 Free Software Foundation, Inc. +# Copyright 2004-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 @@ -181,12 +181,16 @@ proc find_ada_tool {tool} { # compiler does not appear to be GCC, this will always return false. proc gnat_version_compare {op l2} { - set gccvers [gcc_major_version] - if {$gccvers == -1} { + set gnatmake [find_gnatmake] + set gnatmake [lindex [split $gnatmake] 0] + if {[catch {exec $gnatmake --version} output]} { + return 0 + } + if {![regexp {GNATMAKE ([0-9]+(\.[0-9]+)*)} $output match version]} { return 0 } - return [version_compare [split $gccvers .] $op $l2] + return [version_compare [split $version .] $op $l2] } # Return 1 if the GNAT runtime appears to have debug info. diff --git a/gdb/testsuite/lib/append_gdb_boards_dir.exp b/gdb/testsuite/lib/append_gdb_boards_dir.exp index 4aedba9..fadb372 100644 --- a/gdb/testsuite/lib/append_gdb_boards_dir.exp +++ b/gdb/testsuite/lib/append_gdb_boards_dir.exp @@ -1,4 +1,4 @@ -# Copyright 2012-2024 Free Software Foundation, Inc. +# Copyright 2012-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 diff --git a/gdb/testsuite/lib/attributes.h b/gdb/testsuite/lib/attributes.h index 5dabd03..626c226 100644 --- a/gdb/testsuite/lib/attributes.h +++ b/gdb/testsuite/lib/attributes.h @@ -1,6 +1,6 @@ /* This file is part of GDB, the GNU debugger. - Copyright (C) 2020-2024 Free Software Foundation, Inc. + Copyright (C) 2020-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 diff --git a/gdb/testsuite/lib/build-piece.exp b/gdb/testsuite/lib/build-piece.exp index 879fbf3..7de1f51 100644 --- a/gdb/testsuite/lib/build-piece.exp +++ b/gdb/testsuite/lib/build-piece.exp @@ -1,4 +1,4 @@ -# Copyright (C) 2014-2024 Free Software Foundation, Inc. +# Copyright (C) 2014-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 diff --git a/gdb/testsuite/lib/cache.exp b/gdb/testsuite/lib/cache.exp index ca3dca2..6ca3f18 100644 --- a/gdb/testsuite/lib/cache.exp +++ b/gdb/testsuite/lib/cache.exp @@ -1,4 +1,4 @@ -# Copyright 2012-2024 Free Software Foundation, Inc. +# Copyright 2012-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 diff --git a/gdb/testsuite/lib/check-test-names.exp b/gdb/testsuite/lib/check-test-names.exp index 11aed63..049addd 100644 --- a/gdb/testsuite/lib/check-test-names.exp +++ b/gdb/testsuite/lib/check-test-names.exp @@ -1,4 +1,4 @@ -# Copyright 2020-2024 Free Software Foundation, Inc. +# Copyright 2020-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 diff --git a/gdb/testsuite/lib/cl_util.c b/gdb/testsuite/lib/cl_util.c index 048346b..e5eb369 100644 --- a/gdb/testsuite/lib/cl_util.c +++ b/gdb/testsuite/lib/cl_util.c @@ -1,6 +1,6 @@ /* This testcase is part of GDB, the GNU debugger. - Copyright 2010-2024 Free Software Foundation, Inc. + Copyright 2010-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 diff --git a/gdb/testsuite/lib/cl_util.h b/gdb/testsuite/lib/cl_util.h index 3d03c84..6034518 100644 --- a/gdb/testsuite/lib/cl_util.h +++ b/gdb/testsuite/lib/cl_util.h @@ -1,6 +1,6 @@ /* This testcase is part of GDB, the GNU debugger. - Copyright 2010-2024 Free Software Foundation, Inc. + Copyright 2010-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 diff --git a/gdb/testsuite/lib/compile-support.exp b/gdb/testsuite/lib/compile-support.exp index 6d7a4ce..dd0b9a9 100644 --- a/gdb/testsuite/lib/compile-support.exp +++ b/gdb/testsuite/lib/compile-support.exp @@ -1,4 +1,4 @@ -# Copyright 2015-2024 Free Software Foundation, Inc. +# Copyright 2015-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 diff --git a/gdb/testsuite/lib/compiler.F90 b/gdb/testsuite/lib/compiler.F90 index 07f9852..b92b9c6 100644 --- a/gdb/testsuite/lib/compiler.F90 +++ b/gdb/testsuite/lib/compiler.F90 @@ -1,4 +1,4 @@ -/* Copyright 2022-2024 Free Software Foundation, Inc. +/* Copyright 2022-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 diff --git a/gdb/testsuite/lib/compiler.c b/gdb/testsuite/lib/compiler.c index 0749435..e457fba 100644 --- a/gdb/testsuite/lib/compiler.c +++ b/gdb/testsuite/lib/compiler.c @@ -1,6 +1,6 @@ /* This test file is part of GDB, the GNU debugger. - Copyright 1995-2024 Free Software Foundation, Inc. + Copyright 1995-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 diff --git a/gdb/testsuite/lib/compiler.cc b/gdb/testsuite/lib/compiler.cc index aa46228..ee2280f 100755 --- a/gdb/testsuite/lib/compiler.cc +++ b/gdb/testsuite/lib/compiler.cc @@ -1,6 +1,6 @@ /* This test file is part of GDB, the GNU debugger. - Copyright 1995-2024 Free Software Foundation, Inc. + Copyright 1995-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 diff --git a/gdb/testsuite/lib/completion-support.exp b/gdb/testsuite/lib/completion-support.exp index 5f0f619..15f59e6 100644 --- a/gdb/testsuite/lib/completion-support.exp +++ b/gdb/testsuite/lib/completion-support.exp @@ -1,4 +1,4 @@ -# Copyright 2017-2024 Free Software Foundation, Inc. +# Copyright 2017-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 diff --git a/gdb/testsuite/lib/cp-support.exp b/gdb/testsuite/lib/cp-support.exp index d883309..40351c6 100644 --- a/gdb/testsuite/lib/cp-support.exp +++ b/gdb/testsuite/lib/cp-support.exp @@ -1,6 +1,6 @@ # This test code is part of GDB, the GNU debugger. -# Copyright 2003-2024 Free Software Foundation, Inc. +# Copyright 2003-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 diff --git a/gdb/testsuite/lib/d-support.exp b/gdb/testsuite/lib/d-support.exp index 3edb664..717d88b 100644 --- a/gdb/testsuite/lib/d-support.exp +++ b/gdb/testsuite/lib/d-support.exp @@ -1,4 +1,4 @@ -# Copyright 2014-2024 Free Software Foundation, Inc. +# Copyright 2014-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 diff --git a/gdb/testsuite/lib/dap-support.exp b/gdb/testsuite/lib/dap-support.exp index 5c192e5..d61b1c4 100644 --- a/gdb/testsuite/lib/dap-support.exp +++ b/gdb/testsuite/lib/dap-support.exp @@ -1,4 +1,4 @@ -# Copyright 2022-2024 Free Software Foundation, Inc. +# Copyright 2022-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 diff --git a/gdb/testsuite/lib/data-structures.exp b/gdb/testsuite/lib/data-structures.exp index 461a11c..ccf7e81 100644 --- a/gdb/testsuite/lib/data-structures.exp +++ b/gdb/testsuite/lib/data-structures.exp @@ -1,4 +1,4 @@ -# Copyright 2017-2024 Free Software Foundation, Inc. +# Copyright 2017-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 diff --git a/gdb/testsuite/lib/debuginfod-support.exp b/gdb/testsuite/lib/debuginfod-support.exp index 0096448..674888a 100644 --- a/gdb/testsuite/lib/debuginfod-support.exp +++ b/gdb/testsuite/lib/debuginfod-support.exp @@ -1,4 +1,4 @@ -# Copyright 2020-2024 Free Software Foundation, Inc. +# Copyright 2020-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 diff --git a/gdb/testsuite/lib/dg-add-core-file-count.sh b/gdb/testsuite/lib/dg-add-core-file-count.sh index b4cb6b9..115cf51 100755 --- a/gdb/testsuite/lib/dg-add-core-file-count.sh +++ b/gdb/testsuite/lib/dg-add-core-file-count.sh @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (C) 2022-2024 Free Software Foundation, Inc. +# Copyright (C) 2022-2025 Free Software Foundation, Inc. # This file is part of GDB. diff --git a/gdb/testsuite/lib/dtrace.exp b/gdb/testsuite/lib/dtrace.exp index fb6204f..d558aba 100644 --- a/gdb/testsuite/lib/dtrace.exp +++ b/gdb/testsuite/lib/dtrace.exp @@ -1,4 +1,4 @@ -# Copyright 2014-2024 Free Software Foundation, Inc. +# Copyright 2014-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 diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp index 7dcf13f..3a182c2 100644 --- a/gdb/testsuite/lib/dwarf.exp +++ b/gdb/testsuite/lib/dwarf.exp @@ -1,4 +1,4 @@ -# Copyright 2010-2024 Free Software Foundation, Inc. +# Copyright 2010-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 @@ -678,6 +678,11 @@ namespace eval Dwarf { } } close $fd + + variable _constants + + # Add DW_FORM_strx_id as alias of DW_FORM_strx. + _process_one_constant DW_FORM_strx_id $_constants(DW_FORM_strx) } proc _quote {string} { @@ -823,6 +828,12 @@ namespace eval Dwarf { DW_FORM_indirect - DW_FORM_exprloc - + # Generate a DW_FORM_str index, but assume generation of .debug_str and + # .debug_str_offsets is taken care of elsewhere. + DW_FORM_strx_id { + _op .uleb128 $value + } + DW_FORM_strx - DW_FORM_strx1 - DW_FORM_strx2 - @@ -1061,7 +1072,10 @@ namespace eval Dwarf { } proc _section {name {flags ""} {type ""}} { - if {$flags == "" && $type == ""} { + if {$name == ".debug_str"} { + # Hard-code this because it's always desirable. + _emit " .section $name, \"MS\", %progbits, 1" + } elseif {$flags == "" && $type == ""} { _emit " .section $name" } elseif {$type == ""} { _emit " .section $name, \"$flags\"" @@ -1244,7 +1258,6 @@ namespace eval Dwarf { # used, as indicated in the header of the section where the location # description is found. # - # (FIXME should use 'info complete' here.) # Each list's first element is the opcode, either short or long # forms are accepted. # FIXME argument handling @@ -1252,9 +1265,18 @@ namespace eval Dwarf { proc _location { body dwarf_version addr_size offset_size } { variable _constants + set collected_lines "" foreach line [split $body \n] { # Ignore blank lines, and allow embedded comments. - if {[lindex $line 0] == "" || [regexp -- {^[ \t]*#} $line]} { + if { [regexp -- {^[ \t]*$} $line] || [regexp -- {^[ \t]*#} $line] } { + continue + } + if { $collected_lines != "" } { + set line "$collected_lines\n$line" + set collected_lines "" + } + if { ! [info complete $line] } { + set collected_lines $line continue } set opcode [_map_name [lindex $line 0] _OP] @@ -1340,6 +1362,17 @@ namespace eval Dwarf { _op .2byte $argvec(label) } + DW_OP_entry_value { + _get_args $line $opcode body + set l1 [new_label "expr_start"] + set l2 [new_label "expr_end"] + _op .uleb128 "$l2 - $l1" "expression" + define_label $l1 + _location $argvec(body) $dwarf_version $addr_size \ + $offset_size + define_label $l2 + } + DW_OP_implicit_value { set l1 [new_label "value_start"] set l2 [new_label "value_end"] @@ -1441,6 +1474,17 @@ namespace eval Dwarf { # default = default # fission 0|1 - boolean indicating if generating Fission debug info # default = 0 + # dwo_id - The value to use as the dwo_id field of skeleton and + # split_compile unit headers. May only be used with DWARF + # version 5. + # + # If a dwo_id value is specified (is non-zero), this unit is + # assumed to be part of a skeleton/split_unit pair. The unit + # type will be chosen according to the `fission` value. + # + # When using DWARF version 5 and fission is non-zero, it is + # mandatory to provide a non-zero dwo_id value. + # default = 0 # label <label> # - string indicating label to be defined at the start # of the CU header. @@ -1463,6 +1507,7 @@ namespace eval Dwarf { set _cu_version 4 set _cu_addr_size default set _cu_is_fission 0 + set dwo_id 0 set section ".debug_info" set _abbrev_section ".debug_abbrev" set label "" @@ -1474,6 +1519,7 @@ namespace eval Dwarf { version { set _cu_version $value } addr_size { set _cu_addr_size $value } fission { set _cu_is_fission $value } + dwo_id { set dwo_id $value } label { set label $value } default { error "unknown option $name" } } @@ -1524,12 +1570,42 @@ namespace eval Dwarf { # The CU header for DWARF 4 and 5 are slightly different. if { $_cu_version == 5 } { - _op .byte 0x1 "DW_UT_compile" + # The presence of a DWO_ID indicates that we generate a skeleton + # or split_compile unit. + if { $dwo_id != 0 } { + if { $_cu_is_fission } { + set unit_type_name "DW_UT_split_compile" + } else { + set unit_type_name "DW_UT_skeleton" + } + } else { + set unit_type_name "DW_UT_compile" + } + + _op .byte $_constants($unit_type_name) $unit_type_name _op .byte $_cu_addr_size "Pointer size" _op_offset $_cu_offset_size $my_abbrevs Abbrevs + + # Output DWO ID, if specified. + if { $dwo_id != 0 } { + _op .8byte $dwo_id "DWO_ID" + } else { + # To help catch user errors: if the caller asked to put this + # unit in the DWO file but didn't provide a DWO ID, it is likely + # an error. + if { $_cu_is_fission } { + error "DWO ID not specified for DWARF 5 split compile" + } + } } else { _op_offset $_cu_offset_size $my_abbrevs Abbrevs _op .byte $_cu_addr_size "Pointer size" + + # For DWARF versions < 5, the DWO ID is not in the unit header, + # so it makes not sense to specify one. + if { $dwo_id != 0 } { + error "DWO ID specified for DWARF < 5 unit" + } } _defer_output $_abbrev_section { @@ -1606,7 +1682,7 @@ namespace eval Dwarf { } if { $_cu_is_fission } { set section "$section.dwo" - set _abbrev_section "$section.dwo" + set _abbrev_section "$_abbrev_section.dwo" } _section $section @@ -3006,6 +3082,24 @@ namespace eval Dwarf { } } + # Emit a .debug_sup section with the given file name and build-id. + # The buildid should be represented as a hexadecimal string, like + # "ffeeddcc". + proc debug_sup {is_sup filename buildid} { + _defer_output .debug_sup { + # The version. + _op .2byte 0x5 + # Supplementary marker. + _op .byte $is_sup + _op .ascii [_quote $filename] + set len [expr {[string length $buildid] / 2}] + _op .uleb128 $len + foreach {a b} [split $buildid {}] { + _op .byte 0x$a$b + } + } + } + proc _note {type name hexdata} { set namelen [expr [string length $name] + 1] set datalen [expr [string length $hexdata] / 2] @@ -3305,6 +3399,58 @@ namespace eval Dwarf { debug_names_end: } + # Add the strings in ARGS to the .debug_str section, and create a + # .debug_str_offsets section pointing to those strings. + # Current options are: + # dwo 0|1 - boolean indicating if the sections have the dwo suffix. + # default = 0 (no .dwo suffix) + # base_offset label + # - generate label, to be used in DW_AT_str_offsets_base. + # default = "" (don't generate a label). + proc debug_str_offsets { options args } { + parse_options { + { dwo 0 } + { base_offset "" } + } + + if { $dwo } { + _section .debug_str.dwo + } else { + _section .debug_str + } + + set num 0 + foreach arg $args { + set str_label [_compute_label "str_${num}"] + define_label $str_label + _op .asciz \"$arg\" ".debug_str_offsets string $num" + incr num + } + + declare_labels debug_str_offsets_start debug_str_offsets_end + set initial_length "$debug_str_offsets_end - $debug_str_offsets_start" + + if { $dwo } { + _section .debug_str_offsets.dwo + } else { + _section .debug_str_offsets + } + _op .4byte $initial_length "Initial_length" + debug_str_offsets_start: + _op .2byte 0x5 "version" + _op .2byte 0x0 "padding" + if { $base_offset != "" } { + $base_offset: + } + set num 0 + foreach arg $args { + set str_label [_compute_label "str_${num}"] + _op .4byte $str_label "string $num" + incr num + } + debug_str_offsets_end: + } + # The top-level interface to the DWARF assembler. # OPTIONS is a list with an even number of elements containing # option-name and option-value pairs. diff --git a/gdb/testsuite/lib/fortran.exp b/gdb/testsuite/lib/fortran.exp index cddcc3a..6f2bbd8 100644 --- a/gdb/testsuite/lib/fortran.exp +++ b/gdb/testsuite/lib/fortran.exp @@ -1,6 +1,6 @@ # This test code is part of GDB, the GNU debugger. -# Copyright 2010-2024 Free Software Foundation, Inc. +# Copyright 2010-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 diff --git a/gdb/testsuite/lib/future.exp b/gdb/testsuite/lib/future.exp index 62913cb..161c31c 100644 --- a/gdb/testsuite/lib/future.exp +++ b/gdb/testsuite/lib/future.exp @@ -1,4 +1,4 @@ -# Copyright 2004-2024 Free Software Foundation, Inc. +# Copyright 2004-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 diff --git a/gdb/testsuite/lib/gdb-guile.exp b/gdb/testsuite/lib/gdb-guile.exp index 412dd56..776dbc6 100644 --- a/gdb/testsuite/lib/gdb-guile.exp +++ b/gdb/testsuite/lib/gdb-guile.exp @@ -1,4 +1,4 @@ -# Copyright 2010-2024 Free Software Foundation, Inc. +# Copyright 2010-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 diff --git a/gdb/testsuite/lib/gdb-python.exp b/gdb/testsuite/lib/gdb-python.exp index a820c87..e026c1b 100644 --- a/gdb/testsuite/lib/gdb-python.exp +++ b/gdb/testsuite/lib/gdb-python.exp @@ -1,4 +1,4 @@ -# Copyright 2010-2024 Free Software Foundation, Inc. +# Copyright 2010-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 @@ -77,3 +77,24 @@ proc gdb_py_module_available { name } { return ${available} } + +# Run a memory leak test within the Python script FILENAME. This proc +# checks that the required Python modules are available, sets up the +# syspath so that the helper module can be found (in the same +# directory as FILENAME), then loads FILENAME to run the test. +proc gdb_py_run_memory_leak_test { filename testname } { + if { ![gdb_py_module_available "tracemalloc"] } { + unsupported "$testname (tracemalloc module not available)" + } + + gdb_test_no_output -nopass "python import sys" + gdb_test_no_output -nopass \ + "python sys.path.insert(0, \"[file dirname $filename]\")" \ + "setup sys.path" + + set pyfile [gdb_remote_download host ${filename}] + + # Source the Python script, this runs the test, and either prints + # PASS, or throws an exception. + gdb_test "source ${pyfile}" "^PASS" $testname +} diff --git a/gdb/testsuite/lib/gdb-utils.exp b/gdb/testsuite/lib/gdb-utils.exp index b8ab30a..c24e7ed 100644 --- a/gdb/testsuite/lib/gdb-utils.exp +++ b/gdb/testsuite/lib/gdb-utils.exp @@ -1,4 +1,4 @@ -# Copyright 2014-2024 Free Software Foundation, Inc. +# Copyright 2014-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 @@ -70,6 +70,8 @@ proc style {str style} { set fg 39 set bg 49 set intensity 22 + set italic 23 + set underline 24 set reverse 27 switch -exact -- $style { title { set intensity 1 } @@ -84,7 +86,7 @@ proc style {str style} { line-number { set intensity 2 } none { return $str } } - return "\033\\\[${fg};${bg};${intensity};${reverse}m${str}\033\\\[m" + return "\033\\\[${fg};${bg};${intensity};${italic};${underline};${reverse}m${str}\033\\\[m" } # gdb_get_bp_addr num @@ -117,7 +119,10 @@ proc gdb_get_bp_addr { num } { # Compare the version numbers in L1 to those in L2 using OP, and # return 1 if the comparison is true. OP can be "<", "<=", ">", ">=", -# or "==". It is ok if the lengths of the lists differ. +# or "==". +# It is ok if the lengths of the lists differ, but note that we have +# "{1} < {1 0}" instead of "{1} == {1 0}". See also +# gdb.testsuite/version-compare.exp. proc version_compare { l1 op l2 } { switch -exact $op { diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 761a4f1..98691df 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -1,4 +1,4 @@ -# Copyright 1992-2024 Free Software Foundation, Inc. +# Copyright 1992-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 @@ -269,6 +269,13 @@ if ![info exists INTERNAL_GDBFLAGS] { } set INTERNAL_GDBFLAGS [append_gdb_data_directory_option $INTERNAL_GDBFLAGS] + + # Handle the case that "interactive-mode auto" reports off. + append INTERNAL_GDBFLAGS { -iex "set interactive-mode on"} + + if { [ishost "*-*-mingw*"] } { + append INTERNAL_GDBFLAGS { -iex "maint set console-translation-mode binary"} + } } # The variable gdb_prompt is a regexp which matches the gdb prompt. @@ -280,10 +287,13 @@ if {![info exists gdb_prompt]} { set gdb_prompt "\\(gdb\\)" } -# A regexp that matches the pagination prompt. -set pagination_prompt \ +# The pagination prompt. +set pagination_prompt_str \ "--Type <RET> for more, q to quit, c to continue without paging--" +# A regexp that matches the pagination prompt. +set pagination_prompt [string_to_regexp $pagination_prompt_str] + # The variable fullname_syntax_POSIX is a regexp which matches a POSIX # absolute path ie. /foo/ set fullname_syntax_POSIX {/[^\n]*/} @@ -1026,7 +1036,10 @@ proc command_to_message { command } { # should not be anchored at the end of the buffer. This means that the # pattern can match even if there is stuff output after the prompt. Does not # have any effect if -prompt is specified. -# -lbl specifies that line-by-line matching will be used. +# -lbl specifies that line-by-line matching will be used. This means +# that lines from GDB not matched by any pattern will be consumed from +# the output buffer. This helps avoid buffer overflows and timeouts +# when testing verbose commands. # EXPECT_ARGUMENTS will be fed to expect in addition to the standard # patterns. Pattern elements will be evaluated in the caller's # context; action elements will be executed in the caller's context. @@ -1124,6 +1137,7 @@ proc gdb_test_multiple { command message args } { global any_spawn_id set line_by_line 0 + set lbl_anchor_re "" set prompt_regexp "" set prompt_anchor 1 for {set i 0} {$i < [llength $args]} {incr i} { @@ -1133,6 +1147,7 @@ proc gdb_test_multiple { command message args } { set prompt_regexp [lindex $args $i] } elseif { $arg == "-lbl" } { set line_by_line 1 + set lbl_anchor_re "^" } elseif { $arg == "-no-prompt-anchor" } { set prompt_anchor 0 } else { @@ -1391,7 +1406,7 @@ proc gdb_test_multiple { command message args } { fail "$errmsg" set result -1 } - -re "\r\n$prompt_regexp" { + -re "${lbl_anchor_re}\r\n$prompt_regexp" { if {![string match "" $message]} { fail "$message" } @@ -2301,7 +2316,8 @@ proc default_gdb_exit {} { } } - if { [is_remote host] && [board_info host exists fileid] } { + if { ([is_remote host] && [board_info host exists fileid]) + || [istarget *-*-mingw*] } { send_gdb "quit\n" gdb_expect 10 { -re "y or n" { @@ -2314,7 +2330,9 @@ proc default_gdb_exit {} { } if ![is_remote host] { - remote_close host + if {[catch { remote_close host } message]} { + warning "closing gdb failed with: $message" + } } unset gdb_spawn_id unset ::gdb_tty_name @@ -2577,6 +2595,17 @@ proc default_gdb_start { } { # Output with -q, and bracketed paste mode enabled, see above. verbose "GDB initialized." } + -re "^\033\\\[6n$gdb_prompt $" { + # With MSYS2 and TERM={xterm,ansi}, I get: + # + # builtin_spawn gdb -q ... + # ^[[6n(gdb) + # + # We set TERM to dumb by default to avoid this, but some + # test-cases set TERM to xterm or ansi, in which case we get this + # output. + verbose "GDB initialized." + } -re "$gdb_prompt $" { perror "GDB never initialized." unset gdb_spawn_id @@ -3758,7 +3787,8 @@ proc supports_reverse {} { || [istarget "aarch64*-*-linux*"] || [istarget "loongarch*-*-linux*"] || [istarget "powerpc*-*-linux*"] - || [istarget "s390*-*-linux*"] } { + || [istarget "s390*-*-linux*"] + || [istarget "riscv*-*-*"] } { return 1 } @@ -3937,13 +3967,16 @@ gdb_caching_proc is_aarch32_target {} { return 0 } - set list {} - foreach reg \ - {r0 r1 r2 r3} { - lappend list "\tmov $reg, $reg" - } + return [gdb_can_simple_compile aarch32 { + int main (void) { + asm ("\tmov r0, r0"); + asm ("\tmov r1, r1"); + asm ("\tmov r2, r2"); + asm ("\tmov r3, r3"); - return [gdb_can_simple_compile aarch32 [join $list \n]] + return 0; + } + }] } # Return 1 if this target is an aarch64, either lp64 or ilp32. @@ -5083,6 +5116,40 @@ proc skip_inline_var_tests {} { return 0 } +# Return whether we allow running fork-related testcases. Targets +# that don't even have any concept of fork will just fail to compile +# the testcases and skip the tests that way if this returns true for +# them. Unix targets that do have a fork system call, but don't +# support intercepting forks will want to return false here, otherwise +# the testcases that exercise fork may hit a number of long cascading +# time out sequences. + +proc allow_fork_tests {} { + if {[istarget "*-*-cygwin*"] || [istarget "*-*-mingw*"]} { + return 0 + } + + return 1 +} + +# Return whether we allow running testcases that want to debug +# multiple inferiors with the same target. Not all targets support +# this. Note that some tests add a second inferior but never start +# it. Those tests should not be skipped due to this proc returning +# false. + +proc allow_multi_inferior_tests {} { + if {[istarget "*-*-cygwin*"] || [istarget "*-*-mingw*"]} { + return 0 + } + + if {[use_gdb_stub]} { + return 0 + } + + return 1 +} + # Return a 1 if we should run tests that require hardware breakpoints proc allow_hw_breakpoint_tests {} { @@ -5662,6 +5729,10 @@ proc gdb_simple_compile {name code {type object} {compile_flags {}} {object obj} set ext "d" break } + if { "$flag" eq "rust" } { + set ext "rs" + break + } } set src [standard_temp_file $name.$ext] set obj [standard_temp_file $name.$postfix] @@ -6916,7 +6987,7 @@ proc kill_wait_spawned_process { proc_spawn_id } { proc spawn_id_get_pid { spawn_id } { set testpid [exp_pid -i $spawn_id] - if { [istarget "*-*-cygwin*"] } { + if { [istarget "*-*-cygwin*"] || [istarget "*-*-mingw*"] } { # testpid is the Cygwin PID, GDB uses the Windows PID, which # might be different due to the way fork/exec works. set testpid [ exec ps -e | gawk "{ if (\$1 == $testpid) print \$4; }" ] @@ -7003,6 +7074,24 @@ proc gdb_load_cmd { args } { return -1 } +# Return non-zero if 'gcore' command is available. +gdb_caching_proc gcore_cmd_available { } { + gdb_exit + gdb_start + + # Does this gdb support gcore? + gdb_test_multiple "help gcore" "" { + -re -wrap "Undefined command: .*" { + return 0 + } + -re -wrap "Save a core file .*" { + return 1 + } + } + + return 0 +} + # Invoke "gcore". CORE is the name of the core file to write. TEST # is the name of the test case. This will return 1 if the core file # was created, 0 otherwise. If this fails to make a core file because @@ -7467,6 +7556,22 @@ proc default_gdb_init { test_file_name } { setenv LC_CTYPE C setenv LANG C + # With MSYS2 and TERM={xterm,ansi}, I get: + # + # builtin_spawn gdb -q ... + # ^[[6n(gdb) + # + # While we're addressing this in default_gdb_start, this is not specific + # to gdb, other tools produce the same CSI sequence, and consequently we + # run into trouble in other places (like get_compiler_info). + # + # Set TERM to dumb to prevent the '^[[6n' from occurring. + # + # We could do this only for ishost *-*-mingw*, but that introduces + # inconsistency between platforms, with test-cases passing on one platform + # but failing on the other. So, we do this for all platforms. + setenv TERM dumb + # Don't let a .inputrc file or an existing setting of INPUTRC mess # up the test results. Certain tests (style tests and TUI tests) # want to set the terminal to a non-"dumb" value, and for those we @@ -9282,7 +9387,12 @@ proc core_find {binfile {deletefiles {}} {arg ""}} { file mkdir $coredir catch "system \"(cd ${coredir}; ulimit -c unlimited; ${binfile} ${arg}; true) >/dev/null 2>&1\"" # remote_exec host "${binfile}" - foreach i "${coredir}/core ${coredir}/core.coremaker.c ${binfile}.core" { + set binfile_basename [file tail $binfile] + foreach i [list \ + ${coredir}/core \ + ${coredir}/core.coremaker.c \ + ${coredir}/${binfile_basename}.core \ + ${coredir}/${binfile_basename}.exe.core] { if [remote_file build exists $i] { remote_exec build "mv $i $destcore" set found 1 @@ -9887,6 +9997,10 @@ proc gdb_stdin_log_init { } { set logfile [standard_output_file_with_gdb_instance gdb.in] set in_file [open $logfile w] + + verbose -log "" + verbose -log "Starting logfile: $logfile" + verbose -log "" } # Write to the file for logging gdb input. @@ -10320,7 +10434,11 @@ proc with_override { name override body } { proc with_ansi_styling_terminal { body } { save_vars { ::env(TERM) ::env(NO_COLOR) ::env(COLORTERM) } { # Set environment variables to allow styling. - setenv TERM ansi + if { [ishost *-*-*bsd*] } { + setenv TERM ansiw + } else { + setenv TERM ansi + } unset -nocomplain ::env(NO_COLOR) unset -nocomplain ::env(COLORTERM) diff --git a/gdb/testsuite/lib/gdbserver-support.exp b/gdb/testsuite/lib/gdbserver-support.exp index 346c9b9..2389206 100644 --- a/gdb/testsuite/lib/gdbserver-support.exp +++ b/gdb/testsuite/lib/gdbserver-support.exp @@ -1,4 +1,4 @@ -# Copyright 2000-2024 Free Software Foundation, Inc. +# Copyright 2000-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 @@ -69,7 +69,7 @@ proc gdb_target_cmd_ext { targetname serialport {additional_text ""} } { } -re "Non-stop mode requested, but remote does not support non-stop.*$gdb_prompt $" { verbose "remote does not support non-stop" - return 1 + return 2 } -re "Remote MIPS debugging.*$additional_text.*$gdb_prompt" { verbose "Set target to $targetname" diff --git a/gdb/testsuite/lib/gen-perf-test.exp b/gdb/testsuite/lib/gen-perf-test.exp index a4debf8..dbdc79b 100644 --- a/gdb/testsuite/lib/gen-perf-test.exp +++ b/gdb/testsuite/lib/gen-perf-test.exp @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2024 Free Software Foundation, Inc. +# Copyright (C) 2013-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 diff --git a/gdb/testsuite/lib/go.exp b/gdb/testsuite/lib/go.exp index 4525d77..5f668e2 100644 --- a/gdb/testsuite/lib/go.exp +++ b/gdb/testsuite/lib/go.exp @@ -1,4 +1,4 @@ -# Copyright 2012-2024 Free Software Foundation, Inc. +# Copyright 2012-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 diff --git a/gdb/testsuite/lib/jit-elf-helpers.exp b/gdb/testsuite/lib/jit-elf-helpers.exp index 4d9c055..e5c328e 100644 --- a/gdb/testsuite/lib/jit-elf-helpers.exp +++ b/gdb/testsuite/lib/jit-elf-helpers.exp @@ -1,4 +1,4 @@ -# Copyright 2020-2024 Free Software Foundation, Inc. +# Copyright 2020-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 diff --git a/gdb/testsuite/lib/memory.exp b/gdb/testsuite/lib/memory.exp index 6675641..b8aadb6 100644 --- a/gdb/testsuite/lib/memory.exp +++ b/gdb/testsuite/lib/memory.exp @@ -1,4 +1,4 @@ -# Copyright 2012-2024 Free Software Foundation, Inc. +# Copyright 2012-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 diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp index 206971c..aba13a2 100644 --- a/gdb/testsuite/lib/mi-support.exp +++ b/gdb/testsuite/lib/mi-support.exp @@ -1,4 +1,4 @@ -# Copyright 1999-2024 Free Software Foundation, Inc. +# Copyright 1999-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 diff --git a/gdb/testsuite/lib/my-syscalls.S b/gdb/testsuite/lib/my-syscalls.S index 19df0ca..c514b32 100644 --- a/gdb/testsuite/lib/my-syscalls.S +++ b/gdb/testsuite/lib/my-syscalls.S @@ -1,6 +1,6 @@ /* This testcase is part of GDB, the GNU debugger. - Copyright 2020-2024 Free Software Foundation, Inc. + Copyright 2020-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 diff --git a/gdb/testsuite/lib/my-syscalls.h b/gdb/testsuite/lib/my-syscalls.h index 8de28ae..03c6f7e 100644 --- a/gdb/testsuite/lib/my-syscalls.h +++ b/gdb/testsuite/lib/my-syscalls.h @@ -1,6 +1,6 @@ /* This testcase is part of GDB, the GNU debugger. - Copyright 2020-2024 Free Software Foundation, Inc. + Copyright 2020-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 diff --git a/gdb/testsuite/lib/notty-wrap b/gdb/testsuite/lib/notty-wrap index 93b81fb..3011753 100755 --- a/gdb/testsuite/lib/notty-wrap +++ b/gdb/testsuite/lib/notty-wrap @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (C) 2021-2024 Free Software Foundation, Inc. +# Copyright (C) 2021-2025 Free Software Foundation, Inc. # # This file is part of GDB. # diff --git a/gdb/testsuite/lib/objc.exp b/gdb/testsuite/lib/objc.exp index 1378f56..cf1fed9 100644 --- a/gdb/testsuite/lib/objc.exp +++ b/gdb/testsuite/lib/objc.exp @@ -1,6 +1,6 @@ # This test code is part of GDB, the GNU debugger. -# Copyright 2010-2024 Free Software Foundation, Inc. +# Copyright 2010-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 diff --git a/gdb/testsuite/lib/opencl.exp b/gdb/testsuite/lib/opencl.exp index caa0e1e..2a5300e 100644 --- a/gdb/testsuite/lib/opencl.exp +++ b/gdb/testsuite/lib/opencl.exp @@ -1,4 +1,4 @@ -# Copyright 2010-2024 Free Software Foundation, Inc. +# Copyright 2010-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 diff --git a/gdb/testsuite/lib/opencl_hostapp.c b/gdb/testsuite/lib/opencl_hostapp.c index 7637a0f..c39995f 100644 --- a/gdb/testsuite/lib/opencl_hostapp.c +++ b/gdb/testsuite/lib/opencl_hostapp.c @@ -1,6 +1,6 @@ /* This testcase is part of GDB, the GNU debugger. - Copyright 2010-2024 Free Software Foundation, Inc. + Copyright 2010-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 diff --git a/gdb/testsuite/lib/pascal.exp b/gdb/testsuite/lib/pascal.exp index 236eca1..d76cdca 100644 --- a/gdb/testsuite/lib/pascal.exp +++ b/gdb/testsuite/lib/pascal.exp @@ -1,4 +1,4 @@ -# Copyright 2007-2024 Free Software Foundation, Inc. +# Copyright 2007-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 diff --git a/gdb/testsuite/lib/pdtrace.in b/gdb/testsuite/lib/pdtrace.in index 08b9efa..a629ff6 100755 --- a/gdb/testsuite/lib/pdtrace.in +++ b/gdb/testsuite/lib/pdtrace.in @@ -2,7 +2,7 @@ # A Poor (but Free) Man's dtrace # -# Copyright (C) 2014-2024 Free Software Foundation, Inc. +# Copyright (C) 2014-2025 Free Software Foundation, Inc. # # Contributed by Oracle, Inc. # diff --git a/gdb/testsuite/lib/perftest.exp b/gdb/testsuite/lib/perftest.exp index b4c997a..cca0ede 100644 --- a/gdb/testsuite/lib/perftest.exp +++ b/gdb/testsuite/lib/perftest.exp @@ -1,4 +1,4 @@ -# Copyright (C) 2013-2024 Free Software Foundation, Inc. +# Copyright (C) 2013-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 diff --git a/gdb/testsuite/lib/precise-aligned-alloc.c b/gdb/testsuite/lib/precise-aligned-alloc.c index 4f55ffd..b914afe 100644 --- a/gdb/testsuite/lib/precise-aligned-alloc.c +++ b/gdb/testsuite/lib/precise-aligned-alloc.c @@ -1,6 +1,6 @@ /* This test file is part of GDB, the GNU debugger. - Copyright 2021-2024 Free Software Foundation, Inc. + Copyright 2021-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 diff --git a/gdb/testsuite/lib/prelink-support.exp b/gdb/testsuite/lib/prelink-support.exp index 3aaea0a..a712a7a 100644 --- a/gdb/testsuite/lib/prelink-support.exp +++ b/gdb/testsuite/lib/prelink-support.exp @@ -1,4 +1,4 @@ -# Copyright (C) 2010-2024 Free Software Foundation, Inc. +# Copyright (C) 2010-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 diff --git a/gdb/testsuite/lib/prompt.exp b/gdb/testsuite/lib/prompt.exp index 51997b3..7fa131b 100644 --- a/gdb/testsuite/lib/prompt.exp +++ b/gdb/testsuite/lib/prompt.exp @@ -1,4 +1,4 @@ -# Copyright (C) 2011-2024 Free Software Foundation, Inc. +# Copyright (C) 2011-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 diff --git a/gdb/testsuite/lib/range-stepping-support.exp b/gdb/testsuite/lib/range-stepping-support.exp index 1f1f9d7..27587e5 100644 --- a/gdb/testsuite/lib/range-stepping-support.exp +++ b/gdb/testsuite/lib/range-stepping-support.exp @@ -1,4 +1,4 @@ -# Copyright 2013-2024 Free Software Foundation, Inc. +# Copyright 2013-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 diff --git a/gdb/testsuite/lib/read1.c b/gdb/testsuite/lib/read1.c index 29570c9..c4c9ee2 100644 --- a/gdb/testsuite/lib/read1.c +++ b/gdb/testsuite/lib/read1.c @@ -1,6 +1,6 @@ /* This is part of GDB, the GNU debugger. - Copyright 2011-2024 Free Software Foundation, Inc. + Copyright 2011-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 diff --git a/gdb/testsuite/lib/rocm.exp b/gdb/testsuite/lib/rocm.exp index 5164f1e..d3f201c 100644 --- a/gdb/testsuite/lib/rocm.exp +++ b/gdb/testsuite/lib/rocm.exp @@ -1,4 +1,4 @@ -# Copyright (C) 2019-2024 Free Software Foundation, Inc. +# Copyright (C) 2019-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 diff --git a/gdb/testsuite/lib/rust-support.exp b/gdb/testsuite/lib/rust-support.exp index 971a4a6..94888e9 100644 --- a/gdb/testsuite/lib/rust-support.exp +++ b/gdb/testsuite/lib/rust-support.exp @@ -1,4 +1,4 @@ -# Copyright 2016-2024 Free Software Foundation, Inc. +# Copyright 2016-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 diff --git a/gdb/testsuite/lib/selftest-support.exp b/gdb/testsuite/lib/selftest-support.exp index 0d76e2f..97be023 100644 --- a/gdb/testsuite/lib/selftest-support.exp +++ b/gdb/testsuite/lib/selftest-support.exp @@ -1,4 +1,4 @@ -# Copyright 2003-2024 Free Software Foundation, Inc. +# Copyright 2003-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 @@ -72,21 +72,39 @@ proc selftest_setup { executable function } { # run yourself set description "run until breakpoint at $function" + set re_hs {[^\r\n]+} + set re_args [string cat \ + [string_to_regexp "("] \ + $re_hs \ + [string_to_regexp ")"]] + set re_pass \ + [multi_line \ + "Starting program: $re_hs" \ + ".*" \ + [string cat "Breakpoint $::decimal, $function $re_args at" \ + " ${re_hs}gdb.c:$re_hs"] \ + ".*"] + set re_xfail \ + [multi_line \ + "Starting program: $re_hs" \ + ".*" \ + "Breakpoint $::decimal, $function $re_args$re_hs" \ + ".*"] gdb_test_multiple "run $INTERNAL_GDBFLAGS" "$description" { - -re "Starting program.*Breakpoint \[0-9\]+,.*$function \\(.*\\).* at .*main.c:.*$gdb_prompt $" { - pass "$description" - } - -re "Starting program.*Breakpoint \[0-9\]+,.*$function \\(.*\\).*$gdb_prompt $" { - xfail "$description (line numbers scrambled?)" - } - -re "vfork: No more processes.*$gdb_prompt $" { - fail "$description (out of virtual memory)" - return -1 - } - -re ".*$gdb_prompt $" { - fail "$description" - return -1 - } + -re -wrap $re_pass { + pass $description + } + -re -wrap $re_xfail { + xfail "$description (line numbers scrambled?)" + } + -re -wrap "vfork: No more processes.*" { + fail "$description (out of virtual memory)" + return -1 + } + -re -wrap "" { + fail $description + return -1 + } } return 0 diff --git a/gdb/testsuite/lib/set_unbuffered_mode.c b/gdb/testsuite/lib/set_unbuffered_mode.c index 0c92d55..f0604a0 100644 --- a/gdb/testsuite/lib/set_unbuffered_mode.c +++ b/gdb/testsuite/lib/set_unbuffered_mode.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2024 Free Software Foundation, Inc. +/* Copyright (C) 2008-2025 Free Software Foundation, Inc. This file is part of GDB. diff --git a/gdb/testsuite/lib/sym-info-cmds.exp b/gdb/testsuite/lib/sym-info-cmds.exp index 9714529..c94b06f 100644 --- a/gdb/testsuite/lib/sym-info-cmds.exp +++ b/gdb/testsuite/lib/sym-info-cmds.exp @@ -1,4 +1,4 @@ -# Copyright 2019-2024 Free Software Foundation, Inc. +# Copyright 2019-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 diff --git a/gdb/testsuite/lib/trace-support.exp b/gdb/testsuite/lib/trace-support.exp index 770a930..a8d0699 100644 --- a/gdb/testsuite/lib/trace-support.exp +++ b/gdb/testsuite/lib/trace-support.exp @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2024 Free Software Foundation, Inc. +# Copyright (C) 1998-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 diff --git a/gdb/testsuite/lib/tuiterm.exp b/gdb/testsuite/lib/tuiterm.exp index 4aa1ea2..e1af223 100644 --- a/gdb/testsuite/lib/tuiterm.exp +++ b/gdb/testsuite/lib/tuiterm.exp @@ -1,4 +1,4 @@ -# Copyright 2019-2024 Free Software Foundation, Inc. +# Copyright 2019-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 @@ -33,1264 +33,1690 @@ namespace eval Term { variable _resize_count - proc _log { what } { - verbose "+++ $what" - } + variable _TERM + set _TERM "" - # Call BODY, then log WHAT along with the original and new cursor position. - proc _log_cur { what body } { - variable _cur_row - variable _cur_col + variable _alternate + variable _alternate_setup + set _alternate 0 + set _alternate_setup 0 +} + +proc Term::_log { what } { + verbose "+++ $what" +} - set orig_cur_row $_cur_row - set orig_cur_col $_cur_col +# Call BODY, then log WHAT along with the original and new cursor position. +proc Term::_log_cur { what body } { + variable _cur_row + variable _cur_col - uplevel $body + set orig_cur_row $_cur_row + set orig_cur_col $_cur_col + + set code [catch {uplevel $body} result] - _log "$what, cursor: ($orig_cur_row, $orig_cur_col) -> ($_cur_row, $_cur_col)" + _log "$what, cursor: ($orig_cur_row, $orig_cur_col) -> ($_cur_row, $_cur_col)" + + if { $code == 1 } { + global errorInfo errorCode + return -code $code -errorinfo $errorInfo -errorcode $errorCode $result + } else { + return -code $code $result } +} - # If ARG is empty, return DEF: otherwise ARG. This is useful for - # defaulting arguments in CSIs. - proc _default {arg def} { - if {$arg == ""} { - return $def - } - return $arg +# If ARG is empty, return DEF: otherwise ARG. This is useful for +# defaulting arguments in CSIs. +proc Term::_default {arg def} { + if {$arg == ""} { + return $def } + return $arg +} - # Erase in the line Y from SX to just before EX. - proc _clear_in_line {sx ex y} { - variable _attrs - variable _chars - set lattr [array get _attrs] - while {$sx < $ex} { - set _chars($sx,$y) [list " " $lattr] - incr sx - } +# Erase in the line Y from SX to just before EX. +proc Term::_clear_in_line {sx ex y} { + variable _attrs + variable _chars + set lattr [array get _attrs] + while {$sx < $ex} { + set _chars($sx,$y) [list " " $lattr] + incr sx } +} - # Erase the lines from SY to just before EY. - proc _clear_lines {sy ey} { - variable _cols - while {$sy < $ey} { - _clear_in_line 0 $_cols $sy - incr sy - } +# Erase the lines from SY to just before EY. +proc Term::_clear_lines {sy ey} { + variable _cols + while {$sy < $ey} { + _clear_in_line 0 $_cols $sy + incr sy } +} + +# Beep. +proc Term::_ctl_0x07 {} { +} + +# Return 1 if tuiterm has the bw/auto_left_margin enabled. +proc Term::_have_bw {} { + return [expr \ + [string equal $Term::_TERM "ansiw"] \ + || [string equal $Term::_TERM "ansis"]] +} - # Beep. - proc _ctl_0x07 {} { +# Backspace. +proc Term::_ctl_0x08 { {bw -1} } { + if { $bw == -1 } { + set bw [_have_bw] } + _log_cur "Backspace, bw == $bw" { + variable _cur_col + variable _cur_row + variable _cols - # Backspace. - proc _ctl_0x08 {} { - _log_cur "Backspace" { - variable _cur_col + if { $_cur_col > 0 } { + # No wrapping needed. + incr _cur_col -1 + return + } - if {$_cur_col > 0} { - incr _cur_col -1 - } + if { ! $bw } { + # Wrapping not enabled. + return } + + if { $_cur_row == 0 } { + # Can't wrap. + return + } + + # Wrap to previous line. + set _cur_col [expr $_cols - 1] + incr _cur_row -1 } +} - # Linefeed. - proc _ctl_0x0a {} { - _log_cur "Line feed" { - variable _cur_row - variable _rows - variable _cols - variable _chars - - incr _cur_row 1 - while {$_cur_row >= $_rows} { - # Scroll the display contents. We scroll one line at - # a time here; as _cur_row was only increased by one, - # a single line scroll should be enough to put the - # cursor back on the screen. But we wrap the - # scrolling inside a while loop just to be on the safe - # side. - for {set y 0} {$y < [expr $_rows - 1]} {incr y} { - set next_y [expr $y + 1] - for {set x 0} {$x < $_cols} {incr x} { - set _chars($x,$y) $_chars($x,$next_y) - } - } +# Linefeed. +proc Term::_ctl_0x0a {} { + _log_cur "Line feed" { + variable _cur_row + variable _rows + variable _cols + variable _chars - incr _cur_row -1 + incr _cur_row 1 + while {$_cur_row >= $_rows} { + # Scroll the display contents. We scroll one line at + # a time here; as _cur_row was only increased by one, + # a single line scroll should be enough to put the + # cursor back on the screen. But we wrap the + # scrolling inside a while loop just to be on the safe + # side. + for {set y 0} {$y < [expr $_rows - 1]} {incr y} { + set next_y [expr $y + 1] + for {set x 0} {$x < $_cols} {incr x} { + set _chars($x,$y) $_chars($x,$next_y) + } } + + incr _cur_row -1 } } +} - # Carriage return. - proc _ctl_0x0d {} { - _log_cur "Carriage return" { - variable _cur_col +# Carriage return. +proc Term::_ctl_0x0d {} { + _log_cur "Carriage return" { + variable _cur_col - set _cur_col 0 - } + set _cur_col 0 } +} - # Insert Character. - # - # https://vt100.net/docs/vt510-rm/ICH.html - proc _csi_@ {args} { - set n [_default [lindex $args 0] 1] +# Designate G0 Character Set, USASCII (ESC ( B) +# +# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html (see "ESC ( C", case C = B) +proc Term::_esc_0x28_B {} { + _log "ignored: G0: USASCII" +} - _log_cur "Insert Character ($n)" { - variable _cur_col - variable _cur_row - variable _cols - variable _chars +# Designate G0 Character Set, DEC Special Character and Line Drawing Set (ESC ( 0) +# +# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html (see "ESC ( C", case C = 0) +proc Term::_esc_0x28_0 {} { + _log "ignored: G0: DEC Special Character and Line Drawing Set" +} - # Move characters right of the cursor right by N positions, - # starting with the rightmost one. - for {set in_col [expr $_cols - $n - 1]} {$in_col >= $_cur_col} {incr in_col -1} { - set out_col [expr $in_col + $n] - set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row) - } +# DECKPAM (Application Keypad, ESC =) +# +# https://vt100.net/docs/vt510-rm/DECKPAM.html +proc Term::_esc_0x3d {} { + _log "ignored: Application Keypad" +} + +# DECKPNM (Normal Keypad, ESC >) +# +# https://vt100.net/docs/vt510-rm/DECKPNM.html +proc Term::_esc_0x3e {} { + _log "ignored: Normal Keypad" +} - # Write N blank spaces starting from the cursor. - _clear_in_line $_cur_col [expr $_cur_col + $n] $_cur_row +# Insert Character. +# +# https://vt100.net/docs/vt510-rm/ICH.html +proc Term::_csi_@ {args} { + set n [_default [lindex $args 0] 1] + + _log_cur "Insert Character ($n)" { + variable _cur_col + variable _cur_row + variable _cols + variable _chars + + # Move characters right of the cursor right by N positions, + # starting with the rightmost one. + for {set in_col [expr $_cols - $n - 1]} {$in_col >= $_cur_col} {incr in_col -1} { + set out_col [expr $in_col + $n] + set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row) } + + # Write N blank spaces starting from the cursor. + _clear_in_line $_cur_col [expr $_cur_col + $n] $_cur_row } +} - # Cursor Up. - # - # https://vt100.net/docs/vt510-rm/CUU.html - proc _csi_A {args} { - set arg [_default [lindex $args 0] 1] +# Horizontal Position Absolute. +# +# https://vt100.net/docs/vt510-rm/HPA.html +proc Term::_csi_` {args} { + # Same as Cursor Horizontal Absolute. + return [Term::_csi_G {*}$args] +} - _log_cur "Cursor Up ($arg)" { - variable _cur_row +# Cursor Up. +# +# https://vt100.net/docs/vt510-rm/CUU.html +proc Term::_csi_A {args} { + set arg [_default [lindex $args 0] 1] - set _cur_row [expr {max ($_cur_row - $arg, 0)}] - } + _log_cur "Cursor Up ($arg)" { + variable _cur_row + + set _cur_row [expr {max ($_cur_row - $arg, 0)}] } +} - # Cursor Down. - # - # https://vt100.net/docs/vt510-rm/CUD.html - proc _csi_B {args} { - set arg [_default [lindex $args 0] 1] +# Cursor Down. +# +# https://vt100.net/docs/vt510-rm/CUD.html +proc Term::_csi_B {args} { + set arg [_default [lindex $args 0] 1] - _log_cur "Cursor Down ($arg)" { - variable _cur_row - variable _rows + _log_cur "Cursor Down ($arg)" { + variable _cur_row + variable _rows - set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}] - } + set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}] } +} - # Cursor Forward. - # - # https://vt100.net/docs/vt510-rm/CUF.html - proc _csi_C {args} { - set arg [_default [lindex $args 0] 1] +# Cursor Forward. +# +# https://vt100.net/docs/vt510-rm/CUF.html +proc Term::_csi_C {args} { + set arg [_default [lindex $args 0] 1] - _log_cur "Cursor Forward ($arg)" { - variable _cur_col - variable _cols + _log_cur "Cursor Forward ($arg)" { + variable _cur_col + variable _cols - set _cur_col [expr {min ($_cur_col + $arg, $_cols - 1)}] - } + set _cur_col [expr {min ($_cur_col + $arg, $_cols - 1)}] } +} - # Cursor Backward. - # - # https://vt100.net/docs/vt510-rm/CUB.html - proc _csi_D {args} { - set arg [_default [lindex $args 0] 1] +# Cursor Backward. +# +# https://vt100.net/docs/vt510-rm/CUB.html +proc Term::_csi_D {args} { + set arg [_default [lindex $args 0] 1] - _log_cur "Cursor Backward ($arg)" { - variable _cur_col + _log_cur "Cursor Backward ($arg)" { + variable _cur_col - set _cur_col [expr {max ($_cur_col - $arg, 0)}] - } + set _cur_col [expr {max ($_cur_col - $arg, 0)}] } +} - # Cursor Next Line. - # - # https://vt100.net/docs/vt510-rm/CNL.html - proc _csi_E {args} { - set arg [_default [lindex $args 0] 1] +# Cursor Next Line. +# +# https://vt100.net/docs/vt510-rm/CNL.html +proc Term::_csi_E {args} { + set arg [_default [lindex $args 0] 1] - _log_cur "Cursor Next Line ($arg)" { - variable _cur_col - variable _cur_row - variable _rows + _log_cur "Cursor Next Line ($arg)" { + variable _cur_col + variable _cur_row + variable _rows - set _cur_col 0 - set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}] - } + set _cur_col 0 + set _cur_row [expr {min ($_cur_row + $arg, $_rows - 1)}] } +} - # Cursor Previous Line. - # - # https://vt100.net/docs/vt510-rm/CPL.html - proc _csi_F {args} { - set arg [_default [lindex $args 0] 1] +# Cursor Previous Line. +# +# https://vt100.net/docs/vt510-rm/CPL.html +proc Term::_csi_F {args} { + set arg [_default [lindex $args 0] 1] - _log_cur "Cursor Previous Line ($arg)" { - variable _cur_col - variable _cur_row - variable _rows + _log_cur "Cursor Previous Line ($arg)" { + variable _cur_col + variable _cur_row + variable _rows - set _cur_col 0 - set _cur_row [expr {max ($_cur_row - $arg, 0)}] - } + set _cur_col 0 + set _cur_row [expr {max ($_cur_row - $arg, 0)}] } +} - # Cursor Horizontal Absolute. - # - # https://vt100.net/docs/vt510-rm/CHA.html - proc _csi_G {args} { - set arg [_default [lindex $args 0] 1] +# Cursor Horizontal Absolute. +# +# https://vt100.net/docs/vt510-rm/CHA.html +proc Term::_csi_G {args} { + set arg [_default [lindex $args 0] 1] - _log_cur "Cursor Horizontal Absolute ($arg)" { - variable _cur_col - variable _cols + _log_cur "Cursor Horizontal Absolute ($arg)" { + variable _cur_col + variable _cols - set _cur_col [expr {min ($arg - 1, $_cols)}] - } + set _cur_col [expr {min ($arg, $_cols)} - 1] } +} - # Cursor Position. - # - # https://vt100.net/docs/vt510-rm/CUP.html - proc _csi_H {args} { - set row [_default [lindex $args 0] 1] - set col [_default [lindex $args 1] 1] +# Cursor Position. +# +# https://vt100.net/docs/vt510-rm/CUP.html +proc Term::_csi_H {args} { + set row [_default [lindex $args 0] 1] + set col [_default [lindex $args 1] 1] - _log_cur "Cursor Position ($row, $col)" { - variable _cur_col - variable _cur_row + _log_cur "Cursor Position ($row, $col)" { + variable _cur_col + variable _cur_row - set _cur_row [expr {$row - 1}] - set _cur_col [expr {$col - 1}] - } + set _cur_row [expr {$row - 1}] + set _cur_col [expr {$col - 1}] } +} - # Cursor Horizontal Forward Tabulation. - # - # https://vt100.net/docs/vt510-rm/CHT.html - proc _csi_I {args} { - set n [_default [lindex $args 0] 1] +# Cursor Horizontal Forward Tabulation. +# +# https://vt100.net/docs/vt510-rm/CHT.html +proc Term::_csi_I {args} { + set n [_default [lindex $args 0] 1] - _log_cur "Cursor Horizontal Forward Tabulation ($n)" { - variable _cur_col - variable _cols + _log_cur "Cursor Horizontal Forward Tabulation ($n)" { + variable _cur_col + variable _cols - incr _cur_col [expr {$n * 8 - $_cur_col % 8}] - if {$_cur_col >= $_cols} { - set _cur_col [expr {$_cols - 1}] - } + incr _cur_col [expr {$n * 8 - $_cur_col % 8}] + if {$_cur_col >= $_cols} { + set _cur_col [expr {$_cols - 1}] } } +} - # Erase in Display. - # - # https://vt100.net/docs/vt510-rm/ED.html - proc _csi_J {args} { - set arg [_default [lindex $args 0] 0] - - _log_cur "Erase in Display ($arg)" { - variable _cur_col - variable _cur_row - variable _rows - variable _cols - - if {$arg == 0} { - # Cursor (inclusive) to end of display. - _clear_in_line $_cur_col $_cols $_cur_row - _clear_lines [expr {$_cur_row + 1}] $_rows - } elseif {$arg == 1} { - # Beginning of display to cursor (inclusive). - _clear_lines 0 $_cur_row - _clear_in_line 0 [expr $_cur_col + 1] $_cur_row - } elseif {$arg == 2} { - # Entire display. - _clear_lines 0 $_rows - } +# Erase in Display. +# +# https://vt100.net/docs/vt510-rm/ED.html +proc Term::_csi_J {args} { + set arg [_default [lindex $args 0] 0] + + _log_cur "Erase in Display ($arg)" { + variable _cur_col + variable _cur_row + variable _rows + variable _cols + + if {$arg == 0} { + # Cursor (inclusive) to end of display. + _clear_in_line $_cur_col $_cols $_cur_row + _clear_lines [expr {$_cur_row + 1}] $_rows + } elseif {$arg == 1} { + # Beginning of display to cursor (inclusive). + _clear_lines 0 $_cur_row + _clear_in_line 0 [expr $_cur_col + 1] $_cur_row + } elseif {$arg == 2} { + # Entire display. + _clear_lines 0 $_rows } } +} - # Erase in Line. - # - # https://vt100.net/docs/vt510-rm/EL.html - proc _csi_K {args} { - set arg [_default [lindex $args 0] 0] +# Erase in Line. +# +# https://vt100.net/docs/vt510-rm/EL.html +proc Term::_csi_K {args} { + set arg [_default [lindex $args 0] 0] - _log_cur "Erase in Line ($arg)" { - variable _cur_col - variable _cur_row - variable _cols + _log_cur "Erase in Line ($arg)" { + variable _cur_col + variable _cur_row + variable _cols - if {$arg == 0} { - # Cursor (inclusive) to end of line. - _clear_in_line $_cur_col $_cols $_cur_row - } elseif {$arg == 1} { - # Beginning of line to cursor (inclusive). - _clear_in_line 0 [expr $_cur_col + 1] $_cur_row - } elseif {$arg == 2} { - # Entire line. - _clear_in_line 0 $_cols $_cur_row - } + if {$arg == 0} { + # Cursor (inclusive) to end of line. + _clear_in_line $_cur_col $_cols $_cur_row + } elseif {$arg == 1} { + # Beginning of line to cursor (inclusive). + _clear_in_line 0 [expr $_cur_col + 1] $_cur_row + } elseif {$arg == 2} { + # Entire line. + _clear_in_line 0 $_cols $_cur_row } } +} - # Insert Line - # - # https://vt100.net/docs/vt510-rm/IL.html - proc _csi_L {args} { - set arg [_default [lindex $args 0] 1] +# Insert Line +# +# https://vt100.net/docs/vt510-rm/IL.html +proc Term::_csi_L {args} { + set arg [_default [lindex $args 0] 1] - _log_cur "Insert Line ($arg)" { - variable _cur_col - variable _cur_row - variable _rows - variable _cols - variable _chars + _log_cur "Insert Line ($arg)" { + variable _cur_col + variable _cur_row + variable _rows + variable _cols + variable _chars - set y [expr $_rows - 2] - set next_y [expr $y + $arg] - while {$y >= $_cur_row} { - for {set x 0} {$x < $_cols} {incr x} { - set _chars($x,$next_y) $_chars($x,$y) - } - incr y -1 - incr next_y -1 + set y [expr $_rows - 2] + set next_y [expr $y + $arg] + while {$y >= $_cur_row} { + for {set x 0} {$x < $_cols} {incr x} { + set _chars($x,$next_y) $_chars($x,$y) } - - _clear_lines $_cur_row [expr $_cur_row + $arg] + incr y -1 + incr next_y -1 } + + _clear_lines $_cur_row [expr $_cur_row + $arg] } +} - # Delete line. - # - # https://vt100.net/docs/vt510-rm/DL.html - proc _csi_M {args} { - set count [_default [lindex $args 0] 1] +# Delete line. +# +# https://vt100.net/docs/vt510-rm/DL.html +proc Term::_csi_M {args} { + set count [_default [lindex $args 0] 1] - _log_cur "Delete line ($count)" { - variable _cur_row - variable _rows - variable _cols - variable _chars + _log_cur "Delete line ($count)" { + variable _cur_row + variable _rows + variable _cols + variable _chars - set y $_cur_row - set next_y [expr {$y + $count}] - while {$next_y < $_rows} { - for {set x 0} {$x < $_cols} {incr x} { - set _chars($x,$y) $_chars($x,$next_y) - } - incr y - incr next_y + set y $_cur_row + set next_y [expr {$y + $count}] + while {$next_y < $_rows} { + for {set x 0} {$x < $_cols} {incr x} { + set _chars($x,$y) $_chars($x,$next_y) } - _clear_lines $y $_rows + incr y + incr next_y } + _clear_lines $y $_rows } +} - # Delete Character. - # - # https://vt100.net/docs/vt510-rm/DCH.html - proc _csi_P {args} { - set count [_default [lindex $args 0] 1] - - _log_cur "Delete character ($count)" { - variable _cur_row - variable _cur_col - variable _chars - variable _cols +# Delete Character. +# +# https://vt100.net/docs/vt510-rm/DCH.html +proc Term::_csi_P {args} { + set count [_default [lindex $args 0] 1] - # Move all characters right of the cursor N positions left. - set out_col [expr $_cur_col] - set in_col [expr $_cur_col + $count] + _log_cur "Delete character ($count)" { + variable _cur_row + variable _cur_col + variable _chars + variable _cols - while {$in_col < $_cols} { - set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row) - incr in_col - incr out_col - } + # Move all characters right of the cursor N positions left. + set out_col [expr $_cur_col] + set in_col [expr $_cur_col + $count] - # Clear the rest of the line. - _clear_in_line $out_col $_cols $_cur_row + while {$in_col < $_cols} { + set _chars($out_col,$_cur_row) $_chars($in_col,$_cur_row) + incr in_col + incr out_col } + + # Clear the rest of the line. + _clear_in_line $out_col $_cols $_cur_row } +} - # Pan Down - # - # https://vt100.net/docs/vt510-rm/SU.html - proc _csi_S {args} { - set count [_default [lindex $args 0] 1] +# Pan Down +# +# https://vt100.net/docs/vt510-rm/SU.html +proc Term::_csi_S {args} { + set count [_default [lindex $args 0] 1] - _log_cur "Pan Down ($count)" { - variable _cur_col - variable _cur_row - variable _cols - variable _rows - variable _chars + _log_cur "Pan Down ($count)" { + variable _cur_col + variable _cur_row + variable _cols + variable _rows + variable _chars - # The following code is written without consideration for - # the scroll margins. At this time this comment was - # written the tuiterm library doesn't support the scroll - # margins. If/when that changes, then the following will - # need to be updated. + # The following code is written without consideration for + # the scroll margins. At this time this comment was + # written the tuiterm library doesn't support the scroll + # margins. If/when that changes, then the following will + # need to be updated. - set dy 0 - set y $count + set dy 0 + set y $count - while {$y < $_rows} { - for {set x 0} {$x < $_cols} {incr x} { - set _chars($x,$dy) $_chars($x,$y) - } - incr y 1 - incr dy 1 + while {$y < $_rows} { + for {set x 0} {$x < $_cols} {incr x} { + set _chars($x,$dy) $_chars($x,$y) } - - _clear_lines $dy $_rows + incr y 1 + incr dy 1 } + + _clear_lines $dy $_rows } +} - # Pan Up - # - # https://vt100.net/docs/vt510-rm/SD.html - proc _csi_T {args} { - set count [_default [lindex $args 0] 1] +# Pan Up +# +# https://vt100.net/docs/vt510-rm/SD.html +proc Term::_csi_T {args} { + set count [_default [lindex $args 0] 1] - _log_cur "Pan Up ($count)" { - variable _cur_col - variable _cur_row - variable _cols - variable _rows - variable _chars + _log_cur "Pan Up ($count)" { + variable _cur_col + variable _cur_row + variable _cols + variable _rows + variable _chars - # The following code is written without consideration for - # the scroll margins. At this time this comment was - # written the tuiterm library doesn't support the scroll - # margins. If/when that changes, then the following will - # need to be updated. + # The following code is written without consideration for + # the scroll margins. At this time this comment was + # written the tuiterm library doesn't support the scroll + # margins. If/when that changes, then the following will + # need to be updated. - set y [expr $_rows - $count] - set dy $_rows + set y [expr $_rows - $count] + set dy $_rows - while {$dy >= $count} { - for {set x 0} {$x < $_cols} {incr x} { - set _chars($x,$dy) $_chars($x,$y) - } - incr y -1 - incr dy -1 + while {$dy >= $count} { + for {set x 0} {$x < $_cols} {incr x} { + set _chars($x,$dy) $_chars($x,$y) } - - _clear_lines 0 $count + incr y -1 + incr dy -1 } + + _clear_lines 0 $count } +} - # Erase chars. - # - # https://vt100.net/docs/vt510-rm/ECH.html - proc _csi_X {args} { - set n [_default [lindex $args 0] 1] +# Erase chars. +# +# https://vt100.net/docs/vt510-rm/ECH.html +proc Term::_csi_X {args} { + set n [_default [lindex $args 0] 1] - _log_cur "Erase chars ($n)" { - # Erase characters but don't move cursor. - variable _cur_col - variable _cur_row - variable _attrs - variable _chars + _log_cur "Erase chars ($n)" { + # Erase characters but don't move cursor. + variable _cur_col + variable _cur_row + variable _attrs + variable _chars - set lattr [array get _attrs] - set x $_cur_col - for {set i 0} {$i < $n} {incr i} { - set _chars($x,$_cur_row) [list " " $lattr] - incr x - } + set lattr [array get _attrs] + set x $_cur_col + for {set i 0} {$i < $n} {incr i} { + set _chars($x,$_cur_row) [list " " $lattr] + incr x } } +} - # Cursor Backward Tabulation. - # - # https://vt100.net/docs/vt510-rm/CBT.html - proc _csi_Z {args} { - set n [_default [lindex $args 0] 1] +# Cursor Backward Tabulation. +# +# https://vt100.net/docs/vt510-rm/CBT.html +proc Term::_csi_Z {args} { + set n [_default [lindex $args 0] 1] - _log_cur "Cursor Backward Tabulation ($n)" { - variable _cur_col + _log_cur "Cursor Backward Tabulation ($n)" { + variable _cur_col - set _cur_col [expr {max (int (($_cur_col - 1) / 8) * 8 - ($n - 1) * 8, 0)}] - } + set _cur_col [expr {max (int (($_cur_col - 1) / 8) * 8 - ($n - 1) * 8, 0)}] } +} - # Repeat. - # - # https://www.xfree86.org/current/ctlseqs.html (See `(REP)`) - proc _csi_b {args} { - set n [_default [lindex $args 0] 1] +# Repeat. +# +# https://www.xfree86.org/current/ctlseqs.html (See `(REP)`) +proc Term::_csi_b {args} { + set n [_default [lindex $args 0] 1] - _log_cur "Repeat ($n)" { - variable _last_char + _log_cur "Repeat ($n)" { + variable _last_char - _insert [string repeat $_last_char $n] - } + _insert [string repeat $_last_char $n] } +} - # Vertical Line Position Absolute. - # - # https://vt100.net/docs/vt510-rm/VPA.html - proc _csi_d {args} { - set row [_default [lindex $args 0] 1] +# Vertical Line Position Absolute. +# +# https://vt100.net/docs/vt510-rm/VPA.html +proc Term::_csi_d {args} { + set row [_default [lindex $args 0] 1] - _log_cur "Vertical Line Position Absolute ($row)" { - variable _cur_row - variable _rows + _log_cur "Vertical Line Position Absolute ($row)" { + variable _cur_row + variable _rows - set _cur_row [expr min ($row - 1, $_rows - 1)] - } + set _cur_row [expr min ($row - 1, $_rows - 1)] } +} - # Reset the attributes in attributes array UPVAR_NAME to the default values. - proc _reset_attrs { upvar_name } { - upvar $upvar_name var - array set var { - intensity normal - fg default - bg default - underline 0 - reverse 0 - invisible 0 - blinking 0 +# Set Mode (SM, CSI h) +# +# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html +proc Term::_csi_h { args } { + foreach item $args { + switch -exact -- $item { + 4 { + # Insert Mode (IRM) + _log "ignored: insert mode" + } + default { + error unsupported + } } } +} - # Translate the color numbers as used in proc _csi_m to a name. - proc _color_attr { n } { - switch -exact -- $n { - 0 { - return black +# Reset Mode (RM, CSI l) +# +# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html +proc Term::_csi_l { args } { + foreach item $args { + switch -exact -- $item { + 4 { + # Replace Mode (IRM) + _log "ignored: replace mode" + } + default { + error unsupported } + } + } +} + +# Set Scrolling Region (DECSTBM, CSI Ps ; Ps r) +# +# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html +proc Term::_csi_r { top bottom } { + _log "ignored: set scrolling region" +} + +# Window manipulation (XTWINOPS, CSI Ps ; Ps ; Ps t) +# +# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html +proc Term::_csi_t { arg1 arg2 arg3 } { + if { $arg1 == 22 && $arg2 == 0 && $arg3 == 0 } { + _log "ignored: Save xterm icon and window title on stack" + return + } + + if { $arg1 == 23 && $arg2 == 0 && $arg3 == 0 } { + _log "ignored: Restore xterm icon and window title from stack" + return + } + + error unsupported +} + +# DECSET (CSI ? h) +# +# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking +proc Term::_csi_0x3f_h { args } { + foreach item $args { + switch -exact -- $item { 1 { - return red + _log "ignored: Application Cursor Keys" } - 2 { - return green + 7 { + _log "ignored: autowrap mode" } - 3 { - return yellow + 1000 { + _log "ignored: Send Mouse X & Y on button press and release" } - 4 { - return blue + 1006 { + _log "ignored: Enable SGR Mouse Mode" } - 5 { - return magenta + 1049 { + _log "switch to alternate screen" + _set_alternate 1 } - 6 { - return cyan + default { + error unsupported + } + } + } +} + +# DECRST (CSI ? l) +# +# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking +proc Term::_csi_0x3f_l { args } { + foreach item $args { + switch -exact -- $item { + 1 { + _log "ignored: Normal Cursor Keys" } 7 { - return white + _log "ignored: no autowrap mode" + } + 1000 { + _log "ignored: Don't send Mouse X & Y on button press and release" + } + 1006 { + _log "ignored: Disable SGR Mouse Mode" + } + 1049 { + _log "switch from alternate screen" + _set_alternate 0 + } + default { + error "unsupported" } - default { error "unsupported color number: $n" } } } +} - # Select Graphic Rendition. - # - # https://vt100.net/docs/vt510-rm/SGR.html - proc _csi_m {args} { - _log_cur "Select Graphic Rendition ([join $args {, }])" { - variable _attrs +# Reset the attributes in attributes array UPVAR_NAME to the default values. +proc Term::_reset_attrs { upvar_name } { + upvar $upvar_name var + array set var { + intensity normal + fg default + bg default + underline 0 + reverse 0 + invisible 0 + blinking 0 + } +} - foreach item $args { - switch -exact -- $item { - "" - 0 { - _reset_attrs _attrs - } - 1 { - set _attrs(intensity) bold - } - 2 { - set _attrs(intensity) dim - } - 4 { - set _attrs(underline) 1 - } - 5 { - set _attrs(blinking) 1 - } - 7 { - set _attrs(reverse) 1 - } - 8 { - set _attrs(invisible) 1 - } - 22 { - set _attrs(intensity) normal - } - 24 { - set _attrs(underline) 0 - } - 25 { - set _attrs(blinking) 0 - } - 27 { - set _attrs(reverse) 0 - } - 28 { - set _attrs(invisible) 0 - } - 30 - 31 - 32 - 33 - 34 - 35 - 36 - 37 { - set _attrs(fg) [_color_attr [expr $item - 30]] - } - 39 { - set _attrs(fg) default - } - 40 - 41 - 42 - 43 - 44 - 45 - 46 - 47 { - set _attrs(bg) [_color_attr [expr $item - 40]] - } - 49 { - set _attrs(bg) default - } +# Translate the color numbers as used in proc _csi_m to a name. +proc Term::_color_attr { n } { + switch -exact -- $n { + 0 { + return black + } + 1 { + return red + } + 2 { + return green + } + 3 { + return yellow + } + 4 { + return blue + } + 5 { + return magenta + } + 6 { + return cyan + } + 7 { + return white + } + default { error "unsupported color number: $n" } + } +} + +# Select Graphic Rendition. +# +# https://vt100.net/docs/vt510-rm/SGR.html +proc Term::_csi_m {args} { + if { [llength $args] == 0 } { + # Apply default. + set args [list 0] + } + + _log_cur "Select Graphic Rendition ([join $args {, }])" { + variable _attrs + + foreach item $args { + switch -exact -- $item { + "" - 0 { + _reset_attrs _attrs + } + 1 { + set _attrs(intensity) bold + } + 2 { + set _attrs(intensity) dim + } + 4 { + set _attrs(underline) 1 + } + 5 { + set _attrs(blinking) 1 + } + 7 { + set _attrs(reverse) 1 + } + 8 { + set _attrs(invisible) 1 + } + 22 { + set _attrs(intensity) normal + } + 24 { + set _attrs(underline) 0 + } + 25 { + set _attrs(blinking) 0 + } + 27 { + set _attrs(reverse) 0 + } + 28 { + set _attrs(invisible) 0 + } + 30 - 31 - 32 - 33 - 34 - 35 - 36 - 37 { + set _attrs(fg) [_color_attr [expr $item - 30]] + } + 39 { + set _attrs(fg) default + } + 40 - 41 - 42 - 43 - 44 - 45 - 46 - 47 { + set _attrs(bg) [_color_attr [expr $item - 40]] + } + 49 { + set _attrs(bg) default } } } } +} - # Insert string at the cursor location. - proc _insert {str} { - _log_cur "Inserted string '$str'" { - _log "Inserting string '$str'" - - variable _cur_col - variable _cur_row - variable _rows - variable _cols - variable _attrs - variable _chars - set lattr [array get _attrs] - foreach char [split $str {}] { - _log_cur " Inserted char '$char'" { - set _chars($_cur_col,$_cur_row) [list $char $lattr] - incr _cur_col - if {$_cur_col >= $_cols} { - set _cur_col 0 - incr _cur_row - if {$_cur_row >= $_rows} { - error "FIXME scroll" - } +# Request Terminal Parameters (DECREQTPARM) +# +# https://invisible-island.net/xterm/ctlseqs/ctlseqs.html +# https://vt100.net/docs/vt100-ug/chapter3.html +proc Term::_csi_x {} { + # Ignore. +} + +# Insert string at the cursor location. +proc Term::_insert {str} { + _log_cur "Inserted string '$str'" { + _log "Inserting string '$str'" + + variable _cur_col + variable _cur_row + variable _rows + variable _cols + variable _attrs + variable _chars + set lattr [array get _attrs] + foreach char [split $str {}] { + _log_cur " Inserted char '$char'" { + set _chars($_cur_col,$_cur_row) [list $char $lattr] + incr _cur_col + if {$_cur_col >= $_cols} { + set _cur_col 0 + incr _cur_row + if {$_cur_row >= $_rows} { + error "FIXME scroll" } } } } + + variable _last_char + set _last_char [string index $str end] } +} - # Move the cursor to the (0-based) COL and ROW positions. - proc _move_cursor { col row } { - variable _cols - variable _rows - variable _cur_col - variable _cur_row +# Move the cursor to the (0-based) COL and ROW positions. +proc Term::_move_cursor { col row } { + variable _cols + variable _rows + variable _cur_col + variable _cur_row - if { $col < 0 || $col >= $_cols } { - error "_move_cursor: invalid col value: $col" - } + if { $col < 0 || $col >= $_cols } { + error "_move_cursor: invalid col value: $col" + } + + if { $row < 0 || $row >= $_rows } { + error "_move_cursor: invalid row value: $row" + } - if { $row < 0 || $row >= $_rows } { - error "_move_cursor: invalid row value: $row" - } + set _cur_col $col + set _cur_row $row +} - set _cur_col $col - set _cur_row $row +# Enable or disable alternate screen. +proc Term::_set_alternate { enable } { + variable _alternate + if { $enable == $_alternate } { + return } + set _alternate $enable - # Initialize. - proc _setup {rows cols} { - global stty_init - set stty_init "rows $rows columns $cols" + variable _attrs + variable _chars + variable _cur_col + variable _cur_row - variable _rows - variable _cols - variable _cur_col - variable _cur_row - variable _attrs - variable _resize_count + variable _save_attrs + variable _save_chars + variable _save_cur_col + variable _save_cur_row - set _rows $rows - set _cols $cols - set _cur_col 0 - set _cur_row 0 - set _resize_count 0 - _reset_attrs _attrs - - _clear_lines 0 $_rows - } - - # Accept some output from gdb and update the screen. - # Return 1 if successful, or 0 if a timeout occurred. - proc accept_gdb_output { } { - global expect_out - gdb_expect { - -re "^\[\x07\x08\x0a\x0d\]" { - 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\])" { - _log "wait_for: unsupported escape" - error "unsupported escape" - } - -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) - variable _last_char - set _last_char [string index $expect_out(0,string) end] - } + variable _alternate_setup - 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 { $_alternate_setup } { + set tmp $_save_chars + } + set _save_chars [array get _chars] + if { $_alternate_setup } { + array set _chars $tmp + } - return 1 + if { $_alternate_setup } { + set tmp $_save_attrs + } + set _save_attrs [array get _attrs] + if { $_alternate_setup } { + array set _attrs $tmp } - # Print arg using "verbose -log" if DEBUG_TUI_MATCHING == 1. - proc debug_tui_matching { arg } { - set debug 0 - if { [info exists ::DEBUG_TUI_MATCHING] } { - set debug $::DEBUG_TUI_MATCHING - } + if { $_alternate_setup } { + set tmp $_save_cur_col + } + set _save_cur_col $_cur_col + if { $_alternate_setup } { + set _cur_col $tmp + } - if { ! $debug } { - return - } + if { $_alternate_setup } { + set tmp $_save_cur_row + } + set _save_cur_row $_cur_row + if { $_alternate_setup } { + set _cur_row $tmp + } - verbose -log "$arg" + if { ! $_alternate_setup } { + variable _rows + variable _cols + _setup $_rows $_cols + set _alternate_setup 1 } +} - # Accept some output from gdb and update the screen. WAIT_FOR is - # a regexp matching the line to wait for. Return 0 on timeout, 1 - # on success. - proc wait_for {wait_for} { - global gdb_prompt - variable _cur_col - variable _cur_row +# Initialize. +proc Term::_setup {rows cols} { + global stty_init + set stty_init "rows $rows columns $cols" + + variable _rows + variable _cols + variable _cur_col + variable _cur_row + variable _attrs + variable _resize_count + + set _rows $rows + set _cols $cols + set _cur_col 0 + set _cur_row 0 + set _resize_count 0 + _reset_attrs _attrs - set fn "wait_for" + _clear_lines 0 $_rows +} - set prompt_wait_for "(^|\\|)$gdb_prompt \$" - if { $wait_for == "" } { - set wait_for $prompt_wait_for +# Accept some output from gdb and update the screen. +# Return 1 if successful, or 0 if a timeout occurred. +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 ^$re_ctls { + scan $expect_out(0,string) %c val + set hexval [format "%02x" $val] + _log "wait_for: _ctl_0x${hexval}" + _ctl_0x${hexval} + } + -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 } + } - debug_tui_matching "$fn: regexp: '$wait_for'" + if { !$have_esc } { + return 1 + } - while 1 { - if { [accept_gdb_output] == 0 } { - return 0 - } + 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 "^(\[\\(\])(\[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 "^(\[=>\])" { + scan $expect_out(1,string) %c val + set hexval [format "%02x" $val] + _esc_0x$hexval + } + -re "^$re_csi" { + _log "wait_for: CSI" + set have_csi 1 + } - # If the cursor appears just after the prompt, return. It - # isn't reliable to check this only after an insertion, - # because curses may make "unusual" redrawing decisions. - if {$wait_for == "$prompt_wait_for"} { - set prev [get_line $_cur_row $_cur_col] - } else { - set prev [get_line $_cur_row] - } - if {[regexp -- $wait_for $prev]} { - debug_tui_matching "$fn: match: '$prev'" - if {$wait_for == "$prompt_wait_for"} { - break - } - set wait_for $prompt_wait_for - debug_tui_matching "$fn: regexp prompt: '$wait_for'" - } else { - debug_tui_matching "$fn: mismatch: '$prev'" + 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 } - # Accept some output from gdb and update the screen. Wait for the screen - # region X/Y/WIDTH/HEIGTH to matches REGEXP. Return 0 on timeout, 1 on - # success. - proc wait_for_region_contents {x y width height regexp} { - while 1 { - if { [accept_gdb_output] == 0 } { - return 0 - } - - if { [check_region_contents_p $x $y $width $height $regexp] } { - break + set re_csi_prefix {[?]} + set re_csi_args {[0-9;]} + set re_csi_cmd {[a-zA-Z@`]} + gdb_expect { + -re "^($re_csi_cmd)" { + set cmd $expect_out(1,string) + _log "wait_for: _csi_$cmd" + eval _csi_$cmd + } + -re "^($re_csi_args*)($re_csi_cmd)" { + set params [split $expect_out(1,string) ";"] + set cmd $expect_out(2,string) + _log "wait_for: _csi_$cmd <<<$params>>>" + eval _csi_$cmd $params + } + -re "^($re_csi_prefix?)($re_csi_args*)($re_csi_cmd)" { + set prefix $expect_out(1,string) + set params [split $expect_out(2,string) ";"] + set cmd $expect_out(3,string) + scan $prefix %c val + set hexval [format "%02x" $val] + _log "wait_for: _csi_0x${hexval}_$cmd <<<$expect_out(1,string)>>>" + eval _csi_0x${hexval}_$cmd $params + } + + timeout { + # Assume a timeout means we somehow missed the + # expected result, and carry on. + if { $warn } { + warning "timeout in accept_gdb_output following CSI" + dump_screen } + _insert "^\[\[" + return 0 } + } - return 1 + return 1 +} + +# Print arg using "verbose -log" if DEBUG_TUI_MATCHING == 1. +proc Term::debug_tui_matching { arg } { + set debug 0 + if { [info exists ::DEBUG_TUI_MATCHING] } { + set debug $::DEBUG_TUI_MATCHING } - # Setup the terminal with dimensions ROWSxCOLS, TERM=ansi, and execute - # BODY. - proc with_tuiterm {rows cols body} { - global env stty_init - save_vars {env(TERM) env(NO_COLOR) stty_init} { - setenv TERM ansi - setenv NO_COLOR "" - _setup $rows $cols + if { ! $debug } { + return + } - uplevel $body - } + verbose -log "$arg" +} + +# Accept some output from gdb and update the screen. WAIT_FOR is +# a regexp matching the line to wait for. Return 0 on timeout, 1 +# on success. +proc Term::wait_for {wait_for} { + global gdb_prompt + variable _cur_col + variable _cur_row + + set fn "wait_for" + + set prompt_wait_for "(^|\\|)$gdb_prompt \$" + if { $wait_for == "" } { + set wait_for $prompt_wait_for } - # Like ::clean_restart, but ensures that gdb starts in an - # environment where the TUI can work. ROWS and COLS are the size - # of the terminal. EXECUTABLE, if given, is passed to - # clean_restart. - proc clean_restart {rows cols {executable {}}} { - with_tuiterm $rows $cols { - save_vars { ::GDBFLAGS } { - # Make GDB not print the directory names. Use this setting to - # remove the differences in test runs due to varying directory - # names. - append ::GDBFLAGS " -ex \"set filename-display basename\"" + debug_tui_matching "$fn: regexp: '$wait_for'" - if {$executable == ""} { - ::clean_restart - } else { - ::clean_restart $executable - } - } + while 1 { + if { [accept_gdb_output] == 0 } { + return 0 + } - ::gdb_test_no_output "set pagination off" + # If the cursor appears just after the prompt, return. It + # isn't reliable to check this only after an insertion, + # because curses may make "unusual" redrawing decisions. + if {$wait_for == "$prompt_wait_for"} { + set prev [get_line $_cur_row $_cur_col] + } else { + set prev [get_line $_cur_row] } - } - # Generate prompt on TUIterm. - proc gen_prompt {} { - # Generate a prompt. - send_gdb "echo\n" + if { ![regexp -- $wait_for $prev] } { + debug_tui_matching "$fn: mismatch: '$prev'" + continue + } - # Drain the output before the prompt. - gdb_expect { - -re "echo\r\n" { + if {$wait_for == "$prompt_wait_for"} { + # We've detected that the cursor is just after the prompt. + # Now check that there's nothing else on the line. + set prev [get_line $_cur_row] + if { ![regexp -- "(^|\\|)$gdb_prompt +($|\\||\\+)" $prev] } { + debug_tui_matching "$fn: mismatch: '$prev'" + continue } } - # Interpret prompt using TUIterm. - wait_for "" - } + debug_tui_matching "$fn: match: '$prev'" - # Setup ready for starting the tui, but don't actually start it. - # Returns 1 on success, 0 if TUI tests should be skipped. - proc prepare_for_tui {} { - if { [is_remote host] } { - # In clean_restart, we're using "setenv TERM ansi", which has - # effect on build. If we have [is_remote host] == 0, so - # build == host, then it also has effect on host. But for - # [is_remote host] == 1, it has no effect on host. - return 0 + if {$wait_for == "$prompt_wait_for"} { + # Matched the prompt, we're done. + break } - if {![allow_tui_tests]} { + # Now try to match the prompt. + set wait_for $prompt_wait_for + debug_tui_matching "$fn: regexp prompt: '$wait_for'" + } + + return 1 +} + +# Accept some output from gdb and update the screen. Wait for the screen +# region X/Y/WIDTH/HEIGTH to matches REGEXP. Return 0 on timeout, 1 on +# success. +proc Term::wait_for_region_contents {x y width height regexp} { + while 1 { + if { [accept_gdb_output] == 0 } { return 0 } - gdb_test_no_output "set tui border-kind ascii" - gdb_test_no_output "maint set tui-resize-message on" - return 1 + if { [check_region_contents_p $x $y $width $height $regexp] } { + break + } } - # Start the TUI. Returns 1 on success, 0 if TUI tests should be - # skipped. - proc enter_tui {} { - if {![prepare_for_tui]} { + return 1 +} + +# Accept some output from gdb and update the screen. Wait for the current +# screen line to match REGEXP and cursor position POS, unless POS is empty. +# Return 0 on timeout, 1 on success. +proc Term::wait_for_line { regexp {pos ""} } { + variable _cur_row + variable _cur_col + variable _cols + + while 1 { + if { [accept_gdb_output] == 0 } { return 0 } - command_no_prompt_prefix "tui enable" - return 1 - } + if { ![check_region_contents_p 0 $_cur_row $_cols 1 $regexp] } { + continue + } - # Send the command CMD to gdb, then wait for a gdb prompt to be - # seen in the TUI. CMD should not end with a newline -- that will - # be supplied by this function. - proc command {cmd} { - global gdb_prompt - send_gdb "$cmd\n" - set str [string_to_regexp $cmd] - set str "(^|\\|)$gdb_prompt $str" - wait_for $str - } - - # As proc command, but don't wait for an initial prompt. This is used for - # initial terminal commands, where there's no prompt yet. - proc command_no_prompt_prefix {cmd} { - gen_prompt - command $cmd - } - - # Apply the attribute list in ATTRS to attributes array UPVAR_NAME. - # Return a string annotating the changed attributes. - proc apply_attrs { upvar_name attrs } { - set res "" - upvar $upvar_name var - foreach { attr val } $attrs { - if { $var($attr) != $val } { - append res "<$attr:$val>" - set var($attr) $val - } + if { $pos == "" || $_cur_col == $pos } { + break } + } - return $res + return 1 +} + +# In BODY, when using Term::with_tuiterm, use TERM instead of the default. + +proc Term::with_term { term body } { + save_vars { Term::_TERM } { + set Term::_TERM $term + uplevel $body } +} - # Return the text of screen line N. Lines are 0-based. If C is given, - # stop before column C. Columns are also zero-based. If ATTRS, annotate - # with attributes. - proc get_line_1 {n c attrs} { - variable _rows - # This can happen during resizing, if the cursor seems to - # temporarily be off-screen. - if {$n >= $_rows} { - return "" +# Setup the terminal with dimensions ROWSxCOLS, TERM=ansi, and execute +# BODY. +proc Term::with_tuiterm {rows cols body} { + global env stty_init + variable _TERM + save_vars {env(TERM) env(NO_COLOR) stty_init} { + if { $Term::_TERM != "" } { + setenv TERM $Term::_TERM + } elseif { [ishost *-*-*bsd*] } { + setenv TERM ansiw + } else { + setenv TERM ansi } + # Save active TERM variable. + set Term::_TERM $env(TERM) - set result "" - variable _cols - variable _chars - set c [_default $c $_cols] - set x 0 - if { $attrs } { - _reset_attrs line_attrs - } - while {$x < $c} { - if { $attrs } { - set char_attrs [lindex $_chars($x,$n) 1] - append result [apply_attrs line_attrs $char_attrs] + setenv NO_COLOR "" + _setup $rows $cols + + uplevel $body + } +} + +# Like ::clean_restart, but ensures that gdb starts in an +# environment where the TUI can work. ROWS and COLS are the size +# of the terminal. EXECUTABLE, if given, is passed to +# clean_restart. +proc Term::clean_restart {rows cols {executable {}}} { + with_tuiterm $rows $cols { + save_vars { ::GDBFLAGS } { + # Make GDB not print the directory names. Use this setting to + # remove the differences in test runs due to varying directory + # names. + append ::GDBFLAGS " -ex \"set filename-display basename\"" + + if {$executable == ""} { + ::clean_restart + } else { + ::clean_restart $executable } - append result [lindex $_chars($x,$n) 0] - incr x } - if { $attrs } { - _reset_attrs zero_attrs - set char_attrs [array get zero_attrs] - append result [apply_attrs line_attrs $char_attrs] + + ::gdb_test_no_output "set pagination off" + } +} + +# Generate prompt on TUIterm. +proc Term::gen_prompt {} { + # Generate a prompt. + send_gdb "echo\n" + + # Drain the output before the prompt. + gdb_expect { + -re "echo\r\n" { } - return $result } - # Return the text of screen line N, without attributes. Lines are - # 0-based. If C is given, stop before column C. Columns are also - # zero-based. - proc get_line {n {c ""} } { - return [get_line_1 $n $c 0] + # Interpret prompt using TUIterm. + wait_for "" +} + +# Setup ready for starting the tui, but don't actually start it. +# Returns 1 on success, 0 if TUI tests should be skipped. +proc Term::prepare_for_tui {} { + if { [is_remote host] } { + # In clean_restart, we're using "setenv TERM ansi", which has + # effect on build. If we have [is_remote host] == 0, so + # build == host, then it also has effect on host. But for + # [is_remote host] == 1, it has no effect on host. + return 0 } - # As get_line, but annotate with attributes. - proc get_line_with_attrs {n {c ""}} { - return [get_line_1 $n $c 1] + if {![allow_tui_tests]} { + return 0 } - # Get just the character at (X, Y). - proc get_char {x y} { - variable _chars - return [lindex $_chars($x,$y) 0] + gdb_test_no_output "set tui border-kind ascii" + gdb_test_no_output "maint set tui-resize-message on" + # When matching GDB output using Term::wait_for, the number of + # matching attempts in wait_for can be influenced by CLI styling. + # Disable it by default to avoid this. + gdb_test_no_output "set style enabled off" + return 1 +} + +# Start the TUI. Returns 1 on success, 0 if TUI tests should be +# skipped. +proc Term::enter_tui {} { + if {![prepare_for_tui]} { + return 0 } - # Get the entire screen as a string. - proc get_all_lines {} { - variable _rows - variable _cols - variable _chars + command_no_prompt_prefix "tui enable" + return 1 +} - set result "" - for {set y 0} {$y < $_rows} {incr y} { - for {set x 0} {$x < $_cols} {incr x} { - append result [lindex $_chars($x,$y) 0] - } - append result "\n" +# Send the command CMD to gdb, then wait for a gdb prompt to be +# seen in the TUI. CMD should not end with a newline -- that will +# be supplied by this function. +proc Term::command {cmd} { + global gdb_prompt + send_gdb "$cmd\n" + set str [string_to_regexp $cmd] + set str "(^|\\|)$gdb_prompt $str" + wait_for $str +} + +# As proc command, but don't wait for an initial prompt. This is used for +# initial terminal commands, where there's no prompt yet. +proc Term::command_no_prompt_prefix {cmd} { + gen_prompt + command $cmd +} + +# Apply the attribute list in ATTRS to attributes array UPVAR_NAME. +# Return a string annotating the changed attributes. +proc Term::apply_attrs { upvar_name attrs } { + set res "" + upvar $upvar_name var + foreach { attr val } $attrs { + if { $var($attr) != $val } { + append res "<$attr:$val>" + set var($attr) $val } + } - return $result + return $res +} + +# Return the text of screen line N. Lines are 0-based. Start at column +# X. If C is non-empty, stop before column C. Columns are also +# zero-based. If ATTRS, annotate with attributes. +proc Term::get_string {n x c {attrs 0}} { + variable _rows + # This can happen during resizing, if the cursor seems to + # temporarily be off-screen. + if {$n >= $_rows} { + return "" } - # Get the text just before the cursor. - proc get_current_line {} { - variable _cur_col - variable _cur_row - return [get_line $_cur_row $_cur_col] + set result "" + variable _cols + variable _chars + set c [_default $c $_cols] + if { $attrs } { + _reset_attrs line_attrs } + while {$x < $c} { + if { $attrs } { + set char_attrs [lindex $_chars($x,$n) 1] + append result [apply_attrs line_attrs $char_attrs] + } + append result [lindex $_chars($x,$n) 0] + incr x + } + if { $attrs } { + _reset_attrs zero_attrs + set char_attrs [array get zero_attrs] + append result [apply_attrs line_attrs $char_attrs] + } + return $result +} - # Helper function for check_box. Returns empty string if the box - # is found, description of why not otherwise. - proc _check_box {x y width height} { - set x2 [expr {$x + $width - 1}] - set y2 [expr {$y + $height - 1}] +# Return the text of screen line N. Lines are 0-based. Start at column +# X. If C is non-empty, stop before column C. Columns are also +# zero-based. Annotate with attributes. +proc Term::get_string_with_attrs { n x c } { + return [get_string $n $x $c 1] +} - verbose -log "_check_box x=$x, y=$y, x2=$x2, y2=$y2, width=$width, height=$height" +# Return the text of screen line N. Lines are 0-based. If C is +# non-empty, stop before column C. Columns are also zero-based. If +# ATTRS, annotate with attributes. +proc Term::get_line_1 {n c attrs} { + return [get_string $n 0 $c $attrs] +} - set c [get_char $x $y] - if {$c != "+"} { - return "ul corner is $c, not +" - } +# Return the text of screen line N, without attributes. Lines are +# 0-based. If C is given, stop before column C. Columns are also +# zero-based. +proc Term::get_line {n {c ""} } { + return [get_line_1 $n $c 0] +} - set c [get_char $x $y2] - if {$c != "+"} { - return "ll corner is $c, not +" - } +# As get_line, but annotate with attributes. +proc Term::get_line_with_attrs {n {c ""}} { + return [get_line_1 $n $c 1] +} - set c [get_char $x2 $y] - if {$c != "+"} { - return "ur corner is $c, not +" - } +# Get just the character at (X, Y). +proc Term::get_char {x y} { + variable _chars + return [lindex $_chars($x,$y) 0] +} - set c [get_char $x2 $y2] - if {$c != "+"} { - return "lr corner is $c, not +" - } +# Get the entire screen as a string. +proc Term::get_all_lines {} { + variable _rows + variable _cols + variable _chars - # Note we do not check the full horizonal borders of the box. - # The top will contain a title, and the bottom may as well, if - # it is overlapped by some other border. However, at most a - # title should appear as '+-VERY LONG TITLE-+', so we can - # check for the '+-' on the left, and '-+' on the right. - set c [get_char [expr {$x + 1}] $y] - if {$c != "-"} { - return "ul title padding is $c, not -" + set result "" + for {set y 0} {$y < $_rows} {incr y} { + for {set x 0} {$x < $_cols} {incr x} { + append result [lindex $_chars($x,$y) 0] } + append result "\n" + } - set c [get_char [expr {$x2 - 1}] $y] - if {$c != "-"} { - return "ul title padding is $c, not -" - } + return $result +} - # Now check the vertical borders. - for {set i [expr {$y + 1}]} {$i < $y2 - 1} {incr i} { - set c [get_char $x $i] - if {$c != "|"} { - return "left side $i is $c, not |" - } +# Get the text just before the cursor. +proc Term::get_current_line {} { + variable _cur_col + variable _cur_row + return [get_line $_cur_row $_cur_col] +} - set c [get_char $x2 $i] - if {$c != "|"} { - return "right side $i is $c, not |" - } - } +# Helper function for check_box. Returns empty string if the box +# is found, description of why not otherwise. +proc Term::_check_box {x y width height} { + set x2 [expr {$x + $width - 1}] + set y2 [expr {$y + $height - 1}] - return "" + verbose -log "_check_box x=$x, y=$y, x2=$x2, y2=$y2, width=$width, height=$height" + + set c [get_char $x $y] + if {$c != "+"} { + return "ul corner is $c, not +" } - # Check for a box at the given coordinates. - proc check_box {test_name x y width height} { - dump_box $x $y $width $height - set why [_check_box $x $y $width $height] - if {$why == ""} { - pass $test_name - } else { - fail "$test_name ($why)" - } + set c [get_char $x $y2] + if {$c != "+"} { + return "ll corner is $c, not +" } - # Wait until a box appears at the given coordinates. - proc wait_for_box {test_name x y width height} { - while 1 { - if { [accept_gdb_output] == 0 } { - return 0 - } + set c [get_char $x2 $y] + if {$c != "+"} { + return "ur corner is $c, not +" + } - set why [_check_box $x $y $width $height] - if {$why == ""} { - pass $test_name - break - } - } + set c [get_char $x2 $y2] + if {$c != "+"} { + return "lr corner is $c, not +" } - # Check whether the text contents of the terminal match the - # regular expression. Note that text styling is not considered. - proc check_contents {test_name regexp} { - dump_screen - set contents [get_all_lines] - gdb_assert {[regexp -- $regexp $contents]} $test_name + # Note we do not check the full horizonal borders of the box. + # The top will contain a title, and the bottom may as well, if + # it is overlapped by some other border. However, at most a + # title should appear as '+-VERY LONG TITLE-+', so we can + # check for the '+-' on the left, and '-+' on the right. + set c [get_char [expr {$x + 1}] $y] + if {$c != "-"} { + return "ul title padding is $c, not -" } - # As check_contents, but check that the text contents of the terminal does - # not match the regular expression. - proc check_contents_not {test_name regexp} { - dump_screen - set contents [get_all_lines] - gdb_assert {![regexp -- $regexp $contents]} $test_name + set c [get_char [expr {$x2 - 1}] $y] + if {$c != "-"} { + return "ul title padding is $c, not -" } - # Get the region of the screen described by X, Y, WIDTH, and - # HEIGHT, and separate the lines using SEP. If ATTRS is true then - # include attribute information in the output. - proc get_region { x y width height sep { attrs false } } { - variable _chars + # Now check the vertical borders. + for {set i [expr {$y + 1}]} {$i < $y2 - 1} {incr i} { + set c [get_char $x $i] + if {$c != "|"} { + return "left side $i is $c, not |" + } - if { $attrs } { - _reset_attrs region_attrs + set c [get_char $x2 $i] + if {$c != "|"} { + return "right side $i is $c, not |" } + } - # Grab the contents of the box, join each line together - # using $sep. - set result "" - for {set yy $y} {$yy < [expr {$y + $height}]} {incr yy} { - if {$yy > $y} { - # Add the end of line sequence only if this isn't the - # first line. - append result $sep - } - for {set xx $x} {$xx < [expr {$x + $width}]} {incr xx} { - if { $attrs } { - set char_attrs [lindex $_chars($xx,$yy) 1] - append result [apply_attrs region_attrs $char_attrs] - } + return "" +} - append result [get_char $xx $yy] - } +# Check for a box at the given coordinates. +proc Term::check_box {test_name x y width height} { + dump_box $x $y $width $height + set why [_check_box $x $y $width $height] + if {$why == ""} { + pass $test_name + } else { + fail "$test_name ($why)" + } +} + +# Wait until a box appears at the given coordinates. +proc Term::wait_for_box {test_name x y width height} { + while 1 { + if { [accept_gdb_output] == 0 } { + return 0 } - if { $attrs } { - _reset_attrs zero_attrs - set char_attrs [array get zero_attrs] - append result [apply_attrs region_attrs $char_attrs] + + set why [_check_box $x $y $width $height] + if {$why == ""} { + pass $test_name + break } - return $result } +} - # Check that the region of the screen described by X, Y, WIDTH, - # and HEIGHT match REGEXP. This is like check_contents except - # only part of the screen is checked. This can be used to check - # the contents within a box (though check_box_contents is a better - # choice for boxes with a border). Return 1 if check succeeded. - proc check_region_contents_p { x y width height regexp } { - variable _chars - dump_box $x $y $width $height +# Check whether the text contents of the terminal match the +# regular expression. Note that text styling is not considered. +proc Term::check_contents {test_name regexp} { + dump_screen + set contents [get_all_lines] + gdb_assert {[regexp -- $regexp $contents]} $test_name +} - # Now grab the contents of the box, join each line together - # with a '\r\n' sequence and match against REGEXP. - set result [get_region $x $y $width $height "\r\n"] - return [regexp -- $regexp $result] - } +# As check_contents, but check that the text contents of the terminal does +# not match the regular expression. +proc Term::check_contents_not {test_name regexp} { + dump_screen + set contents [get_all_lines] + gdb_assert {![regexp -- $regexp $contents]} $test_name +} - # Check that the region of the screen described by X, Y, WIDTH, - # and HEIGHT match REGEXP. As check_region_contents_p, but produce - # a pass/fail message. - proc check_region_contents { test_name x y width height regexp } { - set ok [check_region_contents_p $x $y $width $height $regexp] - gdb_assert {$ok} $test_name - } +# Get the region of the screen described by X, Y, WIDTH, and +# HEIGHT, and separate the lines using SEP. If ATTRS is true then +# include attribute information in the output. +proc Term::get_region { x y width height sep { attrs false } } { + variable _chars - # Check the contents of a box on the screen. This is a little - # like check_contents, but doesn't check the whole screen - # contents, only the contents of a single box. This procedure - # includes (effectively) a call to check_box to ensure there is a - # box where expected, if there is then the contents of the box are - # matched against REGEXP. - proc check_box_contents {test_name x y width height regexp} { - variable _chars + if { $attrs } { + _reset_attrs region_attrs + } - dump_box $x $y $width $height - set why [_check_box $x $y $width $height] - if {$why != ""} { - fail "$test_name (box check: $why)" - return + # Grab the contents of the box, join each line together + # using $sep. + set result "" + for {set yy $y} {$yy < [expr {$y + $height}]} {incr yy} { + if {$yy > $y} { + # Add the end of line sequence only if this isn't the + # first line. + append result $sep } + for {set xx $x} {$xx < [expr {$x + $width}]} {incr xx} { + if { $attrs } { + set char_attrs [lindex $_chars($xx,$yy) 1] + append result [apply_attrs region_attrs $char_attrs] + } - check_region_contents $test_name [expr {$x + 1}] [expr {$y + 1}] \ - [expr {$width - 2}] [expr {$height - 2}] $regexp + append result [get_char $xx $yy] + } + } + if { $attrs } { + _reset_attrs zero_attrs + set char_attrs [array get zero_attrs] + append result [apply_attrs region_attrs $char_attrs] } + return $result +} - # A debugging function to dump the current screen, with line - # numbers. If ATTRS, annotate with attributes. - proc dump_screen { {attrs 0} } { - variable _rows - variable _cols - variable _cur_row - variable _cur_col +# Check that the region of the screen described by X, Y, WIDTH, +# and HEIGHT match REGEXP. This is like check_contents except +# only part of the screen is checked. This can be used to check +# the contents within a box (though check_box_contents is a better +# choice for boxes with a border). Return 1 if check succeeded. +proc Term::check_region_contents_p { x y width height regexp } { + variable _chars + dump_box $x $y $width $height - verbose -log "Screen Dump (size $_cols columns x $_rows rows, cursor at column $_cur_col, row $_cur_row):" + # Now grab the contents of the box, join each line together + # with a '\r\n' sequence and match against REGEXP. + set result [get_region $x $y $width $height "\r\n"] + return [regexp -- $regexp $result] +} - for {set y 0} {$y < $_rows} {incr y} { - set fmt [format %5d $y] - verbose -log "$fmt [get_line_1 $y "" $attrs]" - } +# Check that the region of the screen described by X, Y, WIDTH, +# and HEIGHT match REGEXP. As check_region_contents_p, but produce +# a pass/fail message. +proc Term::check_region_contents { test_name x y width height regexp } { + set ok [check_region_contents_p $x $y $width $height $regexp] + gdb_assert {$ok} $test_name +} + +# Check the contents of a box on the screen. This is a little +# like check_contents, but doesn't check the whole screen +# contents, only the contents of a single box. This procedure +# includes (effectively) a call to check_box to ensure there is a +# box where expected, if there is then the contents of the box are +# matched against REGEXP. +proc Term::check_box_contents {test_name x y width height regexp} { + variable _chars + + dump_box $x $y $width $height + set why [_check_box $x $y $width $height] + if {$why != ""} { + fail "$test_name (box check: $why)" + return } - # As dump_screen, but with attributes annotation. - proc dump_screen_with_attrs {} { - return [dump_screen 1] + check_region_contents $test_name [expr {$x + 1}] [expr {$y + 1}] \ + [expr {$width - 2}] [expr {$height - 2}] $regexp +} + +# A debugging function to dump the current screen, with line +# numbers. If ATTRS, annotate with attributes. +proc Term::dump_screen { {attrs 0} } { + variable _rows + variable _cols + variable _cur_row + variable _cur_col + + verbose -log "Screen Dump (size $_cols columns x $_rows rows, cursor at column $_cur_col, row $_cur_row):" + + for {set y 0} {$y < $_rows} {incr y} { + set fmt [format %5d $y] + verbose -log "$fmt [get_line_1 $y {} $attrs]" } +} - # A debugging function to dump a box from the current screen, with line - # numbers. - proc dump_box { x y width height } { - verbose -log "Box Dump ($width x $height) @ ($x, $y):" - set region [get_region $x $y $width $height "\n"] - set lines [split $region "\n"] - set nr $y - foreach line $lines { - set fmt [format %5d $nr] - verbose -log "$fmt $line" - incr nr - } +# As dump_screen, but with attributes annotation. +proc Term::dump_screen_with_attrs {} { + return [dump_screen 1] +} + +# A debugging function to dump a box from the current screen, with line +# numbers. +proc Term::dump_box { x y width height } { + verbose -log "Box Dump ($width x $height) @ ($x, $y):" + set region [get_region $x $y $width $height "\n"] + set lines [split $region "\n"] + set nr $y + foreach line $lines { + set fmt [format %5d $nr] + verbose -log "$fmt $line" + incr nr } +} - # Resize the terminal. - proc _do_resize {rows cols} { - variable _chars - variable _rows - variable _cols +# Resize the terminal. +proc Term::_do_resize {rows cols} { + variable _chars + variable _rows + variable _cols - set old_rows [expr {min ($_rows, $rows)}] - set old_cols [expr {min ($_cols, $cols)}] + set old_rows [expr {min ($_rows, $rows)}] + set old_cols [expr {min ($_cols, $cols)}] - # Copy locally. - array set local_chars [array get _chars] - unset _chars + # Copy locally. + array set local_chars [array get _chars] + unset _chars - set _rows $rows - set _cols $cols - _clear_lines 0 $_rows + set _rows $rows + set _cols $cols + _clear_lines 0 $_rows - for {set x 0} {$x < $old_cols} {incr x} { - for {set y 0} {$y < $old_rows} {incr y} { - set _chars($x,$y) $local_chars($x,$y) - } + for {set x 0} {$x < $old_cols} {incr x} { + for {set y 0} {$y < $old_rows} {incr y} { + set _chars($x,$y) $local_chars($x,$y) } } +} - proc resize {rows cols {wait_for_msg 1}} { - variable _rows - variable _cols - variable _resize_count +proc Term::resize {rows cols {wait_for_msg 1}} { + variable _rows + variable _cols + variable _resize_count - # expect handles each argument to stty separately. This means - # that gdb will see SIGWINCH twice. Rather than rely on this - # behavior (which, after all, could be changed), we make it - # explicit here. This also simplifies waiting for the redraw. - _do_resize $rows $_cols - stty rows $_rows < $::gdb_tty_name - if { $wait_for_msg } { - wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}" - } - incr _resize_count - _do_resize $_rows $cols - stty columns $_cols < $::gdb_tty_name - if { $wait_for_msg } { - wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}" - } - incr _resize_count - } + # expect handles each argument to stty separately. This means + # that gdb will see SIGWINCH twice. Rather than rely on this + # behavior (which, after all, could be changed), we make it + # explicit here. This also simplifies waiting for the redraw. + _do_resize $rows $_cols + stty rows $_rows < $::gdb_tty_name + if { $wait_for_msg } { + wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}" + } + incr _resize_count + _do_resize $_rows $cols + stty columns $_cols < $::gdb_tty_name + if { $wait_for_msg } { + wait_for "@@ resize done $_resize_count, size = ${_cols}x${rows}" + } + incr _resize_count } diff --git a/gdb/testsuite/lib/unbuffer_output.c b/gdb/testsuite/lib/unbuffer_output.c index a286e3f..cdaa227 100644 --- a/gdb/testsuite/lib/unbuffer_output.c +++ b/gdb/testsuite/lib/unbuffer_output.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2008-2024 Free Software Foundation, Inc. +/* Copyright (C) 2008-2025 Free Software Foundation, Inc. This file is part of GDB. diff --git a/gdb/testsuite/lib/valgrind.exp b/gdb/testsuite/lib/valgrind.exp index c952e92..aad0a3b 100644 --- a/gdb/testsuite/lib/valgrind.exp +++ b/gdb/testsuite/lib/valgrind.exp @@ -1,4 +1,4 @@ -# Copyright 2009-2024 Free Software Foundation, Inc. +# Copyright 2009-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 |