1275970Scy/**
2275970Scy * \file initialize.c
3275970Scy *
4275970Scy *  initialize the libopts data structures.
5275970Scy *
6275970Scy * @addtogroup autoopts
7275970Scy * @{
8275970Scy */
9275970Scy/*
10275970Scy *  This file is part of AutoOpts, a companion to AutoGen.
11275970Scy *  AutoOpts is free software.
12285612Sdelphij *  AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved
13275970Scy *
14275970Scy *  AutoOpts is available under any one of two licenses.  The license
15275970Scy *  in use must be one of these two and the choice is under the control
16275970Scy *  of the user of the license.
17275970Scy *
18275970Scy *   The GNU Lesser General Public License, version 3 or later
19275970Scy *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
20275970Scy *
21275970Scy *   The Modified Berkeley Software Distribution License
22275970Scy *      See the file "COPYING.mbsd"
23275970Scy *
24275970Scy *  These files have the following sha256 sums:
25275970Scy *
26275970Scy *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
27275970Scy *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
28275970Scy *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
29275970Scy */
30275970Scy
31275970Scy/* = = = START-STATIC-FORWARD = = = */
32275970Scystatic tSuccess
33275970Scydo_presets(tOptions * opts);
34275970Scy/* = = = END-STATIC-FORWARD = = = */
35275970Scy
36275970Scy/**
37275970Scy *  Make sure the option descriptor is there and that we understand it.
38275970Scy *  This should be called from any user entry point where one needs to
39275970Scy *  worry about validity.  (Some entry points are free to assume that
40275970Scy *  the call is not the first to the library and, thus, that this has
41275970Scy *  already been called.)
42275970Scy *
43275970Scy *  Upon successful completion, pzProgName and pzProgPath are set.
44275970Scy *
45275970Scy *  @param[in,out] opts   program options descriptor
46275970Scy *  @param[in]     pname  name of program, from argv[]
47275970Scy *  @returns SUCCESS or FAILURE
48275970Scy */
49275970ScyLOCAL tSuccess
50275970Scyvalidate_struct(tOptions * opts, char const * pname)
51275970Scy{
52275970Scy    if (opts == NULL) {
53275970Scy        fputs(zno_opt_arg, stderr);
54275970Scy        return FAILURE;
55275970Scy    }
56275970Scy    print_exit = ((opts->fOptSet & OPTPROC_SHELL_OUTPUT) != 0);
57275970Scy
58275970Scy    /*
59275970Scy     *  IF the client has enabled translation and the translation procedure
60275970Scy     *  is available, then go do it.
61275970Scy     */
62275970Scy    if (  ((opts->fOptSet & OPTPROC_TRANSLATE) != 0)
63275970Scy       && (opts->pTransProc != NULL)
64275970Scy       && (option_xlateable_txt.field_ct != 0) ) {
65275970Scy        /*
66275970Scy         *  If option names are not to be translated at all, then do not do
67275970Scy         *  it for configuration parsing either.  (That is the bit that really
68275970Scy         *  gets tested anyway.)
69275970Scy         */
70275970Scy        if ((opts->fOptSet & OPTPROC_NO_XLAT_MASK) == OPTPROC_NXLAT_OPT)
71275970Scy            opts->fOptSet |= OPTPROC_NXLAT_OPT_CFG;
72285612Sdelphij        opts->pTransProc();
73275970Scy    }
74275970Scy
75275970Scy    /*
76275970Scy     *  IF the struct version is not the current, and also
77275970Scy     *     either too large (?!) or too small,
78275970Scy     *  THEN emit error message and fail-exit
79275970Scy     */
80275970Scy    if (  ( opts->structVersion  != OPTIONS_STRUCT_VERSION  )
81275970Scy       && (  (opts->structVersion > OPTIONS_STRUCT_VERSION  )
82275970Scy          || (opts->structVersion < OPTIONS_MINIMUM_VERSION )
83275970Scy       )  )  {
84275970Scy        fprintf(stderr, zwrong_ver, pname, NUM_TO_VER(opts->structVersion));
85275970Scy        if (opts->structVersion > OPTIONS_STRUCT_VERSION )
86275970Scy            fputs(ztoo_new, stderr);
87275970Scy        else
88275970Scy            fputs(ztoo_old, stderr);
89275970Scy
90275970Scy        fwrite(ao_ver_string, sizeof(ao_ver_string) - 1, 1, stderr);
91275970Scy        return FAILURE;
92275970Scy    }
93275970Scy
94275970Scy    /*
95275970Scy     *  If the program name hasn't been set, then set the name and the path
96275970Scy     *  and the set of equivalent characters.
97275970Scy     */
98275970Scy    if (opts->pzProgName == NULL) {
99275970Scy        char const *  pz = strrchr(pname, DIRCH);
100294569Sdelphij        char const ** pp = VOIDP(&(opts->pzProgName));
101275970Scy
102275970Scy        if (pz != NULL)
103285612Sdelphij            *pp = pz+1;
104275970Scy        else
105285612Sdelphij            *pp = pname;
106275970Scy
107294569Sdelphij        pz = pathfind(getenv("PATH"), pname, "rx");
108275970Scy        if (pz != NULL)
109285612Sdelphij            pname = VOIDP(pz);
110275970Scy
111285612Sdelphij        pp  = (char const **)VOIDP(&(opts->pzProgPath));
112285612Sdelphij        *pp = pname;
113275970Scy
114275970Scy        /*
115275970Scy         *  when comparing long names, these are equivalent
116275970Scy         */
117275970Scy        strequate(zSepChars);
118275970Scy    }
119275970Scy
120275970Scy    return SUCCESS;
121275970Scy}
122275970Scy
123275970Scy/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
124275970Scy *
125275970Scy *  DO PRESETS
126275970Scy *
127275970Scy *  The next several routines do the immediate action pass on the command
128275970Scy *  line options, then the environment variables, then the config files in
129275970Scy *  reverse order.  Once done with that, the order is reversed and all
130275970Scy *  the config files and environment variables are processed again, this
131275970Scy *  time only processing the non-immediate action options.  do_presets()
132275970Scy *  will then return for optionProcess() to do the final pass on the command
133275970Scy *  line arguments.
134275970Scy */
135275970Scy
136275970Scy/**
137275970Scy *  scan the command line for immediate action options.
138275970Scy *  This is only called the first time through.
139275970Scy *  While this procedure is active, the OPTPROC_IMMEDIATE is true.
140275970Scy *
141275970Scy *  @param pOpts   program options descriptor
142275970Scy *  @returns SUCCESS or FAILURE
143275970Scy */
144275970ScyLOCAL tSuccess
145275970Scyimmediate_opts(tOptions * opts)
146275970Scy{
147275970Scy    tSuccess  res;
148275970Scy
149275970Scy    opts->fOptSet  |= OPTPROC_IMMEDIATE;
150275970Scy    opts->curOptIdx = 1;     /* start by skipping program name */
151275970Scy    opts->pzCurOpt  = NULL;
152275970Scy
153275970Scy    /*
154275970Scy     *  Examine all the options from the start.  We process any options that
155275970Scy     *  are marked for immediate processing.
156275970Scy     */
157275970Scy    for (;;) {
158275970Scy        tOptState opt_st = OPTSTATE_INITIALIZER(PRESET);
159275970Scy
160275970Scy        res = next_opt(opts, &opt_st);
161275970Scy        switch (res) {
162275970Scy        case FAILURE: goto   failed_option;
163275970Scy        case PROBLEM: res = SUCCESS; goto leave;
164275970Scy        case SUCCESS: break;
165275970Scy        }
166275970Scy
167275970Scy        /*
168275970Scy         *  IF this is an immediate-attribute option, then do it.
169275970Scy         */
170275970Scy        if (! DO_IMMEDIATELY(opt_st.flags))
171275970Scy            continue;
172275970Scy
173275970Scy        if (! SUCCESSFUL(handle_opt(opts, &opt_st)))
174275970Scy            break;
175275970Scy    } failed_option:;
176275970Scy
177275970Scy    if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0)
178275970Scy        (*opts->pUsageProc)(opts, EXIT_FAILURE);
179275970Scy
180275970Scy leave:
181275970Scy
182275970Scy    opts->fOptSet &= ~OPTPROC_IMMEDIATE;
183275970Scy    return res;
184275970Scy}
185275970Scy
186275970Scy/**
187275970Scy *  check for preset values from a config files or envrionment variables
188275970Scy *
189275970Scy * @param[in,out] opts  the structure with the option names to check
190275970Scy */
191275970Scystatic tSuccess
192275970Scydo_presets(tOptions * opts)
193275970Scy{
194275970Scy    tOptDesc * od = NULL;
195275970Scy
196275970Scy    if (! SUCCESSFUL(immediate_opts(opts)))
197275970Scy        return FAILURE;
198275970Scy
199275970Scy    /*
200275970Scy     *  IF this option set has a --save-opts option, then it also
201275970Scy     *  has a --load-opts option.  See if a command line option has disabled
202275970Scy     *  option presetting.
203275970Scy     */
204275970Scy    if (  (opts->specOptIdx.save_opts != NO_EQUIVALENT)
205275970Scy       && (opts->specOptIdx.save_opts != 0)) {
206275970Scy        od = opts->pOptDesc + opts->specOptIdx.save_opts + 1;
207275970Scy        if (DISABLED_OPT(od))
208275970Scy            return SUCCESS;
209275970Scy    }
210275970Scy
211275970Scy    /*
212275970Scy     *  Until we return from this procedure, disable non-presettable opts
213275970Scy     */
214275970Scy    opts->fOptSet |= OPTPROC_PRESETTING;
215275970Scy    /*
216275970Scy     *  IF there are no config files,
217275970Scy     *  THEN do any environment presets and leave.
218275970Scy     */
219275970Scy    if (opts->papzHomeList == NULL) {
220275970Scy        env_presets(opts, ENV_ALL);
221275970Scy    }
222275970Scy    else {
223275970Scy        env_presets(opts, ENV_IMM);
224275970Scy
225275970Scy        /*
226275970Scy         *  Check to see if environment variables have disabled presetting.
227275970Scy         */
228275970Scy        if ((od != NULL) && ! DISABLED_OPT(od))
229275970Scy            intern_file_load(opts);
230275970Scy
231275970Scy        /*
232275970Scy         *  ${PROGRAM_LOAD_OPTS} value of "no" cannot disable other environment
233275970Scy         *  variable options.  Only the loading of .rc files.
234275970Scy         */
235275970Scy        env_presets(opts, ENV_NON_IMM);
236275970Scy    }
237275970Scy    opts->fOptSet &= ~OPTPROC_PRESETTING;
238275970Scy
239275970Scy    return SUCCESS;
240275970Scy}
241275970Scy
242275970Scy/**
243275970Scy * AutoOpts initialization
244275970Scy *
245275970Scy * @param[in,out] opts  the structure to initialize
246275970Scy * @param[in]     a_ct  program argument count
247275970Scy * @param[in]     a_v   program argument vector
248275970Scy */
249275970ScyLOCAL bool
250275970Scyao_initialize(tOptions * opts, int a_ct, char ** a_v)
251275970Scy{
252275970Scy    if ((opts->fOptSet & OPTPROC_INITDONE) != 0)
253275970Scy        return true;
254275970Scy
255275970Scy    opts->origArgCt   = (unsigned int)a_ct;
256275970Scy    opts->origArgVect = a_v;
257275970Scy    opts->fOptSet    |= OPTPROC_INITDONE;
258275970Scy
259275970Scy    if (HAS_pzPkgDataDir(opts))
260275970Scy        program_pkgdatadir = opts->pzPkgDataDir;
261275970Scy
262275970Scy    if (! SUCCESSFUL(do_presets(opts)))
263275970Scy        return false;
264275970Scy
265275970Scy    /*
266275970Scy     *  IF option name conversion was suppressed but it is not suppressed
267275970Scy     *  for the command line, then it's time to translate option names.
268275970Scy     *  Usage text will not get retranslated.
269275970Scy     */
270275970Scy    if (  ((opts->fOptSet & OPTPROC_TRANSLATE) != 0)
271275970Scy       && (opts->pTransProc != NULL)
272275970Scy       && ((opts->fOptSet & OPTPROC_NO_XLAT_MASK) == OPTPROC_NXLAT_OPT_CFG)
273275970Scy       )  {
274275970Scy        opts->fOptSet &= ~OPTPROC_NXLAT_OPT_CFG;
275275970Scy        (*opts->pTransProc)();
276275970Scy    }
277275970Scy
278275970Scy    if ((opts->fOptSet & OPTPROC_REORDER) != 0)
279275970Scy        optionSort(opts);
280275970Scy
281275970Scy    opts->curOptIdx   = 1;
282275970Scy    opts->pzCurOpt    = NULL;
283275970Scy    return true;
284275970Scy}
285275970Scy
286275970Scy/** @}
287275970Scy *
288275970Scy * Local Variables:
289275970Scy * mode: C
290275970Scy * c-file-style: "stroustrup"
291275970Scy * indent-tabs-mode: nil
292275970Scy * End:
293275970Scy * end of autoopts/initialize.c */
294