+export -f _com_help
+
+# internal gsu function that syntactically checks the gsu_options array
+# for errors and parses the config file.
+_gsu_check_options()
+{
+ local i conf="${gsu_config_file:=$HOME/.$gsu_name.rc}" val
+
+ for ((i=0; i < ${#gsu_options[@]}; i++)); do
+ eval "${gsu_options[$i]}"
+ eval val='"'\$$name'"'
+ eval orig_${gsu_config_var_prefix}_$name='"'${val}'"'
+ done
+
+ [[ -r "$conf" ]] && source "$conf"
+
+ for ((i=0; i < ${#gsu_options[@]}; i++)); do
+ local name= option_type= default_value= required=
+ local description= help_text=
+ local val orig_val
+
+ eval "${gsu_options[$i]}"
+
+
+ # Check name. It must be non-empty and consist of [a-zA-Z_0-9]
+ # only. Moreover it must not start with [a-zA-Z].
+
+ ret=-$E_GSU_BAD_CONFIG_VAR
+ result="name: '$name'"
+ # bash's =~ works only for 3.2 and newer, so use grep
+ echo "$name" | grep '^[a-zA-Z][a-zA-Z_0123456789]*$' &> /dev/null;
+ [[ $? -ne 0 ]] && return
+
+ eval orig_val='"'\$orig_${gsu_config_var_prefix}_$name'"'
+ if [[ -z "$orig_val" ]]; then
+ eval val='"'\$$name'"'
+ else
+ val="$orig_val"
+ fi
+ case "$required" in
+ true|yes)
+ ret=-$E_GSU_NEED_VALUE
+ result="$name"
+ [[ -z "$val" ]] && return
+ ;;
+ false|no)
+ ;;
+ *)
+ ret=-$E_GSU_BAD_BOOL
+ result="required: $required, name: $name, val: $val"
+ return
+ esac
+
+ eval ${gsu_config_var_prefix}_$name='"'${val:=$default_value}'"'
+ # Check option type. ATM, only num and string are supported
+ # Other types may be added without breaking compatibility
+ case "$option_type" in
+ string)
+ ;;
+ num)
+ gsu_is_a_number "$val"
+ [[ $ret -lt 0 ]] && return
+ ;;
+ *)
+ ret=-$E_GSU_BAD_OPTION_TYPE
+ result="$name/$option_type"
+ return
+ esac
+ done
+ ret=$GSU_SUCCESS
+}
+export -f _gsu_check_options
+
+# Wrapper for bash's getopts.
+#
+# 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 an argument or the emtpy string/the
+# given argument, depending on whether this option was contained in the "$@"
+# array.
+#
+# Example:
+# gsu_getopts abc:x:y
+# eval "$result"
+# [[ $ret -lt 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 -lt 0 ]]; then
+ gsu_err_msg
+ exit 1
+ fi
+
+ ret=-$E_GSU_GETOPTS
+ result="invalid optstring $1"
+ if [[ -z "$1" || "$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 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 opt \"\$@\"; do
+ case \"\$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
+}
+export -f gsu_getopts