[pacman-dev] [PATCH] Added the function parse_options to replace getopt

Yun Zheng Hu yunzheng.hu at gmail.com
Wed Nov 19 18:43:30 EST 2008


This will make makepkg work properly on systems like Mac OS X, where
the default installed getopt does not handle long options.

The new parse_options function tries to behave like the original
getopt command as much as possible.

see also:
http://www.archlinux.org/pipermail/pacman-dev/2008-May/011830.html

Signed-off-by: Yun Zheng Hu <yunzheng.hu at gmail.com>
---
 scripts/makepkg.sh.in |   81 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 79 insertions(+), 2 deletions(-)

diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index 6dc7db4..8e3ad25 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -1117,6 +1117,83 @@ devel_update() {
 	fi
 }
 
+##
+#  usage : match_long_opt( $needle, $options )
+# return : matched option
+##
+match_long_opt() {
+	local needle=$1; shift
+	local matches item
+	for item in "$@"; do
+		[[ "$item" =~ ^"$needle" ]] && matches="$matches $item"
+	done
+	matches=( $matches )
+	[[ ${#matches[@]} == 1 ]] && echo ${matches[0]}
+}
+
+# getopt like parser, returns 1 on error
+parse_options() {
+	local short_options=$1; shift;
+	local long_options=$1; shift;
+	
+	local needs_args=0 consume_args=0 retcode=0
+	local opt_args="" last_opt=""
+	until [ -z "$1" ]; do
+		local handle_opt=$((!$needs_args && !$consume_args))
+		
+		if [[ ${1:0:2} = '--' && $handle_opt == 1 ]]; then
+			# handle long option
+			opt=${1:2}
+			if [ ! -z "$opt" ]; then
+				longopt_match=$(match_long_opt $opt ${long_options//,/ })
+				longopt_real="${longopt_match/:/}"	# strip possible ':'
+				[[ "${longopt_match}" == "${longopt_real}:" ]] && needs_args=1
+				[[ ! -z "$longopt_match" ]] && printf ' --%s' "$longopt_real" || {
+					echo "makepkg: $(gettext "unrecognized option") '$1'" >&2
+					retcode=1
+				}
+			elif [ $consume_args == 0 ]; then
+				# option '--', stop parsing options
+				consume_args=1
+			fi
+		elif [[ ${1:0:1} = '-' && $handle_opt == 1 ]]; then
+			# handle short option(s)
+			opts=${1:1}
+			local i=0 args=""
+			while [ $i -lt ${#opts} ]; do
+				opt=${opts:$((i++)):1}
+				[[ "$needs_args" == 1 ]] && args="${param}${opt}" && continue
+				[[ "$short_options" =~ "${opt}:" ]] && needs_args=1
+				[[ "$short_options" =~ "${opt}" ]] && printf ' -%s' "${opt}" || {
+					echo "makepkg: $(gettext "invalid option") -- '$opt'" >&2
+					retcode=1
+				}
+			done
+			# check if the user supplied the argument directly after the option
+			[ ! -z "$args" ] && printf " '$param'" && needs_args=0
+		else
+			# handle non option
+			[ "$needs_args" == 1 ] && printf " '$1'" && needs_args=0
+			[ "$consume_args" == 1 ] && opt_args="$opt_args '$1'"
+		fi
+		last_opt="$1"
+		shift
+	done
+	
+	# check if the user forgot to supply a required argument
+	if [[ "$needs_args" == 1 ]]; then
+		if [[ ${last_opt:0:2} = '--' ]]; then
+			echo "makepkg: option '$last_opt' $(gettext "requires an argument")" >&2
+		else
+			echo "makepkg: option $(gettext "requires an argument") -- '${last_opt:1}'" >&2
+		fi
+		retcode=1
+	fi
+	
+	printf " --$opt_args\n"
+	return $retcode
+}
+
 usage() {
 	printf "makepkg (pacman) %s\n" "$myver"
 	echo
@@ -1182,8 +1259,8 @@ OPT_LONG="$OPT_LONG,install,log,nocolor,nobuild,rmdeps,repackage,source"
 OPT_LONG="$OPT_LONG,syncdeps,version,config:"
 # Pacman Options
 OPT_LONG="$OPT_LONG,noconfirm,noprogressbar"
-OPT_TEMP="$(getopt -o "$OPT_SHORT" -l "$OPT_LONG" -n "$(basename "$0")" -- "$@" || echo 'GETOPT GO BANG!')"
-if echo "$OPT_TEMP" | grep -q 'GETOPT GO BANG!'; then
+OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@" || echo 'PARSE_OPTIONS FAILED')"
+if echo "$OPT_TEMP" | grep -q 'PARSE_OPTIONS FAILED'; then
 	# This is a small hack to stop the script bailing with 'set -e'
 	echo; usage; exit 1 # E_INVALID_OPTION;
 fi
-- 
1.5.6.5




More information about the pacman-dev mailing list