📄 makeshell.c
字号:
/* * $Id: makeshell.c,v 4.20 2007/02/04 17:44:12 bkorb Exp $ * Time-stamp: "2007-01-27 06:05:45 bkorb" * * 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. */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 * * 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";/* * * * * * * * * * * * * * * * * * CASE SELECTORS * * 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";/* * * * * * * * * * * * * * * * * * 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";/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * OPTION SELECTION */tSCC zOptionCase[] =" case \"${OPT_CODE}\" in\n";tSCC zOptionPartName[] =" '%s' | \\\n";tSCC zOptionFullName[] =" '%s' )\n";tSCC zOptionFlag[] =" '%c' )\n";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";/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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;/* = = = START-STATIC-FORWARD = = = *//* static forward declarations maintained by :mkfwd */static voidtextToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD );static voidemitUsage( tOptions* pOpts );static voidemitSetup( tOptions* pOpts );static voidprintOptionAction( tOptions* pOpts, tOptDesc* pOptDesc );static voidprintOptionInaction( tOptions* pOpts, tOptDesc* pOptDesc );static voidemitFlag( tOptions* pOpts );static voidemitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts );static voidemitLong( tOptions* pOpts );static voidopenOutput( char const* pzFile );/* = = = END-STATIC-FORWARD = = = *//*=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.=*/voidoptionParseShell( tOptions* pOpts ){ /* * 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 ); else if (! ENABLED_OPT( SHELL )) pzShell = NULL; else if ((pzShell = getenv( "SHELL" )), pzShell == NULL) pzShell = "/bin/sh"; /* * Check for a specified output file */ if (HAVE_OPT( SCRIPT )) openOutput( OPT_ARG( SCRIPT )); emitUsage( pOpts ); emitSetup( pOpts ); /* * There are four modes of option processing. */ switch (pOpts->fOptSet & (OPTPROC_LONGOPT|OPTPROC_SHORTOPT)) { case OPTPROC_LONGOPT: fputs( zLoopCase, stdout ); fputs( zLongSelection, stdout ); fputs( zLongOptInit, stdout ); emitLong( pOpts ); printf( zLongOptArg, pOpts->pzPROGNAME ); fputs( zEndSelection, stdout ); fputs( zNoSelection, stdout ); break; case 0: fputs( zLoopOnly, stdout ); fputs( zLongOptInit, stdout ); emitLong( pOpts ); printf( zLongOptArg, pOpts->pzPROGNAME ); break; case OPTPROC_SHORTOPT: fputs( zLoopCase, stdout ); fputs( zFlagSelection, stdout ); fputs( zFlagOptInit, stdout ); emitFlag( pOpts ); printf( zFlagOptArg, pOpts->pzPROGNAME ); fputs( zEndSelection, stdout ); fputs( zNoSelection, stdout ); break; case OPTPROC_LONGOPT|OPTPROC_SHORTOPT: fputs( zLoopCase, stdout ); fputs( zLongSelection, stdout ); fputs( zLongOptInit, stdout ); emitLong( pOpts ); printf( zLongOptArg, pOpts->pzPROGNAME ); fputs( zEndSelection, stdout ); fputs( zFlagSelection, stdout ); fputs( zFlagOptInit, stdout ); emitFlag( pOpts ); printf( zFlagOptArg, pOpts->pzPROGNAME ); fputs( zEndSelection, stdout ); fputs( zNoSelection, 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 ); fflush( stdout ); fchmod( STDOUT_FILENO, 0755 ); fclose( stdout );}static voidtextToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD ){# define _TT_(n) tSCC z ## n [] = #n; TEXTTO_TABLE# undef _TT_# define _TT_(n) z ## n , static char const* apzTTNames[] = { TEXTTO_TABLE };# undef _TT_#if defined(__windows__) && !defined(__CYGWIN__) printf( "%1$s_%2$s_TEXT='no %2$s text'\n", pOpts->pzPROGNAME, apzTTNames[ whichVar ]);#else int nlHoldCt = 0; int pipeFd[2]; FILE* fp; printf( "%s_%s_TEXT='", pOpts->pzPROGNAME, apzTTNames[ whichVar ]); fflush( stdout ); if (pipe( pipeFd ) != 0) { fprintf( stderr, zBadPipe, errno, strerror( errno )); exit( EXIT_FAILURE ); } switch (fork()) { case -1: fprintf( stderr, zForkFail, errno, strerror(errno), pOpts->pzProgName); exit( EXIT_FAILURE ); break; case 0: dup2( pipeFd[1], STDERR_FILENO ); dup2( pipeFd[1], STDOUT_FILENO ); close( pipeFd[0] ); switch (whichVar) { case TT_LONGUSAGE: (*(pOpts->pUsageProc))( pOpts, EXIT_SUCCESS ); /* NOTREACHED */ exit( EXIT_FAILURE ); case TT_USAGE: (*(pOpts->pUsageProc))( pOpts, EXIT_FAILURE ); /* NOTREACHED */ exit( EXIT_FAILURE ); case TT_VERSION: if (pOD->fOptState & OPTST_ALLOC_ARG) { AGFREE(pOD->optArg.argString); pOD->fOptState &= ~OPTST_ALLOC_ARG; } pOD->optArg.argString = "c"; optionPrintVersion( pOpts, pOD ); /* NOTREACHED */ default: exit( EXIT_FAILURE ); } default: close( pipeFd[1] ); fp = fdopen( pipeFd[0], "r" FOPEN_BINARY_FLAG );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -