bumped version
[gnutls.git] / src / libopts / usage.c
blobebdc46ae867317a1a13c129b206d07f46b2e58cb
2 /*
3 * \file usage.c
5 * Time-stamp: "2012-03-31 19:19:26 bkorb"
7 * This module implements the default usage procedure for
8 * Automated Options. It may be overridden, of course.
10 * Sort options:
11 --start=END-[S]TATIC-FORWARD --patt='^/\*($|[^:])' \
12 --out=xx.c key='^[a-zA-Z0-9_]+\(' --trail='^/\*:' \
13 --spac=2 --input=usage.c
17 * This file is part of AutoOpts, a companion to AutoGen.
18 * AutoOpts is free software.
19 * AutoOpts is Copyright (c) 1992-2012 by Bruce Korb - all rights reserved
21 * AutoOpts is available under any one of two licenses. The license
22 * in use must be one of these two and the choice is under the control
23 * of the user of the license.
25 * The GNU Lesser General Public License, version 3 or later
26 * See the files "COPYING.lgplv3" and "COPYING.gplv3"
28 * The Modified Berkeley Software Distribution License
29 * See the file "COPYING.mbsd"
31 * These files have the following md5sums:
33 * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3
34 * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3
35 * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
38 #define OPTPROC_L_N_S (OPTPROC_LONGOPT | OPTPROC_SHORTOPT)
40 /* = = = START-STATIC-FORWARD = = = */
41 static inline bool
42 do_gnu_usage(tOptions * pOpts);
44 static inline bool
45 skip_misuse_usage(tOptions * pOpts);
47 static void
48 print_usage_details(tOptions * opts, int exit_code);
50 static void
51 prt_conflicts(tOptions * pOptions, tOptDesc * pOD);
53 static void
54 prt_one_vendor(tOptions * pOptions, tOptDesc * pOD,
55 arg_types_t * pAT, char const * usefmt);
57 static void
58 prt_vendor_opts(tOptions * pOpts, char const * pOptTitle);
60 static void
61 prt_extd_usage(tOptions * pOpts, tOptDesc * pOD,
62 char const * pOptTitle);
64 static void
65 prt_ini_list(char const * const * papz, bool * pInitIntro,
66 char const * pzRc, char const * pzPN);
68 static void
69 prt_preamble(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT);
71 static void
72 prt_one_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT);
74 static void
75 prt_opt_usage(tOptions * pOpts, int ex_code, char const * pOptTitle);
77 static void
78 prt_prog_detail(tOptions* pOptions);
80 static int
81 setGnuOptFmts(tOptions* pOpts, tCC** ppT);
83 static int
84 setStdOptFmts(tOptions* pOpts, tCC** ppT);
85 /* = = = END-STATIC-FORWARD = = = */
88 * NB: no entry may be a prefix of another entry
90 #define AOFLAG_TABLE \
91 _aof_(gnu, OPTPROC_GNUUSAGE ) \
92 _aof_(autoopts, ~OPTPROC_GNUUSAGE) \
93 _aof_(no_misuse_usage, OPTPROC_MISUSE ) \
94 _aof_(misuse_usage, ~OPTPROC_MISUSE )
96 LOCAL void
97 set_usage_flags(tOptions * opts, char const * flg_txt)
99 typedef struct {
100 size_t fnm_len;
101 uint32_t fnm_mask;
102 char const * fnm_name;
103 } ao_flag_names_t;
105 # define _aof_(_n, _f) AOUF_ ## _n ## _ID,
106 typedef enum { AOFLAG_TABLE AOUF_COUNT } ao_flag_id_t;
107 # undef _aof_
109 # define _aof_(_n, _f) AOUF_ ## _n = (1 << AOUF_ ## _n ## _ID),
110 typedef enum { AOFLAG_TABLE } ao_flags_t;
111 # undef _aof_
113 # define _aof_(_n, _f) { sizeof(#_n)-1, _f, #_n },
114 static ao_flag_names_t const fn_table[AOUF_COUNT] = {
115 AOFLAG_TABLE
117 # undef _aof_
119 unsigned int flg = (ao_flags_t)0;
121 if (flg_txt == NULL) {
122 flg_txt = getenv("AUTOOPTS_USAGE");
123 if (flg_txt == NULL) return;
126 flg_txt = SPN_WHITESPACE_CHARS(flg_txt);
127 if (*flg_txt == NUL)
128 return;
130 for (;;) {
131 int ix = 0;
132 ao_flag_names_t const * fnt = fn_table;
134 for (;;) {
135 if (strneqvcmp(flg_txt, fnt->fnm_name, fnt->fnm_len) == 0)
136 break;
137 if (++ix >= AOUF_COUNT)
138 return;
139 fnt++;
143 * Make sure we have a full match. Look for whitespace,
144 * a comma, or a NUL byte.
146 if (! IS_END_LIST_ENTRY_CHAR(flg_txt[fnt->fnm_len]))
147 return;
149 flg |= 1 << ix;
150 flg_txt = SPN_WHITESPACE_CHARS(flg_txt + fnt->fnm_len);
152 if (*flg_txt == NUL)
153 break;
155 if (*flg_txt == ',') {
157 * skip the comma and following white space
159 flg_txt = SPN_WHITESPACE_CHARS(flg_txt + 1);
160 if (*flg_txt == NUL)
161 break;
166 ao_flag_names_t const * fnm = fn_table;
168 while (flg != 0) {
169 if ((flg & 1) != 0) {
170 if ((fnm->fnm_mask & OPTPROC_LONGOPT) != 0)
171 opts->fOptSet &= fnm->fnm_mask;
172 else opts->fOptSet |= fnm->fnm_mask;
174 flg >>= 1;
175 fnm++;
181 * Figure out if we should try to format usage text sort-of like
182 * the way many GNU programs do.
184 static inline bool
185 do_gnu_usage(tOptions * pOpts)
187 return (pOpts->fOptSet & OPTPROC_GNUUSAGE) ? true : false;
191 * Figure out if we should try to format usage text sort-of like
192 * the way many GNU programs do.
194 static inline bool
195 skip_misuse_usage(tOptions * pOpts)
197 return (pOpts->fOptSet & OPTPROC_MISUSE) ? true : false;
201 /*=export_func optionOnlyUsage
203 * what: Print usage text for just the options
204 * arg: + tOptions* + pOpts + program options descriptor +
205 * arg: + int + ex_code + exit code for calling exit(3) +
207 * doc:
208 * This routine will print only the usage for each option.
209 * This function may be used when the emitted usage must incorporate
210 * information not available to AutoOpts.
212 void
213 optionOnlyUsage(tOptions * pOpts, int ex_code)
215 char const * pOptTitle = NULL;
217 set_usage_flags(pOpts, NULL);
218 if ((ex_code != EXIT_SUCCESS) &&
219 skip_misuse_usage(pOpts))
220 return;
223 * Determine which header and which option formatting strings to use
225 if (do_gnu_usage(pOpts))
226 (void)setGnuOptFmts(pOpts, &pOptTitle);
227 else
228 (void)setStdOptFmts(pOpts, &pOptTitle);
230 prt_opt_usage(pOpts, ex_code, pOptTitle);
232 fflush(option_usage_fp);
233 if (ferror(option_usage_fp) != 0) {
234 fputs(zOutputFail, stderr);
235 exit(EXIT_FAILURE);
239 static void
240 print_usage_details(tOptions * opts, int exit_code)
243 char const * pOptTitle = NULL;
246 * Determine which header and which option formatting strings to use
248 if (do_gnu_usage(opts)) {
249 int flen = setGnuOptFmts(opts, &pOptTitle);
250 sprintf(line_fmt_buf, zFmtFmt, flen);
251 fputc(NL, option_usage_fp);
253 else {
254 int flen = setStdOptFmts(opts, &pOptTitle);
255 sprintf(line_fmt_buf, zFmtFmt, flen);
258 * When we exit with EXIT_SUCCESS and the first option is a doc
259 * option, we do *NOT* want to emit the column headers.
260 * Otherwise, we do.
262 if ( (exit_code != EXIT_SUCCESS)
263 || ((opts->pOptDesc->fOptState & OPTST_DOCUMENT) == 0) )
265 fputs(pOptTitle, option_usage_fp);
268 prt_opt_usage(opts, exit_code, pOptTitle);
272 * Describe the mechanics of denoting the options
274 switch (opts->fOptSet & OPTPROC_L_N_S) {
275 case OPTPROC_L_N_S: fputs(zFlagOkay, option_usage_fp); break;
276 case OPTPROC_SHORTOPT: break;
277 case OPTPROC_LONGOPT: fputs(zNoFlags, option_usage_fp); break;
278 case 0: fputs(zOptsOnly, option_usage_fp); break;
281 if ((opts->fOptSet & OPTPROC_NUM_OPT) != 0)
282 fputs(zNumberOpt, option_usage_fp);
284 if ((opts->fOptSet & OPTPROC_REORDER) != 0)
285 fputs(zReorder, option_usage_fp);
287 if (opts->pzExplain != NULL)
288 fputs(opts->pzExplain, option_usage_fp);
291 * IF the user is asking for help (thus exiting with SUCCESS),
292 * THEN see what additional information we can provide.
294 if (exit_code == EXIT_SUCCESS)
295 prt_prog_detail(opts);
298 * Give bug notification preference to the packager information
300 if (HAS_pzPkgDataDir(opts) && (opts->pzPackager != NULL))
301 fputs(opts->pzPackager, option_usage_fp);
303 else if (opts->pzBugAddr != NULL)
304 fprintf(option_usage_fp, zPlsSendBugs, opts->pzBugAddr);
306 fflush(option_usage_fp);
308 if (ferror(option_usage_fp) != 0) {
309 fputs(zOutputFail, stderr);
310 exit(EXIT_FAILURE);
315 /*=export_func optionUsage
316 * private:
318 * what: Print usage text
319 * arg: + tOptions* + pOptions + program options descriptor +
320 * arg: + int + exitCode + exit code for calling exit(3) +
322 * doc:
323 * This routine will print usage in both GNU-standard and AutoOpts-expanded
324 * formats. The descriptor specifies the default, but AUTOOPTS_USAGE will
325 * over-ride this, providing the value of it is set to either "gnu" or
326 * "autoopts". This routine will @strong{not} return.
328 * If "exitCode" is "AO_EXIT_REQ_USAGE" (normally 64), then output will to
329 * to stdout and the actual exit code will be "EXIT_SUCCESS".
331 void
332 optionUsage(tOptions * pOptions, int usage_exit_code)
334 int exit_code = (usage_exit_code == AO_EXIT_REQ_USAGE)
335 ? EXIT_SUCCESS : usage_exit_code;
337 displayEnum = false;
340 * Paged usage will preset option_usage_fp to an output file.
341 * If it hasn't already been set, then set it to standard output
342 * on successful exit (help was requested), otherwise error out.
344 * Test the version before obtaining pzFullUsage or pzShortUsage.
345 * These fields do not exist before revision 30.
348 char const * pz;
350 if (exit_code == EXIT_SUCCESS) {
351 pz = (pOptions->structVersion >= 30 * 4096)
352 ? pOptions->pzFullUsage : NULL;
354 if (option_usage_fp == NULL)
355 option_usage_fp = stdout;
356 } else {
357 pz = (pOptions->structVersion >= 30 * 4096)
358 ? pOptions->pzShortUsage : NULL;
360 if (option_usage_fp == NULL)
361 option_usage_fp = stderr;
364 if (pz != NULL) {
365 fputs(pz, option_usage_fp);
366 exit(exit_code);
370 fprintf(option_usage_fp, pOptions->pzUsageTitle, pOptions->pzProgName);
371 set_usage_flags(pOptions, NULL);
373 if ((exit_code == EXIT_SUCCESS) ||
374 (! skip_misuse_usage(pOptions)))
376 print_usage_details(pOptions, usage_exit_code);
378 exit(exit_code);
381 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
382 * PER OPTION TYPE USAGE INFORMATION
383 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
385 * print option conflicts.
387 * @param pOptions the program option descriptor
388 * @param pOD the option descriptor
389 * @param pAT names of the option argument types
391 static void
392 prt_conflicts(tOptions * pOptions, tOptDesc * pOD)
395 fputs(zTabHyp, option_usage_fp);
398 * REQUIRED:
400 if (pOD->pOptMust != NULL) {
401 const int* pOptNo = pOD->pOptMust;
403 fputs(zReqThese, option_usage_fp);
404 for (;;) {
405 fprintf(option_usage_fp, zTabout,
406 pOptions->pOptDesc[*pOptNo].pz_Name);
407 if (*++pOptNo == NO_EQUIVALENT)
408 break;
411 if (pOD->pOptCant != NULL)
412 fputs(zTabHypAnd, option_usage_fp);
416 * CONFLICTS:
418 if (pOD->pOptCant != NULL) {
419 const int* pOptNo = pOD->pOptCant;
421 fputs(zProhib, option_usage_fp);
422 for (;;) {
423 fprintf(option_usage_fp, zTabout,
424 pOptions->pOptDesc[*pOptNo].pz_Name);
425 if (*++pOptNo == NO_EQUIVALENT)
426 break;
432 * Print the usage information for a single vendor option.
434 * @param pOpts the program option descriptor
435 * @param pOD the option descriptor
436 * @param pAT names of the option argument types
438 static void
439 prt_one_vendor(tOptions * pOptions, tOptDesc * pOD,
440 arg_types_t * pAT, char const * usefmt)
442 prt_preamble(pOptions, pOD, pAT);
445 char z[ 80 ];
446 char const * pzArgType;
449 * Determine the argument type string first on its usage, then,
450 * when the option argument is required, base the type string on the
451 * argument type.
453 if (pOD->fOptState & OPTST_ARG_OPTIONAL) {
454 pzArgType = pAT->pzOpt;
456 } else switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
457 case OPARG_TYPE_NONE: pzArgType = pAT->pzNo; break;
458 case OPARG_TYPE_ENUMERATION: pzArgType = pAT->pzKey; break;
459 case OPARG_TYPE_FILE: pzArgType = pAT->pzFile; break;
460 case OPARG_TYPE_MEMBERSHIP: pzArgType = pAT->pzKeyL; break;
461 case OPARG_TYPE_BOOLEAN: pzArgType = pAT->pzBool; break;
462 case OPARG_TYPE_NUMERIC: pzArgType = pAT->pzNum; break;
463 case OPARG_TYPE_HIERARCHY: pzArgType = pAT->pzNest; break;
464 case OPARG_TYPE_STRING: pzArgType = pAT->pzStr; break;
465 case OPARG_TYPE_TIME: pzArgType = pAT->pzTime; break;
466 default: goto bogus_desc;
469 pzArgType = SPN_WHITESPACE_CHARS(pzArgType);
470 if (*pzArgType == NUL)
471 snprintf(z, sizeof(z), "%s", pOD->pz_Name);
472 else
473 snprintf(z, sizeof(z), "%s=%s", pOD->pz_Name, pzArgType);
474 fprintf(option_usage_fp, usefmt, z, pOD->pzText);
476 switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
477 case OPARG_TYPE_ENUMERATION:
478 case OPARG_TYPE_MEMBERSHIP:
479 displayEnum = (pOD->pOptProc != NULL) ? true : displayEnum;
483 return;
485 bogus_desc:
486 fprintf(stderr, zInvalOptDesc, pOD->pz_Name);
487 exit(EX_SOFTWARE);
491 * Print the long options processed with "-W". These options will be the
492 * ones that do *not* have flag characters.
494 * @param pOptions the program option descriptor
495 * @param pOD the option descriptor
497 static void
498 prt_vendor_opts(tOptions * pOpts, char const * pOptTitle)
500 static unsigned int const not_vended_mask =
501 OPTST_NO_USAGE_MASK | OPTST_DOCUMENT;
503 static char const vfmtfmt[] = "%%-%us %%s\n";
504 char vfmt[sizeof(vfmtfmt)];
507 * Only handle client specified options. The "vendor option" follows
508 * "presetOptCt", so we won't loop/recurse indefinitely.
510 int ct = pOpts->presetOptCt;
511 tOptDesc * pOD = pOpts->pOptDesc;
512 size_t nmlen = 0;
514 fprintf(option_usage_fp, zTabout, zVendOptsAre);
516 do {
517 size_t l;
518 if ( ((pOD->fOptState & not_vended_mask) != 0)
519 || IS_GRAPHIC_CHAR(pOD->optValue))
520 continue;
522 l = strlen(pOD->pz_Name);
523 if (l > nmlen) nmlen = l;
524 } while (pOD++, (--ct > 0));
526 sprintf(vfmt, vfmtfmt, (unsigned int)nmlen + 4);
527 ct = pOpts->presetOptCt;
528 pOD = pOpts->pOptDesc;
530 do {
531 if ( ((pOD->fOptState & not_vended_mask) != 0)
532 || IS_GRAPHIC_CHAR(pOD->optValue))
533 continue;
535 prt_one_vendor(pOpts, pOD, &argTypes, vfmt);
536 prt_extd_usage(pOpts, pOD, pOptTitle);
538 } while (pOD++, (--ct > 0));
542 * Print extended usage. Usage/help was requested.
544 * @param pOptions the program option descriptor
545 * @param pOD the option descriptor
546 * @param pAT names of the option argument types
548 static void
549 prt_extd_usage(tOptions * pOpts, tOptDesc * pOD,
550 char const * pOptTitle)
552 if ( ((pOpts->fOptSet & OPTPROC_VENDOR_OPT) != 0)
553 && (pOD->optActualValue == VENDOR_OPTION_VALUE)) {
554 prt_vendor_opts(pOpts, pOptTitle);
555 return;
559 * IF there are option conflicts or dependencies,
560 * THEN print them here.
562 if ( (pOD->pOptMust != NULL)
563 || (pOD->pOptCant != NULL) )
564 prt_conflicts(pOpts, pOD);
567 * IF there is a disablement string
568 * THEN print the disablement info
570 if (pOD->pz_DisableName != NULL )
571 fprintf(option_usage_fp, zDis, pOD->pz_DisableName);
574 * Check for argument types that have callbacks with magical properties
576 switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
577 case OPARG_TYPE_NUMERIC:
579 * IF the numeric option has a special callback,
580 * THEN call it, requesting the range or other special info
582 if ( (pOD->pOptProc != NULL)
583 && (pOD->pOptProc != optionNumericVal) ) {
584 (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD);
586 break;
588 case OPARG_TYPE_FILE:
589 (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD);
590 break;
594 * IF the option defaults to being enabled,
595 * THEN print that out
597 if (pOD->fOptState & OPTST_INITENABLED)
598 fputs(zEnab, option_usage_fp);
601 * IF the option is in an equivalence class
602 * AND not the designated lead
603 * THEN print equivalence and leave it at that.
605 if ( (pOD->optEquivIndex != NO_EQUIVALENT)
606 && (pOD->optEquivIndex != pOD->optActualIndex ) ) {
607 fprintf(option_usage_fp, zAlt,
608 pOpts->pOptDesc[ pOD->optEquivIndex ].pz_Name);
609 return;
613 * IF this particular option can NOT be preset
614 * AND some form of presetting IS allowed,
615 * AND it is not an auto-managed option (e.g. --help, et al.)
616 * THEN advise that this option may not be preset.
618 if ( ((pOD->fOptState & OPTST_NO_INIT) != 0)
619 && ( (pOpts->papzHomeList != NULL)
620 || (pOpts->pzPROGNAME != NULL)
622 && (pOD->optIndex < pOpts->presetOptCt)
625 fputs(zNoPreset, option_usage_fp);
628 * Print the appearance requirements.
630 if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP)
631 fputs(zMembers, option_usage_fp);
633 else switch (pOD->optMinCt) {
634 case 1:
635 case 0:
636 switch (pOD->optMaxCt) {
637 case 0: fputs(zPreset, option_usage_fp); break;
638 case NOLIMIT: fputs(zNoLim, option_usage_fp); break;
639 case 1: break;
641 * IF the max is more than one but limited, print "UP TO" message
643 default: fprintf(option_usage_fp, zUpTo, pOD->optMaxCt); break;
645 break;
647 default:
649 * More than one is required. Print the range.
651 fprintf(option_usage_fp, zMust, pOD->optMinCt, pOD->optMaxCt);
654 if ( NAMED_OPTS(pOpts)
655 && (pOpts->specOptIdx.default_opt == pOD->optIndex))
656 fputs(zDefaultOpt, option_usage_fp);
659 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
661 * Figure out where all the initialization files might live.
662 * This requires translating some environment variables and
663 * testing to see if a name is a directory or a file. It's
664 * squishy, but important to tell users how to find these files.
666 static void
667 prt_ini_list(char const * const * papz, bool * pInitIntro,
668 char const * pzRc, char const * pzPN)
670 char zPath[AG_PATH_MAX+1];
672 if (papz == NULL)
673 return;
675 fputs(zPresetIntro, option_usage_fp);
676 *pInitIntro = false;
678 for (;;) {
679 char const * pzPath = *(papz++);
680 char const * pzReal = zPath;
682 if (pzPath == NULL)
683 break;
686 * Ignore any invalid paths
688 if (! optionMakePath(zPath, (int)sizeof(zPath), pzPath, pzPN))
689 pzReal = pzPath;
692 * Expand paths that are relative to the executable or installation
693 * directories. Leave alone paths that use environment variables.
695 else if ((*pzPath == '$')
696 && ((pzPath[1] == '$') || (pzPath[1] == '@')))
697 pzPath = pzReal;
700 * Print the name of the "homerc" file. If the "rcfile" name is
701 * not empty, we may or may not print that, too...
703 fprintf(option_usage_fp, zPathFmt, pzPath);
704 if (*pzRc != NUL) {
705 struct stat sb;
708 * IF the "homerc" file is a directory,
709 * then append the "rcfile" name.
711 if ((stat(pzReal, &sb) == 0) && S_ISDIR(sb.st_mode)) {
712 fputc(DIRCH, option_usage_fp);
713 fputs(pzRc, option_usage_fp);
717 fputc(NL, option_usage_fp);
722 static void
723 prt_preamble(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT)
726 * Flag prefix: IF no flags at all, then omit it. If not printable
727 * (not allowed for this option), then blank, else print it.
728 * Follow it with a comma if we are doing GNU usage and long
729 * opts are to be printed too.
731 if ((pOptions->fOptSet & OPTPROC_SHORTOPT) == 0)
732 fputs(pAT->pzSpc, option_usage_fp);
734 else if (! IS_GRAPHIC_CHAR(pOD->optValue)) {
735 if ( (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
736 == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
737 fputc(' ', option_usage_fp);
738 fputs(pAT->pzNoF, option_usage_fp);
740 } else {
741 fprintf(option_usage_fp, " -%c", pOD->optValue);
742 if ( (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
743 == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
744 fputs(", ", option_usage_fp);
749 * Print the usage information for a single option.
751 * @param pOpts the program option descriptor
752 * @param pOD the option descriptor
753 * @param pAT names of the option argument types
755 static void
756 prt_one_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT)
758 prt_preamble(pOptions, pOD, pAT);
761 char z[ 80 ];
762 char const * pzArgType;
765 * Determine the argument type string first on its usage, then,
766 * when the option argument is required, base the type string on the
767 * argument type.
769 if (pOD->fOptState & OPTST_ARG_OPTIONAL) {
770 pzArgType = pAT->pzOpt;
772 } else switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
773 case OPARG_TYPE_NONE: pzArgType = pAT->pzNo; break;
774 case OPARG_TYPE_ENUMERATION: pzArgType = pAT->pzKey; break;
775 case OPARG_TYPE_FILE: pzArgType = pAT->pzFile; break;
776 case OPARG_TYPE_MEMBERSHIP: pzArgType = pAT->pzKeyL; break;
777 case OPARG_TYPE_BOOLEAN: pzArgType = pAT->pzBool; break;
778 case OPARG_TYPE_NUMERIC: pzArgType = pAT->pzNum; break;
779 case OPARG_TYPE_HIERARCHY: pzArgType = pAT->pzNest; break;
780 case OPARG_TYPE_STRING: pzArgType = pAT->pzStr; break;
781 case OPARG_TYPE_TIME: pzArgType = pAT->pzTime; break;
782 default: goto bogus_desc;
785 snprintf(z, sizeof(z), pAT->pzOptFmt, pzArgType, pOD->pz_Name,
786 (pOD->optMinCt != 0) ? pAT->pzReq : pAT->pzOpt);
788 fprintf(option_usage_fp, line_fmt_buf, z, pOD->pzText);
790 switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
791 case OPARG_TYPE_ENUMERATION:
792 case OPARG_TYPE_MEMBERSHIP:
793 displayEnum = (pOD->pOptProc != NULL) ? true : displayEnum;
797 return;
799 bogus_desc:
800 fprintf(stderr, zInvalOptDesc, pOD->pz_Name);
801 exit(EX_SOFTWARE);
805 * Print out the usage information for just the options.
807 static void
808 prt_opt_usage(tOptions * pOpts, int ex_code, char const * pOptTitle)
810 int ct = pOpts->optCt;
811 int optNo = 0;
812 tOptDesc * pOD = pOpts->pOptDesc;
813 int docCt = 0;
815 do {
817 * no usage --> disallowed on command line (OPTST_NO_COMMAND), or
818 * deprecated -- strongly discouraged (OPTST_DEPRECATED), or
819 * compiled out of current object code (OPTST_OMITTED)
821 if ((pOD->fOptState & OPTST_NO_USAGE_MASK) != 0) {
824 * IF this is a compiled-out option
825 * *AND* usage was requested with "omitted-usage"
826 * *AND* this is NOT abbreviated usage
827 * THEN display this option.
829 if ( (pOD->fOptState == (OPTST_OMITTED | OPTST_NO_INIT))
830 && (pOD->pz_Name != NULL)
831 && (ex_code == EXIT_SUCCESS)) {
833 char const * why_pz =
834 (pOD->pzText == NULL) ? zDisabledWhy : pOD->pzText;
835 prt_preamble(pOpts, pOD, &argTypes);
836 fprintf(option_usage_fp, zDisabledOpt, pOD->pz_Name, why_pz);
839 continue;
842 if ((pOD->fOptState & OPTST_DOCUMENT) != 0) {
843 if (ex_code == EXIT_SUCCESS) {
844 fprintf(option_usage_fp, argTypes.pzBrk, pOD->pzText,
845 pOptTitle);
846 docCt++;
849 continue;
852 /* Skip name only options when we have a vendor option */
853 if ( ((pOpts->fOptSet & OPTPROC_VENDOR_OPT) != 0)
854 && (! IS_GRAPHIC_CHAR(pOD->optValue)))
855 continue;
858 * IF this is the first auto-opt maintained option
859 * *AND* we are doing a full help
860 * *AND* there are documentation options
861 * *AND* the last one was not a doc option,
862 * THEN document that the remaining options are not user opts
864 if ((docCt > 0) && (ex_code == EXIT_SUCCESS)) {
865 if (pOpts->presetOptCt == optNo) {
866 if ((pOD[-1].fOptState & OPTST_DOCUMENT) == 0)
867 fprintf(option_usage_fp, argTypes.pzBrk, zAuto, pOptTitle);
869 } else if ((ct == 1) &&
870 (pOpts->fOptSet & OPTPROC_VENDOR_OPT))
871 fprintf(option_usage_fp, argTypes.pzBrk, zVendIntro, pOptTitle);
874 prt_one_usage(pOpts, pOD, &argTypes);
877 * IF we were invoked because of the --help option,
878 * THEN print all the extra info
880 if (ex_code == EXIT_SUCCESS)
881 prt_extd_usage(pOpts, pOD, pOptTitle);
883 } while (pOD++, optNo++, (--ct > 0));
885 fputc(NL, option_usage_fp);
889 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
891 * PROGRAM DETAILS
893 static void
894 prt_prog_detail(tOptions* pOptions)
896 bool initIntro = true;
899 * Display all the places we look for config files
901 prt_ini_list(pOptions->papzHomeList, &initIntro,
902 pOptions->pzRcName, pOptions->pzProgPath);
905 * Let the user know about environment variable settings
907 if ((pOptions->fOptSet & OPTPROC_ENVIRON) != 0) {
908 if (initIntro)
909 fputs(zPresetIntro, option_usage_fp);
911 fprintf(option_usage_fp, zExamineFmt, pOptions->pzPROGNAME);
915 * IF we found an enumeration,
916 * THEN hunt for it again. Call the handler proc with a NULL
917 * option struct pointer. That tells it to display the keywords.
919 if (displayEnum) {
920 int ct = pOptions->optCt;
921 int optNo = 0;
922 tOptDesc* pOD = pOptions->pOptDesc;
924 fputc(NL, option_usage_fp);
925 fflush(option_usage_fp);
926 do {
927 switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
928 case OPARG_TYPE_ENUMERATION:
929 case OPARG_TYPE_MEMBERSHIP:
930 (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD);
932 } while (pOD++, optNo++, (--ct > 0));
936 * If there is a detail string, now is the time for that.
938 if (pOptions->pzDetail != NULL)
939 fputs(pOptions->pzDetail, option_usage_fp);
943 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
945 * OPTION LINE FORMATTING SETUP
947 * The "OptFmt" formats receive three arguments:
948 * 1. the type of the option's argument
949 * 2. the long name of the option
950 * 3. "YES" or "no ", depending on whether or not the option must appear
951 * on the command line.
952 * These formats are used immediately after the option flag (if used) has
953 * been printed.
955 * Set up the formatting for GNU-style output
957 static int
958 setGnuOptFmts(tOptions* pOpts, tCC** ppT)
960 static char const zOneSpace[] = " ";
961 int flen = 22;
962 *ppT = zNoRq_ShrtTtl;
964 argTypes.pzStr = zGnuStrArg;
965 argTypes.pzReq = zOneSpace;
966 argTypes.pzNum = zGnuNumArg;
967 argTypes.pzKey = zGnuKeyArg;
968 argTypes.pzKeyL = zGnuKeyLArg;
969 argTypes.pzTime = zGnuTimeArg;
970 argTypes.pzFile = zGnuFileArg;
971 argTypes.pzBool = zGnuBoolArg;
972 argTypes.pzNest = zGnuNestArg;
973 argTypes.pzOpt = zGnuOptArg;
974 argTypes.pzNo = zOneSpace;
975 argTypes.pzBrk = zGnuBreak;
976 argTypes.pzNoF = zSixSpaces;
977 argTypes.pzSpc = zThreeSpaces;
979 switch (pOpts->fOptSet & OPTPROC_L_N_S) {
980 case OPTPROC_L_N_S: argTypes.pzOptFmt = zGnuOptFmt; break;
981 case OPTPROC_LONGOPT: argTypes.pzOptFmt = zGnuOptFmt; break;
982 case 0: argTypes.pzOptFmt = zGnuOptFmt + 2; break;
983 case OPTPROC_SHORTOPT:
984 argTypes.pzOptFmt = zShrtGnuOptFmt;
985 zGnuStrArg[0] = zGnuNumArg[0] = zGnuKeyArg[0] = zGnuBoolArg[0] = ' ';
986 argTypes.pzOpt = " [arg]";
987 flen = 8;
988 break;
991 return flen;
996 * Standard (AutoOpts normal) option line formatting
998 static int
999 setStdOptFmts(tOptions* pOpts, tCC** ppT)
1001 int flen = 0;
1003 argTypes.pzStr = zStdStrArg;
1004 argTypes.pzReq = zStdReqArg;
1005 argTypes.pzNum = zStdNumArg;
1006 argTypes.pzKey = zStdKeyArg;
1007 argTypes.pzKeyL = zStdKeyLArg;
1008 argTypes.pzTime = zStdTimeArg;
1009 argTypes.pzFile = zStdFileArg;
1010 argTypes.pzBool = zStdBoolArg;
1011 argTypes.pzNest = zStdNestArg;
1012 argTypes.pzOpt = zStdOptArg;
1013 argTypes.pzNo = zStdNoArg;
1014 argTypes.pzBrk = zStdBreak;
1015 argTypes.pzNoF = zFiveSpaces;
1016 argTypes.pzSpc = zTwoSpaces;
1018 switch (pOpts->fOptSet & (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT)) {
1019 case (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT):
1020 *ppT = zNoRq_ShrtTtl;
1021 argTypes.pzOptFmt = zNrmOptFmt;
1022 flen = 19;
1023 break;
1025 case OPTPROC_NO_REQ_OPT:
1026 *ppT = zNoRq_NoShrtTtl;
1027 argTypes.pzOptFmt = zNrmOptFmt;
1028 flen = 19;
1029 break;
1031 case OPTPROC_SHORTOPT:
1032 *ppT = zReq_ShrtTtl;
1033 argTypes.pzOptFmt = zReqOptFmt;
1034 flen = 24;
1035 break;
1037 case 0:
1038 *ppT = zReq_NoShrtTtl;
1039 argTypes.pzOptFmt = zReqOptFmt;
1040 flen = 24;
1043 return flen;
1048 * Local Variables:
1049 * mode: C
1050 * c-file-style: "stroustrup"
1051 * indent-tabs-mode: nil
1052 * End:
1053 * end of autoopts/usage.c */