aboutsummaryrefslogtreecommitdiff
path: root/lib/utils.exp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/utils.exp')
-rw-r--r--lib/utils.exp441
1 files changed, 441 insertions, 0 deletions
diff --git a/lib/utils.exp b/lib/utils.exp
new file mode 100644
index 0000000..565f18e
--- /dev/null
+++ b/lib/utils.exp
@@ -0,0 +1,441 @@
+# 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)
+
+#
+# Most of the procedures found here mimic their unix counter-part.
+# This file is sourced by runtest.exp, so they are usable by any test case.
+#
+
+#
+# Gets the directories in a directory
+# args: the first is the dir to look in, the next
+# is the pattern to match. It
+# defaults to *. Patterns are csh style
+# globbing rules
+# returns: a list of dirs or NULL
+#
+proc getdirs { args } {
+ if { [lindex $args 0] == "-all" } {
+ set alldirs 1
+ set args [lrange $args 1 end]
+ } else {
+ set alldirs 0
+ }
+
+ set path [lindex $args 0]
+ if { [llength $args] > 1} {
+ set pattern [lindex $args 1]
+ } else {
+ set pattern "*"
+ }
+ verbose "Looking in ${path} for directories that match \"${pattern}\"" 3
+ catch "glob ${path}/${pattern}" tmp
+ if { ${tmp} != "" } {
+ foreach i ${tmp} {
+ if [file isdirectory $i] {
+ switch -- "[file tail $i]" {
+ "testsuite" -
+ "config" -
+ "lib" -
+ "CVS" -
+ "RCS" -
+ "SCCS" {
+ verbose "Ignoring directory [file tail $i]" 3
+ continue
+ }
+ default {
+ if [file readable $i] {
+ verbose "Found directory [file tail $i]" 3
+ lappend dirs $i
+ if { $alldirs } {
+ eval lappend dirs [getdirs -all $i $pattern]
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ perror "$tmp"
+ return ""
+ }
+
+ if ![info exists dirs] {
+ return ""
+ } else {
+ return $dirs
+ }
+}
+
+#
+# Finds all the files recursively
+# rootdir - this is the directory to start the search
+# from. This is and all subdirectories are search for
+# filenames. Directory names are not included in the
+# list, but the filenames have path information.
+# pattern - this is the pattern to match. Patterns are csh style
+# globbing rules.
+# returns: a list or a NULL.
+#
+proc find { rootdir pattern } {
+ # first find all the directories
+ set dirs "$rootdir "
+ while 1 {
+ set tmp $rootdir
+ set rootdir ""
+ if [string match "" $tmp] {
+ break
+ }
+ foreach i $tmp {
+ set j [getdirs $i]
+ if ![string match "" $j] {
+ append dirs "$j "
+ set rootdir $j
+ unset j
+ } else {
+ set rootdir ""
+ }
+ }
+ set tmp ""
+ }
+
+ # find all the files that match the pattern
+ foreach i $dirs {
+ verbose "Looking in $i" 3
+ set tmp [glob -nocomplain $i/$pattern]
+ if { [llength $tmp] != 0 } {
+ foreach j $tmp {
+ if ![file isdirectory $j] {
+ lappend files $j
+ verbose "Adding $j to file list" 3
+ }
+ }
+ }
+ }
+
+ if ![info exists files] {
+ lappend files ""
+ }
+ return $files
+}
+
+#
+# Search the path for a file. This is basically a version
+# of the BSD-unix which utility. This procedure depends on
+# the shell environment variable $PATH. It returns 0 if $PATH
+# does not exist or the binary is not in the path. If the
+# binary is in the path, it returns the full path to the binary.
+#
+proc which { file } {
+ global env
+
+ # strip off any extraneous arguments (like flags to the compiler)
+ set file [lindex $file 0]
+
+ # if it exists then the path must be OK
+ # ??? What if $file has no path and "." isn't in $PATH?
+ if [file exists $file] {
+ return $file
+ }
+ if [info exists env(PATH)] {
+ set path [split $env(PATH) ":"]
+ } else {
+ return 0
+ }
+
+ foreach i $path {
+ verbose "Checking against $i" 3
+ if [file exists $i/$file] {
+ if [file executable $i/$file] {
+ return $i/$file
+ } else {
+ warning "$i/$file exists but is not an executable"
+ }
+ }
+ }
+ # not in path
+ return 0
+}
+
+#
+# Looks for a string in a file.
+# return:list of lines that matched or NULL if none match.
+# args: first arg is the filename,
+# second is the pattern,
+# third are any options.
+# Options: line - puts line numbers of match in list
+#
+proc grep { args } {
+
+ set file [lindex $args 0]
+ set pattern [lindex $args 1]
+
+ verbose "Grepping $file for the pattern \"$pattern\"" 3
+
+ set argc [llength $args]
+ if { $argc > 2 } {
+ for { set i 2 } { $i < $argc } { incr i } {
+ append options [lindex $args $i]
+ append options " "
+ }
+ } else {
+ set options ""
+ }
+
+ set i 0
+ set fd [open $file r]
+ while { [gets $fd cur_line]>=0 } {
+ incr i
+ if [regexp -- "$pattern" $cur_line match] {
+ if ![string match "" $options] {
+ foreach opt $options {
+ case $opt in {
+ "line" {
+ lappend grep_out [concat $i $match]
+ }
+ }
+ }
+ } else {
+ lappend grep_out $match
+ }
+ }
+ }
+ close $fd
+ unset fd
+ unset i
+ if ![info exists grep_out] {
+ set grep_out ""
+ }
+ return $grep_out
+}
+
+#
+# Remove elements based on patterns. elements are delimited by spaces.
+# pattern is the pattern to look for using glob style matching
+# list is the list to check against
+# returns the new list
+#
+proc prune { list pattern } {
+ set tmp {}
+ foreach i $list {
+ verbose "Checking pattern \"$pattern\" against $i" 3
+ if ![string match $pattern $i] {
+ lappend tmp $i
+ } else {
+ verbose "Removing element $i from list" 3
+ }
+ }
+ return $tmp
+}
+
+#
+# Attempt to kill a process that you started on the local machine.
+#
+proc slay { name } {
+ set in [open [concat "|ps"] r]
+ while {[gets $in line]>-1} {
+ if ![string match "*expect*slay*" $line] {
+ if [string match "*$name*" $line] {
+ set pid [lindex $line 0]
+ catch "exec kill -9 $pid]"
+ verbose "Killing $name, pid = $pid\n"
+ }
+ }
+ }
+ close $in
+}
+
+#
+# Convert a relative path to an absolute one on the local machine.
+#
+proc absolute { path } {
+ if [string match "." $path] {
+ return [pwd]
+ }
+
+ set basedir [pwd]
+ cd $path
+ set path [pwd]
+ cd $basedir
+ return $path
+}
+
+#
+# Source a file and trap any real errors. This ignores extraneous
+# output. returns a 1 if there was an error, otherwise it returns 0.
+#
+proc psource { file } {
+ global errorInfo
+ global errorCode
+
+ unset errorInfo
+ if [file exists $file] {
+ catch "source $file"
+ if [info exists errorInfo] {
+ send_error "ERROR: errors in $file\n"
+ send_error "$errorInfo"
+ return 1
+ }
+ }
+ return 0
+}
+
+#
+# Check if a testcase should be run or not
+#
+# RUNTESTS is a copy of global `runtests'.
+#
+# This proc hides the details of global `runtests' from the test scripts, and
+# implements uniform handling of "script arguments" where those arguments are
+# file names (ie: the "foo" in make check RUNTESTFLAGS="bar.exp=foo").
+# "glob" style expressions are supported as well as multiple files (with
+# spaces between them).
+# Eg: RUNTESTFLAGS="bar.exp=foo1.c foo2.c foo3*.c bar*.c"
+#
+proc runtest_file_p { runtests testcase } {
+ if [string length [lindex $runtests 1]] {
+ set basename [file tail $testcase]
+ foreach ptn [lindex $runtests 1] {
+ if [string match $ptn $basename] {
+ return 1
+ }
+ if [string match $ptn $testcase] {
+ return 1
+ }
+ }
+ return 0
+ }
+ return 1
+}
+
+#
+# Delete various system verbosities from TEXT on SYSTEM
+#
+# An example is:
+# ld.so: warning: /usr/lib/libc.so.1.8.1 has older revision than expected 9
+#
+# SYSTEM is typical $target_triplet or $host_triplet.
+#
+
+#
+# Compares two files line-by-line
+# returns 1 it the files match,
+# returns 0 if there was a file error,
+# returns -1 if they didn't match.
+#
+proc diff { file_1 file_2 } {
+ set eof -1
+ set differences 0
+
+ if [file exists ${file_1}] {
+ set file_a [open ${file_1} r]
+ } else {
+ warning "${file_1} doesn't exist"
+ return 0
+ }
+
+ if [file exists ${file_2}] {
+ set file_b [open ${file_2} r]
+ } else {
+ warning "${file_2} doesn't exist"
+ return 0
+ }
+
+ verbose "# Diff'ing: ${file_1} ${file_2}\n" 1
+
+ set list_a ""
+ while { [gets ${file_a} line] != ${eof} } {
+ if [regexp "^#.*$" ${line}] {
+ continue
+ } else {
+ lappend list_a ${line}
+ }
+ }
+ close ${file_a}
+
+ set list_b ""
+ while { [gets ${file_b} line] != ${eof} } {
+ if [regexp "^#.*$" ${line}] {
+ continue
+ } else {
+ lappend list_b ${line}
+ }
+ }
+ close ${file_b}
+ for { set i 0 } { $i < [llength $list_a] } { incr i } {
+ set line_a [lindex ${list_a} ${i}]
+ set line_b [lindex ${list_b} ${i}]
+
+# verbose "\t${file_1}: ${i}: ${line_a}\n" 3
+# verbose "\t${file_2}: ${i}: ${line_b}\n" 3
+ if [string compare ${line_a} ${line_b}] {
+ verbose "line #${i}\n" 2
+ verbose "\< ${line_a}\n" 2
+ verbose "\> ${line_b}\n" 2
+
+ send_log "line #${i}\n"
+ send_log "\< ${line_a}\n"
+ send_log "\> ${line_b}\n"
+
+ set differences -1
+ }
+ }
+
+ if { $differences == -1 || [llength ${list_a}] != [llength ${list_b}] } {
+ verbose "Files not the same" 2
+ set differences -1
+ } else {
+ verbose "Files are the same" 2
+ set differences 1
+ }
+ return ${differences}
+}
+
+#
+# Set an environment variable
+#
+proc setenv { var val } {
+ global env
+
+ set env($var) $val
+}
+
+#
+# Unset an environment variable
+#
+proc unsetenv { var } {
+ global env
+ unset env($var)
+}
+
+#
+# Get a value from an environment variable
+#
+proc getenv { var } {
+ global env
+
+ if [info exists env($var)] {
+ return $env($var)
+ } else {
+ return ""
+ }
+}
+