1:
2: /*
3: * \file usage.c
4: *
5: * Time-stamp: "2011-02-01 14:42:37 bkorb"
6: *
7: * This module implements the default usage procedure for
8: * Automated Options. It may be overridden, of course.
9: *
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
14: */
15:
16: /*
17: * This file is part of AutoOpts, a companion to AutoGen.
18: * AutoOpts is free software.
19: * AutoOpts is Copyright (c) 1992-2011 by Bruce Korb - all rights reserved
20: *
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.
24: *
25: * The GNU Lesser General Public License, version 3 or later
26: * See the files "COPYING.lgplv3" and "COPYING.gplv3"
27: *
28: * The Modified Berkeley Software Distribution License
29: * See the file "COPYING.mbsd"
30: *
31: * These files have the following md5sums:
32: *
33: * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3
34: * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3
35: * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
36: */
37:
38: #define OPTPROC_L_N_S (OPTPROC_LONGOPT | OPTPROC_SHORTOPT)
39:
40: /* = = = START-STATIC-FORWARD = = = */
41: static void
42: set_usage_flags(tOptions * opts, char const * flg_txt);
43:
44: static inline ag_bool
45: do_gnu_usage(tOptions * pOpts);
46:
47: static inline ag_bool
48: skip_misuse_usage(tOptions * pOpts);
49:
50: static void
51: print_usage_details(tOptions * opts, int exit_code);
52:
53: static void
54: prt_extd_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT);
55:
56: static void
57: prt_ini_list(char const * const * papz, ag_bool * pInitIntro,
58: char const * pzRc, char const * pzPN);
59:
60: static void
61: prt_preamble(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT);
62:
63: static void
64: prt_one_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT);
65:
66: static void
67: prt_opt_usage(tOptions * pOpts, int ex_code, char const * pOptTitle);
68:
69: static void
70: prt_prog_detail(tOptions* pOptions);
71:
72: static int
73: setGnuOptFmts(tOptions* pOpts, tCC** ppT);
74:
75: static int
76: setStdOptFmts(tOptions* pOpts, tCC** ppT);
77: /* = = = END-STATIC-FORWARD = = = */
78:
79: /*
80: * NB: no entry may be a prefix of another entry
81: */
82: #define AOFLAG_TABLE \
83: _aof_(gnu, OPTPROC_GNUUSAGE ) \
84: _aof_(autoopts, ~OPTPROC_GNUUSAGE) \
85: _aof_(no_misuse_usage, OPTPROC_MISUSE ) \
86: _aof_(misuse_usage, ~OPTPROC_MISUSE )
87:
88: static void
89: set_usage_flags(tOptions * opts, char const * flg_txt)
90: {
91: typedef struct {
92: size_t fnm_len;
93: uint32_t fnm_mask;
94: char const * fnm_name;
95: } ao_flag_names_t;
96:
97: # define _aof_(_n, _f) AOUF_ ## _n ## _ID,
98: typedef enum { AOFLAG_TABLE AOUF_COUNT } ao_flag_id_t;
99: # undef _aof_
100:
101: # define _aof_(_n, _f) AOUF_ ## _n = (1 << AOUF_ ## _n ## _ID),
102: typedef enum { AOFLAG_TABLE } ao_flags_t;
103: # undef _aof_
104:
105: # define _aof_(_n, _f) { sizeof(#_n)-1, _f, #_n },
106: static ao_flag_names_t const fn_table[AOUF_COUNT] = {
107: AOFLAG_TABLE
108: };
109: # undef _aof_
110:
111: ao_flags_t flg = 0;
112:
113: if (flg_txt == NULL) {
114: flg_txt = getenv("AUTOOPTS_USAGE");
115: if (flg_txt == NULL)
116: return;
117: }
118:
119: while (IS_WHITESPACE_CHAR(*flg_txt)) flg_txt++;
120: if (*flg_txt == NUL)
121: return;
122:
123: for (;;) {
124: int ix = 0;
125: ao_flag_names_t const * fnt = fn_table;
126:
127: for (;;) {
128: if (strneqvcmp(flg_txt, fnt->fnm_name, fnt->fnm_len) == 0)
129: break;
130: if (++ix >= AOUF_COUNT)
131: return;
132: fnt++;
133: }
134:
135: /*
136: * Make sure we have a full match. Look for whitespace,
137: * a comma, or a NUL byte.
138: */
139: if (! IS_END_LIST_ENTRY_CHAR(flg_txt[fnt->fnm_len]))
140: return;
141:
142: flg |= 1 << ix;
143: flg_txt += fnt->fnm_len;
144: while (IS_WHITESPACE_CHAR(*flg_txt)) flg_txt++;
145:
146: if (*flg_txt == NUL)
147: break;
148:
149: if (*flg_txt == ',') {
150: /*
151: * skip the comma and following white space
152: */
153: while (IS_WHITESPACE_CHAR(*++flg_txt)) ;
154: if (*flg_txt == NUL)
155: break;
156: }
157: }
158:
159: {
160: ao_flag_names_t const * fnm = fn_table;
161:
162: while (flg != 0) {
163: if ((flg & 1) != 0) {
164: if ((fnm->fnm_mask & OPTPROC_LONGOPT) != 0)
165: opts->fOptSet &= fnm->fnm_mask;
166: else opts->fOptSet |= fnm->fnm_mask;
167: }
168: flg >>= 1;
169: fnm++;
170: }
171: }
172: }
173:
174: /*
175: * Figure out if we should try to format usage text sort-of like
176: * the way many GNU programs do.
177: */
178: static inline ag_bool
179: do_gnu_usage(tOptions * pOpts)
180: {
181: return (pOpts->fOptSet & OPTPROC_GNUUSAGE) ? AG_TRUE : AG_FALSE;
182: }
183:
184: /*
185: * Figure out if we should try to format usage text sort-of like
186: * the way many GNU programs do.
187: */
188: static inline ag_bool
189: skip_misuse_usage(tOptions * pOpts)
190: {
191: return (pOpts->fOptSet & OPTPROC_MISUSE) ? AG_TRUE : AG_FALSE;
192: }
193:
194:
195: /*=export_func optionOnlyUsage
196: *
197: * what: Print usage text for just the options
198: * arg: + tOptions* + pOpts + program options descriptor +
199: * arg: + int + ex_code + exit code for calling exit(3) +
200: *
201: * doc:
202: * This routine will print only the usage for each option.
203: * This function may be used when the emitted usage must incorporate
204: * information not available to AutoOpts.
205: =*/
206: void
207: optionOnlyUsage(tOptions * pOpts, int ex_code)
208: {
209: char const * pOptTitle = NULL;
210:
211: set_usage_flags(pOpts, NULL);
212: if ((ex_code != EXIT_SUCCESS) &&
213: skip_misuse_usage(pOpts))
214: return;
215:
216: /*
217: * Determine which header and which option formatting strings to use
218: */
219: if (do_gnu_usage(pOpts)) {
220: (void)setGnuOptFmts(pOpts, &pOptTitle);
221: }
222: else {
223: (void)setStdOptFmts(pOpts, &pOptTitle);
224: }
225:
226: prt_opt_usage(pOpts, ex_code, pOptTitle);
227:
228: fflush(option_usage_fp);
229: if (ferror(option_usage_fp) != 0) {
230: fputs(zOutputFail, stderr);
231: exit(EXIT_FAILURE);
232: }
233: }
234:
235: static void
236: print_usage_details(tOptions * opts, int exit_code)
237: {
238: {
239: char const * pOptTitle = NULL;
240:
241: /*
242: * Determine which header and which option formatting strings to use
243: */
244: if (do_gnu_usage(opts)) {
245: int flen = setGnuOptFmts(opts, &pOptTitle);
246: sprintf(zOptFmtLine, zFmtFmt, flen);
247: fputc('\n', option_usage_fp);
248: }
249: else {
250: int flen = setStdOptFmts(opts, &pOptTitle);
251: sprintf(zOptFmtLine, zFmtFmt, flen);
252:
253: /*
254: * When we exit with EXIT_SUCCESS and the first option is a doc
255: * option, we do *NOT* want to emit the column headers.
256: * Otherwise, we do.
257: */
258: if ( (exit_code != EXIT_SUCCESS)
259: || ((opts->pOptDesc->fOptState & OPTST_DOCUMENT) == 0) )
260:
261: fputs(pOptTitle, option_usage_fp);
262: }
263:
264: prt_opt_usage(opts, exit_code, pOptTitle);
265: }
266:
267: /*
268: * Describe the mechanics of denoting the options
269: */
270: switch (opts->fOptSet & OPTPROC_L_N_S) {
271: case OPTPROC_L_N_S: fputs(zFlagOkay, option_usage_fp); break;
272: case OPTPROC_SHORTOPT: break;
273: case OPTPROC_LONGOPT: fputs(zNoFlags, option_usage_fp); break;
274: case 0: fputs(zOptsOnly, option_usage_fp); break;
275: }
276:
277: if ((opts->fOptSet & OPTPROC_NUM_OPT) != 0)
278: fputs(zNumberOpt, option_usage_fp);
279:
280: if ((opts->fOptSet & OPTPROC_REORDER) != 0)
281: fputs(zReorder, option_usage_fp);
282:
283: if (opts->pzExplain != NULL)
284: fputs(opts->pzExplain, option_usage_fp);
285:
286: /*
287: * IF the user is asking for help (thus exiting with SUCCESS),
288: * THEN see what additional information we can provide.
289: */
290: if (exit_code == EXIT_SUCCESS)
291: prt_prog_detail(opts);
292:
293: /*
294: * Give bug notification preference to the packager information
295: */
296: if (HAS_pzPkgDataDir(opts) && (opts->pzPackager != NULL))
297: fputs(opts->pzPackager, option_usage_fp);
298:
299: else if (opts->pzBugAddr != NULL)
300: fprintf(option_usage_fp, zPlsSendBugs, opts->pzBugAddr);
301:
302: fflush(option_usage_fp);
303:
304: if (ferror(option_usage_fp) != 0) {
305: fputs(zOutputFail, stderr);
306: exit(EXIT_FAILURE);
307: }
308: }
309:
310:
311: /*=export_func optionUsage
312: * private:
313: *
314: * what: Print usage text
315: * arg: + tOptions* + pOptions + program options descriptor +
316: * arg: + int + exitCode + exit code for calling exit(3) +
317: *
318: * doc:
319: * This routine will print usage in both GNU-standard and AutoOpts-expanded
320: * formats. The descriptor specifies the default, but AUTOOPTS_USAGE will
321: * over-ride this, providing the value of it is set to either "gnu" or
322: * "autoopts". This routine will @strong{not} return.
323: *
324: * If "exitCode" is "EX_USAGE" (normally 64), then output will to to stdout
325: * and the actual exit code will be "EXIT_SUCCESS".
326: =*/
327: void
328: optionUsage(tOptions * pOptions, int usage_exit_code)
329: {
330: int exit_code =
331: (usage_exit_code == EX_USAGE) ? EXIT_SUCCESS : usage_exit_code;
332:
333: displayEnum = AG_FALSE;
334:
335: /*
336: * Paged usage will preset option_usage_fp to an output file.
337: * If it hasn't already been set, then set it to standard output
338: * on successful exit (help was requested), otherwise error out.
339: *
340: * Test the version before obtaining pzFullUsage or pzShortUsage.
341: * These fields do not exist before revision 30.
342: */
343: {
344: char const * pz;
345:
346: if (exit_code == EXIT_SUCCESS) {
347: pz = (pOptions->structVersion >= 30 * 4096)
348: ? pOptions->pzFullUsage : NULL;
349:
350: if (option_usage_fp == NULL)
351: option_usage_fp = stdout;
352: } else {
353: pz = (pOptions->structVersion >= 30 * 4096)
354: ? pOptions->pzShortUsage : NULL;
355:
356: if (option_usage_fp == NULL)
357: option_usage_fp = stderr;
358: }
359:
360: if (pz != NULL) {
361: fputs(pz, option_usage_fp);
362: exit(exit_code);
363: }
364: }
365:
366: fprintf(option_usage_fp, pOptions->pzUsageTitle, pOptions->pzProgName);
367: set_usage_flags(pOptions, NULL);
368:
369: if ((exit_code == EXIT_SUCCESS) ||
370: (! skip_misuse_usage(pOptions)))
371:
372: print_usage_details(pOptions, usage_exit_code);
373:
374: exit(exit_code);
375: }
376:
377:
378: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
379: *
380: * PER OPTION TYPE USAGE INFORMATION
381: */
382: static void
383: prt_extd_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT)
384: {
385: /*
386: * IF there are option conflicts or dependencies,
387: * THEN print them here.
388: */
389: if ( (pOD->pOptMust != NULL)
390: || (pOD->pOptCant != NULL) ) {
391:
392: fputs(zTabHyp, option_usage_fp);
393:
394: /*
395: * DEPENDENCIES:
396: */
397: if (pOD->pOptMust != NULL) {
398: const int* pOptNo = pOD->pOptMust;
399:
400: fputs(zReqThese, option_usage_fp);
401: for (;;) {
402: fprintf(option_usage_fp, zTabout,
403: pOptions->pOptDesc[*pOptNo].pz_Name);
404: if (*++pOptNo == NO_EQUIVALENT)
405: break;
406: }
407:
408: if (pOD->pOptCant != NULL)
409: fputs(zTabHypAnd, option_usage_fp);
410: }
411:
412: /*
413: * CONFLICTS:
414: */
415: if (pOD->pOptCant != NULL) {
416: const int* pOptNo = pOD->pOptCant;
417:
418: fputs(zProhib, option_usage_fp);
419: for (;;) {
420: fprintf(option_usage_fp, zTabout,
421: pOptions->pOptDesc[*pOptNo].pz_Name);
422: if (*++pOptNo == NO_EQUIVALENT)
423: break;
424: }
425: }
426: }
427:
428: /*
429: * IF there is a disablement string
430: * THEN print the disablement info
431: */
432: if (pOD->pz_DisableName != NULL )
433: fprintf(option_usage_fp, zDis, pOD->pz_DisableName);
434:
435: /*
436: * Check for argument types that have callbacks with magical properties
437: */
438: switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
439: case OPARG_TYPE_NUMERIC:
440: /*
441: * IF the numeric option has a special callback,
442: * THEN call it, requesting the range or other special info
443: */
444: if ( (pOD->pOptProc != NULL)
445: && (pOD->pOptProc != optionNumericVal) ) {
446: (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD);
447: }
448: break;
449:
450: case OPARG_TYPE_FILE:
451: (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD);
452: break;
453: }
454:
455: /*
456: * IF the option defaults to being enabled,
457: * THEN print that out
458: */
459: if (pOD->fOptState & OPTST_INITENABLED)
460: fputs(zEnab, option_usage_fp);
461:
462: /*
463: * IF the option is in an equivalence class
464: * AND not the designated lead
465: * THEN print equivalence and leave it at that.
466: */
467: if ( (pOD->optEquivIndex != NO_EQUIVALENT)
468: && (pOD->optEquivIndex != pOD->optActualIndex ) ) {
469: fprintf(option_usage_fp, zAlt,
470: pOptions->pOptDesc[ pOD->optEquivIndex ].pz_Name);
471: return;
472: }
473:
474: /*
475: * IF this particular option can NOT be preset
476: * AND some form of presetting IS allowed,
477: * AND it is not an auto-managed option (e.g. --help, et al.)
478: * THEN advise that this option may not be preset.
479: */
480: if ( ((pOD->fOptState & OPTST_NO_INIT) != 0)
481: && ( (pOptions->papzHomeList != NULL)
482: || (pOptions->pzPROGNAME != NULL)
483: )
484: && (pOD->optIndex < pOptions->presetOptCt)
485: )
486:
487: fputs(zNoPreset, option_usage_fp);
488:
489: /*
490: * Print the appearance requirements.
491: */
492: if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP)
493: fputs(zMembers, option_usage_fp);
494:
495: else switch (pOD->optMinCt) {
496: case 1:
497: case 0:
498: switch (pOD->optMaxCt) {
499: case 0: fputs(zPreset, option_usage_fp); break;
500: case NOLIMIT: fputs(zNoLim, option_usage_fp); break;
501: case 1: break;
502: /*
503: * IF the max is more than one but limited, print "UP TO" message
504: */
505: default: fprintf(option_usage_fp, zUpTo, pOD->optMaxCt); break;
506: }
507: break;
508:
509: default:
510: /*
511: * More than one is required. Print the range.
512: */
513: fprintf(option_usage_fp, zMust, pOD->optMinCt, pOD->optMaxCt);
514: }
515:
516: if ( NAMED_OPTS(pOptions)
517: && (pOptions->specOptIdx.default_opt == pOD->optIndex))
518: fputs(zDefaultOpt, option_usage_fp);
519: }
520:
521:
522: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
523: *
524: * Figure out where all the initialization files might live.
525: * This requires translating some environment variables and
526: * testing to see if a name is a directory or a file. It's
527: * squishy, but important to tell users how to find these files.
528: */
529: static void
530: prt_ini_list(char const * const * papz, ag_bool * pInitIntro,
531: char const * pzRc, char const * pzPN)
532: {
533: char zPath[AG_PATH_MAX+1];
534:
535: if (papz == NULL)
536: return;
537:
538: fputs(zPresetIntro, option_usage_fp);
539: *pInitIntro = AG_FALSE;
540:
541: for (;;) {
542: char const * pzPath = *(papz++);
543: char const * pzReal = zPath;
544:
545: if (pzPath == NULL)
546: break;
547:
548: /*
549: * Ignore any invalid paths
550: */
551: if (! optionMakePath(zPath, (int)sizeof(zPath), pzPath, pzPN))
552: pzReal = pzPath;
553:
554: /*
555: * Expand paths that are relative to the executable or installation
556: * directories. Leave alone paths that use environment variables.
557: */
558: else if ((*pzPath == '$')
559: && ((pzPath[1] == '$') || (pzPath[1] == '@')))
560: pzPath = pzReal;
561:
562: /*
563: * Print the name of the "homerc" file. If the "rcfile" name is
564: * not empty, we may or may not print that, too...
565: */
566: fprintf(option_usage_fp, zPathFmt, pzPath);
567: if (*pzRc != NUL) {
568: struct stat sb;
569:
570: /*
571: * IF the "homerc" file is a directory,
572: * then append the "rcfile" name.
573: */
574: if ((stat(pzReal, &sb) == 0) && S_ISDIR(sb.st_mode)) {
575: fputc(DIRCH, option_usage_fp);
576: fputs(pzRc, option_usage_fp);
577: }
578: }
579:
580: fputc('\n', option_usage_fp);
581: }
582: }
583:
584:
585: static void
586: prt_preamble(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT)
587: {
588: /*
589: * Flag prefix: IF no flags at all, then omit it. If not printable
590: * (not allowed for this option), then blank, else print it.
591: * Follow it with a comma if we are doing GNU usage and long
592: * opts are to be printed too.
593: */
594: if ((pOptions->fOptSet & OPTPROC_SHORTOPT) == 0)
595: fputs(pAT->pzSpc, option_usage_fp);
596:
597: else if (! IS_GRAPHIC_CHAR(pOD->optValue)) {
598: if ( (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
599: == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
600: fputc(' ', option_usage_fp);
601: fputs(pAT->pzNoF, option_usage_fp);
602:
603: } else {
604: fprintf(option_usage_fp, " -%c", pOD->optValue);
605: if ( (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
606: == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
607: fputs(", ", option_usage_fp);
608: }
609: }
610:
611: /*
612: * Print the usage information for a single option.
613: */
614: static void
615: prt_one_usage(tOptions * pOptions, tOptDesc * pOD, arg_types_t * pAT)
616: {
617: prt_preamble(pOptions, pOD, pAT);
618:
619: {
620: char z[ 80 ];
621: char const * pzArgType;
622:
623: /*
624: * Determine the argument type string first on its usage, then,
625: * when the option argument is required, base the type string on the
626: * argument type.
627: */
628: if (pOD->fOptState & OPTST_ARG_OPTIONAL) {
629: pzArgType = pAT->pzOpt;
630:
631: } else switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
632: case OPARG_TYPE_NONE: pzArgType = pAT->pzNo; break;
633: case OPARG_TYPE_ENUMERATION: pzArgType = pAT->pzKey; break;
634: case OPARG_TYPE_FILE: pzArgType = pAT->pzFile; break;
635: case OPARG_TYPE_MEMBERSHIP: pzArgType = pAT->pzKeyL; break;
636: case OPARG_TYPE_BOOLEAN: pzArgType = pAT->pzBool; break;
637: case OPARG_TYPE_NUMERIC: pzArgType = pAT->pzNum; break;
638: case OPARG_TYPE_HIERARCHY: pzArgType = pAT->pzNest; break;
639: case OPARG_TYPE_STRING: pzArgType = pAT->pzStr; break;
640: case OPARG_TYPE_TIME: pzArgType = pAT->pzTime; break;
641: default: goto bogus_desc;
642: }
643:
644: snprintf(z, sizeof(z), pAT->pzOptFmt, pzArgType, pOD->pz_Name,
645: (pOD->optMinCt != 0) ? pAT->pzReq : pAT->pzOpt);
646:
647: fprintf(option_usage_fp, zOptFmtLine, z, pOD->pzText);
648:
649: switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
650: case OPARG_TYPE_ENUMERATION:
651: case OPARG_TYPE_MEMBERSHIP:
652: displayEnum = (pOD->pOptProc != NULL) ? AG_TRUE : displayEnum;
653: }
654: }
655: return;
656:
657: bogus_desc:
658: fprintf(stderr, zInvalOptDesc, pOD->pz_Name);
659: exit(EX_SOFTWARE);
660: }
661:
662:
663: /*
664: * Print out the usage information for just the options.
665: */
666: static void
667: prt_opt_usage(tOptions * pOpts, int ex_code, char const * pOptTitle)
668: {
669: int ct = pOpts->optCt;
670: int optNo = 0;
671: tOptDesc * pOD = pOpts->pOptDesc;
672: int docCt = 0;
673:
674: do {
675: if ((pOD->fOptState & OPTST_NO_USAGE_MASK) != 0) {
676:
677: /*
678: * IF this is a compiled-out option
679: * *AND* usage was requested with "omitted-usage"
680: * *AND* this is NOT abbreviated usage
681: * THEN display this option.
682: */
683: if ( (pOD->fOptState == (OPTST_OMITTED | OPTST_NO_INIT))
684: && (pOD->pz_Name != NULL)
685: && (ex_code == EXIT_SUCCESS)) {
686:
687: char const * why_pz =
688: (pOD->pzText == NULL) ? zDisabledWhy : pOD->pzText;
689: prt_preamble(pOpts, pOD, &argTypes);
690: fprintf(option_usage_fp, zDisabledOpt, pOD->pz_Name, why_pz);
691: }
692:
693: continue;
694: }
695:
696: if ((pOD->fOptState & OPTST_DOCUMENT) != 0) {
697: if (ex_code == EXIT_SUCCESS) {
698: fprintf(option_usage_fp, argTypes.pzBrk, pOD->pzText,
699: pOptTitle);
700: docCt++;
701: }
702:
703: continue;
704: }
705:
706: /*
707: * IF this is the first auto-opt maintained option
708: * *AND* we are doing a full help
709: * *AND* there are documentation options
710: * *AND* the last one was not a doc option,
711: * THEN document that the remaining options are not user opts
712: */
713: if ( (pOpts->presetOptCt == optNo)
714: && (ex_code == EXIT_SUCCESS)
715: && (docCt > 0)
716: && ((pOD[-1].fOptState & OPTST_DOCUMENT) == 0) )
717: fprintf(option_usage_fp, argTypes.pzBrk, zAuto, pOptTitle);
718:
719: prt_one_usage(pOpts, pOD, &argTypes);
720:
721: /*
722: * IF we were invoked because of the --help option,
723: * THEN print all the extra info
724: */
725: if (ex_code == EXIT_SUCCESS)
726: prt_extd_usage(pOpts, pOD, &argTypes);
727:
728: } while (pOD++, optNo++, (--ct > 0));
729:
730: fputc('\n', option_usage_fp);
731: }
732:
733:
734: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
735: *
736: * PROGRAM DETAILS
737: */
738: static void
739: prt_prog_detail(tOptions* pOptions)
740: {
741: ag_bool initIntro = AG_TRUE;
742:
743: /*
744: * Display all the places we look for config files
745: */
746: prt_ini_list(pOptions->papzHomeList, &initIntro,
747: pOptions->pzRcName, pOptions->pzProgPath);
748:
749: /*
750: * Let the user know about environment variable settings
751: */
752: if ((pOptions->fOptSet & OPTPROC_ENVIRON) != 0) {
753: if (initIntro)
754: fputs(zPresetIntro, option_usage_fp);
755:
756: fprintf(option_usage_fp, zExamineFmt, pOptions->pzPROGNAME);
757: }
758:
759: /*
760: * IF we found an enumeration,
761: * THEN hunt for it again. Call the handler proc with a NULL
762: * option struct pointer. That tells it to display the keywords.
763: */
764: if (displayEnum) {
765: int ct = pOptions->optCt;
766: int optNo = 0;
767: tOptDesc* pOD = pOptions->pOptDesc;
768:
769: fputc('\n', option_usage_fp);
770: fflush(option_usage_fp);
771: do {
772: switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
773: case OPARG_TYPE_ENUMERATION:
774: case OPARG_TYPE_MEMBERSHIP:
775: (*(pOD->pOptProc))(OPTPROC_EMIT_USAGE, pOD);
776: }
777: } while (pOD++, optNo++, (--ct > 0));
778: }
779:
780: /*
781: * If there is a detail string, now is the time for that.
782: */
783: if (pOptions->pzDetail != NULL)
784: fputs(pOptions->pzDetail, option_usage_fp);
785: }
786:
787:
788: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
789: *
790: * OPTION LINE FORMATTING SETUP
791: *
792: * The "OptFmt" formats receive three arguments:
793: * 1. the type of the option's argument
794: * 2. the long name of the option
795: * 3. "YES" or "no ", depending on whether or not the option must appear
796: * on the command line.
797: * These formats are used immediately after the option flag (if used) has
798: * been printed.
799: *
800: * Set up the formatting for GNU-style output
801: */
802: static int
803: setGnuOptFmts(tOptions* pOpts, tCC** ppT)
804: {
805: int flen = 22;
806: *ppT = zNoRq_ShrtTtl;
807:
808: argTypes.pzStr = zGnuStrArg;
809: argTypes.pzReq = zOneSpace;
810: argTypes.pzNum = zGnuNumArg;
811: argTypes.pzKey = zGnuKeyArg;
812: argTypes.pzKeyL = zGnuKeyLArg;
813: argTypes.pzTime = zGnuTimeArg;
814: argTypes.pzFile = zGnuFileArg;
815: argTypes.pzBool = zGnuBoolArg;
816: argTypes.pzNest = zGnuNestArg;
817: argTypes.pzOpt = zGnuOptArg;
818: argTypes.pzNo = zOneSpace;
819: argTypes.pzBrk = zGnuBreak;
820: argTypes.pzNoF = zSixSpaces;
821: argTypes.pzSpc = zThreeSpaces;
822:
823: switch (pOpts->fOptSet & OPTPROC_L_N_S) {
824: case OPTPROC_L_N_S: argTypes.pzOptFmt = zGnuOptFmt; break;
825: case OPTPROC_LONGOPT: argTypes.pzOptFmt = zGnuOptFmt; break;
826: case 0: argTypes.pzOptFmt = zGnuOptFmt + 2; break;
827: case OPTPROC_SHORTOPT:
828: argTypes.pzOptFmt = zShrtGnuOptFmt;
829: zGnuStrArg[0] = zGnuNumArg[0] = zGnuKeyArg[0] = zGnuBoolArg[0] = ' ';
830: argTypes.pzOpt = " [arg]";
831: flen = 8;
832: break;
833: }
834:
835: return flen;
836: }
837:
838:
839: /*
840: * Standard (AutoOpts normal) option line formatting
841: */
842: static int
843: setStdOptFmts(tOptions* pOpts, tCC** ppT)
844: {
845: int flen = 0;
846:
847: argTypes.pzStr = zStdStrArg;
848: argTypes.pzReq = zStdReqArg;
849: argTypes.pzNum = zStdNumArg;
850: argTypes.pzKey = zStdKeyArg;
851: argTypes.pzKeyL = zStdKeyLArg;
852: argTypes.pzTime = zStdTimeArg;
853: argTypes.pzFile = zStdFileArg;
854: argTypes.pzBool = zStdBoolArg;
855: argTypes.pzNest = zStdNestArg;
856: argTypes.pzOpt = zStdOptArg;
857: argTypes.pzNo = zStdNoArg;
858: argTypes.pzBrk = zStdBreak;
859: argTypes.pzNoF = zFiveSpaces;
860: argTypes.pzSpc = zTwoSpaces;
861:
862: switch (pOpts->fOptSet & (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT)) {
863: case (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT):
864: *ppT = zNoRq_ShrtTtl;
865: argTypes.pzOptFmt = zNrmOptFmt;
866: flen = 19;
867: break;
868:
869: case OPTPROC_NO_REQ_OPT:
870: *ppT = zNoRq_NoShrtTtl;
871: argTypes.pzOptFmt = zNrmOptFmt;
872: flen = 19;
873: break;
874:
875: case OPTPROC_SHORTOPT:
876: *ppT = zReq_ShrtTtl;
877: argTypes.pzOptFmt = zReqOptFmt;
878: flen = 24;
879: break;
880:
881: case 0:
882: *ppT = zReq_NoShrtTtl;
883: argTypes.pzOptFmt = zReqOptFmt;
884: flen = 24;
885: }
886:
887: return flen;
888: }
889:
890:
891: /*:
892: * Local Variables:
893: * mode: C
894: * c-file-style: "stroustrup"
895: * indent-tabs-mode: nil
896: * End:
897: * end of autoopts/usage.c */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>