5 * usage.c Id: f611ee45aa9aa8dc102b8acf6b4bc568c60fa99f
6 * Time-stamp: "2009-10-02 23:18:50 bkorb"
8 * This module implements the default usage procedure for
9 * Automated Options. It may be overridden, of course.
12 --start=END-[S]TATIC-FORWARD --patt='^/\*($|[^:])' \
13 --out=xx.c key='^[a-zA-Z0-9_]+\(' --trail='^/\*:' \
14 --spac=2 --input=usage.c
18 * This file is part of AutoOpts, a companion to AutoGen.
19 * AutoOpts is free software.
20 * AutoOpts is copyright (c) 1992-2009 by Bruce Korb - all rights reserved
22 * AutoOpts is available under any one of two licenses. The license
23 * in use must be one of these two and the choice is under the control
24 * of the user of the license.
26 * The GNU Lesser General Public License, version 3 or later
27 * See the files "COPYING.lgplv3" and "COPYING.gplv3"
29 * The Modified Berkeley Software Distribution License
30 * See the file "COPYING.mbsd"
32 * These files have the following md5sums:
34 * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3
35 * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3
36 * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
39 #define OPTPROC_L_N_S (OPTPROC_LONGOPT | OPTPROC_SHORTOPT)
41 static arg_types_t argTypes
;
43 FILE* option_usage_fp
= NULL
;
44 static char zOptFmtLine
[ 16 ];
45 static ag_bool displayEnum
;
47 /* = = = START-STATIC-FORWARD = = = */
48 /* static forward declarations maintained by mk-fwd */
50 checkGNUUsage( tOptions
* pOpts
);
84 printProgramDetails( tOptions
* pOptions
);
87 setGnuOptFmts( tOptions
* pOpts
, tCC
** ppT
);
90 setStdOptFmts( tOptions
* pOpts
, tCC
** ppT
);
91 /* = = = END-STATIC-FORWARD = = = */
95 * Figure out if we should try to format usage text sort-of like
96 * the way many GNU programs do.
99 checkGNUUsage( tOptions
* pOpts
)
101 char* pz
= getenv( "AUTOOPTS_USAGE" );
105 else if (streqvcmp( pz
, "gnu" ) == 0)
106 pOpts
->fOptSet
|= OPTPROC_GNUUSAGE
;
108 else if (streqvcmp( pz
, "autoopts" ) == 0)
109 pOpts
->fOptSet
&= ~OPTPROC_GNUUSAGE
;
111 return (pOpts
->fOptSet
& OPTPROC_GNUUSAGE
) ? AG_TRUE
: AG_FALSE
;
115 /*=export_func optionOnlyUsage
117 * what: Print usage text for just the options
118 * arg: + tOptions* + pOpts + program options descriptor +
119 * arg: + int + ex_code + exit code for calling exit(3) +
122 * This routine will print only the usage for each option.
123 * This function may be used when the emitted usage must incorporate
124 * information not available to AutoOpts.
131 tCC
* pOptTitle
= NULL
;
134 * Determine which header and which option formatting strings to use
136 if (checkGNUUsage(pOpts
)) {
137 (void)setGnuOptFmts( pOpts
, &pOptTitle
);
140 (void)setStdOptFmts( pOpts
, &pOptTitle
);
143 printOptionUsage( pOpts
, ex_code
, pOptTitle
);
147 /*=export_func optionUsage
150 * what: Print usage text
151 * arg: + tOptions* + pOptions + program options descriptor +
152 * arg: + int + exitCode + exit code for calling exit(3) +
155 * This routine will print usage in both GNU-standard and AutoOpts-expanded
156 * formats. The descriptor specifies the default, but AUTOOPTS_USAGE will
157 * over-ride this, providing the value of it is set to either "gnu" or
158 * "autoopts". This routine will @strong{not} return.
160 * If "exitCode" is "EX_USAGE" (normally 64), then output will to to stdout
161 * and the actual exit code will be "EXIT_SUCCESS".
166 int usage_exit_code
)
168 int actual_exit_code
=
169 (usage_exit_code
== EX_USAGE
) ? EXIT_SUCCESS
: usage_exit_code
;
171 displayEnum
= AG_FALSE
;
174 * Paged usage will preset option_usage_fp to an output file.
175 * If it hasn't already been set, then set it to standard output
176 * on successful exit (help was requested), otherwise error out.
178 * Test the version before obtaining pzFullUsage or pzShortUsage.
179 * These fields do not exist before revision 30.
184 if (actual_exit_code
== EXIT_SUCCESS
) {
185 pz
= (pOptions
->structVersion
>= 30 * 4096)
186 ? pOptions
->pzFullUsage
: NULL
;
188 if (option_usage_fp
== NULL
)
189 option_usage_fp
= stdout
;
191 pz
= (pOptions
->structVersion
>= 30 * 4096)
192 ? pOptions
->pzShortUsage
: NULL
;
194 if (option_usage_fp
== NULL
)
195 option_usage_fp
= stderr
;
199 fputs(pz
, option_usage_fp
);
200 exit(actual_exit_code
);
204 fprintf( option_usage_fp
, pOptions
->pzUsageTitle
, pOptions
->pzProgName
);
207 tCC
* pOptTitle
= NULL
;
210 * Determine which header and which option formatting strings to use
212 if (checkGNUUsage(pOptions
)) {
213 int flen
= setGnuOptFmts( pOptions
, &pOptTitle
);
214 sprintf( zOptFmtLine
, zFmtFmt
, flen
);
215 fputc( '\n', option_usage_fp
);
218 int flen
= setStdOptFmts( pOptions
, &pOptTitle
);
219 sprintf( zOptFmtLine
, zFmtFmt
, flen
);
222 * When we exit with EXIT_SUCCESS and the first option is a doc
223 * option, we do *NOT* want to emit the column headers.
226 if ( (usage_exit_code
!= EXIT_SUCCESS
)
227 || ((pOptions
->pOptDesc
->fOptState
& OPTST_DOCUMENT
) == 0) )
229 fputs( pOptTitle
, option_usage_fp
);
232 printOptionUsage( pOptions
, usage_exit_code
, pOptTitle
);
236 * Describe the mechanics of denoting the options
238 switch (pOptions
->fOptSet
& OPTPROC_L_N_S
) {
239 case OPTPROC_L_N_S
: fputs( zFlagOkay
, option_usage_fp
); break;
240 case OPTPROC_SHORTOPT
: break;
241 case OPTPROC_LONGOPT
: fputs( zNoFlags
, option_usage_fp
); break;
242 case 0: fputs( zOptsOnly
, option_usage_fp
); break;
245 if ((pOptions
->fOptSet
& OPTPROC_NUM_OPT
) != 0) {
246 fputs( zNumberOpt
, option_usage_fp
);
249 if ((pOptions
->fOptSet
& OPTPROC_REORDER
) != 0) {
250 fputs( zReorder
, option_usage_fp
);
253 if (pOptions
->pzExplain
!= NULL
)
254 fputs( pOptions
->pzExplain
, option_usage_fp
);
257 * IF the user is asking for help (thus exiting with SUCCESS),
258 * THEN see what additional information we can provide.
260 if (usage_exit_code
== EXIT_SUCCESS
)
261 printProgramDetails( pOptions
);
263 if (pOptions
->pzBugAddr
!= NULL
)
264 fprintf( option_usage_fp
, zPlsSendBugs
, pOptions
->pzBugAddr
);
265 fflush( option_usage_fp
);
267 exit( actual_exit_code
);
271 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
273 * PER OPTION TYPE USAGE INFORMATION
282 * IF there are option conflicts or dependencies,
283 * THEN print them here.
285 if ( (pOD
->pOptMust
!= NULL
)
286 || (pOD
->pOptCant
!= NULL
) ) {
288 fputs( zTabHyp
, option_usage_fp
);
293 if (pOD
->pOptMust
!= NULL
) {
294 const int* pOptNo
= pOD
->pOptMust
;
296 fputs( zReqThese
, option_usage_fp
);
298 fprintf( option_usage_fp
, zTabout
, pOptions
->pOptDesc
[
300 if (*++pOptNo
== NO_EQUIVALENT
)
304 if (pOD
->pOptCant
!= NULL
)
305 fputs( zTabHypAnd
, option_usage_fp
);
311 if (pOD
->pOptCant
!= NULL
) {
312 const int* pOptNo
= pOD
->pOptCant
;
314 fputs( zProhib
, option_usage_fp
);
316 fprintf( option_usage_fp
, zTabout
, pOptions
->pOptDesc
[
318 if (*++pOptNo
== NO_EQUIVALENT
)
325 * IF there is a disablement string
326 * THEN print the disablement info
328 if (pOD
->pz_DisableName
!= NULL
)
329 fprintf( option_usage_fp
, zDis
, pOD
->pz_DisableName
);
332 * Check for argument types that have callbacks with magical properties
334 switch (OPTST_GET_ARGTYPE(pOD
->fOptState
)) {
335 case OPARG_TYPE_NUMERIC
:
337 * IF the numeric option has a special callback,
338 * THEN call it, requesting the range or other special info
340 if ( (pOD
->pOptProc
!= NULL
)
341 && (pOD
->pOptProc
!= optionNumericVal
) ) {
342 (*(pOD
->pOptProc
))(OPTPROC_EMIT_USAGE
, pOD
);
346 case OPARG_TYPE_FILE
:
347 (*(pOD
->pOptProc
))(OPTPROC_EMIT_USAGE
, pOD
);
352 * IF the option defaults to being enabled,
353 * THEN print that out
355 if (pOD
->fOptState
& OPTST_INITENABLED
)
356 fputs( zEnab
, option_usage_fp
);
359 * IF the option is in an equivalence class
360 * AND not the designated lead
361 * THEN print equivalence and leave it at that.
363 if ( (pOD
->optEquivIndex
!= NO_EQUIVALENT
)
364 && (pOD
->optEquivIndex
!= pOD
->optActualIndex
) ) {
365 fprintf( option_usage_fp
, zAlt
,
366 pOptions
->pOptDesc
[ pOD
->optEquivIndex
].pz_Name
);
371 * IF this particular option can NOT be preset
372 * AND some form of presetting IS allowed,
373 * AND it is not an auto-managed option (e.g. --help, et al.)
374 * THEN advise that this option may not be preset.
376 if ( ((pOD
->fOptState
& OPTST_NO_INIT
) != 0)
377 && ( (pOptions
->papzHomeList
!= NULL
)
378 || (pOptions
->pzPROGNAME
!= NULL
)
380 && (pOD
->optIndex
< pOptions
->presetOptCt
)
383 fputs( zNoPreset
, option_usage_fp
);
386 * Print the appearance requirements.
388 if (OPTST_GET_ARGTYPE(pOD
->fOptState
) == OPARG_TYPE_MEMBERSHIP
)
389 fputs( zMembers
, option_usage_fp
);
391 else switch (pOD
->optMinCt
) {
394 switch (pOD
->optMaxCt
) {
395 case 0: fputs( zPreset
, option_usage_fp
); break;
396 case NOLIMIT
: fputs( zNoLim
, option_usage_fp
); break;
399 * IF the max is more than one but limited, print "UP TO" message
401 default: fprintf( option_usage_fp
, zUpTo
, pOD
->optMaxCt
); break;
407 * More than one is required. Print the range.
409 fprintf( option_usage_fp
, zMust
, pOD
->optMinCt
, pOD
->optMaxCt
);
412 if ( NAMED_OPTS( pOptions
)
413 && (pOptions
->specOptIdx
.default_opt
== pOD
->optIndex
))
414 fputs( zDefaultOpt
, option_usage_fp
);
418 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
420 * Figure out where all the initialization files might live.
421 * This requires translating some environment variables and
422 * testing to see if a name is a directory or a file. It's
423 * squishy, but important to tell users how to find these files.
432 char zPath
[ AG_PATH_MAX
+1 ];
437 fputs( zPresetIntro
, option_usage_fp
);
438 *pInitIntro
= AG_FALSE
;
441 char const* pzPath
= *(papz
++);
446 if (optionMakePath(zPath
, (int)sizeof( zPath
), pzPath
, pzPN
))
450 * Print the name of the "homerc" file. If the "rcfile" name is
451 * not empty, we may or may not print that, too...
453 fprintf( option_usage_fp
, zPathFmt
, pzPath
);
458 * IF the "homerc" file is a directory,
459 * then append the "rcfile" name.
461 if ( (stat( pzPath
, &sb
) == 0)
462 && S_ISDIR( sb
.st_mode
) ) {
463 fputc( DIRCH
, option_usage_fp
);
464 fputs( pzRc
, option_usage_fp
);
468 fputc( '\n', option_usage_fp
);
480 * Flag prefix: IF no flags at all, then omit it. If not printable
481 * (not allowed for this option), then blank, else print it.
482 * Follow it with a comma if we are doing GNU usage and long
483 * opts are to be printed too.
485 if ((pOptions
->fOptSet
& OPTPROC_SHORTOPT
) == 0)
486 fputs( pAT
->pzSpc
, option_usage_fp
);
488 else if (! IS_GRAPHIC_CHAR(pOD
->optValue
)) {
489 if ( (pOptions
->fOptSet
& (OPTPROC_GNUUSAGE
|OPTPROC_LONGOPT
))
490 == (OPTPROC_GNUUSAGE
|OPTPROC_LONGOPT
))
491 fputc( ' ', option_usage_fp
);
492 fputs( pAT
->pzNoF
, option_usage_fp
);
495 fprintf( option_usage_fp
, " -%c", pOD
->optValue
);
496 if ( (pOptions
->fOptSet
& (OPTPROC_GNUUSAGE
|OPTPROC_LONGOPT
))
497 == (OPTPROC_GNUUSAGE
|OPTPROC_LONGOPT
))
498 fputs( ", ", option_usage_fp
);
503 * Print the usage information for a single option.
511 printOptPreamble(pOptions
, pOD
, pAT
);
517 * Determine the argument type string first on its usage, then,
518 * when the option argument is required, base the type string on the
521 if (pOD
->fOptState
& OPTST_ARG_OPTIONAL
) {
522 pzArgType
= pAT
->pzOpt
;
524 } else switch (OPTST_GET_ARGTYPE(pOD
->fOptState
)) {
525 case OPARG_TYPE_NONE
: pzArgType
= pAT
->pzNo
; break;
526 case OPARG_TYPE_ENUMERATION
: pzArgType
= pAT
->pzKey
; break;
527 case OPARG_TYPE_FILE
: pzArgType
= pAT
->pzFile
; break;
528 case OPARG_TYPE_MEMBERSHIP
: pzArgType
= pAT
->pzKeyL
; break;
529 case OPARG_TYPE_BOOLEAN
: pzArgType
= pAT
->pzBool
; break;
530 case OPARG_TYPE_NUMERIC
: pzArgType
= pAT
->pzNum
; break;
531 case OPARG_TYPE_HIERARCHY
: pzArgType
= pAT
->pzNest
; break;
532 case OPARG_TYPE_STRING
: pzArgType
= pAT
->pzStr
; break;
533 case OPARG_TYPE_TIME
: pzArgType
= pAT
->pzTime
; break;
534 default: goto bogus_desc
;
537 snprintf( z
, sizeof(z
), pAT
->pzOptFmt
, pzArgType
, pOD
->pz_Name
,
538 (pOD
->optMinCt
!= 0) ? pAT
->pzReq
: pAT
->pzOpt
);
540 fprintf( option_usage_fp
, zOptFmtLine
, z
, pOD
->pzText
);
542 switch (OPTST_GET_ARGTYPE(pOD
->fOptState
)) {
543 case OPARG_TYPE_ENUMERATION
:
544 case OPARG_TYPE_MEMBERSHIP
:
545 displayEnum
= (pOD
->pOptProc
!= NULL
) ? AG_TRUE
: displayEnum
;
551 fprintf( stderr
, zInvalOptDesc
, pOD
->pz_Name
);
557 * Print out the usage information for just the options.
565 int ct
= pOpts
->optCt
;
567 tOptDesc
* pOD
= pOpts
->pOptDesc
;
571 if ((pOD
->fOptState
& OPTST_NO_USAGE_MASK
) != 0) {
574 * IF this is a compiled-out option
575 * *AND* usage was requested with "omitted-usage"
576 * *AND* this is NOT abbreviated usage
577 * THEN display this option.
579 if ( (pOD
->fOptState
== (OPTST_OMITTED
| OPTST_NO_INIT
))
580 && (pOD
->pz_Name
!= NULL
)
581 && (ex_code
== EXIT_SUCCESS
)) {
583 char const * why_pz
=
584 (pOD
->pzText
== NULL
) ? zDisabledWhy
: pOD
->pzText
;
585 printOptPreamble(pOpts
, pOD
, &argTypes
);
586 fprintf(option_usage_fp
, zDisabledOpt
, pOD
->pz_Name
, why_pz
);
592 if ((pOD
->fOptState
& OPTST_DOCUMENT
) != 0) {
593 if (ex_code
== EXIT_SUCCESS
) {
594 fprintf(option_usage_fp
, argTypes
.pzBrk
, pOD
->pzText
,
603 * IF this is the first auto-opt maintained option
604 * *AND* we are doing a full help
605 * *AND* there are documentation options
606 * *AND* the last one was not a doc option,
607 * THEN document that the remaining options are not user opts
609 if ( (pOpts
->presetOptCt
== optNo
)
610 && (ex_code
== EXIT_SUCCESS
)
612 && ((pOD
[-1].fOptState
& OPTST_DOCUMENT
) == 0) )
613 fprintf( option_usage_fp
, argTypes
.pzBrk
, zAuto
, pOptTitle
);
615 printOneUsage(pOpts
, pOD
, &argTypes
);
618 * IF we were invoked because of the --help option,
619 * THEN print all the extra info
621 if (ex_code
== EXIT_SUCCESS
)
622 printExtendedUsage( pOpts
, pOD
, &argTypes
);
624 } while (pOD
++, optNo
++, (--ct
> 0));
626 fputc( '\n', option_usage_fp
);
630 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
635 printProgramDetails( tOptions
* pOptions
)
637 ag_bool initIntro
= AG_TRUE
;
640 * Display all the places we look for config files
642 printInitList( pOptions
->papzHomeList
, &initIntro
,
643 pOptions
->pzRcName
, pOptions
->pzProgPath
);
646 * Let the user know about environment variable settings
648 if ((pOptions
->fOptSet
& OPTPROC_ENVIRON
) != 0) {
650 fputs( zPresetIntro
, option_usage_fp
);
652 fprintf( option_usage_fp
, zExamineFmt
, pOptions
->pzPROGNAME
);
656 * IF we found an enumeration,
657 * THEN hunt for it again. Call the handler proc with a NULL
658 * option struct pointer. That tells it to display the keywords.
661 int ct
= pOptions
->optCt
;
663 tOptDesc
* pOD
= pOptions
->pOptDesc
;
665 fputc( '\n', option_usage_fp
);
666 fflush( option_usage_fp
);
668 switch (OPTST_GET_ARGTYPE(pOD
->fOptState
)) {
669 case OPARG_TYPE_ENUMERATION
:
670 case OPARG_TYPE_MEMBERSHIP
:
671 (*(pOD
->pOptProc
))(OPTPROC_EMIT_USAGE
, pOD
);
673 } while (pOD
++, optNo
++, (--ct
> 0));
677 * If there is a detail string, now is the time for that.
679 if (pOptions
->pzDetail
!= NULL
)
680 fputs( pOptions
->pzDetail
, option_usage_fp
);
684 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
686 * OPTION LINE FORMATTING SETUP
688 * The "OptFmt" formats receive three arguments:
689 * 1. the type of the option's argument
690 * 2. the long name of the option
691 * 3. "YES" or "no ", depending on whether or not the option must appear
692 * on the command line.
693 * These formats are used immediately after the option flag (if used) has
696 * Set up the formatting for GNU-style output
699 setGnuOptFmts( tOptions
* pOpts
, tCC
** ppT
)
702 *ppT
= zNoRq_ShrtTtl
;
704 argTypes
.pzStr
= zGnuStrArg
;
705 argTypes
.pzReq
= zOneSpace
;
706 argTypes
.pzNum
= zGnuNumArg
;
707 argTypes
.pzKey
= zGnuKeyArg
;
708 argTypes
.pzKeyL
= zGnuKeyLArg
;
709 argTypes
.pzTime
= zGnuTimeArg
;
710 argTypes
.pzFile
= zGnuFileArg
;
711 argTypes
.pzBool
= zGnuBoolArg
;
712 argTypes
.pzNest
= zGnuNestArg
;
713 argTypes
.pzOpt
= zGnuOptArg
;
714 argTypes
.pzNo
= zOneSpace
;
715 argTypes
.pzBrk
= zGnuBreak
;
716 argTypes
.pzNoF
= zSixSpaces
;
717 argTypes
.pzSpc
= zThreeSpaces
;
719 switch (pOpts
->fOptSet
& OPTPROC_L_N_S
) {
720 case OPTPROC_L_N_S
: argTypes
.pzOptFmt
= zGnuOptFmt
; break;
721 case OPTPROC_LONGOPT
: argTypes
.pzOptFmt
= zGnuOptFmt
; break;
722 case 0: argTypes
.pzOptFmt
= zGnuOptFmt
+ 2; break;
723 case OPTPROC_SHORTOPT
:
724 argTypes
.pzOptFmt
= zShrtGnuOptFmt
;
725 zGnuStrArg
[0] = zGnuNumArg
[0] = zGnuKeyArg
[0] = zGnuBoolArg
[0] = ' ';
726 argTypes
.pzOpt
= " [arg]";
736 * Standard (AutoOpts normal) option line formatting
739 setStdOptFmts( tOptions
* pOpts
, tCC
** ppT
)
743 argTypes
.pzStr
= zStdStrArg
;
744 argTypes
.pzReq
= zStdReqArg
;
745 argTypes
.pzNum
= zStdNumArg
;
746 argTypes
.pzKey
= zStdKeyArg
;
747 argTypes
.pzKeyL
= zStdKeyLArg
;
748 argTypes
.pzTime
= zStdTimeArg
;
749 argTypes
.pzFile
= zStdFileArg
;
750 argTypes
.pzBool
= zStdBoolArg
;
751 argTypes
.pzNest
= zStdNestArg
;
752 argTypes
.pzOpt
= zStdOptArg
;
753 argTypes
.pzNo
= zStdNoArg
;
754 argTypes
.pzBrk
= zStdBreak
;
755 argTypes
.pzNoF
= zFiveSpaces
;
756 argTypes
.pzSpc
= zTwoSpaces
;
758 switch (pOpts
->fOptSet
& (OPTPROC_NO_REQ_OPT
| OPTPROC_SHORTOPT
)) {
759 case (OPTPROC_NO_REQ_OPT
| OPTPROC_SHORTOPT
):
760 *ppT
= zNoRq_ShrtTtl
;
761 argTypes
.pzOptFmt
= zNrmOptFmt
;
765 case OPTPROC_NO_REQ_OPT
:
766 *ppT
= zNoRq_NoShrtTtl
;
767 argTypes
.pzOptFmt
= zNrmOptFmt
;
771 case OPTPROC_SHORTOPT
:
773 argTypes
.pzOptFmt
= zReqOptFmt
;
778 *ppT
= zReq_NoShrtTtl
;
779 argTypes
.pzOptFmt
= zReqOptFmt
;
790 * c-file-style: "stroustrup"
791 * indent-tabs-mode: nil
793 * end of autoopts/usage.c */