5 * Id: 7226344c6486a4eda395f893881080b7d80a2003
6 * Time-stamp: "2009-11-01 11:52:37 bkorb"
8 * This module will interpret the options set in the tOptions
9 * structure and create a Bourne shell script capable of parsing them.
11 * This file is part of AutoOpts, a companion to AutoGen.
12 * AutoOpts is free software.
13 * AutoOpts is copyright (c) 1992-2009 by Bruce Korb - all rights reserved
15 * AutoOpts is available under any one of two licenses. The license
16 * in use must be one of these two and the choice is under the control
17 * of the user of the license.
19 * The GNU Lesser General Public License, version 3 or later
20 * See the files "COPYING.lgplv3" and "COPYING.gplv3"
22 * The Modified Berkeley Software Distribution License
23 * See the file "COPYING.mbsd"
25 * These files have the following md5sums:
27 * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3
28 * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3
29 * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
32 tOptions
* pShellParseOptions
= NULL
;
34 /* * * * * * * * * * * * * * * * * * * * *
36 * Setup Format Strings
38 static char const zStartMarker
[] =
39 "# # # # # # # # # # -- do not modify this marker --\n#\n"
40 "# DO NOT EDIT THIS SECTION";
42 static char const zPreamble
[] =
44 "# From here to the next `-- do not modify this marker --',\n"
45 "# the text has been generated %s\n";
47 static char const zEndPreamble
[] =
48 "# From the %s option definitions\n#\n";
50 static char const zMultiDef
[] = "\n"
51 "if test -z \"${%1$s_%2$s}\"\n"
56 " %1$s_%2$s_1=\"${%1$s_%2$s}\"\n"
58 "export %1$s_%2$s_CT";
60 static char const zSingleDef
[] = "\n"
61 "%1$s_%2$s=\"${%1$s_%2$s-'%3$s'}\"\n"
62 "%1$s_%2$s_set=false\n"
65 static char const zSingleNoDef
[] = "\n"
66 "%1$s_%2$s=\"${%1$s_%2$s}\"\n"
67 "%1$s_%2$s_set=false\n"
70 /* * * * * * * * * * * * * * * * * * * * *
74 * The loop may run in either of two modes:
75 * all options are named options (loop only)
76 * regular, marked option processing.
78 static char const zLoopCase
[] = "\n"
81 "while ${OPT_PROCESS} && [ $# -gt 0 ]\ndo\n"
85 * 'OPT_ARG' may or may not match the current $1
87 " case \"${OPT_ARG}\" in\n"
89 " OPT_PROCESS=false\n"
93 static char const zLoopOnly
[] = "\n"
95 "while [ $# -gt 0 ]\ndo\n"
98 " OPT_ARG=\"${1}\"\n";
100 /* * * * * * * * * * * * * * * *
104 * If the loop runs as a regular option loop,
105 * then we must have selectors for each acceptable option
106 * type (long option, flag character and non-option)
108 static char const zLongSelection
[] =
111 static char const zFlagSelection
[] =
114 static char const zEndSelection
[] =
117 static char const zNoSelection
[] =
119 " OPT_PROCESS=false\n"
123 /* * * * * * * * * * * * * * * *
127 static char const zLoopEnd
[] =
128 " if [ -n \"${OPT_ARG_VAL}\" ]\n"
130 " eval %1$s_${OPT_NAME}${OPT_ELEMENT}=\"'${OPT_ARG_VAL}'\"\n"
131 " export %1$s_${OPT_NAME}${OPT_ELEMENT}\n"
134 "unset OPT_PROCESS || :\n"
135 "unset OPT_ELEMENT || :\n"
136 "unset OPT_ARG || :\n"
137 "unset OPT_ARG_NEEDED || :\n"
138 "unset OPT_NAME || :\n"
139 "unset OPT_CODE || :\n"
140 "unset OPT_ARG_VAL || :\n%2$s";
142 static char const zTrailerMarker
[] = "\n"
143 "# # # # # # # # # #\n#\n"
144 "# END OF AUTOMATED OPTION PROCESSING\n"
145 "#\n# # # # # # # # # # -- do not modify this marker --\n";
147 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
151 static char const zOptionCase
[] =
152 " case \"${OPT_CODE}\" in\n";
154 static char const zOptionPartName
[] =
157 static char const zOptionFullName
[] =
160 static char const zOptionFlag
[] =
163 static char const zOptionEndSelect
[] =
166 static char const zOptionUnknown
[] =
168 " echo Unknown %s: \"${OPT_CODE}\" >&2\n"
169 " echo \"$%s_USAGE_TEXT\"\n"
174 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
178 * Formats for emitting the text for handling particular options
180 static char const zTextExit
[] =
181 " echo \"$%s_%s_TEXT\"\n"
184 static char const zPagedUsageExit
[] =
185 " echo \"$%s_LONGUSAGE_TEXT\" | ${PAGER-more}\n"
188 static char const zCmdFmt
[] =
191 static char const zCountTest
[] =
192 " if [ $%1$s_%2$s_CT -ge %3$d ] ; then\n"
193 " echo Error: more than %3$d %2$s options >&2\n"
194 " echo \"$%1$s_USAGE_TEXT\"\n"
197 static char const zMultiArg
[] =
198 " %1$s_%2$s_CT=`expr ${%1$s_%2$s_CT} + 1`\n"
199 " OPT_ELEMENT=\"_${%1$s_%2$s_CT}\"\n"
200 " OPT_NAME='%2$s'\n";
202 static char const zSingleArg
[] =
203 " if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n"
204 " echo Error: duplicate %2$s option >&2\n"
205 " echo \"$%1$s_USAGE_TEXT\"\n"
207 " %1$s_%2$s_set=true\n"
208 " OPT_NAME='%2$s'\n";
210 static char const zNoMultiArg
[] =
213 " %1$s_%2$s='%3$s'\n"
214 " export %1$s_%2$s\n"
215 " OPT_NAME='%2$s'\n";
217 static char const zNoSingleArg
[] =
218 " if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n"
219 " echo Error: duplicate %2$s option >&2\n"
220 " echo \"$%1$s_USAGE_TEXT\"\n"
222 " %1$s_%2$s_set=true\n"
223 " %1$s_%2$s='%3$s'\n"
224 " export %1$s_%2$s\n"
225 " OPT_NAME='%2$s'\n";
227 static char const zMayArg
[] =
228 " eval %1$s_%2$s${OPT_ELEMENT}=true\n"
229 " export %1$s_%2$s${OPT_ELEMENT}\n"
230 " OPT_ARG_NEEDED=OK\n";
232 static char const zMustArg
[] =
233 " OPT_ARG_NEEDED=YES\n";
235 static char const zCantArg
[] =
236 " eval %1$s_%2$s${OPT_ELEMENT}=true\n"
237 " export %1$s_%2$s${OPT_ELEMENT}\n"
238 " OPT_ARG_NEEDED=NO\n";
240 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
242 * LONG OPTION PROCESSING
244 * Formats for emitting the text for handling long option types
246 static char const zLongOptInit
[] =
247 " OPT_CODE=`echo \"X${OPT_ARG}\"|sed 's/^X-*//'`\n"
249 " OPT_ARG=\"$1\"\n\n"
250 " case \"${OPT_CODE}\" in *=* )\n"
251 " OPT_ARG_VAL=`echo \"${OPT_CODE}\"|sed 's/^[^=]*=//'`\n"
252 " OPT_CODE=`echo \"${OPT_CODE}\"|sed 's/=.*$//'` ;; esac\n\n";
254 static char const zLongOptArg
[] =
255 " case \"${OPT_ARG_NEEDED}\" in\n"
260 " if [ -z \"${OPT_ARG_VAL}\" ]\n"
264 " echo No argument provided for ${OPT_NAME} option >&2\n"
265 " echo \"$%s_USAGE_TEXT\"\n"
268 " OPT_ARG_VAL=\"${OPT_ARG}\"\n"
274 " if [ -z \"${OPT_ARG_VAL}\" ] && [ $# -gt 0 ]\n"
276 " case \"${OPT_ARG}\" in -* ) ;; * )\n"
277 " OPT_ARG_VAL=\"${OPT_ARG}\"\n"
279 " OPT_ARG=\"$1\" ;; esac\n"
284 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
286 * FLAG OPTION PROCESSING
288 * Formats for emitting the text for handling flag option types
290 static char const zFlagOptInit
[] =
291 " OPT_CODE=`echo \"X${OPT_ARG}\" | sed 's/X-\\(.\\).*/\\1/'`\n"
292 " OPT_ARG=` echo \"X${OPT_ARG}\" | sed 's/X-.//'`\n\n";
294 static char const zFlagOptArg
[] =
295 " case \"${OPT_ARG_NEEDED}\" in\n"
297 " if [ -n \"${OPT_ARG}\" ]\n"
299 " OPT_ARG=-\"${OPT_ARG}\"\n"
306 " if [ -n \"${OPT_ARG}\" ]\n"
308 " OPT_ARG_VAL=\"${OPT_ARG}\"\n\n"
312 " echo No argument provided for ${OPT_NAME} option >&2\n"
313 " echo \"$%s_USAGE_TEXT\"\n"
317 " OPT_ARG_VAL=\"$1\"\n"
323 " if [ -n \"${OPT_ARG}\" ]\n"
325 " OPT_ARG_VAL=\"${OPT_ARG}\"\n"
327 " OPT_ARG=\"$1\"\n\n"
332 " case \"$1\" in -* ) ;; * )\n"
333 " OPT_ARG_VAL=\"$1\"\n"
341 tSCC
* pzShell
= NULL
;
342 static char* pzLeader
= NULL
;
343 static char* pzTrailer
= NULL
;
345 /* = = = START-STATIC-FORWARD = = = */
346 /* static forward declarations maintained by mk-fwd */
348 textToVariable( tOptions
* pOpts
, teTextTo whichVar
, tOptDesc
* pOD
);
351 emitUsage( tOptions
* pOpts
);
354 emitSetup( tOptions
* pOpts
);
357 printOptionAction( tOptions
* pOpts
, tOptDesc
* pOptDesc
);
360 printOptionInaction( tOptions
* pOpts
, tOptDesc
* pOptDesc
);
363 emitFlag( tOptions
* pOpts
);
366 emitMatchExpr( tCC
* pzMatchName
, tOptDesc
* pCurOpt
, tOptions
* pOpts
);
369 emitLong( tOptions
* pOpts
);
372 openOutput( char const* pzFile
);
373 /* = = = END-STATIC-FORWARD = = = */
375 /*=export_func optionParseShell
378 * what: Decipher a boolean value
379 * arg: + tOptions* + pOpts + program options descriptor +
382 * Emit a shell script that will parse the command line options.
385 optionParseShell( tOptions
* pOpts
)
388 * Check for our SHELL option now.
389 * IF the output file contains the "#!" magic marker,
390 * it will override anything we do here.
392 if (HAVE_OPT( SHELL
))
393 pzShell
= OPT_ARG( SHELL
);
395 else if (! ENABLED_OPT( SHELL
))
398 else if ((pzShell
= getenv( "SHELL" )),
404 * Check for a specified output file
406 if (HAVE_OPT( SCRIPT
))
407 openOutput( OPT_ARG( SCRIPT
));
413 * There are four modes of option processing.
415 switch (pOpts
->fOptSet
& (OPTPROC_LONGOPT
|OPTPROC_SHORTOPT
)) {
416 case OPTPROC_LONGOPT
:
417 fputs( zLoopCase
, stdout
);
419 fputs( zLongSelection
, stdout
);
420 fputs( zLongOptInit
, stdout
);
422 printf( zLongOptArg
, pOpts
->pzPROGNAME
);
423 fputs( zEndSelection
, stdout
);
425 fputs( zNoSelection
, stdout
);
429 fputs( zLoopOnly
, stdout
);
430 fputs( zLongOptInit
, stdout
);
432 printf( zLongOptArg
, pOpts
->pzPROGNAME
);
435 case OPTPROC_SHORTOPT
:
436 fputs( zLoopCase
, stdout
);
438 fputs( zFlagSelection
, stdout
);
439 fputs( zFlagOptInit
, stdout
);
441 printf( zFlagOptArg
, pOpts
->pzPROGNAME
);
442 fputs( zEndSelection
, stdout
);
444 fputs( zNoSelection
, stdout
);
447 case OPTPROC_LONGOPT
|OPTPROC_SHORTOPT
:
448 fputs( zLoopCase
, stdout
);
450 fputs( zLongSelection
, stdout
);
451 fputs( zLongOptInit
, stdout
);
453 printf( zLongOptArg
, pOpts
->pzPROGNAME
);
454 fputs( zEndSelection
, stdout
);
456 fputs( zFlagSelection
, stdout
);
457 fputs( zFlagOptInit
, stdout
);
459 printf( zFlagOptArg
, pOpts
->pzPROGNAME
);
460 fputs( zEndSelection
, stdout
);
462 fputs( zNoSelection
, stdout
);
466 printf( zLoopEnd
, pOpts
->pzPROGNAME
, zTrailerMarker
);
467 if ((pzTrailer
!= NULL
) && (*pzTrailer
!= '\0'))
468 fputs( pzTrailer
, stdout
);
469 else if (ENABLED_OPT( SHELL
))
470 printf( "\nenv | grep '^%s_'\n", pOpts
->pzPROGNAME
);
473 fchmod( STDOUT_FILENO
, 0755 );
479 textToVariable( tOptions
* pOpts
, teTextTo whichVar
, tOptDesc
* pOD
)
481 # define _TT_(n) tSCC z ## n [] = #n;
484 # define _TT_(n) z ## n ,
485 static char const* apzTTNames
[] = { TEXTTO_TABLE
};
488 #if ! defined(HAVE_WORKING_FORK)
489 printf( "%1$s_%2$s_TEXT='no %2$s text'\n",
490 pOpts
->pzPROGNAME
, apzTTNames
[ whichVar
]);
496 printf( "%s_%s_TEXT='", pOpts
->pzPROGNAME
, apzTTNames
[ whichVar
]);
499 if (pipe( pipeFd
) != 0) {
500 fprintf( stderr
, zBadPipe
, errno
, strerror( errno
));
501 exit( EXIT_FAILURE
);
506 fprintf( stderr
, zForkFail
, errno
, strerror(errno
), pOpts
->pzProgName
);
507 exit( EXIT_FAILURE
);
511 dup2( pipeFd
[1], STDERR_FILENO
);
512 dup2( pipeFd
[1], STDOUT_FILENO
);
517 (*(pOpts
->pUsageProc
))( pOpts
, EXIT_SUCCESS
);
519 exit( EXIT_FAILURE
);
522 (*(pOpts
->pUsageProc
))( pOpts
, EXIT_FAILURE
);
524 exit( EXIT_FAILURE
);
527 if (pOD
->fOptState
& OPTST_ALLOC_ARG
) {
528 AGFREE(pOD
->optArg
.argString
);
529 pOD
->fOptState
&= ~OPTST_ALLOC_ARG
;
531 pOD
->optArg
.argString
= "c";
532 optionPrintVersion( pOpts
, pOD
);
536 exit( EXIT_FAILURE
);
541 fp
= fdopen( pipeFd
[0], "r" FOPEN_BINARY_FLAG
);
545 int ch
= fgetc( fp
);
553 while (nlHoldCt
> 0) {
554 fputc( '\n', stdout
);
557 fputs( "'\\''", stdout
);
564 while (nlHoldCt
> 0) {
565 fputc( '\n', stdout
);
573 fputs( "'\n\n", stdout
);
580 emitUsage( tOptions
* pOpts
)
582 char zTimeBuf
[ AO_NAME_SIZE
];
585 * First, switch stdout to the output file name.
586 * Then, change the program name to the one defined
587 * by the definitions (rather than the current
588 * executable name). Down case the upper cased name.
590 if (pzLeader
!= NULL
)
591 fputs( pzLeader
, stdout
);
594 tSCC zStdout
[] = "stdout";
598 time_t curTime
= time( NULL
);
599 struct tm
* pTime
= localtime( &curTime
);
600 strftime(zTimeBuf
, AO_NAME_SIZE
, "%A %B %e, %Y at %r %Z", pTime
);
603 if (HAVE_OPT( SCRIPT
))
604 pzOutName
= OPT_ARG( SCRIPT
);
605 else pzOutName
= zStdout
;
607 if ((pzLeader
== NULL
) && (pzShell
!= NULL
))
608 printf( "#! %s\n", pzShell
);
610 printf( zPreamble
, zStartMarker
, pzOutName
, zTimeBuf
);
614 * Get a copy of the original program name in lower case
617 char* pzPN
= zTimeBuf
;
618 tCC
* pz
= pOpts
->pzPROGNAME
;
620 if ((*pzPN
++ = tolower( *pz
++ )) == '\0')
625 printf( zEndPreamble
, pOpts
->pzPROGNAME
);
627 pOpts
->pzProgPath
= pOpts
->pzProgName
= zTimeBuf
;
628 textToVariable( pOpts
, TT_LONGUSAGE
, NULL
);
629 textToVariable( pOpts
, TT_USAGE
, NULL
);
632 tOptDesc
* pOptDesc
= pOpts
->pOptDesc
;
633 int optionCt
= pOpts
->optCt
;
636 if (pOptDesc
->pOptProc
== optionPrintVersion
) {
637 textToVariable( pOpts
, TT_VERSION
, pOptDesc
);
650 emitSetup( tOptions
* pOpts
)
652 tOptDesc
* pOptDesc
= pOpts
->pOptDesc
;
653 int optionCt
= pOpts
->presetOptCt
;
655 char const* pzDefault
;
657 for (;optionCt
> 0; pOptDesc
++, --optionCt
) {
661 * Options that are either usage documentation or are compiled out
662 * are not to be processed.
664 if (SKIP_OPT(pOptDesc
) || (pOptDesc
->pz_NAME
== NULL
))
667 if (pOptDesc
->optMaxCt
> 1)
669 else pzFmt
= zSingleDef
;
672 * IF this is an enumeration/bitmask option, then convert the value
673 * to a string before printing the default value.
675 switch (OPTST_GET_ARGTYPE(pOptDesc
->fOptState
)) {
676 case OPARG_TYPE_ENUMERATION
:
677 (*(pOptDesc
->pOptProc
))(OPTPROC_EMIT_SHELL
, pOptDesc
);
678 pzDefault
= pOptDesc
->optArg
.argString
;
682 * Numeric and membership bit options are just printed as a number.
684 case OPARG_TYPE_NUMERIC
:
685 snprintf( zVal
, sizeof( zVal
), "%d",
686 (int)pOptDesc
->optArg
.argInt
);
690 case OPARG_TYPE_MEMBERSHIP
:
691 snprintf( zVal
, sizeof( zVal
), "%lu",
692 (unsigned long)pOptDesc
->optArg
.argIntptr
);
696 case OPARG_TYPE_BOOLEAN
:
697 pzDefault
= (pOptDesc
->optArg
.argBool
) ? "true" : "false";
701 if (pOptDesc
->optArg
.argString
== NULL
) {
702 if (pzFmt
== zSingleDef
)
703 pzFmt
= zSingleNoDef
;
707 pzDefault
= pOptDesc
->optArg
.argString
;
710 printf( pzFmt
, pOpts
->pzPROGNAME
, pOptDesc
->pz_NAME
, pzDefault
);
716 printOptionAction( tOptions
* pOpts
, tOptDesc
* pOptDesc
)
718 if (pOptDesc
->pOptProc
== optionPrintVersion
)
719 printf( zTextExit
, pOpts
->pzPROGNAME
, "VERSION" );
721 else if (pOptDesc
->pOptProc
== optionPagedUsage
)
722 printf( zPagedUsageExit
, pOpts
->pzPROGNAME
);
724 else if (pOptDesc
->pOptProc
== optionLoadOpt
) {
725 printf( zCmdFmt
, "echo 'Warning: Cannot load options files' >&2" );
726 printf( zCmdFmt
, "OPT_ARG_NEEDED=YES" );
728 } else if (pOptDesc
->pz_NAME
== NULL
) {
730 if (pOptDesc
->pOptProc
== NULL
) {
731 printf( zCmdFmt
, "echo 'Warning: Cannot save options files' "
733 printf( zCmdFmt
, "OPT_ARG_NEEDED=OK" );
735 printf( zTextExit
, pOpts
->pzPROGNAME
, "LONGUSAGE" );
738 if (pOptDesc
->optMaxCt
== 1)
739 printf( zSingleArg
, pOpts
->pzPROGNAME
, pOptDesc
->pz_NAME
);
741 if ((unsigned)pOptDesc
->optMaxCt
< NOLIMIT
)
742 printf( zCountTest
, pOpts
->pzPROGNAME
,
743 pOptDesc
->pz_NAME
, pOptDesc
->optMaxCt
);
745 printf( zMultiArg
, pOpts
->pzPROGNAME
, pOptDesc
->pz_NAME
);
751 if (OPTST_GET_ARGTYPE(pOptDesc
->fOptState
) == OPARG_TYPE_NONE
) {
752 printf( zCantArg
, pOpts
->pzPROGNAME
, pOptDesc
->pz_NAME
);
754 } else if (pOptDesc
->fOptState
& OPTST_ARG_OPTIONAL
) {
755 printf( zMayArg
, pOpts
->pzPROGNAME
, pOptDesc
->pz_NAME
);
758 fputs( zMustArg
, stdout
);
761 fputs( zOptionEndSelect
, stdout
);
766 printOptionInaction( tOptions
* pOpts
, tOptDesc
* pOptDesc
)
768 if (pOptDesc
->pOptProc
== optionLoadOpt
) {
769 printf( zCmdFmt
, "echo 'Warning: Cannot suppress the loading of "
770 "options files' >&2" );
772 } else if (pOptDesc
->optMaxCt
== 1)
773 printf( zNoSingleArg
, pOpts
->pzPROGNAME
,
774 pOptDesc
->pz_NAME
, pOptDesc
->pz_DisablePfx
);
776 printf( zNoMultiArg
, pOpts
->pzPROGNAME
,
777 pOptDesc
->pz_NAME
, pOptDesc
->pz_DisablePfx
);
779 printf( zCmdFmt
, "OPT_ARG_NEEDED=NO" );
780 fputs( zOptionEndSelect
, stdout
);
785 emitFlag( tOptions
* pOpts
)
787 tOptDesc
* pOptDesc
= pOpts
->pOptDesc
;
788 int optionCt
= pOpts
->optCt
;
790 fputs( zOptionCase
, stdout
);
792 for (;optionCt
> 0; pOptDesc
++, --optionCt
) {
794 if (SKIP_OPT(pOptDesc
))
797 if (IS_GRAPHIC_CHAR(pOptDesc
->optValue
)) {
798 printf( zOptionFlag
, pOptDesc
->optValue
);
799 printOptionAction( pOpts
, pOptDesc
);
802 printf( zOptionUnknown
, "flag", pOpts
->pzPROGNAME
);
807 * Emit the match text for a long option
810 emitMatchExpr( tCC
* pzMatchName
, tOptDesc
* pCurOpt
, tOptions
* pOpts
)
812 tOptDesc
* pOD
= pOpts
->pOptDesc
;
813 int oCt
= pOpts
->optCt
;
822 * Omit the current option, Documentation opts and compiled out opts.
824 if ((pOD
== pCurOpt
) || SKIP_OPT(pOD
)){
832 * Check each character of the name case insensitively.
833 * They must not be the same. They cannot be, because it would
834 * not compile correctly if they were.
836 while ( toupper( pOD
->pz_Name
[matchCt
] )
837 == toupper( pzMatchName
[matchCt
] ))
844 * Check the disablement name, too.
846 if (pOD
->pz_DisableName
!= NULL
) {
848 while ( toupper( pOD
->pz_DisableName
[matchCt
] )
849 == toupper( pzMatchName
[matchCt
] ))
860 * IF the 'min' is all or one short of the name length,
861 * THEN the entire string must be matched.
863 if ( (pzMatchName
[min
] == NUL
)
864 || (pzMatchName
[min
+1] == NUL
) )
865 printf( zOptionFullName
, pzMatchName
);
869 for (; matchCt
<= min
; matchCt
++)
870 *pz
++ = pzMatchName
[matchCt
];
874 printf( zOptionPartName
, zName
);
875 *pz
++ = pzMatchName
[matchCt
++];
876 if (pzMatchName
[matchCt
] == NUL
) {
878 printf( zOptionFullName
, zName
);
887 * Emit GNU-standard long option handling code
890 emitLong( tOptions
* pOpts
)
892 tOptDesc
* pOD
= pOpts
->pOptDesc
;
893 int ct
= pOpts
->optCt
;
895 fputs( zOptionCase
, stdout
);
898 * do each option, ...
902 * Documentation & compiled-out options
907 emitMatchExpr( pOD
->pz_Name
, pOD
, pOpts
);
908 printOptionAction( pOpts
, pOD
);
911 * Now, do the same thing for the disablement version of the option.
913 if (pOD
->pz_DisableName
!= NULL
) {
914 emitMatchExpr( pOD
->pz_DisableName
, pOD
, pOpts
);
915 printOptionInaction( pOpts
, pOD
);
917 } while (pOD
++, --ct
> 0);
919 printf( zOptionUnknown
, "option", pOpts
->pzPROGNAME
);
924 openOutput( char const* pzFile
)
935 * IF we cannot stat the file,
936 * THEN assume we are creating a new file.
937 * Skip the loading of the old data.
939 if (stat( pzFile
, &stbf
) != 0)
943 * The file must be a regular file
945 if (! S_ISREG( stbf
.st_mode
)) {
946 fprintf( stderr
, zNotFile
, pzFile
);
947 exit( EXIT_FAILURE
);
950 pzData
= AGALOC(stbf
.st_size
+ 1, "file data");
951 fp
= fopen( pzFile
, "r" FOPEN_BINARY_FLAG
);
953 sizeLeft
= (unsigned)stbf
.st_size
;
957 * Read in all the data as fast as our OS will let us.
960 int inct
= fread( (void*)pzScan
, (size_t)1, sizeLeft
, fp
);
972 * NUL-terminate the leader and look for the trailer
976 pzScan
= strstr( pzData
, zStartMarker
);
977 if (pzScan
== NULL
) {
983 pzScan
= strstr( pzScan
, zTrailerMarker
);
984 if (pzScan
== NULL
) {
990 * Check to see if the data contains
991 * our marker. If it does, then we will skip over it
993 pzTrailer
= pzScan
+ sizeof( zTrailerMarker
) - 1;
997 freopen( pzFile
, "w" FOPEN_BINARY_FLAG
, stdout
);
1001 /*=export_func genshelloptUsage
1003 * what: The usage function for the genshellopt generated program
1005 * arg: + tOptions* + pOpts + program options descriptor +
1006 * arg: + int + exitCode + usage text type to produce +
1009 * This function is used to create the usage strings for the option
1010 * processing shell script code. Two child processes are spawned
1011 * each emitting the usage text in either the short (error exit)
1012 * style or the long style. The generated program will capture this
1013 * and create shell script variables containing the two types of text.
1016 genshelloptUsage( tOptions
* pOpts
, int exitCode
)
1018 #if ! defined(HAVE_WORKING_FORK)
1019 optionUsage( pOpts
, exitCode
);
1022 * IF not EXIT_SUCCESS,
1023 * THEN emit the short form of usage.
1025 if (exitCode
!= EXIT_SUCCESS
)
1026 optionUsage( pOpts
, exitCode
);
1030 option_usage_fp
= stdout
;
1033 * First, print our usage
1037 optionUsage( pOpts
, EXIT_FAILURE
);
1039 _exit( EXIT_FAILURE
);
1042 pagerState
= PAGER_STATE_CHILD
;
1043 optionUsage( pOpts
, EXIT_SUCCESS
);
1045 _exit( EXIT_FAILURE
);
1055 * Generate the pzProgName, since optionProcess() normally
1056 * gets it from the command line
1060 AGDUPSTR( pz
, pShellParseOptions
->pzPROGNAME
, "program name" );
1061 pShellParseOptions
->pzProgName
= pz
;
1062 while (*pz
!= NUL
) {
1063 *pz
= tolower( *pz
);
1069 * Separate the makeshell usage from the client usage
1071 fprintf( option_usage_fp
, zGenshell
, pShellParseOptions
->pzProgName
);
1072 fflush( option_usage_fp
);
1075 * Now, print the client usage.
1079 pagerState
= PAGER_STATE_CHILD
;
1082 optionUsage( pShellParseOptions
, EXIT_FAILURE
);
1091 exit( EXIT_SUCCESS
);
1098 * c-file-style: "stroustrup"
1099 * indent-tabs-mode: nil
1101 * end of autoopts/makeshell.c */