1 /**
2 * @file check.c
3 *
4 * @brief Hunt for options in the option descriptor list
5 *
6 * This file contains the routines that deal with processing quoted strings
7 * into an internal format.
8 *
9 * @addtogroup autoopts
10 * @{
11 */
12 /*
13 * This file is part of AutoOpts, a companion to AutoGen.
14 * AutoOpts is free software.
15 * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved
16 *
17 * AutoOpts is available under any one of two licenses. The license
18 * in use must be one of these two and the choice is under the control
19 * of the user of the license.
20 *
21 * The GNU Lesser General Public License, version 3 or later
22 * See the files "COPYING.lgplv3" and "COPYING.gplv3"
23 *
24 * The Modified Berkeley Software Distribution License
25 * See the file "COPYING.mbsd"
26 *
27 * These files have the following sha256 sums:
28 *
29 * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3
30 * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3
31 * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd
32 */
33
34 /**
35 * find the name and name length we are looking for
36 */
37 static int
parse_opt(char const ** nm_pp,char ** arg_pp,char * buf,size_t bufsz)38 parse_opt(char const ** nm_pp, char ** arg_pp, char * buf, size_t bufsz)
39 {
40 int res = 0;
41 char const * p = *nm_pp;
42 *arg_pp = NULL;
43
44 for (;;) {
45 switch (*(p++)) {
46 case NUL: return res;
47
48 case '=':
49 memcpy(buf, *nm_pp, (size_t)res);
50
51 buf[res] = NUL;
52 *nm_pp = buf;
53 *arg_pp = (char *)p;
54 return res;
55
56 default:
57 if (++res >= (int)bufsz)
58 return -1;
59 }
60 }
61 }
62
63 /**
64 * print out the options that match the given name.
65 *
66 * @param pOpts option data
67 * @param opt_name name of option to look for
68 */
69 static void
opt_ambiguities(tOptions * opts,char const * name,int nm_len)70 opt_ambiguities(tOptions * opts, char const * name, int nm_len)
71 {
72 char const * const hyph =
73 NAMED_OPTS(opts) ? "" : LONG_OPT_MARKER;
74
75 tOptDesc * pOD = opts->pOptDesc;
76 int idx = 0;
77
78 fputs(zambig_list_msg, stderr);
79 do {
80 if (pOD->pz_Name == NULL)
81 continue; /* doc option */
82
83 if (strneqvcmp(name, pOD->pz_Name, nm_len) == 0)
84 fprintf(stderr, zambig_file, hyph, pOD->pz_Name);
85
86 else if ( (pOD->pz_DisableName != NULL)
87 && (strneqvcmp(name, pOD->pz_DisableName, nm_len) == 0)
88 )
89 fprintf(stderr, zambig_file, hyph, pOD->pz_DisableName);
90 } while (pOD++, (++idx < opts->optCt));
91 }
92
93 /**
94 * Determine the number of options that match the name
95 *
96 * @param pOpts option data
97 * @param opt_name name of option to look for
98 * @param nm_len length of provided name
99 * @param index pointer to int for option index
100 * @param disable pointer to bool to mark disabled option
101 * @return count of options that match
102 */
103 static int
opt_match_ct(tOptions * opts,char const * name,int nm_len,int * ixp,bool * disable)104 opt_match_ct(tOptions * opts, char const * name, int nm_len,
105 int * ixp, bool * disable)
106 {
107 int matchCt = 0;
108 int idx = 0;
109 int idxLim = opts->optCt;
110 tOptDesc * pOD = opts->pOptDesc;
111
112 do {
113 /*
114 * If option disabled or a doc option, skip to next
115 */
116 if (pOD->pz_Name == NULL)
117 continue;
118
119 if ( SKIP_OPT(pOD)
120 && (pOD->fOptState != (OPTST_OMITTED | OPTST_NO_INIT)))
121 continue;
122
123 if (strneqvcmp(name, pOD->pz_Name, nm_len) == 0) {
124 /*
125 * IF we have a complete match
126 * THEN it takes priority over any already located partial
127 */
128 if (pOD->pz_Name[ nm_len ] == NUL) {
129 *ixp = idx;
130 return 1;
131 }
132 }
133
134 /*
135 * IF there is a disable name
136 * *AND* the option name matches the disable name
137 * THEN ...
138 */
139 else if ( (pOD->pz_DisableName != NULL)
140 && (strneqvcmp(name, pOD->pz_DisableName, nm_len) == 0)
141 ) {
142 *disable = true;
143
144 /*
145 * IF we have a complete match
146 * THEN it takes priority over any already located partial
147 */
148 if (pOD->pz_DisableName[ nm_len ] == NUL) {
149 *ixp = idx;
150 return 1;
151 }
152 }
153
154 else
155 continue; /* does not match any option */
156
157 /*
158 * We found a full or partial match, either regular or disabling.
159 * Remember the index for later.
160 */
161 *ixp = idx;
162 ++matchCt;
163
164 } while (pOD++, (++idx < idxLim));
165
166 return matchCt;
167 }
168
169 /**
170 * Set the option to the indicated option number.
171 *
172 * @param opts option data
173 * @param arg option argument (if glued to name)
174 * @param idx option index
175 * @param disable mark disabled option
176 * @param st state about current option
177 */
178 static tSuccess
opt_set(tOptions * opts,char * arg,int idx,bool disable,tOptState * st)179 opt_set(tOptions * opts, char * arg, int idx, bool disable, tOptState * st)
180 {
181 tOptDesc * pOD = opts->pOptDesc + idx;
182
183 if (SKIP_OPT(pOD)) {
184 if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0)
185 return FAILURE;
186
187 fprintf(stderr, zDisabledErr, opts->pzProgName, pOD->pz_Name);
188 if (pOD->pzText != NULL)
189 fprintf(stderr, SET_OFF_FMT, pOD->pzText);
190 fputc(NL, stderr);
191 (*opts->pUsageProc)(opts, EXIT_FAILURE);
192 /* NOTREACHED */
193 _exit(EXIT_FAILURE); /* to be certain */
194 }
195
196 /*
197 * IF we found a disablement name,
198 * THEN set the bit in the callers' flag word
199 */
200 if (disable)
201 st->flags |= OPTST_DISABLED;
202
203 st->pOD = pOD;
204 st->pzOptArg = arg;
205 st->optType = TOPT_LONG;
206
207 return SUCCESS;
208 }
209
210 /**
211 * An option was not found. Check for default option and set it
212 * if there is one. Otherwise, handle the error.
213 *
214 * @param opts option data
215 * @param name name of option to look for
216 * @param arg option argument
217 * @param st state about current option
218 *
219 * @return success status
220 */
221 static tSuccess
opt_unknown(tOptions * opts,char const * name,char * arg,tOptState * st)222 opt_unknown(tOptions * opts, char const * name, char * arg, tOptState * st)
223 {
224 /*
225 * IF there is no equal sign
226 * *AND* we are using named arguments
227 * *AND* there is a default named option,
228 * THEN return that option.
229 */
230 if ( (arg == NULL)
231 && NAMED_OPTS(opts)
232 && (opts->specOptIdx.default_opt != NO_EQUIVALENT)) {
233
234 st->pOD = opts->pOptDesc + opts->specOptIdx.default_opt;
235 st->pzOptArg = name;
236 st->optType = TOPT_DEFAULT;
237 return SUCCESS;
238 }
239
240 if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) {
241 fprintf(stderr, zIllOptStr, opts->pzProgPath, name);
242 (*opts->pUsageProc)(opts, EXIT_FAILURE);
243 /* NOTREACHED */
244 _exit(EXIT_FAILURE); /* to be certain */
245 }
246
247 return FAILURE;
248 }
249
250 /**
251 * Several options match the provided name.
252 *
253 * @param opts option data
254 * @param name name of option to look for
255 * @param match_ct number of matching options
256 *
257 * @return success status (always FAILURE, if it returns)
258 */
259 static tSuccess
opt_ambiguous(tOptions * opts,char const * name,int match_ct)260 opt_ambiguous(tOptions * opts, char const * name, int match_ct)
261 {
262 if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) {
263 fprintf(stderr, zambig_opt_fmt, opts->pzProgPath, name, match_ct);
264 if (match_ct <= 4)
265 opt_ambiguities(opts, name, (int)strlen(name));
266 (*opts->pUsageProc)(opts, EXIT_FAILURE);
267 /* NOTREACHED */
268 _exit(EXIT_FAILURE); /* to be certain */
269 }
270 return FAILURE;
271 }
272
273 /*=export_func optionVendorOption
274 * private:
275 *
276 * what: Process a vendor option
277 * arg: + tOptions * + pOpts + program options descriptor +
278 * arg: + tOptDesc * + pOptDesc + the descriptor for this arg +
279 *
280 * doc:
281 * For POSIX specified utilities, the options are constrained to the options,
282 * @xref{config attributes, Program Configuration}. AutoOpts clients should
283 * never specify this directly. It gets referenced when the option
284 * definitions contain a "vendor-opt" attribute.
285 =*/
286 void
optionVendorOption(tOptions * pOpts,tOptDesc * pOD)287 optionVendorOption(tOptions * pOpts, tOptDesc * pOD)
288 {
289 tOptState opt_st = OPTSTATE_INITIALIZER(PRESET);
290 char const * vopt_str = pOD->optArg.argString;
291
292 if (pOpts <= OPTPROC_EMIT_LIMIT)
293 return;
294
295 if ((pOD->fOptState & OPTST_RESET) != 0)
296 return;
297
298 if ((pOD->fOptState & OPTPROC_IMMEDIATE) == 0)
299 opt_st.flags = OPTST_DEFINED;
300
301 if ( ((pOpts->fOptSet & OPTPROC_VENDOR_OPT) == 0)
302 || ! SUCCESSFUL(opt_find_long(pOpts, vopt_str, &opt_st))
303 || ! SUCCESSFUL(get_opt_arg(pOpts, &opt_st)) )
304 {
305 fprintf(stderr, zIllVendOptStr, pOpts->pzProgName, vopt_str);
306 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE);
307 /* NOTREACHED */
308 _exit(EXIT_FAILURE); /* to be certain */
309 }
310
311 /*
312 * See if we are in immediate handling state.
313 */
314 if (pOpts->fOptSet & OPTPROC_IMMEDIATE) {
315 /*
316 * See if the enclosed option is okay with that state.
317 */
318 if (DO_IMMEDIATELY(opt_st.flags))
319 (void)handle_opt(pOpts, &opt_st);
320
321 } else {
322 /*
323 * non-immediate direction.
324 * See if the enclosed option is okay with that state.
325 */
326 if (DO_NORMALLY(opt_st.flags) || DO_SECOND_TIME(opt_st.flags))
327 (void)handle_opt(pOpts, &opt_st);
328 }
329 }
330
331 /**
332 * Find the option descriptor by full name.
333 *
334 * @param opts option data
335 * @param opt_name name of option to look for
336 * @param state state about current option
337 *
338 * @return success status
339 */
340 static tSuccess
opt_find_long(tOptions * opts,char const * opt_name,tOptState * state)341 opt_find_long(tOptions * opts, char const * opt_name, tOptState * state)
342 {
343 char name_buf[128];
344 char * opt_arg;
345 int nm_len = parse_opt(&opt_name, &opt_arg, name_buf, sizeof(name_buf));
346
347 int idx = 0;
348 bool disable = false;
349 int ct;
350
351 if (nm_len <= 1) {
352 if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0)
353 return FAILURE;
354
355 fprintf(stderr, zInvalOptName, opts->pzProgName, opt_name);
356 (*opts->pUsageProc)(opts, EXIT_FAILURE);
357 /* NOTREACHED */
358 _exit(EXIT_FAILURE); /* to be certain */
359 }
360
361 ct = opt_match_ct(opts, opt_name, nm_len, &idx, &disable);
362
363 /*
364 * See if we found one match, no matches or multiple matches.
365 */
366 switch (ct) {
367 case 1: return opt_set(opts, opt_arg, idx, disable, state);
368 case 0: return opt_unknown(opts, opt_name, opt_arg, state);
369 default: return opt_ambiguous(opts, opt_name, ct);
370 }
371 }
372
373
374 /**
375 * Find the short option descriptor for the current option
376 *
377 * @param pOpts option data
378 * @param optValue option flag character
379 * @param pOptState state about current option
380 */
381 static tSuccess
opt_find_short(tOptions * pOpts,uint_t optValue,tOptState * pOptState)382 opt_find_short(tOptions * pOpts, uint_t optValue, tOptState * pOptState)
383 {
384 tOptDesc * pRes = pOpts->pOptDesc;
385 int ct = pOpts->optCt;
386
387 /*
388 * Search the option list
389 */
390 do {
391 if (optValue != pRes->optValue)
392 continue;
393
394 if (SKIP_OPT(pRes)) {
395 if ( (pRes->fOptState == (OPTST_OMITTED | OPTST_NO_INIT))
396 && (pRes->pz_Name != NULL)) {
397 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) == 0)
398 return FAILURE;
399
400 fprintf(stderr, zDisabledErr, pOpts->pzProgPath, pRes->pz_Name);
401 if (pRes->pzText != NULL)
402 fprintf(stderr, SET_OFF_FMT, pRes->pzText);
403 fputc(NL, stderr);
404 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE);
405 /* NOTREACHED */
406 _exit(EXIT_FAILURE); /* to be certain */
407 }
408 goto short_opt_error;
409 }
410
411 pOptState->pOD = pRes;
412 pOptState->optType = TOPT_SHORT;
413 return SUCCESS;
414
415 } while (pRes++, --ct > 0);
416
417 /*
418 * IF the character value is a digit
419 * AND there is a special number option ("-n")
420 * THEN the result is the "option" itself and the
421 * option is the specially marked "number" option.
422 */
423 if ( IS_DEC_DIGIT_CHAR(optValue)
424 && (pOpts->specOptIdx.number_option != NO_EQUIVALENT) ) {
425 pOptState->pOD = \
426 pRes = pOpts->pOptDesc + pOpts->specOptIdx.number_option;
427 (pOpts->pzCurOpt)--;
428 pOptState->optType = TOPT_SHORT;
429 return SUCCESS;
430 }
431
432 short_opt_error:
433
434 /*
435 * IF we are to stop on errors (the default, actually)
436 * THEN call the usage procedure.
437 */
438 if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
439 fprintf(stderr, zIllOptChr, pOpts->pzProgPath, optValue);
440 (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE);
441 /* NOTREACHED */
442 _exit(EXIT_FAILURE); /* to be certain */
443 }
444
445 return FAILURE;
446 }
447
448 /**
449 * Process option with a required argument. Long options can either have a
450 * separate command line argument, or an argument attached by the '='
451 * character. Figure out which.
452 *
453 * @param[in,out] opts the program option descriptor
454 * @param[in,out] o_st the option processing state
455 * @returns SUCCESS or FAILURE
456 */
457 static tSuccess
get_opt_arg_must(tOptions * opts,tOptState * o_st)458 get_opt_arg_must(tOptions * opts, tOptState * o_st)
459 {
460 switch (o_st->optType) {
461 case TOPT_SHORT:
462 /*
463 * See if an arg string follows the flag character
464 */
465 if (*++(opts->pzCurOpt) == NUL)
466 opts->pzCurOpt = opts->origArgVect[ opts->curOptIdx++ ];
467 o_st->pzOptArg = opts->pzCurOpt;
468 break;
469
470 case TOPT_LONG:
471 /*
472 * See if an arg string has already been assigned (glued on
473 * with an `=' character)
474 */
475 if (o_st->pzOptArg == NULL)
476 o_st->pzOptArg = opts->origArgVect[ opts->curOptIdx++ ];
477 break;
478
479 default:
480 #ifdef DEBUG
481 fputs("AutoOpts lib error: option type not selected\n", stderr);
482 option_exits(EXIT_FAILURE);
483 #endif
484
485 case TOPT_DEFAULT:
486 /*
487 * The option was selected by default. The current token is
488 * the option argument.
489 */
490 break;
491 }
492
493 /*
494 * Make sure we did not overflow the argument list.
495 */
496 if (opts->curOptIdx > opts->origArgCt) {
497 fprintf(stderr, zMisArg, opts->pzProgPath, o_st->pOD->pz_Name);
498 return FAILURE;
499 }
500
501 opts->pzCurOpt = NULL; /* next time advance to next arg */
502 return SUCCESS;
503 }
504
505 /**
506 * Process an option with an optional argument. For short options, it looks
507 * at the character after the option character, or it consumes the next full
508 * argument. For long options, it looks for an '=' character attachment to
509 * the long option name before deciding to take the next command line
510 * argument.
511 *
512 * @param pOpts the option descriptor
513 * @param o_st a structure for managing the current processing state
514 * @returns SUCCESS or does not return
515 */
516 static tSuccess
get_opt_arg_may(tOptions * pOpts,tOptState * o_st)517 get_opt_arg_may(tOptions * pOpts, tOptState * o_st)
518 {
519 /*
520 * An option argument is optional.
521 */
522 switch (o_st->optType) {
523 case TOPT_SHORT:
524 if (*++pOpts->pzCurOpt != NUL)
525 o_st->pzOptArg = pOpts->pzCurOpt;
526 else {
527 char * pzLA = pOpts->origArgVect[ pOpts->curOptIdx ];
528
529 /*
530 * BECAUSE it is optional, we must make sure
531 * we did not find another flag and that there
532 * is such an argument.
533 */
534 if ((pzLA == NULL) || (*pzLA == '-'))
535 o_st->pzOptArg = NULL;
536 else {
537 pOpts->curOptIdx++; /* argument found */
538 o_st->pzOptArg = pzLA;
539 }
540 }
541 break;
542
543 case TOPT_LONG:
544 /*
545 * Look for an argument if we don't already have one (glued on
546 * with a `=' character) *AND* we are not in named argument mode
547 */
548 if ( (o_st->pzOptArg == NULL)
549 && (! NAMED_OPTS(pOpts))) {
550 char * pzLA = pOpts->origArgVect[ pOpts->curOptIdx ];
551
552 /*
553 * BECAUSE it is optional, we must make sure
554 * we did not find another flag and that there
555 * is such an argument.
556 */
557 if ((pzLA == NULL) || (*pzLA == '-'))
558 o_st->pzOptArg = NULL;
559 else {
560 pOpts->curOptIdx++; /* argument found */
561 o_st->pzOptArg = pzLA;
562 }
563 }
564 break;
565
566 default:
567 case TOPT_DEFAULT:
568 ao_bug(zbad_default_msg);
569 }
570
571 /*
572 * After an option with an optional argument, we will
573 * *always* start with the next option because if there
574 * were any characters following the option name/flag,
575 * they would be interpreted as the argument.
576 */
577 pOpts->pzCurOpt = NULL;
578 return SUCCESS;
579 }
580
581 /**
582 * Process option that does not have an argument.
583 *
584 * @param[in,out] opts the program option descriptor
585 * @param[in,out] o_st the option processing state
586 * @returns SUCCESS or FAILURE
587 */
588 static tSuccess
get_opt_arg_none(tOptions * pOpts,tOptState * o_st)589 get_opt_arg_none(tOptions * pOpts, tOptState * o_st)
590 {
591 /*
592 * No option argument. Make sure next time around we find
593 * the correct option flag character for short options
594 */
595 if (o_st->optType == TOPT_SHORT)
596 (pOpts->pzCurOpt)++;
597
598 /*
599 * It is a long option. Make sure there was no ``=xxx'' argument
600 */
601 else if (o_st->pzOptArg != NULL) {
602 fprintf(stderr, zNoArg, pOpts->pzProgPath, o_st->pOD->pz_Name);
603 return FAILURE;
604 }
605
606 /*
607 * It is a long option. Advance to next command line argument.
608 */
609 else
610 pOpts->pzCurOpt = NULL;
611
612 return SUCCESS;
613 }
614
615 /**
616 * Process option. Figure out whether or not to look for an option argument.
617 *
618 * @param[in,out] opts the program option descriptor
619 * @param[in,out] o_st the option processing state
620 * @returns SUCCESS or FAILURE
621 */
622 static tSuccess
get_opt_arg(tOptions * opts,tOptState * o_st)623 get_opt_arg(tOptions * opts, tOptState * o_st)
624 {
625 o_st->flags |= (o_st->pOD->fOptState & OPTST_PERSISTENT_MASK);
626
627 /*
628 * Disabled options and options specified to not have arguments
629 * are handled with the "none" procedure. Otherwise, check the
630 * optional flag and call either the "may" or "must" function.
631 */
632 if ((o_st->flags & OPTST_DISABLED) != 0)
633 return get_opt_arg_none(opts, o_st);
634
635 switch (OPTST_GET_ARGTYPE(o_st->flags)) {
636 case OPARG_TYPE_STATIC:
637 {
638 /*
639 * Propagate the static arg
640 */
641 tSuccess res = get_opt_arg_none(opts, o_st);
642 o_st->pzOptArg = o_st->pOD->optArg.argString;
643 return res;
644 }
645
646 case OPARG_TYPE_NONE:
647 return get_opt_arg_none(opts, o_st);
648 }
649
650 if (o_st->flags & OPTST_ARG_OPTIONAL)
651 return get_opt_arg_may( opts, o_st);
652
653 return get_opt_arg_must(opts, o_st);
654 }
655
656 /**
657 * Find the option descriptor for the current option.
658 *
659 * @param[in,out] opts the program option descriptor
660 * @param[in,out] o_st the option processing state
661 * @returns SUCCESS or FAILURE
662 */
663 static tSuccess
find_opt(tOptions * opts,tOptState * o_st)664 find_opt(tOptions * opts, tOptState * o_st)
665 {
666 /*
667 * IF we are continuing a short option list (e.g. -xyz...)
668 * THEN continue a single flag option.
669 * OTHERWISE see if there is room to advance and then do so.
670 */
671 if ((opts->pzCurOpt != NULL) && (*opts->pzCurOpt != NUL))
672 return opt_find_short(opts, (uint8_t)*(opts->pzCurOpt), o_st);
673
674 if (opts->curOptIdx >= opts->origArgCt)
675 return PROBLEM; /* NORMAL COMPLETION */
676
677 opts->pzCurOpt = opts->origArgVect[ opts->curOptIdx ];
678
679 /*
680 * IF all arguments must be named options, ...
681 */
682 if (NAMED_OPTS(opts)) {
683 char * pz = opts->pzCurOpt;
684 int def;
685 tSuccess res;
686 uint16_t * def_opt;
687
688 opts->curOptIdx++;
689
690 if (*pz != '-')
691 return opt_find_long(opts, pz, o_st);
692
693 /*
694 * The name is prefixed with one or more hyphens. Strip them off
695 * and disable the "default_opt" setting. Use heavy recasting to
696 * strip off the "const" quality of the "default_opt" field.
697 */
698 while (*(++pz) == '-') ;
699 def_opt = VOIDP(&(opts->specOptIdx.default_opt));
700 def = *def_opt;
701 *def_opt = NO_EQUIVALENT;
702 res = opt_find_long(opts, pz, o_st);
703 *def_opt = (uint16_t)def;
704 return res;
705 }
706
707 /*
708 * Note the kind of flag/option marker
709 */
710 if (*((opts->pzCurOpt)++) != '-')
711 return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
712
713 /*
714 * Special hack for a hyphen by itself
715 */
716 if (*(opts->pzCurOpt) == NUL)
717 return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
718
719 /*
720 * The current argument is to be processed as an option argument
721 */
722 opts->curOptIdx++;
723
724 /*
725 * We have an option marker.
726 * Test the next character for long option indication
727 */
728 if (opts->pzCurOpt[0] == '-') {
729 if (*++(opts->pzCurOpt) == NUL)
730 /*
731 * NORMAL COMPLETION - NOT this arg, but rest are operands
732 */
733 return PROBLEM;
734
735 /*
736 * We do not allow the hyphen to be used as a flag value.
737 * Therefore, if long options are not to be accepted, we punt.
738 */
739 if ((opts->fOptSet & OPTPROC_LONGOPT) == 0) {
740 fprintf(stderr, zIllOptStr, opts->pzProgPath, opts->pzCurOpt-2);
741 return FAILURE;
742 }
743
744 return opt_find_long(opts, opts->pzCurOpt, o_st);
745 }
746
747 /*
748 * If short options are not allowed, then do long
749 * option processing. Otherwise the character must be a
750 * short (i.e. single character) option.
751 */
752 if ((opts->fOptSet & OPTPROC_SHORTOPT) != 0)
753 return opt_find_short(opts, (uint8_t)*(opts->pzCurOpt), o_st);
754
755 return opt_find_long(opts, opts->pzCurOpt, o_st);
756 }
757
758 /** @}
759 *
760 * Local Variables:
761 * mode: C
762 * c-file-style: "stroustrup"
763 * indent-tabs-mode: nil
764 * End:
765 * end of autoopts/find.c */
766