1__require_tool_version_compare () 2{ 3 ( 4 # Locally ignore failures, otherwise we'll exit whenever $1 and $2 5 # are not equal! 6 set +e 7 8awk_strverscmp=' 9 # Use only awk features that work with 7th edition Unix awk (1978). 10 # My, what an old awk you have, Mr. Solaris! 11 END { 12 while (length(v1) || length(v2)) { 13 # Set d1 to be the next thing to compare from v1, and likewise for d2. 14 # Normally this is a single character, but if v1 and v2 contain digits, 15 # compare them as integers and fractions as strverscmp does. 16 if (v1 ~ /^[0-9]/ && v2 ~ /^[0-9]/) { 17 # Split v1 and v2 into their leading digit string components d1 and d2, 18 # and advance v1 and v2 past the leading digit strings. 19 for (len1 = 1; substr(v1, len1 + 1) ~ /^[0-9]/; len1++) continue 20 for (len2 = 1; substr(v2, len2 + 1) ~ /^[0-9]/; len2++) continue 21 d1 = substr(v1, 1, len1); v1 = substr(v1, len1 + 1) 22 d2 = substr(v2, 1, len2); v2 = substr(v2, len2 + 1) 23 if (d1 ~ /^0/) { 24 if (d2 ~ /^0/) { 25 # Compare two fractions. 26 while (d1 ~ /^0/ && d2 ~ /^0/) { 27 d1 = substr(d1, 2); len1-- 28 d2 = substr(d2, 2); len2-- 29 } 30 if (len1 != len2 && ! (len1 && len2 && substr(d1, 1, 1) == substr(d2, 1, 1))) { 31 # The two components differ in length, and the common prefix 32 # contains only leading zeros. Consider the longer to be less. 33 d1 = -len1 34 d2 = -len2 35 } else { 36 # Otherwise, compare as strings. 37 d1 = "x" d1 38 d2 = "x" d2 39 } 40 } else { 41 # A fraction is less than an integer. 42 exit 1 43 } 44 } else { 45 if (d2 ~ /^0/) { 46 # An integer is greater than a fraction. 47 exit 2 48 } else { 49 # Compare two integers. 50 d1 += 0 51 d2 += 0 52 } 53 } 54 } else { 55 # The normal case, without worrying about digits. 56 if (v1 == "") d1 = v1; else { d1 = substr(v1, 1, 1); v1 = substr(v1,2) } 57 if (v2 == "") d2 = v2; else { d2 = substr(v2, 1, 1); v2 = substr(v2,2) } 58 } 59 if (d1 < d2) exit 1 60 if (d1 > d2) exit 2 61 } 62 } 63' 64 awk "$awk_strverscmp" v1="$1" v2="$2" /dev/null 65 case $? in 66 1) echo '<';; 67 0) echo '=';; 68 2) echo '>';; 69 esac 70 ) 71} 72 73 74__require_tool_fatal () 75{ 76 echo $@ >/dev/stderr 77 return 1 78} 79 80# Usage: require_tool program version 81# Returns: 0 if $1 version if greater equals than $2, 1 otherwise. 82# In case of error, message is written on error output. 83# 84# Example: require_tool gcc 4.6 85# Use GCC environment variable if defined instead of lookup for the tool 86# in the environment. 87require_tool () 88{ 89 envvar_name=$(echo $1 | tr '[:lower:]' '[:upper:]') 90 tool=$(printenv $envvar_name || echo $1) 91 local version=$($tool --version 2>/dev/null| \ 92 sed -n 's/.*[^0-9.]\([0-9]*\.[0-9.]*\).*/\1/p;q') 93 if test x"$version" = x ; then 94 echo "$tool is required" >/dev/stderr 95 return 1 96 fi 97 case $(__require_tool_version_compare "$2" "$version") in 98 '>') 99 echo "$1 $2 or better is required: this is $tool $version" >/dev/stderr 100 return 1 101 ;; 102 esac 103} 104 105usage() { 106 cat <<EOF 107NAME 108 require_tool.sh - Ensure version of a tool is greater than the one expected 109 110SYNOPSYS 111 require_tool.sh [ -h ] 112 [ --help ] 113 [ TOOL MIN_VERSION ] 114 115DESCRIPTION 116 TOOL is the name or path of the program to check. If the name is specified, its 117 path is deduced from PATH environment variable. If environment variable TOOL 118 (in upper-case characters) is defined, considers its value as path to the tool. 119 120 MIN_VERSION is a string representing the minimum required version. 121 122BEHAVIOR 123 * locate path to the program. 124 * execute $ TOOL_PATH --version 125 * extract version from standard output. 126 * compare this version to the expected one. 127 128OPTIONS 129 -h --help 130 Display this message and exit 0 131 132ERRORS 133 if program is not found or its version is prior to expected version, 134 a message is written to error output. 135 136EXIT VALUE 137 returns 0 if program version if greater equals than expected version, 138 returns 1 otherwise. 139 140EXAMPLE 141 $ require_tool.sh emacs 23 142 $ CC=g++ require_tool.sh cc 4.6 143 $ require_tool.sh zsh 4.5 144 145EOF 146} 147 148for arg in $@; do 149 case $arg in 150 -h|--help) 151 usage 152 exit 0 153 ;; 154 esac 155done 156if [ $# -gt 2 ] ; then 157 echo "ERROR: expecting 2 parameters. Please see option --help" 158 exit 1 159fi 160 161require_tool $@ 162