| # Copyright (C) 1988, 90, 91, 92, 1994, 1996, 1997, 2000 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 2 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, write to the Free Software |
| # Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| |
| # This file was written by Rob Savoye. (rob@cygnus.com) |
| # With modifications by Mike Stump <mrs@cygnus.com>. |
| |
| # These tests come from the original DejaGnu test suite |
| # developed at Cygnus Support. If this isn't deja gnu, I |
| # don't know what is. |
| # |
| # Language independence is achieved by: |
| # |
| # 1) Using global $tool to indicate the language (eg: gcc, g++, etc.). |
| # This should only be used to look up other objects. We don't want to |
| # have to add code for each new language that is supported. If this is |
| # done right, no code needs to be added here for each new language. |
| # |
| # 2) Passing compiler options in as arguments. |
| # |
| # We require a bit of smarts in our caller to isolate us from the vagaries of |
| # each language. See old-deja.exp for the g++ example. |
| |
| # Useful subroutines. |
| |
| # process-option -- Look for and process a test harness option in the testcase. |
| # |
| # PROG is the pathname of the testcase. |
| # OPTION is the string to look for. |
| # MESSAGE is what to print if $verbose > 1. |
| # FLAG_NAME is one of ERROR, WARNING, etc. |
| # PATTERN is ??? |
| |
| proc process-option { prog option message flag_name pattern } { |
| global verbose |
| |
| set result "" |
| |
| set tmp [grep $prog "$option.*" line] |
| if ![string match "" $tmp] then { |
| foreach i $tmp { |
| #send_user "Found: $i\n" |
| set xfail_test 0 |
| set triplet_match 0 |
| regsub "\\*/$" [string trim $i] "" i |
| if [regexp "LINE +\[0-9\]+" $i xopt] then { |
| regsub "LINE" $xopt "" xopt; |
| regsub "LINE +\[0-9\]+" $i "" i |
| set i [lreplace $i 0 0 [expr "${xopt}-0"]]; |
| } |
| if [regexp "XFAIL( +\[^ \]+-\[^ \]+-\[^ \]+)*" $i xopt] then { |
| set xfail_test 1 |
| regsub "XFAIL( +\[^ \]+-\[^ \]+-\[^ \]+)*" $i "" i |
| regsub "XFAIL" $xopt "" xopt |
| if ![string match "" [string trim $xopt]] then { |
| foreach triplet $xopt { |
| if [istarget $triplet] { |
| set triplet_match 1; |
| break; |
| } |
| } |
| } else { |
| set triplet_match 1 |
| } |
| } |
| set compos [expr [llength $option] + 1] ;# Start of comment, if any |
| if { $xfail_test && $triplet_match } then { |
| lappend result [list [lindex $i 0] "X$flag_name" [lrange $i $compos end] "$pattern"] |
| } else { |
| lappend result [list [lindex $i 0] "$flag_name" [lrange $i $compos end] "$pattern"] |
| } |
| if { $verbose > 1 } then { |
| if [string match "" [lrange $i $compos end]] then { |
| send_user "Found $message for line [lindex $i 0]\n" |
| } else { |
| send_user "Found $message \"[lrange $i $compos end]\" for line [lindex $i 0]\n" |
| } |
| } |
| } |
| } |
| |
| #send_user "Returning: $result\n" |
| return $result |
| } |
| |
| # old-dejagnu-init -- set up some statistics collectors |
| # |
| # There currently isn't much to do, but always calling it allows us to add |
| # enhancements without having to update our callers. |
| # It must be run before calling `old-dejagnu'. |
| |
| proc old-dejagnu-init { } { |
| } |
| |
| # old-dejagnu-stat -- print the stats of this run |
| # |
| # ??? This is deprecated, and can be removed. |
| |
| proc old-dejagnu-stat { } { |
| } |
| |
| # old-dejagnu -- runs an old style DejaGnu test. |
| # |
| # Returns 0 if successful, 1 if their were any errors. |
| # PROG is the full path name of the file to compile. |
| # |
| # CFLAGSX is the options to always pass to the compiler. |
| # |
| # DEFAULT_CFLAGS are additional options if the testcase has none. |
| # |
| # LIBS_VAR is the name of the global variable containing libraries (-lxxx's). |
| # This is also ignored. |
| # |
| # LIBS is any additional libraries to link with. This *cannot* be specified |
| # with the compiler flags because otherwise gcc will issue, for example, a |
| # "-lg++ argument not used since linking not done" warning which will screw up |
| # the test for excess errors. We could ignore such messages instead. |
| # |
| # Think of "cflags" here as "compiler flags", not "C compiler flags". |
| |
| proc old-dejagnu { compiler prog name cflagsx default_cflags libs } { |
| global verbose |
| global tool |
| global subdir ;# eg: g++.old-dejagnu |
| global host_triplet |
| global tmpdir |
| |
| set runflag 1 |
| set execbug_flag 0 |
| set excessbug_flag 0 |
| set pattern "" |
| set text "\[- A-Za-z0-9\.\;\"\_\:\'\`\(\)\!\#\=\+\?\&\*]*" |
| |
| if ![info exists tmpdir] then { |
| set tmpdir "/tmp" |
| } |
| |
| # look for keywords that change the compiler options |
| # |
| # There are two types of test, negative and affirmative. Negative |
| # tests have the keyword of "ERROR - " or "WARNING - " on the line |
| # expected to produce an error. This is followed by the pattern. If |
| # the desired error or warning message appears, then the test passes. |
| # |
| # Affirmative test can have the following keywords "gets bogus error", |
| # "causes invalid C code", "invalid assembly code", "causes abort", |
| # "causes segfault", "causes linker error", "execution test fails". If |
| # the pattern after the keyword matches, then the test is a failure. |
| # |
| # One can specify particular targets for expected failures of the above |
| # keywords by putting "XFAIL target-triplet" after the keyword. |
| # |
| # Example: |
| # |
| # void f () |
| #{ |
| # int i[2], j; |
| # A a (int (i[1]), j); // gets bogus error - late parsing XFAIL *-*-* |
| # A b (int (i[1]), int j); // function |
| # a.k = 0; // gets bogus error - late parsing XFAIL *-*-* |
| # b (i, j); |
| #} |
| # |
| # Note also, that one can add a comment with the keyword ("late parsing" |
| # in the above example). |
| # |
| # If any of the tests contain the special pattern "FIXME -" that test is |
| # not run because it will produce incorrect output. |
| # |
| # Testcases can supply special options to the compiler with a line containing |
| # "Special.*Options: ...", where ".*" can be anything (eg: g++) and "..." are |
| # the additional options to pass to the compiler. Nothing else may appear |
| # after the options. IE: for a C testcase |
| # /* Special Options: -fomit-frame-pointer */ /* Oops! */ |
| # is wrong, |
| # /* Special Options: -fomit-frame-pointer */ |
| # is right. If no such Special Options are found, $default_cflags is used. |
| # FIXME: Can there be multiple lines of these? |
| # |
| # Other keywords: "Build don't link:", "Build don't run:", "Build then link:", |
| # "Additional sources: <file>.cc ..." |
| |
| # $name is now passed in. |
| # set name "[file tail [file dirname $prog]]/[file tail $prog]" |
| |
| set tmp [grep $prog "FIXME -.*"] |
| if ![string match "" $tmp] then { |
| foreach i $tmp { |
| warning "[file tail [file dirname $prog]]/[file tail $prog] [lrange $i 2 end]" |
| } |
| return 1 |
| } |
| |
| set tmp [lindex [grep $prog "Special.*Options:.*"] 0] |
| set cflags "" |
| |
| regsub -all "\n\[^\n\]+(\n|$)" $tmp "\n" tmp |
| set tmp [string trim $tmp] |
| if ![string match "" $tmp] then { |
| regsub "^.*Special.*Options:" $tmp "" tmp |
| lappend cflags "additional_flags=$tmp" |
| verbose "Adding special options $tmp" 2 |
| } else { |
| lappend cflags "additional_flags=$default_cflags" |
| } |
| |
| if { $cflagsx != "" } { |
| lappend cflags "additional_flags=$cflagsx" |
| } |
| |
| set tmp [lindex [grep $prog "Additional sources: .*"] 0] |
| regsub -all "\n\[^\n\]+(\n|$)" $tmp "\n" tmp |
| set tmp [string trim $tmp] |
| if ![string match "" $tmp] then { |
| regsub "^.*Additional.*sources:" $tmp "" tmp |
| regsub -all " " $tmp " [file dirname $prog]/" tmp |
| lappend cflags "additional_flags=$tmp" |
| verbose "Adding sources $tmp" |
| } |
| |
| lappend cflags "compiler=$compiler" |
| |
| regsub -all "\[./\]" "$name" "-" output; |
| set output "$tmpdir/$output"; |
| set compile_type "executable" |
| |
| set tmp [lindex [grep $prog "Build don.t link:"] 0] |
| if ![string match "" $tmp] then { |
| set compile_type "object" |
| set runflag 0 |
| set output "$tmpdir/[file tail [file rootname $prog]].o" |
| verbose "Will compile $prog to object" 3 |
| } |
| |
| set tmp [lindex [grep $prog "Build then link:"] 0] |
| if ![string match "" $tmp] then { |
| set compile_type "object" |
| set runflag 2 |
| set final_output "$output" |
| set output "$tmpdir/[file tail [file rootname $prog]].o" |
| verbose "Will compile $prog to object, then link it" 3 |
| } |
| |
| set tmp [lindex [grep $prog "Build don.t run:"] 0] |
| if ![string match "" $tmp] then { |
| set runflag 0 |
| verbose "Will compile $prog to binary" 3 |
| } |
| |
| set tmp [grep $prog "Skip if (|not )feature:.*"]; |
| if { $tmp != "" } { |
| foreach line $tmp { |
| if [regexp "Skip if not feature" $line] { |
| set not 1; |
| } else { |
| set not 0; |
| } |
| regsub "^.*Skip if (|not )feature:\[ \]*" "$line" "" i; |
| set is_set 0; |
| foreach j $i { |
| if [target_info exists $j] { |
| set is_set 1; |
| break; |
| } |
| } |
| if { $is_set != $not } { |
| untested "$name: Test skipped: ${line}($j set)" |
| return; |
| } |
| } |
| } |
| |
| set tmp [grep $prog "Skip if (|not )target:.*"]; |
| if { $tmp != "" } { |
| foreach line $tmp { |
| if [regexp "Skip if not target:" $line] { |
| set not 1; |
| } else { |
| set not 0; |
| } |
| regsub "^.*Skip if (|not )target:\[ \]*" "$line" "" i; |
| set ist 0; |
| foreach j $i { |
| if [istarget $j] { |
| set ist 1; |
| break; |
| } |
| } |
| if { $ist != $not } { |
| untested "$name: Test skipped: ${line}" |
| return; |
| } |
| } |
| } |
| |
| if ![isnative] { |
| set tmp [lindex [grep $prog "Skip if not native"] 0]; |
| if { $tmp != "" } { |
| untested "$name: Test skipped because not native"; |
| return; |
| } |
| } else { |
| set tmp [lindex [grep $prog "Skip if native"] 0]; |
| if { $tmp != "" } { |
| untested "$name: Test skipped because native"; |
| return; |
| } |
| } |
| |
| lappend cflags "libs=$libs" |
| |
| # |
| # Look for the other keywords and extract the error messages. |
| # `message' contains all the things we found. |
| # ??? We'd like to use lappend below instead of concat, but that doesn't |
| # work (adds an extra level of nesting to $tmp). |
| # |
| |
| set message "" |
| |
| set tmp [process-option $prog "ERROR - " "an error message" ERROR "$text error$text"] |
| if ![string match "" $tmp] then { |
| set runflag 0 |
| set message [concat $message $tmp] |
| } |
| |
| set tmp [process-option $prog "WARNING - " "a warning message" WARNING "warning"] |
| if ![string match "" $tmp] then { |
| set runflag 0 |
| set message [concat $message $tmp] |
| } |
| |
| set tmp [process-option $prog "gets bogus error" "a bogus error" BOGUS $text] |
| if ![string match "" $tmp] then { |
| set message [concat $message $tmp] |
| } |
| |
| set tmp [process-option $prog "causes invalid C code" "a bad C translation" BADC $text] |
| if ![string match "" $tmp] then { |
| set message [concat $message $tmp] |
| } |
| |
| set tmp [process-option $prog "invalid assembly code" "some invalid assembly code" BADASM $text] |
| if ![string match "" $tmp] then { |
| set message [concat $message $tmp] |
| } |
| |
| set tmp [process-option $prog "causes abort" "an abort cause" ABORT $text] |
| if ![string match "" $tmp] then { |
| set message [concat $message $tmp] |
| } |
| |
| set tmp [process-option $prog "causes segfault" "a segfault cause" SEGFAULT $text] |
| if ![string match "" $tmp] then { |
| set message [concat $message $tmp] |
| } |
| |
| set tmp [process-option $prog "causes linker error" "a linker error" LINKER $text] |
| if ![string match "" $tmp] then { |
| set message [concat $message $tmp] |
| } |
| |
| set tmp [process-option $prog "execution test fails" "an execution failure" EXECO $text] |
| if ![string match "" $tmp] then { |
| set execbug_flag 1 |
| set message [concat $message $tmp] |
| warning "please use execution test - XFAIL *-*-* in $prog instead" |
| } |
| |
| set tmp [process-option $prog "execution test - " "an excess error failure" EXEC $text] |
| if ![string match "" $tmp] then { |
| set message [concat $message $tmp] |
| } |
| |
| set tmp [process-option $prog "excess errors test fails" "an excess error failure" EXCESSO $text] |
| if ![string match "" $tmp] then { |
| set excessbug_flag 1 |
| set message [concat $message $tmp] |
| warning "please use excess errors test - XFAIL *-*-* in $prog instead" |
| } |
| |
| set tmp [process-option $prog "excess errors test - " "an excess error failure" EXCESS $text] |
| if ![string match "" $tmp] then { |
| set message [concat $message $tmp] |
| } |
| |
| set expect_crash \ |
| [process-option $prog "crash test - " "a crash" CRASH $text] |
| if {$expect_crash != "" |
| && [lindex [lindex $expect_crash 0] 1] == "XCRASH"} then { |
| set expect_crash 1 |
| } else { |
| set expect_crash 0 |
| } |
| |
| # |
| # run the compiler and analyze the results |
| # |
| |
| # Since we don't check return status of the compiler, make sure |
| # we can't run a.out when the compilation fails. |
| remote_file build delete $output |
| set comp_output [${tool}_target_compile $prog $output $compile_type $cflags] |
| if { $runflag == 2 && [file exists $output] } then { |
| set runflag 0 |
| set comp_output [concat $comp_output [${tool}_target_compile $output $final_output "executable" $cflags]] |
| set output $final_output |
| } |
| |
| # Delete things like "ld.so: warning" messages. |
| set comp_output [prune_warnings $comp_output] |
| |
| if [regexp "Internal (compiler )?error" $comp_output] then { |
| if $expect_crash then { |
| setup_xfail "*-*-*" |
| } |
| fail "$name caused compiler crash" |
| remote_file build delete $output |
| return 1 |
| } |
| |
| #send_user "\nold_dejagnu.exp: comp_output1 = :$comp_output:\n\n" |
| #send_user "\nold_dejagnu.exp: message = :$message:\n\n" |
| #send_user "\nold_dejagnu.exp: message length = [llength $message]\n\n" |
| |
| set last_line 0 |
| foreach i $message { |
| |
| #send_user "\nold_dejagnu.exp: i = :$i:\n\n" |
| |
| # Remove all error messages for the line [lindex $i 0] |
| # in the source file. If we find any, success! |
| set line [lindex $i 0] |
| set pattern [lindex $i 2] |
| |
| # Multiple tests one one line don't work, because we remove all |
| # messages on the line for the first test. So skip later ones. |
| if { $line == $last_line } { |
| continue |
| } |
| set last_line $line |
| |
| if [regsub -all "(^|\n)\[^\n\]+:$line:\[^\n\]*" $comp_output "" comp_output] { |
| set comp_output [string trimleft $comp_output] |
| set ok pass |
| set uhoh fail |
| } else { |
| set ok fail |
| set uhoh pass |
| } |
| |
| case [lindex $i 1] { |
| "ERROR" { |
| $ok "$name $pattern (test for errors, line $line)" |
| } |
| "XERROR" { |
| x$ok "$name $pattern (test for errors, line $line)" |
| } |
| "WARNING" { |
| $ok "$name $pattern (test for warnings, line $line)" |
| } |
| "XWARNING" { |
| x$ok "$name $pattern (test for warnings, line $line)" |
| } |
| "BOGUS" { |
| $uhoh "$name $pattern (test for bogus messages, line $line)" |
| } |
| "XBOGUS" { |
| x$uhoh "$name $pattern (test for bogus messages, line $line)" |
| } |
| "ABORT" { |
| $uhoh "$name $pattern (test for compiler aborts, line $line)" |
| } |
| "XABORT" { |
| x$uhoh "$name $pattern (test for compiler aborts, line $line)" |
| } |
| "SEGFAULT" { |
| $uhoh "$name $pattern (test for compiler segfaults, line $line)" |
| } |
| "XSEGFAULT" { |
| x$uhoh "$name $pattern (test for compiler segfaults, line $line)" |
| } |
| "LINKER" { |
| $uhoh "$name $pattern (test for linker problems, line $line)" |
| } |
| "XLINKER" { |
| x$uhoh "$name $pattern (test for linker problems, line $line)" |
| } |
| "BADC" { |
| $uhoh "$name $pattern (test for Bad C code, line $line)" |
| } |
| "XBADC" { |
| x$uhoh "$name $pattern (test for Bad C code, line $line)" |
| } |
| "BADASM" { |
| $uhoh "$name $pattern (test for bad assembler, line $line)" |
| } |
| "XBADASM" { |
| x$uhoh "$name $pattern (test for bad assembler, line $line)" |
| } |
| "XEXEC" { |
| set execbug_flag 1 |
| } |
| "XEXCESS" { |
| set excessbug_flag 1 |
| } |
| } |
| #send_user "\nold_dejagnu.exp: comp_output2= :$comp_output:\n\n" |
| } |
| #send_user "\nold_dejagnu.exp: comp_output3 = :$comp_output:\n\n" |
| |
| #look to see if this is all thats left, if so, all messages have been handled |
| #send_user "comp_output: $comp_output\n" |
| regsub -all "(^|\n)\[^\n\]*: In (\[^\n\]*function|method|\[^\n\]*structor) \[^\n\]*" $comp_output "" comp_output |
| regsub -all "(^|\n)\[^\n\]*: In instantiation of \[^\n\]*" $comp_output "" comp_output |
| regsub -all "(^|\n)\[^\n\]*: instantiated from \[^\n\]*" $comp_output "" comp_output |
| regsub -all "(^|\n)\[^\n\]*: At (top level|global scope):\[^\n\]*" $comp_output "" comp_output |
| regsub -all "(^|\n)\[^\n\]*file path prefix \[^\n\]* never used" $comp_output "" comp_output |
| regsub -all "(^|\n)\[^\n\]*linker input file unused since linking not done" $comp_output "" comp_output |
| regsub -all "(^|\n)collect: re(compiling|linking)\[^\n\]*" $comp_output "" comp_output |
| |
| set unsupported_message [${tool}_check_unsupported_p $comp_output] |
| if { $unsupported_message != "" } { |
| unsupported "$name: $unsupported_message" |
| return |
| } |
| |
| # someone forgot to delete the extra lines |
| regsub -all "\n+" $comp_output "\n" comp_output |
| regsub "^\n+" $comp_output "" comp_output |
| #send_user "comp_output: $comp_output\n" |
| |
| # excess errors |
| if $excessbug_flag then { |
| setup_xfail "*-*-*" |
| } |
| if ![string match "" $comp_output] then { |
| fail "$name (test for excess errors)" |
| send_log "$comp_output\n" |
| } else { |
| pass "$name (test for excess errors)" |
| } |
| |
| # run the executable image |
| if $runflag then { |
| set executable $output |
| if ![file exists $executable] then { |
| # Since we couldn't run it, we consider it an expected failure, |
| # so that test cases don't appear to disappear, and reappear. |
| setup_xfail "*-*-*" |
| fail "$name $pattern Execution test" |
| } else { |
| set status -1 |
| set result [eval [format "%s_load %s" $tool $executable]] |
| set status [lindex $result 0]; |
| set output [lindex $result 1]; |
| if { $status == "pass" } { |
| remote_file build delete $executable; |
| } |
| if { $execbug_flag || $excessbug_flag } then { |
| setup_xfail "*-*-*" |
| } |
| $status "$name $pattern Execution test" |
| } |
| } |
| |
| verbose "deleting $output" |
| remote_file build delete $output |
| return 0 |
| } |