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

Allan McRae allan at archlinux.org
Tue Nov 18 20:46:02 EST 2008


Yun Zheng Hu wrote:
> This will make makepkg work properly on systems like Mac OS X, where
> the default installed getopt does not handle long options.
>
> 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 |   54 +++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 52 insertions(+), 2 deletions(-)
>
> diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
> index 6dc7db4..ddcb06e 100644
> --- a/scripts/makepkg.sh.in
> +++ b/scripts/makepkg.sh.in
> @@ -27,7 +27,7 @@
>  # makepkg uses quite a few external programs during its execution. You
>  # need to have at least the following installed for makepkg to function:
>  #   awk, bsdtar (libarchive), bzip2, coreutils, fakeroot, find (findutils),
> -#   getopt (util-linux), gettext, grep, gzip, openssl, sed
> +#   gettext, grep, gzip, openssl, sed
>  
>  # gettext initialization
>  export TEXTDOMAIN='pacman'
> @@ -1117,6 +1117,56 @@ devel_update() {
>  	fi
>  }
>  
> +##
> +#  usage : match_long_opt( $needle, $options )
> +# return : matched option
> +##
> +match_long_opt() {
> +    local needle=$1; shift
> +    local matches
> +    local 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_param=0
> +    until [ -z "$1" ]; do
> +        if [ ${1:0:2} = '--' ]; then
> +            # handle long option
> +            [ "$needs_param" = 1 ] && return 1
> +            opt=${1:2}
> +            [ -z "$opt" ] && break
> +            longopt=$(match_long_opt $opt ${long_options//,/ })
> +            [ ! -z "$longopt" ] && printf " %s" "--${longopt}" || return 1
> +        elif [ ${1:0:1} = '-' ]; then
> +            # handle short option(s)
> +            [ $needs_param = 1 ] && return 1
> +            opts=${1:1}
> +            local param
> +            local i=0
> +            while [ $i -lt ${#opts} ]; do
> +                opt=${opts:$((i++)):1}
> +                [[ "$needs_param" = 1 ]] && param="${param}${opt}" && continue
> +                [[ "$short_options" =~ "${opt}" ]] && printf " %s" "-${opt}" || return 1
> +                [[ "$short_options" =~ "${opt}:" ]] && needs_param=1
> +            done
> +            [ ! -z "$param" ] && printf " $param" && needs_param=0
> +        else
> +            # handle non option
> +            [ "$needs_param" = 1 ] && printf " $1" && needs_param=0
> +        fi
> +        shift
> +    done
> +    printf " --\n"
> +}
> +
>  usage() {
>  	printf "makepkg (pacman) %s\n" "$myver"
>  	echo
> @@ -1182,7 +1232,7 @@ 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!')"
> +OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@" || echo 'GETOPT GO BANG!')"
>  if echo "$OPT_TEMP" | grep -q 'GETOPT GO BANG!'; then
>  	# This is a small hack to stop the script bailing with 'set -e'
>  	echo; usage; exit 1 # E_INVALID_OPTION;
>   

I need to go through this more fully but this seems OK to me.   One 
comment:  you should probably change the GETOPT GO BANG! stuff to 
something like "PARSE_OPTIONS FAILED", or preferably handle the error 
return properly.

Allan






More information about the pacman-dev mailing list