1290001Sglebius/**
2290001Sglebius * \file initialize.c
3290001Sglebius *
4290001Sglebius *  initialize the libopts data structures.
5290001Sglebius *
6290001Sglebius * @addtogroup autoopts
7290001Sglebius * @{
8290001Sglebius */
9290001Sglebius/*
10290001Sglebius *  This file is part of AutoOpts, a companion to AutoGen.
11290001Sglebius *  AutoOpts is free software.
12290001Sglebius *  AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved
13290001Sglebius *
14290001Sglebius *  AutoOpts is available under any one of two licenses.  The license
15290001Sglebius *  in use must be one of these two and the choice is under the control
16290001Sglebius *  of the user of the license.
17290001Sglebius *
18290001Sglebius *   The GNU Lesser General Public License, version 3 or later
19290001Sglebius *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
20290001Sglebius *
21290001Sglebius *   The Modified Berkeley Software Distribution License
22290001Sglebius *      See the file "COPYING.mbsd"
23290001Sglebius *
24290001Sglebius *  These files have the following sha256 sums:
25290001Sglebius *
26290001Sglebius *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
27290001Sglebius *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
28290001Sglebius *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
29290001Sglebius */
30290001Sglebius
31290001Sglebius/* = = = START-STATIC-FORWARD = = = */
32290001Sglebiusstatic tSuccess
33290001Sglebiusdo_presets(tOptions * opts);
34290001Sglebius/* = = = END-STATIC-FORWARD = = = */
35290001Sglebius
36290001Sglebius/**
37290001Sglebius *  Make sure the option descriptor is there and that we understand it.
38290001Sglebius *  This should be called from any user entry point where one needs to
39290001Sglebius *  worry about validity.  (Some entry points are free to assume that
40290001Sglebius *  the call is not the first to the library and, thus, that this has
41290001Sglebius *  already been called.)
42290001Sglebius *
43290001Sglebius *  Upon successful completion, pzProgName and pzProgPath are set.
44290001Sglebius *
45290001Sglebius *  @param[in,out] opts   program options descriptor
46290001Sglebius *  @param[in]     pname  name of program, from argv[]
47290001Sglebius *  @returns SUCCESS or FAILURE
48290001Sglebius */
49290001SglebiusLOCAL tSuccess
50290001Sglebiusvalidate_struct(tOptions * opts, char const * pname)
51290001Sglebius{
52290001Sglebius    if (opts == NULL) {
53290001Sglebius        fputs(zno_opt_arg, stderr);
54290001Sglebius        return FAILURE;
55290001Sglebius    }
56290001Sglebius    print_exit = ((opts->fOptSet & OPTPROC_SHELL_OUTPUT) != 0);
57290001Sglebius
58290001Sglebius    /*
59290001Sglebius     *  IF the client has enabled translation and the translation procedure
60290001Sglebius     *  is available, then go do it.
61290001Sglebius     */
62290001Sglebius    if (  ((opts->fOptSet & OPTPROC_TRANSLATE) != 0)
63290001Sglebius       && (opts->pTransProc != NULL)
64290001Sglebius       && (option_xlateable_txt.field_ct != 0) ) {
65290001Sglebius        /*
66290001Sglebius         *  If option names are not to be translated at all, then do not do
67290001Sglebius         *  it for configuration parsing either.  (That is the bit that really
68290001Sglebius         *  gets tested anyway.)
69290001Sglebius         */
70290001Sglebius        if ((opts->fOptSet & OPTPROC_NO_XLAT_MASK) == OPTPROC_NXLAT_OPT)
71290001Sglebius            opts->fOptSet |= OPTPROC_NXLAT_OPT_CFG;
72290001Sglebius        opts->pTransProc();
73290001Sglebius    }
74290001Sglebius
75290001Sglebius    /*
76290001Sglebius     *  IF the struct version is not the current, and also
77290001Sglebius     *     either too large (?!) or too small,
78290001Sglebius     *  THEN emit error message and fail-exit
79290001Sglebius     */
80290001Sglebius    if (  ( opts->structVersion  != OPTIONS_STRUCT_VERSION  )
81290001Sglebius       && (  (opts->structVersion > OPTIONS_STRUCT_VERSION  )
82290001Sglebius          || (opts->structVersion < OPTIONS_MINIMUM_VERSION )
83290001Sglebius       )  )  {
84290001Sglebius        fprintf(stderr, zwrong_ver, pname, NUM_TO_VER(opts->structVersion));
85290001Sglebius        if (opts->structVersion > OPTIONS_STRUCT_VERSION )
86290001Sglebius            fputs(ztoo_new, stderr);
87290001Sglebius        else
88290001Sglebius            fputs(ztoo_old, stderr);
89290001Sglebius
90290001Sglebius        fwrite(ao_ver_string, sizeof(ao_ver_string) - 1, 1, stderr);
91290001Sglebius        return FAILURE;
92290001Sglebius    }
93290001Sglebius
94290001Sglebius    /*
95290001Sglebius     *  If the program name hasn't been set, then set the name and the path
96290001Sglebius     *  and the set of equivalent characters.
97290001Sglebius     */
98290001Sglebius    if (opts->pzProgName == NULL) {
99290001Sglebius        char const *  pz = strrchr(pname, DIRCH);
100294905Sdelphij        char const ** pp = VOIDP(&(opts->pzProgName));
101290001Sglebius
102290001Sglebius        if (pz != NULL)
103290001Sglebius            *pp = pz+1;
104290001Sglebius        else
105290001Sglebius            *pp = pname;
106290001Sglebius
107294905Sdelphij        pz = pathfind(getenv("PATH"), pname, "rx");
108290001Sglebius        if (pz != NULL)
109290001Sglebius            pname = VOIDP(pz);
110290001Sglebius
111290001Sglebius        pp  = (char const **)VOIDP(&(opts->pzProgPath));
112290001Sglebius        *pp = pname;
113290001Sglebius
114290001Sglebius        /*
115290001Sglebius         *  when comparing long names, these are equivalent
116290001Sglebius         */
117290001Sglebius        strequate(zSepChars);
118290001Sglebius    }
119290001Sglebius
120290001Sglebius    return SUCCESS;
121290001Sglebius}
122290001Sglebius
123290001Sglebius/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
124290001Sglebius *
125290001Sglebius *  DO PRESETS
126290001Sglebius *
127290001Sglebius *  The next several routines do the immediate action pass on the command
128290001Sglebius *  line options, then the environment variables, then the config files in
129290001Sglebius *  reverse order.  Once done with that, the order is reversed and all
130290001Sglebius *  the config files and environment variables are processed again, this
131290001Sglebius *  time only processing the non-immediate action options.  do_presets()
132290001Sglebius *  will then return for optionProcess() to do the final pass on the command
133290001Sglebius *  line arguments.
134290001Sglebius */
135290001Sglebius
136290001Sglebius/**
137290001Sglebius *  scan the command line for immediate action options.
138290001Sglebius *  This is only called the first time through.
139290001Sglebius *  While this procedure is active, the OPTPROC_IMMEDIATE is true.
140290001Sglebius *
141290001Sglebius *  @param pOpts   program options descriptor
142290001Sglebius *  @returns SUCCESS or FAILURE
143290001Sglebius */
144290001SglebiusLOCAL tSuccess
145290001Sglebiusimmediate_opts(tOptions * opts)
146290001Sglebius{
147290001Sglebius    tSuccess  res;
148290001Sglebius
149290001Sglebius    opts->fOptSet  |= OPTPROC_IMMEDIATE;
150290001Sglebius    opts->curOptIdx = 1;     /* start by skipping program name */
151290001Sglebius    opts->pzCurOpt  = NULL;
152290001Sglebius
153290001Sglebius    /*
154290001Sglebius     *  Examine all the options from the start.  We process any options that
155290001Sglebius     *  are marked for immediate processing.
156290001Sglebius     */
157290001Sglebius    for (;;) {
158290001Sglebius        tOptState opt_st = OPTSTATE_INITIALIZER(PRESET);
159290001Sglebius
160290001Sglebius        res = next_opt(opts, &opt_st);
161290001Sglebius        switch (res) {
162290001Sglebius        case FAILURE: goto   failed_option;
163290001Sglebius        case PROBLEM: res = SUCCESS; goto leave;
164290001Sglebius        case SUCCESS: break;
165290001Sglebius        }
166290001Sglebius
167290001Sglebius        /*
168290001Sglebius         *  IF this is an immediate-attribute option, then do it.
169290001Sglebius         */
170290001Sglebius        if (! DO_IMMEDIATELY(opt_st.flags))
171290001Sglebius            continue;
172290001Sglebius
173290001Sglebius        if (! SUCCESSFUL(handle_opt(opts, &opt_st)))
174290001Sglebius            break;
175290001Sglebius    } failed_option:;
176290001Sglebius
177290001Sglebius    if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0)
178290001Sglebius        (*opts->pUsageProc)(opts, EXIT_FAILURE);
179290001Sglebius
180290001Sglebius leave:
181290001Sglebius
182290001Sglebius    opts->fOptSet &= ~OPTPROC_IMMEDIATE;
183290001Sglebius    return res;
184290001Sglebius}
185290001Sglebius
186290001Sglebius/**
187290001Sglebius *  check for preset values from a config files or envrionment variables
188290001Sglebius *
189290001Sglebius * @param[in,out] opts  the structure with the option names to check
190290001Sglebius */
191290001Sglebiusstatic tSuccess
192290001Sglebiusdo_presets(tOptions * opts)
193290001Sglebius{
194290001Sglebius    tOptDesc * od = NULL;
195290001Sglebius
196290001Sglebius    if (! SUCCESSFUL(immediate_opts(opts)))
197290001Sglebius        return FAILURE;
198290001Sglebius
199290001Sglebius    /*
200290001Sglebius     *  IF this option set has a --save-opts option, then it also
201290001Sglebius     *  has a --load-opts option.  See if a command line option has disabled
202290001Sglebius     *  option presetting.
203290001Sglebius     */
204290001Sglebius    if (  (opts->specOptIdx.save_opts != NO_EQUIVALENT)
205290001Sglebius       && (opts->specOptIdx.save_opts != 0)) {
206290001Sglebius        od = opts->pOptDesc + opts->specOptIdx.save_opts + 1;
207290001Sglebius        if (DISABLED_OPT(od))
208290001Sglebius            return SUCCESS;
209290001Sglebius    }
210290001Sglebius
211290001Sglebius    /*
212290001Sglebius     *  Until we return from this procedure, disable non-presettable opts
213290001Sglebius     */
214290001Sglebius    opts->fOptSet |= OPTPROC_PRESETTING;
215290001Sglebius    /*
216290001Sglebius     *  IF there are no config files,
217290001Sglebius     *  THEN do any environment presets and leave.
218290001Sglebius     */
219290001Sglebius    if (opts->papzHomeList == NULL) {
220290001Sglebius        env_presets(opts, ENV_ALL);
221290001Sglebius    }
222290001Sglebius    else {
223290001Sglebius        env_presets(opts, ENV_IMM);
224290001Sglebius
225290001Sglebius        /*
226290001Sglebius         *  Check to see if environment variables have disabled presetting.
227290001Sglebius         */
228290001Sglebius        if ((od != NULL) && ! DISABLED_OPT(od))
229290001Sglebius            intern_file_load(opts);
230290001Sglebius
231290001Sglebius        /*
232290001Sglebius         *  ${PROGRAM_LOAD_OPTS} value of "no" cannot disable other environment
233290001Sglebius         *  variable options.  Only the loading of .rc files.
234290001Sglebius         */
235290001Sglebius        env_presets(opts, ENV_NON_IMM);
236290001Sglebius    }
237290001Sglebius    opts->fOptSet &= ~OPTPROC_PRESETTING;
238290001Sglebius
239290001Sglebius    return SUCCESS;
240290001Sglebius}
241290001Sglebius
242290001Sglebius/**
243290001Sglebius * AutoOpts initialization
244290001Sglebius *
245290001Sglebius * @param[in,out] opts  the structure to initialize
246290001Sglebius * @param[in]     a_ct  program argument count
247290001Sglebius * @param[in]     a_v   program argument vector
248290001Sglebius */
249290001SglebiusLOCAL bool
250290001Sglebiusao_initialize(tOptions * opts, int a_ct, char ** a_v)
251290001Sglebius{
252290001Sglebius    if ((opts->fOptSet & OPTPROC_INITDONE) != 0)
253290001Sglebius        return true;
254290001Sglebius
255290001Sglebius    opts->origArgCt   = (unsigned int)a_ct;
256290001Sglebius    opts->origArgVect = a_v;
257290001Sglebius    opts->fOptSet    |= OPTPROC_INITDONE;
258290001Sglebius
259290001Sglebius    if (HAS_pzPkgDataDir(opts))
260290001Sglebius        program_pkgdatadir = opts->pzPkgDataDir;
261290001Sglebius
262290001Sglebius    if (! SUCCESSFUL(do_presets(opts)))
263290001Sglebius        return false;
264290001Sglebius
265290001Sglebius    /*
266290001Sglebius     *  IF option name conversion was suppressed but it is not suppressed
267290001Sglebius     *  for the command line, then it's time to translate option names.
268290001Sglebius     *  Usage text will not get retranslated.
269290001Sglebius     */
270290001Sglebius    if (  ((opts->fOptSet & OPTPROC_TRANSLATE) != 0)
271290001Sglebius       && (opts->pTransProc != NULL)
272290001Sglebius       && ((opts->fOptSet & OPTPROC_NO_XLAT_MASK) == OPTPROC_NXLAT_OPT_CFG)
273290001Sglebius       )  {
274290001Sglebius        opts->fOptSet &= ~OPTPROC_NXLAT_OPT_CFG;
275290001Sglebius        (*opts->pTransProc)();
276290001Sglebius    }
277290001Sglebius
278290001Sglebius    if ((opts->fOptSet & OPTPROC_REORDER) != 0)
279290001Sglebius        optionSort(opts);
280290001Sglebius
281290001Sglebius    opts->curOptIdx   = 1;
282290001Sglebius    opts->pzCurOpt    = NULL;
283290001Sglebius    return true;
284290001Sglebius}
285290001Sglebius
286290001Sglebius/** @}
287290001Sglebius *
288290001Sglebius * Local Variables:
289290001Sglebius * mode: C
290290001Sglebius * c-file-style: "stroustrup"
291290001Sglebius * indent-tabs-mode: nil
292290001Sglebius * End:
293290001Sglebius * end of autoopts/initialize.c */
294