1ea906c41SOllivier Robert 2ea906c41SOllivier Robert /* 3ea906c41SOllivier Robert * $Id: makeshell.c,v 4.20 2007/02/04 17:44:12 bkorb Exp $ 4ea906c41SOllivier Robert * Time-stamp: "2007-01-27 06:05:45 bkorb" 5ea906c41SOllivier Robert * 6ea906c41SOllivier Robert * This module will interpret the options set in the tOptions 7ea906c41SOllivier Robert * structure and create a Bourne shell script capable of parsing them. 8ea906c41SOllivier Robert */ 9ea906c41SOllivier Robert 10ea906c41SOllivier Robert /* 11ea906c41SOllivier Robert * Automated Options copyright 1992-2007 Bruce Korb 12ea906c41SOllivier Robert * 13ea906c41SOllivier Robert * Automated Options is free software. 14ea906c41SOllivier Robert * You may redistribute it and/or modify it under the terms of the 15ea906c41SOllivier Robert * GNU General Public License, as published by the Free Software 16ea906c41SOllivier Robert * Foundation; either version 2, or (at your option) any later version. 17ea906c41SOllivier Robert * 18ea906c41SOllivier Robert * Automated Options is distributed in the hope that it will be useful, 19ea906c41SOllivier Robert * but WITHOUT ANY WARRANTY; without even the implied warranty of 20ea906c41SOllivier Robert * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21ea906c41SOllivier Robert * GNU General Public License for more details. 22ea906c41SOllivier Robert * 23ea906c41SOllivier Robert * You should have received a copy of the GNU General Public License 24ea906c41SOllivier Robert * along with Automated Options. See the file "COPYING". If not, 25ea906c41SOllivier Robert * write to: The Free Software Foundation, Inc., 26ea906c41SOllivier Robert * 51 Franklin Street, Fifth Floor, 27ea906c41SOllivier Robert * Boston, MA 02110-1301, USA. 28ea906c41SOllivier Robert * 29ea906c41SOllivier Robert * As a special exception, Bruce Korb gives permission for additional 30ea906c41SOllivier Robert * uses of the text contained in his release of AutoOpts. 31ea906c41SOllivier Robert * 32ea906c41SOllivier Robert * The exception is that, if you link the AutoOpts library with other 33ea906c41SOllivier Robert * files to produce an executable, this does not by itself cause the 34ea906c41SOllivier Robert * resulting executable to be covered by the GNU General Public License. 35ea906c41SOllivier Robert * Your use of that executable is in no way restricted on account of 36ea906c41SOllivier Robert * linking the AutoOpts library code into it. 37ea906c41SOllivier Robert * 38ea906c41SOllivier Robert * This exception does not however invalidate any other reasons why 39ea906c41SOllivier Robert * the executable file might be covered by the GNU General Public License. 40ea906c41SOllivier Robert * 41ea906c41SOllivier Robert * This exception applies only to the code released by Bruce Korb under 42ea906c41SOllivier Robert * the name AutoOpts. If you copy code from other sources under the 43ea906c41SOllivier Robert * General Public License into a copy of AutoOpts, as the General Public 44ea906c41SOllivier Robert * License permits, the exception does not apply to the code that you add 45ea906c41SOllivier Robert * in this way. To avoid misleading anyone as to the status of such 46ea906c41SOllivier Robert * modified files, you must delete this exception notice from them. 47ea906c41SOllivier Robert * 48ea906c41SOllivier Robert * If you write modifications of your own for AutoOpts, it is your choice 49ea906c41SOllivier Robert * whether to permit this exception to apply to your modifications. 50ea906c41SOllivier Robert * If you do not wish that, delete this exception notice. 51ea906c41SOllivier Robert */ 52ea906c41SOllivier Robert 53ea906c41SOllivier Robert tOptions* pShellParseOptions = NULL; 54ea906c41SOllivier Robert 55ea906c41SOllivier Robert /* * * * * * * * * * * * * * * * * * * * * 56ea906c41SOllivier Robert * 57ea906c41SOllivier Robert * Setup Format Strings 58ea906c41SOllivier Robert */ 59ea906c41SOllivier Robert tSCC zStartMarker[] = 60ea906c41SOllivier Robert "# # # # # # # # # # -- do not modify this marker --\n#\n" 61ea906c41SOllivier Robert "# DO NOT EDIT THIS SECTION"; 62ea906c41SOllivier Robert 63ea906c41SOllivier Robert tSCC zPreamble[] = 64ea906c41SOllivier Robert "%s OF %s\n#\n" 65ea906c41SOllivier Robert "# From here to the next `-- do not modify this marker --',\n" 66ea906c41SOllivier Robert "# the text has been generated %s\n"; 67ea906c41SOllivier Robert 68ea906c41SOllivier Robert tSCC zEndPreamble[] = 69ea906c41SOllivier Robert "# From the %s option definitions\n#\n"; 70ea906c41SOllivier Robert 71ea906c41SOllivier Robert tSCC zMultiDef[] = "\n" 72ea906c41SOllivier Robert "if test -z \"${%1$s_%2$s}\"\n" 73ea906c41SOllivier Robert "then\n" 74ea906c41SOllivier Robert " %1$s_%2$s_CT=0\n" 75ea906c41SOllivier Robert "else\n" 76ea906c41SOllivier Robert " %1$s_%2$s_CT=1\n" 77ea906c41SOllivier Robert " %1$s_%2$s_1=\"${%1$s_%2$s}\"\n" 78ea906c41SOllivier Robert "fi\n" 79ea906c41SOllivier Robert "export %1$s_%2$s_CT"; 80ea906c41SOllivier Robert 81ea906c41SOllivier Robert tSCC zSingleDef[] = "\n" 82ea906c41SOllivier Robert "%1$s_%2$s=\"${%1$s_%2$s-'%3$s'}\"\n" 83ea906c41SOllivier Robert "%1$s_%2$s_set=false\n" 84ea906c41SOllivier Robert "export %1$s_%2$s\n"; 85ea906c41SOllivier Robert 86ea906c41SOllivier Robert tSCC zSingleNoDef[] = "\n" 87ea906c41SOllivier Robert "%1$s_%2$s=\"${%1$s_%2$s}\"\n" 88ea906c41SOllivier Robert "%1$s_%2$s_set=false\n" 89ea906c41SOllivier Robert "export %1$s_%2$s\n"; 90ea906c41SOllivier Robert 91ea906c41SOllivier Robert /* * * * * * * * * * * * * * * * * * * * * 92ea906c41SOllivier Robert * 93ea906c41SOllivier Robert * LOOP START 94ea906c41SOllivier Robert * 95ea906c41SOllivier Robert * The loop may run in either of two modes: 96ea906c41SOllivier Robert * all options are named options (loop only) 97ea906c41SOllivier Robert * regular, marked option processing. 98ea906c41SOllivier Robert */ 99ea906c41SOllivier Robert tSCC zLoopCase[] = "\n" 100ea906c41SOllivier Robert "OPT_PROCESS=true\n" 101ea906c41SOllivier Robert "OPT_ARG=\"$1\"\n\n" 102ea906c41SOllivier Robert "while ${OPT_PROCESS} && [ $# -gt 0 ]\ndo\n" 103ea906c41SOllivier Robert " OPT_ELEMENT=''\n" 104ea906c41SOllivier Robert " OPT_ARG_VAL=''\n\n" 105ea906c41SOllivier Robert /* 106ea906c41SOllivier Robert * 'OPT_ARG' may or may not match the current $1 107ea906c41SOllivier Robert */ 108ea906c41SOllivier Robert " case \"${OPT_ARG}\" in\n" 109ea906c41SOllivier Robert " -- )\n" 110ea906c41SOllivier Robert " OPT_PROCESS=false\n" 111ea906c41SOllivier Robert " shift\n" 112ea906c41SOllivier Robert " ;;\n\n"; 113ea906c41SOllivier Robert 114ea906c41SOllivier Robert tSCC zLoopOnly[] = "\n" 115ea906c41SOllivier Robert "OPT_ARG=\"$1\"\n\n" 116ea906c41SOllivier Robert "while [ $# -gt 0 ]\ndo\n" 117ea906c41SOllivier Robert " OPT_ELEMENT=''\n" 118ea906c41SOllivier Robert " OPT_ARG_VAL=''\n\n" 119ea906c41SOllivier Robert " OPT_ARG=\"${1}\"\n"; 120ea906c41SOllivier Robert 121ea906c41SOllivier Robert /* * * * * * * * * * * * * * * * 122ea906c41SOllivier Robert * 123ea906c41SOllivier Robert * CASE SELECTORS 124ea906c41SOllivier Robert * 125ea906c41SOllivier Robert * If the loop runs as a regular option loop, 126ea906c41SOllivier Robert * then we must have selectors for each acceptable option 127ea906c41SOllivier Robert * type (long option, flag character and non-option) 128ea906c41SOllivier Robert */ 129ea906c41SOllivier Robert tSCC zLongSelection[] = 130ea906c41SOllivier Robert " --* )\n"; 131ea906c41SOllivier Robert 132ea906c41SOllivier Robert tSCC zFlagSelection[] = 133ea906c41SOllivier Robert " -* )\n"; 134ea906c41SOllivier Robert 135ea906c41SOllivier Robert tSCC zEndSelection[] = 136ea906c41SOllivier Robert " ;;\n\n"; 137ea906c41SOllivier Robert 138ea906c41SOllivier Robert tSCC zNoSelection[] = 139ea906c41SOllivier Robert " * )\n" 140ea906c41SOllivier Robert " OPT_PROCESS=false\n" 141ea906c41SOllivier Robert " ;;\n" 142ea906c41SOllivier Robert " esac\n\n"; 143ea906c41SOllivier Robert 144ea906c41SOllivier Robert /* * * * * * * * * * * * * * * * 145ea906c41SOllivier Robert * 146ea906c41SOllivier Robert * LOOP END 147ea906c41SOllivier Robert */ 148ea906c41SOllivier Robert tSCC zLoopEnd[] = 149ea906c41SOllivier Robert " if [ -n \"${OPT_ARG_VAL}\" ]\n" 150ea906c41SOllivier Robert " then\n" 151ea906c41SOllivier Robert " eval %1$s_${OPT_NAME}${OPT_ELEMENT}=\"'${OPT_ARG_VAL}'\"\n" 152ea906c41SOllivier Robert " export %1$s_${OPT_NAME}${OPT_ELEMENT}\n" 153ea906c41SOllivier Robert " fi\n" 154ea906c41SOllivier Robert "done\n\n" 155ea906c41SOllivier Robert "unset OPT_PROCESS || :\n" 156ea906c41SOllivier Robert "unset OPT_ELEMENT || :\n" 157ea906c41SOllivier Robert "unset OPT_ARG || :\n" 158ea906c41SOllivier Robert "unset OPT_ARG_NEEDED || :\n" 159ea906c41SOllivier Robert "unset OPT_NAME || :\n" 160ea906c41SOllivier Robert "unset OPT_CODE || :\n" 161ea906c41SOllivier Robert "unset OPT_ARG_VAL || :\n%2$s"; 162ea906c41SOllivier Robert 163ea906c41SOllivier Robert tSCC zTrailerMarker[] = "\n" 164ea906c41SOllivier Robert "# # # # # # # # # #\n#\n" 165ea906c41SOllivier Robert "# END OF AUTOMATED OPTION PROCESSING\n" 166ea906c41SOllivier Robert "#\n# # # # # # # # # # -- do not modify this marker --\n"; 167ea906c41SOllivier Robert 168ea906c41SOllivier Robert /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 169ea906c41SOllivier Robert * 170ea906c41SOllivier Robert * OPTION SELECTION 171ea906c41SOllivier Robert */ 172ea906c41SOllivier Robert tSCC zOptionCase[] = 173ea906c41SOllivier Robert " case \"${OPT_CODE}\" in\n"; 174ea906c41SOllivier Robert 175ea906c41SOllivier Robert tSCC zOptionPartName[] = 176ea906c41SOllivier Robert " '%s' | \\\n"; 177ea906c41SOllivier Robert 178ea906c41SOllivier Robert tSCC zOptionFullName[] = 179ea906c41SOllivier Robert " '%s' )\n"; 180ea906c41SOllivier Robert 181ea906c41SOllivier Robert tSCC zOptionFlag[] = 182ea906c41SOllivier Robert " '%c' )\n"; 183ea906c41SOllivier Robert 184ea906c41SOllivier Robert tSCC zOptionEndSelect[] = 185ea906c41SOllivier Robert " ;;\n\n"; 186ea906c41SOllivier Robert 187ea906c41SOllivier Robert tSCC zOptionUnknown[] = 188ea906c41SOllivier Robert " * )\n" 189ea906c41SOllivier Robert " echo Unknown %s: \"${OPT_CODE}\" >&2\n" 190ea906c41SOllivier Robert " echo \"$%s_USAGE_TEXT\"\n" 191ea906c41SOllivier Robert " exit 1\n" 192ea906c41SOllivier Robert " ;;\n" 193ea906c41SOllivier Robert " esac\n\n"; 194ea906c41SOllivier Robert 195ea906c41SOllivier Robert /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 196ea906c41SOllivier Robert * 197ea906c41SOllivier Robert * OPTION PROCESSING 198ea906c41SOllivier Robert * 199ea906c41SOllivier Robert * Formats for emitting the text for handling particular options 200ea906c41SOllivier Robert */ 201ea906c41SOllivier Robert tSCC zTextExit[] = 202ea906c41SOllivier Robert " echo \"$%s_%s_TEXT\"\n" 203ea906c41SOllivier Robert " exit 0\n"; 204ea906c41SOllivier Robert 205ea906c41SOllivier Robert tSCC zPagedUsageExit[] = 206ea906c41SOllivier Robert " echo \"$%s_LONGUSAGE_TEXT\" | ${PAGER-more}\n" 207ea906c41SOllivier Robert " exit 0\n"; 208ea906c41SOllivier Robert 209ea906c41SOllivier Robert tSCC zCmdFmt[] = 210ea906c41SOllivier Robert " %s\n"; 211ea906c41SOllivier Robert 212ea906c41SOllivier Robert tSCC zCountTest[] = 213ea906c41SOllivier Robert " if [ $%1$s_%2$s_CT -ge %3$d ] ; then\n" 214ea906c41SOllivier Robert " echo Error: more than %3$d %2$s options >&2\n" 215ea906c41SOllivier Robert " echo \"$%1$s_USAGE_TEXT\"\n" 216ea906c41SOllivier Robert " exit 1 ; fi\n"; 217ea906c41SOllivier Robert 218ea906c41SOllivier Robert tSCC zMultiArg[] = 219ea906c41SOllivier Robert " %1$s_%2$s_CT=`expr ${%1$s_%2$s_CT} + 1`\n" 220ea906c41SOllivier Robert " OPT_ELEMENT=\"_${%1$s_%2$s_CT}\"\n" 221ea906c41SOllivier Robert " OPT_NAME='%2$s'\n"; 222ea906c41SOllivier Robert 223ea906c41SOllivier Robert tSCC zSingleArg[] = 224ea906c41SOllivier Robert " if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n" 225ea906c41SOllivier Robert " echo Error: duplicate %2$s option >&2\n" 226ea906c41SOllivier Robert " echo \"$%1$s_USAGE_TEXT\"\n" 227ea906c41SOllivier Robert " exit 1 ; fi\n" 228ea906c41SOllivier Robert " %1$s_%2$s_set=true\n" 229ea906c41SOllivier Robert " OPT_NAME='%2$s'\n"; 230ea906c41SOllivier Robert 231ea906c41SOllivier Robert tSCC zNoMultiArg[] = 232ea906c41SOllivier Robert " %1$s_%2$s_CT=0\n" 233ea906c41SOllivier Robert " OPT_ELEMENT=''\n" 234ea906c41SOllivier Robert " %1$s_%2$s='%3$s'\n" 235ea906c41SOllivier Robert " export %1$s_%2$s\n" 236ea906c41SOllivier Robert " OPT_NAME='%2$s'\n"; 237ea906c41SOllivier Robert 238ea906c41SOllivier Robert tSCC zNoSingleArg[] = 239ea906c41SOllivier Robert " if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n" 240ea906c41SOllivier Robert " echo Error: duplicate %2$s option >&2\n" 241ea906c41SOllivier Robert " echo \"$%1$s_USAGE_TEXT\"\n" 242ea906c41SOllivier Robert " exit 1 ; fi\n" 243ea906c41SOllivier Robert " %1$s_%2$s_set=true\n" 244ea906c41SOllivier Robert " %1$s_%2$s='%3$s'\n" 245ea906c41SOllivier Robert " export %1$s_%2$s\n" 246ea906c41SOllivier Robert " OPT_NAME='%2$s'\n"; 247ea906c41SOllivier Robert 248ea906c41SOllivier Robert tSCC zMayArg[] = 249ea906c41SOllivier Robert " eval %1$s_%2$s${OPT_ELEMENT}=true\n" 250ea906c41SOllivier Robert " export %1$s_%2$s${OPT_ELEMENT}\n" 251ea906c41SOllivier Robert " OPT_ARG_NEEDED=OK\n"; 252ea906c41SOllivier Robert 253ea906c41SOllivier Robert tSCC zMustArg[] = 254ea906c41SOllivier Robert " OPT_ARG_NEEDED=YES\n"; 255ea906c41SOllivier Robert 256ea906c41SOllivier Robert tSCC zCantArg[] = 257ea906c41SOllivier Robert " eval %1$s_%2$s${OPT_ELEMENT}=true\n" 258ea906c41SOllivier Robert " export %1$s_%2$s${OPT_ELEMENT}\n" 259ea906c41SOllivier Robert " OPT_ARG_NEEDED=NO\n"; 260ea906c41SOllivier Robert 261ea906c41SOllivier Robert /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 262ea906c41SOllivier Robert * 263ea906c41SOllivier Robert * LONG OPTION PROCESSING 264ea906c41SOllivier Robert * 265ea906c41SOllivier Robert * Formats for emitting the text for handling long option types 266ea906c41SOllivier Robert */ 267ea906c41SOllivier Robert tSCC zLongOptInit[] = 268ea906c41SOllivier Robert " OPT_CODE=`echo \"X${OPT_ARG}\"|sed 's/^X-*//'`\n" 269ea906c41SOllivier Robert " shift\n" 270ea906c41SOllivier Robert " OPT_ARG=\"$1\"\n\n" 271ea906c41SOllivier Robert " case \"${OPT_CODE}\" in *=* )\n" 272ea906c41SOllivier Robert " OPT_ARG_VAL=`echo \"${OPT_CODE}\"|sed 's/^[^=]*=//'`\n" 273ea906c41SOllivier Robert " OPT_CODE=`echo \"${OPT_CODE}\"|sed 's/=.*$//'` ;; esac\n\n"; 274ea906c41SOllivier Robert 275ea906c41SOllivier Robert tSCC zLongOptArg[] = 276ea906c41SOllivier Robert " case \"${OPT_ARG_NEEDED}\" in\n" 277ea906c41SOllivier Robert " NO )\n" 278ea906c41SOllivier Robert " OPT_ARG_VAL=''\n" 279ea906c41SOllivier Robert " ;;\n\n" 280ea906c41SOllivier Robert " YES )\n" 281ea906c41SOllivier Robert " if [ -z \"${OPT_ARG_VAL}\" ]\n" 282ea906c41SOllivier Robert " then\n" 283ea906c41SOllivier Robert " if [ $# -eq 0 ]\n" 284ea906c41SOllivier Robert " then\n" 285ea906c41SOllivier Robert " echo No argument provided for ${OPT_NAME} option >&2\n" 286ea906c41SOllivier Robert " echo \"$%s_USAGE_TEXT\"\n" 287ea906c41SOllivier Robert " exit 1\n" 288ea906c41SOllivier Robert " fi\n\n" 289ea906c41SOllivier Robert " OPT_ARG_VAL=\"${OPT_ARG}\"\n" 290ea906c41SOllivier Robert " shift\n" 291ea906c41SOllivier Robert " OPT_ARG=\"$1\"\n" 292ea906c41SOllivier Robert " fi\n" 293ea906c41SOllivier Robert " ;;\n\n" 294ea906c41SOllivier Robert " OK )\n" 295ea906c41SOllivier Robert " if [ -z \"${OPT_ARG_VAL}\" ] && [ $# -gt 0 ]\n" 296ea906c41SOllivier Robert " then\n" 297ea906c41SOllivier Robert " case \"${OPT_ARG}\" in -* ) ;; * )\n" 298ea906c41SOllivier Robert " OPT_ARG_VAL=\"${OPT_ARG}\"\n" 299ea906c41SOllivier Robert " shift\n" 300ea906c41SOllivier Robert " OPT_ARG=\"$1\" ;; esac\n" 301ea906c41SOllivier Robert " fi\n" 302ea906c41SOllivier Robert " ;;\n" 303ea906c41SOllivier Robert " esac\n"; 304ea906c41SOllivier Robert 305ea906c41SOllivier Robert /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 306ea906c41SOllivier Robert * 307ea906c41SOllivier Robert * FLAG OPTION PROCESSING 308ea906c41SOllivier Robert * 309ea906c41SOllivier Robert * Formats for emitting the text for handling flag option types 310ea906c41SOllivier Robert */ 311ea906c41SOllivier Robert tSCC zFlagOptInit[] = 312ea906c41SOllivier Robert " OPT_CODE=`echo \"X${OPT_ARG}\" | sed 's/X-\\(.\\).*/\\1/'`\n" 313ea906c41SOllivier Robert " OPT_ARG=` echo \"X${OPT_ARG}\" | sed 's/X-.//'`\n\n"; 314ea906c41SOllivier Robert 315ea906c41SOllivier Robert tSCC zFlagOptArg[] = 316ea906c41SOllivier Robert " case \"${OPT_ARG_NEEDED}\" in\n" 317ea906c41SOllivier Robert " NO )\n" 318ea906c41SOllivier Robert " if [ -n \"${OPT_ARG}\" ]\n" 319ea906c41SOllivier Robert " then\n" 320ea906c41SOllivier Robert " OPT_ARG=-\"${OPT_ARG}\"\n" 321ea906c41SOllivier Robert " else\n" 322ea906c41SOllivier Robert " shift\n" 323ea906c41SOllivier Robert " OPT_ARG=\"$1\"\n" 324ea906c41SOllivier Robert " fi\n" 325ea906c41SOllivier Robert " ;;\n\n" 326ea906c41SOllivier Robert " YES )\n" 327ea906c41SOllivier Robert " if [ -n \"${OPT_ARG}\" ]\n" 328ea906c41SOllivier Robert " then\n" 329ea906c41SOllivier Robert " OPT_ARG_VAL=\"${OPT_ARG}\"\n\n" 330ea906c41SOllivier Robert " else\n" 331ea906c41SOllivier Robert " if [ $# -eq 0 ]\n" 332ea906c41SOllivier Robert " then\n" 333ea906c41SOllivier Robert " echo No argument provided for ${OPT_NAME} option >&2\n" 334ea906c41SOllivier Robert " echo \"$%s_USAGE_TEXT\"\n" 335ea906c41SOllivier Robert " exit 1\n" 336ea906c41SOllivier Robert " fi\n" 337ea906c41SOllivier Robert " shift\n" 338ea906c41SOllivier Robert " OPT_ARG_VAL=\"$1\"\n" 339ea906c41SOllivier Robert " fi\n\n" 340ea906c41SOllivier Robert " shift\n" 341ea906c41SOllivier Robert " OPT_ARG=\"$1\"\n" 342ea906c41SOllivier Robert " ;;\n\n" 343ea906c41SOllivier Robert " OK )\n" 344ea906c41SOllivier Robert " if [ -n \"${OPT_ARG}\" ]\n" 345ea906c41SOllivier Robert " then\n" 346ea906c41SOllivier Robert " OPT_ARG_VAL=\"${OPT_ARG}\"\n" 347ea906c41SOllivier Robert " shift\n" 348ea906c41SOllivier Robert " OPT_ARG=\"$1\"\n\n" 349ea906c41SOllivier Robert " else\n" 350ea906c41SOllivier Robert " shift\n" 351ea906c41SOllivier Robert " if [ $# -gt 0 ]\n" 352ea906c41SOllivier Robert " then\n" 353ea906c41SOllivier Robert " case \"$1\" in -* ) ;; * )\n" 354ea906c41SOllivier Robert " OPT_ARG_VAL=\"$1\"\n" 355ea906c41SOllivier Robert " shift ;; esac\n" 356ea906c41SOllivier Robert " OPT_ARG=\"$1\"\n" 357ea906c41SOllivier Robert " fi\n" 358ea906c41SOllivier Robert " fi\n" 359ea906c41SOllivier Robert " ;;\n" 360ea906c41SOllivier Robert " esac\n"; 361ea906c41SOllivier Robert 362ea906c41SOllivier Robert tSCC* pzShell = NULL; 363ea906c41SOllivier Robert static char* pzLeader = NULL; 364ea906c41SOllivier Robert static char* pzTrailer = NULL; 365ea906c41SOllivier Robert 366ea906c41SOllivier Robert /* = = = START-STATIC-FORWARD = = = */ 367ea906c41SOllivier Robert /* static forward declarations maintained by :mkfwd */ 368ea906c41SOllivier Robert static void 369ea906c41SOllivier Robert textToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD ); 370ea906c41SOllivier Robert 371ea906c41SOllivier Robert static void 372ea906c41SOllivier Robert emitUsage( tOptions* pOpts ); 373ea906c41SOllivier Robert 374ea906c41SOllivier Robert static void 375ea906c41SOllivier Robert emitSetup( tOptions* pOpts ); 376ea906c41SOllivier Robert 377ea906c41SOllivier Robert static void 378ea906c41SOllivier Robert printOptionAction( tOptions* pOpts, tOptDesc* pOptDesc ); 379ea906c41SOllivier Robert 380ea906c41SOllivier Robert static void 381ea906c41SOllivier Robert printOptionInaction( tOptions* pOpts, tOptDesc* pOptDesc ); 382ea906c41SOllivier Robert 383ea906c41SOllivier Robert static void 384ea906c41SOllivier Robert emitFlag( tOptions* pOpts ); 385ea906c41SOllivier Robert 386ea906c41SOllivier Robert static void 387ea906c41SOllivier Robert emitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts ); 388ea906c41SOllivier Robert 389ea906c41SOllivier Robert static void 390ea906c41SOllivier Robert emitLong( tOptions* pOpts ); 391ea906c41SOllivier Robert 392ea906c41SOllivier Robert static void 393ea906c41SOllivier Robert openOutput( char const* pzFile ); 394ea906c41SOllivier Robert /* = = = END-STATIC-FORWARD = = = */ 395ea906c41SOllivier Robert 396ea906c41SOllivier Robert /*=export_func optionParseShell 397ea906c41SOllivier Robert * private: 398ea906c41SOllivier Robert * 399ea906c41SOllivier Robert * what: Decipher a boolean value 400ea906c41SOllivier Robert * arg: + tOptions* + pOpts + program options descriptor + 401ea906c41SOllivier Robert * 402ea906c41SOllivier Robert * doc: 403ea906c41SOllivier Robert * Emit a shell script that will parse the command line options. 404ea906c41SOllivier Robert =*/ 405ea906c41SOllivier Robert void 406ea906c41SOllivier Robert optionParseShell( tOptions* pOpts ) 407ea906c41SOllivier Robert { 408ea906c41SOllivier Robert /* 409ea906c41SOllivier Robert * Check for our SHELL option now. 410ea906c41SOllivier Robert * IF the output file contains the "#!" magic marker, 411ea906c41SOllivier Robert * it will override anything we do here. 412ea906c41SOllivier Robert */ 413ea906c41SOllivier Robert if (HAVE_OPT( SHELL )) 414ea906c41SOllivier Robert pzShell = OPT_ARG( SHELL ); 415ea906c41SOllivier Robert 416ea906c41SOllivier Robert else if (! ENABLED_OPT( SHELL )) 417ea906c41SOllivier Robert pzShell = NULL; 418ea906c41SOllivier Robert 419ea906c41SOllivier Robert else if ((pzShell = getenv( "SHELL" )), 420ea906c41SOllivier Robert pzShell == NULL) 421ea906c41SOllivier Robert 422ea906c41SOllivier Robert pzShell = "/bin/sh"; 423ea906c41SOllivier Robert 424ea906c41SOllivier Robert /* 425ea906c41SOllivier Robert * Check for a specified output file 426ea906c41SOllivier Robert */ 427ea906c41SOllivier Robert if (HAVE_OPT( SCRIPT )) 428ea906c41SOllivier Robert openOutput( OPT_ARG( SCRIPT )); 429ea906c41SOllivier Robert 430ea906c41SOllivier Robert emitUsage( pOpts ); 431ea906c41SOllivier Robert emitSetup( pOpts ); 432ea906c41SOllivier Robert 433ea906c41SOllivier Robert /* 434ea906c41SOllivier Robert * There are four modes of option processing. 435ea906c41SOllivier Robert */ 436ea906c41SOllivier Robert switch (pOpts->fOptSet & (OPTPROC_LONGOPT|OPTPROC_SHORTOPT)) { 437ea906c41SOllivier Robert case OPTPROC_LONGOPT: 438ea906c41SOllivier Robert fputs( zLoopCase, stdout ); 439ea906c41SOllivier Robert 440ea906c41SOllivier Robert fputs( zLongSelection, stdout ); 441ea906c41SOllivier Robert fputs( zLongOptInit, stdout ); 442ea906c41SOllivier Robert emitLong( pOpts ); 443ea906c41SOllivier Robert printf( zLongOptArg, pOpts->pzPROGNAME ); 444ea906c41SOllivier Robert fputs( zEndSelection, stdout ); 445ea906c41SOllivier Robert 446ea906c41SOllivier Robert fputs( zNoSelection, stdout ); 447ea906c41SOllivier Robert break; 448ea906c41SOllivier Robert 449ea906c41SOllivier Robert case 0: 450ea906c41SOllivier Robert fputs( zLoopOnly, stdout ); 451ea906c41SOllivier Robert fputs( zLongOptInit, stdout ); 452ea906c41SOllivier Robert emitLong( pOpts ); 453ea906c41SOllivier Robert printf( zLongOptArg, pOpts->pzPROGNAME ); 454ea906c41SOllivier Robert break; 455ea906c41SOllivier Robert 456ea906c41SOllivier Robert case OPTPROC_SHORTOPT: 457ea906c41SOllivier Robert fputs( zLoopCase, stdout ); 458ea906c41SOllivier Robert 459ea906c41SOllivier Robert fputs( zFlagSelection, stdout ); 460ea906c41SOllivier Robert fputs( zFlagOptInit, stdout ); 461ea906c41SOllivier Robert emitFlag( pOpts ); 462ea906c41SOllivier Robert printf( zFlagOptArg, pOpts->pzPROGNAME ); 463ea906c41SOllivier Robert fputs( zEndSelection, stdout ); 464ea906c41SOllivier Robert 465ea906c41SOllivier Robert fputs( zNoSelection, stdout ); 466ea906c41SOllivier Robert break; 467ea906c41SOllivier Robert 468ea906c41SOllivier Robert case OPTPROC_LONGOPT|OPTPROC_SHORTOPT: 469ea906c41SOllivier Robert fputs( zLoopCase, stdout ); 470ea906c41SOllivier Robert 471ea906c41SOllivier Robert fputs( zLongSelection, stdout ); 472ea906c41SOllivier Robert fputs( zLongOptInit, stdout ); 473ea906c41SOllivier Robert emitLong( pOpts ); 474ea906c41SOllivier Robert printf( zLongOptArg, pOpts->pzPROGNAME ); 475ea906c41SOllivier Robert fputs( zEndSelection, stdout ); 476ea906c41SOllivier Robert 477ea906c41SOllivier Robert fputs( zFlagSelection, stdout ); 478ea906c41SOllivier Robert fputs( zFlagOptInit, stdout ); 479ea906c41SOllivier Robert emitFlag( pOpts ); 480ea906c41SOllivier Robert printf( zFlagOptArg, pOpts->pzPROGNAME ); 481ea906c41SOllivier Robert fputs( zEndSelection, stdout ); 482ea906c41SOllivier Robert 483ea906c41SOllivier Robert fputs( zNoSelection, stdout ); 484ea906c41SOllivier Robert break; 485ea906c41SOllivier Robert } 486ea906c41SOllivier Robert 487ea906c41SOllivier Robert printf( zLoopEnd, pOpts->pzPROGNAME, zTrailerMarker ); 488ea906c41SOllivier Robert if ((pzTrailer != NULL) && (*pzTrailer != '\0')) 489ea906c41SOllivier Robert fputs( pzTrailer, stdout ); 490ea906c41SOllivier Robert else if (ENABLED_OPT( SHELL )) 491ea906c41SOllivier Robert printf( "\nenv | grep '^%s_'\n", pOpts->pzPROGNAME ); 492ea906c41SOllivier Robert 493ea906c41SOllivier Robert fflush( stdout ); 494ea906c41SOllivier Robert fchmod( STDOUT_FILENO, 0755 ); 495ea906c41SOllivier Robert fclose( stdout ); 496ea906c41SOllivier Robert } 497ea906c41SOllivier Robert 498ea906c41SOllivier Robert 499ea906c41SOllivier Robert static void 500ea906c41SOllivier Robert textToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD ) 501ea906c41SOllivier Robert { 502ea906c41SOllivier Robert # define _TT_(n) tSCC z ## n [] = #n; 503ea906c41SOllivier Robert TEXTTO_TABLE 504ea906c41SOllivier Robert # undef _TT_ 505ea906c41SOllivier Robert # define _TT_(n) z ## n , 506ea906c41SOllivier Robert static char const* apzTTNames[] = { TEXTTO_TABLE }; 507ea906c41SOllivier Robert # undef _TT_ 508ea906c41SOllivier Robert 509ea906c41SOllivier Robert #if defined(__windows__) && !defined(__CYGWIN__) 510ea906c41SOllivier Robert printf( "%1$s_%2$s_TEXT='no %2$s text'\n", 511ea906c41SOllivier Robert pOpts->pzPROGNAME, apzTTNames[ whichVar ]); 512ea906c41SOllivier Robert #else 513ea906c41SOllivier Robert int nlHoldCt = 0; 514ea906c41SOllivier Robert int pipeFd[2]; 515ea906c41SOllivier Robert FILE* fp; 516ea906c41SOllivier Robert 517ea906c41SOllivier Robert printf( "%s_%s_TEXT='", pOpts->pzPROGNAME, apzTTNames[ whichVar ]); 518ea906c41SOllivier Robert fflush( stdout ); 519ea906c41SOllivier Robert 520ea906c41SOllivier Robert if (pipe( pipeFd ) != 0) { 521ea906c41SOllivier Robert fprintf( stderr, zBadPipe, errno, strerror( errno )); 522ea906c41SOllivier Robert exit( EXIT_FAILURE ); 523ea906c41SOllivier Robert } 524ea906c41SOllivier Robert 525ea906c41SOllivier Robert switch (fork()) { 526ea906c41SOllivier Robert case -1: 527ea906c41SOllivier Robert fprintf( stderr, zForkFail, errno, strerror(errno), pOpts->pzProgName); 528ea906c41SOllivier Robert exit( EXIT_FAILURE ); 529ea906c41SOllivier Robert break; 530ea906c41SOllivier Robert 531ea906c41SOllivier Robert case 0: 532ea906c41SOllivier Robert dup2( pipeFd[1], STDERR_FILENO ); 533ea906c41SOllivier Robert dup2( pipeFd[1], STDOUT_FILENO ); 534ea906c41SOllivier Robert close( pipeFd[0] ); 535ea906c41SOllivier Robert 536ea906c41SOllivier Robert switch (whichVar) { 537ea906c41SOllivier Robert case TT_LONGUSAGE: 538ea906c41SOllivier Robert (*(pOpts->pUsageProc))( pOpts, EXIT_SUCCESS ); 539ea906c41SOllivier Robert /* NOTREACHED */ 540ea906c41SOllivier Robert exit( EXIT_FAILURE ); 541ea906c41SOllivier Robert 542ea906c41SOllivier Robert case TT_USAGE: 543ea906c41SOllivier Robert (*(pOpts->pUsageProc))( pOpts, EXIT_FAILURE ); 544ea906c41SOllivier Robert /* NOTREACHED */ 545ea906c41SOllivier Robert exit( EXIT_FAILURE ); 546ea906c41SOllivier Robert 547ea906c41SOllivier Robert case TT_VERSION: 548ea906c41SOllivier Robert if (pOD->fOptState & OPTST_ALLOC_ARG) { 549ea906c41SOllivier Robert AGFREE(pOD->optArg.argString); 550ea906c41SOllivier Robert pOD->fOptState &= ~OPTST_ALLOC_ARG; 551ea906c41SOllivier Robert } 552ea906c41SOllivier Robert pOD->optArg.argString = "c"; 553ea906c41SOllivier Robert optionPrintVersion( pOpts, pOD ); 554ea906c41SOllivier Robert /* NOTREACHED */ 555ea906c41SOllivier Robert 556ea906c41SOllivier Robert default: 557ea906c41SOllivier Robert exit( EXIT_FAILURE ); 558ea906c41SOllivier Robert } 559ea906c41SOllivier Robert 560ea906c41SOllivier Robert default: 561ea906c41SOllivier Robert close( pipeFd[1] ); 562ea906c41SOllivier Robert fp = fdopen( pipeFd[0], "r" FOPEN_BINARY_FLAG ); 563ea906c41SOllivier Robert } 564ea906c41SOllivier Robert 565ea906c41SOllivier Robert for (;;) { 566ea906c41SOllivier Robert int ch = fgetc( fp ); 567ea906c41SOllivier Robert switch (ch) { 568ea906c41SOllivier Robert 569ea906c41SOllivier Robert case '\n': 570ea906c41SOllivier Robert nlHoldCt++; 571ea906c41SOllivier Robert break; 572ea906c41SOllivier Robert 573ea906c41SOllivier Robert case '\'': 574ea906c41SOllivier Robert while (nlHoldCt > 0) { 575ea906c41SOllivier Robert fputc( '\n', stdout ); 576ea906c41SOllivier Robert nlHoldCt--; 577ea906c41SOllivier Robert } 578ea906c41SOllivier Robert fputs( "'\\''", stdout ); 579ea906c41SOllivier Robert break; 580ea906c41SOllivier Robert 581ea906c41SOllivier Robert case EOF: 582ea906c41SOllivier Robert goto endCharLoop; 583ea906c41SOllivier Robert 584ea906c41SOllivier Robert default: 585ea906c41SOllivier Robert while (nlHoldCt > 0) { 586ea906c41SOllivier Robert fputc( '\n', stdout ); 587ea906c41SOllivier Robert nlHoldCt--; 588ea906c41SOllivier Robert } 589ea906c41SOllivier Robert fputc( ch, stdout ); 590ea906c41SOllivier Robert break; 591ea906c41SOllivier Robert } 592ea906c41SOllivier Robert } endCharLoop:; 593ea906c41SOllivier Robert 594ea906c41SOllivier Robert fputs( "'\n\n", stdout ); 595ea906c41SOllivier Robert close( pipeFd[0] ); 596ea906c41SOllivier Robert #endif 597ea906c41SOllivier Robert } 598ea906c41SOllivier Robert 599ea906c41SOllivier Robert 600ea906c41SOllivier Robert static void 601ea906c41SOllivier Robert emitUsage( tOptions* pOpts ) 602ea906c41SOllivier Robert { 603ea906c41SOllivier Robert char zTimeBuf[ AO_NAME_SIZE ]; 604ea906c41SOllivier Robert 605ea906c41SOllivier Robert /* 606ea906c41SOllivier Robert * First, switch stdout to the output file name. 607ea906c41SOllivier Robert * Then, change the program name to the one defined 608ea906c41SOllivier Robert * by the definitions (rather than the current 609ea906c41SOllivier Robert * executable name). Down case the upper cased name. 610ea906c41SOllivier Robert */ 611ea906c41SOllivier Robert if (pzLeader != NULL) 612ea906c41SOllivier Robert fputs( pzLeader, stdout ); 613ea906c41SOllivier Robert 614ea906c41SOllivier Robert { 615ea906c41SOllivier Robert tSCC zStdout[] = "stdout"; 616ea906c41SOllivier Robert tCC* pzOutName; 617ea906c41SOllivier Robert 618ea906c41SOllivier Robert { 619ea906c41SOllivier Robert time_t curTime = time( NULL ); 620ea906c41SOllivier Robert struct tm* pTime = localtime( &curTime ); 621ea906c41SOllivier Robert strftime(zTimeBuf, AO_NAME_SIZE, "%A %B %e, %Y at %r %Z", pTime ); 622ea906c41SOllivier Robert } 623ea906c41SOllivier Robert 624ea906c41SOllivier Robert if (HAVE_OPT( SCRIPT )) 625ea906c41SOllivier Robert pzOutName = OPT_ARG( SCRIPT ); 626ea906c41SOllivier Robert else pzOutName = zStdout; 627ea906c41SOllivier Robert 628ea906c41SOllivier Robert if ((pzLeader == NULL) && (pzShell != NULL)) 629ea906c41SOllivier Robert printf( "#! %s\n", pzShell ); 630ea906c41SOllivier Robert 631ea906c41SOllivier Robert printf( zPreamble, zStartMarker, pzOutName, zTimeBuf ); 632ea906c41SOllivier Robert } 633ea906c41SOllivier Robert 634ea906c41SOllivier Robert /* 635ea906c41SOllivier Robert * Get a copy of the original program name in lower case 636ea906c41SOllivier Robert */ 637ea906c41SOllivier Robert { 638ea906c41SOllivier Robert char* pzPN = zTimeBuf; 639ea906c41SOllivier Robert tCC* pz = pOpts->pzPROGNAME; 640ea906c41SOllivier Robert for (;;) { 641ea906c41SOllivier Robert if ((*pzPN++ = tolower( *pz++ )) == '\0') 642ea906c41SOllivier Robert break; 643ea906c41SOllivier Robert } 644ea906c41SOllivier Robert } 645ea906c41SOllivier Robert 646ea906c41SOllivier Robert printf( zEndPreamble, pOpts->pzPROGNAME ); 647ea906c41SOllivier Robert 648ea906c41SOllivier Robert pOpts->pzProgPath = pOpts->pzProgName = zTimeBuf; 649ea906c41SOllivier Robert textToVariable( pOpts, TT_LONGUSAGE, NULL ); 650ea906c41SOllivier Robert textToVariable( pOpts, TT_USAGE, NULL ); 651ea906c41SOllivier Robert 652ea906c41SOllivier Robert { 653ea906c41SOllivier Robert tOptDesc* pOptDesc = pOpts->pOptDesc; 654ea906c41SOllivier Robert int optionCt = pOpts->optCt; 655ea906c41SOllivier Robert 656ea906c41SOllivier Robert for (;;) { 657ea906c41SOllivier Robert if (pOptDesc->pOptProc == optionPrintVersion) { 658ea906c41SOllivier Robert textToVariable( pOpts, TT_VERSION, pOptDesc ); 659ea906c41SOllivier Robert break; 660ea906c41SOllivier Robert } 661ea906c41SOllivier Robert 662ea906c41SOllivier Robert if (--optionCt <= 0) 663ea906c41SOllivier Robert break; 664ea906c41SOllivier Robert pOptDesc++; 665ea906c41SOllivier Robert } 666ea906c41SOllivier Robert } 667ea906c41SOllivier Robert } 668ea906c41SOllivier Robert 669ea906c41SOllivier Robert 670ea906c41SOllivier Robert static void 671ea906c41SOllivier Robert emitSetup( tOptions* pOpts ) 672ea906c41SOllivier Robert { 673ea906c41SOllivier Robert tOptDesc* pOptDesc = pOpts->pOptDesc; 674ea906c41SOllivier Robert int optionCt = pOpts->presetOptCt; 675ea906c41SOllivier Robert char const* pzFmt; 676ea906c41SOllivier Robert char const* pzDefault; 677ea906c41SOllivier Robert 678ea906c41SOllivier Robert for (;optionCt > 0; pOptDesc++, --optionCt) { 679ea906c41SOllivier Robert char zVal[16]; 680ea906c41SOllivier Robert 681ea906c41SOllivier Robert /* 682ea906c41SOllivier Robert * Options that are either usage documentation or are compiled out 683ea906c41SOllivier Robert * are not to be processed. 684ea906c41SOllivier Robert */ 685ea906c41SOllivier Robert if (SKIP_OPT(pOptDesc) || (pOptDesc->pz_NAME == NULL)) 686ea906c41SOllivier Robert continue; 687ea906c41SOllivier Robert 688ea906c41SOllivier Robert if (pOptDesc->optMaxCt > 1) 689ea906c41SOllivier Robert pzFmt = zMultiDef; 690ea906c41SOllivier Robert else pzFmt = zSingleDef; 691ea906c41SOllivier Robert 692ea906c41SOllivier Robert /* 693ea906c41SOllivier Robert * IF this is an enumeration/bitmask option, then convert the value 694ea906c41SOllivier Robert * to a string before printing the default value. 695ea906c41SOllivier Robert */ 696ea906c41SOllivier Robert switch (OPTST_GET_ARGTYPE(pOptDesc->fOptState)) { 697ea906c41SOllivier Robert case OPARG_TYPE_ENUMERATION: 698ea906c41SOllivier Robert (*(pOptDesc->pOptProc))( (tOptions*)2UL, pOptDesc ); 699ea906c41SOllivier Robert pzDefault = pOptDesc->optArg.argString; 700ea906c41SOllivier Robert break; 701ea906c41SOllivier Robert 702ea906c41SOllivier Robert /* 703ea906c41SOllivier Robert * Numeric and membership bit options are just printed as a number. 704ea906c41SOllivier Robert */ 705ea906c41SOllivier Robert case OPARG_TYPE_NUMERIC: 706ea906c41SOllivier Robert snprintf( zVal, sizeof( zVal ), "%d", 707ea906c41SOllivier Robert (int)pOptDesc->optArg.argInt ); 708ea906c41SOllivier Robert pzDefault = zVal; 709ea906c41SOllivier Robert break; 710ea906c41SOllivier Robert 711ea906c41SOllivier Robert case OPARG_TYPE_MEMBERSHIP: 712ea906c41SOllivier Robert snprintf( zVal, sizeof( zVal ), "%lu", 713ea906c41SOllivier Robert (unsigned long)pOptDesc->optArg.argIntptr ); 714ea906c41SOllivier Robert pzDefault = zVal; 715ea906c41SOllivier Robert break; 716ea906c41SOllivier Robert 717ea906c41SOllivier Robert case OPARG_TYPE_BOOLEAN: 718ea906c41SOllivier Robert pzDefault = (pOptDesc->optArg.argBool) ? "true" : "false"; 719ea906c41SOllivier Robert break; 720ea906c41SOllivier Robert 721ea906c41SOllivier Robert default: 722ea906c41SOllivier Robert if (pOptDesc->optArg.argString == NULL) { 723ea906c41SOllivier Robert if (pzFmt == zSingleDef) 724ea906c41SOllivier Robert pzFmt = zSingleNoDef; 725ea906c41SOllivier Robert pzDefault = NULL; 726ea906c41SOllivier Robert } 727ea906c41SOllivier Robert else 728ea906c41SOllivier Robert pzDefault = pOptDesc->optArg.argString; 729ea906c41SOllivier Robert } 730ea906c41SOllivier Robert 731ea906c41SOllivier Robert printf( pzFmt, pOpts->pzPROGNAME, pOptDesc->pz_NAME, pzDefault ); 732ea906c41SOllivier Robert } 733ea906c41SOllivier Robert } 734ea906c41SOllivier Robert 735ea906c41SOllivier Robert 736ea906c41SOllivier Robert static void 737ea906c41SOllivier Robert printOptionAction( tOptions* pOpts, tOptDesc* pOptDesc ) 738ea906c41SOllivier Robert { 739ea906c41SOllivier Robert if (pOptDesc->pOptProc == optionPrintVersion) 740ea906c41SOllivier Robert printf( zTextExit, pOpts->pzPROGNAME, "VERSION" ); 741ea906c41SOllivier Robert 742ea906c41SOllivier Robert else if (pOptDesc->pOptProc == optionPagedUsage) 743ea906c41SOllivier Robert printf( zPagedUsageExit, pOpts->pzPROGNAME ); 744ea906c41SOllivier Robert 745ea906c41SOllivier Robert else if (pOptDesc->pOptProc == optionLoadOpt) { 746ea906c41SOllivier Robert printf( zCmdFmt, "echo 'Warning: Cannot load options files' >&2" ); 747ea906c41SOllivier Robert printf( zCmdFmt, "OPT_ARG_NEEDED=YES" ); 748ea906c41SOllivier Robert 749ea906c41SOllivier Robert } else if (pOptDesc->pz_NAME == NULL) { 750ea906c41SOllivier Robert 751ea906c41SOllivier Robert if (pOptDesc->pOptProc == NULL) { 752ea906c41SOllivier Robert printf( zCmdFmt, "echo 'Warning: Cannot save options files' " 753ea906c41SOllivier Robert ">&2" ); 754ea906c41SOllivier Robert printf( zCmdFmt, "OPT_ARG_NEEDED=OK" ); 755ea906c41SOllivier Robert } else 756ea906c41SOllivier Robert printf( zTextExit, pOpts->pzPROGNAME, "LONGUSAGE" ); 757ea906c41SOllivier Robert 758ea906c41SOllivier Robert } else { 759ea906c41SOllivier Robert if (pOptDesc->optMaxCt == 1) 760ea906c41SOllivier Robert printf( zSingleArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME ); 761ea906c41SOllivier Robert else { 762ea906c41SOllivier Robert if ((unsigned)pOptDesc->optMaxCt < NOLIMIT) 763ea906c41SOllivier Robert printf( zCountTest, pOpts->pzPROGNAME, 764ea906c41SOllivier Robert pOptDesc->pz_NAME, pOptDesc->optMaxCt ); 765ea906c41SOllivier Robert 766ea906c41SOllivier Robert printf( zMultiArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME ); 767ea906c41SOllivier Robert } 768ea906c41SOllivier Robert 769ea906c41SOllivier Robert /* 770ea906c41SOllivier Robert * Fix up the args. 771ea906c41SOllivier Robert */ 772ea906c41SOllivier Robert if (OPTST_GET_ARGTYPE(pOptDesc->fOptState) == OPARG_TYPE_NONE) { 773ea906c41SOllivier Robert printf( zCantArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME ); 774ea906c41SOllivier Robert 775ea906c41SOllivier Robert } else if (pOptDesc->fOptState & OPTST_ARG_OPTIONAL) { 776ea906c41SOllivier Robert printf( zMayArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME ); 777ea906c41SOllivier Robert 778ea906c41SOllivier Robert } else { 779ea906c41SOllivier Robert fputs( zMustArg, stdout ); 780ea906c41SOllivier Robert } 781ea906c41SOllivier Robert } 782ea906c41SOllivier Robert fputs( zOptionEndSelect, stdout ); 783ea906c41SOllivier Robert } 784ea906c41SOllivier Robert 785ea906c41SOllivier Robert 786ea906c41SOllivier Robert static void 787ea906c41SOllivier Robert printOptionInaction( tOptions* pOpts, tOptDesc* pOptDesc ) 788ea906c41SOllivier Robert { 789ea906c41SOllivier Robert if (pOptDesc->pOptProc == optionLoadOpt) { 790ea906c41SOllivier Robert printf( zCmdFmt, "echo 'Warning: Cannot suppress the loading of " 791ea906c41SOllivier Robert "options files' >&2" ); 792ea906c41SOllivier Robert 793ea906c41SOllivier Robert } else if (pOptDesc->optMaxCt == 1) 794ea906c41SOllivier Robert printf( zNoSingleArg, pOpts->pzPROGNAME, 795ea906c41SOllivier Robert pOptDesc->pz_NAME, pOptDesc->pz_DisablePfx ); 796ea906c41SOllivier Robert else 797ea906c41SOllivier Robert printf( zNoMultiArg, pOpts->pzPROGNAME, 798ea906c41SOllivier Robert pOptDesc->pz_NAME, pOptDesc->pz_DisablePfx ); 799ea906c41SOllivier Robert 800ea906c41SOllivier Robert printf( zCmdFmt, "OPT_ARG_NEEDED=NO" ); 801ea906c41SOllivier Robert fputs( zOptionEndSelect, stdout ); 802ea906c41SOllivier Robert } 803ea906c41SOllivier Robert 804ea906c41SOllivier Robert 805ea906c41SOllivier Robert static void 806ea906c41SOllivier Robert emitFlag( tOptions* pOpts ) 807ea906c41SOllivier Robert { 808ea906c41SOllivier Robert tOptDesc* pOptDesc = pOpts->pOptDesc; 809ea906c41SOllivier Robert int optionCt = pOpts->optCt; 810ea906c41SOllivier Robert 811ea906c41SOllivier Robert fputs( zOptionCase, stdout ); 812ea906c41SOllivier Robert 813ea906c41SOllivier Robert for (;optionCt > 0; pOptDesc++, --optionCt) { 814ea906c41SOllivier Robert 815ea906c41SOllivier Robert if (SKIP_OPT(pOptDesc)) 816ea906c41SOllivier Robert continue; 817ea906c41SOllivier Robert 818ea906c41SOllivier Robert if (isprint( pOptDesc->optValue )) { 819ea906c41SOllivier Robert printf( zOptionFlag, pOptDesc->optValue ); 820ea906c41SOllivier Robert printOptionAction( pOpts, pOptDesc ); 821ea906c41SOllivier Robert } 822ea906c41SOllivier Robert } 823ea906c41SOllivier Robert printf( zOptionUnknown, "flag", pOpts->pzPROGNAME ); 824ea906c41SOllivier Robert } 825ea906c41SOllivier Robert 826ea906c41SOllivier Robert 827ea906c41SOllivier Robert /* 828ea906c41SOllivier Robert * Emit the match text for a long option 829ea906c41SOllivier Robert */ 830ea906c41SOllivier Robert static void 831ea906c41SOllivier Robert emitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts ) 832ea906c41SOllivier Robert { 833ea906c41SOllivier Robert tOptDesc* pOD = pOpts->pOptDesc; 834ea906c41SOllivier Robert int oCt = pOpts->optCt; 835ea906c41SOllivier Robert int min = 1; 836ea906c41SOllivier Robert char zName[ 256 ]; 837ea906c41SOllivier Robert char* pz = zName; 838ea906c41SOllivier Robert 839ea906c41SOllivier Robert for (;;) { 840ea906c41SOllivier Robert int matchCt = 0; 841ea906c41SOllivier Robert 842ea906c41SOllivier Robert /* 843ea906c41SOllivier Robert * Omit the current option, Documentation opts and compiled out opts. 844ea906c41SOllivier Robert */ 845ea906c41SOllivier Robert if ((pOD == pCurOpt) || SKIP_OPT(pOD)){ 846ea906c41SOllivier Robert if (--oCt <= 0) 847ea906c41SOllivier Robert break; 848ea906c41SOllivier Robert pOD++; 849ea906c41SOllivier Robert continue; 850ea906c41SOllivier Robert } 851ea906c41SOllivier Robert 852ea906c41SOllivier Robert /* 853ea906c41SOllivier Robert * Check each character of the name case insensitively. 854ea906c41SOllivier Robert * They must not be the same. They cannot be, because it would 855ea906c41SOllivier Robert * not compile correctly if they were. 856ea906c41SOllivier Robert */ 857ea906c41SOllivier Robert while ( toupper( pOD->pz_Name[matchCt] ) 858ea906c41SOllivier Robert == toupper( pzMatchName[matchCt] )) 859ea906c41SOllivier Robert matchCt++; 860ea906c41SOllivier Robert 861ea906c41SOllivier Robert if (matchCt > min) 862ea906c41SOllivier Robert min = matchCt; 863ea906c41SOllivier Robert 864ea906c41SOllivier Robert /* 865ea906c41SOllivier Robert * Check the disablement name, too. 866ea906c41SOllivier Robert */ 867ea906c41SOllivier Robert if (pOD->pz_DisableName != NULL) { 868ea906c41SOllivier Robert matchCt = 0; 869ea906c41SOllivier Robert while ( toupper( pOD->pz_DisableName[matchCt] ) 870ea906c41SOllivier Robert == toupper( pzMatchName[matchCt] )) 871ea906c41SOllivier Robert matchCt++; 872ea906c41SOllivier Robert if (matchCt > min) 873ea906c41SOllivier Robert min = matchCt; 874ea906c41SOllivier Robert } 875ea906c41SOllivier Robert if (--oCt <= 0) 876ea906c41SOllivier Robert break; 877ea906c41SOllivier Robert pOD++; 878ea906c41SOllivier Robert } 879ea906c41SOllivier Robert 880ea906c41SOllivier Robert /* 881ea906c41SOllivier Robert * IF the 'min' is all or one short of the name length, 882ea906c41SOllivier Robert * THEN the entire string must be matched. 883ea906c41SOllivier Robert */ 884ea906c41SOllivier Robert if ( (pzMatchName[min ] == NUL) 885ea906c41SOllivier Robert || (pzMatchName[min+1] == NUL) ) 886ea906c41SOllivier Robert printf( zOptionFullName, pzMatchName ); 887ea906c41SOllivier Robert 888ea906c41SOllivier Robert else { 889ea906c41SOllivier Robert int matchCt = 0; 890ea906c41SOllivier Robert for (; matchCt <= min; matchCt++) 891ea906c41SOllivier Robert *pz++ = pzMatchName[matchCt]; 892ea906c41SOllivier Robert 893ea906c41SOllivier Robert for (;;) { 894ea906c41SOllivier Robert *pz = NUL; 895ea906c41SOllivier Robert printf( zOptionPartName, zName ); 896ea906c41SOllivier Robert *pz++ = pzMatchName[matchCt++]; 897ea906c41SOllivier Robert if (pzMatchName[matchCt] == NUL) { 898ea906c41SOllivier Robert *pz = NUL; 899ea906c41SOllivier Robert printf( zOptionFullName, zName ); 900ea906c41SOllivier Robert break; 901ea906c41SOllivier Robert } 902ea906c41SOllivier Robert } 903ea906c41SOllivier Robert } 904ea906c41SOllivier Robert } 905ea906c41SOllivier Robert 906ea906c41SOllivier Robert 907ea906c41SOllivier Robert /* 908ea906c41SOllivier Robert * Emit GNU-standard long option handling code 909ea906c41SOllivier Robert */ 910ea906c41SOllivier Robert static void 911ea906c41SOllivier Robert emitLong( tOptions* pOpts ) 912ea906c41SOllivier Robert { 913ea906c41SOllivier Robert tOptDesc* pOD = pOpts->pOptDesc; 914ea906c41SOllivier Robert int ct = pOpts->optCt; 915ea906c41SOllivier Robert 916ea906c41SOllivier Robert fputs( zOptionCase, stdout ); 917ea906c41SOllivier Robert 918ea906c41SOllivier Robert /* 919ea906c41SOllivier Robert * do each option, ... 920ea906c41SOllivier Robert */ 921ea906c41SOllivier Robert do { 922ea906c41SOllivier Robert /* 923ea906c41SOllivier Robert * Documentation & compiled-out options 924ea906c41SOllivier Robert */ 925ea906c41SOllivier Robert if (SKIP_OPT(pOD)) 926ea906c41SOllivier Robert continue; 927ea906c41SOllivier Robert 928ea906c41SOllivier Robert emitMatchExpr( pOD->pz_Name, pOD, pOpts ); 929ea906c41SOllivier Robert printOptionAction( pOpts, pOD ); 930ea906c41SOllivier Robert 931ea906c41SOllivier Robert /* 932ea906c41SOllivier Robert * Now, do the same thing for the disablement version of the option. 933ea906c41SOllivier Robert */ 934ea906c41SOllivier Robert if (pOD->pz_DisableName != NULL) { 935ea906c41SOllivier Robert emitMatchExpr( pOD->pz_DisableName, pOD, pOpts ); 936ea906c41SOllivier Robert printOptionInaction( pOpts, pOD ); 937ea906c41SOllivier Robert } 938ea906c41SOllivier Robert } while (pOD++, --ct > 0); 939ea906c41SOllivier Robert 940ea906c41SOllivier Robert printf( zOptionUnknown, "option", pOpts->pzPROGNAME ); 941ea906c41SOllivier Robert } 942ea906c41SOllivier Robert 943ea906c41SOllivier Robert 944ea906c41SOllivier Robert static void 945ea906c41SOllivier Robert openOutput( char const* pzFile ) 946ea906c41SOllivier Robert { 947ea906c41SOllivier Robert FILE* fp; 948ea906c41SOllivier Robert char* pzData = NULL; 949ea906c41SOllivier Robert struct stat stbf; 950ea906c41SOllivier Robert 951ea906c41SOllivier Robert do { 952ea906c41SOllivier Robert char* pzScan; 953ea906c41SOllivier Robert size_t sizeLeft; 954ea906c41SOllivier Robert 955ea906c41SOllivier Robert /* 956ea906c41SOllivier Robert * IF we cannot stat the file, 957ea906c41SOllivier Robert * THEN assume we are creating a new file. 958ea906c41SOllivier Robert * Skip the loading of the old data. 959ea906c41SOllivier Robert */ 960ea906c41SOllivier Robert if (stat( pzFile, &stbf ) != 0) 961ea906c41SOllivier Robert break; 962ea906c41SOllivier Robert 963ea906c41SOllivier Robert /* 964ea906c41SOllivier Robert * The file must be a regular file 965ea906c41SOllivier Robert */ 966ea906c41SOllivier Robert if (! S_ISREG( stbf.st_mode )) { 967ea906c41SOllivier Robert fprintf( stderr, zNotFile, pzFile ); 968ea906c41SOllivier Robert exit( EXIT_FAILURE ); 969ea906c41SOllivier Robert } 970ea906c41SOllivier Robert 971ea906c41SOllivier Robert pzData = AGALOC(stbf.st_size + 1, "file data"); 972ea906c41SOllivier Robert fp = fopen( pzFile, "r" FOPEN_BINARY_FLAG ); 973ea906c41SOllivier Robert 974ea906c41SOllivier Robert sizeLeft = (unsigned)stbf.st_size; 975ea906c41SOllivier Robert pzScan = pzData; 976ea906c41SOllivier Robert 977ea906c41SOllivier Robert /* 978ea906c41SOllivier Robert * Read in all the data as fast as our OS will let us. 979ea906c41SOllivier Robert */ 980ea906c41SOllivier Robert for (;;) { 981ea906c41SOllivier Robert int inct = fread( (void*)pzScan, (size_t)1, sizeLeft, fp); 982ea906c41SOllivier Robert if (inct == 0) 983ea906c41SOllivier Robert break; 984ea906c41SOllivier Robert 985ea906c41SOllivier Robert pzScan += inct; 986ea906c41SOllivier Robert sizeLeft -= inct; 987ea906c41SOllivier Robert 988ea906c41SOllivier Robert if (sizeLeft == 0) 989ea906c41SOllivier Robert break; 990ea906c41SOllivier Robert } 991ea906c41SOllivier Robert 992ea906c41SOllivier Robert /* 993ea906c41SOllivier Robert * NUL-terminate the leader and look for the trailer 994ea906c41SOllivier Robert */ 995ea906c41SOllivier Robert *pzScan = '\0'; 996ea906c41SOllivier Robert fclose( fp ); 997ea906c41SOllivier Robert pzScan = strstr( pzData, zStartMarker ); 998ea906c41SOllivier Robert if (pzScan == NULL) { 999ea906c41SOllivier Robert pzTrailer = pzData; 1000ea906c41SOllivier Robert break; 1001ea906c41SOllivier Robert } 1002ea906c41SOllivier Robert 1003ea906c41SOllivier Robert *(pzScan++) = NUL; 1004ea906c41SOllivier Robert pzScan = strstr( pzScan, zTrailerMarker ); 1005ea906c41SOllivier Robert if (pzScan == NULL) { 1006ea906c41SOllivier Robert pzTrailer = pzData; 1007ea906c41SOllivier Robert break; 1008ea906c41SOllivier Robert } 1009ea906c41SOllivier Robert 1010ea906c41SOllivier Robert /* 1011ea906c41SOllivier Robert * Check to see if the data contains 1012ea906c41SOllivier Robert * our marker. If it does, then we will skip over it 1013ea906c41SOllivier Robert */ 1014ea906c41SOllivier Robert pzTrailer = pzScan + sizeof( zTrailerMarker ) - 1; 1015ea906c41SOllivier Robert pzLeader = pzData; 1016ea906c41SOllivier Robert } while (AG_FALSE); 1017ea906c41SOllivier Robert 1018ea906c41SOllivier Robert freopen( pzFile, "w" FOPEN_BINARY_FLAG, stdout ); 1019ea906c41SOllivier Robert } 1020ea906c41SOllivier Robert 1021ea906c41SOllivier Robert 1022ea906c41SOllivier Robert /*=export_func genshelloptUsage 1023ea906c41SOllivier Robert * private: 1024ea906c41SOllivier Robert * what: The usage function for the genshellopt generated program 1025ea906c41SOllivier Robert * 1026ea906c41SOllivier Robert * arg: + tOptions* + pOpts + program options descriptor + 1027ea906c41SOllivier Robert * arg: + int + exitCode + usage text type to produce + 1028ea906c41SOllivier Robert * 1029ea906c41SOllivier Robert * doc: 1030ea906c41SOllivier Robert * This function is used to create the usage strings for the option 1031ea906c41SOllivier Robert * processing shell script code. Two child processes are spawned 1032ea906c41SOllivier Robert * each emitting the usage text in either the short (error exit) 1033ea906c41SOllivier Robert * style or the long style. The generated program will capture this 1034ea906c41SOllivier Robert * and create shell script variables containing the two types of text. 1035ea906c41SOllivier Robert =*/ 1036ea906c41SOllivier Robert void 1037ea906c41SOllivier Robert genshelloptUsage( tOptions* pOpts, int exitCode ) 1038ea906c41SOllivier Robert { 1039ea906c41SOllivier Robert #if defined(__windows__) && !defined(__CYGWIN__) 1040ea906c41SOllivier Robert optionUsage( pOpts, exitCode ); 1041ea906c41SOllivier Robert #else 1042ea906c41SOllivier Robert /* 1043ea906c41SOllivier Robert * IF not EXIT_SUCCESS, 1044ea906c41SOllivier Robert * THEN emit the short form of usage. 1045ea906c41SOllivier Robert */ 1046ea906c41SOllivier Robert if (exitCode != EXIT_SUCCESS) 1047ea906c41SOllivier Robert optionUsage( pOpts, exitCode ); 1048ea906c41SOllivier Robert fflush( stderr ); 1049ea906c41SOllivier Robert fflush( stdout ); 1050ea906c41SOllivier Robert 1051ea906c41SOllivier Robert option_usage_fp = stdout; 1052ea906c41SOllivier Robert 1053ea906c41SOllivier Robert /* 1054ea906c41SOllivier Robert * First, print our usage 1055ea906c41SOllivier Robert */ 1056ea906c41SOllivier Robert switch (fork()) { 1057ea906c41SOllivier Robert case -1: 1058ea906c41SOllivier Robert optionUsage( pOpts, EXIT_FAILURE ); 1059ea906c41SOllivier Robert /*NOTREACHED*/ 1060ea906c41SOllivier Robert _exit( EXIT_FAILURE ); 1061ea906c41SOllivier Robert 1062ea906c41SOllivier Robert case 0: 1063ea906c41SOllivier Robert pagerState = PAGER_STATE_CHILD; 1064ea906c41SOllivier Robert optionUsage( pOpts, EXIT_SUCCESS ); 1065ea906c41SOllivier Robert /*NOTREACHED*/ 1066ea906c41SOllivier Robert _exit( EXIT_FAILURE ); 1067ea906c41SOllivier Robert 1068ea906c41SOllivier Robert default: 1069ea906c41SOllivier Robert { 1070ea906c41SOllivier Robert int sts; 1071ea906c41SOllivier Robert wait( &sts ); 1072ea906c41SOllivier Robert } 1073ea906c41SOllivier Robert } 1074ea906c41SOllivier Robert 1075ea906c41SOllivier Robert /* 1076ea906c41SOllivier Robert * Generate the pzProgName, since optionProcess() normally 1077ea906c41SOllivier Robert * gets it from the command line 1078ea906c41SOllivier Robert */ 1079ea906c41SOllivier Robert { 1080ea906c41SOllivier Robert char* pz; 1081ea906c41SOllivier Robert AGDUPSTR( pz, pShellParseOptions->pzPROGNAME, "program name" ); 1082ea906c41SOllivier Robert pShellParseOptions->pzProgName = pz; 1083ea906c41SOllivier Robert while (*pz != NUL) { 1084ea906c41SOllivier Robert *pz = tolower( *pz ); 1085ea906c41SOllivier Robert pz++; 1086ea906c41SOllivier Robert } 1087ea906c41SOllivier Robert } 1088ea906c41SOllivier Robert 1089ea906c41SOllivier Robert /* 1090ea906c41SOllivier Robert * Separate the makeshell usage from the client usage 1091ea906c41SOllivier Robert */ 1092ea906c41SOllivier Robert fprintf( option_usage_fp, zGenshell, pShellParseOptions->pzProgName ); 1093ea906c41SOllivier Robert fflush( option_usage_fp ); 1094ea906c41SOllivier Robert 1095ea906c41SOllivier Robert /* 1096ea906c41SOllivier Robert * Now, print the client usage. 1097ea906c41SOllivier Robert */ 1098ea906c41SOllivier Robert switch (fork()) { 1099ea906c41SOllivier Robert case 0: 1100ea906c41SOllivier Robert pagerState = PAGER_STATE_CHILD; 1101ea906c41SOllivier Robert /*FALLTHROUGH*/ 1102ea906c41SOllivier Robert case -1: 1103ea906c41SOllivier Robert optionUsage( pShellParseOptions, EXIT_FAILURE ); 1104ea906c41SOllivier Robert 1105ea906c41SOllivier Robert default: 1106ea906c41SOllivier Robert { 1107ea906c41SOllivier Robert int sts; 1108ea906c41SOllivier Robert wait( &sts ); 1109ea906c41SOllivier Robert } 1110ea906c41SOllivier Robert } 1111ea906c41SOllivier Robert 1112ea906c41SOllivier Robert exit( EXIT_SUCCESS ); 1113ea906c41SOllivier Robert #endif 1114ea906c41SOllivier Robert } 1115ea906c41SOllivier Robert 1116ea906c41SOllivier Robert /* 1117ea906c41SOllivier Robert * Local Variables: 1118ea906c41SOllivier Robert * mode: C 1119ea906c41SOllivier Robert * c-file-style: "stroustrup" 1120ea906c41SOllivier Robert * indent-tabs-mode: nil 1121ea906c41SOllivier Robert * End: 1122ea906c41SOllivier Robert * end of autoopts/makeshell.c */ 1123