blob: 8f1cff52c4d9cbd6fc184da9d6871913e3454973 [file] [log] [blame]
# Copyright 2008 Kate Ward. All Rights Reserved.
# Released under the LGPL (GNU Lesser General Public License)
#
# shFlags -- Advanced command-line flag library for Unix shell scripts
#
# Author: kate.ward@forestent.com (Kate Ward)
#
# This module implements something like the google-gflags library available
# from http://code.google.com/p/google-gflags/.
#
# FLAG TYPES: This is a list of the DEFINE_*'s that you can do. All flags take
# a name, default value, help-string, and optional 'short' name (one-letter
# name). Some flags have other arguments, which are described with the flag.
#
# DEFINE_string: takes any input, and intreprets it as a string.
#
# DEFINE_boolean: typically does not take any argument: say --myflag to set
# FLAGS_myflag to true, or --nomyflag to set FLAGS_myflag to false.
# Alternately, you can say
# --myflag=true or --myflag=t or --myflag=1 or
# --myflag=false or --myflag=f or --myflag=0
# Passing an option has the same affect as passing the option once.
#
# DEFINE_float: takes an input and intreprets it as a floating point number. As
# shell does not support floats per-se, the input is merely validated as
# being a valid floating point value.
#
# DEFINE_integer: takes an input and intreprets it as an integer.
#
# SPECIAL FLAGS: There are a few flags that have special meaning:
# --help (or -?) prints a list of all the flags in a human-readable fashion
# --flagfile=foo read flags from foo.
# -- as in getopt(), terminates flag-processing
#
# EXAMPLE USAGE:
#
# #! /bin/sh
# . ./shflags
#
# DEFINE_string name 'world' "somebody's name"
# FLAGS "$@" || exit $?; shift ${FLAGS_ARGC}
# echo "Hello, ${FLAGS_name}."
#
# NOTE: Not all systems include a getopt version that supports long flags. On
# these systems, only short flags are recognized.
#==============================================================================
# shFlags
#
# Shared attributes:
# flags_error: last error message
# flags_return: last return value
#
# __flags_longNames: list of long names for all flags
# __flags_shortNames: list of short names for all flags
# __flags_boolNames: list of boolean flag names
#
# Per-flag attributes:
# FLAGS_<flag_name>: contains value of flag named 'flag_name'
# __flags_<flag_name>_default: the default flag value
# __flags_<flag_name>_help: the flag help string
# __flags_<flag_name>_short: the flag short name
# __flags_<flag_name>_type: the flag type
#
# Notes:
# - lists of strings are space separated, and a null value is the '~' char.
# return if FLAGS already loaded
[ -n "${FLAGS_VERSION:-}" ] && return 0
FLAGS_VERSION='1.0.2pre'
_flags_debug() { echo "flags:DEBUG $@" >&2; }
_flags_error() { echo "flags:ERROR $@" >&2; }
_flags_fatal() { echo "flags:FATAL $@" >&2; }
FLAGS_TRUE=0
FLAGS_FALSE=1
FLAGS_ERROR=2
# specific shell checks
if [ -n "${ZSH_VERSION:-}" ]; then
setopt |grep "^shwordsplit$" >/dev/null
if [ $? -ne ${FLAGS_TRUE} ]; then
_flags_fatal 'zsh shwordsplit option is required for proper zsh operation'
exit ${FLAGS_ERROR}
fi
if [ -z "${FLAGS_PARENT:-}" ]; then
_flags_fatal "zsh does not pass \$0 through properly. please declare' \
\"FLAGS_PARENT=\$0\" before calling shFlags"
exit ${FLAGS_ERROR}
fi
fi
# shell flags
# u: treat unset variables as an error when performing parameter expansion
__FLAGS_SHELL_FLAGS='u'
# save the current set of shell flags, and then set some for ourself
_flags_oldShellFlags=$-
for _flags_shellFlag in `echo "${__FLAGS_SHELL_FLAGS}" |sed 's/\(.\)/\1 /g'`
do
set "-${_flags_shellFlag}"
done
unset _flags_shellFlag
#
# constants
#
# getopt version
__FLAGS_GETOPT_VERS_STD=0
__FLAGS_GETOPT_VERS_ENH=1
__FLAGS_GETOPT_VERS_BSD=2
getopt >/dev/null 2>&1
case $? in
0) __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD} ;; # bsd getopt
2)
if [ "`getopt --version`" = '-- ' ]; then
__FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD}
else
__FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_ENH}
fi
;;
*)
_flags_fatal 'unable to determine getopt version'
exit ${FLAGS_ERROR}
;;
esac
# getopt optstring lengths
__FLAGS_OPTSTR_SHORT=0
__FLAGS_OPTSTR_LONG=1
__FLAGS_NULL='~'
# flag info strings
__FLAGS_INFO_DEFAULT_STR='default'
__FLAGS_INFO_HELP_STR='help'
__FLAGS_INFO_SHORT_STR='short'
__FLAGS_INFO_TYPE_STR='type'
# flag lengths
__FLAGS_LEN_SHORT=0
__FLAGS_LEN_LONG=1
# flag types
__FLAGS_TYPE_NONE=0
__FLAGS_TYPE_BOOLEAN=1
__FLAGS_TYPE_FLOAT=2
__FLAGS_TYPE_INTEGER=3
__FLAGS_TYPE_STRING=4
# set the constants readonly
_flags_constants=`set |awk -F= '/^FLAGS_/ || /^__FLAGS_/ {print $1}'`
for _flags_const in ${_flags_constants}; do
if [ -n "${ZSH_VERSION:-}" ]; then
case ${ZSH_VERSION} in
[123].*) readonly ${_flags_const} ;;
*) readonly -g ${_flags_const} ;; # declare readonly constants globally
esac
else
readonly ${_flags_const}
fi
done
unset _flags_const _flags_constants
#
# internal variables
#
__flags_boolNames=' '
__flags_longNames=' '
__flags_shortNames=' '
#------------------------------------------------------------------------------
# private functions
#
# Define a flag. Calling this function will define the following info variables
# for the specified flag:
# FLAGS_flagname - the name for this flag (based upon the long flag name)
# __flags_<flag_name>_default - the default value
# __flags_flagname_help - the help string
# __flags_flagname_short - the single letter alias
# __flags_flagname_type - the type of flag (one of __FLAGS_TYPE_*)
#
# Args:
# _flags__type: integer: internal type of flag (__FLAGS_TYPE_*)
# _flags__name: string: long flag name
# _flags__default: default flag value
# _flags__help: string: help string
# _flags__short: string: (optional) short flag name
# Returns:
# integer: success of operation, or error
_flags_define()
{
if [ $# -lt 4 ]; then
flags_error='DEFINE error: too few arguments'
flags_return=${FLAGS_ERROR}
_flags_error "${flags_error}"
return ${flags_return}
fi
_flags__type=$1
_flags__name=$2
_flags__default=$3
_flags__help=$4
_flags__short=${5:-${__FLAGS_NULL}}
_flags__return=${FLAGS_TRUE}
# TODO(kward): check for validity of the flag name (e.g. dashes)
# TODO(kward): throw warning when a flag without a short name is defined on a
# system with a standard getopt
# require short option for getopt that don't support long options
if [ ${_flags__return} -eq ${FLAGS_TRUE} \
-a ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} \
-a "${_flags__short}" = "${__FLAGS_NULL}" ]
then
flags_error="getopt on this platform supports only short flags. Please \
declare one for the (${_flags__name}) flag."
_flags__return=${FLAGS_ERROR}
fi
# check for existing long name definition
if [ ${_flags__return} -eq ${FLAGS_TRUE} ]; then
if _flags_itemInList "${_flags__name}" \
${__flags_longNames} ${__flags_boolNames}
then
flags_error="flag name ([no]${_flags__name}) already defined"
_flags__return=${FLAGS_FALSE}
fi
fi
# check for existing short name definition
if [ ${_flags__return} -eq ${FLAGS_TRUE} \
-a "${_flags__short}" != "${__FLAGS_NULL}" ]
then
if _flags_itemInList "${_flags__short}" ${__flags_shortNames}; then
flags_error="flag short name (${_flags__short}) already defined"
_flags__return=${FLAGS_FALSE}
fi
fi
# handle default value. note, on several occasions the 'if' portion of an
# if/then/else contains just a ':' which does nothing. a binary reversal via
# '!' is not done because it does not work on all shells.
if [ ${_flags__return} -eq ${FLAGS_TRUE} ]; then
case ${_flags__type} in
${__FLAGS_TYPE_BOOLEAN})
if _flags_validateBoolean "${_flags__default}"; then
case ${_flags__default} in
true|t|0) _flags__default=${FLAGS_TRUE} ;;
false|f|1) _flags__default=${FLAGS_FALSE} ;;
esac
else
flags_error="invalid default flag value '${_flags__default}'"
_flags__return=${FLAGS_ERROR}
fi
;;
${__FLAGS_TYPE_FLOAT})
if _flags_validateFloat "${_flags__default}"; then
:
else
flags_error="invalid default flag value '${_flags__default}'"
_flags__return=${FLAGS_ERROR}
fi
;;
${__FLAGS_TYPE_INTEGER})
if _flags_validateInteger "${_flags__default}"; then
:
else
flags_error="invalid default flag value '${_flags__default}'"
_flags__return=${FLAGS_ERROR}
fi
;;
${__FLAGS_TYPE_STRING}) ;; # everything in shell is a valid string
*)
flags_error="unrecognized flag type '${_flags__type}'"
_flags__return=${FLAGS_ERROR}
;;
esac
fi
if [ ${_flags__return} -eq ${FLAGS_TRUE} ]; then
# store flag information
eval "FLAGS_${_flags__name}='${_flags__default}'"
eval "__flags_${_flags__name}_${__FLAGS_INFO_TYPE_STR}=${_flags__type}"
eval "__flags_${_flags__name}_${__FLAGS_INFO_DEFAULT_STR}=\
\"${_flags__default}\""
eval "__flags_${_flags__name}_${__FLAGS_INFO_HELP_STR}=\"${_flags__help}\""
eval "__flags_${_flags__name}_${__FLAGS_INFO_SHORT_STR}='${_flags__short}'"
# append flag name(s) to list of names
__flags_longNames="${__flags_longNames}${_flags__name} "
__flags_shortNames="${__flags_shortNames}${_flags__short} "
[ ${_flags__type} -eq ${__FLAGS_TYPE_BOOLEAN} ] && \
__flags_boolNames="${__flags_boolNames}no${_flags__name} "
fi
flags_return=${_flags__return}
unset _flags__default _flags__help _flags__name _flags__return _flags__short \
_flags__type
[ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
return ${flags_return}
}
# return a valid getopt of either short or long options using currently defined
# list of long options as reference
#
# Args:
# _flags__optStr: int: option string type (__FLAGS_OPTSTR_*)
# Output:
# string: generated option string for getopt
# Returns:
# boolean: success of operation (always returns True)
_flags_genOptStr()
{
_flags__optStrType=$1
_flags__opts=''
for _flags__flag in ${__flags_longNames}; do
_flags__type=`_flags_getFlagInfo ${_flags__flag} ${__FLAGS_INFO_TYPE_STR}`
case ${_flags__optStrType} in
${__FLAGS_OPTSTR_SHORT})
_flags__shortName=`_flags_getFlagInfo \
${_flags__flag} ${__FLAGS_INFO_SHORT_STR}`
if [ "${_flags__shortName}" != "${__FLAGS_NULL}" ]; then
_flags__opts="${_flags__opts}${_flags__shortName}"
# getopt needs a trailing ':' to indicate a needed option
[ ${_flags__type} -ne ${__FLAGS_TYPE_BOOLEAN} ] && \
_flags__opts="${_flags__opts}:"
fi
;;
${__FLAGS_OPTSTR_LONG})
_flags__opts="${_flags__opts:+${_flags__opts},}${_flags__flag}"
# getopt needs a trailing ':' to indicate a needed option
[ ${_flags__type} -ne ${__FLAGS_TYPE_BOOLEAN} ] && \
_flags__opts="${_flags__opts}:"
;;
esac
done
echo "${_flags__opts}"
unset _flags__flag _flags__opts _flags__optStrType _flags__shortName \
_flags__type
return ${FLAGS_TRUE}
}
# Returns flag details based on a flag name and flag info.
#
# Args:
# string: long flag name
# string: flag info (see the _flags_define function for valid info types)
# Output:
# string: value of dereferenced flag variable
# Returns:
# integer: one of FLAGS_{TRUE|FALSE|ERROR}
_flags_getFlagInfo()
{
_flags__name=$1
_flags__info=$2
_flags__var="__flags_${_flags__name}_${_flags__info}"
_flags__strToEval="_flags__value=\"\${${_flags__var}:-}\""
eval "${_flags__strToEval}"
if [ -n "${_flags__value}" ]; then
flags_return=${FLAGS_TRUE}
else
flags_return=${FLAGS_ERROR}
flags_error="invalid variable name (${_flags__var})"
fi
echo "${_flags__value}"
unset _flags__info _flags__name _flags__strToEval _flags__var _flags__value
[ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
return ${flags_return}
}
# check for presense of item in a list. passed a string (e.g. 'abc'), this
# function will determine if the string is present in the list of strings (e.g.
# ' foo bar abc ').
#
# Args:
# _flags__str: string: string to search for in a list of strings
# unnamed: list: list of strings
# Returns:
# boolean: true if item is in the list
_flags_itemInList() {
_flags__str=$1
shift
echo " ${*:-} " |grep " ${_flags__str} " >/dev/null
if [ $? -eq 0 ]; then
flags_return=${FLAGS_TRUE}
else
flags_return=${FLAGS_FALSE}
fi
unset _flags__str
return ${flags_return}
}
# validate a boolean
#
# Args:
# _flags__bool: boolean: value to validate
# Returns:
# bool: true if the value is a valid boolean
_flags_validateBoolean()
{
_flags__bool=$1
flags_return=${FLAGS_TRUE}
case ${_flags__bool} in
true|t|0) ;;
false|f|1) ;;
*) flags_return=${FLAGS_FALSE} ;;
esac
unset _flags__bool
return ${flags_return}
}
# validate a float
#
# Args:
# _flags__float: float: value to validate
# Returns:
# bool: true if the value is a valid float
_flags_validateFloat()
{
_flags__float=$1
if _flags_validateInteger ${_flags__float}; then
flags_return=${FLAGS_TRUE}
else
flags_return=${FLAGS_TRUE}
case ${_flags__float} in
-*) # negative floats
_flags__test=`expr "${_flags__float}" : '\(-[0-9][0-9]*\.[0-9][0-9]*\)'`
;;
*) # positive floats
_flags__test=`expr "${_flags__float}" : '\([0-9][0-9]*\.[0-9][0-9]*\)'`
;;
esac
[ "${_flags__test}" != "${_flags__float}" ] && flags_return=${FLAGS_FALSE}
fi
unset _flags__float _flags__test
return ${flags_return}
}
# validate an integer
#
# Args:
# _flags__integer: interger: value to validate
# Returns:
# bool: true if the value is a valid integer
_flags_validateInteger()
{
_flags__int=$1
flags_return=${FLAGS_TRUE}
case ${_flags__int} in
-*) # negative ints
_flags__test=`expr "${_flags__int}" : '\(-[0-9][0-9]*\)'`
;;
*) # positive ints
_flags__test=`expr "${_flags__int}" : '\([0-9][0-9]*\)'`
;;
esac
[ "${_flags__test}" != "${_flags__int}" ] && flags_return=${FLAGS_FALSE}
unset _flags__int _flags__test
return ${flags_return}
}
#------------------------------------------------------------------------------
# public functions
#
# A basic boolean flag. Boolean flags do not take any arguments, and their
# value is either 1 (false) or 0 (true). For long flags, the false value is
# specified on the command line by prepending the word 'no'. With short flags,
# the presense of the flag toggles the current value between true and false.
# Specifying a short boolean flag twice on the command results in returning the
# value back to the default value.
#
# A default value is required for boolean flags.
#
# For example, lets say a Boolean flag was created whose long name was 'update'
# and whose short name was 'x', and the default value was 'false'. This flag
# could be explicitly set to 'true' with '--update' or by '-x', and it could be
# explicitly set to 'false' with '--noupdate'.
DEFINE_boolean() { _flags_define ${__FLAGS_TYPE_BOOLEAN} "$@"; }
# Other basic flags.
DEFINE_float() { _flags_define ${__FLAGS_TYPE_FLOAT} "$@"; }
DEFINE_integer() { _flags_define ${__FLAGS_TYPE_INTEGER} "$@"; }
DEFINE_string() { _flags_define ${__FLAGS_TYPE_STRING} "$@"; }
# Parse the flags.
#
# Args:
# unnamed: list: command-line flags to parse
# Returns:
# integer: success of operation, or error
FLAGS()
{
_flags_return=${FLAGS_TRUE}
# define standard 'help' flag
DEFINE_boolean 'help' false 'show this help' 'h'
FLAGS_ARGC=0
_flags_shortOpts=`_flags_genOptStr ${__FLAGS_OPTSTR_SHORT}`
_flags_longOpts='' # generated later only when needed
# parse options
# TODO(kward): look into '-T' option to test the internal getopt() version
if [ ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} ]; then
# check for spaces in passed options
for _flags_opt in "$@"; do
_flags_match=`echo "${_flags_opt}" |sed 's/ //g'`
if [ "${_flags_match}" != "${_flags_opt}" ]; then
_flags_error 'the available getopt does not support spaces in options'
return ${FLAGS_ERROR}
fi
done
unset _flags_match
_flags_opts=`getopt ${_flags_shortOpts} $@ 2>&1`
else
_flags_boolOpts=`echo "${__flags_boolNames}" \
|sed 's/^ *//;s/ *$//;s/ /,/g'`
_flags_longOpts=`_flags_genOptStr ${__FLAGS_OPTSTR_LONG}`
_flags_longOpts="${_flags_longOpts},${_flags_boolOpts}"
_flags_opts=`getopt \
-o ${_flags_shortOpts} \
-l ${_flags_longOpts} \
-- "$@" 2>&1`
fi
if [ $? -ne 0 ]; then
flags_error='unable to parse provided options with getopt.'
_flags_return=${FLAGS_ERROR}
fi
# output the options
if [ ${_flags_return} -eq ${FLAGS_TRUE} ]; then
if [ ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} ]; then
set -- ${_flags_opts}
else
# note the quotes around the `${_flags_opts}' -- they are essential!
eval set -- "${_flags_opts}"
fi
# handle options. note options with values must do an additional shift
while true; do
_flags_opt=$1
_flags_arg=${2:-}
_flags_type=${__FLAGS_TYPE_NONE}
# determine long flag name
case "${_flags_opt}" in
--) shift; break ;; # discontinue option parsing
--*) # long option
_flags_opt=`expr "${_flags_opt}" : '--\(.*\)'`
_flags_len=${__FLAGS_LEN_LONG}
if _flags_itemInList "${_flags_opt}" ${__flags_longNames}; then
_flags_name=${_flags_opt}
else
# check for negated long boolean version
if _flags_itemInList "${_flags_opt}" ${__flags_boolNames}; then
_flags_name=`expr "${_flags_opt}" : 'no\(.*\)'`
_flags_type=${__FLAGS_TYPE_BOOLEAN}
_flags_arg=${__FLAGS_NULL}
fi
fi
;;
-*) # short option
_flags_opt=`expr "${_flags_opt}" : '-\(.*\)'`
_flags_len=${__FLAGS_LEN_SHORT}
if _flags_itemInList "${_flags_opt}" ${__flags_shortNames}; then
# yes. match short name to long name. note purposeful off-by-one
# (too high) with awk calculations.
_flags_pos=`echo "${__flags_shortNames}" \
|awk 'BEGIN{RS=" ";rn=0}$0==e{rn=NR}END{print rn}' \
e=${_flags_opt}`
_flags_name=`echo "${__flags_longNames}" \
|awk 'BEGIN{RS=" "}rn==NR{print $0}' rn="${_flags_pos}"`
fi
;;
esac
# die if the flag was unrecognized
if [ -z "${_flags_name}" ]; then
flags_error="unrecognized option (${_flags_opt})"
_flags_return=${FLAGS_ERROR}
break
fi
# handle special case help flag
if [ "${_flags_name}" = 'help' ]; then
flags_help
flags_error='help requested'
_flags_return=${FLAGS_FALSE}
break
fi
# set new flag value
[ ${_flags_type} -eq ${__FLAGS_TYPE_NONE} ] && \
_flags_type=`_flags_getFlagInfo \
"${_flags_name}" ${__FLAGS_INFO_TYPE_STR}`
case ${_flags_type} in
${__FLAGS_TYPE_BOOLEAN})
if [ ${_flags_len} -eq ${__FLAGS_LEN_LONG} ]; then
if [ "${_flags_arg}" != "${__FLAGS_NULL}" ]; then
eval "FLAGS_${_flags_name}=${FLAGS_TRUE}"
else
eval "FLAGS_${_flags_name}=${FLAGS_FALSE}"
fi
else
_flags_strToEval="_flags_val=\
\${__flags_${_flags_name}_${__FLAGS_INFO_DEFAULT_STR}}"
eval "${_flags_strToEval}"
if [ ${_flags_val} -eq ${FLAGS_FALSE} ]; then
eval "FLAGS_${_flags_name}=${FLAGS_TRUE}"
else
eval "FLAGS_${_flags_name}=${FLAGS_FALSE}"
fi
fi
;;
${__FLAGS_TYPE_FLOAT})
if _flags_validateFloat "${_flags_arg}"; then
eval "FLAGS_${_flags_name}='${_flags_arg}'"
else
flags_error="invalid float value (${_flags_arg})"
_flags_return=${FLAGS_ERROR}
break
fi
;;
${__FLAGS_TYPE_INTEGER})
if _flags_validateInteger "${_flags_arg}"; then
eval "FLAGS_${_flags_name}='${_flags_arg}'"
else
flags_error="invalid integer value (${_flags_arg})"
_flags_return=${FLAGS_ERROR}
break
fi
;;
${__FLAGS_TYPE_STRING})
eval "FLAGS_${_flags_name}='${_flags_arg}'"
;;
esac
# shift the option out
shift
FLAGS_ARGC=`expr ${FLAGS_ARGC} + 1`
# additional shift for the argument
if [ ${_flags_type} != ${__FLAGS_TYPE_BOOLEAN} ]; then
shift
FLAGS_ARGC=`expr ${FLAGS_ARGC} + 1`
fi
done
fi
flags_return=${_flags_return}
unset _flags_arg _flags_boolOpts _flags_len _flags_longOpts _flags_name \
_flags_opt _flags_opts _flags_pos _flags_return _flags_shortOpts \
_flags_strToEval _flags_type _flags_val
[ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_fatal "${flags_error}"
return ${flags_return}
}
# This is a helper function for determining the `getopt` version for platforms
# where the detection isn't working. It simply outputs debug information that
# can be included in a bug report.
#
# Args:
# none
# Returns:
# nothing
flags_getoptInfo()
{
# platform info
_flags_debug "uname -a: `uname -a`"
_flags_debug "PATH: ${PATH}"
# shell info
if [ -n "${BASH_VERSION:-}" ]; then
_flags_debug 'shell: bash'
_flags_debug "BASH_VERSION: ${BASH_VERSION}"
elif [ -n "${ZSH_VERSION:-}" ]; then
_flags_debug 'shell: zsh'
_flags_debug "ZSH_VERSION: ${ZSH_VERSION}"
fi
# getopt info
getopt >/dev/null
_flags__getoptReturn=$?
_flags_debug "getopt return: ${_flags__getoptReturn}"
_flags_debug "getopt --version: `getopt --version 2>&1`"
unset _flags__getoptReturn
}
# returns whether the detected getopt version is the enhanced version
#
# Args:
# none
# Returns:
# bool: true if getopt is the enhanced version
flags_getoptIsEnh()
{
if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} ]; then
return ${FLAGS_TRUE}
else
return ${FLAGS_FALSE}
fi
}
# returns whether the detected getopt version is the standard version
#
# Args:
# none
# Returns:
# bool: true if getopt is the standard version
flags_getoptIsStd()
{
if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD} ]; then
return ${FLAGS_TRUE}
else
return ${FLAGS_FALSE}
fi
}
# This is effectively a 'usage()' function. It prints usage information and
# exits the program with ${FLAGS_FALSE} if it is ever found in the command line
# arguments. Note this function can be overridden so other apps can define
# their own --help flag, replacing this one, if they want.
#
# Args:
# none
# Returns:
# integer: success of operation (always returns true)
flags_help()
{
if [ -n "${FLAGS_HELP:-}" ]; then
echo "${FLAGS_HELP}" >&2
else
echo "USAGE: ${FLAGS_PARENT:-$0} [flags] args" >&2
fi
if [ -n "${__flags_longNames}" ]; then
echo 'flags:' >&2
for _flags_name in `echo ${__flags_longNames} |sort`; do
_flags_helpstr=' '
_flags_short=`_flags_getFlagInfo \
"${_flags_name}" ${__FLAGS_INFO_SHORT_STR}`
if [ "${_flags_short}" != "${__FLAGS_NULL}" ]; then
_flags_helpstr="${_flags_helpstr}-${_flags_short}"
fi
if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} ]; then
[ "${_flags_short}" != "${__FLAGS_NULL}" ] && \
_flags_helpstr="${_flags_helpstr},"
_flags_type=`_flags_getFlagInfo \
"${_flags_name}" ${__FLAGS_INFO_TYPE_STR}`
if [ ${_flags_type} -eq ${__FLAGS_TYPE_BOOLEAN} ]; then
_flags_boolstr='[no]'
else
_flags_boolstr=''
fi
_flags_helpstr="${_flags_helpstr}--${_flags_boolstr:-}${_flags_name}:"
fi
_flags_help=`_flags_getFlagInfo \
"${_flags_name}" ${__FLAGS_INFO_HELP_STR}`
_flags_helpstr="${_flags_helpstr} ${_flags_help}"
echo "${_flags_helpstr}" >&2
done
fi
unset _flags_boolstr _flags_help _flags_helpstr _flags_name _flags_short \
_flags_type
return ${FLAGS_TRUE}
}
# reset all flags back to their default values
#
# Args:
# none
# Returns:
# nothing
flags_reset()
{
for _flags_name in ${__flags_longNames}; do
_flags_strToEval="unset FLAGS_${_flags_name}"
for _flags_type in \
${__FLAGS_INFO_HELP_STR} \
${__FLAGS_INFO_SHORT_STR} \
${__FLAGS_INFO_TYPE_STR}
do
_flags_strToEval=\
"${_flags_strToEval} __flags_${_flags_name}_${_flags_type}"
done
eval ${_flags_strToEval}
done
# reset internal variables
__flags_boolNames=' '
__flags_longNames=' '
__flags_shortNames=' '
unset _flags_name _flags_type _flags_strToEval
}
#==============================================================================
# main
#
# restore the previous set of shell flags
for _flags_shellFlag in ${__FLAGS_SHELL_FLAGS}; do
echo ${_flags_oldShellFlags} |grep ${_flags_shellFlag} >/dev/null || \
set +${_flags_shellFlag}
done
unset _flags_oldShellFlags _flags_shellFlag
# vim:et:ft=sh:sts=2:sw=2
# $Id$