summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Reisner <dreisner@archlinux.org>2012-04-18 01:22:24 +0200
committerDave Reisner <dreisner@archlinux.org>2012-04-20 03:14:44 +0200
commit5d62de59adfa8e6b7c19c418effc8757637c702e (patch)
treeb6e3e1997ff93e7441298c9f565ff63d59d8ee18
parentf44797037bc0741c1e5cffcb5751721edfa79e48 (diff)
downloadmkinitcpio-5d62de59adfa8e6b7c19c418effc8757637c702e.tar.gz
mkinitcpio-5d62de59adfa8e6b7c19c418effc8757637c702e.tar.xz
functions: add parseopts for longopt fun
Signed-off-by: Dave Reisner <dreisner@archlinux.org>
-rw-r--r--functions138
1 files changed, 138 insertions, 0 deletions
diff --git a/functions b/functions
index 5485578..eebf3a4 100644
--- a/functions
+++ b/functions
@@ -1,5 +1,143 @@
#!/bin/bash
+parseopts() {
+ local opt= optarg= i= shortopts=$1
+ local -a longopts=() unused_argv=()
+
+ shift
+ while [[ $1 && $1 != '--' ]]; do
+ longopts+=("$1")
+ shift
+ done
+ shift
+
+ longoptmatch() {
+ local o longmatch=()
+ for o in "${longopts[@]}"; do
+ if [[ ${o%:} = "$1" ]]; then
+ longmatch=("$o")
+ break
+ fi
+ [[ ${o%:} = "$1"* ]] && longmatch+=("$o")
+ done
+
+ case ${#longmatch[*]} in
+ 1)
+ # success, override with opt and return arg req (0 == none, 1 == required)
+ opt=${longmatch%:}
+ if [[ $longmatch = *: ]]; then
+ return 1
+ else
+ return 0
+ fi ;;
+ 0)
+ # fail, no match found
+ return 255 ;;
+ *)
+ # fail, ambiguous match
+ error "option '%s' is ambiguous; possibilities:%s" \
+ "--$1" "$(printf " '%s'" "${longmatch[@]%:}")"
+ return 254 ;;
+ esac
+ }
+
+ while (( $# )); do
+ case $1 in
+ --) # explicit end of options
+ shift
+ break
+ ;;
+ -[!-]*) # short option
+ for (( i = 1; i < ${#1}; i++ )); do
+ opt=${1:i:1}
+
+ # option doesn't exist
+ if [[ $shortopts != *$opt* ]]; then
+ error "invalid option '%s'" "$opt"
+ OPTRET=(--)
+ return 1
+ fi
+
+ OPTRET+=("-$opt")
+ # option requires optarg
+ if [[ $shortopts = *$opt:* ]]; then
+ # if we're not at the end of the option chunk, the rest is the optarg
+ if (( i < ${#1} - 1 )); then
+ OPTRET+=("${1:i+1}")
+ break
+ # if we're at the end, grab the the next positional, if it exists
+ elif (( i == ${#1} - 1 )) && [[ $2 ]]; then
+ OPTRET+=("$2")
+ shift
+ break
+ # parse failure
+ else
+ error "option '%s' requires an argument" "-$opt"
+ OPTRET=(--)
+ return 1
+ fi
+ fi
+ done
+ ;;
+ --?*=*|--?*) # long option
+ IFS='=' read -r opt optarg <<< "${1#--}"
+ longoptmatch "$opt"
+ case $? in
+ 0)
+ if [[ $optarg ]]; then
+ error "option '%s' does not allow an argument" "--$opt"
+ OPTRET=(--)
+ return 1
+ else
+ OPTRET+=("--$opt")
+ shift
+ continue 2
+ fi
+ ;;
+ 1)
+ # --longopt=optarg
+ if [[ $optarg ]]; then
+ OPTRET+=("--$opt" "$optarg")
+ shift
+ # --longopt optarg
+ elif [[ $2 ]]; then
+ OPTRET+=("--$opt" "$2" )
+ shift 2
+ else
+ error "option '%s' requires an argument" "--$opt"
+ OPTRET=(--)
+ return 1
+ fi
+ continue 2
+ ;;
+ 254)
+ # ambiguous option -- error was reported for us by longoptmatch()
+ OPTRET=(--)
+ return 1
+ ;;
+ 255)
+ error "invalid option '%s'" "--$opt"
+ OPTRET=(--)
+ return 1
+ ;;
+ *)
+ error "internal error: invalid option in longopt array '%s'" "--$opt"
+ esac
+ ;;
+ *) # non-option arg encountered, add it as a parameter
+ unused_argv+=("$1")
+ ;;
+ esac
+ shift
+ done
+
+ # add end-of-opt terminator and any leftover positional parameters
+ OPTRET+=('--' "${unused_argv[@]}" "$@")
+ unset longoptmatch
+
+ return 0
+}
+
plain() {
local mesg=$1; shift
printf "$BOLD $mesg$NC\n" "$@" >&1