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/\&/\&/g;s/</\</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 }