aboutsummaryrefslogtreecommitdiff
path: root/runtest.exp
diff options
context:
space:
mode:
authorRob Savoye <rob@welcomehome.org>2001-02-05 04:14:59 +0000
committerRob Savoye <rob@welcomehome.org>2001-02-05 04:14:59 +0000
commit20f1185dd84bcadf4b238d1d2ca18f5ca79157d4 (patch)
treeda300d5097593bc1d61123a8e32179914440e85f /runtest.exp
downloaddejagnu-20f1185dd84bcadf4b238d1d2ca18f5ca79157d4.zip
dejagnu-20f1185dd84bcadf4b238d1d2ca18f5ca79157d4.tar.gz
dejagnu-20f1185dd84bcadf4b238d1d2ca18f5ca79157d4.tar.bz2
Initial revision
Diffstat (limited to 'runtest.exp')
-rwxr-xr-xruntest.exp1873
1 files changed, 1873 insertions, 0 deletions
diff --git a/runtest.exp b/runtest.exp
new file mode 100755
index 0000000..cfc2ea8
--- /dev/null
+++ b/runtest.exp
@@ -0,0 +1,1873 @@
+# Test Framework Driver
+# Copyright (C) 92, 93, 94, 95, 96, 97, 98, 1999 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-dejagnu@prep.ai.mit.edu
+
+# This file was written by Rob Savoye. (rob@cygnus.com)
+
+set frame_version 1.3.1
+if ![info exists argv0] {
+ send_error "Must use a version of Expect greater than 5.0\n"
+ exit 1
+}
+
+#
+# trap some signals so we know whats happening. These definitions are only
+# temporary until we read in the library stuff
+#
+trap { send_user "\nterminated\n"; exit 1 } SIGTERM
+trap { send_user "\ninterrupted by user\n"; exit 1 } SIGINT
+trap { send_user "\nsigquit\n"; exit 1 } SIGQUIT
+
+#
+# Initialize a few global variables used by all tests.
+# `reset_vars' resets several of these, we define them here to document their
+# existence. In fact, it would be nice if all globals used by some interface
+# of dejagnu proper were documented here.
+#
+# Keep these all lowercase. Interface variables used by the various
+# testsuites (eg: the gcc testsuite) should be in all capitals
+# (eg: TORTURE_OPTIONS).
+#
+set mail_logs 0 ;# flag for mailing of summary and diff logs
+set psum_file "latest" ;# file name of previous summary to diff against
+
+set exit_status 0 ;# exit code returned by this program
+
+set xfail_flag 0
+set xfail_prms 0
+set sum_file "" ;# name of the file that contains the summary log
+set base_dir "" ;# the current working directory
+set logname "" ;# the users login name
+set prms_id 0 ;# GNATS prms id number
+set bug_id 0 ;# optional bug id number
+set dir "" ;# temp variable for directory names
+set srcdir "." ;# source directory containing the test suite
+set ignoretests "" ;# list of tests to not execute
+set objdir "." ;# directory where test case binaries live
+set reboot 0
+set configfile site.exp ;# (local to this file)
+set multipass "" ;# list of passes and var settings
+set errno ""; ;#
+#
+# These describe the host and target environments.
+#
+set build_triplet "" ;# type of architecture to run tests on
+set build_os "" ;# type of os the tests are running on
+set build_vendor "" ;# vendor name of the OS or workstation the test are running on
+set build_cpu "" ;# type of the cpu tests are running on
+set host_triplet "" ;# type of architecture to run tests on, sometimes remotely
+set host_os "" ;# type of os the tests are running on
+set host_vendor "" ;# vendor name of the OS or workstation the test are running on
+set host_cpu "" ;# type of the cpu tests are running on
+set target_triplet "" ;# type of architecture to run tests on, final remote
+set target_os "" ;# type of os the tests are running on
+set target_vendor "" ;# vendor name of the OS or workstation the test are running on
+set target_cpu "" ;# type of the cpu tests are running on
+set target_alias "" ;# standard abbreviation of target
+set compiler_flags "" ;# the flags used by the compiler
+
+#
+# some convenience abbreviations
+#
+if ![info exists hex] {
+ set hex "0x\[0-9A-Fa-f\]+"
+}
+if ![info exists decimal] {
+ set decimal "\[0-9\]+"
+}
+
+#
+# set the base dir (current working directory)
+#
+set base_dir [pwd]
+
+#
+# These are tested in case they are not initialized in $configfile. They are
+# tested here instead of the init module so they can be overridden by command
+# line options.
+#
+if ![info exists all_flag] {
+ set all_flag 0
+}
+if ![info exists binpath] {
+ set binpath ""
+}
+if ![info exists debug] {
+ set debug 0
+}
+if ![info exists options] {
+ set options ""
+}
+if ![info exists outdir] {
+ set outdir "."
+}
+if ![info exists reboot] {
+ set reboot 1
+}
+if ![info exists tracelevel] {
+ set tracelevel 0
+}
+if ![info exists verbose] {
+ set verbose 0
+}
+
+#
+# verbose [-n] [-log] [--] message [level]
+#
+# Print MESSAGE if the verbose level is >= LEVEL.
+# The default value of LEVEL is 1.
+# "-n" says to not print a trailing newline.
+# "-log" says to add the text to the log file even if it won't be printed.
+# Note that the apparent behaviour of `send_user' dictates that if the message
+# is printed it is also added to the log file.
+# Use "--" if MESSAGE begins with "-".
+#
+# This is defined here rather than in framework.exp so we can use it
+# while still loading in the support files.
+#
+proc verbose { args } {
+ global verbose
+ set newline 1
+ set logfile 0
+
+ set i 0
+ if { [string index [lindex $args 0] 0] == "-" } {
+ for { set i 0 } { $i < [llength $args] } { incr i } {
+ if { [lindex $args $i] == "--" } {
+ incr i
+ break
+ } elseif { [lindex $args $i] == "-n" } {
+ set newline 0
+ } elseif { [lindex $args $i] == "-log" } {
+ set logfile 1
+ } elseif { [string index [lindex $args $i] 0] == "-" } {
+ clone_output "ERROR: verbose: illegal argument: [lindex $args $i]"
+ return
+ } else {
+ break
+ }
+ }
+ if { [llength $args] == $i } {
+ clone_output "ERROR: verbose: nothing to print"
+ return
+ }
+ }
+
+ set level 1
+ if { [llength $args] > $i + 1 } {
+ set level [lindex $args [expr $i+1]]
+ }
+ set message [lindex $args $i]
+
+ if { $verbose >= $level } {
+ # There is no need for the "--" argument here, but play it safe.
+ # We assume send_user also sends the text to the log file (which
+ # appears to be the case though the docs aren't clear on this).
+ if { $newline } {
+ send_user -- "$message\n"
+ } else {
+ send_user -- "$message"
+ }
+ } elseif { $logfile } {
+ if { $newline } {
+ send_log "$message\n"
+ } else {
+ send_log "$message"
+ }
+ }
+}
+
+#
+# Transform a tool name to get the installed name.
+# target_triplet is the canonical target name. target_alias is the
+# target name used when configure was run.
+#
+proc transform { name } {
+ global target_triplet
+ global target_alias
+ global host_triplet
+ global board;
+
+ if [string match $target_triplet $host_triplet] {
+ return $name
+ }
+ if [string match "native" $target_triplet] {
+ return $name
+ }
+ if [board_info host exists no_transform_name] {
+ return $name
+ }
+ if [string match "" $target_triplet] {
+ return $name
+ } else {
+ if [info exists board] {
+ if [board_info $board exists target_install] {
+ set target_install [board_info $board target_install];
+ }
+ }
+ if [target_info exists target_install] {
+ set target_install [target_info target_install];
+ }
+ if [info exists target_alias] {
+ set tmp ${target_alias}-${name};
+ } elseif [info exists target_install] {
+ if { [lsearch -exact $target_install $target_alias] >= 0 } {
+ set tmp ${target_alias}-${name};
+ } else {
+ set tmp "[lindex $target_install 0]-${name}";
+ }
+ }
+ verbose "Transforming $name to $tmp";
+ return $tmp;
+ }
+}
+
+#
+# findfile arg0 [arg1] [arg2]
+#
+# Find a file and see if it exists. If you only care about the false
+# condition, then you'll need to pass a null "" for arg1.
+# arg0 is the filename to look for. If the only arg,
+# then that's what gets returned. If this is the
+# only arg, then if it exists, arg0 gets returned.
+# if it doesn't exist, return only the prog name.
+# arg1 is optional, and it's what gets returned if
+# the file exists.
+# arg2 is optional, and it's what gets returned if
+# the file doesn't exist.
+#
+proc findfile { args } {
+ # look for the file
+ verbose "Seeing if [lindex $args 0] exists." 2
+ if [file exists [lindex $args 0]] {
+ if { [llength $args] > 1 } {
+ verbose "Found file, returning [lindex $args 1]"
+ return [lindex $args 1]
+ } else {
+ verbose "Found file, returning [lindex $args 0]"
+ return [lindex $args 0]
+ }
+ } else {
+ if { [llength $args] > 2 } {
+ verbose "Didn't find file [lindex $args 0], returning [lindex $args 2]"
+ return [lindex $args 2]
+ } else {
+ verbose "Didn't find file, returning [file tail [lindex $args 0]]"
+ return [transform [file tail [lindex $args 0]]]
+ }
+ }
+}
+
+#
+# load_file [-1] [--] file1 [ file2 ... ]
+#
+# Utility to source a file. All are sourced in order unless the flag "-1"
+# is given in which case we stop after finding the first one.
+# The result is 1 if a file was found, 0 if not.
+# If a tcl error occurs while sourcing a file, we print an error message
+# and exit.
+#
+# ??? Perhaps add an optional argument of some descriptive text to add to
+# verbose and error messages (eg: -t "library file" ?).
+#
+proc load_file { args } {
+ set i 0
+ set only_one 0
+ if { [lindex $args $i] == "-1" } {
+ set only_one 1
+ incr i
+ }
+ if { [lindex $args $i] == "--" } {
+ incr i
+ }
+
+ set found 0
+ foreach file [lrange $args $i end] {
+ verbose "Looking for $file" 2
+ # In Tcl7.5a2, "file exists" can fail if the filename looks
+ # like ~/FILE and the environment variable HOME does not
+ # exist.
+ if {! [catch {file exists $file} result] && $result} {
+ set found 1
+ verbose "Found $file"
+ if { [catch "uplevel #0 source $file"] == 1 } {
+ send_error "ERROR: tcl error sourcing $file.\n"
+ global errorInfo
+ if [info exists errorInfo] {
+ send_error "$errorInfo\n"
+ }
+ exit 1
+ }
+ if $only_one {
+ break
+ }
+ }
+ }
+ return $found
+}
+
+#
+# search_and_load_file -- search DIRLIST looking for FILELIST.
+# TYPE is used when displaying error and progress messages.
+#
+proc search_and_load_file { type filelist dirlist } {
+ set found 0;
+
+ foreach dir $dirlist {
+ foreach initfile $filelist {
+ verbose "Looking for $type ${dir}/${initfile}" 1
+ if [file exists ${dir}/${initfile}] {
+ set found 1
+ set error ""
+ if { ${type} != "library file" } {
+ send_user "Using ${dir}/${initfile} as ${type}.\n"
+ } else {
+ verbose "Loading ${dir}/${initfile}"
+ }
+ if [catch "uplevel #0 source ${dir}/${initfile}" error]==1 {
+ global errorInfo
+ send_error "ERROR: tcl error sourcing ${type} ${dir}/${initfile}.\n${error}\n"
+ if [info exists errorInfo] {
+ send_error "$errorInfo\n"
+ }
+ exit 1
+ }
+ break
+ }
+ }
+ if $found {
+ break
+ }
+ }
+ return $found;
+}
+
+#
+# Give a usage statement.
+#
+proc usage { } {
+ global tool;
+
+ send_user "USAGE: runtest \[options...\]\n"
+ send_user "\t--all (-a)\t\tPrint all test output to screen\n"
+ send_user "\t--build \[string\]\tThe canonical config name of the build machine\n"
+ send_user "\t--host \[string\]\t\tThe canonical config name of the host machine\n"
+ send_user "\t--host_board \[name\]\tThe host board to use\n"
+ send_user "\t--target \[string\]\tThe canonical config name of the target board\n"
+ send_user "\t--debug (-de)\t\tSet expect debugging ON\n"
+ send_user "\t--help (-he)\t\tPrint help text\n"
+ send_user "\t--mail \[name(s)\]\tWhom to mail the results to\n"
+ send_user "\t--ignore \[name(s)\]\tThe names of specific tests to ignore\n"
+ send_user "\t--objdir \[name\]\t\tThe test suite binary directory\n"
+ send_user "\t--outdir \[name\]\t\tThe directory to put logs in\n"
+ send_user "\t--reboot \[name\]\t\tReboot the target (if supported)\n"
+ send_user "\t--srcdir \[name\]\t\tThe test suite source code directory\n"
+ send_user "\t--strace \[number\]\tSet expect tracing ON\n"
+ send_user "\t--target_board \[name(s)\] The list of target boards to run tests on\n"
+ send_user "\t--tool\[name(s)\]\t\tRun tests on these tools\n"
+ send_user "\t--tool_exec \[name\]\tThe path to the tool executable to test\n"
+ send_user "\t--tool_opts \[options\]\tA list of additional options to pass to the tool\n"
+ send_user "\t--directory (-di) name\tRun only the tests in directory 'name'\n"
+ send_user "\t--verbose (-v)\t\tEmit verbose output\n"
+ send_user "\t--version (-V)\t\tEmit all version numbers\n"
+ send_user "\t--D\[0-1\]\t\tTcl debugger\n"
+ send_user "\tscript.exp\[=arg(s)\]\tRun these tests only\n"
+ if { [info exists tool] } {
+ if { [info proc ${tool}_option_help] != "" } {
+ ${tool}_option_help;
+ }
+ }
+}
+
+#
+# Parse the arguments the first time looking for these. We will ultimately
+# parse them twice. Things are complicated because:
+# - we want to parse --verbose early on
+# - we don't want config files to override command line arguments
+# (eg: $base_dir/$configfile vs --host/--target)
+# - we need some command line arguments before we can process some config files
+# (eg: --objdir before $objdir/$configfile, --host/--target before $DEJAGNU)
+# The use of `arg_host_triplet' and `arg_target_triplet' lets us avoid parsing
+# the arguments three times.
+#
+
+set arg_host_triplet ""
+set arg_target_triplet ""
+set arg_build_triplet ""
+set argc [ llength $argv ]
+for { set i 0 } { $i < $argc } { incr i } {
+ set option [lindex $argv $i]
+
+ # make all options have two hyphens
+ switch -glob -- $option {
+ "--*" {
+ }
+ "-*" {
+ set option "-$option"
+ }
+ }
+
+ # split out the argument for options that take them
+ switch -glob -- $option {
+ "--*=*" {
+ regexp {^[^=]*=(.*)$} $option nil optarg
+ }
+ "--bu*" -
+ "--ho*" -
+ "--ig*" -
+ "--m*" -
+ "--n*" -
+ "--ob*" -
+ "--ou*" -
+ "--sr*" -
+ "--st*" -
+ "--ta*" -
+ "--di*" -
+ "--to*" {
+ incr i
+ set optarg [lindex $argv $i]
+ }
+ }
+
+ switch -glob -- $option {
+ "--bu*" { # (--build) the build host configuration
+ set arg_build_triplet $optarg
+ continue
+ }
+
+ "--host_bo*" {
+ set host_board $optarg
+ continue
+ }
+
+ "--ho*" { # (--host) the host configuration
+ set arg_host_triplet $optarg
+ continue
+ }
+
+ "--ob*" { # (--objdir) where the test case object code lives
+ set objdir $optarg
+ continue
+ }
+
+ "--sr*" { # (--srcdir) where the testsuite source code lives
+ set srcdir $optarg
+ continue
+ }
+
+ "--target_bo*" {
+ set target_list $optarg;
+ continue;
+ }
+
+ "--ta*" { # (--target) the target configuration
+ set arg_target_triplet $optarg
+ continue
+ }
+
+ "--tool_opt*" {
+ set TOOL_OPTIONS $optarg
+ continue
+ }
+
+ "--tool_exec*" {
+ set TOOL_EXECUTABLE $optarg
+ continue
+ }
+
+ "--tool_ro*" {
+ set tool_root_dir $optarg
+ continue;
+ }
+
+ "--to*" { # (--tool) specify tool name
+ set tool $optarg
+ set comm_line_tool $optarg;
+ continue
+ }
+
+ "--di*" {
+ set cmdline_dir_to_run $optarg
+ puts "cmdline_dir_to_run = $cmdline_dir_to_run"
+ continue
+ }
+
+ "--v" -
+ "--verb*" { # (--verbose) verbose output
+ incr verbose
+ continue
+ }
+ }
+}
+verbose "Verbose level is $verbose"
+
+#
+# get the users login name
+#
+if [string match "" $logname] {
+ if [info exists env(USER)] {
+ set logname $env(USER)
+ } else {
+ if [info exists env(LOGNAME)] {
+ set logname $env(LOGNAME)
+ } else {
+ # try getting it with whoami
+ catch "set logname [exec whoami]" tmp
+ if [string match "*couldn't find*to execute*" $tmp] {
+ # try getting it with who am i
+ unset tmp
+ catch "set logname [exec who am i]" tmp
+ if [string match "*Command not found*" $tmp] {
+ send_user "ERROR: couldn't get the users login name\n"
+ set logname "Unknown"
+ } else {
+ set logname [lindex [split $logname " !"] 1]
+ }
+ }
+ }
+ }
+}
+
+#
+# lookfor_file -- try to find a file by searching up multiple directory levels
+#
+proc lookfor_file { dir name } {
+ foreach x ".. ../.. ../../.. ../../../.." {
+ verbose "$dir/$name"
+ if [file exists $dir/$name] {
+ return $dir/$name;
+ }
+ set dir [remote_file build dirname $dir];
+ }
+ return ""
+}
+
+#
+# load_lib -- load a library by sourcing it
+#
+# If there a multiple files with the same name, stop after the first one found.
+# The order is first look in the install dir, then in a parallel dir in the
+# source tree, (up one or two levels), then in the current dir.
+#
+proc load_lib { file } {
+ global verbose libdir srcdir base_dir execpath tool
+ global loaded_libs
+
+ if [info exists loaded_libs($file)] {
+ return;
+ }
+
+ set loaded_libs($file) "";
+
+ if { [search_and_load_file "library file" $file [list $libdir $libdir/lib [file dirname [file dirname $srcdir]]/dejagnu/lib $srcdir/lib . [file dirname [file dirname [file dirname $srcdir]]]/dejagnu/lib]] == 0 } {
+ send_error "ERROR: Couldn't find library file $file.\n"
+ exit 1
+ }
+}
+
+verbose "Login name is $logname"
+
+#
+# Begin sourcing the config files.
+# All are sourced in order.
+#
+# Search order:
+# $HOME/.dejagnurc -> $base_dir/$configfile -> $objdir/$configfile
+# -> installed -> $DEJAGNU
+#
+# ??? It might be nice to do $HOME last as it would allow it to be the
+# ultimate override. Though at present there is still $DEJAGNU.
+#
+# For the normal case, we rely on $base_dir/$configfile to set
+# host_triplet and target_triplet.
+#
+
+load_file ~/.dejagnurc $base_dir/$configfile
+
+#
+# If objdir didn't get set in $base_dir/$configfile, set it to $base_dir.
+# Make sure we source $objdir/$configfile in case $base_dir/$configfile doesn't
+# exist and objdir was given on the command line.
+#
+
+if [expr [string match "." $objdir] || [string match $srcdir $objdir]] {
+ set objdir $base_dir
+} else {
+ load_file $objdir/$configfile
+}
+
+# Well, this just demonstrates the real problem...
+if ![info exists tool_root_dir] {
+ set tool_root_dir [file dirname $objdir];
+ if [file exists "$tool_root_dir/testsuite"] {
+ set tool_root_dir [file dirname $tool_root_dir];
+ }
+}
+
+verbose "Using test sources in $srcdir"
+verbose "Using test binaries in $objdir"
+verbose "Tool root directory is $tool_root_dir"
+
+set execpath [file dirname $argv0]
+set libdir [file dirname $execpath]/dejagnu
+if [info exists env(DEJAGNULIBS)] {
+ set libdir $env(DEJAGNULIBS)
+}
+
+verbose "Using $libdir to find libraries"
+
+#
+# If the host or target was given on the command line, override the above
+# config files. We allow $DEJAGNU to massage them though in case it would
+# ever want to do such a thing.
+#
+if { $arg_host_triplet != "" } {
+ set host_triplet $arg_host_triplet
+}
+if { $arg_build_triplet != "" } {
+ set build_triplet $arg_build_triplet
+}
+
+# if we only specify --host, then that must be the build machne too, and we're
+# stuck using the old functionality of a simple cross test
+if [expr { $build_triplet == "" && $host_triplet != "" } ] {
+ set build_triplet $host_triplet
+}
+# if we only specify --build, then we'll use that as the host too
+if [expr { $build_triplet != "" && $host_triplet == "" } ] {
+ set host_triplet $build_triplet
+}
+unset arg_host_triplet arg_build_triplet
+
+#
+# If the build machine type hasn't been specified by now, use config.guess.
+#
+
+if [expr { $build_triplet == "" && $host_triplet == ""} ] {
+ # find config.guess
+ foreach dir "$libdir $libdir/.. $srcdir/.. $srcdir/../.." {
+ verbose "Looking for ${dir}/config.guess" 2
+ if [file exists ${dir}/config.guess] {
+ set config_guess ${dir}/config.guess
+ verbose "Found ${dir}/config.guess"
+ break
+ }
+ }
+
+ # get the canonical config name
+ if ![info exists config_guess] {
+ send_error "ERROR: Couldn't find config.guess program.\n"
+ exit 1
+ }
+ catch "exec $config_guess" build_triplet
+ case $build_triplet in {
+ { "No uname command or uname output not recognized" "Unable to guess system type" } {
+ verbose "WARNING: Uname output not recognized"
+ set build_triplet unknown
+ }
+ }
+ verbose "Assuming build host is $build_triplet"
+ if { $host_triplet == "" } {
+ set host_triplet $build_triplet
+ }
+
+}
+
+#
+# Figure out the target. If the target hasn't been specified, then we have to
+# assume we are native.
+#
+if { $arg_target_triplet != "" } {
+ set target_triplet $arg_target_triplet
+} elseif { $target_triplet == "" } {
+ set target_triplet $build_triplet
+ verbose "Assuming native target is $target_triplet" 2
+}
+unset arg_target_triplet
+#
+# Default target_alias to target_triplet.
+#
+if ![info exists target_alias] {
+ set target_alias $target_triplet
+}
+
+proc get_local_hostname { } {
+ if [catch "info hostname" hb] {
+ set hb ""
+ } else {
+ regsub "\\..*$" $hb "" hb;
+ }
+ verbose "hostname=$hb" 3;
+ return $hb;
+}
+
+#
+# We put these here so that they can be overridden later by site.exp or
+# friends.
+#
+# Set up the target as machine NAME. We also load base-config.exp as a
+# default configuration. The config files are sourced with the global
+# variable $board set to the name of the current target being defined.
+#
+proc setup_target_hook { whole_name name } {
+ global board;
+ global host_board;
+
+ if [info exists host_board] {
+ set hb $host_board;
+ } else {
+ set hb [get_local_hostname];
+ }
+
+ set board $whole_name;
+
+ global board_type;
+ set board_type "target";
+
+ load_config base-config.exp;
+ if ![load_board_description ${name} ${whole_name} ${hb}] {
+ if { $name != "unix" } {
+ perror "couldn't load description file for ${name}";
+ exit 1;
+ } else {
+ load_generic_config "unix"
+ }
+ }
+
+ if [board_info $board exists generic_name] {
+ load_tool_target_config [board_info $board generic_name];
+ }
+
+ unset board;
+ unset board_type;
+
+ push_target $whole_name;
+
+ if { [info procs ${whole_name}_init] != "" } {
+ ${whole_name}_init $whole_name;
+ }
+
+ if { ![isnative] && ![is_remote target] } {
+ global env build_triplet target_triplet
+ if { (![info exists env(DEJAGNU)]) && ($build_triplet != $target_triplet) } {
+ warning "Assuming target board is the local machine (which is probably wrong).\nYou may need to set your DEJAGNU environment variable."
+ }
+ }
+}
+
+#
+# Clean things up afterwards.
+#
+proc cleanup_target_hook { name } {
+ global tool;
+ # Clean up the target board.
+ if { [info procs "${name}_exit"] != "" } {
+ ${name}_exit;
+ }
+ # We also call the tool exit routine here.
+ if [info exists tool] {
+ if { [info procs "${tool}_exit"] != "" } {
+ ${tool}_exit;
+ }
+ }
+ remote_close target;
+ pop_target;
+}
+
+proc setup_host_hook { name } {
+ global board;
+ global board_info;
+ global board_type;
+
+ set board $name;
+ set board_type "host";
+
+ load_board_description $name;
+ unset board;
+ unset board_type;
+ push_host $name;
+ if { [info proc ${name}_init] != "" } {
+ ${name}_init $name;
+ }
+}
+
+proc setup_build_hook { name } {
+ global board;
+ global board_info;
+ global board_type;
+
+ set board $name;
+ set board_type "build";
+
+ load_board_description $name;
+ unset board;
+ unset board_type;
+ push_build $name;
+ if { [info proc ${name}_init] != "" } {
+ ${name}_init $name;
+ }
+}
+
+#
+# Find and load the global config file if it exists.
+# The global config file is used to set the connect mode and other
+# parameters specific to each particular target.
+# These files assume the host and target have been set.
+#
+
+if { [load_file -- $libdir/$configfile] == 0 } {
+ # If $DEJAGNU isn't set either then there isn't any global config file.
+ # Warn the user as there really should be one.
+ if { ! [info exists env(DEJAGNU)] } {
+ send_error "WARNING: Couldn't find the global config file.\n"
+ }
+}
+
+if [info exists env(DEJAGNU)] {
+ if { [load_file -- $env(DEJAGNU)] == 0 } {
+ # It may seem odd to only issue a warning if there isn't a global
+ # config file, but issue an error if $DEJAGNU is erroneously defined.
+ # Since $DEJAGNU is set there is *supposed* to be a global config file,
+ # so the current behaviour seems reasonable.
+ send_error "WARNING: global config file $env(DEJAGNU) not found.\n"
+ }
+ if ![info exists boards_dir] {
+ set boards_dir "[file dirname $env(DEJAGNU)]/boards";
+ }
+}
+
+if ![info exists boards_dir] {
+ set boards_dir ""
+}
+
+#
+# parse out the config parts of the triplet name
+#
+
+# build values
+if { $build_cpu == "" } {
+ regsub -- "-.*-.*" ${build_triplet} "" build_cpu
+}
+if { $build_vendor == "" } {
+ regsub -- "^\[a-z0-9\]*-" ${build_triplet} "" build_vendor
+ regsub -- "-.*" ${build_vendor} "" build_vendor
+}
+if { $build_os == "" } {
+ regsub -- ".*-.*-" ${build_triplet} "" build_os
+}
+
+# host values
+if { $host_cpu == "" } {
+ regsub -- "-.*-.*" ${host_triplet} "" host_cpu
+}
+if { $host_vendor == "" } {
+ regsub -- "^\[a-z0-9\]*-" ${host_triplet} "" host_vendor
+ regsub -- "-.*" ${host_vendor} "" host_vendor
+}
+if { $host_os == "" } {
+ regsub -- ".*-.*-" ${host_triplet} "" host_os
+}
+
+# target values
+if { $target_cpu == "" } {
+ regsub -- "-.*-.*" ${target_triplet} "" target_cpu
+}
+if { $target_vendor == "" } {
+ regsub -- "^\[a-z0-9\]*-" ${target_triplet} "" target_vendor
+ regsub -- "-.*" ${target_vendor} "" target_vendor
+}
+if { $target_os == "" } {
+ regsub -- ".*-.*-" ${target_triplet} "" target_os
+}
+
+#
+# Load the primary tool initialization file.
+#
+
+proc load_tool_init { file } {
+ global srcdir
+ global loaded_libs
+
+ if [info exists loaded_libs($file)] {
+ return;
+ }
+
+ set loaded_libs($file) "";
+
+ if [file exists ${srcdir}/lib/$file] {
+ verbose "Loading library file ${srcdir}/lib/$file"
+ if { [catch "uplevel #0 source ${srcdir}/lib/$file"] == 1 } {
+ send_error "ERROR: tcl error sourcing library file ${srcdir}/lib/$file.\n"
+ global errorInfo
+ if [info exists errorInfo] {
+ send_error "$errorInfo\n"
+ }
+ exit 1
+ }
+ } else {
+ warning "Couldn't find tool init file"
+ }
+}
+
+#
+# load the testing framework libraries
+#
+load_lib utils.exp
+load_lib framework.exp
+load_lib debugger.exp
+load_lib remote.exp
+load_lib target.exp
+load_lib targetdb.exp
+load_lib libgloss.exp
+
+# Initialize the test counters and reset them to 0.
+init_testcounts;
+reset_vars;
+
+#
+# Parse the command line arguments.
+#
+
+# Load the tool initialization file. Allow the --tool option to override
+# what's set in the site.exp file.
+if [info exists comm_line_tool] {
+ set tool $comm_line_tool;
+}
+
+if [info exists tool] {
+ load_tool_init ${tool}.exp;
+}
+
+set argc [ llength $argv ]
+for { set i 0 } { $i < $argc } { incr i } {
+ set option [ lindex $argv $i ]
+
+ # make all options have two hyphens
+ switch -glob -- $option {
+ "--*" {
+ }
+ "-*" {
+ set option "-$option"
+ }
+ }
+
+ # split out the argument for options that take them
+ switch -glob -- $option {
+ "--*=*" {
+ regexp {^[^=]*=(.*)$} $option nil optarg
+ }
+ "--bu*" -
+ "--ho*" -
+ "--ig*" -
+ "--m*" -
+ "--n*" -
+ "--ob*" -
+ "--ou*" -
+ "--sr*" -
+ "--st*" -
+ "--ta*" -
+ "--di*" -
+ "--to*" {
+ incr i
+ set optarg [lindex $argv $i]
+ }
+ }
+
+ switch -glob -- $option {
+ "--V*" -
+ "--vers*" { # (--version) version numbers
+ send_user "Expect version is\t[exp_version]\n"
+ send_user "Tcl version is\t\t[ info tclversion ]\n"
+ send_user "Framework version is\t$frame_version\n"
+ exit
+ }
+
+ "--v*" { # (--verbose) verbose output
+ # Already parsed.
+ continue
+ }
+
+ "--bu*" { # (--build) the build host configuration
+ # Already parsed (and don't set again). Let $DEJAGNU rename it.
+ continue
+ }
+
+ "--ho*" { # (--host) the host configuration
+ # Already parsed (and don't set again). Let $DEJAGNU rename it.
+ continue
+ }
+
+ "--target_bo*" {
+ # Set it again, father knows best.
+ set target_list $optarg;
+ continue;
+ }
+
+ "--ta*" { # (--target) the target configuration
+ # Already parsed (and don't set again). Let $DEJAGNU rename it.
+ continue
+ }
+
+ "--a*" { # (--all) print all test output to screen
+ set all_flag 1
+ verbose "Print all test output to screen"
+ continue
+ }
+
+ "--di*" {
+ # Already parsed (and don't set again). Let $DEJAGNU rename it.
+ # set cmdline_dir_to_run $optarg
+ continue
+ }
+
+
+ "--de*" { # (--debug) expect internal debugging
+ if [file exists ./dbg.log] {
+ catch "exec rm -f ./dbg.log"
+ }
+ if { $verbose > 2 } {
+ exp_internal -f dbg.log 1
+ } else {
+ exp_internal -f dbg.log 0
+ }
+ verbose "Expect Debugging is ON"
+ continue
+ }
+
+ "--D[01]" { # (-Debug) turn on Tcl debugger
+ verbose "Tcl debugger is ON"
+ continue
+ }
+
+ "--m*" { # (--mail) mail the output
+ set mailing_list $optarg
+ set mail_logs 1
+ verbose "Mail results to $mailing_list"
+ continue
+ }
+
+ "--r*" { # (--reboot) reboot the target
+ set reboot 1
+ verbose "Will reboot the target (if supported)"
+ continue
+ }
+
+ "--ob*" { # (--objdir) where the test case object code lives
+ # Already parsed, but parse again to make sure command line
+ # options override any config file.
+ set objdir $optarg
+ verbose "Using test binaries in $objdir"
+ continue
+ }
+
+ "--ou*" { # (--outdir) where to put the output files
+ set outdir $optarg
+ verbose "Test output put in $outdir"
+ continue
+ }
+
+ "*.exp" { # specify test names to run
+ set all_runtests($option) ""
+ verbose "Running only tests $option"
+ continue
+ }
+
+ "*.exp=*" { # specify test names to run
+ set tmp [split $option "="]
+ set all_runtests([lindex $tmp 0]) [lindex $tmp 1]
+ verbose "Running only tests $option"
+ unset tmp
+ continue
+ }
+
+ "--ig*" { # (--ignore) specify test names to exclude
+ set ignoretests $optarg
+ verbose "Ignoring test $ignoretests"
+ continue
+ }
+
+ "--sr*" { # (--srcdir) where the testsuite source code lives
+ # Already parsed, but parse again to make sure command line
+ # options override any config file.
+
+ set srcdir $optarg
+ continue
+ }
+
+ "--st*" { # (--strace) expect trace level
+ set tracelevel $optarg
+ strace $tracelevel
+ verbose "Source Trace level is now $tracelevel"
+ continue
+ }
+
+ "--tool_opt*" {
+ continue
+ }
+
+ "--tool_exec*" {
+ set TOOL_EXECUTABLE $optarg
+ continue
+ }
+
+ "--tool_ro*" {
+ set tool_root_dir $optarg
+ continue;
+ }
+
+ "--to*" { # (--tool) specify tool name
+ set tool $optarg
+ verbose "Testing $tool"
+ continue
+ }
+
+ "[A-Z0-9_-.]*=*" { # process makefile style args like CC=gcc, etc...
+ if [regexp "^(\[A-Z0-9_-\]+)=(.*)$" $option junk var val] {
+ set $var $val
+ verbose "$var is now $val"
+ append makevars "set $var $val;" ;# FIXME: Used anywhere?
+ unset junk var val
+ } else {
+ send_error "Illegal variable specification:\n"
+ send_error "$option\n"
+ }
+ continue
+ }
+
+ "--he*" { # (--help) help text
+ usage;
+ exit 0
+ }
+
+ default {
+ if [info exists tool] {
+ if { [info proc ${tool}_option_proc] != "" } {
+ if [${tool}_option_proc $option] {
+ continue;
+ }
+ }
+ }
+ send_error "\nIllegal Argument \"$option\"\n"
+ send_error "try \"runtest --help\" for option list\n"
+ exit 1
+ }
+ }
+}
+
+#
+# check for a few crucial variables
+#
+if ![info exists tool] {
+ send_error "WARNING: No tool specified\n"
+ set tool ""
+}
+
+#
+# initialize a few Tcl variables to something other than their default
+#
+if { $verbose > 2 } {
+ log_user 1
+} else {
+ log_user 0
+}
+
+set timeout 10
+
+
+
+#
+# open log files
+#
+open_logs
+
+# print the config info
+clone_output "Test Run By $logname on [timestamp -format %c]"
+if [is3way] {
+ clone_output "Target is $target_triplet"
+ clone_output "Host is $host_triplet"
+ clone_output "Build is $build_triplet"
+} else {
+ if [isnative] {
+ clone_output "Native configuration is $target_triplet"
+ } else {
+ clone_output "Target is $target_triplet"
+ clone_output "Host is $host_triplet"
+ }
+}
+
+clone_output "\n\t\t=== $tool tests ===\n"
+
+#
+# Look for the generic board configuration file. It searches in several
+# places: ${libdir}/config, ${libdir}/../config, and $boards_dir.
+#
+
+proc load_generic_config { name } {
+ global srcdir;
+ global configfile;
+ global libdir;
+ global env;
+ global board;
+ global board_info;
+ global boards_dir;
+ global board_type;
+
+ if [info exists board] {
+ if ![info exists board_info($board,generic_name)] {
+ set board_info($board,generic_name) $name;
+ }
+ }
+
+ if [info exists board_type] {
+ set type "for $board_type";
+ } else {
+ set type ""
+ }
+
+ set dirlist [concat ${libdir}/config [file dirname $libdir]/config $boards_dir];
+ set result [search_and_load_file "generic interface file $type" ${name}.exp $dirlist];
+
+ return $result;
+}
+
+#
+# Load the tool-specific target description.
+#
+proc load_config { args } {
+ global srcdir;
+ global board_type;
+
+ set found 0;
+
+ return [search_and_load_file "tool-and-target-specific interface file" $args [list ${srcdir}/config ${srcdir}/../config ${srcdir}/../../config ${srcdir}/../../../config]];
+}
+
+#
+# Find the files that set up the configuration for the target. There
+# are assumed to be two of them; one defines a basic set of
+# functionality for the target that can be used by all tool
+# testsuites, and the other defines any necessary tool-specific
+# functionality. These files are loaded via load_config.
+#
+# These used to all be named $target_abbrev-$tool.exp, but as the
+# $tool variable goes away, it's now just $target_abbrev.exp. First
+# we look for a file named with both the abbrev and the tool names.
+# Then we look for one named with just the abbrev name. Finally, we
+# look for a file called default, which is the default actions, as
+# some tools could be purely host based. Unknown is mostly for error
+# trapping.
+#
+
+proc load_tool_target_config { name } {
+ global target_os
+
+ set found [load_config "${name}.exp" "${target_os}.exp" "default.exp" "unknown.exp"];
+
+ if { $found == 0 } {
+ send_error "ERROR: Couldn't find tool config file for $name.\n"
+ }
+}
+
+
+#
+# Find the file that describes the machine specified by board_name.
+#
+
+proc load_board_description { board_name args } {
+ global srcdir;
+ global configfile;
+ global libdir;
+ global env;
+ global board;
+ global board_info
+ global boards_dir;
+ global board_type;
+
+ set dejagnu ""
+
+ if { [llength $args] > 0 } {
+ set whole_name [lindex $args 0];
+ } else {
+ set whole_name $board_name;
+ }
+
+ set board_info($whole_name,name) $whole_name;
+ if ![info exists board] {
+ set board $whole_name;
+ set board_set 1;
+ } else {
+ set board_set 0;
+ }
+
+ set dirlist {};
+ if { [llength $args] > 1 } {
+ set suffix [lindex $args 1];
+ if { ${suffix} != "" } {
+ foreach x ${boards_dir} {
+ lappend dirlist ${x}/${suffix}
+ }
+ lappend dirlist ${libdir}/baseboards/${suffix};
+ }
+ }
+ set dirlist [concat $dirlist $boards_dir];
+ lappend dirlist ${libdir}/baseboards;
+ verbose "dirlist is $dirlist"
+ if [info exists board_type] {
+ set type "for $board_type";
+ } else {
+ set type "";
+ }
+ if ![info exists board_info($whole_name,isremote)] {
+ set board_info($whole_name,isremote) 1;
+ if [info exists board_type] {
+ if { $board_type == "build" } {
+ set board_info($whole_name,isremote) 0;
+ }
+ }
+ if { ${board_name} == [get_local_hostname] } {
+ set board_info($whole_name,isremote) 0;
+ }
+ }
+ search_and_load_file "standard board description file $type" standard.exp $dirlist;
+ set found [search_and_load_file "board description file $type" ${board_name}.exp $dirlist];
+ if { $board_set != 0 } {
+ unset board;
+ }
+
+ return $found;
+}
+
+#
+# Find the base-level file that describes the machine specified by args. We
+# only look in one directory, ${libdir}/baseboards.
+#
+
+proc load_base_board_description { board_name } {
+ global srcdir;
+ global configfile;
+ global libdir;
+ global env;
+ global board;
+ global board_info
+ global board_type;
+
+ set board_set 0;
+ set board_info($board_name,name) $board_name;
+ if ![info exists board] {
+ set board $board_name;
+ set board_set 1;
+ }
+ if [info exists board_type] {
+ set type "for $board_type";
+ } else {
+ set type ""
+ };
+ if ![info exists board_info($board_name,isremote)] {
+ set board_info($board_name,isremote) 1;
+ if [info exists board_type] {
+ if { $board_type == "build" } {
+ set board_info($board_name,isremote) 0;
+ }
+ }
+ }
+
+ if { ${board_name} == [get_local_hostname] } {
+ set board_info($board_name,isremote) 0;
+ }
+ set found [search_and_load_file "board description file $type" ${board_name}.exp ${libdir}/baseboards];
+ if { $board_set != 0 } {
+ unset board;
+ }
+
+ return $found;
+}
+
+#
+# Source the testcase in TEST_FILE_NAME.
+#
+
+proc runtest { test_file_name } {
+ global prms_id
+ global bug_id
+ global test_result
+ global errcnt
+ global errorInfo
+ global tool
+
+ clone_output "Running $test_file_name ..."
+ set prms_id 0
+ set bug_id 0
+ set test_result ""
+
+ if [file exists $test_file_name] {
+ set timestart [timestamp];
+
+ if [info exists tool] {
+ if { [info procs "${tool}_init"] != "" } {
+ ${tool}_init $test_file_name;
+ }
+ }
+
+ if { [catch "uplevel #0 source $test_file_name"] == 1 } {
+ # We can't call `perror' here, it resets `errorInfo'
+ # before we want to look at it. Also remember that perror
+ # increments `errcnt'. If we do call perror we'd have to
+ # reset errcnt afterwards.
+ clone_output "ERROR: tcl error sourcing $test_file_name."
+ if [info exists errorInfo] {
+ clone_output "ERROR: $errorInfo"
+ unset errorInfo
+ }
+ }
+
+ if [info exists tool] {
+ if { [info procs "${tool}_finish"] != "" } {
+ ${tool}_finish;
+ }
+ }
+ set timeend [timestamp];
+ set timediff [expr $timeend - $timestart];
+ verbose -log "testcase $test_file_name completed in $timediff seconds" 4
+ } else {
+ # This should never happen, but maybe if the file got removed
+ # between the `find' above and here.
+ perror "$test_file_name does not exist."
+ # ??? This is a hack. We want to send a message to stderr and
+ # to the summary file (just like perror does), but we don't
+ # want the next testcase to get a spurious "unresolved" because
+ # errcnt != 0. Calling `clone_output' is also supposed to be a
+ # no-no (see the comments for clone_output).
+ set errcnt 0
+ }
+}
+
+#
+# Trap some signals so we know what's happening. These replace the previous
+# ones because we've now loaded the library stuff.
+#
+if ![exp_debug] {
+ foreach sig "{SIGTERM {terminated}} \
+ {SIGINT {interrupted by user}} \
+ {SIGQUIT {interrupted by user}} \
+ {SIGSEGV {segmentation violation}}" {
+ set signal [lindex $sig 0];
+ set str [lindex $sig 1];
+ trap "send_error \"got a \[trap -name\] signal, $str \\n\"; log_and_exit;" $signal;
+ verbose "setting trap for $signal to $str" 1
+ }
+ unset signal str sig;
+}
+
+#
+# Given a list of targets, process any iterative lists.
+#
+proc process_target_variants { target_list } {
+ set result {};
+ foreach x $target_list {
+ if [regexp "\\(" $x] {
+ regsub "^.*\\((\[^()\]*)\\)$" "$x" "\\1" variant_list;
+ regsub "\\(\[^(\]*$" "$x" "" x;
+ set list [process_target_variants $x];
+ set result {}
+ foreach x $list {
+ set result [concat $result [iterate_target_variants $x [split $variant_list ","]]];
+ }
+ } elseif [regexp "\{" $x] {
+ regsub "^.*\{(\[^\{\}\]*)\}$" "$x" "\\1" variant_list;
+ regsub "\{\[^\{\]*$" "$x" "" x;
+ set list [process_target_variants $x];
+ foreach x $list {
+ foreach i [split $variant_list ","] {
+ set name $x;
+ if { $i != "" } {
+ append name "/" $i;
+ }
+ lappend result $name;
+ }
+ }
+ } else {
+ lappend result "$x";
+ }
+ }
+ return $result;
+}
+
+proc iterate_target_variants { target variants } {
+ return [iterate_target_variants_two $target $target $variants];
+}
+
+#
+# Given a list of variants, produce the list of all possible combinations.
+#
+proc iterate_target_variants_two { orig_target target variants } {
+
+ if { [llength $variants] == 0 } {
+ return [list $target];
+ } else {
+ if { [llength $variants] > 1 } {
+ set result [iterate_target_variants_two $orig_target $target [lrange $variants 1 end]];
+ } else {
+ if { $target != $orig_target } {
+ set result [list $target];
+ } else {
+ set result {};
+ }
+ }
+ if { [lindex $variants 0] != "" } {
+ append target "/" [lindex $variants 0];
+ return [concat $result [iterate_target_variants_two $orig_target $target [lrange $variants 1 end]]];
+ } else {
+ return [concat $result $target];
+ }
+ }
+}
+
+setup_build_hook [get_local_hostname];
+
+if [info exists host_board] {
+ setup_host_hook $host_board;
+} else {
+ set hb [get_local_hostname];
+ if { $hb != "" } {
+ setup_host_hook $hb;
+ }
+}
+
+#
+# main test execution loop
+#
+
+if [info exists errorInfo] {
+ unset errorInfo
+}
+# make sure we have only single path delimiters
+regsub -all "\(\[^/\]\)//*" $srcdir "\\1/" srcdir
+
+if ![info exists target_list] {
+# Make sure there is at least one target machine. It's probably a Unix box,
+# but that's just a guess.
+ set target_list { "unix" }
+} else {
+ verbose "target list is $target_list"
+}
+
+#
+# Iterate through the list of targets.
+#
+global current_target;
+
+set target_list [process_target_variants $target_list];
+
+set target_count [llength $target_list]
+
+clone_output "Schedule of variations:"
+foreach current_target $target_list {
+ clone_output " $current_target"
+}
+clone_output ""
+
+
+foreach current_target $target_list {
+ verbose "target is $current_target";
+ set current_target_name $current_target;
+ set tlist [split $current_target /];
+ set current_target [lindex $tlist 0];
+ set board_variant_list [lrange $tlist 1 end];
+
+ # Set the counts for this target to 0.
+ reset_vars;
+ clone_output "Running target $current_target_name"
+
+ setup_target_hook $current_target_name $current_target;
+
+# If multiple passes requested, set them up. Otherwise prepare just one.
+# The format of `MULTIPASS' is a list of elements containing
+# "{ name var1=value1 ... }" where `name' is a generic name for the pass and
+# currently has no other meaning.
+
+ global env
+
+ if { [info exists MULTIPASS] } {
+ set multipass $MULTIPASS
+ }
+ if { $multipass == "" } {
+ set multipass { "" }
+ }
+
+# If PASS is specified, we want to run only the tests specified.
+# Its value should be a number or a list of numbers that specify
+# the passes that we want to run.
+ if [info exists PASS] {
+ set pass $PASS
+ } else {
+ set pass ""
+ }
+
+ if {$pass != ""} {
+ set passes [list]
+ foreach p $pass {
+ foreach multipass_elem $multipass {
+ set multipass_name [lindex $multipass_elem 0]
+ if {$p == $multipass_name} {
+ lappend passes $multipass_elem
+ break;
+ }
+ }
+ }
+ set multipass $passes
+ }
+
+ foreach pass $multipass {
+
+ # multipass_name is set for `record_test' to use (see framework.exp).
+ if { [lindex $pass 0] != "" } {
+ set multipass_name [lindex $pass 0]
+ clone_output "Running pass `$multipass_name' ..."
+ } else {
+ set multipass_name ""
+ }
+ set restore ""
+ foreach varval [lrange $pass 1 end] {
+ set tmp [string first "=" $varval]
+ set var [string range $varval 0 [expr $tmp - 1]]
+ # Save previous value.
+ if [info exists $var] {
+ lappend restore "$var [list [eval concat \$$var]]"
+ } else {
+ lappend restore "$var"
+ }
+ # Handle "CFLAGS=$CFLAGS foo".
+ # FIXME: Do we need to `catch' this?
+ eval set $var \[string range \"$varval\" [expr $tmp + 1] end\]
+ verbose "$var is now [eval concat \$$var]"
+ unset tmp var
+ }
+
+ # look for the top level testsuites. if $tool doesn't
+ # exist and there are no subdirectories in $srcdir, then
+ # we default to srcdir.
+ set test_top_dirs [lsort [getdirs -all ${srcdir} "${tool}*"]]
+ if { ${test_top_dirs} == "" } {
+ set test_top_dirs ${srcdir}
+ } else {
+ # JYG:
+ # DejaGNU's notion of test tree and test files is very
+ # general:
+ # given ${srcdir} and ${tool}, any subdirectory (at any
+ # level deep) with the "${tool}" prefix starts a test tree;
+ # given a test tree, any *.exp file underneath (at any
+ # level deep) is a test file.
+ #
+ # For test tree layouts with ${tool} prefix on
+ # both a parent and a child directory, we need to eliminate
+ # the child directory entry from test_top_dirs list.
+ # e.g. gdb.hp/gdb.base-hp/ would result in two entries
+ # in the list: gdb.hp, gdb.hp/gdb.base-hp.
+ # If the latter not eliminated, test files under
+ # gdb.hp/gdb.base-hp would be run twice (since test files
+ # are gathered from all sub-directories underneath a
+ # directory).
+ #
+ # Since ${tool} may be g++, etc. which could confuse
+ # regexp, we cannot do the simpler test:
+ # ...
+ # if [regexp "${srcdir}/.*${tool}.*/.*${tool}.*" ${dir}]
+ # ...
+ # instead, we rely on the fact that test_top_dirs is
+ # a sorted list of entries, and any entry that contains
+ # the previous valid test top dir entry in its own pathname
+ # must be excluded.
+
+ set temp_top_dirs ""
+ set prev_dir ""
+ foreach dir "${test_top_dirs}" {
+ if { [string length ${prev_dir}] == 0 ||
+ [string first "${prev_dir}/" ${dir}] == -1} {
+ # the first top dir entry, or an entry that
+ # does not share the previous entry's entire
+ # pathname, record it as a valid top dir entry.
+ #
+ lappend temp_top_dirs ${dir}
+ set prev_dir ${dir}
+ }
+ }
+ set test_top_dirs ${temp_top_dirs}
+ }
+ verbose "Top level testsuite dirs are ${test_top_dirs}" 2
+ set testlist "";
+ if [info exists all_runtests] {
+ foreach x [array names all_runtests] {
+ verbose "trying to glob ${srcdir}/${x}" 2
+ set s [glob -nocomplain ${srcdir}/$x];
+ if { $s != "" } {
+ set testlist [concat $testlist $s];
+ }
+ }
+ }
+ #
+ # If we have a list of tests, run all of them.
+ #
+ if { $testlist != "" } {
+ foreach test_name $testlist {
+ if { ${ignoretests} != "" } {
+ if { 0 <= [lsearch ${ignoretests} [file tail ${test_name}]]} {
+ continue
+ }
+ }
+
+ # set subdir to the tail of the dirname after $srcdir,
+ # for the driver files that want it. XXX this is silly.
+ # drivers should get a single var, not "$srcdir/$subdir"
+ set subdir [file dirname $test_name]
+ set p [expr [string length $srcdir]-1]
+ while {0 < $p && [string index $srcdir $p] == "/"} {
+ incr p -1
+ }
+ if {[string range $subdir 0 $p] == $srcdir} {
+ set subdir [string range $subdir [expr $p+1] end];
+ regsub "^/" $subdir "" subdir
+ }
+
+ # XXX not the right thing to do.
+ set runtests [list [file tail $test_name] ""]
+
+ runtest $test_name;
+ }
+ } else {
+ #
+ # Go digging for tests.
+ #
+ foreach dir "${test_top_dirs}" {
+ if { ${dir} != ${srcdir} } {
+ # Ignore this directory if is a directory to be
+ # ignored.
+ if {[info exists ignoredirs] && $ignoredirs != ""} {
+ set found 0
+ foreach directory $ignoredirs {
+ if [string match "*${directory}*" $dir] {
+ set found 1
+ break
+ }
+ }
+ if {$found} {
+ continue
+ }
+ }
+
+ # Run the test if dir_to_run was specified as a
+ # value (for example in MULTIPASS) and the test
+ # directory matches that directory.
+ if {[info exists dir_to_run] && $dir_to_run != ""} {
+ # JYG: dir_to_run might be a space delimited list
+ # of directories. Look for match on each item.
+ set found 0
+ foreach directory $dir_to_run {
+ if [string match "*${directory}*" $dir] {
+ set found 1
+ break
+ }
+ }
+ if {!$found} {
+ continue
+ }
+ }
+
+ # Run the test if cmdline_dir_to_run was specified
+ # by the user using --directory and the test
+ # directory matches that directory
+ if {[info exists cmdline_dir_to_run] \
+ && $cmdline_dir_to_run != ""} {
+ # JYG: cmdline_dir_to_run might be a space delimited
+ # list of directories. Look for match on each item.
+ set found 0
+ foreach directory $cmdline_dir_to_run {
+ if [string match "*${directory}*" $dir] {
+ set found 1
+ break
+ }
+ }
+ if {!$found} {
+ continue
+ }
+ }
+
+ foreach test_name [lsort [find ${dir} *.exp]] {
+ if { ${test_name} == "" } {
+ continue
+ }
+ # Ignore this one if asked to.
+ if { ${ignoretests} != "" } {
+ if { 0 <= [lsearch ${ignoretests} [file tail ${test_name}]]} {
+ continue
+ }
+ }
+
+ # Get the path after the $srcdir so we know
+ # the subdir we're in.
+ set subdir [file dirname $test_name]
+ # We used to do
+ # regsub $srcdir [file dirname $test_name] "" subdir
+ # but what if [file dirname $test_name] contains regexp
+ # characters? We lose. Instead...
+ set first [string first $srcdir $subdir]
+ if { $first >= 0 } {
+ set first [expr $first + [string length $srcdir]];
+ set subdir [string range $subdir $first end];
+ regsub "^/" "$subdir" "" subdir;
+ }
+ if { "$srcdir" == "$subdir" || "$srcdir" == "$subdir/" } {
+ set subdir ""
+ }
+ # Check to see if the range of tests is limited,
+ # set `runtests' to a list of two elements: the script name
+ # and any arguments ("" if none).
+ if [info exists all_runtests] {
+ verbose "searching for $test_name in [array names all_runtests]"
+ if { 0 > [lsearch [array names all_runtests] [file tail $test_name]]} {
+ if { 0 > [lsearch [array names all_runtests] $test_name] } {
+ continue
+ }
+ }
+ set runtests [list [file tail $test_name] $all_runtests([file tail $test_name])]
+ } else {
+ set runtests [list [file tail $test_name] ""]
+ }
+ runtest $test_name;
+ }
+ }
+ }
+ # Restore the variables set by this pass.
+ foreach varval $restore {
+ if { [llength $varval] > 1 } {
+ verbose "Restoring [lindex $varval 0] to [lindex $varval 1]" 4;
+ set [lindex $varval 0] [lindex $varval 1];
+ } else {
+ verbose "Restoring [lindex $varval 0] to `unset'" 4;
+ unset [lindex $varval 0];
+ }
+ }
+ }
+ }
+ cleanup_target_hook $current_target;
+ if { $target_count > 1 } {
+ log_summary;
+ }
+}
+
+log_and_exit;