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