load.c revision 1.1.1.6 1 1.1 kardel
2 1.1.1.2 kardel /**
3 1.1.1.2 kardel * \file load.c
4 1.1 kardel *
5 1.1 kardel * This file contains the routines that deal with processing text strings
6 1.1 kardel * for options, either from a NUL-terminated string passed in or from an
7 1.1 kardel * rc/ini file.
8 1.1 kardel *
9 1.1.1.3 christos * @addtogroup autoopts
10 1.1.1.3 christos * @{
11 1.1.1.3 christos */
12 1.1.1.3 christos /*
13 1.1 kardel * This file is part of AutoOpts, a companion to AutoGen.
14 1.1 kardel * AutoOpts is free software.
15 1.1.1.6 christos * AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved
16 1.1 kardel *
17 1.1 kardel * AutoOpts is available under any one of two licenses. The license
18 1.1 kardel * in use must be one of these two and the choice is under the control
19 1.1 kardel * of the user of the license.
20 1.1 kardel *
21 1.1 kardel * The GNU Lesser General Public License, version 3 or later
22 1.1 kardel * See the files "COPYING.lgplv3" and "COPYING.gplv3"
23 1.1 kardel *
24 1.1 kardel * The Modified Berkeley Software Distribution License
25 1.1 kardel * See the file "COPYING.mbsd"
26 1.1 kardel *
27 1.1.1.3 christos * These files have the following sha256 sums:
28 1.1 kardel *
29 1.1.1.3 christos * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3
30 1.1.1.3 christos * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3
31 1.1.1.3 christos * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd
32 1.1 kardel */
33 1.1 kardel
34 1.1 kardel /* = = = START-STATIC-FORWARD = = = */
35 1.1.1.3 christos static bool
36 1.1.1.3 christos get_realpath(char * buf, size_t b_sz);
37 1.1.1.3 christos
38 1.1.1.3 christos static bool
39 1.1.1.3 christos add_prog_path(char * buf, int b_sz, char const * fname, char const * prg_path);
40 1.1.1.3 christos
41 1.1.1.3 christos static bool
42 1.1.1.3 christos add_env_val(char * buf, int buf_sz, char const * name);
43 1.1 kardel
44 1.1.1.3 christos static char *
45 1.1.1.3 christos assemble_arg_val(char * txt, tOptionLoadMode mode);
46 1.1.1.3 christos
47 1.1.1.3 christos static char *
48 1.1.1.3 christos trim_quotes(char * arg);
49 1.1.1.3 christos
50 1.1.1.3 christos static bool
51 1.1.1.3 christos direction_ok(opt_state_mask_t f, int dir);
52 1.1 kardel /* = = = END-STATIC-FORWARD = = = */
53 1.1 kardel
54 1.1.1.3 christos static bool
55 1.1.1.3 christos get_realpath(char * buf, size_t b_sz)
56 1.1.1.3 christos {
57 1.1.1.3 christos #if defined(HAVE_CANONICALIZE_FILE_NAME)
58 1.1.1.3 christos {
59 1.1.1.3 christos size_t name_len;
60 1.1.1.3 christos
61 1.1.1.3 christos char * pz = canonicalize_file_name(buf);
62 1.1.1.3 christos if (pz == NULL)
63 1.1.1.3 christos return false;
64 1.1.1.3 christos
65 1.1.1.3 christos name_len = strlen(pz);
66 1.1.1.3 christos if (name_len >= (size_t)b_sz) {
67 1.1.1.3 christos free(pz);
68 1.1.1.3 christos return false;
69 1.1.1.3 christos }
70 1.1.1.3 christos
71 1.1.1.3 christos memcpy(buf, pz, name_len + 1);
72 1.1.1.3 christos free(pz);
73 1.1.1.3 christos }
74 1.1.1.3 christos
75 1.1.1.3 christos #elif defined(HAVE_REALPATH)
76 1.1.1.3 christos {
77 1.1.1.3 christos size_t name_len;
78 1.1.1.3 christos char z[PATH_MAX+1];
79 1.1.1.3 christos
80 1.1.1.3 christos if (realpath(buf, z) == NULL)
81 1.1.1.3 christos return false;
82 1.1.1.3 christos
83 1.1.1.3 christos name_len = strlen(z);
84 1.1.1.3 christos if (name_len >= b_sz)
85 1.1.1.3 christos return false;
86 1.1.1.3 christos
87 1.1.1.3 christos memcpy(buf, z, name_len + 1);
88 1.1.1.3 christos }
89 1.1.1.3 christos #endif
90 1.1.1.3 christos return true;
91 1.1.1.3 christos }
92 1.1.1.3 christos
93 1.1 kardel /*=export_func optionMakePath
94 1.1 kardel * private:
95 1.1 kardel *
96 1.1 kardel * what: translate and construct a path
97 1.1.1.6 christos * arg: + char * + p_buf + The result buffer +
98 1.1.1.6 christos * arg: + int + b_sz + The size of this buffer +
99 1.1.1.6 christos * arg: + char const * + fname + The input name +
100 1.1.1.6 christos * arg: + char const * + prg_path + The full path of the current program +
101 1.1 kardel *
102 1.1.1.3 christos * ret-type: bool
103 1.1.1.3 christos * ret-desc: true if the name was handled, otherwise false.
104 1.1 kardel * If the name does not start with ``$'', then it is handled
105 1.1 kardel * simply by copying the input name to the output buffer and
106 1.1 kardel * resolving the name with either
107 1.1 kardel * @code{canonicalize_file_name(3GLIBC)} or @code{realpath(3C)}.
108 1.1 kardel *
109 1.1 kardel * doc:
110 1.1 kardel *
111 1.1.1.2 kardel * This routine will copy the @code{pzName} input name into the
112 1.1.1.2 kardel * @code{pzBuf} output buffer, not exceeding @code{bufSize} bytes. If the
113 1.1 kardel * first character of the input name is a @code{'$'} character, then there
114 1.1 kardel * is special handling:
115 1.1 kardel * @*
116 1.1 kardel * @code{$$} is replaced with the directory name of the @code{pzProgPath},
117 1.1 kardel * searching @code{$PATH} if necessary.
118 1.1 kardel * @*
119 1.1 kardel * @code{$@} is replaced with the AutoGen package data installation directory
120 1.1 kardel * (aka @code{pkgdatadir}).
121 1.1 kardel * @*
122 1.1 kardel * @code{$NAME} is replaced by the contents of the @code{NAME} environment
123 1.1 kardel * variable. If not found, the search fails.
124 1.1 kardel *
125 1.1 kardel * Please note: both @code{$$} and @code{$NAME} must be at the start of the
126 1.1 kardel * @code{pzName} string and must either be the entire string or be followed
127 1.1 kardel * by the @code{'/'} (backslash on windows) character.
128 1.1 kardel *
129 1.1.1.3 christos * err: @code{false} is returned if:
130 1.1 kardel * @*
131 1.1 kardel * @bullet{} The input name exceeds @code{bufSize} bytes.
132 1.1 kardel * @*
133 1.1 kardel * @bullet{} @code{$$}, @code{$@@} or @code{$NAME} is not the full string
134 1.1 kardel * and the next character is not '/'.
135 1.1 kardel * @*
136 1.1 kardel * @bullet{} libopts was built without PKGDATADIR defined and @code{$@@}
137 1.1 kardel * was specified.
138 1.1 kardel * @*
139 1.1 kardel * @bullet{} @code{NAME} is not a known environment variable
140 1.1 kardel * @*
141 1.1 kardel * @bullet{} @code{canonicalize_file_name} or @code{realpath} return
142 1.1 kardel * errors (cannot resolve the resulting path).
143 1.1 kardel =*/
144 1.1.1.3 christos bool
145 1.1.1.3 christos optionMakePath(char * p_buf, int b_sz, char const * fname, char const * prg_path)
146 1.1 kardel {
147 1.1.1.3 christos {
148 1.1.1.3 christos size_t len = strlen(fname);
149 1.1 kardel
150 1.1.1.3 christos if (((size_t)b_sz <= len) || (len == 0))
151 1.1.1.3 christos return false;
152 1.1.1.3 christos }
153 1.1 kardel
154 1.1 kardel /*
155 1.1 kardel * IF not an environment variable, just copy the data
156 1.1 kardel */
157 1.1.1.3 christos if (*fname != '$') {
158 1.1.1.3 christos char const * src = fname;
159 1.1.1.3 christos char * dst = p_buf;
160 1.1.1.3 christos int ct = b_sz;
161 1.1 kardel
162 1.1 kardel for (;;) {
163 1.1.1.3 christos if ( (*(dst++) = *(src++)) == NUL)
164 1.1 kardel break;
165 1.1 kardel if (--ct <= 0)
166 1.1.1.3 christos return false;
167 1.1 kardel }
168 1.1 kardel }
169 1.1 kardel
170 1.1 kardel /*
171 1.1 kardel * IF the name starts with "$$", then it must be "$$" or
172 1.1 kardel * it must start with "$$/". In either event, replace the "$$"
173 1.1 kardel * with the path to the executable and append a "/" character.
174 1.1 kardel */
175 1.1.1.3 christos else switch (fname[1]) {
176 1.1 kardel case NUL:
177 1.1.1.3 christos return false;
178 1.1 kardel
179 1.1 kardel case '$':
180 1.1.1.3 christos if (! add_prog_path(p_buf, b_sz, fname, prg_path))
181 1.1.1.3 christos return false;
182 1.1 kardel break;
183 1.1 kardel
184 1.1 kardel case '@':
185 1.1.1.2 kardel if (program_pkgdatadir[0] == NUL)
186 1.1.1.3 christos return false;
187 1.1 kardel
188 1.1.1.3 christos if (snprintf(p_buf, (size_t)b_sz, "%s%s",
189 1.1.1.3 christos program_pkgdatadir, fname + 2) >= b_sz)
190 1.1.1.3 christos return false;
191 1.1 kardel break;
192 1.1 kardel
193 1.1 kardel default:
194 1.1.1.3 christos if (! add_env_val(p_buf, b_sz, fname))
195 1.1.1.3 christos return false;
196 1.1 kardel }
197 1.1 kardel
198 1.1.1.3 christos return get_realpath(p_buf, b_sz);
199 1.1 kardel }
200 1.1 kardel
201 1.1.1.3 christos /**
202 1.1.1.3 christos * convert a leading "$$" into a path to the executable.
203 1.1.1.3 christos */
204 1.1.1.3 christos static bool
205 1.1.1.3 christos add_prog_path(char * buf, int b_sz, char const * fname, char const * prg_path)
206 1.1 kardel {
207 1.1.1.3 christos char const * path;
208 1.1.1.3 christos char const * pz;
209 1.1 kardel int skip = 2;
210 1.1 kardel
211 1.1.1.3 christos switch (fname[2]) {
212 1.1 kardel case DIRCH:
213 1.1 kardel skip = 3;
214 1.1 kardel case NUL:
215 1.1 kardel break;
216 1.1 kardel default:
217 1.1.1.3 christos return false;
218 1.1 kardel }
219 1.1 kardel
220 1.1 kardel /*
221 1.1 kardel * See if the path is included in the program name.
222 1.1 kardel * If it is, we're done. Otherwise, we have to hunt
223 1.1 kardel * for the program using "pathfind".
224 1.1 kardel */
225 1.1.1.3 christos if (strchr(prg_path, DIRCH) != NULL)
226 1.1.1.3 christos path = prg_path;
227 1.1 kardel else {
228 1.1.1.6 christos path = pathfind(getenv("PATH"), (char *)prg_path, "rx");
229 1.1 kardel
230 1.1.1.3 christos if (path == NULL)
231 1.1.1.3 christos return false;
232 1.1 kardel }
233 1.1 kardel
234 1.1.1.3 christos pz = strrchr(path, DIRCH);
235 1.1 kardel
236 1.1 kardel /*
237 1.1 kardel * IF we cannot find a directory name separator,
238 1.1 kardel * THEN we do not have a path name to our executable file.
239 1.1 kardel */
240 1.1 kardel if (pz == NULL)
241 1.1.1.3 christos return false;
242 1.1 kardel
243 1.1.1.3 christos fname += skip;
244 1.1 kardel
245 1.1 kardel /*
246 1.1 kardel * Concatenate the file name to the end of the executable path.
247 1.1 kardel * The result may be either a file or a directory.
248 1.1 kardel */
249 1.1.1.3 christos if ((unsigned)(pz - path) + 1 + strlen(fname) >= (unsigned)b_sz)
250 1.1.1.3 christos return false;
251 1.1 kardel
252 1.1.1.3 christos memcpy(buf, path, (size_t)((pz - path)+1));
253 1.1.1.3 christos strcpy(buf + (pz - path) + 1, fname);
254 1.1 kardel
255 1.1 kardel /*
256 1.1.1.3 christos * If the "path" path was gotten from "pathfind()", then it was
257 1.1 kardel * allocated and we need to deallocate it.
258 1.1 kardel */
259 1.1.1.3 christos if (path != prg_path)
260 1.1.1.3 christos AGFREE(path);
261 1.1.1.3 christos return true;
262 1.1 kardel }
263 1.1 kardel
264 1.1.1.3 christos /**
265 1.1.1.3 christos * Add an environment variable value.
266 1.1.1.3 christos */
267 1.1.1.3 christos static bool
268 1.1.1.3 christos add_env_val(char * buf, int buf_sz, char const * name)
269 1.1 kardel {
270 1.1.1.3 christos char * dir_part = buf;
271 1.1 kardel
272 1.1 kardel for (;;) {
273 1.1.1.3 christos int ch = (int)*++name;
274 1.1 kardel if (! IS_VALUE_NAME_CHAR(ch))
275 1.1 kardel break;
276 1.1.1.3 christos *(dir_part++) = (char)ch;
277 1.1 kardel }
278 1.1 kardel
279 1.1.1.3 christos if (dir_part == buf)
280 1.1.1.3 christos return false;
281 1.1 kardel
282 1.1.1.3 christos *dir_part = NUL;
283 1.1 kardel
284 1.1.1.3 christos dir_part = getenv(buf);
285 1.1 kardel
286 1.1 kardel /*
287 1.1 kardel * Environment value not found -- skip the home list entry
288 1.1 kardel */
289 1.1.1.3 christos if (dir_part == NULL)
290 1.1.1.3 christos return false;
291 1.1 kardel
292 1.1.1.3 christos if (strlen(dir_part) + 1 + strlen(name) >= (unsigned)buf_sz)
293 1.1.1.3 christos return false;
294 1.1 kardel
295 1.1.1.3 christos sprintf(buf, "%s%s", dir_part, name);
296 1.1.1.3 christos return true;
297 1.1 kardel }
298 1.1 kardel
299 1.1.1.3 christos /**
300 1.1.1.3 christos * Trim leading and trailing white space.
301 1.1.1.3 christos * If we are cooking the text and the text is quoted, then "cook"
302 1.1.1.3 christos * the string. To cook, the string must be quoted.
303 1.1.1.3 christos *
304 1.1.1.3 christos * @param[in,out] txt the input and output string
305 1.1.1.3 christos * @param[in] mode the handling mode (cooking method)
306 1.1.1.3 christos */
307 1.1 kardel LOCAL void
308 1.1.1.3 christos munge_str(char * txt, tOptionLoadMode mode)
309 1.1 kardel {
310 1.1.1.3 christos char * pzE;
311 1.1 kardel
312 1.1 kardel if (mode == OPTION_LOAD_KEEP)
313 1.1 kardel return;
314 1.1 kardel
315 1.1.1.3 christos if (IS_WHITESPACE_CHAR(*txt)) {
316 1.1.1.3 christos char * src = SPN_WHITESPACE_CHARS(txt+1);
317 1.1.1.3 christos size_t l = strlen(src) + 1;
318 1.1.1.3 christos memmove(txt, src, l);
319 1.1.1.3 christos pzE = txt + l - 1;
320 1.1.1.3 christos
321 1.1 kardel } else
322 1.1.1.3 christos pzE = txt + strlen(txt);
323 1.1 kardel
324 1.1.1.3 christos pzE = SPN_WHITESPACE_BACK(txt, pzE);
325 1.1 kardel *pzE = NUL;
326 1.1 kardel
327 1.1 kardel if (mode == OPTION_LOAD_UNCOOKED)
328 1.1 kardel return;
329 1.1 kardel
330 1.1.1.3 christos switch (*txt) {
331 1.1 kardel default: return;
332 1.1 kardel case '"':
333 1.1 kardel case '\'': break;
334 1.1 kardel }
335 1.1 kardel
336 1.1 kardel switch (pzE[-1]) {
337 1.1 kardel default: return;
338 1.1 kardel case '"':
339 1.1 kardel case '\'': break;
340 1.1 kardel }
341 1.1 kardel
342 1.1.1.3 christos (void)ao_string_cook(txt, NULL);
343 1.1 kardel }
344 1.1 kardel
345 1.1.1.3 christos static char *
346 1.1.1.3 christos assemble_arg_val(char * txt, tOptionLoadMode mode)
347 1.1 kardel {
348 1.1.1.3 christos char * end = strpbrk(txt, ARG_BREAK_STR);
349 1.1.1.3 christos int space_break;
350 1.1 kardel
351 1.1 kardel /*
352 1.1 kardel * Not having an argument to a configurable name is okay.
353 1.1 kardel */
354 1.1.1.3 christos if (end == NULL)
355 1.1.1.3 christos return txt + strlen(txt);
356 1.1 kardel
357 1.1 kardel /*
358 1.1 kardel * If we are keeping all whitespace, then the modevalue starts with the
359 1.1 kardel * character that follows the end of the configurable name, regardless
360 1.1 kardel * of which character caused it.
361 1.1 kardel */
362 1.1 kardel if (mode == OPTION_LOAD_KEEP) {
363 1.1.1.3 christos *(end++) = NUL;
364 1.1.1.3 christos return end;
365 1.1 kardel }
366 1.1 kardel
367 1.1 kardel /*
368 1.1 kardel * If the name ended on a white space character, remember that
369 1.1 kardel * because we'll have to skip over an immediately following ':' or '='
370 1.1 kardel * (and the white space following *that*).
371 1.1 kardel */
372 1.1.1.3 christos space_break = IS_WHITESPACE_CHAR(*end);
373 1.1.1.3 christos *(end++) = NUL;
374 1.1.1.3 christos
375 1.1.1.3 christos end = SPN_WHITESPACE_CHARS(end);
376 1.1.1.3 christos if (space_break && ((*end == ':') || (*end == '=')))
377 1.1.1.3 christos end = SPN_WHITESPACE_CHARS(end+1);
378 1.1 kardel
379 1.1.1.3 christos return end;
380 1.1 kardel }
381 1.1 kardel
382 1.1.1.3 christos static char *
383 1.1.1.3 christos trim_quotes(char * arg)
384 1.1.1.3 christos {
385 1.1.1.3 christos switch (*arg) {
386 1.1.1.3 christos case '"':
387 1.1.1.3 christos case '\'':
388 1.1.1.3 christos ao_string_cook(arg, NULL);
389 1.1.1.3 christos }
390 1.1.1.3 christos return arg;
391 1.1.1.3 christos }
392 1.1 kardel
393 1.1.1.3 christos /**
394 1.1.1.3 christos * See if the option is to be processed in the current scan direction
395 1.1.1.3 christos * (-1 or +1).
396 1.1 kardel */
397 1.1.1.3 christos static bool
398 1.1.1.3 christos direction_ok(opt_state_mask_t f, int dir)
399 1.1 kardel {
400 1.1.1.3 christos if (dir == 0)
401 1.1.1.3 christos return true;
402 1.1 kardel
403 1.1.1.3 christos switch (f & (OPTST_IMM|OPTST_DISABLE_IMM)) {
404 1.1 kardel case 0:
405 1.1 kardel /*
406 1.1 kardel * The selected option has no immediate action.
407 1.1 kardel * THEREFORE, if the direction is PRESETTING
408 1.1 kardel * THEN we skip this option.
409 1.1 kardel */
410 1.1.1.3 christos if (PRESETTING(dir))
411 1.1.1.3 christos return false;
412 1.1 kardel break;
413 1.1 kardel
414 1.1 kardel case OPTST_IMM:
415 1.1.1.3 christos if (PRESETTING(dir)) {
416 1.1 kardel /*
417 1.1 kardel * We are in the presetting direction with an option we handle
418 1.1 kardel * immediately for enablement, but normally for disablement.
419 1.1 kardel * Therefore, skip if disabled.
420 1.1 kardel */
421 1.1.1.3 christos if ((f & OPTST_DISABLED) == 0)
422 1.1.1.3 christos return false;
423 1.1 kardel } else {
424 1.1 kardel /*
425 1.1 kardel * We are in the processing direction with an option we handle
426 1.1 kardel * immediately for enablement, but normally for disablement.
427 1.1 kardel * Therefore, skip if NOT disabled.
428 1.1 kardel */
429 1.1.1.3 christos if ((f & OPTST_DISABLED) != 0)
430 1.1.1.3 christos return false;
431 1.1 kardel }
432 1.1 kardel break;
433 1.1 kardel
434 1.1 kardel case OPTST_DISABLE_IMM:
435 1.1.1.3 christos if (PRESETTING(dir)) {
436 1.1 kardel /*
437 1.1 kardel * We are in the presetting direction with an option we handle
438 1.1 kardel * immediately for disablement, but normally for disablement.
439 1.1 kardel * Therefore, skip if NOT disabled.
440 1.1 kardel */
441 1.1.1.3 christos if ((f & OPTST_DISABLED) != 0)
442 1.1.1.3 christos return false;
443 1.1 kardel } else {
444 1.1 kardel /*
445 1.1 kardel * We are in the processing direction with an option we handle
446 1.1 kardel * immediately for disablement, but normally for disablement.
447 1.1 kardel * Therefore, skip if disabled.
448 1.1 kardel */
449 1.1.1.3 christos if ((f & OPTST_DISABLED) == 0)
450 1.1.1.3 christos return false;
451 1.1 kardel }
452 1.1 kardel break;
453 1.1 kardel
454 1.1 kardel case OPTST_IMM|OPTST_DISABLE_IMM:
455 1.1 kardel /*
456 1.1 kardel * The selected option is always for immediate action.
457 1.1 kardel * THEREFORE, if the direction is PROCESSING
458 1.1 kardel * THEN we skip this option.
459 1.1 kardel */
460 1.1.1.3 christos if (PROCESSING(dir))
461 1.1.1.3 christos return false;
462 1.1 kardel break;
463 1.1 kardel }
464 1.1.1.3 christos return true;
465 1.1.1.3 christos }
466 1.1.1.3 christos
467 1.1.1.3 christos /**
468 1.1.1.3 christos * Load an option from a block of text. The text must start with the
469 1.1.1.3 christos * configurable/option name and be followed by its associated value.
470 1.1.1.3 christos * That value may be processed in any of several ways. See "tOptionLoadMode"
471 1.1.1.3 christos * in autoopts.h.
472 1.1.1.3 christos *
473 1.1.1.3 christos * @param[in,out] opts program options descriptor
474 1.1.1.3 christos * @param[in,out] opt_state option processing state
475 1.1.1.3 christos * @param[in,out] line source line with long option name in it
476 1.1.1.3 christos * @param[in] direction current processing direction (preset or not)
477 1.1.1.3 christos * @param[in] load_mode option loading mode (OPTION_LOAD_*)
478 1.1.1.3 christos */
479 1.1.1.3 christos LOCAL void
480 1.1.1.3 christos load_opt_line(tOptions * opts, tOptState * opt_state, char * line,
481 1.1.1.3 christos tDirection direction, tOptionLoadMode load_mode )
482 1.1.1.3 christos {
483 1.1.1.3 christos /*
484 1.1.1.3 christos * When parsing a stored line, we only look at the characters after
485 1.1.1.3 christos * a hyphen. Long names must always be at least two characters and
486 1.1.1.3 christos * short options are always exactly one character long.
487 1.1.1.3 christos */
488 1.1.1.3 christos line = SPN_LOAD_LINE_SKIP_CHARS(line);
489 1.1.1.3 christos
490 1.1.1.3 christos {
491 1.1.1.3 christos char * arg = assemble_arg_val(line, load_mode);
492 1.1.1.3 christos
493 1.1.1.3 christos if (IS_OPTION_NAME_CHAR(line[1])) {
494 1.1.1.3 christos
495 1.1.1.3 christos if (! SUCCESSFUL(opt_find_long(opts, line, opt_state)))
496 1.1.1.3 christos return;
497 1.1.1.3 christos
498 1.1.1.3 christos } else if (! SUCCESSFUL(opt_find_short(opts, *line, opt_state)))
499 1.1.1.3 christos return;
500 1.1.1.3 christos
501 1.1.1.3 christos if ((! CALLED(direction)) && (opt_state->flags & OPTST_NO_INIT))
502 1.1.1.3 christos return;
503 1.1.1.3 christos
504 1.1.1.3 christos opt_state->pzOptArg = trim_quotes(arg);
505 1.1.1.3 christos }
506 1.1.1.3 christos
507 1.1.1.3 christos if (! direction_ok(opt_state->flags, direction))
508 1.1.1.3 christos return;
509 1.1 kardel
510 1.1 kardel /*
511 1.1 kardel * Fix up the args.
512 1.1 kardel */
513 1.1.1.3 christos if (OPTST_GET_ARGTYPE(opt_state->pOD->fOptState) == OPARG_TYPE_NONE) {
514 1.1.1.3 christos if (*opt_state->pzOptArg != NUL)
515 1.1 kardel return;
516 1.1.1.3 christos opt_state->pzOptArg = NULL;
517 1.1 kardel
518 1.1.1.3 christos } else if (opt_state->pOD->fOptState & OPTST_ARG_OPTIONAL) {
519 1.1.1.3 christos if (*opt_state->pzOptArg == NUL)
520 1.1.1.3 christos opt_state->pzOptArg = NULL;
521 1.1 kardel else {
522 1.1.1.3 christos AGDUPSTR(opt_state->pzOptArg, opt_state->pzOptArg, "opt arg");
523 1.1.1.3 christos opt_state->flags |= OPTST_ALLOC_ARG;
524 1.1 kardel }
525 1.1 kardel
526 1.1 kardel } else {
527 1.1.1.3 christos if (*opt_state->pzOptArg == NUL)
528 1.1.1.3 christos opt_state->pzOptArg = zNil;
529 1.1 kardel else {
530 1.1.1.3 christos AGDUPSTR(opt_state->pzOptArg, opt_state->pzOptArg, "opt arg");
531 1.1.1.3 christos opt_state->flags |= OPTST_ALLOC_ARG;
532 1.1 kardel }
533 1.1 kardel }
534 1.1 kardel
535 1.1 kardel {
536 1.1 kardel tOptionLoadMode sv = option_load_mode;
537 1.1 kardel option_load_mode = load_mode;
538 1.1.1.3 christos handle_opt(opts, opt_state);
539 1.1 kardel option_load_mode = sv;
540 1.1 kardel }
541 1.1 kardel }
542 1.1 kardel
543 1.1 kardel /*=export_func optionLoadLine
544 1.1 kardel *
545 1.1 kardel * what: process a string for an option name and value
546 1.1 kardel *
547 1.1.1.6 christos * arg: tOptions *, opts, program options descriptor
548 1.1.1.6 christos * arg: char const *, line, NUL-terminated text
549 1.1 kardel *
550 1.1 kardel * doc:
551 1.1 kardel *
552 1.1 kardel * This is a client program callable routine for setting options from, for
553 1.1 kardel * example, the contents of a file that they read in. Only one option may
554 1.1 kardel * appear in the text. It will be treated as a normal (non-preset) option.
555 1.1 kardel *
556 1.1 kardel * When passed a pointer to the option struct and a string, it will find
557 1.1 kardel * the option named by the first token on the string and set the option
558 1.1 kardel * argument to the remainder of the string. The caller must NUL terminate
559 1.1.1.3 christos * the string. The caller need not skip over any introductory hyphens.
560 1.1.1.3 christos * Any embedded new lines will be included in the option
561 1.1 kardel * argument. If the input looks like one or more quoted strings, then the
562 1.1 kardel * input will be "cooked". The "cooking" is identical to the string
563 1.1 kardel * formation used in AutoGen definition files (@pxref{basic expression}),
564 1.1 kardel * except that you may not use backquotes.
565 1.1 kardel *
566 1.1 kardel * err: Invalid options are silently ignored. Invalid option arguments
567 1.1 kardel * will cause a warning to print, but the function should return.
568 1.1 kardel =*/
569 1.1 kardel void
570 1.1.1.3 christos optionLoadLine(tOptions * opts, char const * line)
571 1.1 kardel {
572 1.1 kardel tOptState st = OPTSTATE_INITIALIZER(SET);
573 1.1.1.3 christos char * pz;
574 1.1.1.3 christos proc_state_mask_t sv_flags = opts->fOptSet;
575 1.1.1.3 christos opts->fOptSet &= ~OPTPROC_ERRSTOP;
576 1.1.1.3 christos AGDUPSTR(pz, line, "opt line");
577 1.1.1.3 christos load_opt_line(opts, &st, pz, DIRECTION_CALLED, OPTION_LOAD_COOKED);
578 1.1.1.2 kardel AGFREE(pz);
579 1.1.1.3 christos opts->fOptSet = sv_flags;
580 1.1 kardel }
581 1.1.1.3 christos /** @}
582 1.1.1.3 christos *
583 1.1 kardel * Local Variables:
584 1.1 kardel * mode: C
585 1.1 kardel * c-file-style: "stroustrup"
586 1.1 kardel * indent-tabs-mode: nil
587 1.1 kardel * End:
588 1.1 kardel * end of autoopts/load.c */
589