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