1 # ============================================================================ 2 # Copyright (c) 2011-2012 University of Pennsylvania 3 # Copyright (c) 2013-2016 Andreas Schuh 6 # See COPYING file for license information or visit 7 # https://cmake-basis.github.io/download.html#license 8 # ============================================================================ 10 ############################################################################## 12 # @brief Core functions for Bash development. 14 # This is the core module of the BASIS utilities for Bash. It implements 15 # fundamental functions for the development in Bash. Therefore, this module 16 # has to be kept independent of any other modules and shall only make use 17 # of Bash builtin's and basic commands. 18 ############################################################################## 20 [
"${_BASIS_CORE_INCLUDED}" ==
'true' ] || {
21 _BASIS_CORE_INCLUDED=
'true' 24 .
"`cd -P -- \`dirname -- "${BASH_SOURCE}
"\` && pwd`/config.sh" || exit 1
27 ## @addtogroup BasisBashUtilities 31 # ============================================================================ 33 # ============================================================================ 35 # ---------------------------------------------------------------------------- 36 ## @brief Import Bash module. 38 # This function can be used to import, i.e., source, a named module, where the 39 # module is searched for in the directories specified by the @c BASHPATH 40 # (environment) variable. Modules can be prepended by the names of the 41 # subdirectories they are located in relative to a directory listed in the 42 # @c BASHPATH, where dots (.) can be used instead of slashes to separate the 43 # parts of the relative module path. A <tt>.sh</tt> file name extension of the 44 # modules is appended to the module name when looking for a matching Bash 45 # module file. It must not be included in the \p module name to avoid 46 # confusion with the dot used as path / submodule separator. The module name 47 # "utils.sh" thus translates to the file path "utils/sh.sh"! 51 # import sbia.basis.core 52 # import -o optional.module 53 # if [ $? -eq 0 ]; then 54 # echo "Module optional.module imported successfully" 56 # echo "Module optional.module not found" 60 # @note The directories listed in the @c BASHPATH must be absolute paths 61 # starting with a forward slash (/). 63 # @param [in] options Option flags. The only possible option is -o. If this 64 # option is given before the module name, the function 65 # returns with return value 1 on error. Otherwise, it 66 # calls the exit function with this exit code. 67 # It can therefore be used for optional modules, which 68 # do not necessarily need to be imported. 69 # @param [in] module Name of the module to import (excl. .sh file name extension). 71 # @returns Only on success or if the -o option is given. Otherwise it calls 72 # the exit function if an error occurs. 74 # @retval 0 if the module was loaded successfully. 75 # @retval 1 on error if -o option is given. 78 if [[ -z
"${BASHPATH}" ]]; then
79 echo
"import: BASHPATH not specified!" 1>&2
82 local exitonerror=
'true' 83 while [ $# -gt 0 ];
do 85 -o) exitonerror=
'false'; ;;
90 local module=
"${1//.//}" # replace dots (.) by forward slashes (/)
91 if [[ -z "${module}
" ]]; then 92 echo "import: missing module name argument!
" 1>&2 95 if [[ $# -gt 1 ]]; then 96 echo "import: too many arguments!
" 1>&2 99 [[ ${module: -3} == '.sh' ]] || module="${module}.sh
" 100 local path="${BASHPATH}:
" # ATTENTION: Trailing ':' required to terminate while loop! 102 while [[ -n "${path}
" ]]; do 104 if [[ "${root:0:1}
" == '/' && -f "${root}/${module}
" ]]; then 105 . "${root}/${module}
" 110 if [[ ${exitonerror} == 'true' ]]; then 111 echo "import: module
'$1' not found!
" 1>&2 117 # ============================================================================ 119 # ============================================================================ 121 # ---------------------------------------------------------------------------- 122 ## @brief This function implements a more portable way to do pattern matching. 124 # Unfortunately, there are significant differences in the way patterns have 125 # to be matched when using different shells. This function considers which 126 # shell is used (at the moment only BASH), and uses the appropriate syntax 127 # for the pattern matching. 129 # @param [in] value The string to match against pattern. 130 # @param [in] pattern The pattern to match. 132 # @returns Whether the given string matches the given pattern. 134 # @retval 0 On match. 135 # @retval 1 Otherwise. 138 [ $# -eq 2 ] || return 1 143 if [ -z "${value}
" ]; then 145 elif [ -z "${pattern}
" ]; then 148 if [ ${BASH_VERSION_MAJOR} -gt 2 ]; then 149 # GNU bash, version 3.00.15(1)-release (x86_64-redhat-linux-gnu) 150 # throws an error when a regular expression with groups 151 # such as in '^(a|b|c)' is used. Here, quotes are required. 152 if [ ${BASH_VERSION_MAJOR} -eq 3 -a ${BASH_VERSION_MINOR} -eq 0 ]; then 153 [[ "${value}
" =~ "${pattern}
" ]] 154 # GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu) 155 # works with either quotes or not. However, on Mac OS Snow Leopard, 156 # GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin10.0) 157 # requires that no quotes are used. The quotes are otherwise 158 # considered to be part of the pattern. 160 [[ "${value}
" =~ ${pattern} ]] 163 echo "${value}
" | egrep -q "${pattern}
" 168 # ============================================================================ 170 # ============================================================================ 172 # ---------------------------------------------------------------------------- 173 ## @brief Assign variable one scope above the caller. 175 # This function can be used inside functions to return values by assigning 176 # them to a variable in the scope of the caller. 178 # @note For assigning multiple variables, use upvars(). Do NOT use multiple 179 # upvar() calls, since one upvar() call might reassign a variable to 180 # be used by another upvar() call. 186 # local "$1
" && upvar $1 "Hello, World!
" 193 # @param [in] var Variable name to assign value to 194 # @param [in] values Value(s) to assign. If multiple values, an array is 195 # assigned, otherwise a single value is assigned. 199 # @retval 0 On success. 200 # @retval 1 On failure. 203 # @sa http://fvue.nl/wiki/Bash:_Passing_variables_by_reference 206 if unset -v "$1
"; then # Unset & validate varname 207 if (( $# == 2 )); then 208 eval $1=\"\$2\" # Return single value 210 eval $1=\(\"\${@:2}\"\) # Return array 215 # ---------------------------------------------------------------------------- 216 ## @brief Assign variables one scope above the caller. 219 # local varname [varname ...] && 220 # upvars [-v varname value] | [-aN varname [value ...]] ... 223 # - -aN Assign next N values to varname as array 224 # - -v Assign single value to varname# 226 # @retval 0 On success. 227 # @retval 1 On failure. 229 # @sa http://fvue.nl/wiki/Bash:_Passing_variables_by_reference 233 echo "${FUNCNAME[0]}: usage: ${FUNCNAME[0]} [-v varname
"\ 234 "value] | [-aN varname [value ...]] ...
" 1>&2 241 [[ ${1#-a} ]] || { echo "bash: ${FUNCNAME[0]}: \`$1
': missing"\ 242 "number specifier" 1>&2; return 1; } 243 printf %d "${1#-a}" &> /dev/null || { echo "bash:"\ 244 "${FUNCNAME[0]}: \`$1': invalid number specifier
" 1>&2 246 # Assign array of -aN elements 247 [[ "$2
" ]] && unset -v "$2
" && eval $2=\(\"\${@:3:${1#-a}}\"\) && 248 shift $((${1#-a} + 2)) || { echo "bash: ${FUNCNAME[0]}:
"\ 249 "\`$1${2+ }$2
': missing argument(s)" 1>&2; return 1; } 252 # Assign single value 253 [[ "$2" ]] && unset -v "$2" && eval $2=\"\$3\" && 254 shift 3 || { echo "bash: ${FUNCNAME[0]}: $1: missing"\ 255 "argument(s)" 1>&2; return 1; } 258 Usage: local varname [varname ...] && 259 ${FUNCNAME[0]} [-v varname value] | [-aN varname [value ...]] ... 261 -aN VARNAME [value ...] assign next N values to varname as array 262 -v VARNAME value assign single value to varname 263 --help display this help and exit 264 --version output version information and exit" 267 ${FUNCNAME[0]}-0.9.dev 268 Copyright (C) 2010 Freddy Vulto 269 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 270 This is free software: you are free to change and redistribute it. 271 There is NO WARRANTY, to the extent permitted by law." 274 echo "bash: ${FUNCNAME[0]}: $1: invalid option" 1>&2 282 # end of Doxygen group 285 } # _BASIS_CORE_INCLUDED