4 * @brief Hunt for options in the option descriptor list
6 * Time-stamp: "2012-01-29 19:07:30 bkorb"
8 * This file contains the routines that deal with processing quoted strings
9 * into an internal format.
11 * This file is part of AutoOpts, a companion to AutoGen.
12 * AutoOpts is free software.
13 * AutoOpts is Copyright (c) 1992-2012 by Bruce Korb - all rights reserved
15 * AutoOpts is available under any one of two licenses. The license
16 * in use must be one of these two and the choice is under the control
17 * of the user of the license.
19 * The GNU Lesser General Public License, version 3 or later
20 * See the files "COPYING.lgplv3" and "COPYING.gplv3"
22 * The Modified Berkeley Software Distribution License
23 * See the file "COPYING.mbsd"
25 * These files have the following md5sums:
27 * 43b91e8ca915626ed3818ffb1b71248b pkg/libopts/COPYING.gplv3
28 * 06a1a2e4760c90ea5e1dad8dfaac4d39 pkg/libopts/COPYING.lgplv3
29 * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
33 * find the name and name length we are looking for
36 parse_opt(char const ** nm_pp
, char ** arg_pp
, char * buf
, size_t bufsz
)
39 char const * p
= *nm_pp
;
47 if (res
>= (int)bufsz
)
50 memcpy(buf
, *nm_pp
, res
);
64 * print out the options that match the given name.
66 * @param pOpts option data
67 * @param opt_name name of option to look for
70 opt_ambiguities(tOptions
* opts
, char const * name
, int nm_len
)
72 char const * const hyph
=
73 NAMED_OPTS(opts
) ? "" : LONG_OPT_MARKER
;
75 tOptDesc
* pOD
= opts
->pOptDesc
;
78 fputs(zAmbigList
, stderr
);
80 if (strneqvcmp(name
, pOD
->pz_Name
, nm_len
) == 0)
81 fprintf(stderr
, zAmbiguous
, hyph
, pOD
->pz_Name
);
83 else if ( (pOD
->pz_DisableName
!= NULL
)
84 && (strneqvcmp(name
, pOD
->pz_DisableName
, nm_len
) == 0)
86 fprintf(stderr
, zAmbiguous
, hyph
, pOD
->pz_DisableName
);
87 } while (pOD
++, (++idx
< opts
->optCt
));
91 * Determine the number of options that match the name
93 * @param pOpts option data
94 * @param opt_name name of option to look for
95 * @param nm_len length of provided name
96 * @param index pointer to int for option index
97 * @param disable pointer to bool to mark disabled option
98 * @return count of options that match
101 opt_match_ct(tOptions
* opts
, char const * name
, int nm_len
,
102 int * ixp
, bool * disable
)
106 int idxLim
= opts
->optCt
;
107 tOptDesc
* pOD
= opts
->pOptDesc
;
111 * If option disabled or a doc option, skip to next
113 if (pOD
->pz_Name
== NULL
)
117 && (pOD
->fOptState
!= (OPTST_OMITTED
| OPTST_NO_INIT
)))
120 if (strneqvcmp(name
, pOD
->pz_Name
, nm_len
) == 0) {
122 * IF we have a complete match
123 * THEN it takes priority over any already located partial
125 if (pOD
->pz_Name
[ nm_len
] == NUL
) {
132 * IF there is a disable name
133 * *AND* the option name matches the disable name
136 else if ( (pOD
->pz_DisableName
!= NULL
)
137 && (strneqvcmp(name
, pOD
->pz_DisableName
, nm_len
) == 0)
142 * IF we have a complete match
143 * THEN it takes priority over any already located partial
145 if (pOD
->pz_DisableName
[ nm_len
] == NUL
) {
152 continue; /* does not match any option */
155 * We found a full or partial match, either regular or disabling.
156 * Remember the index for later.
161 } while (pOD
++, (++idx
< idxLim
));
167 * Set the option to the indicated option number.
169 * @param opts option data
170 * @param arg option argument (if glued to name)
171 * @param idx option index
172 * @param disable mark disabled option
173 * @param st state about current option
176 opt_set(tOptions
* opts
, char * arg
, int idx
, bool disable
, tOptState
* st
)
178 tOptDesc
* pOD
= opts
->pOptDesc
+ idx
;
181 if ((opts
->fOptSet
& OPTPROC_ERRSTOP
) == 0)
184 fprintf(stderr
, zDisabledErr
, opts
->pzProgName
, pOD
->pz_Name
);
185 if (pOD
->pzText
!= NULL
)
186 fprintf(stderr
, SET_OFF_FMT
, pOD
->pzText
);
188 (*opts
->pUsageProc
)(opts
, EXIT_FAILURE
);
190 _exit(EXIT_FAILURE
); /* to be certain */
194 * IF we found a disablement name,
195 * THEN set the bit in the callers' flag word
198 st
->flags
|= OPTST_DISABLED
;
202 st
->optType
= TOPT_LONG
;
208 * An option was not found. Check for default option and set it
209 * if there is one. Otherwise, handle the error.
211 * @param opts option data
212 * @param name name of option to look for
213 * @param arg option argument
214 * @param st state about current option
216 * @return success status
219 opt_unknown(tOptions
* opts
, char const * name
, char * arg
, tOptState
* st
)
222 * IF there is no equal sign
223 * *AND* we are using named arguments
224 * *AND* there is a default named option,
225 * THEN return that option.
229 && (opts
->specOptIdx
.default_opt
!= NO_EQUIVALENT
)) {
231 st
->pOD
= opts
->pOptDesc
+ opts
->specOptIdx
.default_opt
;
233 st
->optType
= TOPT_DEFAULT
;
237 if ((opts
->fOptSet
& OPTPROC_ERRSTOP
) != 0) {
238 fprintf(stderr
, zIllOptStr
, opts
->pzProgPath
, name
);
239 (*opts
->pUsageProc
)(opts
, EXIT_FAILURE
);
241 _exit(EXIT_FAILURE
); /* to be certain */
248 * Several options match the provided name.
250 * @param opts option data
251 * @param name name of option to look for
252 * @param match_ct number of matching options
254 * @return success status (always FAILURE, if it returns)
257 opt_ambiguous(tOptions
* opts
, char const * name
, int match_ct
)
259 if ((opts
->fOptSet
& OPTPROC_ERRSTOP
) != 0) {
260 fprintf(stderr
, zAmbigOptStr
, opts
->pzProgPath
, name
, match_ct
);
262 opt_ambiguities(opts
, name
, strlen(name
));
263 (*opts
->pUsageProc
)(opts
, EXIT_FAILURE
);
265 _exit(EXIT_FAILURE
); /* to be certain */
270 /*=export_func optionVendorOption
273 * what: Process a vendor option
274 * arg: + tOptions * + pOpts + program options descriptor +
275 * arg: + tOptDesc * + pOptDesc + the descriptor for this arg +
278 * For POSIX specified utilities, the options are constrained to the options,
279 * @xref{config attributes, Program Configuration}. AutoOpts clients should
280 * never specify this directly. It gets referenced when the option
281 * definitions contain a "vendor-opt" attribute.
284 optionVendorOption(tOptions
* pOpts
, tOptDesc
* pOD
)
286 tOptState opt_st
= OPTSTATE_INITIALIZER(PRESET
);
287 char const * vopt_str
= pOD
->optArg
.argString
;
289 if ((pOD
->fOptState
& OPTPROC_IMMEDIATE
) == 0)
290 opt_st
.flags
= OPTST_DEFINED
;
292 if ( ((pOpts
->fOptSet
& OPTPROC_VENDOR_OPT
) == 0)
293 || ! SUCCESSFUL(opt_find_long(pOpts
, vopt_str
, &opt_st
))
294 || ! SUCCESSFUL(get_opt_arg(pOpts
, &opt_st
)) )
296 fprintf(stderr
, zIllVendOptStr
, vopt_str
);
297 (*pOpts
->pUsageProc
)(pOpts
, EXIT_FAILURE
);
302 * See if we are in immediate handling state.
304 if (pOpts
->fOptSet
& OPTPROC_IMMEDIATE
) {
306 * See if the enclosed option is okay with that state.
308 if (DO_IMMEDIATELY(opt_st
.flags
))
309 (void)handle_opt(pOpts
, &opt_st
);
313 * non-immediate direction.
314 * See if the enclosed option is okay with that state.
316 if (DO_NORMALLY(opt_st
.flags
) || DO_SECOND_TIME(opt_st
.flags
))
317 (void)handle_opt(pOpts
, &opt_st
);
322 * Find the option descriptor by full name.
324 * @param pOpts option data
325 * @param opt_name name of option to look for
326 * @param pOptState state about current option
328 * @return success status
331 opt_find_long(tOptions
* pOpts
, char const * opt_name
, tOptState
* pOptState
)
335 int nm_len
= parse_opt(&opt_name
, &opt_arg
, name_buf
, sizeof(name_buf
));
338 bool disable
= false;
340 opt_match_ct(pOpts
, opt_name
, nm_len
, &matchIdx
, &disable
);
343 * See if we found one match, no matches or multiple matches.
346 case 1: return opt_set(pOpts
, opt_arg
, matchIdx
, disable
, pOptState
);
347 case 0: return opt_unknown(pOpts
, opt_name
, opt_arg
, pOptState
);
348 default: return opt_ambiguous(pOpts
, opt_name
, match_ct
);
354 * Find the short option descriptor for the current option
356 * @param pOpts option data
357 * @param optValue option flag character
358 * @param pOptState state about current option
361 opt_find_short(tOptions
* pOpts
, uint_t optValue
, tOptState
* pOptState
)
363 tOptDesc
* pRes
= pOpts
->pOptDesc
;
364 int ct
= pOpts
->optCt
;
367 * Search the option list
370 if (optValue
!= pRes
->optValue
)
373 if (SKIP_OPT(pRes
)) {
374 if ( (pRes
->fOptState
== (OPTST_OMITTED
| OPTST_NO_INIT
))
375 && (pRes
->pz_Name
!= NULL
)) {
376 fprintf(stderr
, zDisabledErr
, pOpts
->pzProgPath
, pRes
->pz_Name
);
377 if (pRes
->pzText
!= NULL
)
378 fprintf(stderr
, SET_OFF_FMT
, pRes
->pzText
);
380 (*pOpts
->pUsageProc
)(pOpts
, EXIT_FAILURE
);
382 _exit(EXIT_FAILURE
); /* to be certain */
384 goto short_opt_error
;
387 pOptState
->pOD
= pRes
;
388 pOptState
->optType
= TOPT_SHORT
;
391 } while (pRes
++, --ct
> 0);
394 * IF the character value is a digit
395 * AND there is a special number option ("-n")
396 * THEN the result is the "option" itself and the
397 * option is the specially marked "number" option.
399 if ( IS_DEC_DIGIT_CHAR(optValue
)
400 && (pOpts
->specOptIdx
.number_option
!= NO_EQUIVALENT
) ) {
402 pRes
= pOpts
->pOptDesc
+ pOpts
->specOptIdx
.number_option
;
404 pOptState
->optType
= TOPT_SHORT
;
411 * IF we are to stop on errors (the default, actually)
412 * THEN call the usage procedure.
414 if ((pOpts
->fOptSet
& OPTPROC_ERRSTOP
) != 0) {
415 fprintf(stderr
, zIllOptChr
, pOpts
->pzProgPath
, optValue
);
416 (*pOpts
->pUsageProc
)(pOpts
, EXIT_FAILURE
);
418 _exit(EXIT_FAILURE
); /* to be certain */
425 get_opt_arg(tOptions
* pOpts
, tOptState
* pOptState
)
427 pOptState
->flags
|= (pOptState
->pOD
->fOptState
& OPTST_PERSISTENT_MASK
);
430 * Figure out what to do about option arguments. An argument may be
431 * required, not associated with the option, or be optional. We detect the
432 * latter by examining for an option marker on the next possible argument.
433 * Disabled mode option selection also disables option arguments.
436 enum { ARG_NONE
, ARG_MAY
, ARG_MUST
} arg_type
= ARG_NONE
;
439 if ((pOptState
->flags
& OPTST_DISABLED
) != 0)
442 else if (OPTST_GET_ARGTYPE(pOptState
->flags
) == OPARG_TYPE_NONE
)
445 else if (pOptState
->flags
& OPTST_ARG_OPTIONAL
)
452 case ARG_MUST
: res
= next_opt_arg_must(pOpts
, pOptState
); break;
453 case ARG_MAY
: res
= next_opt_arg_may( pOpts
, pOptState
); break;
454 case ARG_NONE
: res
= next_opt_arg_none(pOpts
, pOptState
); break;
462 * Find the option descriptor for the current option
465 find_opt(tOptions
* pOpts
, tOptState
* pOptState
)
468 * IF we are continuing a short option list (e.g. -xyz...)
469 * THEN continue a single flag option.
470 * OTHERWISE see if there is room to advance and then do so.
472 if ((pOpts
->pzCurOpt
!= NULL
) && (*pOpts
->pzCurOpt
!= NUL
))
473 return opt_find_short(pOpts
, (tAoUC
)*(pOpts
->pzCurOpt
), pOptState
);
475 if (pOpts
->curOptIdx
>= pOpts
->origArgCt
)
476 return PROBLEM
; /* NORMAL COMPLETION */
478 pOpts
->pzCurOpt
= pOpts
->origArgVect
[ pOpts
->curOptIdx
];
481 * IF all arguments must be named options, ...
483 if (NAMED_OPTS(pOpts
)) {
484 char * pz
= pOpts
->pzCurOpt
;
492 return opt_find_long(pOpts
, pz
, pOptState
);
495 * The name is prefixed with one or more hyphens. Strip them off
496 * and disable the "default_opt" setting. Use heavy recasting to
497 * strip off the "const" quality of the "default_opt" field.
499 while (*(++pz
) == '-') ;
500 def_opt
= (void *)&(pOpts
->specOptIdx
.default_opt
);
502 *def_opt
= NO_EQUIVALENT
;
503 res
= opt_find_long(pOpts
, pz
, pOptState
);
509 * Note the kind of flag/option marker
511 if (*((pOpts
->pzCurOpt
)++) != '-')
512 return PROBLEM
; /* NORMAL COMPLETION - this + rest are operands */
515 * Special hack for a hyphen by itself
517 if (*(pOpts
->pzCurOpt
) == NUL
)
518 return PROBLEM
; /* NORMAL COMPLETION - this + rest are operands */
521 * The current argument is to be processed as an option argument
526 * We have an option marker.
527 * Test the next character for long option indication
529 if (pOpts
->pzCurOpt
[0] == '-') {
530 if (*++(pOpts
->pzCurOpt
) == NUL
)
532 * NORMAL COMPLETION - NOT this arg, but rest are operands
537 * We do not allow the hyphen to be used as a flag value.
538 * Therefore, if long options are not to be accepted, we punt.
540 if ((pOpts
->fOptSet
& OPTPROC_LONGOPT
) == 0) {
541 fprintf(stderr
, zIllOptStr
, pOpts
->pzProgPath
,
546 return opt_find_long(pOpts
, pOpts
->pzCurOpt
, pOptState
);
550 * If short options are not allowed, then do long
551 * option processing. Otherwise the character must be a
552 * short (i.e. single character) option.
554 if ((pOpts
->fOptSet
& OPTPROC_SHORTOPT
) != 0)
555 return opt_find_short(pOpts
, (tAoUC
)*(pOpts
->pzCurOpt
), pOptState
);
557 return opt_find_long(pOpts
, pOpts
->pzCurOpt
, pOptState
);
563 * c-file-style: "stroustrup"
564 * indent-tabs-mode: nil
566 * end of autoopts/find.c */