113978Smrkam/*	$NetBSD$	*/
213978Smrkam
313978Smrkam
413978Smrkam/*
513978Smrkam *  Id: 8700c8e91e8094c455392c691d9b6a7d62222240
613978Smrkam * Time-stamp:      "2009-07-20 20:12:24 bkorb"
713978Smrkam *
813978Smrkam *  This file contains all of the routines that must be linked into
913978Smrkam *  an executable to use the generated option processing.  The optional
1013978Smrkam *  routines are in separately compiled modules so that they will not
1113978Smrkam *  necessarily be linked in.
1213978Smrkam *
1313978Smrkam *  This file is part of AutoOpts, a companion to AutoGen.
1413978Smrkam *  AutoOpts is free software.
1513978Smrkam *  AutoOpts is copyright (c) 1992-2009 by Bruce Korb - all rights reserved
1613978Smrkam *
1713978Smrkam *  AutoOpts is available under any one of two licenses.  The license
1813978Smrkam *  in use must be one of these two and the choice is under the control
1913978Smrkam *  of the user of the license.
2013978Smrkam *
2113978Smrkam *   The GNU Lesser General Public License, version 3 or later
2213978Smrkam *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
2313978Smrkam *
2414305Smrkam *   The Modified Berkeley Software Distribution License
2514305Smrkam *      See the file "COPYING.mbsd"
2613978Smrkam *
2713978Smrkam *  These files have the following md5sums:
2813978Smrkam *
2913978Smrkam *  43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3
3013978Smrkam *  06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3
3113978Smrkam *  66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
3213978Smrkam */
3313978Smrkam
3413978Smrkam/* = = = START-STATIC-FORWARD = = = */
3513978Smrkam/* static forward declarations maintained by mk-fwd */
3613978Smrkamstatic void
3714305SmrkamcheckEnvOpt(tOptState * os, char * env_name,
3813978Smrkam            tOptions* pOpts, teEnvPresetType type);
3913978Smrkam/* = = = END-STATIC-FORWARD = = = */
4013978Smrkam
4114801Sprr/*
4213978Smrkam *  doPrognameEnv - check for preset values from the ${PROGNAME}
4313978Smrkam *  environment variable.  This is accomplished by parsing the text into
4413978Smrkam *  tokens, temporarily replacing the arg vector and calling
4513978Smrkam *  doImmediateOpts and/or doRegularOpts.
4613978Smrkam */
4714305SmrkamLOCAL void
4813978SmrkamdoPrognameEnv( tOptions* pOpts, teEnvPresetType type )
4914801Sprr{
5014801Sprr    char const*   pczOptStr = getenv( pOpts->pzPROGNAME );
5113978Smrkam    token_list_t* pTL;
5213978Smrkam    int           sv_argc;
5313978Smrkam    tAoUI         sv_flag;
5413978Smrkam    char**        sv_argv;
5514305Smrkam
5613978Smrkam    /*
5713978Smrkam     *  No such beast?  Then bail now.
5813978Smrkam     */
5913978Smrkam    if (pczOptStr == NULL)
6013978Smrkam        return;
6113978Smrkam
6214305Smrkam    /*
6313978Smrkam     *  Tokenize the string.  If there's nothing of interest, we'll bail
6414305Smrkam     *  here immediately.
6513978Smrkam     */
6614305Smrkam    pTL = ao_string_tokenize( pczOptStr );
6714305Smrkam    if (pTL == NULL)
6813978Smrkam        return;
6914305Smrkam
7014305Smrkam    /*
7114305Smrkam     *  Substitute our $PROGNAME argument list for the real one
7214305Smrkam     */
7313978Smrkam    sv_argc = pOpts->origArgCt;
7413978Smrkam    sv_argv = pOpts->origArgVect;
7513978Smrkam    sv_flag = pOpts->fOptSet;
7613978Smrkam
7713978Smrkam    /*
7813978Smrkam     *  We add a bogus pointer to the start of the list.  The program name
7913978Smrkam     *  has already been pulled from "argv", so it won't get dereferenced.
8013978Smrkam     *  The option scanning code will skip the "program name" at the start
8113978Smrkam     *  of this list of tokens, so we accommodate this way ....
8213978Smrkam     */
8313978Smrkam    pOpts->origArgVect = (char**)(pTL->tkn_list - 1);
8413978Smrkam    pOpts->origArgCt   = pTL->tkn_ct   + 1;
8513978Smrkam    pOpts->fOptSet    &= ~OPTPROC_ERRSTOP;
8613978Smrkam
8713978Smrkam    pOpts->curOptIdx   = 1;
8813978Smrkam    pOpts->pzCurOpt    = NULL;
8913978Smrkam
9013978Smrkam    switch (type) {
9113978Smrkam    case ENV_IMM:
9213978Smrkam        (void)doImmediateOpts( pOpts );
9313978Smrkam        break;
9413978Smrkam
9513978Smrkam    case ENV_ALL:
9613978Smrkam        (void)doImmediateOpts( pOpts );
9713978Smrkam        pOpts->curOptIdx = 1;
9813978Smrkam        pOpts->pzCurOpt  = NULL;
99        /* FALLTHROUGH */
100
101    case ENV_NON_IMM:
102        (void)doRegularOpts( pOpts );
103    }
104
105    /*
106     *  Free up the temporary arg vector and restore the original program args.
107     */
108    free( pTL );
109    pOpts->origArgVect = sv_argv;
110    pOpts->origArgCt   = sv_argc;
111    pOpts->fOptSet     = sv_flag;
112}
113
114static void
115checkEnvOpt(tOptState * os, char * env_name,
116            tOptions* pOpts, teEnvPresetType type)
117{
118    os->pzOptArg = getenv( env_name );
119    if (os->pzOptArg == NULL)
120        return;
121
122    os->flags    = OPTST_PRESET | OPTST_ALLOC_ARG | os->pOD->fOptState;
123    os->optType  = TOPT_UNDEFINED;
124
125    if (  (os->pOD->pz_DisablePfx != NULL)
126       && (streqvcmp( os->pzOptArg, os->pOD->pz_DisablePfx ) == 0)) {
127        os->flags |= OPTST_DISABLED;
128        os->pzOptArg = NULL;
129    }
130
131    switch (type) {
132    case ENV_IMM:
133        /*
134         *  Process only immediate actions
135         */
136        if (DO_IMMEDIATELY(os->flags))
137            break;
138        return;
139
140    case ENV_NON_IMM:
141        /*
142         *  Process only NON immediate actions
143         */
144        if (DO_NORMALLY(os->flags) || DO_SECOND_TIME(os->flags))
145            break;
146        return;
147
148    default: /* process everything */
149        break;
150    }
151
152    /*
153     *  Make sure the option value string is persistent and consistent.
154     *
155     *  The interpretation of the option value depends
156     *  on the type of value argument the option takes
157     */
158    if (os->pzOptArg != NULL) {
159        if (OPTST_GET_ARGTYPE(os->pOD->fOptState) == OPARG_TYPE_NONE) {
160            os->pzOptArg = NULL;
161        } else if (  (os->pOD->fOptState & OPTST_ARG_OPTIONAL)
162                     && (*os->pzOptArg == NUL)) {
163            os->pzOptArg = NULL;
164        } else if (*os->pzOptArg == NUL) {
165            os->pzOptArg = zNil;
166        } else {
167            AGDUPSTR( os->pzOptArg, os->pzOptArg, "option argument" );
168            os->flags |= OPTST_ALLOC_ARG;
169        }
170    }
171
172    handleOption( pOpts, os );
173}
174
175/*
176 *  doEnvPresets - check for preset values from the envrionment
177 *  This routine should process in all, immediate or normal modes....
178 */
179LOCAL void
180doEnvPresets( tOptions* pOpts, teEnvPresetType type )
181{
182    int        ct;
183    tOptState  st;
184    char*      pzFlagName;
185    size_t     spaceLeft;
186    char       zEnvName[ AO_NAME_SIZE ];
187
188    /*
189     *  Finally, see if we are to look at the environment
190     *  variables for initial values.
191     */
192    if ((pOpts->fOptSet & OPTPROC_ENVIRON) == 0)
193        return;
194
195    doPrognameEnv( pOpts, type );
196
197    ct  = pOpts->presetOptCt;
198    st.pOD = pOpts->pOptDesc;
199
200    pzFlagName = zEnvName
201        + snprintf( zEnvName, sizeof( zEnvName ), "%s_", pOpts->pzPROGNAME );
202    spaceLeft = AO_NAME_SIZE - (pzFlagName - zEnvName) - 1;
203
204    for (;ct-- > 0; st.pOD++) {
205        /*
206         *  If presetting is disallowed, then skip this entry
207         */
208        if (  ((st.pOD->fOptState & OPTST_NO_INIT) != 0)
209           || (st.pOD->optEquivIndex != NO_EQUIVALENT)  )
210            continue;
211
212        /*
213         *  IF there is no such environment variable,
214         *  THEN skip this entry, too.
215         */
216        if (strlen( st.pOD->pz_NAME ) >= spaceLeft)
217            continue;
218
219        /*
220         *  Set up the option state
221         */
222        strcpy( pzFlagName, st.pOD->pz_NAME );
223        checkEnvOpt(&st, zEnvName, pOpts, type);
224    }
225
226    /*
227     *  Special handling for ${PROGNAME_LOAD_OPTS}
228     */
229    if (  (pOpts->specOptIdx.save_opts != NO_EQUIVALENT)
230       && (pOpts->specOptIdx.save_opts != 0)) {
231        st.pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1;
232        strcpy( pzFlagName, st.pOD->pz_NAME );
233        checkEnvOpt(&st, zEnvName, pOpts, type);
234    }
235}
236
237/*
238 * Local Variables:
239 * mode: C
240 * c-file-style: "stroustrup"
241 * indent-tabs-mode: nil
242 * End:
243 * end of autoopts/environment.c */
244