+# Check number of arguments.
+#
+# Usage: gsu_check_arg_count <num_given> <num1> [<num2>]
+#
+# Check that <num_given> is between <num1> and <num2> inclusively.
+# If only <num1> ist given, num2 is assumed to be infinity.
+#
+# Examples:
+# 0 0 no argument allowed
+# 1 1 exactly one argument required
+# 0 2 at most two arguments admissible
+# 2 at least two arguments required
+gsu_check_arg_count()
+{
+ ret=-$E_GSU_BAD_ARG_COUNT
+ if (($# == 2)); then # only num1 is given
+ result="at least $2 args required, $1 given"
+ (($1 < $2)) && return
+ ret=$GSU_SUCCESS
+ return
+ fi
+ # num1 and num2 given
+ result="need at least $2 args, $1 given"
+ (($1 < $2)) && return
+ result="need at most $3 args, $1 given"
+ (($1 > $3)) && return
+ ret=$GSU_SUCCESS
+}
+
+# Wrapper for the bash getopts builtin.
+#
+# Aborts on programming errors such as missing or invalid option string. On
+# success $result contains shell code that can be eval'ed. For each defined
+# option x, the local variable o_x will be created when calling eval "$result".
+# o_x contains true/false for options without argument and either the empty
+# string or the given argument for options that take an argument.
+#
+# Example:
+# gsu_getopts abc:x:y
+# eval "$result"
+# (($ret < 0)) && return
+#
+# [[ "$o_a" = 'true' ]] && echo 'The -a flag was given'
+# [[ -n "$o_c" ]] && echo "The -c option was given with arg $o_c"
+gsu_getopts()
+{
+ local i c tab=' ' cr='
+'
+
+ gsu_check_arg_count $# 1 1
+ if (($ret < 0)); then
+ gsu_err_msg
+ exit 1
+ fi
+
+ ret=-$E_GSU_GETOPTS
+ result="invalid optstring $1"
+ if [[ -z "$1" ]] || grep -q '::' <<< "$1" ; then
+ gsu_err_msg
+ exit 1
+ fi
+
+ for ((i=0; i < ${#1}; i++)); do
+ c=${1:$i:1}
+ case "$c" in
+ [a-zA-Z:]);;
+ *)
+ ret=-$E_GSU_GETOPTS
+ result="invalid character $c in optstring"
+ gsu_err_msg
+ exit 1
+ esac
+ done
+ result="local _gsu_getopts_opt"
+ for ((i=0; i < ${#1}; i++)); do
+ c1=${1:$i:1}
+ c2=${1:$(($i + 1)):1}
+ result+=" o_$c1="
+ if [[ "$c2" = ":" ]]; then
+ let i++
+ else
+ result+="false"
+ fi
+ done
+ result+="
+ OPTIND=1
+ while getopts $1 _gsu_getopts_opt \"\$@\"; do
+ case \"\$_gsu_getopts_opt\" in
+"
+ for ((i=0; i < ${#1}; i++)); do
+ c1=${1:$i:1}
+ c2=${1:$(($i + 1)):1}
+ result+="$tab$tab$c1) o_$c1="
+ if [[ "$c2" = ":" ]]; then
+ result+="\"\$OPTARG\""
+ let i++
+ else
+ result+="true"
+ fi
+ result+=";;$cr"
+ done
+ result+="
+ *)
+ ret=-\$E_GSU_GETOPTS
+ result=\"invalid option given\"
+ return
+ ;;
+ esac
+ done
+ shift \$((\$OPTIND - 1))
+"
+ ret=$GSU_SUCCESS
+}
+