5 * Id: makeshell.c,v 4.20 2007/02/04 17:44:12 bkorb Exp
6 * Time-stamp: "2007-01-27 06:05:45 bkorb"
8 * This module will interpret the options set in the tOptions
9 * structure and create a Bourne shell script capable of parsing them.
13 * Automated Options copyright 1992-2007 Bruce Korb
15 * Automated Options is free software.
16 * You may redistribute it and/or modify it under the terms of the
17 * GNU General Public License, as published by the Free Software
18 * Foundation; either version 2, or (at your option) any later version.
20 * Automated Options is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with Automated Options. See the file "COPYING". If not,
27 * write to: The Free Software Foundation, Inc.,
28 * 51 Franklin Street, Fifth Floor,
29 * Boston, MA 02110-1301, USA.
31 * As a special exception, Bruce Korb gives permission for additional
32 * uses of the text contained in his release of AutoOpts.
34 * The exception is that, if you link the AutoOpts library with other
35 * files to produce an executable, this does not by itself cause the
36 * resulting executable to be covered by the GNU General Public License.
37 * Your use of that executable is in no way restricted on account of
38 * linking the AutoOpts library code into it.
40 * This exception does not however invalidate any other reasons why
41 * the executable file might be covered by the GNU General Public License.
43 * This exception applies only to the code released by Bruce Korb under
44 * the name AutoOpts. If you copy code from other sources under the
45 * General Public License into a copy of AutoOpts, as the General Public
46 * License permits, the exception does not apply to the code that you add
47 * in this way. To avoid misleading anyone as to the status of such
48 * modified files, you must delete this exception notice from them.
50 * If you write modifications of your own for AutoOpts, it is your choice
51 * whether to permit this exception to apply to your modifications.
52 * If you do not wish that, delete this exception notice.
55 tOptions
* pShellParseOptions
= NULL
;
57 /* * * * * * * * * * * * * * * * * * * * *
59 * Setup Format Strings
62 "# # # # # # # # # # -- do not modify this marker --\n#\n"
63 "# DO NOT EDIT THIS SECTION";
67 "# From here to the next `-- do not modify this marker --',\n"
68 "# the text has been generated %s\n";
71 "# From the %s option definitions\n#\n";
73 tSCC zMultiDef
[] = "\n"
74 "if test -z \"${%1$s_%2$s}\"\n"
79 " %1$s_%2$s_1=\"${%1$s_%2$s}\"\n"
81 "export %1$s_%2$s_CT";
83 tSCC zSingleDef
[] = "\n"
84 "%1$s_%2$s=\"${%1$s_%2$s-'%3$s'}\"\n"
85 "%1$s_%2$s_set=false\n"
88 tSCC zSingleNoDef
[] = "\n"
89 "%1$s_%2$s=\"${%1$s_%2$s}\"\n"
90 "%1$s_%2$s_set=false\n"
93 /* * * * * * * * * * * * * * * * * * * * *
97 * The loop may run in either of two modes:
98 * all options are named options (loop only)
99 * regular, marked option processing.
101 tSCC zLoopCase
[] = "\n"
104 "while ${OPT_PROCESS} && [ $# -gt 0 ]\ndo\n"
106 " OPT_ARG_VAL=''\n\n"
108 * 'OPT_ARG' may or may not match the current $1
110 " case \"${OPT_ARG}\" in\n"
112 " OPT_PROCESS=false\n"
116 tSCC zLoopOnly
[] = "\n"
118 "while [ $# -gt 0 ]\ndo\n"
120 " OPT_ARG_VAL=''\n\n"
121 " OPT_ARG=\"${1}\"\n";
123 /* * * * * * * * * * * * * * * *
127 * If the loop runs as a regular option loop,
128 * then we must have selectors for each acceptable option
129 * type (long option, flag character and non-option)
131 tSCC zLongSelection
[] =
134 tSCC zFlagSelection
[] =
137 tSCC zEndSelection
[] =
140 tSCC zNoSelection
[] =
142 " OPT_PROCESS=false\n"
146 /* * * * * * * * * * * * * * * *
151 " if [ -n \"${OPT_ARG_VAL}\" ]\n"
153 " eval %1$s_${OPT_NAME}${OPT_ELEMENT}=\"'${OPT_ARG_VAL}'\"\n"
154 " export %1$s_${OPT_NAME}${OPT_ELEMENT}\n"
157 "unset OPT_PROCESS || :\n"
158 "unset OPT_ELEMENT || :\n"
159 "unset OPT_ARG || :\n"
160 "unset OPT_ARG_NEEDED || :\n"
161 "unset OPT_NAME || :\n"
162 "unset OPT_CODE || :\n"
163 "unset OPT_ARG_VAL || :\n%2$s";
165 tSCC zTrailerMarker
[] = "\n"
166 "# # # # # # # # # #\n#\n"
167 "# END OF AUTOMATED OPTION PROCESSING\n"
168 "#\n# # # # # # # # # # -- do not modify this marker --\n";
170 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
175 " case \"${OPT_CODE}\" in\n";
177 tSCC zOptionPartName
[] =
180 tSCC zOptionFullName
[] =
186 tSCC zOptionEndSelect
[] =
189 tSCC zOptionUnknown
[] =
191 " echo Unknown %s: \"${OPT_CODE}\" >&2\n"
192 " echo \"$%s_USAGE_TEXT\"\n"
197 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
201 * Formats for emitting the text for handling particular options
204 " echo \"$%s_%s_TEXT\"\n"
207 tSCC zPagedUsageExit
[] =
208 " echo \"$%s_LONGUSAGE_TEXT\" | ${PAGER-more}\n"
215 " if [ $%1$s_%2$s_CT -ge %3$d ] ; then\n"
216 " echo Error: more than %3$d %2$s options >&2\n"
217 " echo \"$%1$s_USAGE_TEXT\"\n"
221 " %1$s_%2$s_CT=`expr ${%1$s_%2$s_CT} + 1`\n"
222 " OPT_ELEMENT=\"_${%1$s_%2$s_CT}\"\n"
223 " OPT_NAME='%2$s'\n";
226 " if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n"
227 " echo Error: duplicate %2$s option >&2\n"
228 " echo \"$%1$s_USAGE_TEXT\"\n"
230 " %1$s_%2$s_set=true\n"
231 " OPT_NAME='%2$s'\n";
236 " %1$s_%2$s='%3$s'\n"
237 " export %1$s_%2$s\n"
238 " OPT_NAME='%2$s'\n";
240 tSCC zNoSingleArg
[] =
241 " if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n"
242 " echo Error: duplicate %2$s option >&2\n"
243 " echo \"$%1$s_USAGE_TEXT\"\n"
245 " %1$s_%2$s_set=true\n"
246 " %1$s_%2$s='%3$s'\n"
247 " export %1$s_%2$s\n"
248 " OPT_NAME='%2$s'\n";
251 " eval %1$s_%2$s${OPT_ELEMENT}=true\n"
252 " export %1$s_%2$s${OPT_ELEMENT}\n"
253 " OPT_ARG_NEEDED=OK\n";
256 " OPT_ARG_NEEDED=YES\n";
259 " eval %1$s_%2$s${OPT_ELEMENT}=true\n"
260 " export %1$s_%2$s${OPT_ELEMENT}\n"
261 " OPT_ARG_NEEDED=NO\n";
263 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
265 * LONG OPTION PROCESSING
267 * Formats for emitting the text for handling long option types
269 tSCC zLongOptInit
[] =
270 " OPT_CODE=`echo \"X${OPT_ARG}\"|sed 's/^X-*//'`\n"
272 " OPT_ARG=\"$1\"\n\n"
273 " case \"${OPT_CODE}\" in *=* )\n"
274 " OPT_ARG_VAL=`echo \"${OPT_CODE}\"|sed 's/^[^=]*=//'`\n"
275 " OPT_CODE=`echo \"${OPT_CODE}\"|sed 's/=.*$//'` ;; esac\n\n";
278 " case \"${OPT_ARG_NEEDED}\" in\n"
283 " if [ -z \"${OPT_ARG_VAL}\" ]\n"
287 " echo No argument provided for ${OPT_NAME} option >&2\n"
288 " echo \"$%s_USAGE_TEXT\"\n"
291 " OPT_ARG_VAL=\"${OPT_ARG}\"\n"
297 " if [ -z \"${OPT_ARG_VAL}\" ] && [ $# -gt 0 ]\n"
299 " case \"${OPT_ARG}\" in -* ) ;; * )\n"
300 " OPT_ARG_VAL=\"${OPT_ARG}\"\n"
302 " OPT_ARG=\"$1\" ;; esac\n"
307 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
309 * FLAG OPTION PROCESSING
311 * Formats for emitting the text for handling flag option types
313 tSCC zFlagOptInit
[] =
314 " OPT_CODE=`echo \"X${OPT_ARG}\" | sed 's/X-\\(.\\).*/\\1/'`\n"
315 " OPT_ARG=` echo \"X${OPT_ARG}\" | sed 's/X-.//'`\n\n";
318 " case \"${OPT_ARG_NEEDED}\" in\n"
320 " if [ -n \"${OPT_ARG}\" ]\n"
322 " OPT_ARG=-\"${OPT_ARG}\"\n"
329 " if [ -n \"${OPT_ARG}\" ]\n"
331 " OPT_ARG_VAL=\"${OPT_ARG}\"\n\n"
335 " echo No argument provided for ${OPT_NAME} option >&2\n"
336 " echo \"$%s_USAGE_TEXT\"\n"
340 " OPT_ARG_VAL=\"$1\"\n"
346 " if [ -n \"${OPT_ARG}\" ]\n"
348 " OPT_ARG_VAL=\"${OPT_ARG}\"\n"
350 " OPT_ARG=\"$1\"\n\n"
355 " case \"$1\" in -* ) ;; * )\n"
356 " OPT_ARG_VAL=\"$1\"\n"
364 tSCC
* pzShell
= NULL
;
365 static char* pzLeader
= NULL
;
366 static char* pzTrailer
= NULL
;
368 /* = = = START-STATIC-FORWARD = = = */
369 /* static forward declarations maintained by :mkfwd */
371 textToVariable( tOptions
* pOpts
, teTextTo whichVar
, tOptDesc
* pOD
);
374 emitUsage( tOptions
* pOpts
);
377 emitSetup( tOptions
* pOpts
);
380 printOptionAction( tOptions
* pOpts
, tOptDesc
* pOptDesc
);
383 printOptionInaction( tOptions
* pOpts
, tOptDesc
* pOptDesc
);
386 emitFlag( tOptions
* pOpts
);
389 emitMatchExpr( tCC
* pzMatchName
, tOptDesc
* pCurOpt
, tOptions
* pOpts
);
392 emitLong( tOptions
* pOpts
);
395 openOutput( char const* pzFile
);
396 /* = = = END-STATIC-FORWARD = = = */
398 /*=export_func optionParseShell
401 * what: Decipher a boolean value
402 * arg: + tOptions* + pOpts + program options descriptor +
405 * Emit a shell script that will parse the command line options.
408 optionParseShell( tOptions
* pOpts
)
411 * Check for our SHELL option now.
412 * IF the output file contains the "#!" magic marker,
413 * it will override anything we do here.
415 if (HAVE_OPT( SHELL
))
416 pzShell
= OPT_ARG( SHELL
);
418 else if (! ENABLED_OPT( SHELL
))
421 else if ((pzShell
= getenv( "SHELL" )),
427 * Check for a specified output file
429 if (HAVE_OPT( SCRIPT
))
430 openOutput( OPT_ARG( SCRIPT
));
436 * There are four modes of option processing.
438 switch (pOpts
->fOptSet
& (OPTPROC_LONGOPT
|OPTPROC_SHORTOPT
)) {
439 case OPTPROC_LONGOPT
:
440 fputs( zLoopCase
, stdout
);
442 fputs( zLongSelection
, stdout
);
443 fputs( zLongOptInit
, stdout
);
445 printf( zLongOptArg
, pOpts
->pzPROGNAME
);
446 fputs( zEndSelection
, stdout
);
448 fputs( zNoSelection
, stdout
);
452 fputs( zLoopOnly
, stdout
);
453 fputs( zLongOptInit
, stdout
);
455 printf( zLongOptArg
, pOpts
->pzPROGNAME
);
458 case OPTPROC_SHORTOPT
:
459 fputs( zLoopCase
, stdout
);
461 fputs( zFlagSelection
, stdout
);
462 fputs( zFlagOptInit
, stdout
);
464 printf( zFlagOptArg
, pOpts
->pzPROGNAME
);
465 fputs( zEndSelection
, stdout
);
467 fputs( zNoSelection
, stdout
);
470 case OPTPROC_LONGOPT
|OPTPROC_SHORTOPT
:
471 fputs( zLoopCase
, stdout
);
473 fputs( zLongSelection
, stdout
);
474 fputs( zLongOptInit
, stdout
);
476 printf( zLongOptArg
, pOpts
->pzPROGNAME
);
477 fputs( zEndSelection
, stdout
);
479 fputs( zFlagSelection
, stdout
);
480 fputs( zFlagOptInit
, stdout
);
482 printf( zFlagOptArg
, pOpts
->pzPROGNAME
);
483 fputs( zEndSelection
, stdout
);
485 fputs( zNoSelection
, stdout
);
489 printf( zLoopEnd
, pOpts
->pzPROGNAME
, zTrailerMarker
);
490 if ((pzTrailer
!= NULL
) && (*pzTrailer
!= '\0'))
491 fputs( pzTrailer
, stdout
);
492 else if (ENABLED_OPT( SHELL
))
493 printf( "\nenv | grep '^%s_'\n", pOpts
->pzPROGNAME
);
496 fchmod( STDOUT_FILENO
, 0755 );
502 textToVariable( tOptions
* pOpts
, teTextTo whichVar
, tOptDesc
* pOD
)
504 # define _TT_(n) tSCC z ## n [] = #n;
507 # define _TT_(n) z ## n ,
508 static char const* apzTTNames
[] = { TEXTTO_TABLE
};
511 #if defined(__windows__) && !defined(__CYGWIN__)
512 printf( "%1$s_%2$s_TEXT='no %2$s text'\n",
513 pOpts
->pzPROGNAME
, apzTTNames
[ whichVar
]);
519 printf( "%s_%s_TEXT='", pOpts
->pzPROGNAME
, apzTTNames
[ whichVar
]);
522 if (pipe( pipeFd
) != 0) {
523 fprintf( stderr
, zBadPipe
, errno
, strerror( errno
));
524 exit( EXIT_FAILURE
);
529 fprintf( stderr
, zForkFail
, errno
, strerror(errno
), pOpts
->pzProgName
);
530 exit( EXIT_FAILURE
);
534 dup2( pipeFd
[1], STDERR_FILENO
);
535 dup2( pipeFd
[1], STDOUT_FILENO
);
540 (*(pOpts
->pUsageProc
))( pOpts
, EXIT_SUCCESS
);
542 exit( EXIT_FAILURE
);
545 (*(pOpts
->pUsageProc
))( pOpts
, EXIT_FAILURE
);
547 exit( EXIT_FAILURE
);
550 if (pOD
->fOptState
& OPTST_ALLOC_ARG
) {
551 AGFREE(pOD
->optArg
.argString
);
552 pOD
->fOptState
&= ~OPTST_ALLOC_ARG
;
554 pOD
->optArg
.argString
= "c";
555 optionPrintVersion( pOpts
, pOD
);
559 exit( EXIT_FAILURE
);
564 fp
= fdopen( pipeFd
[0], "r" FOPEN_BINARY_FLAG
);
568 int ch
= fgetc( fp
);
576 while (nlHoldCt
> 0) {
577 fputc( '\n', stdout
);
580 fputs( "'\\''", stdout
);
587 while (nlHoldCt
> 0) {
588 fputc( '\n', stdout
);
596 fputs( "'\n\n", stdout
);
603 emitUsage( tOptions
* pOpts
)
605 char zTimeBuf
[ AO_NAME_SIZE
];
608 * First, switch stdout to the output file name.
609 * Then, change the program name to the one defined
610 * by the definitions (rather than the current
611 * executable name). Down case the upper cased name.
613 if (pzLeader
!= NULL
)
614 fputs( pzLeader
, stdout
);
617 tSCC zStdout
[] = "stdout";
621 time_t curTime
= time( NULL
);
622 struct tm
* pTime
= localtime( &curTime
);
623 strftime(zTimeBuf
, AO_NAME_SIZE
, "%A %B %e, %Y at %r %Z", pTime
);
626 if (HAVE_OPT( SCRIPT
))
627 pzOutName
= OPT_ARG( SCRIPT
);
628 else pzOutName
= zStdout
;
630 if ((pzLeader
== NULL
) && (pzShell
!= NULL
))
631 printf( "#! %s\n", pzShell
);
633 printf( zPreamble
, zStartMarker
, pzOutName
, zTimeBuf
);
637 * Get a copy of the original program name in lower case
640 char* pzPN
= zTimeBuf
;
641 tCC
* pz
= pOpts
->pzPROGNAME
;
643 if ((*pzPN
++ = tolower( *pz
++ )) == '\0')
648 printf( zEndPreamble
, pOpts
->pzPROGNAME
);
650 pOpts
->pzProgPath
= pOpts
->pzProgName
= zTimeBuf
;
651 textToVariable( pOpts
, TT_LONGUSAGE
, NULL
);
652 textToVariable( pOpts
, TT_USAGE
, NULL
);
655 tOptDesc
* pOptDesc
= pOpts
->pOptDesc
;
656 int optionCt
= pOpts
->optCt
;
659 if (pOptDesc
->pOptProc
== optionPrintVersion
) {
660 textToVariable( pOpts
, TT_VERSION
, pOptDesc
);
673 emitSetup( tOptions
* pOpts
)
675 tOptDesc
* pOptDesc
= pOpts
->pOptDesc
;
676 int optionCt
= pOpts
->presetOptCt
;
678 char const* pzDefault
;
680 for (;optionCt
> 0; pOptDesc
++, --optionCt
) {
684 * Options that are either usage documentation or are compiled out
685 * are not to be processed.
687 if (SKIP_OPT(pOptDesc
) || (pOptDesc
->pz_NAME
== NULL
))
690 if (pOptDesc
->optMaxCt
> 1)
692 else pzFmt
= zSingleDef
;
695 * IF this is an enumeration/bitmask option, then convert the value
696 * to a string before printing the default value.
698 switch (OPTST_GET_ARGTYPE(pOptDesc
->fOptState
)) {
699 case OPARG_TYPE_ENUMERATION
:
700 (*(pOptDesc
->pOptProc
))( (tOptions
*)2UL, pOptDesc
);
701 pzDefault
= pOptDesc
->optArg
.argString
;
705 * Numeric and membership bit options are just printed as a number.
707 case OPARG_TYPE_NUMERIC
:
708 snprintf( zVal
, sizeof( zVal
), "%d",
709 (int)pOptDesc
->optArg
.argInt
);
713 case OPARG_TYPE_MEMBERSHIP
:
714 snprintf( zVal
, sizeof( zVal
), "%lu",
715 (unsigned long)pOptDesc
->optArg
.argIntptr
);
719 case OPARG_TYPE_BOOLEAN
:
720 pzDefault
= (pOptDesc
->optArg
.argBool
) ? "true" : "false";
724 if (pOptDesc
->optArg
.argString
== NULL
) {
725 if (pzFmt
== zSingleDef
)
726 pzFmt
= zSingleNoDef
;
730 pzDefault
= pOptDesc
->optArg
.argString
;
733 printf( pzFmt
, pOpts
->pzPROGNAME
, pOptDesc
->pz_NAME
, pzDefault
);
739 printOptionAction( tOptions
* pOpts
, tOptDesc
* pOptDesc
)
741 if (pOptDesc
->pOptProc
== optionPrintVersion
)
742 printf( zTextExit
, pOpts
->pzPROGNAME
, "VERSION" );
744 else if (pOptDesc
->pOptProc
== optionPagedUsage
)
745 printf( zPagedUsageExit
, pOpts
->pzPROGNAME
);
747 else if (pOptDesc
->pOptProc
== optionLoadOpt
) {
748 printf( zCmdFmt
, "echo 'Warning: Cannot load options files' >&2" );
749 printf( zCmdFmt
, "OPT_ARG_NEEDED=YES" );
751 } else if (pOptDesc
->pz_NAME
== NULL
) {
753 if (pOptDesc
->pOptProc
== NULL
) {
754 printf( zCmdFmt
, "echo 'Warning: Cannot save options files' "
756 printf( zCmdFmt
, "OPT_ARG_NEEDED=OK" );
758 printf( zTextExit
, pOpts
->pzPROGNAME
, "LONGUSAGE" );
761 if (pOptDesc
->optMaxCt
== 1)
762 printf( zSingleArg
, pOpts
->pzPROGNAME
, pOptDesc
->pz_NAME
);
764 if ((unsigned)pOptDesc
->optMaxCt
< NOLIMIT
)
765 printf( zCountTest
, pOpts
->pzPROGNAME
,
766 pOptDesc
->pz_NAME
, pOptDesc
->optMaxCt
);
768 printf( zMultiArg
, pOpts
->pzPROGNAME
, pOptDesc
->pz_NAME
);
774 if (OPTST_GET_ARGTYPE(pOptDesc
->fOptState
) == OPARG_TYPE_NONE
) {
775 printf( zCantArg
, pOpts
->pzPROGNAME
, pOptDesc
->pz_NAME
);
777 } else if (pOptDesc
->fOptState
& OPTST_ARG_OPTIONAL
) {
778 printf( zMayArg
, pOpts
->pzPROGNAME
, pOptDesc
->pz_NAME
);
781 fputs( zMustArg
, stdout
);
784 fputs( zOptionEndSelect
, stdout
);
789 printOptionInaction( tOptions
* pOpts
, tOptDesc
* pOptDesc
)
791 if (pOptDesc
->pOptProc
== optionLoadOpt
) {
792 printf( zCmdFmt
, "echo 'Warning: Cannot suppress the loading of "
793 "options files' >&2" );
795 } else if (pOptDesc
->optMaxCt
== 1)
796 printf( zNoSingleArg
, pOpts
->pzPROGNAME
,
797 pOptDesc
->pz_NAME
, pOptDesc
->pz_DisablePfx
);
799 printf( zNoMultiArg
, pOpts
->pzPROGNAME
,
800 pOptDesc
->pz_NAME
, pOptDesc
->pz_DisablePfx
);
802 printf( zCmdFmt
, "OPT_ARG_NEEDED=NO" );
803 fputs( zOptionEndSelect
, stdout
);
808 emitFlag( tOptions
* pOpts
)
810 tOptDesc
* pOptDesc
= pOpts
->pOptDesc
;
811 int optionCt
= pOpts
->optCt
;
813 fputs( zOptionCase
, stdout
);
815 for (;optionCt
> 0; pOptDesc
++, --optionCt
) {
817 if (SKIP_OPT(pOptDesc
))
820 if (isprint( pOptDesc
->optValue
)) {
821 printf( zOptionFlag
, pOptDesc
->optValue
);
822 printOptionAction( pOpts
, pOptDesc
);
825 printf( zOptionUnknown
, "flag", pOpts
->pzPROGNAME
);
830 * Emit the match text for a long option
833 emitMatchExpr( tCC
* pzMatchName
, tOptDesc
* pCurOpt
, tOptions
* pOpts
)
835 tOptDesc
* pOD
= pOpts
->pOptDesc
;
836 int oCt
= pOpts
->optCt
;
845 * Omit the current option, Documentation opts and compiled out opts.
847 if ((pOD
== pCurOpt
) || SKIP_OPT(pOD
)){
855 * Check each character of the name case insensitively.
856 * They must not be the same. They cannot be, because it would
857 * not compile correctly if they were.
859 while ( toupper( pOD
->pz_Name
[matchCt
] )
860 == toupper( pzMatchName
[matchCt
] ))
867 * Check the disablement name, too.
869 if (pOD
->pz_DisableName
!= NULL
) {
871 while ( toupper( pOD
->pz_DisableName
[matchCt
] )
872 == toupper( pzMatchName
[matchCt
] ))
883 * IF the 'min' is all or one short of the name length,
884 * THEN the entire string must be matched.
886 if ( (pzMatchName
[min
] == NUL
)
887 || (pzMatchName
[min
+1] == NUL
) )
888 printf( zOptionFullName
, pzMatchName
);
892 for (; matchCt
<= min
; matchCt
++)
893 *pz
++ = pzMatchName
[matchCt
];
897 printf( zOptionPartName
, zName
);
898 *pz
++ = pzMatchName
[matchCt
++];
899 if (pzMatchName
[matchCt
] == NUL
) {
901 printf( zOptionFullName
, zName
);
910 * Emit GNU-standard long option handling code
913 emitLong( tOptions
* pOpts
)
915 tOptDesc
* pOD
= pOpts
->pOptDesc
;
916 int ct
= pOpts
->optCt
;
918 fputs( zOptionCase
, stdout
);
921 * do each option, ...
925 * Documentation & compiled-out options
930 emitMatchExpr( pOD
->pz_Name
, pOD
, pOpts
);
931 printOptionAction( pOpts
, pOD
);
934 * Now, do the same thing for the disablement version of the option.
936 if (pOD
->pz_DisableName
!= NULL
) {
937 emitMatchExpr( pOD
->pz_DisableName
, pOD
, pOpts
);
938 printOptionInaction( pOpts
, pOD
);
940 } while (pOD
++, --ct
> 0);
942 printf( zOptionUnknown
, "option", pOpts
->pzPROGNAME
);
947 openOutput( char const* pzFile
)
958 * IF we cannot stat the file,
959 * THEN assume we are creating a new file.
960 * Skip the loading of the old data.
962 if (stat( pzFile
, &stbf
) != 0)
966 * The file must be a regular file
968 if (! S_ISREG( stbf
.st_mode
)) {
969 fprintf( stderr
, zNotFile
, pzFile
);
970 exit( EXIT_FAILURE
);
973 pzData
= AGALOC(stbf
.st_size
+ 1, "file data");
974 fp
= fopen( pzFile
, "r" FOPEN_BINARY_FLAG
);
976 sizeLeft
= (unsigned)stbf
.st_size
;
980 * Read in all the data as fast as our OS will let us.
983 int inct
= fread( (void*)pzScan
, (size_t)1, sizeLeft
, fp
);
995 * NUL-terminate the leader and look for the trailer
999 pzScan
= strstr( pzData
, zStartMarker
);
1000 if (pzScan
== NULL
) {
1006 pzScan
= strstr( pzScan
, zTrailerMarker
);
1007 if (pzScan
== NULL
) {
1013 * Check to see if the data contains
1014 * our marker. If it does, then we will skip over it
1016 pzTrailer
= pzScan
+ sizeof( zTrailerMarker
) - 1;
1020 freopen( pzFile
, "w" FOPEN_BINARY_FLAG
, stdout
);
1024 /*=export_func genshelloptUsage
1026 * what: The usage function for the genshellopt generated program
1028 * arg: + tOptions* + pOpts + program options descriptor +
1029 * arg: + int + exitCode + usage text type to produce +
1032 * This function is used to create the usage strings for the option
1033 * processing shell script code. Two child processes are spawned
1034 * each emitting the usage text in either the short (error exit)
1035 * style or the long style. The generated program will capture this
1036 * and create shell script variables containing the two types of text.
1039 genshelloptUsage( tOptions
* pOpts
, int exitCode
)
1041 #if defined(__windows__) && !defined(__CYGWIN__)
1042 optionUsage( pOpts
, exitCode
);
1045 * IF not EXIT_SUCCESS,
1046 * THEN emit the short form of usage.
1048 if (exitCode
!= EXIT_SUCCESS
)
1049 optionUsage( pOpts
, exitCode
);
1053 option_usage_fp
= stdout
;
1056 * First, print our usage
1060 optionUsage( pOpts
, EXIT_FAILURE
);
1062 _exit( EXIT_FAILURE
);
1065 pagerState
= PAGER_STATE_CHILD
;
1066 optionUsage( pOpts
, EXIT_SUCCESS
);
1068 _exit( EXIT_FAILURE
);
1078 * Generate the pzProgName, since optionProcess() normally
1079 * gets it from the command line
1083 AGDUPSTR( pz
, pShellParseOptions
->pzPROGNAME
, "program name" );
1084 pShellParseOptions
->pzProgName
= pz
;
1085 while (*pz
!= NUL
) {
1086 *pz
= tolower( *pz
);
1092 * Separate the makeshell usage from the client usage
1094 fprintf( option_usage_fp
, zGenshell
, pShellParseOptions
->pzProgName
);
1095 fflush( option_usage_fp
);
1098 * Now, print the client usage.
1102 pagerState
= PAGER_STATE_CHILD
;
1105 optionUsage( pShellParseOptions
, EXIT_FAILURE
);
1114 exit( EXIT_SUCCESS
);
1121 * c-file-style: "stroustrup"
1122 * indent-tabs-mode: nil
1124 * end of autoopts/makeshell.c */