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