BASIS  version 1.2.3 (revision 2104)
shflags.sh
Go to the documentation of this file.
00001 # vim:et:ft=sh:sts=2:sw=2
00002 
00003 ##############################################################################
00004 # @file   shflags.sh
00005 # @author Kate Ward <kate.ward at forestent.com>, Andreas Schuh
00006 # @brief  Advanced command-line flag library for Unix shell scripts.
00007 #
00008 # @sa http://code.google.com/p/shflags/
00009 #
00010 # @note The shFlags implementation by Kate Ward (revision 147) has been
00011 #       considerably modified by Andreas Schuh as part of the BASIS project
00012 #       to fit the needs of the SBIA Group at The University of Pennsylvania.
00013 #
00014 # This module implements something like the google-gflags library available
00015 # from http://code.google.com/p/google-gflags/.
00016 #
00017 # FLAG TYPES: This is a list of the DEFINE_*'s that you can do.  All flags take
00018 # a name, default value, help-string, and optional 'short' name (one-letter
00019 # name).  Some flags have other arguments, which are described with the flag.
00020 #
00021 # - DEFINE_string: takes any input, and intreprets it as a string.
00022 #
00023 # - DEFINE_boolean: typically does not take any argument: say --myflag to set
00024 #   FLAGS_myflag to true, or --nomyflag to set FLAGS_myflag to false.
00025 #   Alternatively, you can say
00026 #     --myflag=true  or --myflag=t or --myflag=0  or
00027 #     --myflag=false or --myflag=f or --myflag=1
00028 #   Passing an option has the same affect as passing the option once.
00029 #
00030 # - DEFINE_float: takes an input and intreprets it as a floating point number. As
00031 #   shell does not support floats per-se, the input is merely validated as
00032 #   being a valid floating point value.
00033 #
00034 # - DEFINE_integer: takes an input and intreprets it as an integer.
00035 #
00036 # - SPECIAL FLAGS: There are a few flags that have special meaning:
00037 #   --help (or -?)  prints a list of all the flags in a human-readable fashion
00038 #   --flagfile=foo  read flags from foo.  (not implemented yet)
00039 #   --              as in getopt(), terminates flag-processing
00040 #
00041 # EXAMPLE USAGE:
00042 #
00043 # Example script hello.sh(.in):
00044 # @code
00045 # #! /bin/sh
00046 # @BASIS_BASH_UTILITIES@
00047 #
00048 # DEFINE_string name 'world' "somebody's name" n
00049 #
00050 # FLAGS "$@" || exit $?
00051 # eval set -- "${FLAGS_ARGV}"
00052 #
00053 # echo "Hello, ${FLAGS_name}."
00054 # @endcode
00055 #
00056 # Usage of example script hello.sh:
00057 # @code
00058 # $ ./hello.sh -n Kate
00059 # Hello, Kate.
00060 # @endcode
00061 #
00062 # CUSTOMIZABLE BEHAVIOR:
00063 #
00064 # A script can override the default 'getopt' command by providing the path to
00065 # an alternate implementation by defining the FLAGS_GETOPT_CMD variable.
00066 #
00067 # ATTRIBUTES:
00068 #
00069 # Shared attributes:
00070 #   flags_error: last error message
00071 #   flags_return: last return value
00072 #
00073 #   __flags_longNames: list of long names for all flags
00074 #   __flags_shortNames: list of short names for all flags
00075 #   __flags_boolNames: list of boolean flag names
00076 #
00077 #   __flags_opts: options parsed by getopt
00078 #
00079 # Per-flag attributes:
00080 #   FLAGS_<flag_name>: contains value of flag named 'flag_name'
00081 #   __flags_<flag_name>_default: the default flag value
00082 #   __flags_<flag_name>_help: the flag help string
00083 #   __flags_<flag_name>_short: the flag short name
00084 #   __flags_<flag_name>_type: the flag type
00085 #   __flags_<flag_name>_category: category of flag, use special category
00086 #                                 'required' to denote flags that need to be
00087 #                                 given on the command line
00088 #
00089 # NOTES:
00090 #
00091 # - Not all systems include a getopt version that supports long flags. On these
00092 #   systems, only short flags are recognized.
00093 #
00094 # - Lists of strings are space separated, and a null value is the '~' char.
00095 #
00096 # Copyright (c) 2008, Kate Ward.<br />
00097 # Copyright (c) 2011, University of Pennsylvania.<br />
00098 # All Rights Reserved.
00099 #
00100 # Released under the LGPL (GNU Lesser General Public License)
00101 
00102 # return if FLAGS already loaded
00103 [ -n "${FLAGS_VERSION:-}" ] && return 0
00104 
00105 FLAGS_VERSION='1.0.4pre-sbia'
00106 
00107 # ============================================================================
00108 # variables
00109 # ============================================================================
00110 
00111 # a user can set the path to a different getopt command by overriding this
00112 # variable in their script
00113 FLAGS_GETOPT_CMD=${FLAGS_GETOPT_CMD:-getopt}
00114 
00115 # return values that scripts can use
00116 FLAGS_TRUE=0
00117 FLAGS_FALSE=1
00118 FLAGS_ERROR=2
00119 
00120 # logging functions
00121 _flags_debug() { echo "flags:DEBUG $@" >&2; }
00122 _flags_warn() { echo "flags:WARN $@" >&2; }
00123 _flags_error() { echo "flags:ERROR $@" >&2; }
00124 _flags_fatal() { echo "flags:FATAL $@" >&2; exit ${FLAGS_ERROR}; }
00125 
00126 # specific shell checks
00127 if [ -n "${ZSH_VERSION:-}" ]; then
00128   setopt |grep "^shwordsplit$" >/dev/null
00129   if [ $? -ne ${FLAGS_TRUE} ]; then
00130     _flags_fatal 'zsh shwordsplit option is required for proper zsh operation'
00131   fi
00132   if [ -z "${FLAGS_PARENT:-}" ]; then
00133     _flags_fatal "zsh does not pass \$0 through properly. please declare' \
00134 \"FLAGS_PARENT=\$0\" before calling shFlags"
00135   fi
00136 fi
00137 
00138 # ----------------------------------------------------------------------------
00139 # constants
00140 # ----------------------------------------------------------------------------
00141 
00142 # reserved flag names
00143 __FLAGS_RESERVED_LIST=' ARGC ARGV ERROR FALSE GETOPT_CMD HELP PARENT TRUE '
00144 __FLAGS_RESERVED_LIST="${__FLAGS_RESERVED_LIST} VERSION "
00145 
00146 # getopt version
00147 __FLAGS_GETOPT_VERS_STD=0
00148 __FLAGS_GETOPT_VERS_ENH=1
00149 __FLAGS_GETOPT_VERS_BSD=2
00150 
00151 ${FLAGS_GETOPT_CMD} >/dev/null 2>&1
00152 case $? in
00153   0) __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD} ;;  # bsd getopt
00154   2)
00155     # TODO(kward): look into '-T' option to test the internal getopt() version
00156     if [ "`${FLAGS_GETOPT_CMD} --version`" = '-- ' ]; then
00157       __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD}
00158     else
00159       __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_ENH}
00160     fi
00161     ;;
00162   *) _flags_fatal 'unable to determine getopt version' ;;
00163 esac
00164 
00165 # getopt optstring lengths
00166 __FLAGS_OPTSTR_SHORT=0
00167 __FLAGS_OPTSTR_LONG=1
00168 
00169 __FLAGS_NULL='~'
00170 
00171 # flag info strings
00172 __FLAGS_INFO_DEFAULT='default'
00173 __FLAGS_INFO_HELP='help'
00174 __FLAGS_INFO_SHORT='short'
00175 __FLAGS_INFO_TYPE='type'
00176 __FLAGS_INFO_CATEGORY='category'
00177 
00178 # flag lengths
00179 __FLAGS_LEN_SHORT=0
00180 __FLAGS_LEN_LONG=1
00181 
00182 # flag types
00183 __FLAGS_TYPE_NONE=0
00184 __FLAGS_TYPE_BOOLEAN=1
00185 __FLAGS_TYPE_FLOAT=2
00186 __FLAGS_TYPE_INTEGER=3
00187 __FLAGS_TYPE_STRING=4
00188 
00189 # flag multi-types, offset MUST be 128
00190 __FLAGS_TYPE_MULTI_BOOLEAN=`expr "${__FLAGS_TYPE_BOOLEAN}" + 128`
00191 __FLAGS_TYPE_MULTI_FLOAT=`expr   "${__FLAGS_TYPE_FLOAT}"   + 128`
00192 __FLAGS_TYPE_MULTI_INTEGER=`expr "${__FLAGS_TYPE_INTEGER}" + 128`
00193 __FLAGS_TYPE_MULTI_STRING=`expr  "${__FLAGS_TYPE_STRING}"  + 128`
00194 
00195 # set the constants readonly
00196 __flags_constants=`set |awk -F= '/^FLAGS_/ || /^__FLAGS_/ {print $1}'`
00197 for __flags_const in ${__flags_constants}; do
00198   # skip certain flags
00199   case ${__flags_const} in
00200     FLAGS_PARENT) continue ;;
00201   esac
00202   # set flag readonly
00203   if [ -z "${ZSH_VERSION:-}" ]; then
00204     readonly ${__flags_const}
00205   else  # handle zsh
00206     case ${ZSH_VERSION} in
00207       [123].*) readonly ${__flags_const} ;;
00208       *) readonly -g ${__flags_const} ;;  # declare readonly constants globally
00209     esac
00210   fi
00211 done
00212 unset __flags_const __flags_constants
00213 
00214 # ----------------------------------------------------------------------------
00215 # internal variables
00216 # ----------------------------------------------------------------------------
00217 
00218 # space separated lists
00219 __flags_boolNames=' '    # boolean flag names
00220 __flags_longNames=' '    # long flag names
00221 __flags_shortNames=' '   # short flag names
00222 __flags_definedNames=' ' # defined flag names (used for validation)
00223 
00224 # arrays
00225 __flags_categoryNames=() # flag category names
00226 
00227 # others
00228 __flags_columns='' # determined screen width in columns
00229 __flags_opts=''    # temporary storage for parsed getopt flags
00230 
00231 # ============================================================================
00232 # private functions
00233 # ============================================================================
00234 
00235 ##############################################################################
00236 # Define a flag.
00237 #
00238 # Calling this function will define the following info variables for the
00239 # specified flag:
00240 #   FLAGS_flagname - the name for this flag (based upon the long flag name)
00241 #   __flags_<flag_name>_default - the default value
00242 #   __flags_<flag_name>_help - the help string
00243 #   __flags_<flag_name>_short - the single letter alias
00244 #   __flags_<flag_name>_type - the type of flag (one of __FLAGS_TYPE_*)
00245 #   __flags_<flag_name>_category - the category of the flag
00246 #
00247 # Args:
00248 #   _flags_type: integer: internal type of flag (__FLAGS_TYPE_*)
00249 #   _flags_name: string: long flag name
00250 #   _flags_default: default flag value
00251 #   _flags_help: string: help string
00252 #   _flags_short: string: (optional) short flag name
00253 #   _flags_category: string: (optional) category name this flags belongs to
00254 # Returns:
00255 #   integer: success of operation, or error
00256 _flags_define()
00257 {
00258   if [ $# -lt 4 ]; then
00259     flags_error='DEFINE error: too few arguments'
00260     flags_return=${FLAGS_ERROR}
00261     _flags_error "${flags_error}"
00262     return ${flags_return}
00263   fi
00264 
00265   _flags_type_="$1"
00266   _flags_name_="$2"
00267   _flags_default_="$3"
00268   _flags_help_="$4"
00269   _flags_short_="${5:-${__FLAGS_NULL}}"
00270   _flags_category_="${6:-${__FLAGS_NULL}}"
00271 
00272   _flags_return_=${FLAGS_TRUE}
00273   _flags_usName_=`_flags_underscoreName ${_flags_name_}`
00274 
00275   # check whether the flag name is reserved
00276   _flags_itemInList ${_flags_usName_} "${__FLAGS_RESERVED_LIST}"
00277   if [ $? -eq ${FLAGS_TRUE} ]; then
00278     flags_error="flag name (${_flags_name_}) is reserved"
00279     _flags_return_=${FLAGS_ERROR}
00280   fi
00281 
00282   # require short option for getopt that don't support long options
00283   if [ ${_flags_return_} -eq ${FLAGS_TRUE} \
00284       -a ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} \
00285       -a "${_flags_short_}" = "${__FLAGS_NULL}" ]
00286   then
00287     flags_error="short flag required for (${_flags_name_}) on this platform"
00288     _flags_return_=${FLAGS_ERROR}
00289   fi
00290 
00291   # check for existing long name definition
00292   if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
00293     if _flags_itemInList ${_flags_usName_} ${__flags_definedNames}; then
00294       flags_error="definition for ([no]${_flags_name_}) already exists"
00295       _flags_warn "${flags_error}"
00296       _flags_return_=${FLAGS_FALSE}
00297     fi
00298   fi
00299 
00300   # check for existing short name definition
00301   if [ ${_flags_return_} -eq ${FLAGS_TRUE} \
00302       -a "${_flags_short_}" != "${__FLAGS_NULL}" ]
00303   then
00304     if _flags_itemInList "${_flags_short_}" ${__flags_shortNames}; then
00305       flags_error="flag short name (${_flags_short_}) already defined"
00306       _flags_warn "${flags_error}"
00307       _flags_return_=${FLAGS_FALSE}
00308     fi
00309   fi
00310 
00311   # convert array given as string such as "'a 1' 'b 2' 'c' 'd 4'" to array
00312   # ('a 1' 'b 2' 'c' 'd 4') and get type of values for multi-flags
00313   if [ ${_flags_type_} -gt 128 -a ${_flags_type_} -ne ${__FLAGS_TYPE_MULTI_BOOLEAN} ]; then
00314     _flags_valueType_=`expr "${_flags_type_}" - 128`
00315     eval "_flags_default_=(${_flags_default_})"
00316   else
00317     if [ ${#_flags_default_[@]} -ne 1 ]; then
00318       flags_error="${_flags_name_}: invalid default flag value '${_flags_default_}'"
00319       _flags_return_=${FLAGS_ERROR}
00320     fi
00321     _flags_valueType_=${_flags_type_}
00322   fi
00323 
00324   # handle default value. note, on several occasions the 'if' portion of an
00325   # if/then/else contains just a ':' which does nothing. a binary reversal via
00326   # '!' is not done because it does not work on all shells.
00327   if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
00328     case ${_flags_type_} in
00329       ${__FLAGS_TYPE_BOOLEAN})
00330         if _flags_validateBoolean "${_flags_default_}"; then
00331           case ${_flags_default_} in
00332             true|t|0) _flags_default_=${FLAGS_TRUE} ;;
00333             false|f|1) _flags_default_=${FLAGS_FALSE} ;;
00334           esac
00335         else
00336           flags_error="${_flags_name_}: invalid default flag value '${_flags_default_}'"
00337           _flags_return_=${FLAGS_ERROR}
00338         fi
00339         ;;
00340 
00341       ${__FLAGS_TYPE_MULTI_BOOLEAN})
00342         if _flags_validateInteger "${_flags_default_}"; then
00343           :
00344         else
00345           flags_error="${_flags_name_}: invalid default flag value '${_flags_default_}'"
00346           _flags_return_=${FLAGS_ERROR}
00347         fi
00348         ;;
00349 
00350       *)
00351         for _flags_defaultValue_ in "${_flags_default_[@]}"; do
00352           case ${_flags_valueType_} in
00353             ${__FLAGS_TYPE_FLOAT})
00354               if _flags_validateFloat "${_flags_defaultValue_}"; then
00355                 :
00356               else
00357                 flags_error="${_flags_name_}: invalid default flag value '${_flags_defaultValue_}'"
00358                 _flags_return_=${FLAGS_ERROR}
00359               fi
00360               ;;
00361 
00362             ${__FLAGS_TYPE_INTEGER})
00363               if _flags_validateInteger "${_flags_defaultValue_}"; then
00364                 :
00365               else
00366                 flags_error="${_flags_name_}: invalid default flag value '${_flags_defaultValue_}'"
00367                 _flags_return_=${FLAGS_ERROR}
00368               fi
00369               ;;
00370 
00371             ${__FLAGS_TYPE_STRING}) ;;  # everything in shell is a valid string
00372 
00373             *)
00374               flags_error="${_flags_name_}: unrecognized flag type '${_flags_type_}'"
00375               _flags_return_=${FLAGS_ERROR}
00376               ;;
00377           esac
00378         done
00379         ;;
00380     esac
00381   fi
00382 
00383   if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
00384     # store flag information
00385     if [ ${_flags_type_} -gt 128 ]; then
00386       eval "FLAGS_${_flags_usName_}=(\"\${_flags_default_[@]}\")"
00387       eval "__flags_${_flags_usName_}_${__FLAGS_INFO_DEFAULT}=(\"\${_flags_default_[@]}\")"
00388     else
00389       eval "FLAGS_${_flags_usName_}='${_flags_default_}'"
00390       eval "__flags_${_flags_usName_}_${__FLAGS_INFO_DEFAULT}='${_flags_default_}'"
00391     fi
00392     eval "__flags_${_flags_usName_}_${__FLAGS_INFO_TYPE}=${_flags_type_}"
00393     eval "__flags_${_flags_usName_}_${__FLAGS_INFO_HELP}=\"${_flags_help_}\""
00394     eval "__flags_${_flags_usName_}_${__FLAGS_INFO_SHORT}='${_flags_short_}'"
00395     eval "__flags_${_flags_usName_}_${__FLAGS_INFO_CATEGORY}='${_flags_category_}'"
00396 
00397     # append flag names to name lists
00398     __flags_shortNames="${__flags_shortNames}${_flags_short_} "
00399     __flags_longNames="${__flags_longNames}${_flags_name_} "
00400     [ ${_flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} -o \
00401       ${_flags_type_} -eq ${__FLAGS_TYPE_MULTI_BOOLEAN} ] && \
00402         __flags_boolNames="${__flags_boolNames}no${_flags_name_} "
00403 
00404     # append flag names to defined names for later validation checks
00405     __flags_definedNames="${__flags_definedNames}${_flags_usName_} "
00406     [ ${_flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] && \
00407         __flags_definedNames="${__flags_definedNames}no${_flags_usName_} "
00408 
00409     # append category name to category names list
00410     if [ "${_flags_category_}" != "${__FLAGS_NULL}" ]; then
00411       _flags_found_=${FLAGS_FALSE}
00412       for _flags_categoryName_ in "${__flags_categoryNames[@]}"; do
00413         if [ "${_flags_categoryName_}" = "${_flags_category_}" ]; then
00414           _flags_found_=${FLAGS_TRUE}
00415           break
00416         fi
00417       done
00418       if [ ${_flags_found_} -eq ${FLAGS_FALSE} ]; then
00419         __flags_categoryNames[${#__flags_categoryNames[@]}]="${_flags_category_}"
00420       fi
00421     fi
00422   fi
00423 
00424   flags_return=${_flags_return_}
00425   unset _flags_default_ _flags_help_ _flags_name_ _flags_return_ \
00426       _flags_short_ _flags_type_ _flags_usName_ \
00427       _flags_category_ _flags_found_
00428   [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
00429   return ${flags_return}
00430 }
00431 
00432 ##############################################################################
00433 # Return valid getopt options using currently defined list of long options.
00434 #
00435 # This function builds a proper getopt option string for short (and long)
00436 # options, using the current list of long options for reference.
00437 #
00438 # Args:
00439 #   _flags_optStr: integer: option string type (__FLAGS_OPTSTR_*)
00440 # Output:
00441 #   string: generated option string for getopt
00442 # Returns:
00443 #   boolean: success of operation (always returns True)
00444 _flags_genOptStr()
00445 {
00446   _flags_optStrType_=$1
00447 
00448   _flags_opts_=''
00449 
00450   for _flags_name_ in ${__flags_longNames}; do
00451     _flags_usName_=`_flags_underscoreName ${_flags_name_}`
00452     _flags_type_=`_flags_getFlagInfo ${_flags_usName_} ${__FLAGS_INFO_TYPE}`
00453     [ $? -eq ${FLAGS_TRUE} ] || _flags_fatal 'call to _flags_type_ failed'
00454     case ${_flags_optStrType_} in
00455       ${__FLAGS_OPTSTR_SHORT})
00456         _flags_shortName_=`_flags_getFlagInfo \
00457             ${_flags_usName_} ${__FLAGS_INFO_SHORT}`
00458         if [ "${_flags_shortName_}" != "${__FLAGS_NULL}" ]; then
00459           _flags_opts_="${_flags_opts_}${_flags_shortName_}"
00460           # getopt needs a trailing ':' to indicate a required argument
00461           [ ${_flags_type_} -ne ${__FLAGS_TYPE_BOOLEAN} -a \
00462             ${_flags_type_} -ne ${__FLAGS_TYPE_MULTI_BOOLEAN} ] && \
00463               _flags_opts_="${_flags_opts_}:"
00464         fi
00465         ;;
00466 
00467       ${__FLAGS_OPTSTR_LONG})
00468         _flags_opts_="${_flags_opts_:+${_flags_opts_},}${_flags_name_}"
00469         # getopt needs a trailing ':' to indicate a required argument
00470         [ ${_flags_type_} -ne ${__FLAGS_TYPE_BOOLEAN} -a \
00471           ${_flags_type_} -ne ${__FLAGS_TYPE_MULTI_BOOLEAN} ] && \
00472             _flags_opts_="${_flags_opts_}:"
00473         ;;
00474     esac
00475   done
00476 
00477   echo "${_flags_opts_}"
00478   unset _flags_name_ _flags_opts_ _flags_optStrType_ _flags_shortName_ \
00479       _flags_type_ _flags_usName_
00480   return ${FLAGS_TRUE}
00481 }
00482 
00483 ##############################################################################
00484 # Returns flag details based on a flag name and flag info.
00485 #
00486 # Args:
00487 #   string: underscored flag name
00488 #   string: flag info (see the _flags_define function for valid info types)
00489 # Output:
00490 #   string: value of dereferenced flag variable
00491 # Returns:
00492 #   integer: one of FLAGS_{TRUE|FALSE|ERROR}
00493 _flags_getFlagInfo()
00494 {
00495   # note: adding gFI to variable names to prevent naming conflicts with calling
00496   # functions
00497   _flags_gFI_usName_=$1
00498   _flags_gFI_info_=$2
00499 
00500   _flags_infoVar_="__flags_${_flags_gFI_usName_}_${_flags_gFI_info_}"
00501   _flags_strToEval_="_flags_infoValue_=\"\${${_flags_infoVar_}:-}\""
00502   eval "${_flags_strToEval_}"
00503   if [ -n "${_flags_infoValue_}" ]; then
00504     flags_return=${FLAGS_TRUE}
00505   else
00506     # see if the _flags_gFI_usName_ variable is a string as strings can be
00507     # empty...
00508     # note: the DRY principle would say to have this function call itself for
00509     # the next three lines, but doing so results in an infinite loop as an
00510     # invalid _flags_name_ will also not have the associated _type variable.
00511     # Because it doesn't (it will evaluate to an empty string) the logic will
00512     # try to find the _type variable of the _type variable, and so on. Not so
00513     # good ;-)
00514     _flags_typeVar_="__flags_${_flags_gFI_usName_}_${__FLAGS_INFO_TYPE}"
00515     _flags_strToEval_="_flags_typeValue_=\"\${${_flags_typeVar_}:-}\""
00516     eval "${_flags_strToEval_}"
00517     if [ "${_flags_typeValue_}" = "${__FLAGS_TYPE_STRING}" -o "${_flags_typeValue_}" -gt 128 ]; then
00518       flags_return=${FLAGS_TRUE}
00519     else
00520       flags_return=${FLAGS_ERROR}
00521       flags_error="missing flag info variable (${_flags_infoVar_})"
00522     fi
00523   fi
00524 
00525   echo "${_flags_infoValue_}"
00526   unset _flags_gFI_usName_ _flags_gfI_info_ _flags_infoValue_ _flags_infoVar_ \
00527       _flags_strToEval_ _flags_typeValue_ _flags_typeVar_
00528   [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
00529   return ${flags_return}
00530 }
00531 
00532 ##############################################################################
00533 # Returns flag value based on a flag name.
00534 #
00535 # Args:
00536 #   unnamed: string: underscored flag name
00537 #   unnamed: string: name of the output variable
00538 # Output:
00539 #   sets the variable named by the second argument to the current value,
00540 #   which is an array in case of a multi-flag.
00541 # Returns:
00542 #   integer: one of FLAGS_{TRUE|FALSE|ERROR}
00543 _flags_getFlagValue()
00544 {
00545   _flags_gFV_usName_=$1
00546   _flags_gFV_type_=`_flags_getFlagInfo ${_flags_gFV_usName_} ${__FLAGS_INFO_TYPE}`
00547 
00548   if [ ${_flags_gFV_type_} -gt 128 ]; then
00549     eval "$2=(\"\${FLAGS_${_flags_gFV_usName_}[@]}\")"
00550   else
00551     eval "$2=\"\${FLAGS_${_flags_gFV_usName_}:-}\""
00552   fi
00553 
00554   unset _flags_gFV_usName_ _flags_gFV_type_
00555 
00556   return ${FLAGS_TRUE}
00557 }
00558 
00559 ##############################################################################
00560 # Returns flag default value based on a flag name.
00561 #
00562 # Args:
00563 #   unnamed: string: underscored flag name
00564 #   unnamed: string: name of the output variable
00565 # Output:
00566 #   sets the variable named by the second argument to the default value,
00567 #   which is an array in case of a multi-flag.
00568 # Returns:
00569 #   integer: one of FLAGS_{TRUE|FALSE|ERROR}
00570 _flags_getFlagDefault()
00571 {
00572   _flags_gFD_usName_=$1
00573   _flags_gFD_type_=`_flags_getFlagInfo ${_flags_gFD_usName_} ${__FLAGS_INFO_TYPE}`
00574 
00575   if [ ${_flags_gFD_type_} -gt 128 ]; then
00576     eval "$2=(\"\${__flags_${_flags_gFD_usName_}_${__FLAGS_INFO_DEFAULT}[@]}\")"
00577   else
00578     eval "$2=\"\${__flags_${_flags_gFD_usName_}_${__FLAGS_INFO_DEFAULT}:-}\""
00579   fi
00580 
00581   unset _flags_gFD_usName_ _flags_gFD_type_
00582 
00583   return ${FLAGS_TRUE}
00584 }
00585 
00586 # ----------------------------------------------------------------------------
00587 # helpers
00588 # ----------------------------------------------------------------------------
00589 
00590 ##############################################################################
00591 # Underscore a flag or category name by replacing dashes and whitespaces with underscores.
00592 #
00593 # Args:
00594 #   unnamed: string: long flag or category name
00595 # Output:
00596 #   string: underscored name
00597 _flags_underscoreName()
00598 {
00599   echo $1 | sed 's/[ -]/_/g'
00600 }
00601 
00602 ##############################################################################
00603 # Returns the width of the current screen.
00604 #
00605 # Output:
00606 #   integer: width in columns of the current screen.
00607 _flags_columns()
00608 {
00609   if [ -z "${__flags_columns}" ]; then
00610     # determine the value and store it
00611     if eval stty size >/dev/null 2>&1; then
00612       # stty size worked :-)
00613       set -- `stty size`
00614       __flags_columns=$2
00615     elif eval tput cols >/dev/null 2>&1; then
00616       set -- `tput cols`
00617       __flags_columns=$1
00618     else
00619       __flags_columns=80  # default terminal width
00620     fi
00621   fi
00622   echo ${__flags_columns}
00623 }
00624 
00625 ##############################################################################
00626 # Check for presense of item in a list.
00627 #
00628 # Passed a string (e.g. 'abc'), this function will determine if the string is
00629 # present in the list of strings (e.g.  ' foo bar abc ').
00630 #
00631 # Args:
00632 #   _flags_str_: string: string to search for in a list of strings
00633 #   unnamed: list: list of strings
00634 # Returns:
00635 #   boolean: true if item is in the list
00636 _flags_itemInList()
00637 {
00638   _flags_str_=$1
00639   shift
00640 
00641   echo " ${*:-} " |grep " ${_flags_str_} " >/dev/null
00642   if [ $? -eq 0 ]; then
00643     flags_return=${FLAGS_TRUE}
00644   else
00645     flags_return=${FLAGS_FALSE}
00646   fi
00647 
00648   unset _flags_str_
00649   return ${flags_return}
00650 }
00651 
00652 ##############################################################################
00653 # Sort space separated list.
00654 #
00655 # Args:
00656 #   @: list: space separated list of strings
00657 # Output:
00658 #   list: sorted space separated list of strings
00659 _flags_sortList()
00660 {
00661   echo "$@" | tr ' ' '\n' | sort | tr '\n' ' '
00662 }
00663 
00664 # ----------------------------------------------------------------------------
00665 # validators
00666 # ----------------------------------------------------------------------------
00667 
00668 ##############################################################################
00669 # Validate a boolean.
00670 #
00671 # Args:
00672 #   _flags__bool: boolean: value to validate
00673 # Returns:
00674 #   bool: true if the value is a valid boolean
00675 _flags_validateBoolean()
00676 {
00677   _flags_bool_=$1
00678 
00679   flags_return=${FLAGS_TRUE}
00680   case "${_flags_bool_}" in
00681     true|t|0) ;;
00682     false|f|1) ;;
00683     *) flags_return=${FLAGS_FALSE} ;;
00684   esac
00685 
00686   unset _flags_bool_
00687   return ${flags_return}
00688 }
00689 
00690 ##############################################################################
00691 # Validate a float.
00692 #
00693 # Args:
00694 #   _flags__float: float: value to validate
00695 # Returns:
00696 #   bool: true if the value is a valid float
00697 _flags_validateFloat()
00698 {
00699   _flags_float_=$1
00700 
00701   if _flags_validateInteger ${_flags_float_}; then
00702     flags_return=${FLAGS_TRUE}
00703   else
00704     flags_return=${FLAGS_TRUE}
00705     case ${_flags_float_} in
00706       -*)  # negative floats
00707         _flags_test_=`expr -- "${_flags_float_}" :\
00708             '\(-[0-9][0-9]*\.[0-9][0-9]*\)'`
00709         ;;
00710       *)  # positive floats
00711         _flags_test_=`expr -- "${_flags_float_}" :\
00712             '\([0-9][0-9]*\.[0-9][0-9]*\)'`
00713         ;;
00714     esac
00715     [ "${_flags_test_}" != "${_flags_float_}" ] && flags_return=${FLAGS_FALSE}
00716   fi
00717 
00718   unset _flags_float_ _flags_test_
00719   return ${flags_return}
00720 }
00721 
00722 ##############################################################################
00723 # Validate an integer.
00724 #
00725 # Args:
00726 #   _flags__int_: interger: value to validate
00727 # Returns:
00728 #   bool: true if the value is a valid integer
00729 _flags_validateInteger()
00730 {
00731   _flags_int_=$1
00732 
00733   flags_return=${FLAGS_TRUE}
00734   case ${_flags_int_} in
00735     -*)  # negative ints
00736       _flags_test_=`expr -- "${_flags_int_}" : '\(-[0-9][0-9]*\)'`
00737       ;;
00738     *)  # positive ints
00739       _flags_test_=`expr -- "${_flags_int_}" : '\([0-9][0-9]*\)'`
00740       ;;
00741   esac
00742   [ "${_flags_test_}" != "${_flags_int_}" ] && flags_return=${FLAGS_FALSE}
00743 
00744   unset _flags_int_ _flags_test_
00745   return ${flags_return}
00746 }
00747 
00748 ##############################################################################
00749 # Validate an unsigned integer.
00750 #
00751 # Args:
00752 #   _flags__uint_: interger: value to validate
00753 # Returns:
00754 #   bool: true if the value is a valid unsigned integer
00755 _flags_validateUnsignedInteger()
00756 {
00757   _flags_uint_=$1
00758 
00759   flags_return=${FLAGS_TRUE}
00760   _flags_test_=`expr -- "${_flags_uint_}" : '\([0-9][0-9]*\)'`
00761   [ "${_flags_test_}" != "${_flags_uint_}" ] && flags_return=${FLAGS_FALSE}
00762 
00763   unset _flags_uint_ _flags_test_
00764   return ${flags_return}
00765 }
00766 
00767 # ----------------------------------------------------------------------------
00768 # helpers for command-line parsing
00769 # ----------------------------------------------------------------------------
00770 
00771 ##############################################################################
00772 # Parse command-line options using the standard getopt.
00773 #
00774 # Note: the flag options are passed around in the global __flags_opts so that
00775 # the formatting is not lost due to shell parsing and such.
00776 #
00777 # Args:
00778 #   @: varies: command-line options to parse
00779 # Returns:
00780 #   integer: a FLAGS success condition
00781 _flags_getoptStandard()
00782 {
00783   flags_return=${FLAGS_TRUE}
00784   _flags_shortOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_SHORT}`
00785 
00786   # check for spaces in passed options
00787   for _flags_opt_ in "$@"; do
00788     # note: the silliness with the x's is purely for ksh93 on Ubuntu 6.06
00789     _flags_match_=`echo "x${_flags_opt_}x" |sed 's/ //g'`
00790     if [ "${_flags_match_}" != "x${_flags_opt_}x" ]; then
00791       flags_error='the available getopt does not support spaces in options'
00792       flags_return=${FLAGS_ERROR}
00793       break
00794     fi
00795   done
00796 
00797   if [ ${flags_return} -eq ${FLAGS_TRUE} ]; then
00798     __flags_opts=`getopt ${_flags_shortOpts_} $@ 2>&1`
00799     _flags_rtrn_=$?
00800     if [ ${_flags_rtrn_} -ne ${FLAGS_TRUE} ]; then
00801       _flags_warn "${__flags_opts}"
00802       flags_error='unable to parse provided options with getopt.'
00803       flags_return=${FLAGS_ERROR}
00804     fi
00805   fi
00806 
00807   unset _flags_match_ _flags_opt_ _flags_rtrn_ _flags_shortOpts_
00808   return ${flags_return}
00809 }
00810 
00811 ##############################################################################
00812 # Parse command-line options using the enhanced getopt.
00813 #
00814 # Note: the flag options are passed around in the global __flags_opts so that
00815 # the formatting is not lost due to shell parsing and such.
00816 #
00817 # Args:
00818 #   @: varies: command-line options to parse
00819 # Returns:
00820 #   integer: a FLAGS success condition
00821 _flags_getoptEnhanced()
00822 {
00823   flags_return=${FLAGS_TRUE}
00824   _flags_shortOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_SHORT}`
00825   _flags_boolOpts_=`echo "${__flags_boolNames}" \
00826       |sed 's/^ *//;s/ *$//;s/ /,/g'`
00827   _flags_longOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_LONG}`
00828 
00829   __flags_opts=`${FLAGS_GETOPT_CMD} \
00830       -o ${_flags_shortOpts_} \
00831       -l "${_flags_longOpts_},${_flags_boolOpts_}" \
00832       -- "$@" 2>&1`
00833   _flags_rtrn_=$?
00834   if [ ${_flags_rtrn_} -ne ${FLAGS_TRUE} ]; then
00835     _flags_warn "${__flags_opts}"
00836     flags_error='unable to parse provided options with getopt.'
00837     flags_return=${FLAGS_ERROR}
00838   fi
00839 
00840   unset _flags_boolOpts_ _flags_longOpts_ _flags_rtrn_ _flags_shortOpts_
00841   return ${flags_return}
00842 }
00843 
00844 ##############################################################################
00845 # Dynamically parse a getopt result and set appropriate variables.
00846 #
00847 # This function does the actual conversion of getopt output and runs it through
00848 # the standard case structure for parsing. The case structure is actually quite
00849 # dynamic to support any number of flags.
00850 #
00851 # Args:
00852 #   argc: int: original command-line argument count
00853 #   @: varies: output from getopt parsing
00854 # Returns:
00855 #   integer: a FLAGS success condition
00856 _flags_parseGetopt()
00857 {
00858   _flags_argc_=$1
00859   shift
00860 
00861   flags_return=${FLAGS_TRUE}
00862 
00863   if [ ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} ]; then
00864     set -- $@
00865   else
00866     # note the quotes around the `$@' -- they are essential!
00867     eval set -- "$@"
00868   fi
00869 
00870   # provide user with number of arguments to shift by later
00871   # NOTE: the FLAGS_ARGC variable is obsolete as of 1.0.3 because it does not
00872   # properly give user access to non-flag arguments mixed in between flag
00873   # arguments. Its usage was replaced by FLAGS_ARGV, and it is being kept only
00874   # for backwards compatibility reasons.
00875   FLAGS_ARGC=`expr $# - 1 - ${_flags_argc_}`
00876 
00877   # handle options. note options with values must do an additional shift
00878   while true; do
00879     _flags_opt_=$1
00880     _flags_arg_=${2:-}
00881     _flags_name_=''
00882 
00883     # determine long flag name
00884     case "${_flags_opt_}" in
00885       --) shift; break ;;  # discontinue option parsing
00886 
00887       --*)  # long option
00888         _flags_opt_=`expr -- "${_flags_opt_}" : '--\(.*\)'`
00889         _flags_len_=${__FLAGS_LEN_LONG}
00890         if _flags_itemInList "${_flags_opt_}" ${__flags_longNames}; then
00891           _flags_name_=${_flags_opt_}
00892         else
00893           # check for negated long boolean version
00894           if _flags_itemInList "${_flags_opt_}" ${__flags_boolNames}; then
00895             _flags_name_=`expr -- "${_flags_opt_}" : 'no\(.*\)'`
00896             _flags_arg_=${__FLAGS_NULL}
00897           fi
00898         fi
00899         ;;
00900 
00901       -*)  # short option
00902         _flags_opt_=`expr -- "${_flags_opt_}" : '-\(.*\)'`
00903         _flags_len_=${__FLAGS_LEN_SHORT}
00904         if _flags_itemInList "${_flags_opt_}" ${__flags_shortNames}; then
00905           # yes. match short name to long name. note purposeful off-by-one
00906           # (too high) with awk calculations.
00907           _flags_pos_=`echo "${__flags_shortNames}" \
00908               |awk 'BEGIN{RS=" ";rn=0}$0==e{rn=NR}END{print rn}' \
00909                   e=${_flags_opt_}`
00910           _flags_name_=`echo "${__flags_longNames}" \
00911               |awk 'BEGIN{RS=" "}rn==NR{print $0}' rn="${_flags_pos_}"`
00912         fi
00913         ;;
00914     esac
00915 
00916     # die if the flag was unrecognized
00917     if [ -z "${_flags_name_}" ]; then
00918       flags_error="unrecognized option (${_flags_opt_})"
00919       flags_return=${FLAGS_ERROR}
00920       break
00921     fi
00922 
00923     # set new flag value
00924     _flags_usName_=`_flags_underscoreName ${_flags_name_}`
00925     _flags_type_=`_flags_getFlagInfo "${_flags_usName_}" ${__FLAGS_INFO_TYPE}`
00926 
00927     case ${_flags_type_} in
00928       ${__FLAGS_TYPE_MULTI_BOOLEAN})
00929         eval "_flags_val_=\${FLAGS_${_flags_usName_}}"
00930         if [ ${_flags_len_} -eq ${__FLAGS_LEN_SHORT} -o \
00931              "${_flags_arg_}" != "${__FLAGS_NULL}" ]; then
00932           _flags_val_=`expr "${_flags_val_}" + 1`
00933         else
00934           _flags_val_=`expr "${_flags_val_}" - 1`
00935         fi
00936         eval "FLAGS_${_flags_usName_}=${_flags_val_}"
00937         ;;
00938 
00939       *)
00940         if [ ${_flags_type_} -ge 128 ]; then
00941           eval "_flags_idx_=\${#FLAGS_${_flags_usName_}[@]}"
00942           _flags_type_=`expr "${_flags_type_}" - 128`
00943         else
00944           _flags_idx_=0
00945         fi
00946         case ${_flags_type_} in
00947           ${__FLAGS_TYPE_BOOLEAN})
00948             if [ ${_flags_len_} -eq ${__FLAGS_LEN_LONG} ]; then
00949               if [ "${_flags_arg_}" != "${__FLAGS_NULL}" ]; then
00950                 eval "FLAGS_${_flags_usName_}[${_flags_idx_}]=${FLAGS_TRUE}"
00951               else
00952                 eval "FLAGS_${_flags_usName_}[${_flags_idx_}]=${FLAGS_FALSE}"
00953               fi
00954             else
00955               _flags_strToEval_="_flags_val_=\${__flags_${_flags_usName_}_${__FLAGS_INFO_DEFAULT}}"
00956               eval "${_flags_strToEval_}"
00957               if [ ${_flags_val_} -eq ${FLAGS_FALSE} ]; then
00958                 eval "FLAGS_${_flags_usName_}[${_flags_idx_}]=${FLAGS_TRUE}"
00959               else
00960                 eval "FLAGS_${_flags_usName_}[${_flags_idx_}]=${FLAGS_FALSE}"
00961               fi
00962             fi
00963             ;;
00964 
00965           ${__FLAGS_TYPE_FLOAT})
00966             if _flags_validateFloat "${_flags_arg_}"; then
00967               eval "FLAGS_${_flags_usName_}[${_flags_idx_}]='${_flags_arg_}'"
00968             else
00969               flags_error="${_flags_name_}: invalid float value (${_flags_arg_})"
00970               flags_return=${FLAGS_ERROR}
00971               break
00972             fi
00973             ;;
00974 
00975           ${__FLAGS_TYPE_INTEGER})
00976             if _flags_validateInteger "${_flags_arg_}"; then
00977               eval "FLAGS_${_flags_usName_}[${_flags_idx_}]='${_flags_arg_}'"
00978             else
00979               flags_error="${_flags_name_}: invalid integer value (${_flags_arg_})"
00980               flags_return=${FLAGS_ERROR}
00981               break
00982             fi
00983             ;;
00984 
00985           ${__FLAGS_TYPE_STRING})
00986             eval "FLAGS_${_flags_usName_}[${_flags_idx_}]='${_flags_arg_}'"
00987             ;;
00988         esac
00989         ;;
00990     esac
00991 
00992     # handle special case help flag
00993     if [ "${_flags_usName_}" = 'help' ]; then
00994       if [ ${FLAGS_help} -eq ${FLAGS_TRUE} ]; then
00995         flags_help
00996         flags_error='help requested'
00997         flags_return=${FLAGS_TRUE}
00998         break
00999       fi
01000     fi
01001 
01002     # handle special case helpman flag
01003     if [ "${_flags_usName_}" = 'helpman' ]; then
01004       if [ ${FLAGS_helpman} -eq ${FLAGS_TRUE} ]; then
01005         flags_error='help requested'
01006         flags_return=${FLAGS_TRUE}
01007         # if man should not be executed dirtly,
01008         # print generated man page to STDOUT instead
01009         if [ -n "${FLAGS_execman}" ] && [ ${FLAGS_execman} -eq ${FLAGS_FALSE} ]; then
01010           flags_helpman
01011           break
01012         fi
01013         # save generated man page to temporary file
01014         flags_manFile_="`mktemp -t \"${0##*/}.1\"`"
01015         if [ $? -ne 0 ]; then
01016           flags_error='failed to create temporary man page file name'
01017           flags_return=${FLAGS_ERROR}
01018           break
01019         fi
01020         flags_man_="`flags_helpman`"
01021         if [ $? -ne ${FLAGS_TRUE} ]; then
01022           flags_error='failed to generate temporary man page file'
01023           flags_return=${FLAGS_ERROR}
01024           break
01025         fi
01026         echo "${flags_man_}" > "${flags_manFile_}"
01027         if [ $? -ne ${FLAGS_TRUE} ]; then
01028           flags_error='failed to write temporary man page file'
01029           flags_return=${FLAGS_ERROR}
01030           break
01031         fi
01032         # execute man to view the man page
01033         man "${flags_manFile_}"
01034         if [ $? -ne ${FLAGS_TRUE} ]; then
01035           flags_error='failed to execute man to view generated man page'
01036           flags_return=${FLAGS_ERROR}
01037         fi
01038         # remove temporary man page file
01039         rm -f "${flags_manFile_}"
01040         if [ ${flags_return} -ne ${FLAGS_ERROR} -a $? -ne ${FLAGS_TRUE} ]; then
01041           flags_error='failed to execute man to view generated man page'
01042           flags_return=${FLAGS_ERROR}
01043         fi
01044         break
01045       fi
01046     fi
01047 
01048     # handle special case helpxml flag
01049     if [ "${_flags_usName_}" = 'helpxml' ]; then
01050       if [ ${FLAGS_helpxml} -eq ${FLAGS_TRUE} ]; then
01051         flags_helpxml
01052         flags_error='help requested'
01053         flags_return=${FLAGS_TRUE}
01054         break
01055       fi
01056     fi
01057 
01058     # handle special case usage flag
01059     if [ "${_flags_usName_}" = 'helpshort' ]; then
01060       if [ ${FLAGS_helpshort} -eq ${FLAGS_TRUE} ]; then
01061         flags_helpshort
01062         flags_error='help requested'
01063         flags_return=${FLAGS_TRUE}
01064         break
01065       fi
01066     fi
01067 
01068     # handle special case version flag
01069     if [ "${_flags_usName_}" = 'version' ]; then
01070       if [ ${FLAGS_version} -eq ${FLAGS_TRUE} ]; then
01071         flags_version
01072         flags_error='version requested'
01073         flags_return=${FLAGS_TRUE}
01074         break
01075       fi
01076     fi
01077 
01078     # shift the option and non-boolean arguments out.
01079     shift
01080     [ ${_flags_type_} != ${__FLAGS_TYPE_BOOLEAN} -a \
01081       ${_flags_type_} != ${__FLAGS_TYPE_MULTI_BOOLEAN} ] && shift
01082   done
01083 
01084   # give user back non-flag arguments
01085   FLAGS_ARGV=''
01086   while [ $# -gt 0 ]; do
01087     FLAGS_ARGV="${FLAGS_ARGV:+${FLAGS_ARGV} }'$1'"
01088     shift
01089   done
01090 
01091   unset _flags_arg_ _flags_len_ _flags_name_ _flags_opt_ _flags_pos_ \
01092       _flags_strToEval_ _flags_type_ _flags_usName_ _flags_val_
01093   return ${flags_return}
01094 }
01095 
01096 # ----------------------------------------------------------------------------
01097 # helpers for help output
01098 # ----------------------------------------------------------------------------
01099 
01100 ##############################################################################
01101 # Convert type ID to type string.
01102 #
01103 # Args:
01104 #   _flags_type_: integer: type ID
01105 # Outputs:
01106 #   string: type string
01107 _flags_typeStr()
01108 {
01109   _flags_tS_type_=$1
01110 
01111   # type ID's of multi-flags have an offset of 128 (8th bit set)
01112   if [ ${_flags_tS_type_} -gt 128 ]; then
01113     _flags_tS_type_=`expr "${_flags_type__}" - 128`
01114     echo -n 'multi '
01115   fi
01116 
01117   # type string of value type
01118   case "${_flags_tS_type_}" in
01119     ${__FLAGS_TYPE_BOOLEAN}) echo -n 'bool'; ;;
01120     ${__FLAGS_TYPE_FLOAT})   echo -n 'float'; ;;
01121     ${__FLAGS_TYPE_INTEGER}) echo -n 'int'; ;;
01122     ${__FLAGS_TYPE_STRING})  echo -n 'string'; ;;
01123     *)                       echo -n 'unknown'; ;;
01124   esac
01125 
01126   unset _flags_tS_type_
01127 }
01128 
01129 ##############################################################################
01130 # Convert current value to string for help output.
01131 _flags_currentStr()
01132 {
01133   _flags_name__=$1
01134 
01135   # get flag info
01136   _flags_usName__=`_flags_underscoreName ${_flags_name__}`
01137   _flags_type__=`_flags_getFlagInfo "${_flags_usName__}" ${__FLAGS_INFO_TYPE}`
01138   _flags_getFlagValue "${_flags_usName__}" '_flags_current__'
01139 
01140   _flags_multi__=${FLAGS_FALSE}
01141   if [ ${_flags_type__} -eq ${__FLAGS_TYPE_MULTI_BOOLEAN} ]; then
01142     _flags_valueType__=${__FLAGS_TYPE_INTEGER}
01143   elif [ ${_flags_type__} -gt 128 ]; then
01144     _flags_valueType__=`expr "${_flags_type__}" - 128`
01145     _flags_multi__=${FLAGS_TRUE}
01146     echo -n '['
01147   else
01148     _flags_valueType__=${_flags_type__}
01149   fi
01150 
01151   _flags_separator__='' # set at end of first iteration
01152   for _flags_value__ in "${_flags_current__[@]}"; do
01153     echo -n "${_flags_separator__}"
01154     case ${_flags_valueType__} in
01155       ${__FLAGS_TYPE_BOOLEAN})
01156         if [ ${_flags_value__} -eq ${FLAGS_TRUE} ]; then
01157           echo -n 'true'
01158         else
01159           echo -n 'false'
01160         fi
01161         ;;
01162 
01163       ${__FLAGS_TYPE_STRING})
01164         echo -n "'${_flags_value__}'"
01165         ;;
01166 
01167       *)
01168         echo -n ${_flags_value__}
01169         ;;
01170     esac
01171     _flags_separator__=' '
01172   done
01173 
01174   if [ ${_flags_multi__} -eq ${FLAGS_TRUE} ]; then
01175     echo -n ']'
01176   fi
01177 
01178   unset _flags_name__ _flags_usName__ _flags_current__ _flags_type__ \
01179       _flags_valueType__ _flags_value__ _flags_multi__ _flags_separator__
01180 }
01181 
01182 ##############################################################################
01183 # Convert default value to string for help output.
01184 _flags_defaultStr()
01185 {
01186   _flags_dS_name_=$1
01187 
01188   # get flag info
01189   _flags_dS_usName_=`_flags_underscoreName ${_flags_dS_name_}`
01190   _flags_dS_type_=`_flags_getFlagInfo "${_flags_dS_usName_}" ${__FLAGS_INFO_TYPE}`
01191   _flags_getFlagDefault "${_flags_dS_usName_}" '_flags_dS_default_'
01192 
01193   _flags_dS_multi_=${FLAGS_FALSE}
01194   if [ ${_flags_dS_type_} -eq ${__FLAGS_TYPE_MULTI_BOOLEAN} ]; then
01195     _flags_dS_valueType_=${__FLAGS_TYPE_INTEGER}
01196   elif [ ${_flags_dS_type_} -gt 128 ]; then
01197     _flags_dS_valueType_=`expr "${_flags_dS_type_}" - 128`
01198     _flags_dS_multi_=${FLAGS_TRUE}
01199     echo -n '['
01200   else
01201     _flags_dS_valueType_=${_flags_dS_type_}
01202   fi
01203 
01204   _flags_dS_separator_='' # set at end of first iteration
01205   for _flags_dS_value_ in "${_flags_dS_default_[@]}"; do
01206     echo -n "${_flags_dS_separator_}"
01207     case ${_flags_dS_valueType_} in
01208       ${__FLAGS_TYPE_BOOLEAN})
01209         if [ ${_flags_dS_value_} -eq ${FLAGS_TRUE} ]; then
01210           echo -n 'true'
01211         else
01212           echo -n 'false'
01213         fi
01214         ;;
01215 
01216       ${__FLAGS_TYPE_STRING})
01217         echo -n "'${_flags_dS_value_}'"
01218         ;;
01219 
01220       *)
01221         echo -n ${_flags_dS_value_}
01222         ;;
01223     esac
01224     _flags_dS_separator_=' '
01225   done
01226 
01227   if [ ${_flags_dS_multi_} -eq ${FLAGS_TRUE} ]; then
01228     echo -n ']'
01229   fi
01230 
01231   unset _flags_dS_name_ _flags_dS_usName_ _flags_dS_default_ _flags_dS_type_ \
01232       _flags_dS_valueType_ _flags_dS_value_ _flags_dS_multi_ _flags_dS_separator_
01233 }
01234 
01235 ##############################################################################
01236 # Escape string for use in XML output.
01237 #
01238 # Args:
01239 #   unnamed: string: some string
01240 # Output:
01241 #   string: xml-escaped string
01242 _flags_xmlText()
01243 {
01244   echo -e "$1" | sed 's/\&/\&amp;/g;s/</\&lt;/g'
01245 }
01246 
01247 ##############################################################################
01248 # Escape string for use in man page output.
01249 #
01250 # Args:
01251 #   unnamed: string: some string
01252 # Output:
01253 #   string: man page-escaped string
01254 _flags_manText()
01255 {
01256   echo -e "$1" | sed 's/\\/\\\\/g;s/-/\\-/g'
01257 }
01258 
01259 ##############################################################################
01260 # Output short usage of named flag.
01261 #
01262 # Args:
01263 #   _flags_name_: string: long flag name
01264 # Outputs:
01265 #  string: usage of flag, e.g., "--someflag=<int>"
01266 _flags_flagusage()
01267 {
01268   _flags_name_=$1
01269 
01270   # get type of flag
01271   _flags_usName_=`_flags_underscoreName ${_flags_name_}`
01272   _flags_type_=`_flags_getFlagInfo "${_flags_usName_}" ${__FLAGS_INFO_TYPE}`
01273 
01274   # type ID's of multi-flags have an offset of 128 (8th bit set)
01275   if [ ${_flags_type_} -ge 128 ]; then
01276     _flags_multi_=${FLAGS_TRUE}
01277     _flags_type_=`expr "${_flags_type_}" - 128`
01278   else
01279     _flags_multi_=${FLAGS_FALSE}
01280   fi
01281 
01282   # value type
01283   case ${_flags_type_} in
01284     ${__FLAGS_TYPE_BOOLEAN})
01285       echo -n "--[no]${_flags_name_}"
01286       ;;
01287 
01288     *)
01289       echo -n "--${_flags_name_}=<`_flags_typeStr ${_flags_type_}`>"
01290       ;;
01291   esac
01292 
01293   # append '...' if it's a multi-flag
01294   if [ ${_flags_multi_} -eq ${FLAGS_TRUE} ]; then
01295     echo -n '...'
01296   fi
01297 
01298   unset _flags_name_ _flags_usName_ _flags_type_ _flags_multi_
01299 }
01300 
01301 ##############################################################################
01302 # Output short usage of named flag in man page format.
01303 #
01304 # Args:
01305 #   _flags_name_: string: long flag name
01306 # Outputs:
01307 #  string: usage of flag, e.g., "--someflag=<int>"
01308 _flags_helpman_flagusage()
01309 {
01310   _flags_name_=$1
01311 
01312   # get type of flag
01313   _flags_usName_=`_flags_underscoreName ${_flags_name_}`
01314   _flags_type_=`_flags_getFlagInfo "${_flags_usName_}" ${__FLAGS_INFO_TYPE}`
01315 
01316   # type ID's of multi-flags have an offset of 128 (8th bit set)
01317   if [ ${_flags_type_} -ge 128 ]; then
01318     _flags_multi_=${FLAGS_TRUE}
01319     _flags_type_=`expr "${_flags_type_}" - 128`
01320   else
01321     _flags_multi_=${FLAGS_FALSE}
01322   fi
01323 
01324   # value type
01325   case ${_flags_type_} in
01326     ${__FLAGS_TYPE_BOOLEAN})
01327       echo -n "\fB--[no]${_flags_name_}\fR"
01328       ;;
01329 
01330     *)
01331       echo -n "\fB--${_flags_name_}\fR=<\fI`_flags_typeStr ${_flags_type_}`\fR>"
01332       ;;
01333   esac
01334 
01335   # append '...' if it's a multi-flag
01336   if [ ${_flags_multi_} -eq ${FLAGS_TRUE} ]; then
01337     echo -n '...'
01338   fi
01339 
01340   unset _flags_name_ _flags_usName_ _flags_type_ _flags_multi_
01341 }
01342 
01343 # ============================================================================
01344 # public functions
01345 # ============================================================================
01346 
01347 # ----------------------------------------------------------------------------
01348 # flag definition
01349 # ----------------------------------------------------------------------------
01350 
01351 # A basic boolean flag. Boolean flags do not take any arguments, and their
01352 # value is either 1 (false) or 0 (true). For long flags, the false value is
01353 # specified on the command line by prepending the word 'no'. With short flags,
01354 # the presense of the flag toggles the current value between true and false.
01355 # Specifying a short boolean flag twice on the command results in returning the
01356 # value back to the default value.
01357 #
01358 # A default value is required for boolean flags.
01359 #
01360 # For example, lets say a Boolean flag was created whose long name was 'update'
01361 # and whose short name was 'x', and the default value was 'false'. This flag
01362 # could be explicitly set to 'true' with '--update' or by '-x', and it could be
01363 # explicitly set to 'false' with '--noupdate'.
01364 DEFINE_boolean() { _flags_define ${__FLAGS_TYPE_BOOLEAN} "$@"; }
01365 DEFINE_bool()    { _flags_define ${__FLAGS_TYPE_BOOLEAN} "$@"; }
01366 
01367 # Other basic flags.
01368 DEFINE_float()   { _flags_define ${__FLAGS_TYPE_FLOAT}   "$@"; }
01369 DEFINE_integer() { _flags_define ${__FLAGS_TYPE_INTEGER} "$@"; }
01370 DEFINE_int()     { _flags_define ${__FLAGS_TYPE_INTEGER} "$@"; }
01371 DEFINE_string()  { _flags_define ${__FLAGS_TYPE_STRING}  "$@"; }
01372 
01373 # A multi boolean flag. Such flag can be given multiple times and instead of
01374 # representing a list of boolean values, this flag's value is a counter which
01375 # is incremented for every boolean flag value that is 'true' and decremented
01376 # otherwise. Note that the value of the counter may hence also be negative.
01377 #
01378 # An example use case of this flag is the --verbose flag. The more often this
01379 # flag was given, the more verbose the output messages should be.
01380 DEFINE_multi_boolean() { _flags_define ${__FLAGS_TYPE_MULTI_BOOLEAN} "$@"; }
01381 DEFINE_multi_bool()    { _flags_define ${__FLAGS_TYPE_MULTI_BOOLEAN} "$@"; }
01382 
01383 # Other multi-flags, i.e., flags that may be given multiple times
01384 DEFINE_multi_float()   { _flags_define ${__FLAGS_TYPE_MULTI_FLOAT}   "$@"; }
01385 DEFINE_multi_integer() { _flags_define ${__FLAGS_TYPE_MULTI_INTEGER} "$@"; }
01386 DEFINE_multi_int()     { _flags_define ${__FLAGS_TYPE_MULTI_INTEGER} "$@"; }
01387 DEFINE_multi_string()  { _flags_define ${__FLAGS_TYPE_MULTI_STRING}  "$@"; }
01388 
01389 # ----------------------------------------------------------------------------
01390 # command-line parsing
01391 # ----------------------------------------------------------------------------
01392 
01393 ##############################################################################
01394 # Parse the flags.
01395 #
01396 # Args:
01397 #   unnamed: list: command-line flags to parse
01398 # Returns:
01399 #   integer: success of operation, or error
01400 FLAGS()
01401 {
01402   # define standard flags if not already defined
01403   [ -z "${__flags_help_type:-}" ] && \
01404       DEFINE_boolean 'help' false 'Show help and exit.' 'h' 'help'
01405   [ -z "${__flags_helpman_type:-}" -a ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} ] && \
01406       DEFINE_boolean 'helpman' false 'Show help as man page and exit. If --execman is true (the default),
01407                                       a temporary man page file is written and displayed using man.
01408                                       Otherwise, if --noexecman was given before, the generated man
01409                                       page is printed to stdout instead.' \
01410           "${__FLAGS_NULL}" 'help'
01411   [ -z "${__flags_execman_type:-}" -a ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} ] && \
01412       DEFINE_boolean 'execman' true 'Execute man to view generated man page. See --helpman.' \
01413           "${__FLAGS_NULL}" 'help'
01414   [ -z "${__flags_helpxml_type:-}" -a ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} ] && \
01415       DEFINE_boolean 'helpxml' false 'Output help in XML format and exit.' "${__FLAGS_NULL}" 'help'
01416   [ -z "${__flags_helpshort_type:-}" -a ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} ] && \
01417       DEFINE_boolean 'helpshort' false 'Show usage information and exit.' "${__FLAGS_NULL}" 'help'
01418   [ -z "${__flags_version_type:-}" ] && \
01419       DEFINE_boolean 'version' false 'Show version and exit.' "${__FLAGS_NULL}" 'help'
01420   [ -z "${__flags_verbose_type:-}" ] && \
01421       DEFINE_multi_boolean 'verbose' 0 'Increase verbosity of output messages.
01422                                         Can be given multiple times.' 'v' 'help'
01423 
01424   # parse options
01425   if [ $# -gt 0 ]; then
01426     if [ ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} ]; then
01427       _flags_getoptStandard "$@"
01428     else
01429       _flags_getoptEnhanced "$@"
01430     fi
01431     flags_return=$?
01432   else
01433     # nothing passed; won't bother running getopt
01434     __flags_opts='--'
01435     flags_return=${FLAGS_TRUE}
01436   fi
01437 
01438   if [ ${flags_return} -eq ${FLAGS_TRUE} ]; then
01439     _flags_parseGetopt $# "${__flags_opts}"
01440     flags_return=$?
01441   fi
01442 
01443   [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_fatal "${flags_error}"
01444   [[ ${flags_error} = 'help requested'    ]] && exit 0
01445   [[ ${flags_error} = 'version requested' ]] && exit 0
01446   return ${flags_return}
01447 }
01448 
01449 # ----------------------------------------------------------------------------
01450 # getopt information
01451 # ----------------------------------------------------------------------------
01452 
01453 ##############################################################################
01454 # This is a helper function for determining the 'getopt' version for platforms
01455 # where the detection isn't working. It simply outputs debug information that
01456 # can be included in a bug report.
01457 #
01458 # Args:
01459 #   none
01460 # Output:
01461 #   debug info that can be included in a bug report
01462 # Returns:
01463 #   nothing
01464 flags_getoptInfo()
01465 {
01466   # platform info
01467   _flags_debug "uname -a: `uname -a`"
01468   _flags_debug "PATH: ${PATH}"
01469 
01470   # shell info
01471   if [ -n "${BASH_VERSION:-}" ]; then
01472     _flags_debug 'shell: bash'
01473     _flags_debug "BASH_VERSION: ${BASH_VERSION}"
01474   elif [ -n "${ZSH_VERSION:-}" ]; then
01475     _flags_debug 'shell: zsh'
01476     _flags_debug "ZSH_VERSION: ${ZSH_VERSION}"
01477   fi
01478 
01479   # getopt info
01480   ${FLAGS_GETOPT_CMD} >/dev/null
01481   _flags_getoptReturn=$?
01482   _flags_debug "getopt return: ${_flags_getoptReturn}"
01483   _flags_debug "getopt --version: `${FLAGS_GETOPT_CMD} --version 2>&1`"
01484 
01485   unset _flags_getoptReturn
01486 }
01487 
01488 ##############################################################################
01489 # Returns whether the detected getopt version is the enhanced version.
01490 #
01491 # Args:
01492 #   none
01493 # Output:
01494 #   none
01495 # Returns:
01496 #   bool: true if getopt is the enhanced version
01497 flags_getoptIsEnh()
01498 {
01499   test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH}
01500 }
01501 
01502 ##############################################################################
01503 # Returns whether the detected getopt version is the standard version.
01504 #
01505 # Args:
01506 #   none
01507 # Returns:
01508 #   bool: true if getopt is the standard version
01509 flags_getoptIsStd()
01510 {
01511   test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD}
01512 }
01513 
01514 # ----------------------------------------------------------------------------
01515 # help and usage information
01516 # ----------------------------------------------------------------------------
01517 
01518 ##############################################################################
01519 # Prints usage as in synopsis section of man pages.
01520 flags_usage()
01521 {
01522   flags_requiredFlags_=' '
01523   flags_optionalFlags_=' '
01524   for flags_name_ in ${__flags_longNames}; do
01525     flags_usName_=`_flags_underscoreName ${flags_name_}`
01526     flags_category_=`_flags_getFlagInfo "${flags_usName_}" ${__FLAGS_INFO_CATEGORY}`
01527     if [ "${flags_category_}" = 'required' ]; then
01528       flags_requiredFlags_="${flags_requiredFlags_}${flags_name_} "
01529     elif [ "${flags_category_}" != 'help' ]; then
01530       flags_optionalFlags_="${flags_optionalFlags_}${flags_name_} "
01531     fi
01532   done
01533 
01534   flags_command_=${HELP_COMMAND:-${0##*/}}       # actual command name (constant)
01535   flags_executable_="${FLAGS_PARENT:-${0##*/}}"  # name of executable (may differ)
01536 
01537   flags_usage_=''
01538   if [ -n "${flags_optionalFlags_}" ]; then
01539     for flags_name_ in ${flags_optionalFlags_}; do
01540       flags_usage_="${flags_usage_} [`_flags_flagusage ${flags_name_}`]"
01541     done
01542   fi
01543   if [ -n "${flags_requiredFlags_}" ]; then
01544     for flags_name_ in ${flags_requiredFlags_}; do
01545       flags_usage_="${flags_usage_} `_flags_flagusage ${flags_name_}`"
01546     done
01547   fi
01548   flags_usage_="${flags_usage_} [args]"
01549 
01550   echo "NAME"
01551   # use first sentence of description as brief description similar to Doxygen
01552   if [ -n "${HELP_DESCRIPTION}" ]; then
01553     flags_brief_=${HELP_DESCRIPTION%%.*}
01554     flags_brief_="$(echo "${flags_brief_}"|sed 's/^\ *//g;s/\ *$//g'|tr '\n' ' ')"
01555     flags_brief_="     ${flags_command_} -- ${flags_brief_}"
01556     flags_columns_=`_flags_columns`
01557     flags_columns_=`expr -- "${flags_columns_}" - 3`
01558     if [ `expr -- "${flags_brief_}" : '.*'` -gt ${flags_columns_} ]; then
01559       flags_brief_="${flags_brief_:0:${flags_columns_}}"
01560       flags_brief_="${flags_brief_% *}..."
01561     fi
01562     echo "${flags_brief_}"
01563   else
01564     echo "     ${flags_command_}"
01565   fi
01566   echo
01567   echo "SYNOPSIS"
01568   # note: the silliness with the x's is purely for ksh93 on Ubuntu 6.06
01569   # because it doesn't like empty strings when used in this manner.
01570   flags_emptyStr_="`echo \"x${flags_executable_}x\" \
01571       |awk '{printf "%"length($0)+3"s", ""}'`"
01572   flags_emptyStrLen_=`expr -- "${flags_emptyStr_}" : '.*'`
01573   flags_usage_="$(echo "${flags_emptyStr_}${flags_usage_}" | fmt -l 0 -$(_flags_columns))"
01574   flags_usage_="     ${flags_executable_}${flags_usage_:${flags_emptyStrLen_}}"
01575   echo "${flags_usage_}"
01576 
01577   unset flags_name_ flags_command_ flags_usage_ flags_brief_ flags_usName_ \
01578       flags_executable_ flags_type_ flags_optionalFlags_ flags_requiredFlags_ \
01579       flags_standardFlags_ flags_emptyStr_ flags_emptyStrLen_ flags_columns_
01580 
01581   return ${FLAGS_TRUE}
01582 }
01583 
01584 ##############################################################################
01585 # Print help for named flag.
01586 #
01587 # Args:
01588 #   flags_name_: string: long name of flag
01589 #   flags_maxNameLen: integer: (optional) maximum length of long flag names
01590 #                              used to align help texts (default: 0)
01591 #   flags_showDefault: boolean: (optional) whether to display default value (default: true)
01592 # Returns:
01593 #   integer: success of operation (always returns true)
01594 flags_helpflag()
01595 {
01596   flags_name_=$1
01597   flags_maxNameLen=${2:-0}
01598   flags_showDefault_=${3:-${FLAGS_TRUE}}
01599   flags_flagStr_=''
01600   flags_boolStr_=''
01601   flags_usName_=`_flags_underscoreName ${flags_name_}`
01602 
01603   flags_help_=`_flags_getFlagInfo \
01604       "${flags_usName_}" ${__FLAGS_INFO_HELP}`
01605   flags_short_=`_flags_getFlagInfo \
01606       "${flags_usName_}" ${__FLAGS_INFO_SHORT}`
01607   flags_type_=`_flags_getFlagInfo \
01608       "${flags_usName_}" ${__FLAGS_INFO_TYPE}`
01609   flags_category_=`_flags_getFlagInfo \
01610       "${flags_usName_}" ${__FLAGS_INFO_CATEGORY}`
01611 
01612   flags_help_=$(echo "${flags_help_}"|sed 's/^\ *//g'|tr '\n' ' ')
01613 
01614   if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} ]; then
01615     # add [no] to long boolean flag names, except the 'help' flags
01616     [ ${flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] && \
01617         flags_boolStr_='[no]'
01618     # long flag name
01619     flags_flagStr_="${flags_flagStr_}--${flags_boolStr_}${flags_name_}"
01620   fi
01621   # short flag name
01622   [ "${flags_short_}" != "${__FLAGS_NULL}" ] && \
01623       flags_flagStr_="${flags_flagStr_}, -${flags_short_}"
01624   # fill with spaces for alignment of help texts
01625   flags_flagStrLen_=`expr -- "${flags_flagStr_}" : '.*'`
01626   flags_numSpaces_=`expr -- 12 + "${flags_maxNameLen_}" - "${flags_flagStrLen_}"`
01627   [ ${flags_numSpaces_} -ge 0 ] || flags_numSpaces_=0
01628   flags_spaces_=`printf %${flags_numSpaces_}s`
01629   flags_flagStr_="${flags_flagStr_}${flags_spaces_}"
01630   # default value
01631   flags_defaultStr_="(default: `_flags_defaultStr ${flags_name_}`)"
01632   # help text
01633   flags_helpStr_="  ${flags_flagStr_}   ${flags_help_}"
01634   if [ ${flags_showDefault_} -eq ${FLAGS_TRUE} ]; then
01635     flags_helpStr_="${flags_helpStr_} ${flags_defaultStr_}"
01636   fi
01637   if [ ${flags_showDefault_} -eq ${FLAGS_TRUE} ]; then
01638     flags_helpStr_="${flags_help_} ${flags_defaultStr_}"
01639   else
01640     flags_helpStr_="${flags_help_}"
01641   fi
01642   flags_helpStrLen_=`expr -- "${flags_helpStr_}" : '.*'`
01643   flags_columns_=`_flags_columns`
01644   # note: the silliness with the x's is purely for ksh93 on Ubuntu 6.06
01645   # because it doesn't like empty strings when used in this manner.
01646   flags_emptyStr_="`echo \"x${flags_flagStr_}x\" \
01647       |awk '{printf "%"length($0)+6"s", ""}'`"
01648   flags_emptyStrLen_=`expr -- "${flags_emptyStr_}" : '.*'`
01649   # split long help text on multiple lines
01650   flags_helpStr_="$(echo "${flags_emptyStr_}${flags_helpStr_}" | fmt -l 0 -${flags_columns_})"
01651   flags_helpStr_="     ${flags_flagStr_}   ${flags_helpStr_:${flags_emptyStrLen_}}"
01652   echo "${flags_helpStr_}"
01653 
01654   unset flags_boolStr_ flags_defaultStr_ flags_emptyStr_ flags_emptyStrLen_ \
01655       flags_flagStr_ flags_help_ flags_helpStr flags_helpStrLen flags_name_ \
01656       flags_columns_ flags_short_ flags_type_ flags_usName_ flags_flagStrLen_
01657 
01658   return ${FLAGS_TRUE}
01659 }
01660 
01661 ##############################################################################
01662 # Print help of all flags.
01663 #
01664 # This function is used by flags_help() and flags_helpshort().
01665 #
01666 # Args:
01667 #   flags_helpshort_: bool: display only short help of options, leaving out
01668 #                           less important options
01669 # Returns:
01670 #   integer: success of operation (always returns true)
01671 flags_helpflags()
01672 {
01673   flags_helpshort_=${1:-${FLAGS_FALSE}}
01674 
01675   echo "OPTIONS"
01676 
01677   # reset (all) categories
01678   flags_maxNameLen_=0
01679   flags_otherFlags_=''
01680   for flags_category_ in "${__flags_categoryNames[@]}"; do
01681     flags_usCategory_=`_flags_underscoreName ${flags_category_}`
01682     eval "flags_${flags_usCategory_}Flags_=''"
01683   done
01684 
01685   # get lists of flags belonging to each category and
01686   # maximum length of long names required for alignment of help
01687   for flags_name_ in ${__flags_longNames}; do
01688     flags_usName_=`_flags_underscoreName ${flags_name_}`
01689 
01690     # update maximum length of flag name
01691     flags_nameStrLen_=`expr -- "${flags_name_}" : '.*'`
01692     # length + 4 for boolean flags because of the '[no]' prefix
01693     flags_type_=`_flags_getFlagInfo "${flags_usName_}" ${__FLAGS_INFO_TYPE}`
01694     if [ ${flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ]; then
01695       flags_nameStrLen_=`expr -- "${flags_nameStrLen}" + 4`
01696     fi
01697     if [ ${flags_nameStrLen_} -gt ${flags_maxNameLen_} ]; then
01698       flags_maxNameLen_=${flags_nameStrLen_}
01699     fi
01700 
01701     # append flag to list for its category
01702     flags_category_=`_flags_getFlagInfo "${flags_usName_}" ${__FLAGS_INFO_CATEGORY}`
01703     if [ "${flags_category_}" = "${__FLAGS_NULL}" ]; then
01704       flags_otherFlags_="${flags_otherFlags_} ${flags_name_}"
01705     else
01706       flags_usCategory_=`_flags_underscoreName ${flags_category_}`
01707       eval "flags_${flags_usCategory_}Flags_=\"\${flags_${flags_usCategory_}Flags_} ${flags_name_}\""
01708     fi
01709   done
01710 
01711   # select subset of categories to display
01712   if [ ${flags_helpshort_} -eq ${FLAGS_TRUE} ]; then
01713     flags_categories_=()
01714     for flags_category_ in "${__flags_categoryNames[@]}"; do
01715       if [ "${flags_category_}" = 'help' ]; then
01716         flags_usCategory_=`_flags_underscoreName ${flags_category_}`
01717         eval "unset flags_${flags_usCategory_}Flags_"
01718         continue
01719       fi
01720       flags_categories_[${#flags_categories_[@]}]="${flags_category_}"
01721     done
01722   else
01723     flags_categories_=("${__flags_categoryNames[@]}")
01724   fi
01725 
01726   # output help of required flags
01727   if [ -n "${flags_requiredFlags_}" ]; then
01728     echo "     The required options are as follows:"
01729     echo
01730     flags_requiredFlags_=`_flags_sortList "${flags_requiredFlags_}"`
01731     for flags_name_ in ${flags_requiredFlags_}; do
01732       flags_helpflag ${flags_name_} ${flags_maxNameLen_} ${FLAGS_FALSE}
01733     done
01734     echo
01735   fi
01736 
01737   # output help of non-required and non-help flags
01738   for flags_category_ in "${flags_categories_[@]}"; do
01739     if [ "${flags_category_}" = 'required' -o \
01740          "${flags_category_}" = 'help' ]; then
01741       continue
01742     fi
01743     flags_usCategory_=`_flags_underscoreName ${flags_category_}`
01744     eval "flags_${flags_usCategory_}Flags_=\`_flags_sortList \"\${flags_${flags_usCategory_}Flags_}\"\`"
01745     eval "flags_names_=\"\${flags_${flags_usCategory_}Flags_}\""
01746     if [ -n "${flags_names_}" ]; then
01747       echo "     The ${flags_category_} options are as follows:"
01748       echo
01749       for flags_name_ in ${flags_names_}; do
01750         flags_helpflag ${flags_name_} ${flags_maxNameLen_} ${FLAGS_TRUE}
01751       done
01752       echo
01753     fi
01754   done
01755 
01756   # output help of remaining non-help flags
01757   if [ -n "${flags_otherFlags_}" ]; then
01758     echo "     The available options are as follows:"
01759     echo
01760     flags_otherFlags_=`_flags_sortList "${flags_otherFlags_}"`
01761     for flags_name_ in ${flags_otherFlags_}; do
01762       flags_helpflag ${flags_name_} ${flags_maxNameLen_} ${FLAGS_TRUE}
01763     done
01764     echo
01765   fi
01766 
01767   # output help of help flags
01768   if [ -n "${flags_helpFlags_}" ]; then
01769     echo "     The help options are as follows:"
01770     echo
01771     for flags_name_ in ${flags_helpFlags_}; do
01772       flags_helpflag ${flags_name_} ${flags_maxNameLen_} ${FLAGS_FALSE}
01773     done
01774     echo
01775   fi
01776 
01777   # clean up
01778   for flags_category_ in "${flags_categories_[@]}"; do
01779     flags_usCategory_=`_flags_underscoreName ${flags_category_}`
01780     eval "unset flags_${flags_usCategory_}Flags_"
01781   done
01782   unset flags_maxNameLen_ flags_name_ flags_nameStrLen_ flags_type_ \
01783       flags_otherFlags flags_categories_ flags_category_ flags_usCategory_
01784  
01785   return ${FLAGS_TRUE}
01786 }
01787 
01788 ##############################################################################
01789 # This is effectively a 'usage()' function. It prints a usage information on
01790 # how to use the program and the available flags. Note this function can be
01791 # overridden so other apps can define their own short help output,
01792 # replacing this one, if they want.
01793 #
01794 # Args:
01795 #   none
01796 # Returns:
01797 #   integer: success of operation (always returns true)
01798 flags_helpshort()
01799 {
01800   # head / usage
01801   echo
01802   flags_usage
01803   echo
01804   # flags
01805   flags_helpflags ${FLAGS_TRUE}
01806  
01807   return ${FLAGS_TRUE}
01808 }
01809 
01810 ##############################################################################
01811 # This is effectively a 'help()' function. It prints a program description together
01812 # with usage information and example command-lines on how to use the program.
01813 # Note this function can be overridden so other apps can define their own help
01814 # output, replacing this one, if they want.
01815 #
01816 # Args:
01817 #  none
01818 # Returns:
01819 #   integer: success of operation (always returns true)
01820 flags_help()
01821 {
01822   # head / usage
01823   echo
01824   flags_usage
01825   # description
01826   if [ -n "${HELP_DESCRIPTION:-}" ]; then
01827     echo
01828     echo "DESCRIPTION"
01829     flags_fmtStr_=$(echo "${HELP_DESCRIPTION}"\
01830         |awk '{printf "%s:NEWLINE:",$0}'\
01831         |sed 's/^\ *:NEWLINE://g;s/:NEWLINE:\ *$//g;s/:NEWLINE:/:NEWLINE:     /g;s/:NEWLINE:/\\n/g')
01832     flags_fmtStr_="$(echo -e "     ${flags_fmtStr_}" | fmt -l 0 -$(_flags_columns))"
01833     echo "${flags_fmtStr_}"
01834   fi
01835   # flags
01836   echo
01837   flags_helpflags ${FLAGS_FALSE} # attention: unsets flags_columns_
01838   # contact
01839   if [ -n "${HELP_CONTACT:-}" ]; then
01840     echo "CONTACT"
01841     flags_fmtStr_=$(echo "${HELP_CONTACT}"\
01842         |awk '{printf "%s:NEWLINE:",$0}'\
01843         |sed 's/^\ *:NEWLINE://g;s/:NEWLINE:$//g;s/:NEWLINE:/:NEWLINE:     /g;s/:NEWLINE:/\\n/g')
01844     flags_fmtStr_="$(echo "     ${flags_fmtStr_}" | fmt -l 0 -$(_flags_columns))"
01845     echo "${flags_fmtStr_}"
01846     echo
01847   fi
01848  
01849   unset flags_fmtStr_
01850 
01851   return ${FLAGS_TRUE}
01852 }
01853 
01854 # ----------------------------------------------------------------------------
01855 # XML help
01856 # ----------------------------------------------------------------------------
01857 
01858 ##############################################################################
01859 # This function outputs the help of named flag in XML format
01860 #
01861 # Args:
01862 #   flags_name_: string: long name of flag
01863 #   indentation: integer: (optional) indentation
01864 # Returns:
01865 #   integer: success of operation (always returns true)
01866 flags_helpflagxml()
01867 {
01868   # get flag attributes
01869   flags_name_=$1
01870   flags_indentation_=${2:-0}
01871   flags_usName_=`_flags_underscoreName ${flags_name_}`
01872 
01873   flags_help_=`_flags_getFlagInfo \
01874       "${flags_usName_}" ${__FLAGS_INFO_HELP}`
01875   flags_short_=`_flags_getFlagInfo \
01876       "${flags_usName_}" ${__FLAGS_INFO_SHORT}`
01877   flags_type_=`_flags_getFlagInfo \
01878       "${flags_usName_}" ${__FLAGS_INFO_TYPE}`
01879   flags_category_=`_flags_getFlagInfo \
01880       "${flags_usName_}" ${__FLAGS_INFO_CATEGORY}`
01881 
01882   # re-format strings
01883   flags_help_=$(echo "${flags_help_}"|sed 's/^\ *//g'|tr '\n' ' '|sed 's/^\ *//g;s/\ *$//g')
01884 
01885   [ "${flags_short_}"    = "${__FLAGS_NULL}" ] && flags_short_=''
01886   [ "${flags_category_}" = "${__FLAGS_NULL}" ] && flags_category_=''
01887 
01888   # current and default value
01889   flags_current_=`_flags_currentStr ${flags_usName_}`
01890   flags_default_=`_flags_defaultStr ${flags_usName_}`
01891 
01892   # convert type
01893   flags_type_=`_flags_typeStr ${flags_type_}`
01894 
01895   # xml-escape values
01896   flags_short_=`_flags_xmlText "${flags_short_}"`
01897   flags_category_=`_flags_xmlText "${flags_category_}"`
01898   flags_help_=`_flags_xmlText "${flags_help_}"`
01899   flags_current_=`_flags_xmlText "${flags_current_}"`
01900   flags_default_=`_flags_xmlText "${flags_default_}"`
01901   flags_type_=`_flags_xmlText "${flags_type_}"`
01902 
01903   # indentation
01904   flags_emptyStr_=`printf %${flags_indentation_}s`
01905 
01906   # output XML tags
01907   echo "${flags_emptyStr_}<flag>"
01908   echo "${flags_emptyStr_}    <category>${flags_category_}</category>"
01909   echo "${flags_emptyStr_}    <name>${flags_name_}</name>"
01910   echo "${flags_emptyStr_}    <short_name>${flags_short_}</short_name>"
01911   echo "${flags_emptyStr_}    <meaning>${flags_help_}</meaning>"
01912   echo "${flags_emptyStr_}    <default>${flags_default_}</default>"
01913   echo "${flags_emptyStr_}    <current>${flags_current_}</current>"
01914   echo "${flags_emptyStr_}    <type>${flags_type_}</type>"
01915   echo "${flags_emptyStr_}</flag>"
01916 
01917   unset flags_current_ flags_default_ flags_name_ flags_usName_ \
01918       flags_short_ flags_type_ flags_help_ flags_indentation_ \
01919       flags_emptyStr_
01920 }
01921 
01922 ##############################################################################
01923 # This function outputs the help in XML format.
01924 #
01925 # Args:
01926 #   none
01927 # Returns:
01928 #   integer: success of operation (always returns true)
01929 flags_helpxml()
01930 {
01931   # get (re-formated) help strings
01932   flags_executable_=${FLAGS_PARENT:-${0##*/}}
01933   flags_command_=${HELP_COMMAND:-${flags_executable_}}
01934   flags_version_=${HELP_VERSION:-'unknown'}
01935   flags_copyright_=$(echo "${HELP_COPYRIGHT}"\
01936         |awk '{printf "%s:NEWLINE:",$0}'\
01937         |sed 's/^\ *:NEWLINE://g;s/:NEWLINE:\ *$//g;s/:NEWLINE:/\\n/g')
01938   flags_contact_=$(echo "${HELP_CONTACT}"\
01939         |awk '{printf "%s:NEWLINE:",$0}'\
01940         |sed 's/^\ *:NEWLINE://g;s/:NEWLINE:$//g;s/:NEWLINE:/\\n/g')
01941   flags_description_=$(echo "${HELP_DESCRIPTION}"\
01942         |awk '{printf "%s:NEWLINE:",$0}'\
01943         |sed 's/^\ *:NEWLINE://g;s/:NEWLINE:\ *$//g;s/:NEWLINE:/\\n/g')
01944 
01945   # xml-escape values
01946   flags_executable_=`_flags_xmlText "${flags_executable_}"`
01947   flags_command_=`_flags_xmlText "${flags_command_}"`
01948   flags_version_=`_flags_xmlText "${flags_version_}"`
01949   flags_copyright_=`_flags_xmlText "${flags_copyright_}"`
01950   flags_contact_=`_flags_xmlText "${flags_contact_}"`
01951   flags_description_=`_flags_xmlText "${flags_description_}"`
01952 
01953   # output XML tags
01954   echo "<?xml version=\"1.0\"?>"
01955   echo "<AllFlags>"
01956   echo "  <name>${flags_command_}</name>"
01957   echo "  <program>${flags_executable_}</program>"
01958   echo "  <version>${flags_version_}</version>"
01959   echo "  <copyright>${flags_copyright_}</copyright>"
01960   echo "  <contact>${flags_contact_}</contact>"
01961   echo "  <usage>${flags_description_}</usage>"
01962   for flags_name_ in ${__flags_longNames}; do
01963     flags_helpflagxml ${flags_name_} 2
01964   done
01965   echo "</AllFlags>"
01966 
01967   # clean up
01968   unset flags_executable_ flags_command_ flags_version_ \
01969       flags_name_ flags_description_ flags_copyright_ flags_contact_
01970 
01971   return ${FLAGS_TRUE}
01972 }
01973 
01974 # ----------------------------------------------------------------------------
01975 # man page
01976 # ----------------------------------------------------------------------------
01977 
01978 ##############################################################################
01979 # Prints NAME section of man page.
01980 flags_helpman_name()
01981 {
01982   flags_command_=${HELP_COMMAND:-${0##*/}}
01983   flags_command_=`_flags_manText "${flags_command_}"`
01984 
01985   echo ".SH NAME"
01986   # use first sentence of description as brief description similar to Doxygen
01987   if [ -n "${HELP_DESCRIPTION}" ]; then
01988     flags_brief_=${HELP_DESCRIPTION%%.*}
01989     flags_brief_="$(echo "${flags_brief_}"|sed 's/^\ *//g;s/\ *$//g'|tr '\n' ' ')"
01990     flags_brief_="${flags_command_} -- ${flags_brief_}"
01991     flags_columns_=`_flags_columns`
01992     flags_columns_=`expr -- "${flags_columns_}" - 24`
01993     [ ${flags_columns_} -lt 80 ] && flags_columns_=80
01994     if [ `expr -- "${flags_brief_}" : '.*'` -gt ${flags_columns_} ]; then
01995       flags_brief_="${flags_brief_:0:${flags_columns_}}"
01996       flags_brief_="${flags_brief_% *}..."
01997     fi
01998     flags_brief_=`_flags_manText "${flags_brief_}"`
01999     echo "${flags_brief_}"
02000   else
02001     echo "${flags_command_}"
02002   fi
02003 
02004   unset flags_command_ flags_brief_ flags_columns_
02005 
02006   return ${FLAGS_TRUE}
02007 }
02008 
02009 ##############################################################################
02010 # Prints SYNOPSIS section of man page.
02011 flags_helpman_synopsis()
02012 {
02013   flags_executable_="${FLAGS_PARENT:-${0##*/}}"
02014 
02015   echo ".SH SYNOPSIS"
02016   echo "\fB${flags_executable_}\fR"
02017 
02018   flags_requiredFlags_=' '
02019   flags_optionalFlags_=' '
02020   for flags_name_ in ${__flags_longNames}; do
02021     flags_usName_=`_flags_underscoreName ${flags_name_}`
02022     flags_category_=`_flags_getFlagInfo "${flags_usName_}" ${__FLAGS_INFO_CATEGORY}`
02023     if [ "${flags_category_}" = 'required' ]; then
02024       flags_requiredFlags_="${flags_requiredFlags_}${flags_name_} "
02025     elif [ "${flags_category_}" != 'help' ]; then
02026       flags_optionalFlags_="${flags_optionalFlags_}${flags_name_} "
02027     fi
02028   done
02029 
02030   flags_requiredFlags_=`_flags_sortList "${flags_requiredFlags_}"`
02031   flags_optionalFlags_=`_flags_sortList "${flags_optionalFlags_}"`
02032 
02033   if [ -n "${flags_optionalFlags_}" ]; then
02034     for flags_name_ in ${flags_optionalFlags_}; do
02035       echo "[\fB`_flags_helpman_flagusage ${flags_name_}`\fR]"
02036     done
02037   fi
02038   if [ -n "${flags_requiredFlags_}" ]; then
02039     for flags_name_ in ${flags_requiredFlags_}; do
02040       echo "\fB`_flags_helpman_flagusage ${flags_name_}`\fR"
02041     done
02042   fi
02043   echo "[args]"
02044 
02045   unset flags_executable_ flags_name_ flags_usName_ flags_type_ \
02046       flags_optionalFlags_ flags_requiredFlags_
02047 
02048   return ${FLAGS_TRUE}
02049 }
02050 
02051 ##############################################################################
02052 # Prints DESCRIPTION section of man page.
02053 flags_helpman_description()
02054 {
02055   if [ -n "${HELP_DESCRIPTION}" ]; then
02056     echo ".SH DESCRIPTION"
02057     flags_description_="${HELP_DESCRIPTION:-'No description available.'}"
02058     flags_description_=`_flags_manText "${flags_description_}"`
02059     echo "${flags_description_}"
02060 
02061     unset flags_description_
02062   fi
02063 }
02064 
02065 ##############################################################################
02066 # Prints OPTIONS section entry of man page of named flag.
02067 flags_helpman_flag()
02068 {
02069   flags_name_=$1
02070   flags_showDefault_=${2:-${FLAGS_TRUE}}
02071   flags_flagStr_=''
02072   flags_boolStr_=''
02073   flags_usName_=`_flags_underscoreName ${flags_name_}`
02074 
02075   _flags_getFlagDefault "${flags_usName_}" 'flags_default_'
02076   flags_help_=`_flags_getFlagInfo \
02077       "${flags_usName_}" ${__FLAGS_INFO_HELP}`
02078   flags_short_=`_flags_getFlagInfo \
02079       "${flags_usName_}" ${__FLAGS_INFO_SHORT}`
02080   flags_type_=`_flags_getFlagInfo \
02081       "${flags_usName_}" ${__FLAGS_INFO_TYPE}`
02082   flags_category_=`_flags_getFlagInfo \
02083       "${flags_usName_}" ${__FLAGS_INFO_CATEGORY}`
02084 
02085   flags_help_=$(echo "${flags_help_}"|sed 's/^\ *//g'|tr '\n' ' ')
02086 
02087   # adjust type ID for multi-flags
02088   if [ ${flags_type_} -gt 128 ]; then
02089     flags_type_=`expr "${flags_type_}" - 128`
02090   fi
02091   # flag name
02092   if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} ]; then
02093     # add [no] to long boolean flag names, except the 'help' flags
02094     [ ${flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] && \
02095         flags_boolStr_='[no]'
02096     # long flag name
02097     flags_flagStr_="\fB${flags_flagStr_}--${flags_boolStr_}${flags_name_}"
02098   fi
02099   [ "${flags_short_}" != "${__FLAGS_NULL}" ] && \
02100       # short flag name
02101       flags_flagStr_="${flags_flagStr_}, -${flags_short_}"
02102   flags_flagStr_="${flags_flagStr_}\fR"
02103   # argument
02104   if [ ${flags_type_} -ne ${__FLAGS_TYPE_BOOLEAN} ]; then
02105     flags_flagStr_="${flags_flagStr_} \fI`_flags_typeStr ${flags_type_}`\fR"
02106   fi
02107   # default value
02108   if [ ${flags_showDefault_} -eq ${FLAGS_TRUE} ]; then
02109     flags_defaultStr_=`_flags_defaultStr "${flags_usName_}"`
02110     flags_defaultStr_=" (default:\ ${flags_defaultStr_//\ /\\ })"
02111   else
02112     flags_defaultStr_=''
02113   fi
02114 
02115   echo ".TP 8"
02116   echo "${flags_flagStr_}"
02117   echo "${flags_help_}${flags_defaultStr_}"
02118 
02119   unset flags_boolStr_ flags_default_ flags_defaultStr_ flags_emptyStr_ flags_emptyStrLen_ \
02120       flags_flagStr_ flags_help_ flags_helpStr flags_helpStrLen flags_name_ \
02121       flags_columns_ flags_short_ flags_type_ flags_usName_ flags_flagStrLen_
02122 
02123   return ${FLAGS_TRUE}
02124 }
02125 
02126 ##############################################################################
02127 # Prints OPTIONS section of man page.
02128 flags_helpman_flags()
02129 {
02130   echo ".SH OPTIONS"
02131   # get lists of flags belonging to same category
02132   flags_otherFlags_=''
02133   for flags_category_ in "${__flags_categoryNames[@]}"; do
02134     flags_usCategory_=`_flags_underscoreName ${flags_category_}`
02135     eval "flags_${flags_usCategory_}Flags_=''"
02136   done
02137   for flags_name_ in ${__flags_longNames}; do
02138     flags_nameStrLen_=`expr -- "${flags_name_}" : '.*'`
02139     flags_usName_=`_flags_underscoreName ${flags_name_}`
02140     flags_category_=`_flags_getFlagInfo "${flags_usName_}" ${__FLAGS_INFO_CATEGORY}`
02141     if [ "${flags_category_}" = "${__FLAGS_NULL}" ]; then
02142       flags_otherFlags_="${flags_otherFlags_} ${flags_name_}"
02143     else
02144       flags_usCategory_=`_flags_underscoreName ${flags_category_}`
02145       eval "flags_${flags_usCategory_}Flags_=\"\${flags_${flags_usCategory_}Flags_} ${flags_name_}\""
02146     fi
02147   done
02148   # output help of required flags
02149   if [ -n "${flags_requiredFlags_}" ]; then
02150     echo ".P"
02151     echo "\fBThe required options are as follows:\fR"
02152     flags_requiredFlags_=`_flags_sortList "${flags_requiredFlags_}"`
02153     for flags_name_ in ${flags_requiredFlags_}; do
02154       flags_helpman_flag ${flags_name_} ${FLAGS_FALSE}
02155     done
02156   fi
02157   # output help of non-required and non-help flags
02158   for flags_category_ in "${__flags_categoryNames[@]}"; do
02159     if [ "${flags_category_}" = 'required' -o \
02160          "${flags_category_}" = 'help' ]; then
02161       continue
02162     fi
02163     flags_usCategory_=`_flags_underscoreName ${flags_category_}`
02164     eval "flags_${flags_usCategory_}Flags_=\`_flags_sortList \"\${flags_${flags_usCategory_}Flags_}\"\`"
02165     eval "flags_names_=\"\${flags_${flags_usCategory_}Flags_}\""
02166     if [ -n "${flags_names_}" ]; then
02167       echo ".P"
02168       echo "\fBThe ${flags_category_} options are as follows:\fR"
02169       for flags_name_ in ${flags_names_}; do
02170         flags_helpman_flag ${flags_name_}
02171       done
02172     fi
02173   done
02174   # output help of remaining non-help flags
02175   if [ -n "${flags_otherFlags_}" ]; then
02176     echo ".P"
02177     echo "\fBThe available options are as follows:\fR"
02178     flags_otherFlags_=`_flags_sortList "${flags_otherFlags_}"`
02179     for flags_name_ in ${flags_otherFlags_}; do
02180       flags_helpman_flag ${flags_name_}
02181     done
02182   fi
02183   # output help of help flags
02184   if [ -n "${flags_helpFlags_}" ]; then
02185     echo ".P"
02186     echo "\fBThe help options are as follows:\fR"
02187     for flags_name_ in ${flags_helpFlags_}; do
02188       flags_helpman_flag ${flags_name_} ${FLAGS_FALSE}
02189     done
02190   fi
02191 
02192   # clean up
02193   for flags_category_ in "${__flags_categoryNames[@]}"; do
02194     flags_usCategory_=`_flags_underscoreName ${flags_category_}`
02195     eval "unset flags_${flags_usCategory_}Flags_"
02196   done
02197   unset flags_maxNameLen_ flags_name_ flags_nameStrLen_ flags_type_ \
02198       flags_otherFlags flags_category_ flags_usCategory_
02199 }
02200 
02201 ##############################################################################
02202 # Prints COPYRIGHT section of man page.
02203 flags_helpman_copyright()
02204 {
02205   if [ -n "${HELP_COPYRIGHT}" ]; then
02206     echo ".SH COPYRIGHT"
02207     flags_copyright_="${HELP_COPYRIGHT}"
02208     flags_copyright_=`echo "${flags_copyright_}"|awk '{printf "%s\n.br\n",$0}'`
02209     flags_copyright_=`_flags_manText "${flags_copyright_}"`
02210     echo "${flags_copyright_}"
02211 
02212     unset flags_copyright_
02213   fi
02214 }
02215 
02216 ##############################################################################
02217 # Prints CONTACT section of man page.
02218 flags_helpman_contact()
02219 {
02220   if [ -n "${HELP_CONTACT}" ]; then
02221     echo ".SH CONTACT"
02222     flags_contact_="${HELP_CONTACT}"
02223     flags_contact_=`_flags_manText "${flags_contact_}"`
02224     echo "${flags_contact_}"
02225 
02226     unset flags_contact_
02227   fi
02228 }
02229 
02230 ##############################################################################
02231 # This function outputs the help in man page format.
02232 #
02233 # Args:
02234 #   none
02235 # Returns:
02236 #   integer: success of operation (always returns true)
02237 flags_helpman()
02238 {
02239   flags_command_=${FLAGS_PARENT:-${0##*/}}
02240   flags_command_=`_flags_manText "${flags_command_}"`
02241 
02242   echo ".TH \"${flags_command_}\" 1 `date '+%e\ %B\ %G'`"
02243   flags_helpman_name
02244   flags_helpman_synopsis
02245   flags_helpman_description
02246   flags_helpman_flags
02247   flags_helpman_copyright
02248   flags_helpman_contact
02249 
02250   unset flags_command_
02251 
02252   return ${FLAGS_TRUE}
02253 }
02254 
02255 # ----------------------------------------------------------------------------
02256 # version information
02257 # ----------------------------------------------------------------------------
02258 
02259 ##############################################################################
02260 # This function outputs the version and copyright.
02261 #
02262 # Args:
02263 #   none
02264 # Returns:
02265 #   integer: success of operation (always returns true)
02266 flags_version()
02267 {
02268   flags_command_=${HELP_COMMAND:-$0##*/}
02269   flags_version_=${HELP_VERSION:-'unknown'}
02270   echo "${flags_command_} version ${flags_version_}"
02271   if [ -n "${HELP_COPYRIGHT}" ]; then
02272     flags_copyright_=$(echo "${HELP_COPYRIGHT}"\
02273         |awk '{printf "%s:NEWLINE:",$0}'\
02274         |sed 's/^\ *:NEWLINE://g;s/:NEWLINE:\ *$//g;s/:NEWLINE:/\\n/g')
02275     echo -e "${flags_copyright_}"
02276   fi
02277   unset flags_command_ flags_version_ flags_copyright_
02278 }
02279 
02280 # ----------------------------------------------------------------------------
02281 # reset
02282 # ----------------------------------------------------------------------------
02283 
02284 ##############################################################################
02285 # Reset shflags back to an uninitialized state.
02286 #
02287 # Args:
02288 #   none
02289 # Returns:
02290 #   nothing
02291 flags_reset()
02292 {
02293   for flags_name_ in ${__flags_longNames}; do
02294     flags_usName_=`_flags_underscoreName ${flags_name_}`
02295     flags_strToEval_="unset FLAGS_${flags_usName_}"
02296     for flags_type_ in \
02297         ${__FLAGS_INFO_DEFAULT} \
02298         ${__FLAGS_INFO_HELP} \
02299         ${__FLAGS_INFO_SHORT} \
02300         ${__FLAGS_INFO_TYPE} \
02301         ${__FLAGS_INFO_CATEGORY}
02302     do
02303       flags_strToEval_=\
02304 "${flags_strToEval_} __flags_${flags_usName_}_${flags_type_}"
02305     done
02306     eval ${flags_strToEval_}
02307   done
02308 
02309   # reset internal variables
02310   __flags_boolNames=' '
02311   __flags_longNames=' '
02312   __flags_shortNames=' '
02313   __flags_definedNames=' '
02314   __flags_categoryNames=' '
02315 
02316   unset flags_name_ flags_type_ flags_strToEval_ flags_usName_
02317 }