Sync usage with man page.
[netbsd-mini2440.git] / dist / ntp / libopts / putshell.c
bloba7b67c8e0ccc6c30215cfb1d5456c8a5f3e0f2a3
1 /* $NetBSD: putshell.c,v 1.1.1.2 2007/06/24 15:49:26 kardel Exp $ */
4 /*
5 * Id: putshell.c,v 4.18 2007/02/04 17:44:12 bkorb Exp
6 * Time-stamp: "2007-01-13 10:29:39 bkorb"
8 * This module will interpret the options set in the tOptions
9 * structure and print them to standard out in a fashion that
10 * will allow them to be interpreted by the Bourne or Korn shells.
14 * Automated Options copyright 1992-2007 Bruce Korb
16 * Automated Options is free software.
17 * You may redistribute it and/or modify it under the terms of the
18 * GNU General Public License, as published by the Free Software
19 * Foundation; either version 2, or (at your option) any later version.
21 * Automated Options is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with Automated Options. See the file "COPYING". If not,
28 * write to: The Free Software Foundation, Inc.,
29 * 51 Franklin Street, Fifth Floor,
30 * Boston, MA 02110-1301, USA.
32 * As a special exception, Bruce Korb gives permission for additional
33 * uses of the text contained in his release of AutoOpts.
35 * The exception is that, if you link the AutoOpts library with other
36 * files to produce an executable, this does not by itself cause the
37 * resulting executable to be covered by the GNU General Public License.
38 * Your use of that executable is in no way restricted on account of
39 * linking the AutoOpts library code into it.
41 * This exception does not however invalidate any other reasons why
42 * the executable file might be covered by the GNU General Public License.
44 * This exception applies only to the code released by Bruce Korb under
45 * the name AutoOpts. If you copy code from other sources under the
46 * General Public License into a copy of AutoOpts, as the General Public
47 * License permits, the exception does not apply to the code that you add
48 * in this way. To avoid misleading anyone as to the status of such
49 * modified files, you must delete this exception notice from them.
51 * If you write modifications of your own for AutoOpts, it is your choice
52 * whether to permit this exception to apply to your modifications.
53 * If you do not wish that, delete this exception notice.
56 /* = = = START-STATIC-FORWARD = = = */
57 /* static forward declarations maintained by :mkfwd */
58 static void
59 putQuotedStr( tCC* pzStr );
60 /* = = = END-STATIC-FORWARD = = = */
63 * Make sure embedded single quotes come out okay. The initial quote has
64 * been emitted and the closing quote will be upon return.
66 static void
67 putQuotedStr( tCC* pzStr )
70 * Handle empty strings to make the rest of the logic simpler.
72 if ((pzStr == NULL) || (*pzStr == NUL)) {
73 fputs( "''", stdout );
74 return;
78 * Emit any single quotes/apostrophes at the start of the string and
79 * bail if that is all we need to do.
81 while (*pzStr == '\'') {
82 fputs( "\\'", stdout );
83 pzStr++;
85 if (*pzStr == NUL)
86 return;
89 * Start the single quote string
91 fputc( '\'', stdout );
92 for (;;) {
93 tCC* pz = strchr( pzStr, '\'' );
94 if (pz == NULL)
95 break;
98 * Emit the string up to the single quote (apostrophe) we just found.
100 (void)fwrite( pzStr, (size_t)(pz - pzStr), (size_t)1, stdout );
101 fputc( '\'', stdout );
102 pzStr = pz;
105 * Emit an escaped apostrophe for every one we find.
106 * If that ends the string, do not re-open the single quotes.
108 while (*++pzStr == '\'') fputs( "\\'", stdout );
109 if (*pzStr == NUL)
110 return;
112 fputc( '\'', stdout );
116 * If we broke out of the loop, we must still emit the remaining text
117 * and then close the single quote string.
119 fputs( pzStr, stdout );
120 fputc( '\'', stdout );
124 /*=export_func optionPutShell
125 * what: write a portable shell script to parse options
126 * private:
127 * arg: tOptions*, pOpts, the program options descriptor
128 * doc: This routine will emit portable shell script text for parsing
129 * the options described in the option definitions.
131 void
132 optionPutShell( tOptions* pOpts )
134 int optIx = 0;
135 tSCC zOptCtFmt[] = "OPTION_CT=%d\nexport OPTION_CT\n";
136 tSCC zOptNumFmt[] = "%1$s_%2$s=%3$d # 0x%3$X\nexport %1$s_%2$s\n";
137 tSCC zOptDisabl[] = "%1$s_%2$s=%3$s\nexport %1$s_%2$s\n";
138 tSCC zOptValFmt[] = "%s_%s=";
139 tSCC zOptEnd[] = "\nexport %s_%s\n";
140 tSCC zFullOptFmt[]= "%1$s_%2$s='%3$s'\nexport %1$s_%2$s\n";
141 tSCC zEquivMode[] = "%1$s_%2$s_MODE='%3$s'\nexport %1$s_%2$s_MODE\n";
143 printf( zOptCtFmt, pOpts->curOptIdx-1 );
145 do {
146 tOptDesc* pOD = pOpts->pOptDesc + optIx;
148 if (SKIP_OPT(pOD))
149 continue;
152 * Equivalence classes are hard to deal with. Where the
153 * option data wind up kind of squishes around. For the purposes
154 * of emitting shell state, they are not recommended, but we'll
155 * do something. I guess we'll emit the equivalenced-to option
156 * at the point in time when the base option is found.
158 if (pOD->optEquivIndex != NO_EQUIVALENT)
159 continue; /* equivalence to a different option */
162 * Equivalenced to a different option. Process the current option
163 * as the equivalenced-to option. Keep the persistent state bits,
164 * but copy over the set-state bits.
166 if (pOD->optActualIndex != optIx) {
167 tOptDesc* p = pOpts->pOptDesc + pOD->optActualIndex;
168 p->optArg = pOD->optArg;
169 p->fOptState &= OPTST_PERSISTENT_MASK;
170 p->fOptState |= pOD->fOptState & ~OPTST_PERSISTENT_MASK;
171 printf( zEquivMode, pOpts->pzPROGNAME, pOD->pz_NAME, p->pz_NAME );
172 pOD = p;
176 * If the argument type is a set membership bitmask, then we always
177 * emit the thing. We do this because it will always have some sort
178 * of bitmask value and we need to emit the bit values.
180 if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) {
181 char const * pz;
182 uintptr_t val = 1;
183 printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
184 (int)(uintptr_t)(pOD->optCookie) );
185 pOD->optCookie = (void*)(uintptr_t)~0UL;
186 (*(pOD->pOptProc))( (tOptions*)2UL, pOD );
189 * We are building the typeset list. The list returned starts with
190 * 'none + ' for use by option saving stuff. We must ignore that.
192 pz = pOD->optArg.argString + 7;
193 while (*pz != NUL) {
194 printf( "typeset -x -i %s_", pOD->pz_NAME );
195 pz += strspn( pz, " +\t\n\f" );
196 for (;;) {
197 int ch = *(pz++);
198 if (islower( ch )) fputc( toupper( ch ), stdout );
199 else if (isalnum( ch )) fputc( ch, stdout );
200 else if (isspace( ch )
201 || (ch == '+')) goto name_done;
202 else if (ch == NUL) { pz--; goto name_done; }
203 else fputc( '_', stdout );
204 } name_done:;
205 printf( "=%1$lu # 0x%1$lX\n", (unsigned long)val );
206 val <<= 1;
209 AGFREE(pOD->optArg.argString);
210 pOD->optArg.argString = NULL;
211 pOD->fOptState &= ~OPTST_ALLOC_ARG;
212 continue;
216 * IF the option was either specified or it wakes up enabled,
217 * then we will emit information. Otherwise, skip it.
218 * The idea is that if someone defines an option to initialize
219 * enabled, we should tell our shell script that it is enabled.
221 if (UNUSED_OPT( pOD ) && DISABLED_OPT( pOD ))
222 continue;
225 * Handle stacked arguments
227 if ( (pOD->fOptState & OPTST_STACKED)
228 && (pOD->optCookie != NULL) ) {
229 tSCC zOptCookieCt[] = "%1$s_%2$s_CT=%3$d\nexport %1$s_%2$s_CT\n";
231 tArgList* pAL = (tArgList*)pOD->optCookie;
232 tCC** ppz = pAL->apzArgs;
233 int ct = pAL->useCt;
235 printf( zOptCookieCt, pOpts->pzPROGNAME, pOD->pz_NAME, ct );
237 while (--ct >= 0) {
238 tSCC numarg_z[] = "%s_%s_%d=";
239 tSCC end_z[] = "\nexport %s_%s_%d\n";
241 printf( numarg_z, pOpts->pzPROGNAME, pOD->pz_NAME,
242 pAL->useCt - ct );
243 putQuotedStr( *(ppz++) );
244 printf( end_z, pOpts->pzPROGNAME, pOD->pz_NAME,
245 pAL->useCt - ct );
250 * If the argument has been disabled,
251 * Then set its value to the disablement string
253 else if ((pOD->fOptState & OPTST_DISABLED) != 0)
254 printf( zOptDisabl, pOpts->pzPROGNAME, pOD->pz_NAME,
255 (pOD->pz_DisablePfx != NULL)
256 ? pOD->pz_DisablePfx : "false" );
259 * If the argument type is numeric, the last arg pointer
260 * is really the VALUE of the string that was pointed to.
262 else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC)
263 printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
264 (int)pOD->optArg.argInt );
267 * If the argument type is an enumeration, then it is much
268 * like a text value, except we call the callback function
269 * to emit the value corresponding to the "optArg" number.
271 else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_ENUMERATION) {
272 printf( zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME );
273 fputc( '\'', stdout );
274 (*(pOD->pOptProc))( (tOptions*)1UL, pOD );
275 fputc( '\'', stdout );
276 printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME );
280 * If the argument type is numeric, the last arg pointer
281 * is really the VALUE of the string that was pointed to.
283 else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_BOOLEAN)
284 printf( zFullOptFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
285 (pOD->optArg.argBool == 0) ? "false" : "true" );
288 * IF the option has an empty value,
289 * THEN we set the argument to the occurrence count.
291 else if ( (pOD->optArg.argString == NULL)
292 || (pOD->optArg.argString[0] == NUL) )
294 printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
295 pOD->optOccCt );
298 * This option has a text value
300 else {
301 printf( zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME );
302 putQuotedStr( pOD->optArg.argString );
303 printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME );
305 } while (++optIx < pOpts->presetOptCt );
307 if ( ((pOpts->fOptSet & OPTPROC_REORDER) != 0)
308 && (pOpts->curOptIdx < pOpts->origArgCt)) {
309 fputs( "set --", stdout );
310 for (optIx = pOpts->curOptIdx; optIx < pOpts->origArgCt; optIx++) {
311 char* pzArg = pOpts->origArgVect[ optIx ];
312 if (strchr( pzArg, '\'' ) == NULL)
313 printf( " '%s'", pzArg );
314 else {
315 fputs( " '", stdout );
316 for (;;) {
317 char ch = *(pzArg++);
318 switch (ch) {
319 case '\'': fputs( "'\\''", stdout ); break;
320 case NUL: goto arg_done;
321 default: fputc( ch, stdout ); break;
323 } arg_done:;
324 fputc( '\'', stdout );
327 fputs( "\nOPTION_CT=0\n", stdout );
332 * Local Variables:
333 * mode: C
334 * c-file-style: "stroustrup"
335 * indent-tabs-mode: nil
336 * End:
337 * end of autoopts/putshell.c */