| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951 | 
							
- /**
 
-  * \file makeshell.c
 
-  *
 
-  *  This module will interpret the options set in the tOptions
 
-  *  structure and create a Bourne shell script capable of parsing them.
 
-  *
 
-  * @addtogroup autoopts
 
-  * @{
 
-  */
 
- /*
 
-  *  This file is part of AutoOpts, a companion to AutoGen.
 
-  *  AutoOpts is free software.
 
-  *  AutoOpts is Copyright (C) 1992-2014 by Bruce Korb - all rights reserved
 
-  *
 
-  *  AutoOpts is available under any one of two licenses.  The license
 
-  *  in use must be one of these two and the choice is under the control
 
-  *  of the user of the license.
 
-  *
 
-  *   The GNU Lesser General Public License, version 3 or later
 
-  *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
 
-  *
 
-  *   The Modified Berkeley Software Distribution License
 
-  *      See the file "COPYING.mbsd"
 
-  *
 
-  *  These files have the following sha256 sums:
 
-  *
 
-  *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
 
-  *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
 
-  *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
 
-  */
 
- /* = = = START-STATIC-FORWARD = = = */
 
- static void
 
- emit_var_text(char const * prog, char const * var, int fdin);
 
- static void
 
- text_to_var(tOptions * opts, teTextTo which, tOptDesc * od);
 
- static void
 
- emit_usage(tOptions * opts);
 
- static void
 
- emit_wrapup(tOptions * opts);
 
- static void
 
- emit_setup(tOptions * opts);
 
- static void
 
- emit_action(tOptions * opts, tOptDesc * od);
 
- static void
 
- emit_inaction(tOptions * opts, tOptDesc * od);
 
- static void
 
- emit_flag(tOptions * opts);
 
- static void
 
- emit_match_expr(char const * name, tOptDesc * cod, tOptions * opts);
 
- static void
 
- emit_long(tOptions * opts);
 
- static char *
 
- load_old_output(char const * fname, char const * pname);
 
- static void
 
- open_out(char const * fname, char const * pname);
 
- /* = = = END-STATIC-FORWARD = = = */
 
- LOCAL noreturn void
 
- option_exits(int exit_code)
 
- {
 
-     if (print_exit)
 
-         printf("\nexit %d\n", exit_code);
 
-     exit(exit_code);
 
- }
 
- LOCAL noreturn void
 
- ao_bug(char const * msg)
 
- {
 
-     fprintf(stderr, zao_bug_msg, msg);
 
-     option_exits(EX_SOFTWARE);
 
- }
 
- LOCAL void
 
- fserr_warn(char const * prog, char const * op, char const * fname)
 
- {
 
-     fprintf(stderr, zfserr_fmt, prog, errno, strerror(errno),
 
-             op, fname);
 
- }
 
- LOCAL noreturn void
 
- fserr_exit(char const * prog, char const * op, char const * fname)
 
- {
 
-     fserr_warn(prog, op, fname);
 
-     option_exits(EXIT_FAILURE);
 
- }
 
- /*=export_func  optionParseShell
 
-  * private:
 
-  *
 
-  * what:  Decipher a boolean value
 
-  * arg:   + tOptions* + pOpts    + program options descriptor +
 
-  *
 
-  * doc:
 
-  *  Emit a shell script that will parse the command line options.
 
- =*/
 
- void
 
- optionParseShell(tOptions * opts)
 
- {
 
-     /*
 
-      *  Check for our SHELL option now.
 
-      *  IF the output file contains the "#!" magic marker,
 
-      *  it will override anything we do here.
 
-      */
 
-     if (HAVE_GENSHELL_OPT(SHELL))
 
-         shell_prog = GENSHELL_OPT_ARG(SHELL);
 
-     else if (! ENABLED_GENSHELL_OPT(SHELL))
 
-         shell_prog = NULL;
 
-     else if ((shell_prog = getenv("SHELL")),
 
-              shell_prog == NULL)
 
-         shell_prog = POSIX_SHELL;
 
-     /*
 
-      *  Check for a specified output file
 
-      */
 
-     if (HAVE_GENSHELL_OPT(SCRIPT))
 
-         open_out(GENSHELL_OPT_ARG(SCRIPT), opts->pzProgName);
 
-     
 
-     emit_usage(opts);
 
-     emit_setup(opts);
 
-     /*
 
-      *  There are four modes of option processing.
 
-      */
 
-     switch (opts->fOptSet & (OPTPROC_LONGOPT|OPTPROC_SHORTOPT)) {
 
-     case OPTPROC_LONGOPT:
 
-         fputs(LOOP_STR,         stdout);
 
-         fputs(LONG_OPT_MARK,    stdout);
 
-         fputs(INIT_LOPT_STR,    stdout);
 
-         emit_long(opts);
 
-         printf(LOPT_ARG_FMT,    opts->pzPROGNAME);
 
-         fputs(END_OPT_SEL_STR,  stdout);
 
-         fputs(NOT_FOUND_STR,    stdout);
 
-         break;
 
-     case 0:
 
-         fputs(ONLY_OPTS_LOOP,   stdout);
 
-         fputs(INIT_LOPT_STR,    stdout);
 
-         emit_long(opts);
 
-         printf(LOPT_ARG_FMT,    opts->pzPROGNAME);
 
-         break;
 
-     case OPTPROC_SHORTOPT:
 
-         fputs(LOOP_STR,         stdout);
 
-         fputs(FLAG_OPT_MARK,    stdout);
 
-         fputs(INIT_OPT_STR,     stdout);
 
-         emit_flag(opts);
 
-         printf(OPT_ARG_FMT,     opts->pzPROGNAME);
 
-         fputs(END_OPT_SEL_STR,  stdout);
 
-         fputs(NOT_FOUND_STR,    stdout);
 
-         break;
 
-     case OPTPROC_LONGOPT|OPTPROC_SHORTOPT:
 
-         fputs(LOOP_STR,         stdout);
 
-         fputs(LONG_OPT_MARK,    stdout);
 
-         fputs(INIT_LOPT_STR,    stdout);
 
-         emit_long(opts);
 
-         printf(LOPT_ARG_FMT,    opts->pzPROGNAME);
 
-         fputs(END_OPT_SEL_STR,  stdout);
 
-         fputs(FLAG_OPT_MARK,    stdout);
 
-         fputs(INIT_OPT_STR,     stdout);
 
-         emit_flag(opts);
 
-         printf(OPT_ARG_FMT,     opts->pzPROGNAME);
 
-         fputs(END_OPT_SEL_STR,  stdout);
 
-         fputs(NOT_FOUND_STR,    stdout);
 
-         break;
 
-     }
 
-     emit_wrapup(opts);
 
-     if ((script_trailer != NULL) && (*script_trailer != NUL))
 
-         fputs(script_trailer, stdout);
 
-     else if (ENABLED_GENSHELL_OPT(SHELL))
 
-         printf(SHOW_PROG_ENV, opts->pzPROGNAME);
 
- #ifdef HAVE_FCHMOD
 
-     fchmod(STDOUT_FILENO, 0755);
 
- #endif
 
-     fclose(stdout);
 
-     if (ferror(stdout))
 
-         fserr_exit(opts->pzProgName, zwriting, zstdout_name);
 
-     AGFREE(script_text);
 
-     script_leader    = NULL;
 
-     script_trailer   = NULL;
 
-     script_text      = NULL;
 
- }
 
- #ifdef HAVE_WORKING_FORK
 
- /**
 
-  * Print the value of "var" to a file descriptor.
 
-  * The "fdin" is the read end of a pipe to a forked process that
 
-  * is writing usage text to it.  We read that text in and re-emit
 
-  * to standard out, formatting it so that it is assigned to a
 
-  * shell variable.
 
-  *
 
-  * @param[in] prog  The capitalized, c-variable-formatted program name
 
-  * @param[in] var   a similarly formatted type name
 
-  *                  (LONGUSAGE, USAGE or VERSION)
 
-  * @param[in] fdin  the input end of a pipe
 
-  */
 
- static void
 
- emit_var_text(char const * prog, char const * var, int fdin)
 
- {
 
-     FILE * fp   = fdopen(fdin, "r" FOPEN_BINARY_FLAG);
 
-     int    nlct = 0; /* defer newlines and skip trailing ones */
 
-     printf(SET_TEXT_FMT, prog, var);
 
-     if (fp == NULL)
 
-         goto skip_text;
 
-     for (;;) {
 
-         int  ch = fgetc(fp);
 
-         switch (ch) {
 
-         case NL:
 
-             nlct++;
 
-             break;
 
-         case '\'':
 
-             while (nlct > 0) {
 
-                 fputc(NL, stdout);
 
-                 nlct--;
 
-             }
 
-             fputs(apostrophe, stdout);
 
-             break;
 
-         case EOF:
 
-             goto done;
 
-         default:
 
-             while (nlct > 0) {
 
-                 fputc(NL, stdout);
 
-                 nlct--;
 
-             }
 
-             fputc(ch, stdout);
 
-             break;
 
-         }
 
-     } done:;
 
-     fclose(fp);
 
-  skip_text:
 
-     fputs(END_SET_TEXT, stdout);
 
- }
 
- #endif
 
- /**
 
-  *  The purpose of this function is to assign "long usage", short usage
 
-  *  and version information to a shell variable.  Rather than wind our
 
-  *  way through all the logic necessary to emit the text directly, we
 
-  *  fork(), have our child process emit the text the normal way and
 
-  *  capture the output in the parent process.
 
-  *
 
-  * @param[in] opts  the program options
 
-  * @param[in] which what to print: long usage, usage or version
 
-  * @param[in] od    for TT_VERSION, it is the version option
 
-  */
 
- static void
 
- text_to_var(tOptions * opts, teTextTo which, tOptDesc * od)
 
- {
 
- #   define _TT_(n) static char const z ## n [] = #n;
 
-     TEXTTO_TABLE
 
- #   undef _TT_
 
- #   define _TT_(n) z ## n ,
 
-       static char const * ttnames[] = { TEXTTO_TABLE };
 
- #   undef _TT_
 
- #if ! defined(HAVE_WORKING_FORK)
 
-     printf(SET_NO_TEXT_FMT, opts->pzPROGNAME, ttnames[which]);
 
- #else
 
-     int  fdpair[2];
 
-     fflush(stdout);
 
-     fflush(stderr);
 
-     if (pipe(fdpair) != 0)
 
-         fserr_exit(opts->pzProgName, "pipe", zinter_proc_pipe);
 
-     switch (fork()) {
 
-     case -1:
 
-         fserr_exit(opts->pzProgName, "fork", opts->pzProgName);
 
-         /* NOTREACHED */
 
-     case 0:
 
-         /*
 
-          * Send both stderr and stdout to the pipe.  No matter which
 
-          * descriptor is used, we capture the output on the read end.
 
-          */
 
-         dup2(fdpair[1], STDERR_FILENO);
 
-         dup2(fdpair[1], STDOUT_FILENO);
 
-         close(fdpair[0]);
 
-         switch (which) {
 
-         case TT_LONGUSAGE:
 
-             (*(opts->pUsageProc))(opts, EXIT_SUCCESS);
 
-             /* NOTREACHED */
 
-         case TT_USAGE:
 
-             (*(opts->pUsageProc))(opts, EXIT_FAILURE);
 
-             /* NOTREACHED */
 
-         case TT_VERSION:
 
-             if (od->fOptState & OPTST_ALLOC_ARG) {
 
-                 AGFREE(od->optArg.argString);
 
-                 od->fOptState &= ~OPTST_ALLOC_ARG;
 
-             }
 
-             od->optArg.argString = "c";
 
-             optionPrintVersion(opts, od);
 
-             /* NOTREACHED */
 
-         default:
 
-             option_exits(EXIT_FAILURE);
 
-             /* NOTREACHED */
 
-         }
 
-         /* NOTREACHED */
 
-     default:
 
-         close(fdpair[1]);
 
-     }
 
-     emit_var_text(opts->pzPROGNAME, ttnames[which], fdpair[0]);
 
- #endif
 
- }
 
- /**
 
-  * capture usage text in shell variables.
 
-  * 
 
-  */
 
- static void
 
- emit_usage(tOptions * opts)
 
- {
 
-     char tm_nm_buf[AO_NAME_SIZE];
 
-     /*
 
-      *  First, switch stdout to the output file name.
 
-      *  Then, change the program name to the one defined
 
-      *  by the definitions (rather than the current
 
-      *  executable name).  Down case the upper cased name.
 
-      */
 
-     if (script_leader != NULL)
 
-         fputs(script_leader, stdout);
 
-     {
 
-         char const * out_nm;
 
-         {
 
-             time_t    c_tim = time(NULL);
 
-             struct tm * ptm = localtime(&c_tim);
 
-             strftime(tm_nm_buf, AO_NAME_SIZE, TIME_FMT, ptm );
 
-         }
 
-         if (HAVE_GENSHELL_OPT(SCRIPT))
 
-              out_nm = GENSHELL_OPT_ARG(SCRIPT);
 
-         else out_nm = STDOUT;
 
-         if ((script_leader == NULL) && (shell_prog != NULL))
 
-             printf(SHELL_MAGIC, shell_prog);
 
-         printf(PREAMBLE_FMT, START_MARK, out_nm, tm_nm_buf);
 
-     }
 
-     printf(END_PRE_FMT, opts->pzPROGNAME);
 
-     /*
 
-      *  Get a copy of the original program name in lower case and
 
-      *  fill in an approximation of the program name from it.
 
-      */
 
-     {
 
-         char *       pzPN = tm_nm_buf;
 
-         char const * pz   = opts->pzPROGNAME;
 
-         char **      pp;
 
-         /* Copy the program name into the time/name buffer */
 
-         for (;;) {
 
-             if ((*pzPN++ = (char)tolower(*pz++)) == NUL)
 
-                 break;
 
-         }
 
-         pp  = (char **)(void *)&(opts->pzProgPath);
 
-         *pp = tm_nm_buf;
 
-         pp  = (char **)(void *)&(opts->pzProgName);
 
-         *pp = tm_nm_buf;
 
-     }
 
-     text_to_var(opts, TT_LONGUSAGE, NULL);
 
-     text_to_var(opts, TT_USAGE,     NULL);
 
-     {
 
-         tOptDesc* pOptDesc = opts->pOptDesc;
 
-         int       optionCt = opts->optCt;
 
-         for (;;) {
 
-             if (pOptDesc->pOptProc == optionPrintVersion) {
 
-                 text_to_var(opts, TT_VERSION, pOptDesc);
 
-                 break;
 
-             }
 
-             if (--optionCt <= 0)
 
-                 break;
 
-             pOptDesc++;
 
-         }
 
-     }
 
- }
 
- static void
 
- emit_wrapup(tOptions * opts)
 
- {
 
-     tOptDesc *   od     = opts->pOptDesc;
 
-     int          opt_ct = opts->presetOptCt;
 
-     char const * fmt;
 
-     printf(FINISH_LOOP, opts->pzPROGNAME);
 
-     for (;opt_ct > 0; od++, --opt_ct) {
 
-         /*
 
-          *  Options that are either usage documentation or are compiled out
 
-          *  are not to be processed.
 
-          */
 
-         if (SKIP_OPT(od) || (od->pz_NAME == NULL))
 
-             continue;
 
-         /*
 
-          *  do not presence check if there is no minimum/must-set
 
-          */
 
-         if ((od->optMinCt == 0) && ((od->fOptState & OPTST_MUST_SET) == 0))
 
-             continue;
 
-         if (od->optMaxCt > 1)
 
-              fmt = CHK_MIN_COUNT;
 
-         else fmt = CHK_ONE_REQUIRED;
 
-         {
 
-             int min = (od->optMinCt == 0) ? 1 : od->optMinCt;
 
-             printf(fmt, opts->pzPROGNAME, od->pz_NAME, min);
 
-         }
 
-     }
 
-     fputs(END_MARK, stdout);
 
- }
 
- static void
 
- emit_setup(tOptions * opts)
 
- {
 
-     tOptDesc *   od     = opts->pOptDesc;
 
-     int          opt_ct = opts->presetOptCt;
 
-     char const * fmt;
 
-     char const * def_val;
 
-     for (;opt_ct > 0; od++, --opt_ct) {
 
-         char int_val_buf[32];
 
-         /*
 
-          *  Options that are either usage documentation or are compiled out
 
-          *  are not to be processed.
 
-          */
 
-         if (SKIP_OPT(od) || (od->pz_NAME == NULL))
 
-             continue;
 
-         if (od->optMaxCt > 1)
 
-              fmt = MULTI_DEF_FMT;
 
-         else fmt = SGL_DEF_FMT;
 
-         /*
 
-          *  IF this is an enumeration/bitmask option, then convert the value
 
-          *  to a string before printing the default value.
 
-          */
 
-         switch (OPTST_GET_ARGTYPE(od->fOptState)) {
 
-         case OPARG_TYPE_ENUMERATION:
 
-             (*(od->pOptProc))(OPTPROC_EMIT_SHELL, od );
 
-             def_val = od->optArg.argString;
 
-             break;
 
-         /*
 
-          *  Numeric and membership bit options are just printed as a number.
 
-          */
 
-         case OPARG_TYPE_NUMERIC:
 
-             snprintf(int_val_buf, sizeof(int_val_buf), "%d",
 
-                      (int)od->optArg.argInt);
 
-             def_val = int_val_buf;
 
-             break;
 
-         case OPARG_TYPE_MEMBERSHIP:
 
-             snprintf(int_val_buf, sizeof(int_val_buf), "%lu",
 
-                      (unsigned long)od->optArg.argIntptr);
 
-             def_val = int_val_buf;
 
-             break;
 
-         case OPARG_TYPE_BOOLEAN:
 
-             def_val = (od->optArg.argBool) ? TRUE_STR : FALSE_STR;
 
-             break;
 
-         default:
 
-             if (od->optArg.argString == NULL) {
 
-                 if (fmt == SGL_DEF_FMT)
 
-                     fmt = SGL_NO_DEF_FMT;
 
-                 def_val = NULL;
 
-             }
 
-             else
 
-                 def_val = od->optArg.argString;
 
-         }
 
-         printf(fmt, opts->pzPROGNAME, od->pz_NAME, def_val);
 
-     }
 
- }
 
- static void
 
- emit_action(tOptions * opts, tOptDesc * od)
 
- {
 
-     if (od->pOptProc == optionPrintVersion)
 
-         printf(ECHO_N_EXIT, opts->pzPROGNAME, VER_STR);
 
-     else if (od->pOptProc == optionPagedUsage)
 
-         printf(PAGE_USAGE_TEXT, opts->pzPROGNAME);
 
-     else if (od->pOptProc == optionLoadOpt) {
 
-         printf(LVL3_CMD, NO_LOAD_WARN);
 
-         printf(LVL3_CMD, YES_NEED_OPT_ARG);
 
-     } else if (od->pz_NAME == NULL) {
 
-         if (od->pOptProc == NULL) {
 
-             printf(LVL3_CMD, NO_SAVE_OPTS);
 
-             printf(LVL3_CMD, OK_NEED_OPT_ARG);
 
-         } else
 
-             printf(ECHO_N_EXIT, opts->pzPROGNAME, LONG_USE_STR);
 
-     } else {
 
-         if (od->optMaxCt == 1)
 
-             printf(SGL_ARG_FMT, opts->pzPROGNAME, od->pz_NAME);
 
-         else {
 
-             if ((unsigned)od->optMaxCt < NOLIMIT)
 
-                 printf(CHK_MAX_COUNT, opts->pzPROGNAME,
 
-                        od->pz_NAME, od->optMaxCt);
 
-             printf(MULTI_ARG_FMT, opts->pzPROGNAME, od->pz_NAME);
 
-         }
 
-         /*
 
-          *  Fix up the args.
 
-          */
 
-         if (OPTST_GET_ARGTYPE(od->fOptState) == OPARG_TYPE_NONE) {
 
-             printf(SET_MULTI_ARG, opts->pzPROGNAME, od->pz_NAME);
 
-             printf(LVL3_CMD, NO_ARG_NEEDED);
 
-         } else if (od->fOptState & OPTST_ARG_OPTIONAL) {
 
-             printf(SET_MULTI_ARG,  opts->pzPROGNAME, od->pz_NAME);
 
-             printf(LVL3_CMD, OK_NEED_OPT_ARG);
 
-         } else {
 
-             printf(LVL3_CMD, YES_NEED_OPT_ARG);
 
-         }
 
-     }
 
-     fputs(zOptionEndSelect, stdout);
 
- }
 
- static void
 
- emit_inaction(tOptions * opts, tOptDesc * od)
 
- {
 
-     if (od->pOptProc == optionLoadOpt) {
 
-         printf(LVL3_CMD, NO_SUPPRESS_LOAD);
 
-     } else if (od->optMaxCt == 1)
 
-         printf(NO_SGL_ARG_FMT, opts->pzPROGNAME,
 
-                od->pz_NAME, od->pz_DisablePfx);
 
-     else
 
-         printf(NO_MULTI_ARG_FMT, opts->pzPROGNAME,
 
-                od->pz_NAME, od->pz_DisablePfx);
 
-     printf(LVL3_CMD, NO_ARG_NEEDED);
 
-     fputs(zOptionEndSelect, stdout);
 
- }
 
- /**
 
-  * recognize flag options.  These go at the end.
 
-  * At the end, emit code to handle options we don't recognize.
 
-  *
 
-  * @param[in] opts  the program options
 
-  */
 
- static void
 
- emit_flag(tOptions * opts)
 
- {
 
-     tOptDesc* od = opts->pOptDesc;
 
-     int       opt_ct = opts->optCt;
 
-     fputs(zOptionCase, stdout);
 
-     for (;opt_ct > 0; od++, --opt_ct) {
 
-         if (SKIP_OPT(od) || ! IS_GRAPHIC_CHAR(od->optValue))
 
-             continue;
 
-         printf(zOptionFlag, od->optValue);
 
-         emit_action(opts, od);
 
-     }
 
-     printf(UNK_OPT_FMT, FLAG_STR, opts->pzPROGNAME);
 
- }
 
- /**
 
-  *  Emit the match text for a long option.  The passed in \a name may be
 
-  *  either the enablement name or the disablement name.
 
-  *
 
-  * @param[in] name  The current name to check.
 
-  * @param[in] cod   current option descriptor
 
-  * @param[in] opts  the program options
 
-  */
 
- static void
 
- emit_match_expr(char const * name, tOptDesc * cod, tOptions * opts)
 
- {
 
-     char name_bf[32];
 
-     unsigned int    min_match_ct = 2;
 
-     unsigned int    max_match_ct = strlen(name) - 1;
 
-     if (max_match_ct >= sizeof(name_bf) - 1)
 
-         goto leave;
 
-     
 
-     {
 
-         tOptDesc *  od = opts->pOptDesc;
 
-         int         ct = opts->optCt;
 
-         for (; ct-- > 0; od++) {
 
-             unsigned int match_ct = 0;
 
-             /*
 
-              *  Omit the current option, Doc opts and compiled out opts.
 
-              */
 
-             if ((od == cod) || SKIP_OPT(od))
 
-                 continue;
 
-             /*
 
-              *  Check each character of the name case insensitively.
 
-              *  They must not be the same.  They cannot be, because it would
 
-              *  not compile correctly if they were.
 
-              */
 
-             while (toupper(od->pz_Name[match_ct]) == toupper(name[match_ct]))
 
-                 match_ct++;
 
-             if (match_ct > min_match_ct)
 
-                 min_match_ct = match_ct;
 
-             /*
 
-              *  Check the disablement name, too.
 
-              */
 
-             if (od->pz_DisableName == NULL)
 
-                 continue;
 
-             match_ct = 0;
 
-             while (  toupper(od->pz_DisableName[match_ct])
 
-                   == toupper(name[match_ct]))
 
-                 match_ct++;
 
-             if (match_ct > min_match_ct)
 
-                 min_match_ct = match_ct;
 
-         }
 
-     }
 
-     /*
 
-      *  Don't bother emitting partial matches if there is only one possible
 
-      *  partial match.
 
-      */
 
-     if (min_match_ct < max_match_ct) {
 
-         char *  pz    = name_bf + min_match_ct;
 
-         int     nm_ix = min_match_ct;
 
-         memcpy(name_bf, name, min_match_ct);
 
-         for (;;) {
 
-             *pz = NUL;
 
-             printf(zOptionPartName, name_bf);
 
-             *pz++ = name[nm_ix++];
 
-             if (name[nm_ix] == NUL) {
 
-                 *pz = NUL;
 
-                 break;
 
-             }
 
-         }
 
-     }
 
- leave:
 
-     printf(zOptionFullName, name);
 
- }
 
- /**
 
-  *  Emit GNU-standard long option handling code.
 
-  *
 
-  * @param[in] opts  the program options
 
-  */
 
- static void
 
- emit_long(tOptions * opts)
 
- {
 
-     tOptDesc * od = opts->pOptDesc;
 
-     int        ct  = opts->optCt;
 
-     fputs(zOptionCase, stdout);
 
-     /*
 
-      *  do each option, ...
 
-      */
 
-     do  {
 
-         /*
 
-          *  Documentation & compiled-out options
 
-          */
 
-         if (SKIP_OPT(od))
 
-             continue;
 
-         emit_match_expr(od->pz_Name, od, opts);
 
-         emit_action(opts, od);
 
-         /*
 
-          *  Now, do the same thing for the disablement version of the option.
 
-          */
 
-         if (od->pz_DisableName != NULL) {
 
-             emit_match_expr(od->pz_DisableName, od, opts);
 
-             emit_inaction(opts, od);
 
-         }
 
-     } while (od++, --ct > 0);
 
-     printf(UNK_OPT_FMT, OPTION_STR, opts->pzPROGNAME);
 
- }
 
- /**
 
-  * Load the previous shell script output file.  We need to preserve any
 
-  * hand-edited additions outside of the START_MARK and END_MARKs.
 
-  *
 
-  * @param[in] fname  the output file name
 
-  */
 
- static char *
 
- load_old_output(char const * fname, char const * pname)
 
- {
 
-     /*
 
-      *  IF we cannot stat the file,
 
-      *  THEN assume we are creating a new file.
 
-      *       Skip the loading of the old data.
 
-      */
 
-     FILE * fp = fopen(fname, "r" FOPEN_BINARY_FLAG);
 
-     struct stat stbf;
 
-     char * text;
 
-     char * scan;
 
-     if (fp == NULL)
 
-         return NULL;
 
-     /*
 
-      * If we opened it, we should be able to stat it and it needs
 
-      * to be a regular file
 
-      */
 
-     if ((fstat(fileno(fp), &stbf) != 0) || (! S_ISREG(stbf.st_mode)))
 
-         fserr_exit(pname, "fstat", fname);
 
-     scan = text = AGALOC(stbf.st_size + 1, "f data");
 
-     /*
 
-      *  Read in all the data as fast as our OS will let us.
 
-      */
 
-     for (;;) {
 
-         size_t inct = fread((void*)scan, 1, (size_t)stbf.st_size, fp);
 
-         if (inct == 0)
 
-             break;
 
-         stbf.st_size -= (ssize_t)inct;
 
-         if (stbf.st_size == 0)
 
-             break;
 
-         scan += inct;
 
-     }
 
-     *scan = NUL;
 
-     fclose(fp);
 
-     return text;
 
- }
 
- /**
 
-  * Open the specified output file.  If it already exists, load its
 
-  * contents and save the non-generated (hand edited) portions.
 
-  * If a "start mark" is found, everything before it is preserved leader.
 
-  * If not, the entire thing is a trailer.  Assuming the start is found,
 
-  * then everything after the end marker is the trailer.  If the end
 
-  * mark is not found, the file is actually corrupt, but we take the
 
-  * remainder to be the trailer.
 
-  *
 
-  * @param[in] fname  the output file name
 
-  */
 
- static void
 
- open_out(char const * fname, char const * pname)
 
- {
 
-     do  {
 
-         char * txt = script_text = load_old_output(fname, pname);
 
-         char * scn;
 
-         if (txt == NULL)
 
-             break;
 
-         scn = strstr(txt, START_MARK);
 
-         if (scn == NULL) {
 
-             script_trailer = txt;
 
-             break;
 
-         }
 
-         *(scn++) = NUL;
 
-         scn = strstr(scn, END_MARK);
 
-         if (scn == NULL) {
 
-             /*
 
-              * The file is corrupt.  Set the trailer to be everything
 
-              * after the start mark. The user will need to fix it up.
 
-              */
 
-             script_trailer = txt + strlen(txt) + START_MARK_LEN + 1;
 
-             break;
 
-         }
 
-         /*
 
-          *  Check to see if the data contains our marker.
 
-          *  If it does, then we will skip over it
 
-          */
 
-         script_trailer = scn + END_MARK_LEN;
 
-         script_leader  = txt;
 
-     } while (false);
 
-     if (freopen(fname, "w" FOPEN_BINARY_FLAG, stdout) != stdout)
 
-         fserr_exit(pname, "freopen", fname);
 
- }
 
- /*=export_func genshelloptUsage
 
-  * private:
 
-  * what: The usage function for the genshellopt generated program
 
-  *
 
-  * arg:  + tOptions* + opts    + program options descriptor +
 
-  * arg:  + int       + exit_cd + usage text type to produce +
 
-  *
 
-  * doc:
 
-  *  This function is used to create the usage strings for the option
 
-  *  processing shell script code.  Two child processes are spawned
 
-  *  each emitting the usage text in either the short (error exit)
 
-  *  style or the long style.  The generated program will capture this
 
-  *  and create shell script variables containing the two types of text.
 
- =*/
 
- void
 
- genshelloptUsage(tOptions * opts, int exit_cd)
 
- {
 
- #if ! defined(HAVE_WORKING_FORK)
 
-     optionUsage(opts, exit_cd);
 
- #else
 
-     /*
 
-      *  IF not EXIT_SUCCESS,
 
-      *  THEN emit the short form of usage.
 
-      */
 
-     if (exit_cd != EXIT_SUCCESS)
 
-         optionUsage(opts, exit_cd);
 
-     fflush(stderr);
 
-     fflush(stdout);
 
-     if (ferror(stdout) || ferror(stderr))
 
-         option_exits(EXIT_FAILURE);
 
-     option_usage_fp = stdout;
 
-     /*
 
-      *  First, print our usage
 
-      */
 
-     switch (fork()) {
 
-     case -1:
 
-         optionUsage(opts, EXIT_FAILURE);
 
-         /* NOTREACHED */
 
-     case 0:
 
-         pagerState = PAGER_STATE_CHILD;
 
-         optionUsage(opts, EXIT_SUCCESS);
 
-         /* NOTREACHED */
 
-         _exit(EXIT_FAILURE);
 
-     default:
 
-     {
 
-         int  sts;
 
-         wait(&sts);
 
-     }
 
-     }
 
-     /*
 
-      *  Generate the pzProgName, since optionProcess() normally
 
-      *  gets it from the command line
 
-      */
 
-     {
 
-         char *  pz;
 
-         char ** pp = (char **)(void *)&(optionParseShellOptions->pzProgName);
 
-         AGDUPSTR(pz, optionParseShellOptions->pzPROGNAME, "prog name");
 
-         *pp = pz;
 
-         while (*pz != NUL) {
 
-             *pz = (char)tolower(*pz);
 
-             pz++;
 
-         }
 
-     }
 
-     /*
 
-      *  Separate the makeshell usage from the client usage
 
-      */
 
-     fprintf(option_usage_fp, zGenshell, optionParseShellOptions->pzProgName);
 
-     fflush(option_usage_fp);
 
-     /*
 
-      *  Now, print the client usage.
 
-      */
 
-     switch (fork()) {
 
-     case 0:
 
-         pagerState = PAGER_STATE_CHILD;
 
-         /*FALLTHROUGH*/
 
-     case -1:
 
-         optionUsage(optionParseShellOptions, EXIT_FAILURE);
 
-     default:
 
-     {
 
-         int  sts;
 
-         wait(&sts);
 
-     }
 
-     }
 
-     fflush(stdout);
 
-     if (ferror(stdout))
 
-         fserr_exit(opts->pzProgName, zwriting, zstdout_name);
 
-     option_exits(EXIT_SUCCESS);
 
- #endif
 
- }
 
- /** @}
 
-  *
 
-  * Local Variables:
 
-  * mode: C
 
-  * c-file-style: "stroustrup"
 
-  * indent-tabs-mode: nil
 
-  * End:
 
-  * end of autoopts/makeshell.c */
 
 
  |