1 /* $NetBSD: putshell.c,v 1.1.1.2 2007/06/24 15:49:26 kardel Exp $ */
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 */
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.
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
);
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
);
89 * Start the single quote string
91 fputc( '\'', stdout
);
93 tCC
* pz
= strchr( pzStr
, '\'' );
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
);
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
);
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
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.
132 optionPutShell( tOptions
* pOpts
)
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 );
146 tOptDesc
* pOD
= pOpts
->pOptDesc
+ optIx
;
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
);
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
) {
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;
194 printf( "typeset -x -i %s_", pOD
->pz_NAME
);
195 pz
+= strspn( pz
, " +\t\n\f" );
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
);
205 printf( "=%1$lu # 0x%1$lX\n", (unsigned long)val
);
209 AGFREE(pOD
->optArg
.argString
);
210 pOD
->optArg
.argString
= NULL
;
211 pOD
->fOptState
&= ~OPTST_ALLOC_ARG
;
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
))
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
;
235 printf( zOptCookieCt
, pOpts
->pzPROGNAME
, pOD
->pz_NAME
, ct
);
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
,
243 putQuotedStr( *(ppz
++) );
244 printf( end_z
, pOpts
->pzPROGNAME
, pOD
->pz_NAME
,
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
,
298 * This option has a text value
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
);
315 fputs( " '", stdout
);
317 char ch
= *(pzArg
++);
319 case '\'': fputs( "'\\''", stdout
); break;
320 case NUL
: goto arg_done
;
321 default: fputc( ch
, stdout
); break;
324 fputc( '\'', stdout
);
327 fputs( "\nOPTION_CT=0\n", stdout
);
334 * c-file-style: "stroustrup"
335 * indent-tabs-mode: nil
337 * end of autoopts/putshell.c */