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)
opt=${longmatch%[:?]}
case $longmatch in
*:) return 1 ;;
*\?) return 2 ;;
*) return 0 ;;
esac
;;
0)
return 255 ;;
*)
printf "${0##*/}: $(gettext "option '%s' is ambiguous; possibilities:")" "--$1"
printf " '%s'" "${longmatch[@]%[:?]}"
printf '\n'
return 254 ;;
esac >&2
}
while (( $# )); do
case $1 in
--) shift
break
;;
-[!-]*) for (( i = 1; i < ${#1}; i++ )); do
opt=${1:i:1}
case $shortopts in
*$opt:*)
if (( i < ${#1} - 1 )); then
OPTRET+=("-$opt" "${1:i+1}")
break
elif (( i == ${#1} - 1 && $# > 1 )); then
OPTRET+=("-$opt" "$2")
shift
break
else
printf "${0##*/}: $(gettext "option requires an argument") -- '%s'\n" "$opt" >&2
OPTRET=(--)
return 1
fi
;;
*$opt\?*)
if (( i < ${#1} - 1 )); then
OPTRET+=("-$opt=${1:i+1}")
break
else
OPTRET+=("-$opt")
fi
;;
*$opt*)
OPTRET+=("-$opt")
;;
*)
printf "${0##*/}: $(gettext "invalid option") -- '%s'\n" "$opt" >&2
OPTRET=(--)
return 1
;;
esac
done
;;
--?*=*|--?*) IFS='=' read -r opt optarg <<< "${1#--}"
longoptmatch "$opt"
case $? in
0)
if [[ $1 = *=* ]]; then
printf "${0##*/}: $(gettext "option '%s' does not allow an argument")\n" "--$opt" >&2
OPTRET=(--)
return 1
else
OPTRET+=("--$opt")
fi
;;
1)
if [[ $1 = *=* ]]; then
OPTRET+=("--$opt" "$optarg")
elif (( $# > 1 )); then
OPTRET+=("--$opt" "$2" )
shift
else
printf "${0##*/}: $(gettext "option '%s' requires an argument")\n" "--$opt" >&2
OPTRET=(--)
return 1
fi
;;
2)
if [[ $1 = *=* ]]; then
OPTRET+=("--$opt=$optarg")
else
OPTRET+=("--$opt")
fi
;;
254)
OPTRET=(--)
return 1
;;
255)
printf "${0##*/}: $(gettext "invalid option") '--%s'\n" "$opt" >&2
OPTRET=(--)
return 1
;;
esac
;;
*) unused_argv+=("$1")
;;
esac
shift
done
OPTRET+=('--' "${unused_argv[@]}" "$@")
unset longoptmatch
return 0
}