1test -n "$_bsda_test_" && return 0 2readonly _bsda_test_=1 3 4# 5# Print failure and exit. 6# 7# @param 1 8# The file name 9# @param 2 10# This should be $LINENO 11# @param 3 12# The error number 13# 14bsda:test:err() { 15 echo "$1 ERROR: $3" >&2 16 echo "$1:$2: $(/usr/bin/head -n$2 "$1" | /usr/bin/tail -n1)" >&2 17 exit $3 18} 19 20# 21# Check a string against a glob pattern. 22# 23# @param 1 24# The glob pattern to match 25# @param 2 26# The string to check 27# @retval 0 28# The string matches the pattern 29# @retval 1 30# The string does not match the pattern 31# 32bsda:test:gmatch() { 33 case "$2" in 34 $1) 35 return 0 36 ;; 37 esac 38 return 1 39} 40 41# 42# Each line is matched against a set of glob patterns. 43# 44# The return value depends on a relationship criteria that specifies 45# how lines from the string should relate to glob patterns. The relationship 46# is a tuple of two variables: `<lines>:<patterns>` 47# 48# | Relationship | Meaning | 49# |--------------|------------------------------------------------------| 50# | all:* | All the lines must be matched by a pattern | 51# | any:* | At least one line must be matched by a pattern | 52# | *:all | All the patterns must match at least one line | 53# | *:any | Any of the patterns can be matched | 54# | *:once | All the patterns must be matched by exactly one line | 55# 56# @param 1 57# The string to match against the patterns 58# @param 2 59# The relationship between string lines and patterns 60# @param @ 61# The glob patterns to match against 62# @retval 0 63# The relationship is satisfied 64# @retval 1 65# The relationship is not satisfied 66# @retval 13 67# The string line part of the relationship is unknown 68# @retval 23 69# The pattern part of the relationship is unknown 70# 71bsda:test:xmatch() { 72 local IFS rel str i 73 IFS=$'\n' 74 str="$1" 75 rel="$2" 76 shift 2 77 i=0 78 while [ $i -lt $# ]; do 79 local count_$i 80 i=$((i + 1)) 81 done 82 case "$rel" in 83 all:any) 84 for str in $str; do 85 bsda:test:xmatch_any "$str" "$@" || return $? 86 done 87 return 0 88 ;; 89 any:any) 90 for str in $str; do 91 bsda:test:xmatch_any "$str" "$@" && return 0 92 done 93 return 1 94 ;; 95 all:*) 96 for str in $str; do 97 bsda:test:xmatch_count "$str" "$@" || return $? 98 done 99 ;; 100 any:*) 101 for str in $str; do 102 bsda:test:xmatch_count "$str" "$@" 103 done 104 ;; 105 *) 106 # Unsupported relation 107 return 13 108 ;; 109 esac 110 # Check counts 111 case "$rel" in 112 *:all) 113 i=0 114 while [ $i -lt $# ]; do 115 # Bail out if a pattern was not matched 116 if [ $((count_$i)) -eq 0 ]; then 117 return 1 118 fi 119 i=$((i + 1)) 120 done 121 return 0 122 ;; 123 *:once) 124 i=0 125 while [ $i -lt $# ]; do 126 # Bail out if a pattern was not matched once 127 if [ $((count_$i)) -ne 1 ]; then 128 return 1 129 fi 130 i=$((i + 1)) 131 done 132 return 0 133 ;; 134 esac 135 # Unsupported relation 136 return 23 137} 138 139# 140# Helper function to bsda:test:xmatch(). 141# 142# Checks the given line against the given patterns. 143# 144# @param 1 145# The string line to match against patterns 146# @param @ 147# The patterns to match against 148# @retval 0 149# A pattern match was encountered 150# @retval 1 151# None of the patterns are a match 152# 153bsda:test:xmatch_any() { 154 local line pattern 155 line="$1" 156 pattern="$2" 157 # Terminate recursion, when running out of patterns to mach 158 if ! shift 2; then 159 return 1 160 fi 161 # Try the current pattern 162 case "$line" in 163 $pattern) 164 return 0 165 ;; 166 esac 167 # Try next pattern 168 bsda:test:xmatch_any "$line" "$@" 169} 170 171# 172# Helper function to bsda:test:xmatch(). 173# 174# Counts the matches of each pattern. 175# 176# @param [count_0..count_$#) 177# Store the number of matches for each pattern 178# @param 1 179# The string line to match against patterns 180# @param @ 181# The patterns to match against 182# @retval 0 183# At least one pattern match was encountered 184# @retval 1 185# None of the patterns are a match 186# 187bsda:test:xmatch_count() { 188 local line pattern ret 189 line="$1" 190 pattern="$2" 191 # Terminate recursion, when running out of patterns to mach 192 if ! shift 2; then 193 return 1 194 fi 195 # Recurse to next pattern 196 bsda:test:xmatch_count "$line" "$@" 197 ret=$? 198 # Try the current pattern 199 case "$line" in 200 $pattern) 201 : $((count_$# += 1)) 202 return 0 203 ;; 204 esac 205 return $ret 206} 207 208# 209# Return the function type of the given function. 210# 211# | Type | Description | 212# |------------|---------------------------------------------------| 213# | alias | The given function is a shell alias | 214# | builtin | The given function is a shell builtin | 215# | function | The given function is a shell function | 216# | executable | The given function names a file system executable | 217# | none | The given function cannot be found | 218# | nil | The `type` builtin returned an unsupported string | 219# 220# Note that `bash` only supports aliases in interactive mode. 221# 222# @param &1 223# The variable to receive the function type 224# @param 2 225# The function to determine the type of 226# 227bsda:test:type() { 228 setvar "$1" "$( 229 case "$(type "$2" 2>&1 )" in 230 "$2 is an alias "*|"$2 is aliased "*) 231 echo alias 232 ;; 233 "$2 is a shell builtin") 234 echo builtin 235 ;; 236 "$2 is a shell function"|"$2 is a function"*) 237 echo function 238 ;; 239 "$2 is /"*) 240 echo executable 241 ;; 242 *"$2: not found") 243 echo none 244 ;; 245 *) 246 echo nil 247 ;; 248 esac 249 )" 250} 251 252# 253# Check if the given function is an alias. 254# 255# @param 1 256# The name of the function 257# @return 258# Returns 0 for yes and 1 for no 259# 260bsda:test:isAlias() { 261 local type 262 bsda:test:type type "$1" 263 test "$type" = alias 264} 265 266# 267# Check if the given function is a builtin. 268# 269# @param 1 270# The name of the function 271# @return 272# Returns 0 for yes and 1 for no 273# 274bsda:test:isBuiltin() { 275 local type 276 bsda:test:type type "$1" 277 test "$type" = builtin 278} 279 280# 281# Check if the given function is a shell function. 282# 283# @param 1 284# The name of the function 285# @return 286# Returns 0 for yes and 1 for no 287# 288bsda:test:isFunction() { 289 local type 290 bsda:test:type type "$1" 291 test "$type" = function 292} 293 294# 295# Check if the given function is a file system executable. 296# 297# @param 1 298# The name of the function 299# @return 300# Returns 0 for yes and 1 for no 301# 302bsda:test:isExecutable() { 303 local type 304 bsda:test:type type "$1" 305 test "$type" = executable 306} 307 308# 309# Check if the given function cannot be found. 310# 311# @param 1 312# The name of the function 313# @return 314# Returns 0 for yes and 1 for no 315# 316bsda:test:isNone() { 317 local type 318 bsda:test:type type "$1" 319 test "$type" = none 320} 321 322# 323# Check if the given variable exists. 324# 325# Note that this returns true for all defined variables, even empty 326# ones. 327# 328# @param 1 329# The name of the variable 330# @retval 0 331# The variable has been defined 332# @retval 1 333# The variable does not exist 334# 335bsda:test:isSet() { 336 eval "test -n \"\${$1+x}\"" 337} 338