usage.c 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336
  1. /*
  2. * \file usage.c
  3. *
  4. * This module implements the default usage procedure for
  5. * Automated Options. It may be overridden, of course.
  6. *
  7. * @addtogroup autoopts
  8. * @{
  9. */
  10. /*
  11. * Sort options:
  12. --start=END-[S]TATIC-FORWARD --patt='^/\*($|[^:])' \
  13. --out=xx.c key='^[a-zA-Z0-9_]+\(' --trail='^/\*:' \
  14. --spac=2 --input=usage.c
  15. */
  16. /*
  17. * This file is part of AutoOpts, a companion to AutoGen.
  18. * AutoOpts is free software.
  19. * AutoOpts is Copyright (C) 1992-2014 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 sha256 sums:
  32. *
  33. * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3
  34. * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3
  35. * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd
  36. */
  37. /* = = = START-STATIC-FORWARD = = = */
  38. static unsigned int
  39. parse_usage_flags(ao_flag_names_t const * fnt, char const * txt);
  40. static inline bool
  41. do_gnu_usage(tOptions * pOpts);
  42. static inline bool
  43. skip_misuse_usage(tOptions * pOpts);
  44. static void
  45. print_offer_usage(tOptions * opts);
  46. static void
  47. print_usage_details(tOptions * opts, int exit_code);
  48. static void
  49. print_one_paragraph(char const * text, bool plain, FILE * fp);
  50. static void
  51. prt_conflicts(tOptions * opts, tOptDesc * od);
  52. static void
  53. prt_one_vendor(tOptions * opts, tOptDesc * od,
  54. arg_types_t * argtp, char const * usefmt);
  55. static void
  56. prt_vendor_opts(tOptions * opts, char const * title);
  57. static void
  58. prt_extd_usage(tOptions * opts, tOptDesc * od, char const * title);
  59. static void
  60. prt_ini_list(char const * const * papz, char const * ini_file,
  61. char const * path_nm);
  62. static void
  63. prt_preamble(tOptions * opts, tOptDesc * od, arg_types_t * at);
  64. static void
  65. prt_one_usage(tOptions * opts, tOptDesc * od, arg_types_t * at);
  66. static void
  67. prt_opt_usage(tOptions * opts, int ex_code, char const * title);
  68. static void
  69. prt_prog_detail(tOptions * opts);
  70. static int
  71. setGnuOptFmts(tOptions * opts, char const ** ptxt);
  72. static int
  73. setStdOptFmts(tOptions * opts, char const ** ptxt);
  74. /* = = = END-STATIC-FORWARD = = = */
  75. /**
  76. * Parse the option usage flags string. Any parsing problems yield
  77. * a zero (no flags set) result. This function is internal to
  78. * set_usage_flags().
  79. *
  80. * @param[in] fnt Flag Name Table - maps a name to a mask
  81. * @param[in] txt the text to process. If NULL, then
  82. * getenv("AUTOOPTS_USAGE") is used.
  83. * @returns a bit mask indicating which \a fnt entries were found.
  84. */
  85. static unsigned int
  86. parse_usage_flags(ao_flag_names_t const * fnt, char const * txt)
  87. {
  88. unsigned int res = 0;
  89. /*
  90. * The text may be passed in. If not, use the environment variable.
  91. */
  92. if (txt == NULL) {
  93. txt = getenv("AUTOOPTS_USAGE");
  94. if (txt == NULL)
  95. return 0;
  96. }
  97. txt = SPN_WHITESPACE_CHARS(txt);
  98. if (*txt == NUL)
  99. return 0;
  100. /*
  101. * search the string for table entries. We must understand everything
  102. * we see in the string, or we give up on it.
  103. */
  104. for (;;) {
  105. int ix = 0;
  106. for (;;) {
  107. if (strneqvcmp(txt, fnt[ix].fnm_name, (int)fnt[ix].fnm_len) == 0)
  108. break;
  109. if (++ix >= AOUF_COUNT)
  110. return 0;
  111. }
  112. /*
  113. * Make sure we have a full match. Look for whitespace,
  114. * a comma, or a NUL byte.
  115. */
  116. if (! IS_END_LIST_ENTRY_CHAR(txt[fnt[ix].fnm_len]))
  117. return 0;
  118. res |= 1U << ix;
  119. txt = SPN_WHITESPACE_CHARS(txt + fnt[ix].fnm_len);
  120. switch (*txt) {
  121. case NUL:
  122. return res;
  123. case ',':
  124. txt = SPN_WHITESPACE_CHARS(txt + 1);
  125. /* Something must follow the comma */
  126. default:
  127. continue;
  128. }
  129. }
  130. }
  131. /**
  132. * Set option usage flags. Any parsing problems yield no changes to options.
  133. * Three different bits may be fiddled: \a OPTPROC_GNUUSAGE, \a OPTPROC_MISUSE
  134. * and \a OPTPROC_COMPUTE.
  135. *
  136. * @param[in] flg_txt text to parse. If NULL, then the AUTOOPTS_USAGE
  137. * environment variable is parsed.
  138. * @param[in,out] opts the program option descriptor
  139. */
  140. LOCAL void
  141. set_usage_flags(tOptions * opts, char const * flg_txt)
  142. {
  143. # define _aof_(_n, _f) { sizeof(#_n)-1, _f, #_n },
  144. static ao_flag_names_t const fn_table[AOUF_COUNT] = {
  145. AOFLAG_TABLE
  146. };
  147. # undef _aof_
  148. /*
  149. * the flag word holds a bit for each selected table entry.
  150. */
  151. unsigned int flg = parse_usage_flags(fn_table, flg_txt);
  152. if (flg == 0) return;
  153. /*
  154. * Ensure we do not have conflicting selections
  155. */
  156. {
  157. static unsigned int const form_mask =
  158. AOUF_gnu | AOUF_autoopts;
  159. static unsigned int const misuse_mask =
  160. AOUF_no_misuse_usage | AOUF_misuse_usage;
  161. if ( ((flg & form_mask) == form_mask)
  162. || ((flg & misuse_mask) == misuse_mask) )
  163. return;
  164. }
  165. /*
  166. * Now fiddle the fOptSet bits, based on settings.
  167. * The OPTPROC_LONGOPT bit is immutable, thus if it is set,
  168. * then fnm points to a mask off mask.
  169. */
  170. {
  171. ao_flag_names_t const * fnm = fn_table;
  172. for (;;) {
  173. if ((flg & 1) != 0) {
  174. if ((fnm->fnm_mask & OPTPROC_LONGOPT) != 0)
  175. opts->fOptSet &= fnm->fnm_mask;
  176. else opts->fOptSet |= fnm->fnm_mask;
  177. }
  178. flg >>= 1;
  179. if (flg == 0)
  180. break;
  181. fnm++;
  182. }
  183. }
  184. }
  185. /*
  186. * Figure out if we should try to format usage text sort-of like
  187. * the way many GNU programs do.
  188. */
  189. static inline bool
  190. do_gnu_usage(tOptions * pOpts)
  191. {
  192. return (pOpts->fOptSet & OPTPROC_GNUUSAGE) ? true : false;
  193. }
  194. /*
  195. * Figure out if we should try to format usage text sort-of like
  196. * the way many GNU programs do.
  197. */
  198. static inline bool
  199. skip_misuse_usage(tOptions * pOpts)
  200. {
  201. return (pOpts->fOptSet & OPTPROC_MISUSE) ? true : false;
  202. }
  203. /*=export_func optionOnlyUsage
  204. *
  205. * what: Print usage text for just the options
  206. * arg: + tOptions* + pOpts + program options descriptor +
  207. * arg: + int + ex_code + exit code for calling exit(3) +
  208. *
  209. * doc:
  210. * This routine will print only the usage for each option.
  211. * This function may be used when the emitted usage must incorporate
  212. * information not available to AutoOpts.
  213. =*/
  214. void
  215. optionOnlyUsage(tOptions * pOpts, int ex_code)
  216. {
  217. char const * pOptTitle = NULL;
  218. set_usage_flags(pOpts, NULL);
  219. if ((ex_code != EXIT_SUCCESS) &&
  220. skip_misuse_usage(pOpts))
  221. return;
  222. /*
  223. * Determine which header and which option formatting strings to use
  224. */
  225. if (do_gnu_usage(pOpts))
  226. (void)setGnuOptFmts(pOpts, &pOptTitle);
  227. else
  228. (void)setStdOptFmts(pOpts, &pOptTitle);
  229. prt_opt_usage(pOpts, ex_code, pOptTitle);
  230. fflush(option_usage_fp);
  231. if (ferror(option_usage_fp) != 0)
  232. fserr_exit(pOpts->pzProgName, zwriting, (option_usage_fp == stderr)
  233. ? zstderr_name : zstdout_name);
  234. }
  235. /**
  236. * Print a message suggesting how to get help.
  237. *
  238. * @param[in] opts the program options
  239. */
  240. static void
  241. print_offer_usage(tOptions * opts)
  242. {
  243. char help[24];
  244. if (HAS_opt_usage_t(opts)) {
  245. int ix = opts->presetOptCt;
  246. tOptDesc * od = opts->pOptDesc + ix;
  247. while (od->optUsage != AOUSE_HELP) {
  248. if (++ix >= opts->optCt)
  249. ao_bug(zmissing_help_msg);
  250. od++;
  251. }
  252. switch (opts->fOptSet & (OPTPROC_LONGOPT | OPTPROC_SHORTOPT)) {
  253. case OPTPROC_SHORTOPT:
  254. help[0] = '-';
  255. help[1] = od->optValue;
  256. help[2] = NUL;
  257. break;
  258. case OPTPROC_LONGOPT:
  259. case (OPTPROC_LONGOPT | OPTPROC_SHORTOPT):
  260. help[0] = help[1] = '-';
  261. strncpy(help + 2, od->pz_Name, 20);
  262. break;
  263. case 0:
  264. strncpy(help, od->pz_Name, 20);
  265. break;
  266. }
  267. } else {
  268. switch (opts->fOptSet & (OPTPROC_LONGOPT | OPTPROC_SHORTOPT)) {
  269. case OPTPROC_SHORTOPT:
  270. strcpy(help, "-h");
  271. break;
  272. case OPTPROC_LONGOPT:
  273. case (OPTPROC_LONGOPT | OPTPROC_SHORTOPT):
  274. strcpy(help, "--help");
  275. break;
  276. case 0:
  277. strcpy(help, "help");
  278. break;
  279. }
  280. }
  281. fprintf(option_usage_fp, zoffer_usage_fmt, opts->pzProgName, help);
  282. }
  283. /**
  284. * Print information about each option.
  285. *
  286. * @param[in] opts the program options
  287. * @param[in] exit_code whether or not there was a usage error reported.
  288. * used to select full usage versus abbreviated.
  289. */
  290. static void
  291. print_usage_details(tOptions * opts, int exit_code)
  292. {
  293. {
  294. char const * pOptTitle = NULL;
  295. int flen;
  296. /*
  297. * Determine which header and which option formatting strings to use
  298. */
  299. if (do_gnu_usage(opts)) {
  300. flen = setGnuOptFmts(opts, &pOptTitle);
  301. sprintf(line_fmt_buf, zFmtFmt, flen);
  302. fputc(NL, option_usage_fp);
  303. }
  304. else {
  305. flen = setStdOptFmts(opts, &pOptTitle);
  306. sprintf(line_fmt_buf, zFmtFmt, flen);
  307. /*
  308. * When we exit with EXIT_SUCCESS and the first option is a doc
  309. * option, we do *NOT* want to emit the column headers.
  310. * Otherwise, we do.
  311. */
  312. if ( (exit_code != EXIT_SUCCESS)
  313. || ((opts->pOptDesc->fOptState & OPTST_DOCUMENT) == 0) )
  314. fputs(pOptTitle, option_usage_fp);
  315. }
  316. flen = 4 - ((flen + 15) / 8);
  317. if (flen > 0)
  318. tab_skip_ct = flen;
  319. prt_opt_usage(opts, exit_code, pOptTitle);
  320. }
  321. /*
  322. * Describe the mechanics of denoting the options
  323. */
  324. switch (opts->fOptSet & OPTPROC_L_N_S) {
  325. case OPTPROC_L_N_S: fputs(zFlagOkay, option_usage_fp); break;
  326. case OPTPROC_SHORTOPT: break;
  327. case OPTPROC_LONGOPT: fputs(zNoFlags, option_usage_fp); break;
  328. case 0: fputs(zOptsOnly, option_usage_fp); break;
  329. }
  330. if ((opts->fOptSet & OPTPROC_NUM_OPT) != 0)
  331. fputs(zNumberOpt, option_usage_fp);
  332. if ((opts->fOptSet & OPTPROC_REORDER) != 0)
  333. fputs(zReorder, option_usage_fp);
  334. if (opts->pzExplain != NULL)
  335. fputs(opts->pzExplain, option_usage_fp);
  336. /*
  337. * IF the user is asking for help (thus exiting with SUCCESS),
  338. * THEN see what additional information we can provide.
  339. */
  340. if (exit_code == EXIT_SUCCESS)
  341. prt_prog_detail(opts);
  342. /*
  343. * Give bug notification preference to the packager information
  344. */
  345. if (HAS_pzPkgDataDir(opts) && (opts->pzPackager != NULL))
  346. fputs(opts->pzPackager, option_usage_fp);
  347. else if (opts->pzBugAddr != NULL)
  348. fprintf(option_usage_fp, zPlsSendBugs, opts->pzBugAddr);
  349. fflush(option_usage_fp);
  350. if (ferror(option_usage_fp) != 0)
  351. fserr_exit(opts->pzProgName, zwriting, (option_usage_fp == stderr)
  352. ? zstderr_name : zstdout_name);
  353. }
  354. static void
  355. print_one_paragraph(char const * text, bool plain, FILE * fp)
  356. {
  357. if (plain) {
  358. #ifdef ENABLE_NLS
  359. #ifdef HAVE_LIBINTL_H
  360. #ifdef DEBUG_ENABLED
  361. #undef gettext
  362. #endif
  363. char * buf = dgettext("libopts", text);
  364. if (buf == text)
  365. text = gettext(text);
  366. #endif /* HAVE_LIBINTL_H */
  367. #endif /* ENABLE_NLS */
  368. fputs(text, fp);
  369. }
  370. else {
  371. char const * t = optionQuoteString(text, LINE_SPLICE);
  372. fprintf(fp, PUTS_FMT, t);
  373. AGFREE((void *)t);
  374. }
  375. }
  376. /*=export_func optionPrintParagraphs
  377. * private:
  378. *
  379. * what: Print a paragraph of usage text
  380. * arg: + char const * + text + a block of text that has bee i18n-ed +
  381. * arg: + bool + plain + false -> wrap text in fputs() +
  382. * arg: + FILE * + fp + the stream file pointer for output +
  383. *
  384. * doc:
  385. * This procedure is called in two contexts: when a full or short usage text
  386. * has been provided for display, and when autogen is assembling a list of
  387. * translatable texts in the optmain.tlib template. In the former case, \a
  388. * plain is set to \a true, otherwise \a false.
  389. *
  390. * Anything less than 256 characters in size is printed as a single unit.
  391. * Otherwise, paragraphs are detected. A paragraph break is defined as just
  392. * before a non-empty line preceded by two newlines or a line that starts
  393. * with at least one space character but fewer than 8 space characters.
  394. * Lines indented with tabs or more than 7 spaces are considered continuation
  395. * lines.
  396. *
  397. * If 'plain' is true, we are emitting text for a user to see. So, if it is
  398. * true and NLS is not enabled, then just write the whole thing at once.
  399. =*/
  400. void
  401. optionPrintParagraphs(char const * text, bool plain, FILE * fp)
  402. {
  403. size_t len = strlen(text);
  404. char * buf;
  405. #ifndef ENABLE_NLS
  406. if (plain || (len < 256))
  407. #else
  408. if (len < 256)
  409. #endif
  410. {
  411. print_one_paragraph(text, plain, fp);
  412. return;
  413. }
  414. AGDUPSTR(buf, text, "ppara");
  415. text = buf;
  416. for (;;) {
  417. char * scan;
  418. if (len < 256) {
  419. done:
  420. print_one_paragraph(buf, plain, fp);
  421. break;
  422. }
  423. scan = buf;
  424. try_longer:
  425. scan = strchr(scan, NL);
  426. if (scan == NULL)
  427. goto done;
  428. if ((scan - buf) < 40) {
  429. scan++;
  430. goto try_longer;
  431. }
  432. scan++;
  433. if ((! isspace((int)*scan)) || (*scan == HT))
  434. /*
  435. * line starts with tab or non-whitespace --> continuation
  436. */
  437. goto try_longer;
  438. if (*scan == NL) {
  439. /*
  440. * Double newline -> paragraph break
  441. * Include all newlines in current paragraph.
  442. */
  443. while (*++scan == NL) /*continue*/;
  444. } else {
  445. char * p = scan;
  446. int sp_ct = 0;
  447. while (*p == ' ') {
  448. if (++sp_ct >= 8) {
  449. /*
  450. * Too many spaces --> continuation line
  451. */
  452. scan = p;
  453. goto try_longer;
  454. }
  455. p++;
  456. }
  457. }
  458. /*
  459. * "scan" points to the first character of a paragraph or the
  460. * terminating NUL byte.
  461. */
  462. {
  463. char svch = *scan;
  464. *scan = NUL;
  465. print_one_paragraph(buf, plain, fp);
  466. len -= scan - buf;
  467. if (len <= 0)
  468. break;
  469. *scan = svch;
  470. buf = scan;
  471. }
  472. }
  473. AGFREE((void *)text);
  474. }
  475. /*=export_func optionUsage
  476. * private:
  477. *
  478. * what: Print usage text
  479. * arg: + tOptions* + opts + program options descriptor +
  480. * arg: + int + exitCode + exit code for calling exit(3) +
  481. *
  482. * doc:
  483. * This routine will print usage in both GNU-standard and AutoOpts-expanded
  484. * formats. The descriptor specifies the default, but AUTOOPTS_USAGE will
  485. * over-ride this, providing the value of it is set to either "gnu" or
  486. * "autoopts". This routine will @strong{not} return.
  487. *
  488. * If "exitCode" is "AO_EXIT_REQ_USAGE" (normally 64), then output will to
  489. * to stdout and the actual exit code will be "EXIT_SUCCESS".
  490. =*/
  491. void
  492. optionUsage(tOptions * opts, int usage_exit_code)
  493. {
  494. int exit_code = (usage_exit_code == AO_EXIT_REQ_USAGE)
  495. ? EXIT_SUCCESS : usage_exit_code;
  496. displayEnum = false;
  497. set_usage_flags(opts, NULL);
  498. /*
  499. * Paged usage will preset option_usage_fp to an output file.
  500. * If it hasn't already been set, then set it to standard output
  501. * on successful exit (help was requested), otherwise error out.
  502. *
  503. * Test the version before obtaining pzFullUsage or pzShortUsage.
  504. * These fields do not exist before revision 30.
  505. */
  506. {
  507. char const * pz;
  508. if (exit_code == EXIT_SUCCESS) {
  509. pz = (opts->structVersion >= 30 * 4096)
  510. ? opts->pzFullUsage : NULL;
  511. if (option_usage_fp == NULL)
  512. option_usage_fp = print_exit ? stderr : stdout;
  513. } else {
  514. pz = (opts->structVersion >= 30 * 4096)
  515. ? opts->pzShortUsage : NULL;
  516. if (option_usage_fp == NULL)
  517. option_usage_fp = stderr;
  518. }
  519. if (((opts->fOptSet & OPTPROC_COMPUTE) == 0) && (pz != NULL)) {
  520. if ((opts->fOptSet & OPTPROC_TRANSLATE) != 0)
  521. optionPrintParagraphs(pz, true, option_usage_fp);
  522. else
  523. fputs(pz, option_usage_fp);
  524. goto flush_and_exit;
  525. }
  526. }
  527. fprintf(option_usage_fp, opts->pzUsageTitle, opts->pzProgName);
  528. if ((exit_code == EXIT_SUCCESS) ||
  529. (! skip_misuse_usage(opts)))
  530. print_usage_details(opts, usage_exit_code);
  531. else
  532. print_offer_usage(opts);
  533. flush_and_exit:
  534. fflush(option_usage_fp);
  535. if (ferror(option_usage_fp) != 0)
  536. fserr_exit(opts->pzProgName, zwriting, (option_usage_fp == stdout)
  537. ? zstdout_name : zstderr_name);
  538. option_exits(exit_code);
  539. }
  540. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  541. * PER OPTION TYPE USAGE INFORMATION
  542. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  543. /**
  544. * print option conflicts.
  545. *
  546. * @param opts the program option descriptor
  547. * @param od the option descriptor
  548. */
  549. static void
  550. prt_conflicts(tOptions * opts, tOptDesc * od)
  551. {
  552. const int * opt_no;
  553. fputs(zTabHyp + tab_skip_ct, option_usage_fp);
  554. /*
  555. * REQUIRED:
  556. */
  557. if (od->pOptMust != NULL) {
  558. opt_no = od->pOptMust;
  559. if (opt_no[1] == NO_EQUIVALENT) {
  560. fprintf(option_usage_fp, zReqOne,
  561. opts->pOptDesc[*opt_no].pz_Name);
  562. } else {
  563. fputs(zReqThese, option_usage_fp);
  564. for (;;) {
  565. fprintf(option_usage_fp, zTabout + tab_skip_ct,
  566. opts->pOptDesc[*opt_no].pz_Name);
  567. if (*++opt_no == NO_EQUIVALENT)
  568. break;
  569. }
  570. }
  571. if (od->pOptCant != NULL)
  572. fputs(zTabHypAnd + tab_skip_ct, option_usage_fp);
  573. }
  574. /*
  575. * CONFLICTS:
  576. */
  577. if (od->pOptCant == NULL)
  578. return;
  579. opt_no = od->pOptCant;
  580. if (opt_no[1] == NO_EQUIVALENT) {
  581. fprintf(option_usage_fp, zProhibOne,
  582. opts->pOptDesc[*opt_no].pz_Name);
  583. return;
  584. }
  585. fputs(zProhib, option_usage_fp);
  586. for (;;) {
  587. fprintf(option_usage_fp, zTabout + tab_skip_ct,
  588. opts->pOptDesc[*opt_no].pz_Name);
  589. if (*++opt_no == NO_EQUIVALENT)
  590. break;
  591. }
  592. }
  593. /**
  594. * Print the usage information for a single vendor option.
  595. *
  596. * @param[in] opts the program option descriptor
  597. * @param[in] od the option descriptor
  598. * @param[in] argtp names of the option argument types
  599. * @param[in] usefmt format for primary usage line
  600. */
  601. static void
  602. prt_one_vendor(tOptions * opts, tOptDesc * od,
  603. arg_types_t * argtp, char const * usefmt)
  604. {
  605. prt_preamble(opts, od, argtp);
  606. {
  607. char z[ 80 ];
  608. char const * pzArgType;
  609. /*
  610. * Determine the argument type string first on its usage, then,
  611. * when the option argument is required, base the type string on the
  612. * argument type.
  613. */
  614. if (od->fOptState & OPTST_ARG_OPTIONAL) {
  615. pzArgType = argtp->pzOpt;
  616. } else switch (OPTST_GET_ARGTYPE(od->fOptState)) {
  617. case OPARG_TYPE_NONE: pzArgType = argtp->pzNo; break;
  618. case OPARG_TYPE_ENUMERATION: pzArgType = argtp->pzKey; break;
  619. case OPARG_TYPE_FILE: pzArgType = argtp->pzFile; break;
  620. case OPARG_TYPE_MEMBERSHIP: pzArgType = argtp->pzKeyL; break;
  621. case OPARG_TYPE_BOOLEAN: pzArgType = argtp->pzBool; break;
  622. case OPARG_TYPE_NUMERIC: pzArgType = argtp->pzNum; break;
  623. case OPARG_TYPE_HIERARCHY: pzArgType = argtp->pzNest; break;
  624. case OPARG_TYPE_STRING: pzArgType = argtp->pzStr; break;
  625. case OPARG_TYPE_TIME: pzArgType = argtp->pzTime; break;
  626. default: goto bogus_desc;
  627. }
  628. pzArgType = SPN_WHITESPACE_CHARS(pzArgType);
  629. if (*pzArgType == NUL)
  630. snprintf(z, sizeof(z), "%s", od->pz_Name);
  631. else
  632. snprintf(z, sizeof(z), "%s=%s", od->pz_Name, pzArgType);
  633. fprintf(option_usage_fp, usefmt, z, od->pzText);
  634. switch (OPTST_GET_ARGTYPE(od->fOptState)) {
  635. case OPARG_TYPE_ENUMERATION:
  636. case OPARG_TYPE_MEMBERSHIP:
  637. displayEnum = (od->pOptProc != NULL) ? true : displayEnum;
  638. }
  639. }
  640. return;
  641. bogus_desc:
  642. fprintf(stderr, zbad_od, opts->pzProgName, od->pz_Name);
  643. ao_bug(zbad_arg_type_msg);
  644. }
  645. /**
  646. * Print the long options processed with "-W". These options will be the
  647. * ones that do *not* have flag characters.
  648. *
  649. * @param opts the program option descriptor
  650. * @param title the title for the options
  651. */
  652. static void
  653. prt_vendor_opts(tOptions * opts, char const * title)
  654. {
  655. static unsigned int const not_vended_mask =
  656. OPTST_NO_USAGE_MASK | OPTST_DOCUMENT;
  657. static char const vfmtfmt[] = "%%-%us %%s\n";
  658. char vfmt[sizeof(vfmtfmt)];
  659. /*
  660. * Only handle client specified options. The "vendor option" follows
  661. * "presetOptCt", so we won't loop/recurse indefinitely.
  662. */
  663. int ct = opts->presetOptCt;
  664. tOptDesc * od = opts->pOptDesc;
  665. fprintf(option_usage_fp, zTabout + tab_skip_ct, zVendOptsAre);
  666. {
  667. size_t nmlen = 0;
  668. do {
  669. size_t l;
  670. if ( ((od->fOptState & not_vended_mask) != 0)
  671. || IS_GRAPHIC_CHAR(od->optValue))
  672. continue;
  673. l = strlen(od->pz_Name);
  674. if (l > nmlen) nmlen = l;
  675. } while (od++, (--ct > 0));
  676. snprintf(vfmt, sizeof(vfmt), vfmtfmt, (unsigned int)nmlen + 4);
  677. }
  678. if (tab_skip_ct > 0)
  679. tab_skip_ct--;
  680. ct = opts->presetOptCt;
  681. od = opts->pOptDesc;
  682. do {
  683. if ( ((od->fOptState & not_vended_mask) != 0)
  684. || IS_GRAPHIC_CHAR(od->optValue))
  685. continue;
  686. prt_one_vendor(opts, od, &argTypes, vfmt);
  687. prt_extd_usage(opts, od, title);
  688. } while (od++, (--ct > 0));
  689. /* no need to restore "tab_skip_ct" - options are done now */
  690. }
  691. /**
  692. * Print extended usage. Usage/help was requested.
  693. *
  694. * @param opts the program option descriptor
  695. * @param od the option descriptor
  696. * @param title the title for the options
  697. */
  698. static void
  699. prt_extd_usage(tOptions * opts, tOptDesc * od, char const * title)
  700. {
  701. if ( ((opts->fOptSet & OPTPROC_VENDOR_OPT) != 0)
  702. && (od->optActualValue == VENDOR_OPTION_VALUE)) {
  703. prt_vendor_opts(opts, title);
  704. return;
  705. }
  706. /*
  707. * IF there are option conflicts or dependencies,
  708. * THEN print them here.
  709. */
  710. if ((od->pOptMust != NULL) || (od->pOptCant != NULL))
  711. prt_conflicts(opts, od);
  712. /*
  713. * IF there is a disablement string
  714. * THEN print the disablement info
  715. */
  716. if (od->pz_DisableName != NULL )
  717. fprintf(option_usage_fp, zDis + tab_skip_ct, od->pz_DisableName);
  718. /*
  719. * Check for argument types that have callbacks with magical properties
  720. */
  721. switch (OPTST_GET_ARGTYPE(od->fOptState)) {
  722. case OPARG_TYPE_NUMERIC:
  723. /*
  724. * IF the numeric option has a special callback,
  725. * THEN call it, requesting the range or other special info
  726. */
  727. if ( (od->pOptProc != NULL)
  728. && (od->pOptProc != optionNumericVal) ) {
  729. (*(od->pOptProc))(OPTPROC_EMIT_USAGE, od);
  730. }
  731. break;
  732. case OPARG_TYPE_FILE:
  733. (*(od->pOptProc))(OPTPROC_EMIT_USAGE, od);
  734. break;
  735. }
  736. /*
  737. * IF the option defaults to being enabled,
  738. * THEN print that out
  739. */
  740. if (od->fOptState & OPTST_INITENABLED)
  741. fputs(zEnab + tab_skip_ct, option_usage_fp);
  742. /*
  743. * IF the option is in an equivalence class
  744. * AND not the designated lead
  745. * THEN print equivalence and leave it at that.
  746. */
  747. if ( (od->optEquivIndex != NO_EQUIVALENT)
  748. && (od->optEquivIndex != od->optActualIndex ) ) {
  749. fprintf(option_usage_fp, zalt_opt + tab_skip_ct,
  750. opts->pOptDesc[ od->optEquivIndex ].pz_Name);
  751. return;
  752. }
  753. /*
  754. * IF this particular option can NOT be preset
  755. * AND some form of presetting IS allowed,
  756. * AND it is not an auto-managed option (e.g. --help, et al.)
  757. * THEN advise that this option may not be preset.
  758. */
  759. if ( ((od->fOptState & OPTST_NO_INIT) != 0)
  760. && ( (opts->papzHomeList != NULL)
  761. || (opts->pzPROGNAME != NULL)
  762. )
  763. && (od->optIndex < opts->presetOptCt)
  764. )
  765. fputs(zNoPreset + tab_skip_ct, option_usage_fp);
  766. /*
  767. * Print the appearance requirements.
  768. */
  769. if (OPTST_GET_ARGTYPE(od->fOptState) == OPARG_TYPE_MEMBERSHIP)
  770. fputs(zMembers + tab_skip_ct, option_usage_fp);
  771. else switch (od->optMinCt) {
  772. case 1:
  773. case 0:
  774. switch (od->optMaxCt) {
  775. case 0: fputs(zPreset + tab_skip_ct, option_usage_fp); break;
  776. case NOLIMIT: fputs(zNoLim + tab_skip_ct, option_usage_fp); break;
  777. case 1: break;
  778. /*
  779. * IF the max is more than one but limited, print "UP TO" message
  780. */
  781. default:
  782. fprintf(option_usage_fp, zUpTo + tab_skip_ct, od->optMaxCt); break;
  783. }
  784. break;
  785. default:
  786. /*
  787. * More than one is required. Print the range.
  788. */
  789. fprintf(option_usage_fp, zMust + tab_skip_ct,
  790. od->optMinCt, od->optMaxCt);
  791. }
  792. if ( NAMED_OPTS(opts)
  793. && (opts->specOptIdx.default_opt == od->optIndex))
  794. fputs(zDefaultOpt + tab_skip_ct, option_usage_fp);
  795. }
  796. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  797. /**
  798. * Figure out where all the initialization files might live. This requires
  799. * translating some environment variables and testing to see if a name is a
  800. * directory or a file. It's squishy, but important to tell users how to
  801. * find these files.
  802. *
  803. * @param[in] papz search path
  804. * @param[out] ini_file an output buffer of AG_PATH_MAX+1 bytes
  805. * @param[in] path_nm the name of the file we're hunting for
  806. */
  807. static void
  808. prt_ini_list(char const * const * papz, char const * ini_file,
  809. char const * path_nm)
  810. {
  811. char pth_buf[AG_PATH_MAX+1];
  812. fputs(zPresetIntro, option_usage_fp);
  813. for (;;) {
  814. char const * path = *(papz++);
  815. char const * nm_buf = pth_buf;
  816. if (path == NULL)
  817. break;
  818. /*
  819. * Ignore any invalid paths
  820. */
  821. if (! optionMakePath(pth_buf, (int)sizeof(pth_buf), path, path_nm))
  822. nm_buf = path;
  823. /*
  824. * Expand paths that are relative to the executable or installation
  825. * directories. Leave alone paths that use environment variables.
  826. */
  827. else if ((*path == '$')
  828. && ((path[1] == '$') || (path[1] == '@')))
  829. path = nm_buf;
  830. /*
  831. * Print the name of the "homerc" file. If the "rcfile" name is
  832. * not empty, we may or may not print that, too...
  833. */
  834. fprintf(option_usage_fp, zPathFmt, path);
  835. if (*ini_file != NUL) {
  836. struct stat sb;
  837. /*
  838. * IF the "homerc" file is a directory,
  839. * then append the "rcfile" name.
  840. */
  841. if ((stat(nm_buf, &sb) == 0) && S_ISDIR(sb.st_mode)) {
  842. fputc(DIRCH, option_usage_fp);
  843. fputs(ini_file, option_usage_fp);
  844. }
  845. }
  846. fputc(NL, option_usage_fp);
  847. }
  848. }
  849. /**
  850. * Print the usage line preamble text
  851. *
  852. * @param opts the program option descriptor
  853. * @param od the option descriptor
  854. * @param at names of the option argument types
  855. */
  856. static void
  857. prt_preamble(tOptions * opts, tOptDesc * od, arg_types_t * at)
  858. {
  859. /*
  860. * Flag prefix: IF no flags at all, then omit it. If not printable
  861. * (not allowed for this option), then blank, else print it.
  862. * Follow it with a comma if we are doing GNU usage and long
  863. * opts are to be printed too.
  864. */
  865. if ((opts->fOptSet & OPTPROC_SHORTOPT) == 0)
  866. fputs(at->pzSpc, option_usage_fp);
  867. else if (! IS_GRAPHIC_CHAR(od->optValue)) {
  868. if ( (opts->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
  869. == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
  870. fputc(' ', option_usage_fp);
  871. fputs(at->pzNoF, option_usage_fp);
  872. } else {
  873. fprintf(option_usage_fp, " -%c", od->optValue);
  874. if ( (opts->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
  875. == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
  876. fputs(", ", option_usage_fp);
  877. }
  878. }
  879. /**
  880. * Print the usage information for a single option.
  881. *
  882. * @param opts the program option descriptor
  883. * @param od the option descriptor
  884. * @param at names of the option argument types
  885. */
  886. static void
  887. prt_one_usage(tOptions * opts, tOptDesc * od, arg_types_t * at)
  888. {
  889. prt_preamble(opts, od, at);
  890. {
  891. char z[80];
  892. char const * atyp;
  893. /*
  894. * Determine the argument type string first on its usage, then,
  895. * when the option argument is required, base the type string on the
  896. * argument type.
  897. */
  898. if (od->fOptState & OPTST_ARG_OPTIONAL) {
  899. atyp = at->pzOpt;
  900. } else switch (OPTST_GET_ARGTYPE(od->fOptState)) {
  901. case OPARG_TYPE_NONE: atyp = at->pzNo; break;
  902. case OPARG_TYPE_ENUMERATION: atyp = at->pzKey; break;
  903. case OPARG_TYPE_FILE: atyp = at->pzFile; break;
  904. case OPARG_TYPE_MEMBERSHIP: atyp = at->pzKeyL; break;
  905. case OPARG_TYPE_BOOLEAN: atyp = at->pzBool; break;
  906. case OPARG_TYPE_NUMERIC: atyp = at->pzNum; break;
  907. case OPARG_TYPE_HIERARCHY: atyp = at->pzNest; break;
  908. case OPARG_TYPE_STRING: atyp = at->pzStr; break;
  909. case OPARG_TYPE_TIME: atyp = at->pzTime; break;
  910. default: goto bogus_desc;
  911. }
  912. #ifdef _WIN32
  913. if (at->pzOptFmt == zGnuOptFmt)
  914. snprintf(z, sizeof(z), "--%s%s", od->pz_Name, atyp);
  915. else if (at->pzOptFmt == zGnuOptFmt + 2)
  916. snprintf(z, sizeof(z), "%s%s", od->pz_Name, atyp);
  917. else
  918. #endif
  919. snprintf(z, sizeof(z), at->pzOptFmt, atyp, od->pz_Name,
  920. (od->optMinCt != 0) ? at->pzReq : at->pzOpt);
  921. fprintf(option_usage_fp, line_fmt_buf, z, od->pzText);
  922. switch (OPTST_GET_ARGTYPE(od->fOptState)) {
  923. case OPARG_TYPE_ENUMERATION:
  924. case OPARG_TYPE_MEMBERSHIP:
  925. displayEnum = (od->pOptProc != NULL) ? true : displayEnum;
  926. }
  927. }
  928. return;
  929. bogus_desc:
  930. fprintf(stderr, zbad_od, opts->pzProgName, od->pz_Name);
  931. option_exits(EX_SOFTWARE);
  932. }
  933. /**
  934. * Print out the usage information for just the options.
  935. */
  936. static void
  937. prt_opt_usage(tOptions * opts, int ex_code, char const * title)
  938. {
  939. int ct = opts->optCt;
  940. int optNo = 0;
  941. tOptDesc * od = opts->pOptDesc;
  942. int docCt = 0;
  943. do {
  944. /*
  945. * no usage --> disallowed on command line (OPTST_NO_COMMAND), or
  946. * deprecated -- strongly discouraged (OPTST_DEPRECATED), or
  947. * compiled out of current object code (OPTST_OMITTED)
  948. */
  949. if ((od->fOptState & OPTST_NO_USAGE_MASK) != 0) {
  950. /*
  951. * IF this is a compiled-out option
  952. * *AND* usage was requested with "omitted-usage"
  953. * *AND* this is NOT abbreviated usage
  954. * THEN display this option.
  955. */
  956. if ( (od->fOptState == (OPTST_OMITTED | OPTST_NO_INIT))
  957. && (od->pz_Name != NULL)
  958. && (ex_code == EXIT_SUCCESS)) {
  959. char const * why_pz =
  960. (od->pzText == NULL) ? zDisabledWhy : od->pzText;
  961. prt_preamble(opts, od, &argTypes);
  962. fprintf(option_usage_fp, zDisabledOpt, od->pz_Name, why_pz);
  963. }
  964. continue;
  965. }
  966. if ((od->fOptState & OPTST_DOCUMENT) != 0) {
  967. if (ex_code == EXIT_SUCCESS) {
  968. fprintf(option_usage_fp, argTypes.pzBrk, od->pzText,
  969. title);
  970. docCt++;
  971. }
  972. continue;
  973. }
  974. /* Skip name only options when we have a vendor option */
  975. if ( ((opts->fOptSet & OPTPROC_VENDOR_OPT) != 0)
  976. && (! IS_GRAPHIC_CHAR(od->optValue)))
  977. continue;
  978. /*
  979. * IF this is the first auto-opt maintained option
  980. * *AND* we are doing a full help
  981. * *AND* there are documentation options
  982. * *AND* the last one was not a doc option,
  983. * THEN document that the remaining options are not user opts
  984. */
  985. if ((docCt > 0) && (ex_code == EXIT_SUCCESS)) {
  986. if (opts->presetOptCt == optNo) {
  987. if ((od[-1].fOptState & OPTST_DOCUMENT) == 0)
  988. fprintf(option_usage_fp, argTypes.pzBrk, zAuto, title);
  989. } else if ((ct == 1) &&
  990. (opts->fOptSet & OPTPROC_VENDOR_OPT))
  991. fprintf(option_usage_fp, argTypes.pzBrk, zVendIntro, title);
  992. }
  993. prt_one_usage(opts, od, &argTypes);
  994. /*
  995. * IF we were invoked because of the --help option,
  996. * THEN print all the extra info
  997. */
  998. if (ex_code == EXIT_SUCCESS)
  999. prt_extd_usage(opts, od, title);
  1000. } while (od++, optNo++, (--ct > 0));
  1001. fputc(NL, option_usage_fp);
  1002. }
  1003. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  1004. /**
  1005. * Print program details.
  1006. * @param[in] opts the program option descriptor
  1007. */
  1008. static void
  1009. prt_prog_detail(tOptions * opts)
  1010. {
  1011. bool need_intro = (opts->papzHomeList == NULL);
  1012. /*
  1013. * Display all the places we look for config files, if we have
  1014. * a list of directories to search.
  1015. */
  1016. if (! need_intro)
  1017. prt_ini_list(opts->papzHomeList, opts->pzRcName, opts->pzProgPath);
  1018. /*
  1019. * Let the user know about environment variable settings
  1020. */
  1021. if ((opts->fOptSet & OPTPROC_ENVIRON) != 0) {
  1022. if (need_intro)
  1023. fputs(zPresetIntro, option_usage_fp);
  1024. fprintf(option_usage_fp, zExamineFmt, opts->pzPROGNAME);
  1025. }
  1026. /*
  1027. * IF we found an enumeration,
  1028. * THEN hunt for it again. Call the handler proc with a NULL
  1029. * option struct pointer. That tells it to display the keywords.
  1030. */
  1031. if (displayEnum) {
  1032. int ct = opts->optCt;
  1033. int optNo = 0;
  1034. tOptDesc * od = opts->pOptDesc;
  1035. fputc(NL, option_usage_fp);
  1036. fflush(option_usage_fp);
  1037. do {
  1038. switch (OPTST_GET_ARGTYPE(od->fOptState)) {
  1039. case OPARG_TYPE_ENUMERATION:
  1040. case OPARG_TYPE_MEMBERSHIP:
  1041. (*(od->pOptProc))(OPTPROC_EMIT_USAGE, od);
  1042. }
  1043. } while (od++, optNo++, (--ct > 0));
  1044. }
  1045. /*
  1046. * If there is a detail string, now is the time for that.
  1047. */
  1048. if (opts->pzDetail != NULL)
  1049. fputs(opts->pzDetail, option_usage_fp);
  1050. }
  1051. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1052. *
  1053. * OPTION LINE FORMATTING SETUP
  1054. *
  1055. * The "OptFmt" formats receive three arguments:
  1056. * 1. the type of the option's argument
  1057. * 2. the long name of the option
  1058. * 3. "YES" or "no ", depending on whether or not the option must appear
  1059. * on the command line.
  1060. * These formats are used immediately after the option flag (if used) has
  1061. * been printed.
  1062. *
  1063. * Set up the formatting for GNU-style output
  1064. */
  1065. static int
  1066. setGnuOptFmts(tOptions * opts, char const ** ptxt)
  1067. {
  1068. static char const zOneSpace[] = " ";
  1069. int flen = 22;
  1070. *ptxt = zNoRq_ShrtTtl;
  1071. argTypes.pzStr = zGnuStrArg;
  1072. argTypes.pzReq = zOneSpace;
  1073. argTypes.pzNum = zGnuNumArg;
  1074. argTypes.pzKey = zGnuKeyArg;
  1075. argTypes.pzKeyL = zGnuKeyLArg;
  1076. argTypes.pzTime = zGnuTimeArg;
  1077. argTypes.pzFile = zGnuFileArg;
  1078. argTypes.pzBool = zGnuBoolArg;
  1079. argTypes.pzNest = zGnuNestArg;
  1080. argTypes.pzOpt = zGnuOptArg;
  1081. argTypes.pzNo = zOneSpace;
  1082. argTypes.pzBrk = zGnuBreak;
  1083. argTypes.pzNoF = zSixSpaces;
  1084. argTypes.pzSpc = zThreeSpaces;
  1085. switch (opts->fOptSet & OPTPROC_L_N_S) {
  1086. case OPTPROC_L_N_S: argTypes.pzOptFmt = zGnuOptFmt; break;
  1087. case OPTPROC_LONGOPT: argTypes.pzOptFmt = zGnuOptFmt; break;
  1088. case 0: argTypes.pzOptFmt = zGnuOptFmt + 2; break;
  1089. case OPTPROC_SHORTOPT:
  1090. argTypes.pzOptFmt = zShrtGnuOptFmt;
  1091. zGnuStrArg[0] = zGnuNumArg[0] = zGnuKeyArg[0] = zGnuBoolArg[0] = ' ';
  1092. argTypes.pzOpt = " [arg]";
  1093. flen = 8;
  1094. break;
  1095. }
  1096. return flen;
  1097. }
  1098. /*
  1099. * Standard (AutoOpts normal) option line formatting
  1100. */
  1101. static int
  1102. setStdOptFmts(tOptions * opts, char const ** ptxt)
  1103. {
  1104. int flen = 0;
  1105. argTypes.pzStr = zStdStrArg;
  1106. argTypes.pzReq = zStdReqArg;
  1107. argTypes.pzNum = zStdNumArg;
  1108. argTypes.pzKey = zStdKeyArg;
  1109. argTypes.pzKeyL = zStdKeyLArg;
  1110. argTypes.pzTime = zStdTimeArg;
  1111. argTypes.pzFile = zStdFileArg;
  1112. argTypes.pzBool = zStdBoolArg;
  1113. argTypes.pzNest = zStdNestArg;
  1114. argTypes.pzOpt = zStdOptArg;
  1115. argTypes.pzNo = zStdNoArg;
  1116. argTypes.pzBrk = zStdBreak;
  1117. argTypes.pzNoF = zFiveSpaces;
  1118. argTypes.pzSpc = zTwoSpaces;
  1119. switch (opts->fOptSet & (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT)) {
  1120. case (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT):
  1121. *ptxt = zNoRq_ShrtTtl;
  1122. argTypes.pzOptFmt = zNrmOptFmt;
  1123. flen = 19;
  1124. break;
  1125. case OPTPROC_NO_REQ_OPT:
  1126. *ptxt = zNoRq_NoShrtTtl;
  1127. argTypes.pzOptFmt = zNrmOptFmt;
  1128. flen = 19;
  1129. break;
  1130. case OPTPROC_SHORTOPT:
  1131. *ptxt = zReq_ShrtTtl;
  1132. argTypes.pzOptFmt = zReqOptFmt;
  1133. flen = 24;
  1134. break;
  1135. case 0:
  1136. *ptxt = zReq_NoShrtTtl;
  1137. argTypes.pzOptFmt = zReqOptFmt;
  1138. flen = 24;
  1139. }
  1140. return flen;
  1141. }
  1142. /** @}
  1143. *
  1144. * Local Variables:
  1145. * mode: C
  1146. * c-file-style: "stroustrup"
  1147. * indent-tabs-mode: nil
  1148. * End:
  1149. * end of autoopts/usage.c */