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