summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/sntp/libopts/makeshell.c
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2015-07-15 19:21:26 +0000
committerdelphij <delphij@FreeBSD.org>2015-07-15 19:21:26 +0000
commit2a25cee78ab1d37e7d2bc40ae675646974d99f56 (patch)
treeb0302ac4be59e104f4e1e54014561a1389397192 /contrib/ntp/sntp/libopts/makeshell.c
parenta0741a75537b2e0514472ac3b28afc55a7846c30 (diff)
downloadFreeBSD-src-2a25cee78ab1d37e7d2bc40ae675646974d99f56.zip
FreeBSD-src-2a25cee78ab1d37e7d2bc40ae675646974d99f56.tar.gz
MFC r280849,280915-280916,281015-281016,282097,282408,282415,283542,
284864,285169-285170,285435: ntp 4.2.8p3. Relnotes: yes Approved by: re (?)
Diffstat (limited to 'contrib/ntp/sntp/libopts/makeshell.c')
-rw-r--r--contrib/ntp/sntp/libopts/makeshell.c1314
1 files changed, 574 insertions, 740 deletions
diff --git a/contrib/ntp/sntp/libopts/makeshell.c b/contrib/ntp/sntp/libopts/makeshell.c
index 8447d45..a61df42 100644
--- a/contrib/ntp/sntp/libopts/makeshell.c
+++ b/contrib/ntp/sntp/libopts/makeshell.c
@@ -1,606 +1,364 @@
-/*
- * $Id: makeshell.c,v 4.20 2007/02/04 17:44:12 bkorb Exp $
- * Time-stamp: "2007-01-27 06:05:45 bkorb"
+/**
+ * \file makeshell.c
*
* This module will interpret the options set in the tOptions
* structure and create a Bourne shell script capable of parsing them.
- */
-
-/*
- * Automated Options copyright 1992-2007 Bruce Korb
- *
- * Automated Options is free software.
- * You may redistribute it and/or modify it under the terms of the
- * GNU General Public License, as published by the Free Software
- * Foundation; either version 2, or (at your option) any later version.
- *
- * Automated Options is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Automated Options. See the file "COPYING". If not,
- * write to: The Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
*
- * As a special exception, Bruce Korb gives permission for additional
- * uses of the text contained in his release of AutoOpts.
- *
- * The exception is that, if you link the AutoOpts library with other
- * files to produce an executable, this does not by itself cause the
- * resulting executable to be covered by the GNU General Public License.
- * Your use of that executable is in no way restricted on account of
- * linking the AutoOpts library code into it.
- *
- * This exception does not however invalidate any other reasons why
- * the executable file might be covered by the GNU General Public License.
- *
- * This exception applies only to the code released by Bruce Korb under
- * the name AutoOpts. If you copy code from other sources under the
- * General Public License into a copy of AutoOpts, as the General Public
- * License permits, the exception does not apply to the code that you add
- * in this way. To avoid misleading anyone as to the status of such
- * modified files, you must delete this exception notice from them.
- *
- * If you write modifications of your own for AutoOpts, it is your choice
- * whether to permit this exception to apply to your modifications.
- * If you do not wish that, delete this exception notice.
+ * @addtogroup autoopts
+ * @{
*/
-
-tOptions* pShellParseOptions = NULL;
-
-/* * * * * * * * * * * * * * * * * * * * *
- *
- * Setup Format Strings
- */
-tSCC zStartMarker[] =
-"# # # # # # # # # # -- do not modify this marker --\n#\n"
-"# DO NOT EDIT THIS SECTION";
-
-tSCC zPreamble[] =
-"%s OF %s\n#\n"
-"# From here to the next `-- do not modify this marker --',\n"
-"# the text has been generated %s\n";
-
-tSCC zEndPreamble[] =
-"# From the %s option definitions\n#\n";
-
-tSCC zMultiDef[] = "\n"
-"if test -z \"${%1$s_%2$s}\"\n"
-"then\n"
-" %1$s_%2$s_CT=0\n"
-"else\n"
-" %1$s_%2$s_CT=1\n"
-" %1$s_%2$s_1=\"${%1$s_%2$s}\"\n"
-"fi\n"
-"export %1$s_%2$s_CT";
-
-tSCC zSingleDef[] = "\n"
-"%1$s_%2$s=\"${%1$s_%2$s-'%3$s'}\"\n"
-"%1$s_%2$s_set=false\n"
-"export %1$s_%2$s\n";
-
-tSCC zSingleNoDef[] = "\n"
-"%1$s_%2$s=\"${%1$s_%2$s}\"\n"
-"%1$s_%2$s_set=false\n"
-"export %1$s_%2$s\n";
-
-/* * * * * * * * * * * * * * * * * * * * *
- *
- * LOOP START
+/*
+ * This file is part of AutoOpts, a companion to AutoGen.
+ * AutoOpts is free software.
+ * AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved
*
- * The loop may run in either of two modes:
- * all options are named options (loop only)
- * regular, marked option processing.
- */
-tSCC zLoopCase[] = "\n"
-"OPT_PROCESS=true\n"
-"OPT_ARG=\"$1\"\n\n"
-"while ${OPT_PROCESS} && [ $# -gt 0 ]\ndo\n"
-" OPT_ELEMENT=''\n"
-" OPT_ARG_VAL=''\n\n"
- /*
- * 'OPT_ARG' may or may not match the current $1
- */
-" case \"${OPT_ARG}\" in\n"
-" -- )\n"
-" OPT_PROCESS=false\n"
-" shift\n"
-" ;;\n\n";
-
-tSCC zLoopOnly[] = "\n"
-"OPT_ARG=\"$1\"\n\n"
-"while [ $# -gt 0 ]\ndo\n"
-" OPT_ELEMENT=''\n"
-" OPT_ARG_VAL=''\n\n"
-" OPT_ARG=\"${1}\"\n";
-
-/* * * * * * * * * * * * * * * *
+ * 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.
*
- * CASE SELECTORS
+ * The GNU Lesser General Public License, version 3 or later
+ * See the files "COPYING.lgplv3" and "COPYING.gplv3"
*
- * If the loop runs as a regular option loop,
- * then we must have selectors for each acceptable option
- * type (long option, flag character and non-option)
- */
-tSCC zLongSelection[] =
-" --* )\n";
-
-tSCC zFlagSelection[] =
-" -* )\n";
-
-tSCC zEndSelection[] =
-" ;;\n\n";
-
-tSCC zNoSelection[] =
-" * )\n"
-" OPT_PROCESS=false\n"
-" ;;\n"
-" esac\n\n";
-
-/* * * * * * * * * * * * * * * *
+ * The Modified Berkeley Software Distribution License
+ * See the file "COPYING.mbsd"
*
- * LOOP END
- */
-tSCC zLoopEnd[] =
-" if [ -n \"${OPT_ARG_VAL}\" ]\n"
-" then\n"
-" eval %1$s_${OPT_NAME}${OPT_ELEMENT}=\"'${OPT_ARG_VAL}'\"\n"
-" export %1$s_${OPT_NAME}${OPT_ELEMENT}\n"
-" fi\n"
-"done\n\n"
-"unset OPT_PROCESS || :\n"
-"unset OPT_ELEMENT || :\n"
-"unset OPT_ARG || :\n"
-"unset OPT_ARG_NEEDED || :\n"
-"unset OPT_NAME || :\n"
-"unset OPT_CODE || :\n"
-"unset OPT_ARG_VAL || :\n%2$s";
-
-tSCC zTrailerMarker[] = "\n"
-"# # # # # # # # # #\n#\n"
-"# END OF AUTOMATED OPTION PROCESSING\n"
-"#\n# # # # # # # # # # -- do not modify this marker --\n";
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * These files have the following sha256 sums:
*
- * OPTION SELECTION
+ * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3
+ * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3
+ * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd
*/
-tSCC zOptionCase[] =
-" case \"${OPT_CODE}\" in\n";
-
-tSCC zOptionPartName[] =
-" '%s' | \\\n";
-tSCC zOptionFullName[] =
-" '%s' )\n";
+ static inline unsigned char to_uchar (char ch) { return ch; }
-tSCC zOptionFlag[] =
-" '%c' )\n";
+#define UPPER(_c) (toupper(to_uchar(_c)))
+#define LOWER(_c) (tolower(to_uchar(_c)))
-tSCC zOptionEndSelect[] =
-" ;;\n\n";
-
-tSCC zOptionUnknown[] =
-" * )\n"
-" echo Unknown %s: \"${OPT_CODE}\" >&2\n"
-" echo \"$%s_USAGE_TEXT\"\n"
-" exit 1\n"
-" ;;\n"
-" esac\n\n";
+/* = = = START-STATIC-FORWARD = = = */
+static void
+emit_var_text(char const * prog, char const * var, int fdin);
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * OPTION PROCESSING
- *
- * Formats for emitting the text for handling particular options
- */
-tSCC zTextExit[] =
-" echo \"$%s_%s_TEXT\"\n"
-" exit 0\n";
-
-tSCC zPagedUsageExit[] =
-" echo \"$%s_LONGUSAGE_TEXT\" | ${PAGER-more}\n"
-" exit 0\n";
-
-tSCC zCmdFmt[] =
-" %s\n";
-
-tSCC zCountTest[] =
-" if [ $%1$s_%2$s_CT -ge %3$d ] ; then\n"
-" echo Error: more than %3$d %2$s options >&2\n"
-" echo \"$%1$s_USAGE_TEXT\"\n"
-" exit 1 ; fi\n";
-
-tSCC zMultiArg[] =
-" %1$s_%2$s_CT=`expr ${%1$s_%2$s_CT} + 1`\n"
-" OPT_ELEMENT=\"_${%1$s_%2$s_CT}\"\n"
-" OPT_NAME='%2$s'\n";
-
-tSCC zSingleArg[] =
-" if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n"
-" echo Error: duplicate %2$s option >&2\n"
-" echo \"$%1$s_USAGE_TEXT\"\n"
-" exit 1 ; fi\n"
-" %1$s_%2$s_set=true\n"
-" OPT_NAME='%2$s'\n";
-
-tSCC zNoMultiArg[] =
-" %1$s_%2$s_CT=0\n"
-" OPT_ELEMENT=''\n"
-" %1$s_%2$s='%3$s'\n"
-" export %1$s_%2$s\n"
-" OPT_NAME='%2$s'\n";
-
-tSCC zNoSingleArg[] =
-" if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n"
-" echo Error: duplicate %2$s option >&2\n"
-" echo \"$%1$s_USAGE_TEXT\"\n"
-" exit 1 ; fi\n"
-" %1$s_%2$s_set=true\n"
-" %1$s_%2$s='%3$s'\n"
-" export %1$s_%2$s\n"
-" OPT_NAME='%2$s'\n";
-
-tSCC zMayArg[] =
-" eval %1$s_%2$s${OPT_ELEMENT}=true\n"
-" export %1$s_%2$s${OPT_ELEMENT}\n"
-" OPT_ARG_NEEDED=OK\n";
-
-tSCC zMustArg[] =
-" OPT_ARG_NEEDED=YES\n";
-
-tSCC zCantArg[] =
-" eval %1$s_%2$s${OPT_ELEMENT}=true\n"
-" export %1$s_%2$s${OPT_ELEMENT}\n"
-" OPT_ARG_NEEDED=NO\n";
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * LONG OPTION PROCESSING
- *
- * Formats for emitting the text for handling long option types
- */
-tSCC zLongOptInit[] =
-" OPT_CODE=`echo \"X${OPT_ARG}\"|sed 's/^X-*//'`\n"
-" shift\n"
-" OPT_ARG=\"$1\"\n\n"
-" case \"${OPT_CODE}\" in *=* )\n"
-" OPT_ARG_VAL=`echo \"${OPT_CODE}\"|sed 's/^[^=]*=//'`\n"
-" OPT_CODE=`echo \"${OPT_CODE}\"|sed 's/=.*$//'` ;; esac\n\n";
-
-tSCC zLongOptArg[] =
-" case \"${OPT_ARG_NEEDED}\" in\n"
-" NO )\n"
-" OPT_ARG_VAL=''\n"
-" ;;\n\n"
-" YES )\n"
-" if [ -z \"${OPT_ARG_VAL}\" ]\n"
-" then\n"
-" if [ $# -eq 0 ]\n"
-" then\n"
-" echo No argument provided for ${OPT_NAME} option >&2\n"
-" echo \"$%s_USAGE_TEXT\"\n"
-" exit 1\n"
-" fi\n\n"
-" OPT_ARG_VAL=\"${OPT_ARG}\"\n"
-" shift\n"
-" OPT_ARG=\"$1\"\n"
-" fi\n"
-" ;;\n\n"
-" OK )\n"
-" if [ -z \"${OPT_ARG_VAL}\" ] && [ $# -gt 0 ]\n"
-" then\n"
-" case \"${OPT_ARG}\" in -* ) ;; * )\n"
-" OPT_ARG_VAL=\"${OPT_ARG}\"\n"
-" shift\n"
-" OPT_ARG=\"$1\" ;; esac\n"
-" fi\n"
-" ;;\n"
-" esac\n";
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
- * FLAG OPTION PROCESSING
- *
- * Formats for emitting the text for handling flag option types
- */
-tSCC zFlagOptInit[] =
-" OPT_CODE=`echo \"X${OPT_ARG}\" | sed 's/X-\\(.\\).*/\\1/'`\n"
-" OPT_ARG=` echo \"X${OPT_ARG}\" | sed 's/X-.//'`\n\n";
-
-tSCC zFlagOptArg[] =
-" case \"${OPT_ARG_NEEDED}\" in\n"
-" NO )\n"
-" if [ -n \"${OPT_ARG}\" ]\n"
-" then\n"
-" OPT_ARG=-\"${OPT_ARG}\"\n"
-" else\n"
-" shift\n"
-" OPT_ARG=\"$1\"\n"
-" fi\n"
-" ;;\n\n"
-" YES )\n"
-" if [ -n \"${OPT_ARG}\" ]\n"
-" then\n"
-" OPT_ARG_VAL=\"${OPT_ARG}\"\n\n"
-" else\n"
-" if [ $# -eq 0 ]\n"
-" then\n"
-" echo No argument provided for ${OPT_NAME} option >&2\n"
-" echo \"$%s_USAGE_TEXT\"\n"
-" exit 1\n"
-" fi\n"
-" shift\n"
-" OPT_ARG_VAL=\"$1\"\n"
-" fi\n\n"
-" shift\n"
-" OPT_ARG=\"$1\"\n"
-" ;;\n\n"
-" OK )\n"
-" if [ -n \"${OPT_ARG}\" ]\n"
-" then\n"
-" OPT_ARG_VAL=\"${OPT_ARG}\"\n"
-" shift\n"
-" OPT_ARG=\"$1\"\n\n"
-" else\n"
-" shift\n"
-" if [ $# -gt 0 ]\n"
-" then\n"
-" case \"$1\" in -* ) ;; * )\n"
-" OPT_ARG_VAL=\"$1\"\n"
-" shift ;; esac\n"
-" OPT_ARG=\"$1\"\n"
-" fi\n"
-" fi\n"
-" ;;\n"
-" esac\n";
-
-tSCC* pzShell = NULL;
-static char* pzLeader = NULL;
-static char* pzTrailer = NULL;
+static void
+text_to_var(tOptions * opts, teTextTo which, tOptDesc * od);
-/* = = = START-STATIC-FORWARD = = = */
-/* static forward declarations maintained by :mkfwd */
static void
-textToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD );
+emit_usage(tOptions * opts);
static void
-emitUsage( tOptions* pOpts );
+emit_wrapup(tOptions * opts);
static void
-emitSetup( tOptions* pOpts );
+emit_setup(tOptions * opts);
static void
-printOptionAction( tOptions* pOpts, tOptDesc* pOptDesc );
+emit_action(tOptions * opts, tOptDesc * od);
static void
-printOptionInaction( tOptions* pOpts, tOptDesc* pOptDesc );
+emit_inaction(tOptions * opts, tOptDesc * od);
static void
-emitFlag( tOptions* pOpts );
+emit_flag(tOptions * opts);
static void
-emitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts );
+emit_match_expr(char const * name, tOptDesc * cod, tOptions * opts);
static void
-emitLong( tOptions* pOpts );
+emit_long(tOptions * opts);
+
+static char *
+load_old_output(char const * fname, char const * pname);
static void
-openOutput( char const* pzFile );
+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 +
+ * arg: + tOptions * + pOpts + program options descriptor +
*
* doc:
* Emit a shell script that will parse the command line options.
=*/
void
-optionParseShell( tOptions* pOpts )
+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_OPT( SHELL ))
- pzShell = OPT_ARG( SHELL );
+ if (HAVE_GENSHELL_OPT(SHELL))
+ shell_prog = GENSHELL_OPT_ARG(SHELL);
- else if (! ENABLED_OPT( SHELL ))
- pzShell = NULL;
+ else if (! ENABLED_GENSHELL_OPT(SHELL))
+ shell_prog = NULL;
- else if ((pzShell = getenv( "SHELL" )),
- pzShell == NULL)
+ else if ((shell_prog = getenv("SHELL")),
+ shell_prog == NULL)
- pzShell = "/bin/sh";
+ shell_prog = POSIX_SHELL;
/*
* Check for a specified output file
*/
- if (HAVE_OPT( SCRIPT ))
- openOutput( OPT_ARG( SCRIPT ));
-
- emitUsage( pOpts );
- emitSetup( pOpts );
+ 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 (pOpts->fOptSet & (OPTPROC_LONGOPT|OPTPROC_SHORTOPT)) {
+ switch (opts->fOptSet & (OPTPROC_LONGOPT|OPTPROC_SHORTOPT)) {
case OPTPROC_LONGOPT:
- fputs( zLoopCase, stdout );
+ fputs(LOOP_STR, stdout);
- fputs( zLongSelection, stdout );
- fputs( zLongOptInit, stdout );
- emitLong( pOpts );
- printf( zLongOptArg, pOpts->pzPROGNAME );
- fputs( zEndSelection, 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( zNoSelection, stdout );
+ fputs(NOT_FOUND_STR, stdout);
break;
case 0:
- fputs( zLoopOnly, stdout );
- fputs( zLongOptInit, stdout );
- emitLong( pOpts );
- printf( zLongOptArg, pOpts->pzPROGNAME );
+ fputs(ONLY_OPTS_LOOP, stdout);
+ fputs(INIT_LOPT_STR, stdout);
+ emit_long(opts);
+ printf(LOPT_ARG_FMT, opts->pzPROGNAME);
break;
case OPTPROC_SHORTOPT:
- fputs( zLoopCase, stdout );
+ fputs(LOOP_STR, stdout);
- fputs( zFlagSelection, stdout );
- fputs( zFlagOptInit, stdout );
- emitFlag( pOpts );
- printf( zFlagOptArg, pOpts->pzPROGNAME );
- fputs( zEndSelection, 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( zNoSelection, stdout );
+ fputs(NOT_FOUND_STR, stdout);
break;
case OPTPROC_LONGOPT|OPTPROC_SHORTOPT:
- fputs( zLoopCase, stdout );
+ fputs(LOOP_STR, stdout);
- fputs( zLongSelection, stdout );
- fputs( zLongOptInit, stdout );
- emitLong( pOpts );
- printf( zLongOptArg, pOpts->pzPROGNAME );
- fputs( zEndSelection, 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( zFlagSelection, stdout );
- fputs( zFlagOptInit, stdout );
- emitFlag( pOpts );
- printf( zFlagOptArg, pOpts->pzPROGNAME );
- fputs( zEndSelection, 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( zNoSelection, stdout );
+ fputs(NOT_FOUND_STR, stdout);
break;
}
- printf( zLoopEnd, pOpts->pzPROGNAME, zTrailerMarker );
- if ((pzTrailer != NULL) && (*pzTrailer != '\0'))
- fputs( pzTrailer, stdout );
- else if (ENABLED_OPT( SHELL ))
- printf( "\nenv | grep '^%s_'\n", pOpts->pzPROGNAME );
+ 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);
- fflush( stdout );
- fchmod( STDOUT_FILENO, 0755 );
- fclose( stdout );
+#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
-textToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD )
+text_to_var(tOptions * opts, teTextTo which, tOptDesc * od)
{
-# define _TT_(n) tSCC z ## n [] = #n;
+# define _TT_(n) static char const z ## n [] = #n;
TEXTTO_TABLE
# undef _TT_
# define _TT_(n) z ## n ,
- static char const* apzTTNames[] = { TEXTTO_TABLE };
+ static char const * ttnames[] = { TEXTTO_TABLE };
# undef _TT_
-#if defined(__windows__) && !defined(__CYGWIN__)
- printf( "%1$s_%2$s_TEXT='no %2$s text'\n",
- pOpts->pzPROGNAME, apzTTNames[ whichVar ]);
+#if ! defined(HAVE_WORKING_FORK)
+ printf(SET_NO_TEXT_FMT, opts->pzPROGNAME, ttnames[which]);
#else
- int nlHoldCt = 0;
- int pipeFd[2];
- FILE* fp;
+ int fdpair[2];
- printf( "%s_%s_TEXT='", pOpts->pzPROGNAME, apzTTNames[ whichVar ]);
- fflush( stdout );
+ fflush(stdout);
+ fflush(stderr);
- if (pipe( pipeFd ) != 0) {
- fprintf( stderr, zBadPipe, errno, strerror( errno ));
- exit( EXIT_FAILURE );
- }
+ if (pipe(fdpair) != 0)
+ fserr_exit(opts->pzProgName, "pipe", zinter_proc_pipe);
switch (fork()) {
case -1:
- fprintf( stderr, zForkFail, errno, strerror(errno), pOpts->pzProgName);
- exit( EXIT_FAILURE );
- break;
+ fserr_exit(opts->pzProgName, "fork", opts->pzProgName);
+ /* NOTREACHED */
case 0:
- dup2( pipeFd[1], STDERR_FILENO );
- dup2( pipeFd[1], STDOUT_FILENO );
- close( pipeFd[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 (whichVar) {
+ switch (which) {
case TT_LONGUSAGE:
- (*(pOpts->pUsageProc))( pOpts, EXIT_SUCCESS );
+ (*(opts->pUsageProc))(opts, EXIT_SUCCESS);
/* NOTREACHED */
- exit( EXIT_FAILURE );
case TT_USAGE:
- (*(pOpts->pUsageProc))( pOpts, EXIT_FAILURE );
+ (*(opts->pUsageProc))(opts, EXIT_FAILURE);
/* NOTREACHED */
- exit( EXIT_FAILURE );
case TT_VERSION:
- if (pOD->fOptState & OPTST_ALLOC_ARG) {
- AGFREE(pOD->optArg.argString);
- pOD->fOptState &= ~OPTST_ALLOC_ARG;
+ if (od->fOptState & OPTST_ALLOC_ARG) {
+ AGFREE(od->optArg.argString);
+ od->fOptState &= ~OPTST_ALLOC_ARG;
}
- pOD->optArg.argString = "c";
- optionPrintVersion( pOpts, pOD );
+ od->optArg.argString = "c";
+ optionPrintVersion(opts, od);
/* NOTREACHED */
default:
- exit( EXIT_FAILURE );
+ option_exits(EXIT_FAILURE);
+ /* NOTREACHED */
}
+ /* NOTREACHED */
default:
- close( pipeFd[1] );
- fp = fdopen( pipeFd[0], "r" FOPEN_BINARY_FLAG );
+ close(fdpair[1]);
}
- for (;;) {
- int ch = fgetc( fp );
- switch (ch) {
-
- case '\n':
- nlHoldCt++;
- break;
-
- case '\'':
- while (nlHoldCt > 0) {
- fputc( '\n', stdout );
- nlHoldCt--;
- }
- fputs( "'\\''", stdout );
- break;
-
- case EOF:
- goto endCharLoop;
-
- default:
- while (nlHoldCt > 0) {
- fputc( '\n', stdout );
- nlHoldCt--;
- }
- fputc( ch, stdout );
- break;
- }
- } endCharLoop:;
-
- fputs( "'\n\n", stdout );
- close( pipeFd[0] );
+ emit_var_text(opts->pzPROGNAME, ttnames[which], fdpair[0]);
#endif
}
-
+/**
+ * capture usage text in shell variables.
+ *
+ */
static void
-emitUsage( tOptions* pOpts )
+emit_usage(tOptions * opts)
{
- char zTimeBuf[ AO_NAME_SIZE ];
+ char tm_nm_buf[AO_NAME_SIZE];
/*
* First, switch stdout to the output file name.
@@ -608,54 +366,61 @@ emitUsage( tOptions* pOpts )
* by the definitions (rather than the current
* executable name). Down case the upper cased name.
*/
- if (pzLeader != NULL)
- fputs( pzLeader, stdout );
+ if (script_leader != NULL)
+ fputs(script_leader, stdout);
{
- tSCC zStdout[] = "stdout";
- tCC* pzOutName;
+ char const * out_nm;
{
- time_t curTime = time( NULL );
- struct tm* pTime = localtime( &curTime );
- strftime(zTimeBuf, AO_NAME_SIZE, "%A %B %e, %Y at %r %Z", pTime );
+ time_t c_tim = time(NULL);
+ struct tm * ptm = localtime(&c_tim);
+ strftime(tm_nm_buf, AO_NAME_SIZE, TIME_FMT, ptm );
}
- if (HAVE_OPT( SCRIPT ))
- pzOutName = OPT_ARG( SCRIPT );
- else pzOutName = zStdout;
+ if (HAVE_GENSHELL_OPT(SCRIPT))
+ out_nm = GENSHELL_OPT_ARG(SCRIPT);
+ else out_nm = STDOUT;
- if ((pzLeader == NULL) && (pzShell != NULL))
- printf( "#! %s\n", pzShell );
+ if ((script_leader == NULL) && (shell_prog != NULL))
+ printf(SHELL_MAGIC, shell_prog);
- printf( zPreamble, zStartMarker, pzOutName, zTimeBuf );
+ 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
+ * Get a copy of the original program name in lower case and
+ * fill in an approximation of the program name from it.
*/
{
- char* pzPN = zTimeBuf;
- tCC* pz = pOpts->pzPROGNAME;
+ char * pzPN = tm_nm_buf;
+ char const * pz = opts->pzPROGNAME;
+ char ** pp;
+
+ /* Copy the program name into the time/name buffer */
for (;;) {
- if ((*pzPN++ = tolower( *pz++ )) == '\0')
+ if ((*pzPN++ = (char)tolower(*pz++)) == NUL)
break;
}
- }
- printf( zEndPreamble, pOpts->pzPROGNAME );
+ pp = VOIDP(&(opts->pzProgPath));
+ *pp = tm_nm_buf;
+ pp = VOIDP(&(opts->pzProgName));
+ *pp = tm_nm_buf;
+ }
- pOpts->pzProgPath = pOpts->pzProgName = zTimeBuf;
- textToVariable( pOpts, TT_LONGUSAGE, NULL );
- textToVariable( pOpts, TT_USAGE, NULL );
+ text_to_var(opts, TT_LONGUSAGE, NULL);
+ text_to_var(opts, TT_USAGE, NULL);
{
- tOptDesc* pOptDesc = pOpts->pOptDesc;
- int optionCt = pOpts->optCt;
+ tOptDesc * pOptDesc = opts->pOptDesc;
+ int optionCt = opts->optCt;
for (;;) {
if (pOptDesc->pOptProc == optionPrintVersion) {
- textToVariable( pOpts, TT_VERSION, pOptDesc );
+ text_to_var(opts, TT_VERSION, pOptDesc);
break;
}
@@ -666,254 +431,291 @@ emitUsage( tOptions* pOpts )
}
}
+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
-emitSetup( tOptions* pOpts )
+emit_setup(tOptions * opts)
{
- tOptDesc* pOptDesc = pOpts->pOptDesc;
- int optionCt = pOpts->presetOptCt;
- char const* pzFmt;
- char const* pzDefault;
+ tOptDesc * od = opts->pOptDesc;
+ int opt_ct = opts->presetOptCt;
+ char const * fmt;
+ char const * def_val;
- for (;optionCt > 0; pOptDesc++, --optionCt) {
- char zVal[16];
+ 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(pOptDesc) || (pOptDesc->pz_NAME == NULL))
+ if (SKIP_OPT(od) || (od->pz_NAME == NULL))
continue;
- if (pOptDesc->optMaxCt > 1)
- pzFmt = zMultiDef;
- else pzFmt = zSingleDef;
+ 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(pOptDesc->fOptState)) {
+ switch (OPTST_GET_ARGTYPE(od->fOptState)) {
case OPARG_TYPE_ENUMERATION:
- (*(pOptDesc->pOptProc))( (tOptions*)2UL, pOptDesc );
- pzDefault = pOptDesc->optArg.argString;
+ (*(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( zVal, sizeof( zVal ), "%d",
- (int)pOptDesc->optArg.argInt );
- pzDefault = zVal;
+ snprintf(int_val_buf, sizeof(int_val_buf), "%d",
+ (int)od->optArg.argInt);
+ def_val = int_val_buf;
break;
case OPARG_TYPE_MEMBERSHIP:
- snprintf( zVal, sizeof( zVal ), "%lu",
- (unsigned long)pOptDesc->optArg.argIntptr );
- pzDefault = zVal;
+ snprintf(int_val_buf, sizeof(int_val_buf), "%lu",
+ (unsigned long)od->optArg.argIntptr);
+ def_val = int_val_buf;
break;
case OPARG_TYPE_BOOLEAN:
- pzDefault = (pOptDesc->optArg.argBool) ? "true" : "false";
+ def_val = (od->optArg.argBool) ? TRUE_STR : FALSE_STR;
break;
default:
- if (pOptDesc->optArg.argString == NULL) {
- if (pzFmt == zSingleDef)
- pzFmt = zSingleNoDef;
- pzDefault = NULL;
+ if (od->optArg.argString == NULL) {
+ if (fmt == SGL_DEF_FMT)
+ fmt = SGL_NO_DEF_FMT;
+ def_val = NULL;
}
else
- pzDefault = pOptDesc->optArg.argString;
+ def_val = od->optArg.argString;
}
- printf( pzFmt, pOpts->pzPROGNAME, pOptDesc->pz_NAME, pzDefault );
+ printf(fmt, opts->pzPROGNAME, od->pz_NAME, def_val);
}
}
-
static void
-printOptionAction( tOptions* pOpts, tOptDesc* pOptDesc )
+emit_action(tOptions * opts, tOptDesc * od)
{
- if (pOptDesc->pOptProc == optionPrintVersion)
- printf( zTextExit, pOpts->pzPROGNAME, "VERSION" );
+ if (od->pOptProc == optionPrintVersion)
+ printf(ECHO_N_EXIT, opts->pzPROGNAME, VER_STR);
- else if (pOptDesc->pOptProc == optionPagedUsage)
- printf( zPagedUsageExit, pOpts->pzPROGNAME );
+ else if (od->pOptProc == optionPagedUsage)
+ printf(PAGE_USAGE_TEXT, opts->pzPROGNAME);
- else if (pOptDesc->pOptProc == optionLoadOpt) {
- printf( zCmdFmt, "echo 'Warning: Cannot load options files' >&2" );
- printf( zCmdFmt, "OPT_ARG_NEEDED=YES" );
+ else if (od->pOptProc == optionLoadOpt) {
+ printf(LVL3_CMD, NO_LOAD_WARN);
+ printf(LVL3_CMD, YES_NEED_OPT_ARG);
- } else if (pOptDesc->pz_NAME == NULL) {
+ } else if (od->pz_NAME == NULL) {
- if (pOptDesc->pOptProc == NULL) {
- printf( zCmdFmt, "echo 'Warning: Cannot save options files' "
- ">&2" );
- printf( zCmdFmt, "OPT_ARG_NEEDED=OK" );
+ if (od->pOptProc == NULL) {
+ printf(LVL3_CMD, NO_SAVE_OPTS);
+ printf(LVL3_CMD, OK_NEED_OPT_ARG);
} else
- printf( zTextExit, pOpts->pzPROGNAME, "LONGUSAGE" );
+ printf(ECHO_N_EXIT, opts->pzPROGNAME, LONG_USE_STR);
} else {
- if (pOptDesc->optMaxCt == 1)
- printf( zSingleArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+ if (od->optMaxCt == 1)
+ printf(SGL_ARG_FMT, opts->pzPROGNAME, od->pz_NAME);
else {
- if ((unsigned)pOptDesc->optMaxCt < NOLIMIT)
- printf( zCountTest, pOpts->pzPROGNAME,
- pOptDesc->pz_NAME, pOptDesc->optMaxCt );
+ if ((unsigned)od->optMaxCt < NOLIMIT)
+ printf(CHK_MAX_COUNT, opts->pzPROGNAME,
+ od->pz_NAME, od->optMaxCt);
- printf( zMultiArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+ printf(MULTI_ARG_FMT, opts->pzPROGNAME, od->pz_NAME);
}
/*
* Fix up the args.
*/
- if (OPTST_GET_ARGTYPE(pOptDesc->fOptState) == OPARG_TYPE_NONE) {
- printf( zCantArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+ 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 (pOptDesc->fOptState & OPTST_ARG_OPTIONAL) {
- printf( zMayArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+ } else if (od->fOptState & OPTST_ARG_OPTIONAL) {
+ printf(SET_MULTI_ARG, opts->pzPROGNAME, od->pz_NAME);
+ printf(LVL3_CMD, OK_NEED_OPT_ARG);
} else {
- fputs( zMustArg, stdout );
+ printf(LVL3_CMD, YES_NEED_OPT_ARG);
}
}
- fputs( zOptionEndSelect, stdout );
+ fputs(zOptionEndSelect, stdout);
}
-
static void
-printOptionInaction( tOptions* pOpts, tOptDesc* pOptDesc )
+emit_inaction(tOptions * opts, tOptDesc * od)
{
- if (pOptDesc->pOptProc == optionLoadOpt) {
- printf( zCmdFmt, "echo 'Warning: Cannot suppress the loading of "
- "options files' >&2" );
+ if (od->pOptProc == optionLoadOpt) {
+ printf(LVL3_CMD, NO_SUPPRESS_LOAD);
- } else if (pOptDesc->optMaxCt == 1)
- printf( zNoSingleArg, pOpts->pzPROGNAME,
- pOptDesc->pz_NAME, pOptDesc->pz_DisablePfx );
+ } else if (od->optMaxCt == 1)
+ printf(NO_SGL_ARG_FMT, opts->pzPROGNAME,
+ od->pz_NAME, od->pz_DisablePfx);
else
- printf( zNoMultiArg, pOpts->pzPROGNAME,
- pOptDesc->pz_NAME, pOptDesc->pz_DisablePfx );
+ printf(NO_MULTI_ARG_FMT, opts->pzPROGNAME,
+ od->pz_NAME, od->pz_DisablePfx);
- printf( zCmdFmt, "OPT_ARG_NEEDED=NO" );
- fputs( zOptionEndSelect, stdout );
+ 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
-emitFlag( tOptions* pOpts )
+emit_flag(tOptions * opts)
{
- tOptDesc* pOptDesc = pOpts->pOptDesc;
- int optionCt = pOpts->optCt;
+ tOptDesc * od = opts->pOptDesc;
+ int opt_ct = opts->optCt;
- fputs( zOptionCase, stdout );
+ fputs(zOptionCase, stdout);
- for (;optionCt > 0; pOptDesc++, --optionCt) {
+ for (;opt_ct > 0; od++, --opt_ct) {
- if (SKIP_OPT(pOptDesc))
+ if (SKIP_OPT(od) || ! IS_GRAPHIC_CHAR(od->optValue))
continue;
- if (isprint( pOptDesc->optValue )) {
- printf( zOptionFlag, pOptDesc->optValue );
- printOptionAction( pOpts, pOptDesc );
- }
+ printf(zOptionFlag, od->optValue);
+ emit_action(opts, od);
}
- printf( zOptionUnknown, "flag", pOpts->pzPROGNAME );
+ printf(UNK_OPT_FMT, FLAG_STR, opts->pzPROGNAME);
}
-
-/*
- * Emit the match text for a long option
+/**
+ * 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
-emitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts )
+emit_match_expr(char const * name, tOptDesc * cod, tOptions * opts)
{
- tOptDesc* pOD = pOpts->pOptDesc;
- int oCt = pOpts->optCt;
- int min = 1;
- char zName[ 256 ];
- char* pz = zName;
-
- for (;;) {
- int matchCt = 0;
-
- /*
- * Omit the current option, Documentation opts and compiled out opts.
- */
- if ((pOD == pCurOpt) || SKIP_OPT(pOD)){
- if (--oCt <= 0)
- break;
- pOD++;
- 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( pOD->pz_Name[matchCt] )
- == toupper( pzMatchName[matchCt] ))
- matchCt++;
-
- if (matchCt > min)
- min = matchCt;
+ char name_bf[32];
+ unsigned int min_match_ct = 2;
+ unsigned int max_match_ct = strlen(name) - 1;
- /*
- * Check the disablement name, too.
- */
- if (pOD->pz_DisableName != NULL) {
- matchCt = 0;
- while ( toupper( pOD->pz_DisableName[matchCt] )
- == toupper( pzMatchName[matchCt] ))
- matchCt++;
- if (matchCt > min)
- min = matchCt;
+ 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 (UPPER(od->pz_Name[match_ct]) == UPPER(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;
}
- if (--oCt <= 0)
- break;
- pOD++;
}
/*
- * IF the 'min' is all or one short of the name length,
- * THEN the entire string must be matched.
+ * Don't bother emitting partial matches if there is only one possible
+ * partial match.
*/
- if ( (pzMatchName[min ] == NUL)
- || (pzMatchName[min+1] == NUL) )
- printf( zOptionFullName, pzMatchName );
+ if (min_match_ct < max_match_ct) {
+ char * pz = name_bf + min_match_ct;
+ int nm_ix = min_match_ct;
- else {
- int matchCt = 0;
- for (; matchCt <= min; matchCt++)
- *pz++ = pzMatchName[matchCt];
+ memcpy(name_bf, name, min_match_ct);
for (;;) {
*pz = NUL;
- printf( zOptionPartName, zName );
- *pz++ = pzMatchName[matchCt++];
- if (pzMatchName[matchCt] == NUL) {
+ printf(zOptionPartName, name_bf);
+ *pz++ = name[nm_ix++];
+ if (name[nm_ix] == NUL) {
*pz = NUL;
- printf( zOptionFullName, zName );
break;
}
}
}
-}
+leave:
+ printf(zOptionFullName, name);
+}
-/*
- * Emit GNU-standard long option handling code
+/**
+ * Emit GNU-standard long option handling code.
+ *
+ * @param[in] opts the program options
*/
static void
-emitLong( tOptions* pOpts )
+emit_long(tOptions * opts)
{
- tOptDesc* pOD = pOpts->pOptDesc;
- int ct = pOpts->optCt;
+ tOptDesc * od = opts->pOptDesc;
+ int ct = opts->optCt;
- fputs( zOptionCase, stdout );
+ fputs(zOptionCase, stdout);
/*
* do each option, ...
@@ -922,109 +724,134 @@ emitLong( tOptions* pOpts )
/*
* Documentation & compiled-out options
*/
- if (SKIP_OPT(pOD))
+ if (SKIP_OPT(od))
continue;
- emitMatchExpr( pOD->pz_Name, pOD, pOpts );
- printOptionAction( pOpts, pOD );
+ 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 (pOD->pz_DisableName != NULL) {
- emitMatchExpr( pOD->pz_DisableName, pOD, pOpts );
- printOptionInaction( pOpts, pOD );
+ if (od->pz_DisableName != NULL) {
+ emit_match_expr(od->pz_DisableName, od, opts);
+ emit_inaction(opts, od);
}
- } while (pOD++, --ct > 0);
+ } while (od++, --ct > 0);
- printf( zOptionUnknown, "option", pOpts->pzPROGNAME );
+ printf(UNK_OPT_FMT, OPTION_STR, opts->pzPROGNAME);
}
-
-static void
-openOutput( char const* pzFile )
+/**
+ * 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)
{
- FILE* fp;
- char* pzData = NULL;
+ /*
+ * 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;
- do {
- char* pzScan;
- size_t sizeLeft;
+ if (fp == NULL)
+ return NULL;
- /*
- * IF we cannot stat the file,
- * THEN assume we are creating a new file.
- * Skip the loading of the old data.
- */
- if (stat( pzFile, &stbf ) != 0)
+ /*
+ * 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(VOIDP(scan), 1, (size_t)stbf.st_size, fp);
+ if (inct == 0)
break;
- /*
- * The file must be a regular file
- */
- if (! S_ISREG( stbf.st_mode )) {
- fprintf( stderr, zNotFile, pzFile );
- exit( EXIT_FAILURE );
- }
+ stbf.st_size -= (ssize_t)inct;
- pzData = AGALOC(stbf.st_size + 1, "file data");
- fp = fopen( pzFile, "r" FOPEN_BINARY_FLAG );
+ if (stbf.st_size == 0)
+ break;
- sizeLeft = (unsigned)stbf.st_size;
- pzScan = pzData;
+ scan += inct;
+ }
- /*
- * Read in all the data as fast as our OS will let us.
- */
- for (;;) {
- int inct = fread( (void*)pzScan, (size_t)1, sizeLeft, fp);
- if (inct == 0)
- break;
+ *scan = NUL;
+ fclose(fp);
- pzScan += inct;
- sizeLeft -= inct;
+ return text;
+}
- if (sizeLeft == 0)
- break;
- }
+/**
+ * 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)
+{
- /*
- * NUL-terminate the leader and look for the trailer
- */
- *pzScan = '\0';
- fclose( fp );
- pzScan = strstr( pzData, zStartMarker );
- if (pzScan == NULL) {
- pzTrailer = pzData;
+ 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;
}
- *(pzScan++) = NUL;
- pzScan = strstr( pzScan, zTrailerMarker );
- if (pzScan == NULL) {
- pzTrailer = pzData;
+ *(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
+ * Check to see if the data contains our marker.
+ * If it does, then we will skip over it
*/
- pzTrailer = pzScan + sizeof( zTrailerMarker ) - 1;
- pzLeader = pzData;
- } while (AG_FALSE);
+ script_trailer = scn + END_MARK_LEN;
+ script_leader = txt;
+ } while (false);
- freopen( pzFile, "w" FOPEN_BINARY_FLAG, stdout );
+ 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* + pOpts + program options descriptor +
- * arg: + int + exitCode + usage text type to produce +
+ * 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
@@ -1034,19 +861,21 @@ openOutput( char const* pzFile )
* and create shell script variables containing the two types of text.
=*/
void
-genshelloptUsage( tOptions* pOpts, int exitCode )
+genshelloptUsage(tOptions * opts, int exit_cd)
{
-#if defined(__windows__) && !defined(__CYGWIN__)
- optionUsage( pOpts, exitCode );
+#if ! defined(HAVE_WORKING_FORK)
+ optionUsage(opts, exit_cd);
#else
/*
* IF not EXIT_SUCCESS,
* THEN emit the short form of usage.
*/
- if (exitCode != EXIT_SUCCESS)
- optionUsage( pOpts, exitCode );
- fflush( stderr );
- fflush( stdout );
+ 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;
@@ -1055,20 +884,19 @@ genshelloptUsage( tOptions* pOpts, int exitCode )
*/
switch (fork()) {
case -1:
- optionUsage( pOpts, EXIT_FAILURE );
- /*NOTREACHED*/
- _exit( EXIT_FAILURE );
+ optionUsage(opts, EXIT_FAILURE);
+ /* NOTREACHED */
case 0:
pagerState = PAGER_STATE_CHILD;
- optionUsage( pOpts, EXIT_SUCCESS );
- /*NOTREACHED*/
- _exit( EXIT_FAILURE );
+ optionUsage(opts, EXIT_SUCCESS);
+ /* NOTREACHED */
+ _exit(EXIT_FAILURE);
default:
{
int sts;
- wait( &sts );
+ wait(&sts);
}
}
@@ -1077,11 +905,12 @@ genshelloptUsage( tOptions* pOpts, int exitCode )
* gets it from the command line
*/
{
- char* pz;
- AGDUPSTR( pz, pShellParseOptions->pzPROGNAME, "program name" );
- pShellParseOptions->pzProgName = pz;
+ char * pz;
+ char ** pp = VOIDP(&(optionParseShellOptions->pzProgName));
+ AGDUPSTR(pz, optionParseShellOptions->pzPROGNAME, "prog name");
+ *pp = pz;
while (*pz != NUL) {
- *pz = tolower( *pz );
+ *pz = (char)LOWER(*pz);
pz++;
}
}
@@ -1089,8 +918,8 @@ genshelloptUsage( tOptions* pOpts, int exitCode )
/*
* Separate the makeshell usage from the client usage
*/
- fprintf( option_usage_fp, zGenshell, pShellParseOptions->pzProgName );
- fflush( option_usage_fp );
+ fprintf(option_usage_fp, zGenshell, optionParseShellOptions->pzProgName);
+ fflush(option_usage_fp);
/*
* Now, print the client usage.
@@ -1100,20 +929,25 @@ genshelloptUsage( tOptions* pOpts, int exitCode )
pagerState = PAGER_STATE_CHILD;
/*FALLTHROUGH*/
case -1:
- optionUsage( pShellParseOptions, EXIT_FAILURE );
+ optionUsage(optionParseShellOptions, EXIT_FAILURE);
default:
{
int sts;
- wait( &sts );
+ wait(&sts);
}
}
- exit( EXIT_SUCCESS );
+ 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"
OpenPOWER on IntegriCloud