# module variables'.
load_lib "fortran.exp"
+load_lib "sym-info-cmds.exp"
if { [skip_fortran_tests] } { continue }
# Test 'info modules' command.
-gdb_test "info modules" \
- [multi_line \
- "All defined modules:" \
- "" \
- "File .*${srcfile2}:" \
- "18:\[\t \]+mod2" \
- "" \
- "File .*${srcfile}:" \
- "16:\[\t \]+mod1" ]
-
-gdb_test "info modules 1" \
- [multi_line \
- "All modules matching regular expression \"1\":" \
- "" \
- "File .*${srcfile}:" \
- "16:\[\t \]+mod1" ]
-
-gdb_test "info modules 2" \
- [multi_line \
- "All modules matching regular expression \"2\":" \
- "" \
- "File .*${srcfile2}:" \
- "18:\[\t \]+mod2" ]
-
-gdb_test "info modules mod" \
- [multi_line \
- "All modules matching regular expression \"mod\":" \
- "" \
- "File .*${srcfile2}:" \
- "18:\[\t \]+mod2" \
- "" \
- "File .*${srcfile}:" \
- "16:\[\t \]+mod1" ]
+GDBInfoSymbols::run_command "info modules"
+GDBInfoSymbols::check_header "All defined modules:"
+GDBInfoSymbols::check_entry "${srcfile2}" "18" "mod2"
+GDBInfoSymbols::check_entry "${srcfile}" "16" "mod1"
+GDBInfoSymbols::check_no_entry "${srcfile}"
+GDBInfoSymbols::check_no_entry "${srcfile2}"
+
+GDBInfoSymbols::run_command "info modules 1"
+GDBInfoSymbols::check_header \
+ "All modules matching regular expression \"1\":"
+GDBInfoSymbols::check_entry "${srcfile}" "16" "mod1"
+GDBInfoSymbols::check_no_entry "${srcfile}"
+GDBInfoSymbols::check_no_entry "${srcfile2}"
+
+GDBInfoSymbols::run_command "info modules 2"
+GDBInfoSymbols::check_header \
+ "All modules matching regular expression \"2\":"
+GDBInfoSymbols::check_entry "${srcfile2}" "18" "mod2"
+GDBInfoSymbols::check_no_entry "${srcfile}"
+GDBInfoSymbols::check_no_entry "${srcfile2}"
+
+GDBInfoSymbols::run_command "info modules mod"
+GDBInfoSymbols::check_header \
+ "All modules matching regular expression \"mod\":"
+GDBInfoSymbols::check_entry "${srcfile2}" "18" "mod2"
+GDBInfoSymbols::check_entry "${srcfile}" "16" "mod1"
+GDBInfoSymbols::check_no_entry "${srcfile}"
+GDBInfoSymbols::check_no_entry "${srcfile2}"
# Test 'info module functions'.
-gdb_test "info module functions" \
- [multi_line \
- "All functions in all modules:" \
- "" \
- "Module \"mod2\":" \
- "" \
- "File .*${srcfile2}:" \
- "22:\[\t \]+void mod2::sub_m2_a\\(${integer4}, ${logical4}\\);" \
- "30:\[\t \]+${logical4} mod2::sub_m2_b\\(${real4}\\);" \
- "" \
- "Module \"mod1\":" \
- "" \
- "File .*${srcfile}:" \
- "35:\[\t \]+void mod1::__copy_mod1_M1t1\\(Type m1t1, Type m1t1\\);" \
- "25:\[\t \]+void mod1::sub_m1_a\\(${integer4}\\);" \
- "31:\[\t \]+${integer4} mod1::sub_m1_b\\(void\\);" ]
-
-gdb_test "info module functions -m mod1" \
- [multi_line \
- "All functions in all modules matching regular expression \"mod1\":" \
- "" \
- "Module \"mod1\":" \
- "" \
- "File .*:" \
- "35:\[\t \]+void mod1::__copy_mod1_M1t1\\(Type m1t1, Type m1t1\\);" \
- "25:\[\t \]+void mod1::sub_m1_a\\(${integer4}\\);" \
- "31:\[\t \]+${integer4} mod1::sub_m1_b\\(void\\);" ]
-
-gdb_test "info module functions -t integer" \
- [multi_line \
- "All functions with type matching regular expression \"integer\" in all modules:" \
- "" \
- "Module \"mod2\":" \
- "" \
- "File .*${srcfile2}:" \
- "22:\[\t \]+void mod2::sub_m2_a\\(${integer4}, ${logical4}\\);" \
- "" \
- "Module \"mod1\":" \
- "" \
- "File .*${srcfile}:" \
- "25:\[\t \]+void mod1::sub_m1_a\\(${integer4}\\);" \
- "31:\[\t \]+${integer4} mod1::sub_m1_b\\(void\\);" ]
+GDBInfoModuleSymbols::run_command "info module functions"
+GDBInfoModuleSymbols::check_header "All functions in all modules:"
+GDBInfoModuleSymbols::check_entry "${srcfile2}" "mod2" "22" \
+ "void mod2::sub_m2_a\\(${integer4}, ${logical4}\\);"
+GDBInfoModuleSymbols::check_entry "${srcfile2}" "mod2" "30" \
+ "${logical4} mod2::sub_m2_b\\(${real4}\\);"
+GDBInfoModuleSymbols::check_entry "${srcfile}" "mod1" "35" \
+ "void mod1::__copy_mod1_M1t1\\(Type m1t1, Type m1t1\\);"
+GDBInfoModuleSymbols::check_entry "${srcfile}" "mod1" "25" \
+ "void mod1::sub_m1_a\\(${integer4}\\);"
+GDBInfoModuleSymbols::check_entry "${srcfile}" "mod1" "31" \
+ "${integer4} mod1::sub_m1_b\\(void\\);"
+GDBInfoModuleSymbols::check_no_entry "${srcfile}" ".*"
+GDBInfoModuleSymbols::check_no_entry "${srcfile2}" ".*"
+
+GDBInfoModuleSymbols::run_command "info module functions -m mod1"
+GDBInfoModuleSymbols::check_header \
+ "All functions in all modules matching regular expression \"mod1\":"
+GDBInfoModuleSymbols::check_entry "${srcfile}" "mod1" "35" \
+ "void mod1::__copy_mod1_M1t1\\(Type m1t1, Type m1t1\\);"
+GDBInfoModuleSymbols::check_entry "${srcfile}" "mod1" "25" \
+ "void mod1::sub_m1_a\\(${integer4}\\);"
+GDBInfoModuleSymbols::check_entry "${srcfile}" "mod1" "31" \
+ "${integer4} mod1::sub_m1_b\\(void\\);"
+GDBInfoModuleSymbols::check_no_entry "${srcfile}" ".*"
+GDBInfoModuleSymbols::check_no_entry "${srcfile2}" ".*"
+
+GDBInfoModuleSymbols::run_command "info module functions -t integer"
+GDBInfoModuleSymbols::check_header \
+ "All functions with type matching regular expression \"integer\" in all modules:"
+GDBInfoModuleSymbols::check_entry "${srcfile2}" "mod2" "22" \
+ "void mod2::sub_m2_a\\(${integer4}, ${logical4}\\);"
+GDBInfoModuleSymbols::check_entry "${srcfile}" "mod1" "25" \
+ "void mod1::sub_m1_a\\(${integer4}\\);"
+GDBInfoModuleSymbols::check_entry "${srcfile}" "mod1" "31" \
+ "${integer4} mod1::sub_m1_b\\(void\\);"
+GDBInfoModuleSymbols::check_no_entry "${srcfile}" ".*"
+GDBInfoModuleSymbols::check_no_entry "${srcfile2}" ".*"
# Test 'info module variables'.
-gdb_test "info module variables" \
- [multi_line \
- "All variables in all modules:" \
- "" \
- "Module \"mod2\":" \
- "" \
- "File .*${srcfile2}:" \
- "19:\[\t \]+${integer4} mod2::mod2_var_1;" \
- "20:\[\t \]+${real4} mod2::mod2_var_2;" \
- "" \
- "Module \"mod1\":" \
- "" \
- "File .*${srcfile}:" \
- "35:\[\t \]+Type m1t1 mod1::__def_init_mod1_M1t1;" \
- "35:\[\t \]+Type __vtype_mod1_M1t1 mod1::__vtab_mod1_M1t1;" \
- "21:\[\t \]+${real4} mod1::mod1_var_1;" \
- "22:\[\t \]+${integer4} mod1::mod1_var_2;" ]
-
-gdb_test "info module variables -t real" \
- [multi_line \
- "All variables with type matching regular expression \"real\" in all modules:" \
- "" \
- "Module \"mod2\":" \
- "" \
- "File .*:" \
- "20:\[\t \]+${real4} mod2::mod2_var_2;" \
- "" \
- "Module \"mod1\":" \
- "" \
- "File .*:" \
- "21:\[\t \]+${real4} mod1::mod1_var_1;" ]
-
-gdb_test "info module variables -m mod2" \
- [multi_line \
- "All variables in all modules matching regular expression \"mod2\":" \
- "" \
- "Module \"mod2\":" \
- "" \
- "File .*${srcfile2}:" \
- "19:\[\t \]+${integer4} mod2::mod2_var_1;" \
- "20:\[\t \]+${real4} mod2::mod2_var_2;" ]
-
-gdb_test "info module variables -m mod2 -t real" \
- [multi_line \
- "All variables with type matching regular expression \"real\"" \
- " in all modules matching regular expression \"mod2\":" \
- "" \
- "Module \"mod2\":" \
- "" \
- "File .*${srcfile2}:" \
- "20:\[\t \]+${real4} mod2::mod2_var_2;" ]
-
-gdb_test "info module variables _1" \
- [multi_line \
- "All variables matching regular expression \"_1\" in all modules:" \
- "" \
- "Module \"mod2\":" \
- "" \
- "File .*:" \
- "19:\[\t \]+${integer4} mod2::mod2_var_1;" \
- "" \
- "Module \"mod1\":" \
- "" \
- "File .*:" \
- "21:\[\t \]+${real4} mod1::mod1_var_1;" ]
+GDBInfoModuleSymbols::run_command "info module variables"
+GDBInfoModuleSymbols::check_header "All variables in all modules:"
+GDBInfoModuleSymbols::check_entry "${srcfile2}" "mod2" "19" \
+ "${integer4} mod2::mod2_var_1;"
+GDBInfoModuleSymbols::check_entry "${srcfile2}" "mod2" "20" \
+ "${real4} mod2::mod2_var_2;"
+GDBInfoModuleSymbols::check_entry "${srcfile}" "mod1" "35" \
+ "Type m1t1 mod1::__def_init_mod1_M1t1;"
+GDBInfoModuleSymbols::check_entry "${srcfile}" "mod1" "35" \
+ "Type __vtype_mod1_M1t1 mod1::__vtab_mod1_M1t1;"
+GDBInfoModuleSymbols::check_entry "${srcfile}" "mod1" "21" \
+ "${real4} mod1::mod1_var_1;"
+GDBInfoModuleSymbols::check_entry "${srcfile}" "mod1" "22" \
+ "${integer4} mod1::mod1_var_2;"
+GDBInfoModuleSymbols::check_no_entry "${srcfile}" ".*"
+GDBInfoModuleSymbols::check_no_entry "${srcfile2}" ".*"
+
+GDBInfoModuleSymbols::run_command "info module variables -t real"
+GDBInfoModuleSymbols::check_header \
+ "All variables with type matching regular expression \"real\" in all modules:"
+GDBInfoModuleSymbols::check_entry "${srcfile2}" "mod2" "20" \
+ "${real4} mod2::mod2_var_2;"
+GDBInfoModuleSymbols::check_entry "${srcfile}" "mod1" "21" \
+ "${real4} mod1::mod1_var_1;"
+GDBInfoModuleSymbols::check_no_entry "${srcfile}" ".*"
+GDBInfoModuleSymbols::check_no_entry "${srcfile2}" ".*"
+
+GDBInfoModuleSymbols::run_command "info module variables -m mod2"
+GDBInfoModuleSymbols::check_header \
+ "All variables in all modules matching regular expression \"mod2\":"
+GDBInfoModuleSymbols::check_entry "${srcfile2}" "mod2" "19" \
+ "${integer4} mod2::mod2_var_1;"
+GDBInfoModuleSymbols::check_entry "${srcfile2}" "mod2" "20" \
+ "${real4} mod2::mod2_var_2;"
+GDBInfoModuleSymbols::check_no_entry "${srcfile}" ".*"
+GDBInfoModuleSymbols::check_no_entry "${srcfile2}" ".*"
+
+GDBInfoModuleSymbols::run_command "info module variables -m mod2 -t real"
+GDBInfoModuleSymbols::check_header \
+ "All variables with type matching regular expression \"real\" in all modules matching regular expression \"mod2\":"
+GDBInfoModuleSymbols::check_entry "${srcfile2}" "mod2" "20" \
+ "${real4} mod2::mod2_var_2;"
+GDBInfoModuleSymbols::check_no_entry "${srcfile}" ".*"
+GDBInfoModuleSymbols::check_no_entry "${srcfile2}" ".*"
+
+GDBInfoModuleSymbols::run_command "info module variables _1"
+GDBInfoModuleSymbols::check_header \
+ "All variables matching regular expression \"_1\" in all modules:"
+GDBInfoModuleSymbols::check_entry "${srcfile2}" "mod2" "19" \
+ "${integer4} mod2::mod2_var_1;"
+GDBInfoModuleSymbols::check_entry "${srcfile}" "mod1" "21" \
+ "${real4} mod1::mod1_var_1;"
+GDBInfoModuleSymbols::check_no_entry "${srcfile}" ".*"
+GDBInfoModuleSymbols::check_no_entry "${srcfile2}" ".*"
--- /dev/null
+# Copyright 2019 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Make it easier to run the 'info modules' command (using
+# GDBInfoModules), and the 'info module ...' commands (using
+# GDBInfoModuleContents) and process the output.
+#
+# The difficulty we run into is that different versions of gFortran
+# include different helper modules which show up in the results. The
+# procedures in this library help process those parts of the output we
+# actually want to check, while ignoring those parts that we don't
+# care about.
+#
+# For each namespace GDBInfoModules and GDBInfoModuleContents, there's
+# a run_command proc, use this to run a command and capture the
+# output. Then make calls to check_header, check_entry, and
+# check_no_entry to ensure the output was as expected.
+
+namespace eval GDBInfoSymbols {
+
+ # A string that is the header printed by GDB immediately after the
+ # 'info [modules|types|functions|variables]' command has been issued.
+ variable _header
+
+ # A list of entries extracted from the output of the command.
+ # Each entry is a filename, a line number, and the rest of the
+ # text describing the entry. If an entry has no line number then
+ # it is replaced with the text NONE.
+ variable _entries
+
+ # The string that is the complete last command run.
+ variable _last_command
+
+ # Add a new entry to the _entries list.
+ proc _add_entry { filename lineno text } {
+ variable _entries
+
+ set entry [list $filename $lineno $text]
+ lappend _entries $entry
+ }
+
+ # Run the 'info modules' command, passing ARGS as extra arguments
+ # to the command. Process the output storing the results within
+ # the variables in this namespace.
+ #
+ # The results of any previous call to run_command are discarded
+ # when this is called.
+ proc run_command { cmd { testname "" } } {
+ global gdb_prompt
+
+ variable _header
+ variable _entries
+ variable _last_command
+
+ if {![regexp -- "^info (modules|types|variables|functions)" $cmd]} {
+ perror "invalid command"
+ }
+
+ set _header ""
+ set _entries [list]
+ set _last_command $cmd
+
+ if { $testname == "" } {
+ set testname $cmd
+ }
+
+ send_gdb "$cmd\n"
+ gdb_expect {
+ -re "^$cmd\r\n" {
+ # Match the original command echoed back to us.
+ }
+ timeout {
+ fail "$testname (timeout)"
+ return 0
+ }
+ }
+
+ gdb_expect {
+ -re "^\r\n" {
+ # Found the blank line after the header, we're done
+ # parsing the header now.
+ }
+ -re "^\[ \t]*(\[^\r\n\]+)\r\n" {
+ set str $expect_out(1,string)
+ if { $_header == "" } {
+ set _header $str
+ } else {
+ set _header "$_header $str"
+ }
+ exp_continue
+ }
+ timeout {
+ fail "$testname (timeout)"
+ return 0
+ }
+ }
+
+ set current_file ""
+ gdb_expect {
+ -re "^File (\[^\r\n\]+):\r\n" {
+ set current_file $expect_out(1,string)
+ exp_continue
+ }
+ -re "^(\[0-9\]+):\[ \t\]+(\[^\r\n\]+)\r\n" {
+ set lineno $expect_out(1,string)
+ set text $expect_out(2,string)
+ if { $current_file == "" } {
+ fail "$testname (missing filename)"
+ return 0
+ }
+ _add_entry $current_file $lineno $text
+ exp_continue
+ }
+ -re "^\[ \t\]+(\[^\r\n\]+)\r\n" {
+ set lineno "NONE"
+ set text $expect_out(1,string)
+ if { $current_file == "" } {
+ fail "$testname (missing filename)"
+ return 0
+ }
+ _add_entry $current_file $lineno $text
+ exp_continue
+ }
+ -re "^\r\n" {
+ exp_continue
+ }
+ -re "^$gdb_prompt $" {
+ # All done.
+ }
+ timeout {
+ fail "$testname (timeout)"
+ return 0
+ }
+ }
+
+ pass $testname
+ return 1
+ }
+
+ # Check that the header held in _header matches PATTERN. Use
+ # TESTNAME as the name of the test, or create a suitable default
+ # test name based on the last command.
+ proc check_header { pattern { testname "" } } {
+ variable _header
+ variable _last_command
+
+ if { $testname == "" } {
+ set testname "$_last_command: check header"
+ }
+
+ gdb_assert {[regexp -- $pattern $_header]} $testname
+ }
+
+ # Check that we have an entry in _entries matching FILENAME,
+ # LINENO, and TEXT. If LINENO is the empty string it is replaced
+ # with the string NONE in order to match a similarly missing line
+ # number in the output of the command.
+ #
+ # TESTNAME is the name of the test, or a default will be created
+ # based on the last command run and the arguments passed here.
+ #
+ # If a matching entry is found then it is removed from the
+ # _entries list, this allows us to check for duplicates using the
+ # check_no_entry call.
+ proc check_entry { filename lineno text { testname "" } } {
+ variable _entries
+ variable _last_command
+
+ if { $testname == "" } {
+ set testname \
+ "$_last_command: check for entry '$filename', '$lineno', '$text'"
+ }
+
+ if { $lineno == "" } {
+ set lineno "NONE"
+ }
+
+ set new_entries [list]
+
+ set found_match 0
+ foreach entry $_entries {
+
+ if {!$found_match} {
+ set f [lindex $entry 0]
+ set l [lindex $entry 1]
+ set t [lindex $entry 2]
+ if { [regexp -- $filename $f] \
+ && [regexp -- $lineno $l] \
+ && [regexp -- $text $t] } {
+ set found_match 1
+ } else {
+ lappend new_entries $entry
+ }
+ } else {
+ lappend new_entries $entry
+ }
+ }
+
+ set _entries $new_entries
+ gdb_assert { $found_match } $testname
+ }
+
+ # Check that there is no entry in the _entries list matching
+ # FILENAME, LINENO, and TEXT. The LINENO and TEXT are optional,
+ # and will be replaced with '.*' if missing.
+ #
+ # If LINENO is the empty string then it will be replaced with the
+ # string NONE in order to match against missing line numbers in
+ # the output of the command.
+ #
+ # TESTNAME is the name of the test, or a default will be built
+ # from the last command run and the arguments passed here.
+ #
+ # This can be used after a call to check_entry to ensure that
+ # there are no further matches for a particular file in the
+ # output.
+ proc check_no_entry { filename { lineno ".*" } { text ".*" } \
+ { testname "" } } {
+ variable _entries
+ variable _last_command
+
+ if { $testname == "" } {
+ set testname \
+ "$_last_command: check no matches for '$filename', $lineno', and '$text'"
+ }
+
+ if { $lineno == "" } {
+ set lineno "NONE"
+ }
+
+ foreach entry $_entries {
+ set f [lindex $entry 0]
+ set l [lindex $entry 1]
+ set t [lindex $entry 2]
+ if { [regexp -- $filename $f] \
+ && [regexp -- $lineno $l] \
+ && [regexp -- $text $t] } {
+ fail $testname
+ }
+ }
+
+ pass $testname
+ }
+}
+
+
+namespace eval GDBInfoModuleSymbols {
+
+ # A string that is the header printed by GDB immediately after the
+ # 'info modules (variables|functions)' command has been issued.
+ variable _header
+
+ # A list of entries extracted from the output of the command.
+ # Each entry is a filename, a module name, a line number, and the
+ # rest of the text describing the entry. If an entry has no line
+ # number then it is replaced with the text NONE.
+ variable _entries
+
+ # The string that is the complete last command run.
+ variable _last_command
+
+ # Add a new entry to the _entries list.
+ proc _add_entry { filename module lineno text } {
+ variable _entries
+
+ set entry [list $filename $module $lineno $text]
+ lappend _entries $entry
+ }
+
+ # Run the 'info module ....' command, passing ARGS as extra
+ # arguments to the command. Process the output storing the
+ # results within the variables in this namespace.
+ #
+ # The results of any previous call to run_command are discarded
+ # when this is called.
+ proc run_command { cmd { testname "" } } {
+ global gdb_prompt
+
+ variable _header
+ variable _entries
+ variable _last_command
+
+ if {![regexp -- "^info module (variables|functions)" $cmd]} {
+ perror "invalid command: '$cmd'"
+ }
+
+ set _header ""
+ set _entries [list]
+ set _last_command $cmd
+
+ if { $testname == "" } {
+ set testname $cmd
+ }
+
+ send_gdb "$cmd\n"
+ gdb_expect {
+ -re "^$cmd\r\n" {
+ # Match the original command echoed back to us.
+ }
+ timeout {
+ fail "$testname (timeout)"
+ return 0
+ }
+ }
+
+ gdb_expect {
+ -re "^\r\n" {
+ # Found the blank line after the header, we're done
+ # parsing the header now.
+ }
+ -re "^\[ \t\]*(\[^\r\n\]+)\r\n" {
+ set str $expect_out(1,string)
+ if { $_header == "" } {
+ set _header $str
+ } else {
+ set _header "$_header $str"
+ }
+ exp_continue
+ }
+ timeout {
+ fail "$testname (timeout)"
+ return 0
+ }
+ }
+
+ set current_module ""
+ set current_file ""
+ gdb_expect {
+ -re "^Module \"(\[^\"\]+)\":\r\n" {
+ set current_module $expect_out(1,string)
+ exp_continue
+ }
+ -re "^File (\[^\r\n\]+):\r\n" {
+ if { $current_module == "" } {
+ fail "$testname (missing module)"
+ return 0
+ }
+ set current_file $expect_out(1,string)
+ exp_continue
+ }
+ -re "^(\[0-9\]+):\[ \t\]+(\[^\r\n\]+)\r\n" {
+ set lineno $expect_out(1,string)
+ set text $expect_out(2,string)
+ if { $current_module == "" } {
+ fail "$testname (missing module)"
+ return 0
+ }
+ if { $current_file == "" } {
+ fail "$testname (missing filename)"
+ return 0
+ }
+ _add_entry $current_file $current_module \
+ $lineno $text
+ exp_continue
+ }
+ -re "^\[ \t\]+(\[^\r\n\]+)\r\n" {
+ set lineno "NONE"
+ set text $expect_out(1,string)
+ if { $current_module == "" } {
+ fail "$testname (missing module)"
+ return 0
+ }
+ if { $current_file == "" } {
+ fail "$testname (missing filename)"
+ return 0
+ }
+ _add_entry $current_file $current_module \
+ $lineno $text
+ exp_continue
+ }
+ -re "^\r\n" {
+ exp_continue
+ }
+ -re "^$gdb_prompt $" {
+ # All done.
+ }
+ timeout {
+ fail "$testname (timeout)"
+ return 0
+ }
+ }
+
+ pass $testname
+ return 1
+ }
+
+ # Check that the header held in _header matches PATTERN. Use
+ # TESTNAME as the name of the test, or create a suitable default
+ # test name based on the last command.
+ proc check_header { pattern { testname "" } } {
+ variable _header
+ variable _last_command
+
+ if { $testname == "" } {
+ set testname "$_last_command: check header"
+ }
+
+ gdb_assert {[regexp -- $pattern $_header]} $testname
+ }
+
+ # Check that we have an entry in _entries matching FILENAME,
+ # MODULE, LINENO, and TEXT. If LINENO is the empty string it is
+ # replaced with the string NONE in order to match a similarly
+ # missing line number in the output of the command.
+ #
+ # TESTNAME is the name of the test, or a default will be created
+ # based on the last command run and the arguments passed here.
+ #
+ # If a matching entry is found then it is removed from the
+ # _entries list, this allows us to check for duplicates using the
+ # check_no_entry call.
+ proc check_entry { filename module lineno text { testname "" } } {
+ variable _entries
+ variable _last_command
+
+ if { $testname == "" } {
+ set testname \
+ "$_last_command: check for entry '$filename', '$lineno', '$text'"
+ }
+
+ if { $lineno == "" } {
+ set lineno "NONE"
+ }
+
+ set new_entries [list]
+
+ set found_match 0
+ foreach entry $_entries {
+
+ if {!$found_match} {
+ set f [lindex $entry 0]
+ set m [lindex $entry 1]
+ set l [lindex $entry 2]
+ set t [lindex $entry 3]
+ if { [regexp -- $filename $f] \
+ && [regexp -- $module $m] \
+ && [regexp -- $lineno $l] \
+ && [regexp -- $text $t] } {
+ set found_match 1
+ } else {
+ lappend new_entries $entry
+ }
+ } else {
+ lappend new_entries $entry
+ }
+ }
+
+ set _entries $new_entries
+ gdb_assert { $found_match } $testname
+ }
+
+ # Check that there is no entry in the _entries list matching
+ # FILENAME, MODULE, LINENO, and TEXT. The LINENO and TEXT are
+ # optional, and will be replaced with '.*' if missing.
+ #
+ # If LINENO is the empty string then it will be replaced with the
+ # string NONE in order to match against missing line numbers in
+ # the output of the command.
+ #
+ # TESTNAME is the name of the test, or a default will be built
+ # from the last command run and the arguments passed here.
+ #
+ # This can be used after a call to check_entry to ensure that
+ # there are no further matches for a particular file in the
+ # output.
+ proc check_no_entry { filename module { lineno ".*" } \
+ { text ".*" } { testname "" } } {
+ variable _entries
+ variable _last_command
+
+ if { $testname == "" } {
+ set testname \
+ "$_last_command: check no matches for '$filename', $lineno', and '$text'"
+ }
+
+ if { $lineno == "" } {
+ set lineno "NONE"
+ }
+
+ foreach entry $_entries {
+ set f [lindex $entry 0]
+ set m [lindex $entry 1]
+ set l [lindex $entry 2]
+ set t [lindex $entry 3]
+ if { [regexp -- $filename $f] \
+ && [regexp -- $module $m] \
+ && [regexp -- $lineno $l] \
+ && [regexp -- $text $t] } {
+ fail $testname
+ }
+ }
+
+ pass $testname
+ }
+}