find.c revision 1.1
1/*	$NetBSD: find.c,v 1.1 2013/12/27 23:31:35 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-2013 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 = = = */
37static int
38parse_opt(char const ** nm_pp, char ** arg_pp, char * buf, size_t bufsz);
39
40static void
41opt_ambiguities(tOptions * opts, char const * name, int nm_len);
42
43static int
44opt_match_ct(tOptions * opts, char const * name, int nm_len,
45             int * ixp, bool * disable);
46
47static tSuccess
48opt_set(tOptions * opts, char * arg, int idx, bool disable, tOptState * st);
49
50static tSuccess
51opt_unknown(tOptions * opts, char const * name, char * arg, tOptState * st);
52
53static tSuccess
54opt_ambiguous(tOptions * opts, char const * name, int match_ct);
55
56static tSuccess
57get_opt_arg_must(tOptions * opts, tOptState * o_st);
58
59static tSuccess
60get_opt_arg_may(tOptions * pOpts, tOptState * o_st);
61
62static tSuccess
63get_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 */
69static int
70parse_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  = (char *)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 */
101static void
102opt_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 */
135static int
136opt_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 */
210static tSuccess
211opt_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 */
253static tSuccess
254opt_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 */
291static tSuccess
292opt_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=*/
318void
319optionVendorOption(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 */
372LOCAL tSuccess
373opt_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 */
413LOCAL tSuccess
414opt_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 */
489static tSuccess
490get_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 */
548static tSuccess
549get_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 */
620static tSuccess
621get_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 */
653LOCAL tSuccess
654get_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 */
680LOCAL tSuccess
681find_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  = (void *)&(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