xref: /freebsd/contrib/ntp/sntp/libopts/putshell.c (revision a466cc55373fc3cf86837f09da729535b57e69a1)
1ea906c41SOllivier Robert 
22b15cb3dSCy Schubert /**
32b15cb3dSCy Schubert  * \file putshell.c
4ea906c41SOllivier Robert  *
5ea906c41SOllivier Robert  *  This module will interpret the options set in the tOptions
6ea906c41SOllivier Robert  *  structure and print them to standard out in a fashion that
7ea906c41SOllivier Robert  *  will allow them to be interpreted by the Bourne or Korn shells.
82b15cb3dSCy Schubert  *
92b15cb3dSCy Schubert  * @addtogroup autoopts
102b15cb3dSCy Schubert  * @{
11ea906c41SOllivier Robert  */
12ea906c41SOllivier Robert /*
132b15cb3dSCy Schubert  *  This file is part of AutoOpts, a companion to AutoGen.
142b15cb3dSCy Schubert  *  AutoOpts is free software.
15*a466cc55SCy Schubert  *  AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved
16ea906c41SOllivier Robert  *
172b15cb3dSCy Schubert  *  AutoOpts is available under any one of two licenses.  The license
182b15cb3dSCy Schubert  *  in use must be one of these two and the choice is under the control
192b15cb3dSCy Schubert  *  of the user of the license.
20ea906c41SOllivier Robert  *
212b15cb3dSCy Schubert  *   The GNU Lesser General Public License, version 3 or later
222b15cb3dSCy Schubert  *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
23ea906c41SOllivier Robert  *
242b15cb3dSCy Schubert  *   The Modified Berkeley Software Distribution License
252b15cb3dSCy Schubert  *      See the file "COPYING.mbsd"
26ea906c41SOllivier Robert  *
272b15cb3dSCy Schubert  *  These files have the following sha256 sums:
28ea906c41SOllivier Robert  *
292b15cb3dSCy Schubert  *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
302b15cb3dSCy Schubert  *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
312b15cb3dSCy Schubert  *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
32ea906c41SOllivier Robert  */
33ea906c41SOllivier Robert 
342b15cb3dSCy Schubert /**
352b15cb3dSCy Schubert  * Count the number of bytes required to represent a string as a
362b15cb3dSCy Schubert  * compilable string.
372b15cb3dSCy Schubert  *
382b15cb3dSCy Schubert  * @param[in] scan    the text to be rewritten as a C program text string.
392b15cb3dSCy Schubert  * @param[in] nl_len  the number of bytes used for each embedded newline.
402b15cb3dSCy Schubert  *
412b15cb3dSCy Schubert  * @returns the count, including the terminating NUL byte.
422b15cb3dSCy Schubert  */
432b15cb3dSCy Schubert static size_t
string_size(char const * scan,size_t nl_len)442b15cb3dSCy Schubert string_size(char const * scan, size_t nl_len)
452b15cb3dSCy Schubert {
46ea906c41SOllivier Robert     /*
472b15cb3dSCy Schubert      *  Start by counting the start and end quotes, plus the NUL.
482b15cb3dSCy Schubert      */
492b15cb3dSCy Schubert     size_t res_ln = 3;
502b15cb3dSCy Schubert 
512b15cb3dSCy Schubert     for (;;) {
522b15cb3dSCy Schubert         char ch = *(scan++);
532b15cb3dSCy Schubert         if ((ch >= ' ') && (ch <= '~')) {
542b15cb3dSCy Schubert 
552b15cb3dSCy Schubert             /*
562b15cb3dSCy Schubert              * a backslash allowance for double quotes and baskslashes
572b15cb3dSCy Schubert              */
582b15cb3dSCy Schubert             res_ln += ((ch == '"') || (ch == '\\')) ? 2 : 1;
592b15cb3dSCy Schubert         }
602b15cb3dSCy Schubert 
612b15cb3dSCy Schubert         /*
622b15cb3dSCy Schubert          *  When not a normal character, then count the characters
632b15cb3dSCy Schubert          *  required to represent whatever it is.
642b15cb3dSCy Schubert          */
652b15cb3dSCy Schubert         else switch (ch) {
662b15cb3dSCy Schubert         case NUL:
672b15cb3dSCy Schubert             return res_ln;
682b15cb3dSCy Schubert 
692b15cb3dSCy Schubert         case NL:
702b15cb3dSCy Schubert             res_ln += nl_len;
712b15cb3dSCy Schubert             break;
722b15cb3dSCy Schubert 
732b15cb3dSCy Schubert         case HT:
742b15cb3dSCy Schubert         case BEL:
752b15cb3dSCy Schubert         case BS:
762b15cb3dSCy Schubert         case FF:
772b15cb3dSCy Schubert         case CR:
782b15cb3dSCy Schubert         case VT:
792b15cb3dSCy Schubert             res_ln += 2;
802b15cb3dSCy Schubert             break;
812b15cb3dSCy Schubert 
822b15cb3dSCy Schubert         default:
832b15cb3dSCy Schubert             res_ln += 4; /* text len for \xNN */
842b15cb3dSCy Schubert         }
852b15cb3dSCy Schubert     }
862b15cb3dSCy Schubert }
872b15cb3dSCy Schubert 
882b15cb3dSCy Schubert /*=export_func  optionQuoteString
892b15cb3dSCy Schubert  * private:
902b15cb3dSCy Schubert  *
912b15cb3dSCy Schubert  * what:  Print a string as quoted text suitable for a C compiler.
922b15cb3dSCy Schubert  * arg:   + char const * + text  + a block of text to quote +
932b15cb3dSCy Schubert  * arg:   + char const * + nl    + line splice text         +
942b15cb3dSCy Schubert  *
952b15cb3dSCy Schubert  * ret_type:  char const *
962b15cb3dSCy Schubert  * ret_desc:  the allocated input string as a quoted string
972b15cb3dSCy Schubert  *
982b15cb3dSCy Schubert  * doc:
992b15cb3dSCy Schubert  *  This is for internal use by autogen and autoopts.
1002b15cb3dSCy Schubert  *  It takes an input string and produces text the C compiler can process
1012b15cb3dSCy Schubert  *  to produce an exact copy of the original string.
1022b15cb3dSCy Schubert  *  The caller must deallocate the result.  Standard C strings and
1032b15cb3dSCy Schubert  *  K&R strings are distinguished by the "nl" string.
1042b15cb3dSCy Schubert =*/
1052b15cb3dSCy Schubert char const *
optionQuoteString(char const * text,char const * nl)1062b15cb3dSCy Schubert optionQuoteString(char const * text, char const * nl)
1072b15cb3dSCy Schubert {
1082b15cb3dSCy Schubert     size_t   nl_len = strlen(nl);
109*a466cc55SCy Schubert     size_t   out_sz = string_size(text, nl_len);
1102b15cb3dSCy Schubert     char *   out;
111*a466cc55SCy Schubert     char *   res    = out = AGALOC(out_sz, "quot str");
112*a466cc55SCy Schubert 
1132b15cb3dSCy Schubert     *(out++) = '"';
1142b15cb3dSCy Schubert 
1152b15cb3dSCy Schubert     for (;;) {
1162b15cb3dSCy Schubert         unsigned char ch = (unsigned char)*text;
1172b15cb3dSCy Schubert         if ((ch >= ' ') && (ch <= '~')) {
1182b15cb3dSCy Schubert             if ((ch == '"') || (ch == '\\'))
1192b15cb3dSCy Schubert                 /*
1202b15cb3dSCy Schubert                  *  We must escape these characters in the output string
1212b15cb3dSCy Schubert                  */
1222b15cb3dSCy Schubert                 *(out++) = '\\';
1232b15cb3dSCy Schubert             *(out++) = (char)ch;
1242b15cb3dSCy Schubert 
1252b15cb3dSCy Schubert         } else switch (ch) {
1262b15cb3dSCy Schubert #       define   add_esc_ch(_ch)  { *(out++) = '\\'; *(out++) = (_ch); }
1272b15cb3dSCy Schubert         case BEL: add_esc_ch('a'); break;
1282b15cb3dSCy Schubert         case BS:  add_esc_ch('b'); break;
1292b15cb3dSCy Schubert         case HT:  add_esc_ch('t'); break;
1302b15cb3dSCy Schubert         case VT:  add_esc_ch('v'); break;
1312b15cb3dSCy Schubert         case FF:  add_esc_ch('f'); break;
1322b15cb3dSCy Schubert         case CR:  add_esc_ch('r'); break;
1332b15cb3dSCy Schubert 
1342b15cb3dSCy Schubert         case LF:
1352b15cb3dSCy Schubert             /*
1362b15cb3dSCy Schubert              *  Place contiguous new-lines on a single line.
1372b15cb3dSCy Schubert              *  The current character is a NL, check the next one.
1382b15cb3dSCy Schubert              */
1392b15cb3dSCy Schubert             while (*++text == NL)
1402b15cb3dSCy Schubert                 add_esc_ch('n');
1412b15cb3dSCy Schubert 
1422b15cb3dSCy Schubert             /*
1432b15cb3dSCy Schubert              *  Insert a splice before starting next line
1442b15cb3dSCy Schubert              */
1452b15cb3dSCy Schubert             if (*text != NUL) {
1462b15cb3dSCy Schubert                 memcpy(out, nl, nl_len);
1472b15cb3dSCy Schubert                 out += nl_len;
1482b15cb3dSCy Schubert 
1492b15cb3dSCy Schubert                 continue; /* text is already at the next character */
1502b15cb3dSCy Schubert             }
1512b15cb3dSCy Schubert 
1522b15cb3dSCy Schubert             add_esc_ch('n');
1532b15cb3dSCy Schubert             /* FALLTHROUGH */
1542b15cb3dSCy Schubert 
1552b15cb3dSCy Schubert         case NUL:
1562b15cb3dSCy Schubert             /*
1572b15cb3dSCy Schubert              *  End of string.  Terminate the quoted output.  If necessary,
1582b15cb3dSCy Schubert              *  deallocate the text string.  Return the scan resumption point.
1592b15cb3dSCy Schubert              */
1602b15cb3dSCy Schubert             *(out++) = '"';
161*a466cc55SCy Schubert             *(out++) = NUL;
162*a466cc55SCy Schubert #ifndef NDEBUG
163*a466cc55SCy Schubert             if ((size_t)(out - res) > out_sz) {
164*a466cc55SCy Schubert                 fputs(misguess_len, stderr);
165*a466cc55SCy Schubert                 option_exits(EXIT_FAILURE);
166*a466cc55SCy Schubert             }
167*a466cc55SCy Schubert #endif
1682b15cb3dSCy Schubert             return res;
1692b15cb3dSCy Schubert 
1702b15cb3dSCy Schubert         default:
1712b15cb3dSCy Schubert             /*
1722b15cb3dSCy Schubert              *  sprintf is safe here, because we already computed
173*a466cc55SCy Schubert              *  the amount of space we will be using.  Assertion is above.
1742b15cb3dSCy Schubert              */
175*a466cc55SCy Schubert             out += sprintf(out, MK_STR_OCT_FMT, ch);
1762b15cb3dSCy Schubert         }
1772b15cb3dSCy Schubert 
1782b15cb3dSCy Schubert         text++;
1792b15cb3dSCy Schubert #       undef add_esc_ch
1802b15cb3dSCy Schubert     }
1812b15cb3dSCy Schubert }
1822b15cb3dSCy Schubert 
1832b15cb3dSCy Schubert /**
1842b15cb3dSCy Schubert  *  Print out escaped apostorophes.
1852b15cb3dSCy Schubert  *
1862b15cb3dSCy Schubert  *  @param[in] str  the apostrophies to print
1872b15cb3dSCy Schubert  */
1882b15cb3dSCy Schubert static char const *
print_quoted_apostrophes(char const * str)1892b15cb3dSCy Schubert print_quoted_apostrophes(char const * str)
1902b15cb3dSCy Schubert {
1912b15cb3dSCy Schubert     while (*str == APOSTROPHE) {
1922b15cb3dSCy Schubert         fputs(QUOT_APOS, stdout);
1932b15cb3dSCy Schubert         str++;
1942b15cb3dSCy Schubert     }
1952b15cb3dSCy Schubert     return str;
1962b15cb3dSCy Schubert }
1972b15cb3dSCy Schubert 
1982b15cb3dSCy Schubert /**
1992b15cb3dSCy Schubert  *  Print a single quote (apostrophe quoted) string.
2002b15cb3dSCy Schubert  *  Other than somersaults for apostrophes, nothing else needs quoting.
2012b15cb3dSCy Schubert  *
2022b15cb3dSCy Schubert  *  @param[in] str  the string to print
203ea906c41SOllivier Robert  */
204ea906c41SOllivier Robert static void
print_quot_str(char const * str)2052b15cb3dSCy Schubert print_quot_str(char const * str)
206ea906c41SOllivier Robert {
207ea906c41SOllivier Robert     /*
208ea906c41SOllivier Robert      *  Handle empty strings to make the rest of the logic simpler.
209ea906c41SOllivier Robert      */
2102b15cb3dSCy Schubert     if ((str == NULL) || (*str == NUL)) {
2112b15cb3dSCy Schubert         fputs(EMPTY_ARG, stdout);
212ea906c41SOllivier Robert         return;
213ea906c41SOllivier Robert     }
214ea906c41SOllivier Robert 
215ea906c41SOllivier Robert     /*
216ea906c41SOllivier Robert      *  Emit any single quotes/apostrophes at the start of the string and
217ea906c41SOllivier Robert      *  bail if that is all we need to do.
218ea906c41SOllivier Robert      */
2192b15cb3dSCy Schubert     str = print_quoted_apostrophes(str);
2202b15cb3dSCy Schubert     if (*str == NUL)
221ea906c41SOllivier Robert         return;
222ea906c41SOllivier Robert 
223ea906c41SOllivier Robert     /*
224ea906c41SOllivier Robert      *  Start the single quote string
225ea906c41SOllivier Robert      */
2262b15cb3dSCy Schubert     fputc(APOSTROPHE, stdout);
227ea906c41SOllivier Robert     for (;;) {
2282b15cb3dSCy Schubert         char const * pz = strchr(str, APOSTROPHE);
229ea906c41SOllivier Robert         if (pz == NULL)
230ea906c41SOllivier Robert             break;
231ea906c41SOllivier Robert 
232ea906c41SOllivier Robert         /*
233ea906c41SOllivier Robert          *  Emit the string up to the single quote (apostrophe) we just found.
234ea906c41SOllivier Robert          */
2352b15cb3dSCy Schubert         (void)fwrite(str, (size_t)(pz - str), (size_t)1, stdout);
236ea906c41SOllivier Robert 
237ea906c41SOllivier Robert         /*
2382b15cb3dSCy Schubert          * Close the current string, emit the apostrophes and re-open the
2392b15cb3dSCy Schubert          * string (IFF there is more text to print).
240ea906c41SOllivier Robert          */
2412b15cb3dSCy Schubert         fputc(APOSTROPHE, stdout);
2422b15cb3dSCy Schubert         str = print_quoted_apostrophes(pz);
2432b15cb3dSCy Schubert         if (*str == NUL)
244ea906c41SOllivier Robert             return;
245ea906c41SOllivier Robert 
2462b15cb3dSCy Schubert         fputc(APOSTROPHE, stdout);
247ea906c41SOllivier Robert     }
248ea906c41SOllivier Robert 
249ea906c41SOllivier Robert     /*
250ea906c41SOllivier Robert      *  If we broke out of the loop, we must still emit the remaining text
251ea906c41SOllivier Robert      *  and then close the single quote string.
252ea906c41SOllivier Robert      */
2532b15cb3dSCy Schubert     fputs(str, stdout);
2542b15cb3dSCy Schubert     fputc(APOSTROPHE, stdout);
255ea906c41SOllivier Robert }
256ea906c41SOllivier Robert 
2572b15cb3dSCy Schubert static void
print_enumeration(tOptions * pOpts,tOptDesc * pOD)2582b15cb3dSCy Schubert print_enumeration(tOptions * pOpts, tOptDesc * pOD)
2592b15cb3dSCy Schubert {
2602b15cb3dSCy Schubert     uintptr_t e_val = pOD->optArg.argEnum;
2612b15cb3dSCy Schubert     printf(OPT_VAL_FMT, pOpts->pzPROGNAME, pOD->pz_NAME);
2622b15cb3dSCy Schubert 
2632b15cb3dSCy Schubert     /*
2642b15cb3dSCy Schubert      *  Convert value to string, print that and restore numeric value.
2652b15cb3dSCy Schubert      */
2662b15cb3dSCy Schubert     (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, pOD);
2672b15cb3dSCy Schubert     printf(QUOT_ARG_FMT, pOD->optArg.argString);
2682b15cb3dSCy Schubert     if (pOD->fOptState & OPTST_ALLOC_ARG)
2692b15cb3dSCy Schubert         AGFREE(pOD->optArg.argString);
2702b15cb3dSCy Schubert     pOD->optArg.argEnum = e_val;
2712b15cb3dSCy Schubert 
2722b15cb3dSCy Schubert     printf(OPT_END_FMT, pOpts->pzPROGNAME, pOD->pz_NAME);
2732b15cb3dSCy Schubert }
2742b15cb3dSCy Schubert 
2752b15cb3dSCy Schubert static void
print_membership(tOptions * pOpts,tOptDesc * pOD)2762b15cb3dSCy Schubert print_membership(tOptions * pOpts, tOptDesc * pOD)
2772b15cb3dSCy Schubert {
2782b15cb3dSCy Schubert     char const * svstr = pOD->optArg.argString;
2792b15cb3dSCy Schubert     char const * pz;
2802b15cb3dSCy Schubert     uintptr_t val = 1;
2812b15cb3dSCy Schubert     printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
2822b15cb3dSCy Schubert            (int)(uintptr_t)(pOD->optCookie));
283276da39aSCy Schubert     pOD->optCookie = VOIDP(~0UL);
2842b15cb3dSCy Schubert     (*(pOD->pOptProc))(OPTPROC_RETURN_VALNAME, pOD);
2852b15cb3dSCy Schubert 
2862b15cb3dSCy Schubert     pz = pOD->optArg.argString;
2872b15cb3dSCy Schubert     while (*pz != NUL) {
2882b15cb3dSCy Schubert         printf("readonly %s_", pOD->pz_NAME);
2892b15cb3dSCy Schubert         pz = SPN_PLUS_N_SPACE_CHARS(pz);
2902b15cb3dSCy Schubert 
2912b15cb3dSCy Schubert         for (;;) {
2922b15cb3dSCy Schubert             int ch = *(pz++);
2932b15cb3dSCy Schubert             if (IS_LOWER_CASE_CHAR(ch))   fputc(toupper(ch), stdout);
2942b15cb3dSCy Schubert             else if (IS_UPPER_CASE_CHAR(ch))   fputc(ch, stdout);
2952b15cb3dSCy Schubert             else if (IS_PLUS_N_SPACE_CHAR(ch)) goto name_done;
2962b15cb3dSCy Schubert             else if (ch == NUL)        { pz--; goto name_done; }
2972b15cb3dSCy Schubert             else fputc('_', stdout);
2982b15cb3dSCy Schubert         } name_done:;
2992b15cb3dSCy Schubert         printf(SHOW_VAL_FMT, (unsigned long)val);
3002b15cb3dSCy Schubert         val <<= 1;
3012b15cb3dSCy Schubert     }
3022b15cb3dSCy Schubert 
3032b15cb3dSCy Schubert     AGFREE(pOD->optArg.argString);
3042b15cb3dSCy Schubert     pOD->optArg.argString = svstr;
3052b15cb3dSCy Schubert }
3062b15cb3dSCy Schubert 
3072b15cb3dSCy Schubert static void
print_stacked_arg(tOptions * pOpts,tOptDesc * pOD)3082b15cb3dSCy Schubert print_stacked_arg(tOptions * pOpts, tOptDesc * pOD)
3092b15cb3dSCy Schubert {
3102b15cb3dSCy Schubert     tArgList *      pAL = (tArgList *)pOD->optCookie;
3112b15cb3dSCy Schubert     char const **   ppz = pAL->apzArgs;
3122b15cb3dSCy Schubert     int             ct  = pAL->useCt;
3132b15cb3dSCy Schubert 
3142b15cb3dSCy Schubert     printf(zOptCookieCt, pOpts->pzPROGNAME, pOD->pz_NAME, ct);
3152b15cb3dSCy Schubert 
3162b15cb3dSCy Schubert     while (--ct >= 0) {
3172b15cb3dSCy Schubert         printf(ARG_BY_NUM_FMT, pOpts->pzPROGNAME, pOD->pz_NAME,
3182b15cb3dSCy Schubert                pAL->useCt - ct);
3192b15cb3dSCy Schubert         print_quot_str(*(ppz++));
3202b15cb3dSCy Schubert         printf(EXPORT_ARG_FMT, pOpts->pzPROGNAME, pOD->pz_NAME,
3212b15cb3dSCy Schubert                pAL->useCt - ct);
3222b15cb3dSCy Schubert     }
3232b15cb3dSCy Schubert }
3242b15cb3dSCy Schubert 
3252b15cb3dSCy Schubert /**
3262b15cb3dSCy Schubert  * emit the arguments as readily parsed text.
3272b15cb3dSCy Schubert  * The program options are set by emitting the shell "set" command.
3282b15cb3dSCy Schubert  *
3292b15cb3dSCy Schubert  * @param[in] opts  the program options structure
3302b15cb3dSCy Schubert  */
3312b15cb3dSCy Schubert static void
print_reordering(tOptions * opts)3322b15cb3dSCy Schubert print_reordering(tOptions * opts)
3332b15cb3dSCy Schubert {
3342b15cb3dSCy Schubert     unsigned int ix;
3352b15cb3dSCy Schubert 
3362b15cb3dSCy Schubert     fputs(set_dash, stdout);
3372b15cb3dSCy Schubert 
3382b15cb3dSCy Schubert     for (ix = opts->curOptIdx;
3392b15cb3dSCy Schubert          ix < opts->origArgCt;
3402b15cb3dSCy Schubert          ix++) {
3412b15cb3dSCy Schubert         fputc(' ', stdout);
3422b15cb3dSCy Schubert         print_quot_str(opts->origArgVect[ ix ]);
3432b15cb3dSCy Schubert     }
3442b15cb3dSCy Schubert     fputs(init_optct, stdout);
3452b15cb3dSCy Schubert }
346ea906c41SOllivier Robert 
347ea906c41SOllivier Robert /*=export_func  optionPutShell
348ea906c41SOllivier Robert  * what:  write a portable shell script to parse options
349ea906c41SOllivier Robert  * private:
350ea906c41SOllivier Robert  * arg:   tOptions *, pOpts, the program options descriptor
351ea906c41SOllivier Robert  * doc:   This routine will emit portable shell script text for parsing
352ea906c41SOllivier Robert  *        the options described in the option definitions.
353ea906c41SOllivier Robert =*/
354ea906c41SOllivier Robert void
optionPutShell(tOptions * pOpts)355ea906c41SOllivier Robert optionPutShell(tOptions * pOpts)
356ea906c41SOllivier Robert {
357ea906c41SOllivier Robert     int  optIx = 0;
358ea906c41SOllivier Robert 
359ea906c41SOllivier Robert     printf(zOptCtFmt, pOpts->curOptIdx-1);
360ea906c41SOllivier Robert 
361ea906c41SOllivier Robert     do  {
362ea906c41SOllivier Robert         tOptDesc * pOD = pOpts->pOptDesc + optIx;
363ea906c41SOllivier Robert 
3642b15cb3dSCy Schubert         if ((pOD->fOptState & OPTST_NO_OUTPUT_MASK) != 0)
365ea906c41SOllivier Robert             continue;
366ea906c41SOllivier Robert 
367ea906c41SOllivier Robert         /*
368ea906c41SOllivier Robert          *  Equivalence classes are hard to deal with.  Where the
369ea906c41SOllivier Robert          *  option data wind up kind of squishes around.  For the purposes
370ea906c41SOllivier Robert          *  of emitting shell state, they are not recommended, but we'll
371ea906c41SOllivier Robert          *  do something.  I guess we'll emit the equivalenced-to option
372ea906c41SOllivier Robert          *  at the point in time when the base option is found.
373ea906c41SOllivier Robert          */
374ea906c41SOllivier Robert         if (pOD->optEquivIndex != NO_EQUIVALENT)
375ea906c41SOllivier Robert             continue; /* equivalence to a different option */
376ea906c41SOllivier Robert 
377ea906c41SOllivier Robert         /*
378ea906c41SOllivier Robert          *  Equivalenced to a different option.  Process the current option
379ea906c41SOllivier Robert          *  as the equivalenced-to option.  Keep the persistent state bits,
380ea906c41SOllivier Robert          *  but copy over the set-state bits.
381ea906c41SOllivier Robert          */
382ea906c41SOllivier Robert         if (pOD->optActualIndex != optIx) {
383ea906c41SOllivier Robert             tOptDesc * p  = pOpts->pOptDesc + pOD->optActualIndex;
384ea906c41SOllivier Robert             p->optArg     = pOD->optArg;
385ea906c41SOllivier Robert             p->fOptState &= OPTST_PERSISTENT_MASK;
386ea906c41SOllivier Robert             p->fOptState |= pOD->fOptState & ~OPTST_PERSISTENT_MASK;
387ea906c41SOllivier Robert             printf(zEquivMode, pOpts->pzPROGNAME, pOD->pz_NAME, p->pz_NAME);
388ea906c41SOllivier Robert             pOD = p;
389ea906c41SOllivier Robert         }
390ea906c41SOllivier Robert 
391ea906c41SOllivier Robert         /*
392ea906c41SOllivier Robert          *  If the argument type is a set membership bitmask, then we always
393ea906c41SOllivier Robert          *  emit the thing.  We do this because it will always have some sort
394ea906c41SOllivier Robert          *  of bitmask value and we need to emit the bit values.
395ea906c41SOllivier Robert          */
396ea906c41SOllivier Robert         if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) {
3972b15cb3dSCy Schubert             print_membership(pOpts, pOD);
398ea906c41SOllivier Robert             continue;
399ea906c41SOllivier Robert         }
400ea906c41SOllivier Robert 
401ea906c41SOllivier Robert         /*
402ea906c41SOllivier Robert          *  IF the option was either specified or it wakes up enabled,
403ea906c41SOllivier Robert          *  then we will emit information.  Otherwise, skip it.
404ea906c41SOllivier Robert          *  The idea is that if someone defines an option to initialize
405ea906c41SOllivier Robert          *  enabled, we should tell our shell script that it is enabled.
406ea906c41SOllivier Robert          */
407ea906c41SOllivier Robert         if (UNUSED_OPT(pOD) && DISABLED_OPT(pOD))
408ea906c41SOllivier Robert             continue;
409ea906c41SOllivier Robert 
410ea906c41SOllivier Robert         /*
411ea906c41SOllivier Robert          *  Handle stacked arguments
412ea906c41SOllivier Robert          */
413ea906c41SOllivier Robert         if (  (pOD->fOptState & OPTST_STACKED)
414ea906c41SOllivier Robert            && (pOD->optCookie != NULL) )  {
4152b15cb3dSCy Schubert             print_stacked_arg(pOpts, pOD);
4162b15cb3dSCy Schubert             continue;
417ea906c41SOllivier Robert         }
418ea906c41SOllivier Robert 
419ea906c41SOllivier Robert         /*
420ea906c41SOllivier Robert          *  If the argument has been disabled,
421ea906c41SOllivier Robert          *  Then set its value to the disablement string
422ea906c41SOllivier Robert          */
4232b15cb3dSCy Schubert         if ((pOD->fOptState & OPTST_DISABLED) != 0) {
424ea906c41SOllivier Robert             printf(zOptDisabl, pOpts->pzPROGNAME, pOD->pz_NAME,
425ea906c41SOllivier Robert                    (pOD->pz_DisablePfx != NULL)
426ea906c41SOllivier Robert                    ? pOD->pz_DisablePfx : "false");
4272b15cb3dSCy Schubert             continue;
4282b15cb3dSCy Schubert         }
429ea906c41SOllivier Robert 
430ea906c41SOllivier Robert         /*
431ea906c41SOllivier Robert          *  If the argument type is numeric, the last arg pointer
432ea906c41SOllivier Robert          *  is really the VALUE of the string that was pointed to.
433ea906c41SOllivier Robert          */
4342b15cb3dSCy Schubert         if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC) {
435ea906c41SOllivier Robert             printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
436ea906c41SOllivier Robert                    (int)pOD->optArg.argInt);
4372b15cb3dSCy Schubert             continue;
4382b15cb3dSCy Schubert         }
439ea906c41SOllivier Robert 
440ea906c41SOllivier Robert         /*
441ea906c41SOllivier Robert          *  If the argument type is an enumeration, then it is much
442ea906c41SOllivier Robert          *  like a text value, except we call the callback function
443ea906c41SOllivier Robert          *  to emit the value corresponding to the "optArg" number.
444ea906c41SOllivier Robert          */
4452b15cb3dSCy Schubert         if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_ENUMERATION) {
4462b15cb3dSCy Schubert             print_enumeration(pOpts, pOD);
4472b15cb3dSCy Schubert             continue;
448ea906c41SOllivier Robert         }
449ea906c41SOllivier Robert 
450ea906c41SOllivier Robert         /*
451ea906c41SOllivier Robert          *  If the argument type is numeric, the last arg pointer
452ea906c41SOllivier Robert          *  is really the VALUE of the string that was pointed to.
453ea906c41SOllivier Robert          */
4542b15cb3dSCy Schubert         if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_BOOLEAN) {
455ea906c41SOllivier Robert             printf(zFullOptFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
456ea906c41SOllivier Robert                    (pOD->optArg.argBool == 0) ? "false" : "true");
4572b15cb3dSCy Schubert             continue;
4582b15cb3dSCy Schubert         }
459ea906c41SOllivier Robert 
460ea906c41SOllivier Robert         /*
461ea906c41SOllivier Robert          *  IF the option has an empty value,
462ea906c41SOllivier Robert          *  THEN we set the argument to the occurrence count.
463ea906c41SOllivier Robert          */
4642b15cb3dSCy Schubert         if (  (pOD->optArg.argString == NULL)
4652b15cb3dSCy Schubert            || (pOD->optArg.argString[0] == NUL) ) {
466ea906c41SOllivier Robert 
467ea906c41SOllivier Robert             printf(zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
468ea906c41SOllivier Robert                    pOD->optOccCt);
4692b15cb3dSCy Schubert             continue;
4702b15cb3dSCy Schubert         }
471ea906c41SOllivier Robert 
472ea906c41SOllivier Robert         /*
473ea906c41SOllivier Robert          *  This option has a text value
474ea906c41SOllivier Robert          */
4752b15cb3dSCy Schubert         printf(OPT_VAL_FMT, pOpts->pzPROGNAME, pOD->pz_NAME);
4762b15cb3dSCy Schubert         print_quot_str(pOD->optArg.argString);
4772b15cb3dSCy Schubert         printf(OPT_END_FMT, pOpts->pzPROGNAME, pOD->pz_NAME);
4782b15cb3dSCy Schubert 
479ea906c41SOllivier Robert     } while (++optIx < pOpts->presetOptCt );
480ea906c41SOllivier Robert 
481ea906c41SOllivier Robert     if (  ((pOpts->fOptSet & OPTPROC_REORDER) != 0)
4822b15cb3dSCy Schubert        && (pOpts->curOptIdx < pOpts->origArgCt))
4832b15cb3dSCy Schubert         print_reordering(pOpts);
4842b15cb3dSCy Schubert 
4852b15cb3dSCy Schubert     fflush(stdout);
486ea906c41SOllivier Robert }
487ea906c41SOllivier Robert 
4882b15cb3dSCy Schubert /** @}
4892b15cb3dSCy Schubert  *
490ea906c41SOllivier Robert  * Local Variables:
491ea906c41SOllivier Robert  * mode: C
492ea906c41SOllivier Robert  * c-file-style: "stroustrup"
493ea906c41SOllivier Robert  * indent-tabs-mode: nil
494ea906c41SOllivier Robert  * End:
495ea906c41SOllivier Robert  * end of autoopts/putshell.c */
496