xref: /freebsd/contrib/ntp/sntp/libopts/makeshell.c (revision ea906c4152774dff300bb26fbfc1e4188351c89a)
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