diff options
Diffstat (limited to 'sntp/libopts/usage.c')
-rw-r--r-- | sntp/libopts/usage.c | 643 |
1 files changed, 400 insertions, 243 deletions
diff --git a/sntp/libopts/usage.c b/sntp/libopts/usage.c index 960339b63cbc..4d106675c304 100644 --- a/sntp/libopts/usage.c +++ b/sntp/libopts/usage.c @@ -1,7 +1,8 @@ /* - * usage.c $Id: usage.c,v 4.15 2007/04/28 22:19:23 bkorb Exp $ - * Time-stamp: "2007-04-15 11:02:46 bkorb" + * \file usage.c + * + * Time-stamp: "2011-02-01 14:42:37 bkorb" * * This module implements the default usage procedure for * Automated Options. It may be overridden, of course. @@ -13,117 +14,183 @@ */ /* - * Automated Options copyright 1992-2007 Bruce Korb - * - * Automated Options is free software. - * You may redistribute it and/or modify it under the terms of the - * GNU General Public License, as published by the Free Software - * Foundation; either version 2, or (at your option) any later version. - * - * Automated Options is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This file is part of AutoOpts, a companion to AutoGen. + * AutoOpts is free software. + * AutoOpts is Copyright (c) 1992-2011 by Bruce Korb - all rights reserved * - * You should have received a copy of the GNU General Public License - * along with Automated Options. See the file "COPYING". If not, - * write to: The Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. + * AutoOpts is available under any one of two licenses. The license + * in use must be one of these two and the choice is under the control + * of the user of the license. * - * As a special exception, Bruce Korb gives permission for additional - * uses of the text contained in his release of AutoOpts. + * The GNU Lesser General Public License, version 3 or later + * See the files "COPYING.lgplv3" and "COPYING.gplv3" * - * The exception is that, if you link the AutoOpts library with other - * files to produce an executable, this does not by itself cause the - * resulting executable to be covered by the GNU General Public License. - * Your use of that executable is in no way restricted on account of - * linking the AutoOpts library code into it. + * The Modified Berkeley Software Distribution License + * See the file "COPYING.mbsd" * - * This exception does not however invalidate any other reasons why - * the executable file might be covered by the GNU General Public License. + * These files have the following md5sums: * - * This exception applies only to the code released by Bruce Korb under - * the name AutoOpts. If you copy code from other sources under the - * General Public License into a copy of AutoOpts, as the General Public - * License permits, the exception does not apply to the code that you add - * in this way. To avoid misleading anyone as to the status of such - * modified files, you must delete this exception notice from them. - * - * If you write modifications of your own for AutoOpts, it is your choice - * whether to permit this exception to apply to your modifications. - * If you do not wish that, delete this exception notice. + * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3 + * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3 + * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd */ #define OPTPROC_L_N_S (OPTPROC_LONGOPT | OPTPROC_SHORTOPT) -static arg_types_t argTypes; +/* = = = START-STATIC-FORWARD = = = */ +static void +set_usage_flags(tOptions * opts, char const * flg_txt); + +static inline ag_bool +do_gnu_usage(tOptions * pOpts); -FILE* option_usage_fp = NULL; -static char zOptFmtLine[ 16 ]; -static ag_bool displayEnum; +static inline ag_bool +skip_misuse_usage(tOptions * pOpts); -/* = = = START-STATIC-FORWARD = = = */ -/* static forward declarations maintained by :mkfwd */ -static ag_bool -checkGNUUsage( tOptions* pOpts ); +static void +print_usage_details(tOptions * opts, int exit_code); + +static void +prt_extd_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT); static void -printExtendedUsage( - tOptions* pOptions, - tOptDesc* pOD, - arg_types_t* pAT ); +prt_ini_list(char const * const * papz, ag_bool * pInitIntro, + char const * pzRc, char const * pzPN); static void -printInitList( - tCC* const* papz, - ag_bool* pInitIntro, - tCC* pzRc, - tCC* pzPN ); +prt_preamble(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT); static void -printOneUsage( - tOptions* pOptions, - tOptDesc* pOD, - arg_types_t* pAT ); +prt_one_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT); static void -printOptionUsage( - tOptions* pOpts, - int ex_code, - tCC* pOptTitle ); +prt_opt_usage(tOptions * pOpts, int ex_code, char const * pOptTitle); static void -printProgramDetails( tOptions* pOptions ); +prt_prog_detail(tOptions* pOptions); static int -setGnuOptFmts( tOptions* pOpts, tCC** ppT ); +setGnuOptFmts(tOptions* pOpts, tCC** ppT); static int -setStdOptFmts( tOptions* pOpts, tCC** ppT ); +setStdOptFmts(tOptions* pOpts, tCC** ppT); /* = = = END-STATIC-FORWARD = = = */ - /* - * Figure out if we should try to format usage text sort-of like - * the way many GNU programs do. + * NB: no entry may be a prefix of another entry */ -static ag_bool -checkGNUUsage( tOptions* pOpts ) +#define AOFLAG_TABLE \ + _aof_(gnu, OPTPROC_GNUUSAGE ) \ + _aof_(autoopts, ~OPTPROC_GNUUSAGE) \ + _aof_(no_misuse_usage, OPTPROC_MISUSE ) \ + _aof_(misuse_usage, ~OPTPROC_MISUSE ) + +static void +set_usage_flags(tOptions * opts, char const * flg_txt) { - char* pz = getenv( "AUTOOPTS_USAGE" ); - if (pz == NULL) - ; + typedef struct { + size_t fnm_len; + uint32_t fnm_mask; + char const * fnm_name; + } ao_flag_names_t; + +# define _aof_(_n, _f) AOUF_ ## _n ## _ID, + typedef enum { AOFLAG_TABLE AOUF_COUNT } ao_flag_id_t; +# undef _aof_ + +# define _aof_(_n, _f) AOUF_ ## _n = (1 << AOUF_ ## _n ## _ID), + typedef enum { AOFLAG_TABLE } ao_flags_t; +# undef _aof_ + +# define _aof_(_n, _f) { sizeof(#_n)-1, _f, #_n }, + static ao_flag_names_t const fn_table[AOUF_COUNT] = { + AOFLAG_TABLE + }; +# undef _aof_ + + ao_flags_t flg = 0; + + if (flg_txt == NULL) { + flg_txt = getenv("AUTOOPTS_USAGE"); + if (flg_txt == NULL) + return; + } - else if (streqvcmp( pz, "gnu" ) == 0) - pOpts->fOptSet |= OPTPROC_GNUUSAGE; + while (IS_WHITESPACE_CHAR(*flg_txt)) flg_txt++; + if (*flg_txt == NUL) + return; - else if (streqvcmp( pz, "autoopts" ) == 0) - pOpts->fOptSet &= ~OPTPROC_GNUUSAGE; + for (;;) { + int ix = 0; + ao_flag_names_t const * fnt = fn_table; + + for (;;) { + if (strneqvcmp(flg_txt, fnt->fnm_name, fnt->fnm_len) == 0) + break; + if (++ix >= AOUF_COUNT) + return; + fnt++; + } + /* + * Make sure we have a full match. Look for whitespace, + * a comma, or a NUL byte. + */ + if (! IS_END_LIST_ENTRY_CHAR(flg_txt[fnt->fnm_len])) + return; + + flg |= 1 << ix; + flg_txt += fnt->fnm_len; + while (IS_WHITESPACE_CHAR(*flg_txt)) flg_txt++; + + if (*flg_txt == NUL) + break; + + if (*flg_txt == ',') { + /* + * skip the comma and following white space + */ + while (IS_WHITESPACE_CHAR(*++flg_txt)) ; + if (*flg_txt == NUL) + break; + } + } + + { + ao_flag_names_t const * fnm = fn_table; + + while (flg != 0) { + if ((flg & 1) != 0) { + if ((fnm->fnm_mask & OPTPROC_LONGOPT) != 0) + opts->fOptSet &= fnm->fnm_mask; + else opts->fOptSet |= fnm->fnm_mask; + } + flg >>= 1; + fnm++; + } + } +} + +/* + * Figure out if we should try to format usage text sort-of like + * the way many GNU programs do. + */ +static inline ag_bool +do_gnu_usage(tOptions * pOpts) +{ return (pOpts->fOptSet & OPTPROC_GNUUSAGE) ? AG_TRUE : AG_FALSE; } +/* + * Figure out if we should try to format usage text sort-of like + * the way many GNU programs do. + */ +static inline ag_bool +skip_misuse_usage(tOptions * pOpts) +{ + return (pOpts->fOptSet & OPTPROC_MISUSE) ? AG_TRUE : AG_FALSE; +} + /*=export_func optionOnlyUsage * @@ -137,23 +204,107 @@ checkGNUUsage( tOptions* pOpts ) * information not available to AutoOpts. =*/ void -optionOnlyUsage( - tOptions* pOpts, - int ex_code ) +optionOnlyUsage(tOptions * pOpts, int ex_code) { - tCC* pOptTitle = NULL; + char const * pOptTitle = NULL; + + set_usage_flags(pOpts, NULL); + if ((ex_code != EXIT_SUCCESS) && + skip_misuse_usage(pOpts)) + return; /* * Determine which header and which option formatting strings to use */ - if (checkGNUUsage(pOpts)) { - (void)setGnuOptFmts( pOpts, &pOptTitle ); + if (do_gnu_usage(pOpts)) { + (void)setGnuOptFmts(pOpts, &pOptTitle); } else { - (void)setStdOptFmts( pOpts, &pOptTitle ); + (void)setStdOptFmts(pOpts, &pOptTitle); + } + + prt_opt_usage(pOpts, ex_code, pOptTitle); + + fflush(option_usage_fp); + if (ferror(option_usage_fp) != 0) { + fputs(zOutputFail, stderr); + exit(EXIT_FAILURE); + } +} + +static void +print_usage_details(tOptions * opts, int exit_code) +{ + { + char const * pOptTitle = NULL; + + /* + * Determine which header and which option formatting strings to use + */ + if (do_gnu_usage(opts)) { + int flen = setGnuOptFmts(opts, &pOptTitle); + sprintf(zOptFmtLine, zFmtFmt, flen); + fputc('\n', option_usage_fp); + } + else { + int flen = setStdOptFmts(opts, &pOptTitle); + sprintf(zOptFmtLine, zFmtFmt, flen); + + /* + * When we exit with EXIT_SUCCESS and the first option is a doc + * option, we do *NOT* want to emit the column headers. + * Otherwise, we do. + */ + if ( (exit_code != EXIT_SUCCESS) + || ((opts->pOptDesc->fOptState & OPTST_DOCUMENT) == 0) ) + + fputs(pOptTitle, option_usage_fp); + } + + prt_opt_usage(opts, exit_code, pOptTitle); + } + + /* + * Describe the mechanics of denoting the options + */ + switch (opts->fOptSet & OPTPROC_L_N_S) { + case OPTPROC_L_N_S: fputs(zFlagOkay, option_usage_fp); break; + case OPTPROC_SHORTOPT: break; + case OPTPROC_LONGOPT: fputs(zNoFlags, option_usage_fp); break; + case 0: fputs(zOptsOnly, option_usage_fp); break; } - printOptionUsage( pOpts, ex_code, pOptTitle ); + if ((opts->fOptSet & OPTPROC_NUM_OPT) != 0) + fputs(zNumberOpt, option_usage_fp); + + if ((opts->fOptSet & OPTPROC_REORDER) != 0) + fputs(zReorder, option_usage_fp); + + if (opts->pzExplain != NULL) + fputs(opts->pzExplain, option_usage_fp); + + /* + * IF the user is asking for help (thus exiting with SUCCESS), + * THEN see what additional information we can provide. + */ + if (exit_code == EXIT_SUCCESS) + prt_prog_detail(opts); + + /* + * Give bug notification preference to the packager information + */ + if (HAS_pzPkgDataDir(opts) && (opts->pzPackager != NULL)) + fputs(opts->pzPackager, option_usage_fp); + + else if (opts->pzBugAddr != NULL) + fprintf(option_usage_fp, zPlsSendBugs, opts->pzBugAddr); + + fflush(option_usage_fp); + + if (ferror(option_usage_fp) != 0) { + fputs(zOutputFail, stderr); + exit(EXIT_FAILURE); + } } @@ -174,11 +325,9 @@ optionOnlyUsage( * and the actual exit code will be "EXIT_SUCCESS". =*/ void -optionUsage( - tOptions* pOptions, - int usage_exit_code ) +optionUsage(tOptions * pOptions, int usage_exit_code) { - int actual_exit_code = + int exit_code = (usage_exit_code == EX_USAGE) ? EXIT_SUCCESS : usage_exit_code; displayEnum = AG_FALSE; @@ -187,74 +336,42 @@ optionUsage( * Paged usage will preset option_usage_fp to an output file. * If it hasn't already been set, then set it to standard output * on successful exit (help was requested), otherwise error out. + * + * Test the version before obtaining pzFullUsage or pzShortUsage. + * These fields do not exist before revision 30. */ - if (option_usage_fp == NULL) - option_usage_fp = (actual_exit_code != EXIT_SUCCESS) ? stderr : stdout; - - fprintf( option_usage_fp, pOptions->pzUsageTitle, pOptions->pzProgName ); - { - tCC* pOptTitle = NULL; + char const * pz; - /* - * Determine which header and which option formatting strings to use - */ - if (checkGNUUsage(pOptions)) { - int flen = setGnuOptFmts( pOptions, &pOptTitle ); - sprintf( zOptFmtLine, zFmtFmt, flen ); - fputc( '\n', option_usage_fp ); - } - else { - int flen = setStdOptFmts( pOptions, &pOptTitle ); - sprintf( zOptFmtLine, zFmtFmt, flen ); + if (exit_code == EXIT_SUCCESS) { + pz = (pOptions->structVersion >= 30 * 4096) + ? pOptions->pzFullUsage : NULL; - /* - * When we exit with EXIT_SUCCESS and the first option is a doc - * option, we do *NOT* want to emit the column headers. - * Otherwise, we do. - */ - if ( (usage_exit_code != EXIT_SUCCESS) - || ((pOptions->pOptDesc->fOptState & OPTST_DOCUMENT) == 0) ) + if (option_usage_fp == NULL) + option_usage_fp = stdout; + } else { + pz = (pOptions->structVersion >= 30 * 4096) + ? pOptions->pzShortUsage : NULL; - fputs( pOptTitle, option_usage_fp ); + if (option_usage_fp == NULL) + option_usage_fp = stderr; } - printOptionUsage( pOptions, usage_exit_code, pOptTitle ); - } - - /* - * Describe the mechanics of denoting the options - */ - switch (pOptions->fOptSet & OPTPROC_L_N_S) { - case OPTPROC_L_N_S: fputs( zFlagOkay, option_usage_fp ); break; - case OPTPROC_SHORTOPT: break; - case OPTPROC_LONGOPT: fputs( zNoFlags, option_usage_fp ); break; - case 0: fputs( zOptsOnly, option_usage_fp ); break; - } - - if ((pOptions->fOptSet & OPTPROC_NUM_OPT) != 0) { - fputs( zNumberOpt, option_usage_fp ); - } - - if ((pOptions->fOptSet & OPTPROC_REORDER) != 0) { - fputs( zReorder, option_usage_fp ); + if (pz != NULL) { + fputs(pz, option_usage_fp); + exit(exit_code); + } } - if (pOptions->pzExplain != NULL) - fputs( pOptions->pzExplain, option_usage_fp ); + fprintf(option_usage_fp, pOptions->pzUsageTitle, pOptions->pzProgName); + set_usage_flags(pOptions, NULL); - /* - * IF the user is asking for help (thus exiting with SUCCESS), - * THEN see what additional information we can provide. - */ - if (usage_exit_code == EXIT_SUCCESS) - printProgramDetails( pOptions ); + if ((exit_code == EXIT_SUCCESS) || + (! skip_misuse_usage(pOptions))) - if (pOptions->pzBugAddr != NULL) - fprintf( option_usage_fp, zPlsSendBugs, pOptions->pzBugAddr ); - fflush( option_usage_fp ); + print_usage_details(pOptions, usage_exit_code); - exit( actual_exit_code ); + exit(exit_code); } @@ -263,10 +380,7 @@ optionUsage( * PER OPTION TYPE USAGE INFORMATION */ static void -printExtendedUsage( - tOptions* pOptions, - tOptDesc* pOD, - arg_types_t* pAT ) +prt_extd_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT) { /* * IF there are option conflicts or dependencies, @@ -275,7 +389,7 @@ printExtendedUsage( if ( (pOD->pOptMust != NULL) || (pOD->pOptCant != NULL) ) { - fputs( zTabHyp, option_usage_fp ); + fputs(zTabHyp, option_usage_fp); /* * DEPENDENCIES: @@ -283,16 +397,16 @@ printExtendedUsage( if (pOD->pOptMust != NULL) { const int* pOptNo = pOD->pOptMust; - fputs( zReqThese, option_usage_fp ); + fputs(zReqThese, option_usage_fp); for (;;) { - fprintf( option_usage_fp, zTabout, pOptions->pOptDesc[ - *pOptNo ].pz_Name ); + fprintf(option_usage_fp, zTabout, + pOptions->pOptDesc[*pOptNo].pz_Name); if (*++pOptNo == NO_EQUIVALENT) break; } if (pOD->pOptCant != NULL) - fputs( zTabHypAnd, option_usage_fp ); + fputs(zTabHypAnd, option_usage_fp); } /* @@ -301,10 +415,10 @@ printExtendedUsage( if (pOD->pOptCant != NULL) { const int* pOptNo = pOD->pOptCant; - fputs( zProhib, option_usage_fp ); + fputs(zProhib, option_usage_fp); for (;;) { - fprintf( option_usage_fp, zTabout, pOptions->pOptDesc[ - *pOptNo ].pz_Name ); + fprintf(option_usage_fp, zTabout, + pOptions->pOptDesc[*pOptNo].pz_Name); if (*++pOptNo == NO_EQUIVALENT) break; } @@ -316,16 +430,26 @@ printExtendedUsage( * THEN print the disablement info */ if (pOD->pz_DisableName != NULL ) - fprintf( option_usage_fp, zDis, pOD->pz_DisableName ); + fprintf(option_usage_fp, zDis, pOD->pz_DisableName); /* - * IF the numeric option has a special callback, - * THEN call it, requesting the range or other special info + * Check for argument types that have callbacks with magical properties */ - if ( (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC) - && (pOD->pOptProc != NULL) - && (pOD->pOptProc != optionNumericVal) ) { - (*(pOD->pOptProc))( pOptions, NULL ); + switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { + case OPARG_TYPE_NUMERIC: + /* + * IF the numeric option has a special callback, + * THEN call it, requesting the range or other special info + */ + if ( (pOD->pOptProc != NULL) + && (pOD->pOptProc != optionNumericVal) ) { + (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD); + } + break; + + case OPARG_TYPE_FILE: + (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD); + break; } /* @@ -333,7 +457,7 @@ printExtendedUsage( * THEN print that out */ if (pOD->fOptState & OPTST_INITENABLED) - fputs( zEnab, option_usage_fp ); + fputs(zEnab, option_usage_fp); /* * IF the option is in an equivalence class @@ -342,8 +466,8 @@ printExtendedUsage( */ if ( (pOD->optEquivIndex != NO_EQUIVALENT) && (pOD->optEquivIndex != pOD->optActualIndex ) ) { - fprintf( option_usage_fp, zAlt, - pOptions->pOptDesc[ pOD->optEquivIndex ].pz_Name ); + fprintf(option_usage_fp, zAlt, + pOptions->pOptDesc[ pOD->optEquivIndex ].pz_Name); return; } @@ -360,25 +484,25 @@ printExtendedUsage( && (pOD->optIndex < pOptions->presetOptCt) ) - fputs( zNoPreset, option_usage_fp ); + fputs(zNoPreset, option_usage_fp); /* * Print the appearance requirements. */ if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) - fputs( zMembers, option_usage_fp ); + fputs(zMembers, option_usage_fp); else switch (pOD->optMinCt) { case 1: case 0: switch (pOD->optMaxCt) { - case 0: fputs( zPreset, option_usage_fp ); break; - case NOLIMIT: fputs( zNoLim, option_usage_fp ); break; + case 0: fputs(zPreset, option_usage_fp); break; + case NOLIMIT: fputs(zNoLim, option_usage_fp); break; case 1: break; /* * IF the max is more than one but limited, print "UP TO" message */ - default: fprintf( option_usage_fp, zUpTo, pOD->optMaxCt ); break; + default: fprintf(option_usage_fp, zUpTo, pOD->optMaxCt); break; } break; @@ -386,12 +510,12 @@ printExtendedUsage( /* * More than one is required. Print the range. */ - fprintf( option_usage_fp, zMust, pOD->optMinCt, pOD->optMaxCt ); + fprintf(option_usage_fp, zMust, pOD->optMinCt, pOD->optMaxCt); } - if ( NAMED_OPTS( pOptions ) + if ( NAMED_OPTS(pOptions) && (pOptions->specOptIdx.default_opt == pOD->optIndex)) - fputs( zDefaultOpt, option_usage_fp ); + fputs(zDefaultOpt, option_usage_fp); } @@ -403,34 +527,43 @@ printExtendedUsage( * squishy, but important to tell users how to find these files. */ static void -printInitList( - tCC* const* papz, - ag_bool* pInitIntro, - tCC* pzRc, - tCC* pzPN ) +prt_ini_list(char const * const * papz, ag_bool * pInitIntro, + char const * pzRc, char const * pzPN) { - char zPath[ AG_PATH_MAX+1 ]; + char zPath[AG_PATH_MAX+1]; if (papz == NULL) return; - fputs( zPresetIntro, option_usage_fp ); + fputs(zPresetIntro, option_usage_fp); *pInitIntro = AG_FALSE; for (;;) { - char const* pzPath = *(papz++); + char const * pzPath = *(papz++); + char const * pzReal = zPath; if (pzPath == NULL) break; - if (optionMakePath(zPath, (int)sizeof( zPath ), pzPath, pzPN)) - pzPath = zPath; + /* + * Ignore any invalid paths + */ + if (! optionMakePath(zPath, (int)sizeof(zPath), pzPath, pzPN)) + pzReal = pzPath; + + /* + * Expand paths that are relative to the executable or installation + * directories. Leave alone paths that use environment variables. + */ + else if ((*pzPath == '$') + && ((pzPath[1] == '$') || (pzPath[1] == '@'))) + pzPath = pzReal; /* * Print the name of the "homerc" file. If the "rcfile" name is * not empty, we may or may not print that, too... */ - fprintf( option_usage_fp, zPathFmt, pzPath ); + fprintf(option_usage_fp, zPathFmt, pzPath); if (*pzRc != NUL) { struct stat sb; @@ -438,26 +571,19 @@ printInitList( * IF the "homerc" file is a directory, * then append the "rcfile" name. */ - if ( (stat( pzPath, &sb ) == 0) - && S_ISDIR( sb.st_mode ) ) { - fputc( DIRCH, option_usage_fp ); - fputs( pzRc, option_usage_fp ); + if ((stat(pzReal, &sb) == 0) && S_ISDIR(sb.st_mode)) { + fputc(DIRCH, option_usage_fp); + fputs(pzRc, option_usage_fp); } } - fputc( '\n', option_usage_fp ); + fputc('\n', option_usage_fp); } } -/* - * Print the usage information for a single option. - */ static void -printOneUsage( - tOptions* pOptions, - tOptDesc* pOD, - arg_types_t* pAT ) +prt_preamble(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT) { /* * Flag prefix: IF no flags at all, then omit it. If not printable @@ -466,47 +592,59 @@ printOneUsage( * opts are to be printed too. */ if ((pOptions->fOptSet & OPTPROC_SHORTOPT) == 0) - fputs( pAT->pzSpc, option_usage_fp ); - else if (! isgraph( pOD->optValue)) { + fputs(pAT->pzSpc, option_usage_fp); + + else if (! IS_GRAPHIC_CHAR(pOD->optValue)) { if ( (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) - fputc( ' ', option_usage_fp ); - fputs( pAT->pzNoF, option_usage_fp ); + fputc(' ', option_usage_fp); + fputs(pAT->pzNoF, option_usage_fp); + } else { - fprintf( option_usage_fp, " -%c", pOD->optValue ); + fprintf(option_usage_fp, " -%c", pOD->optValue); if ( (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT)) - fputs( ", ", option_usage_fp ); + fputs(", ", option_usage_fp); } +} + +/* + * Print the usage information for a single option. + */ +static void +prt_one_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT) +{ + prt_preamble(pOptions, pOD, pAT); { - char z[ 80 ]; - tCC* pzArgType; + char z[ 80 ]; + char const * pzArgType; + /* * Determine the argument type string first on its usage, then, * when the option argument is required, base the type string on the * argument type. */ - if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NONE) { - pzArgType = pAT->pzNo; - - } else if (pOD->fOptState & OPTST_ARG_OPTIONAL) { + if (pOD->fOptState & OPTST_ARG_OPTIONAL) { pzArgType = pAT->pzOpt; } else switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { + case OPARG_TYPE_NONE: pzArgType = pAT->pzNo; break; case OPARG_TYPE_ENUMERATION: pzArgType = pAT->pzKey; break; + case OPARG_TYPE_FILE: pzArgType = pAT->pzFile; break; case OPARG_TYPE_MEMBERSHIP: pzArgType = pAT->pzKeyL; break; case OPARG_TYPE_BOOLEAN: pzArgType = pAT->pzBool; break; case OPARG_TYPE_NUMERIC: pzArgType = pAT->pzNum; break; case OPARG_TYPE_HIERARCHY: pzArgType = pAT->pzNest; break; case OPARG_TYPE_STRING: pzArgType = pAT->pzStr; break; - default: goto bogus_desc; break; + case OPARG_TYPE_TIME: pzArgType = pAT->pzTime; break; + default: goto bogus_desc; } - snprintf( z, sizeof(z), pAT->pzOptFmt, pzArgType, pOD->pz_Name, - (pOD->optMinCt != 0) ? pAT->pzReq : pAT->pzOpt ); + snprintf(z, sizeof(z), pAT->pzOptFmt, pzArgType, pOD->pz_Name, + (pOD->optMinCt != 0) ? pAT->pzReq : pAT->pzOpt); - fprintf( option_usage_fp, zOptFmtLine, z, pOD->pzText ); + fprintf(option_usage_fp, zOptFmtLine, z, pOD->pzText); switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { case OPARG_TYPE_ENUMERATION: @@ -517,8 +655,8 @@ printOneUsage( return; bogus_desc: - fprintf( stderr, zInvalOptDesc, pOD->pz_Name ); - exit( EX_SOFTWARE ); + fprintf(stderr, zInvalOptDesc, pOD->pz_Name); + exit(EX_SOFTWARE); } @@ -526,19 +664,34 @@ printOneUsage( * Print out the usage information for just the options. */ static void -printOptionUsage( - tOptions* pOpts, - int ex_code, - tCC* pOptTitle ) +prt_opt_usage(tOptions * pOpts, int ex_code, char const * pOptTitle) { - int ct = pOpts->optCt; - int optNo = 0; - tOptDesc* pOD = pOpts->pOptDesc; - int docCt = 0; + int ct = pOpts->optCt; + int optNo = 0; + tOptDesc * pOD = pOpts->pOptDesc; + int docCt = 0; do { - if ((pOD->fOptState & OPTST_OMITTED) != 0) + if ((pOD->fOptState & OPTST_NO_USAGE_MASK) != 0) { + + /* + * IF this is a compiled-out option + * *AND* usage was requested with "omitted-usage" + * *AND* this is NOT abbreviated usage + * THEN display this option. + */ + if ( (pOD->fOptState == (OPTST_OMITTED | OPTST_NO_INIT)) + && (pOD->pz_Name != NULL) + && (ex_code == EXIT_SUCCESS)) { + + char const * why_pz = + (pOD->pzText == NULL) ? zDisabledWhy : pOD->pzText; + prt_preamble(pOpts, pOD, &argTypes); + fprintf(option_usage_fp, zDisabledOpt, pOD->pz_Name, why_pz); + } + continue; + } if ((pOD->fOptState & OPTST_DOCUMENT) != 0) { if (ex_code == EXIT_SUCCESS) { @@ -558,23 +711,23 @@ printOptionUsage( * THEN document that the remaining options are not user opts */ if ( (pOpts->presetOptCt == optNo) - && (ex_code == EXIT_SUCCESS) - && (docCt > 0) - && ((pOD[-1].fOptState & OPTST_DOCUMENT) == 0) ) - fprintf( option_usage_fp, argTypes.pzBrk, zAuto, pOptTitle ); + && (ex_code == EXIT_SUCCESS) + && (docCt > 0) + && ((pOD[-1].fOptState & OPTST_DOCUMENT) == 0) ) + fprintf(option_usage_fp, argTypes.pzBrk, zAuto, pOptTitle); - printOneUsage( pOpts, pOD, &argTypes ); + prt_one_usage(pOpts, pOD, &argTypes); /* * IF we were invoked because of the --help option, * THEN print all the extra info */ if (ex_code == EXIT_SUCCESS) - printExtendedUsage( pOpts, pOD, &argTypes ); + prt_extd_usage(pOpts, pOD, &argTypes); } while (pOD++, optNo++, (--ct > 0)); - fputc( '\n', option_usage_fp ); + fputc('\n', option_usage_fp); } @@ -583,24 +736,24 @@ printOptionUsage( * PROGRAM DETAILS */ static void -printProgramDetails( tOptions* pOptions ) +prt_prog_detail(tOptions* pOptions) { ag_bool initIntro = AG_TRUE; /* * Display all the places we look for config files */ - printInitList( pOptions->papzHomeList, &initIntro, - pOptions->pzRcName, pOptions->pzProgPath ); + prt_ini_list(pOptions->papzHomeList, &initIntro, + pOptions->pzRcName, pOptions->pzProgPath); /* * Let the user know about environment variable settings */ if ((pOptions->fOptSet & OPTPROC_ENVIRON) != 0) { if (initIntro) - fputs( zPresetIntro, option_usage_fp ); + fputs(zPresetIntro, option_usage_fp); - fprintf( option_usage_fp, zExamineFmt, pOptions->pzPROGNAME ); + fprintf(option_usage_fp, zExamineFmt, pOptions->pzPROGNAME); } /* @@ -613,13 +766,13 @@ printProgramDetails( tOptions* pOptions ) int optNo = 0; tOptDesc* pOD = pOptions->pOptDesc; - fputc( '\n', option_usage_fp ); - fflush( option_usage_fp ); + fputc('\n', option_usage_fp); + fflush(option_usage_fp); do { switch (OPTST_GET_ARGTYPE(pOD->fOptState)) { case OPARG_TYPE_ENUMERATION: case OPARG_TYPE_MEMBERSHIP: - (*(pOD->pOptProc))( NULL, pOD ); + (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD); } } while (pOD++, optNo++, (--ct > 0)); } @@ -628,7 +781,7 @@ printProgramDetails( tOptions* pOptions ) * If there is a detail string, now is the time for that. */ if (pOptions->pzDetail != NULL) - fputs( pOptions->pzDetail, option_usage_fp ); + fputs(pOptions->pzDetail, option_usage_fp); } @@ -647,7 +800,7 @@ printProgramDetails( tOptions* pOptions ) * Set up the formatting for GNU-style output */ static int -setGnuOptFmts( tOptions* pOpts, tCC** ppT ) +setGnuOptFmts(tOptions* pOpts, tCC** ppT) { int flen = 22; *ppT = zNoRq_ShrtTtl; @@ -657,6 +810,8 @@ setGnuOptFmts( tOptions* pOpts, tCC** ppT ) argTypes.pzNum = zGnuNumArg; argTypes.pzKey = zGnuKeyArg; argTypes.pzKeyL = zGnuKeyLArg; + argTypes.pzTime = zGnuTimeArg; + argTypes.pzFile = zGnuFileArg; argTypes.pzBool = zGnuBoolArg; argTypes.pzNest = zGnuNestArg; argTypes.pzOpt = zGnuOptArg; @@ -685,7 +840,7 @@ setGnuOptFmts( tOptions* pOpts, tCC** ppT ) * Standard (AutoOpts normal) option line formatting */ static int -setStdOptFmts( tOptions* pOpts, tCC** ppT ) +setStdOptFmts(tOptions* pOpts, tCC** ppT) { int flen = 0; @@ -694,6 +849,8 @@ setStdOptFmts( tOptions* pOpts, tCC** ppT ) argTypes.pzNum = zStdNumArg; argTypes.pzKey = zStdKeyArg; argTypes.pzKeyL = zStdKeyLArg; + argTypes.pzTime = zStdTimeArg; + argTypes.pzFile = zStdFileArg; argTypes.pzBool = zStdBoolArg; argTypes.pzNest = zStdNestArg; argTypes.pzOpt = zStdOptArg; |