Coverage Report

Created: 2026-02-26 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ntp-dev/sntp/libopts/find.c
Line
Count
Source
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
38
parse_opt(char const ** nm_pp, char ** arg_pp, char * buf, size_t bufsz)
39
0
{
40
0
    int  res = 0;
41
0
    char const * p = *nm_pp;
42
0
    *arg_pp  = NULL;
43
44
0
    for (;;) {
45
0
        switch (*(p++)) {
46
0
        case NUL: return res;
47
48
0
        case '=':
49
0
            memcpy(buf, *nm_pp, (size_t)res);
50
51
0
            buf[res] = NUL;
52
0
            *nm_pp   = buf;
53
0
            *arg_pp  = (char *)p;
54
0
            return res;
55
56
0
        default:
57
0
            if (++res >= (int)bufsz)
58
0
                return -1;
59
0
        }
60
0
    }
61
0
}
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
70
opt_ambiguities(tOptions * opts, char const * name, int nm_len)
71
0
{
72
0
    char const * const hyph =
73
0
        NAMED_OPTS(opts) ? "" : LONG_OPT_MARKER;
74
75
0
    tOptDesc * pOD = opts->pOptDesc;
76
0
    int        idx = 0;
77
78
0
    fputs(zambig_list_msg, stderr);
79
0
    do  {
80
0
        if (pOD->pz_Name == NULL)
81
0
            continue; /* doc option */
82
83
0
        if (strneqvcmp(name, pOD->pz_Name, nm_len) == 0)
84
0
            fprintf(stderr, zambig_file, hyph, pOD->pz_Name);
85
86
0
        else if (  (pOD->pz_DisableName != NULL)
87
0
                && (strneqvcmp(name, pOD->pz_DisableName, nm_len) == 0)
88
0
                )
89
0
            fprintf(stderr, zambig_file, hyph, pOD->pz_DisableName);
90
0
    } while (pOD++, (++idx < opts->optCt));
91
0
}
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
104
opt_match_ct(tOptions * opts, char const * name, int nm_len,
105
             int * ixp, bool * disable)
106
0
{
107
0
    int   matchCt  = 0;
108
0
    int   idx      = 0;
109
0
    int   idxLim   = opts->optCt;
110
0
    tOptDesc * pOD = opts->pOptDesc;
111
112
0
    do  {
113
        /*
114
         *  If option disabled or a doc option, skip to next
115
         */
116
0
        if (pOD->pz_Name == NULL)
117
0
            continue;
118
119
0
        if (  SKIP_OPT(pOD)
120
0
           && (pOD->fOptState != (OPTST_OMITTED | OPTST_NO_INIT)))
121
0
            continue;
122
123
0
        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
0
            if (pOD->pz_Name[ nm_len ] == NUL) {
129
0
                *ixp = idx;
130
0
                return 1;
131
0
            }
132
0
        }
133
134
        /*
135
         *  IF       there is a disable name
136
         *     *AND* the option name matches the disable name
137
         *  THEN ...
138
         */
139
0
        else if (  (pOD->pz_DisableName != NULL)
140
0
                && (strneqvcmp(name, pOD->pz_DisableName, nm_len) == 0)
141
0
                )  {
142
0
            *disable = true;
143
144
            /*
145
             *  IF we have a complete match
146
             *  THEN it takes priority over any already located partial
147
             */
148
0
            if (pOD->pz_DisableName[ nm_len ] == NUL) {
149
0
                *ixp = idx;
150
0
                return 1;
151
0
            }
152
0
        }
153
154
0
        else
155
0
            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
0
        *ixp = idx;
162
0
        ++matchCt;
163
164
0
    } while (pOD++, (++idx < idxLim));
165
166
0
    return matchCt;
167
0
}
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
179
opt_set(tOptions * opts, char * arg, int idx, bool disable, tOptState * st)
180
0
{
181
0
    tOptDesc * pOD = opts->pOptDesc + idx;
182
183
0
    if (SKIP_OPT(pOD)) {
184
0
        if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0)
185
0
            return FAILURE;
186
187
0
        fprintf(stderr, zDisabledErr, opts->pzProgName, pOD->pz_Name);
188
0
        if (pOD->pzText != NULL)
189
0
            fprintf(stderr, SET_OFF_FMT, pOD->pzText);
190
0
        fputc(NL, stderr);
191
0
        (*opts->pUsageProc)(opts, EXIT_FAILURE);
192
        /* NOTREACHED */
193
0
        _exit(EXIT_FAILURE); /* to be certain */
194
0
    }
195
196
    /*
197
     *  IF we found a disablement name,
198
     *  THEN set the bit in the callers' flag word
199
     */
200
0
    if (disable)
201
0
        st->flags |= OPTST_DISABLED;
202
203
0
    st->pOD      = pOD;
204
0
    st->pzOptArg = arg;
205
0
    st->optType  = TOPT_LONG;
206
207
0
    return SUCCESS;
208
0
}
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
222
opt_unknown(tOptions * opts, char const * name, char * arg, tOptState * st)
223
0
{
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
0
    if (  (arg == NULL)
231
0
       && NAMED_OPTS(opts)
232
0
       && (opts->specOptIdx.default_opt != NO_EQUIVALENT)) {
233
234
0
        st->pOD      = opts->pOptDesc + opts->specOptIdx.default_opt;
235
0
        st->pzOptArg = name;
236
0
        st->optType  = TOPT_DEFAULT;
237
0
        return SUCCESS;
238
0
    }
239
240
0
    if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) {
241
0
        fprintf(stderr, zIllOptStr, opts->pzProgPath, name);
242
0
        (*opts->pUsageProc)(opts, EXIT_FAILURE);
243
        /* NOTREACHED */
244
0
        _exit(EXIT_FAILURE); /* to be certain */
245
0
    }
246
247
0
    return FAILURE;
248
0
}
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
260
opt_ambiguous(tOptions * opts, char const * name, int match_ct)
261
0
{
262
0
    if ((opts->fOptSet & OPTPROC_ERRSTOP) != 0) {
263
0
        fprintf(stderr, zambig_opt_fmt, opts->pzProgPath, name, match_ct);
264
0
        if (match_ct <= 4)
265
0
            opt_ambiguities(opts, name, (int)strlen(name));
266
0
        (*opts->pUsageProc)(opts, EXIT_FAILURE);
267
        /* NOTREACHED */
268
0
        _exit(EXIT_FAILURE); /* to be certain */
269
0
    }
270
0
    return FAILURE;
271
0
}
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
287
optionVendorOption(tOptions * pOpts, tOptDesc * pOD)
288
0
{
289
0
    tOptState     opt_st   = OPTSTATE_INITIALIZER(PRESET);
290
0
    char const *  vopt_str = pOD->optArg.argString;
291
292
0
    if (pOpts <= OPTPROC_EMIT_LIMIT)
293
0
        return;
294
295
0
    if ((pOD->fOptState & OPTST_RESET) != 0)
296
0
        return;
297
298
0
    if ((pOD->fOptState & OPTPROC_IMMEDIATE) == 0)
299
0
        opt_st.flags = OPTST_DEFINED;
300
301
0
    if (  ((pOpts->fOptSet & OPTPROC_VENDOR_OPT) == 0)
302
0
       || ! SUCCESSFUL(opt_find_long(pOpts, vopt_str, &opt_st))
303
0
       || ! SUCCESSFUL(get_opt_arg(pOpts, &opt_st)) )
304
0
    {
305
0
        fprintf(stderr, zIllVendOptStr, pOpts->pzProgName, vopt_str);
306
0
        (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE);
307
        /* NOTREACHED */
308
0
        _exit(EXIT_FAILURE); /* to be certain */
309
0
    }
310
311
    /*
312
     *  See if we are in immediate handling state.
313
     */
314
0
    if (pOpts->fOptSet & OPTPROC_IMMEDIATE) {
315
        /*
316
         *  See if the enclosed option is okay with that state.
317
         */
318
0
        if (DO_IMMEDIATELY(opt_st.flags))
319
0
            (void)handle_opt(pOpts, &opt_st);
320
321
0
    } else {
322
        /*
323
         *  non-immediate direction.
324
         *  See if the enclosed option is okay with that state.
325
         */
326
0
        if (DO_NORMALLY(opt_st.flags) || DO_SECOND_TIME(opt_st.flags))
327
0
            (void)handle_opt(pOpts, &opt_st);
328
0
    }
329
0
}
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
341
opt_find_long(tOptions * opts, char const * opt_name, tOptState * state)
342
0
{
343
0
    char    name_buf[128];
344
0
    char *  opt_arg;
345
0
    int     nm_len = parse_opt(&opt_name, &opt_arg, name_buf, sizeof(name_buf));
346
347
0
    int     idx = 0;
348
0
    bool    disable  = false;
349
0
    int     ct;
350
351
0
    if (nm_len <= 1) {
352
0
        if ((opts->fOptSet & OPTPROC_ERRSTOP) == 0)
353
0
            return FAILURE;
354
        
355
0
        fprintf(stderr, zInvalOptName, opts->pzProgName, opt_name);
356
0
        (*opts->pUsageProc)(opts, EXIT_FAILURE);
357
        /* NOTREACHED */
358
0
        _exit(EXIT_FAILURE); /* to be certain */
359
0
    }
360
361
0
    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
0
    switch (ct) {
367
0
    case 1:  return opt_set(opts, opt_arg, idx, disable, state);
368
0
    case 0:  return opt_unknown(opts, opt_name, opt_arg, state);
369
0
    default: return opt_ambiguous(opts, opt_name, ct);
370
0
    }
371
0
}
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
382
opt_find_short(tOptions * pOpts, uint_t optValue, tOptState * pOptState)
383
0
{
384
0
    tOptDesc * pRes = pOpts->pOptDesc;
385
0
    int        ct   = pOpts->optCt;
386
387
    /*
388
     *  Search the option list
389
     */
390
0
    do  {
391
0
        if (optValue != pRes->optValue)
392
0
            continue;
393
394
0
        if (SKIP_OPT(pRes)) {
395
0
            if (  (pRes->fOptState == (OPTST_OMITTED | OPTST_NO_INIT))
396
0
               && (pRes->pz_Name != NULL)) {
397
0
                if ((pOpts->fOptSet & OPTPROC_ERRSTOP) == 0)
398
0
                    return FAILURE;
399
        
400
0
                fprintf(stderr, zDisabledErr, pOpts->pzProgPath, pRes->pz_Name);
401
0
                if (pRes->pzText != NULL)
402
0
                    fprintf(stderr, SET_OFF_FMT, pRes->pzText);
403
0
                fputc(NL, stderr);
404
0
                (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE);
405
                /* NOTREACHED */
406
0
                _exit(EXIT_FAILURE); /* to be certain */
407
0
            }
408
0
            goto short_opt_error;
409
0
        }
410
411
0
        pOptState->pOD     = pRes;
412
0
        pOptState->optType = TOPT_SHORT;
413
0
        return SUCCESS;
414
415
0
    } 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
0
    if (  IS_DEC_DIGIT_CHAR(optValue)
424
0
       && (pOpts->specOptIdx.number_option != NO_EQUIVALENT) ) {
425
0
        pOptState->pOD = \
426
0
        pRes           = pOpts->pOptDesc + pOpts->specOptIdx.number_option;
427
0
        (pOpts->pzCurOpt)--;
428
0
        pOptState->optType = TOPT_SHORT;
429
0
        return SUCCESS;
430
0
    }
431
432
0
 short_opt_error:
433
434
    /*
435
     *  IF we are to stop on errors (the default, actually)
436
     *  THEN call the usage procedure.
437
     */
438
0
    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
439
0
        fprintf(stderr, zIllOptChr, pOpts->pzProgPath, optValue);
440
0
        (*pOpts->pUsageProc)(pOpts, EXIT_FAILURE);
441
        /* NOTREACHED */
442
0
        _exit(EXIT_FAILURE); /* to be certain */
443
0
    }
444
445
0
    return FAILURE;
446
0
}
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
458
get_opt_arg_must(tOptions * opts, tOptState * o_st)
459
0
{
460
0
    switch (o_st->optType) {
461
0
    case TOPT_SHORT:
462
        /*
463
         *  See if an arg string follows the flag character
464
         */
465
0
        if (*++(opts->pzCurOpt) == NUL)
466
0
            opts->pzCurOpt = opts->origArgVect[ opts->curOptIdx++ ];
467
0
        o_st->pzOptArg = opts->pzCurOpt;
468
0
        break;
469
470
0
    case TOPT_LONG:
471
        /*
472
         *  See if an arg string has already been assigned (glued on
473
         *  with an `=' character)
474
         */
475
0
        if (o_st->pzOptArg == NULL)
476
0
            o_st->pzOptArg = opts->origArgVect[ opts->curOptIdx++ ];
477
0
        break;
478
479
0
    default:
480
0
#ifdef DEBUG
481
0
        fputs("AutoOpts lib error: option type not selected\n", stderr);
482
0
        option_exits(EXIT_FAILURE);
483
0
#endif
484
485
0
    case TOPT_DEFAULT:
486
        /*
487
         *  The option was selected by default.  The current token is
488
         *  the option argument.
489
         */
490
0
        break;
491
0
    }
492
493
    /*
494
     *  Make sure we did not overflow the argument list.
495
     */
496
0
    if (opts->curOptIdx > opts->origArgCt) {
497
0
        fprintf(stderr, zMisArg, opts->pzProgPath, o_st->pOD->pz_Name);
498
0
        return FAILURE;
499
0
    }
500
501
0
    opts->pzCurOpt = NULL;  /* next time advance to next arg */
502
0
    return SUCCESS;
503
0
}
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
517
get_opt_arg_may(tOptions * pOpts, tOptState * o_st)
518
0
{
519
    /*
520
     *  An option argument is optional.
521
     */
522
0
    switch (o_st->optType) {
523
0
    case TOPT_SHORT:
524
0
        if (*++pOpts->pzCurOpt != NUL)
525
0
            o_st->pzOptArg = pOpts->pzCurOpt;
526
0
        else {
527
0
            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
0
            if ((pzLA == NULL) || (*pzLA == '-'))
535
0
                o_st->pzOptArg = NULL;
536
0
            else {
537
0
                pOpts->curOptIdx++; /* argument found */
538
0
                o_st->pzOptArg = pzLA;
539
0
            }
540
0
        }
541
0
        break;
542
543
0
    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
0
        if (  (o_st->pzOptArg == NULL)
549
0
           && (! NAMED_OPTS(pOpts))) {
550
0
            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
0
            if ((pzLA == NULL) || (*pzLA == '-'))
558
0
                o_st->pzOptArg = NULL;
559
0
            else {
560
0
                pOpts->curOptIdx++; /* argument found */
561
0
                o_st->pzOptArg = pzLA;
562
0
            }
563
0
        }
564
0
        break;
565
566
0
    default:
567
0
    case TOPT_DEFAULT:
568
0
        ao_bug(zbad_default_msg);
569
0
    }
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
0
    pOpts->pzCurOpt = NULL;
578
0
    return SUCCESS;
579
0
}
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
589
get_opt_arg_none(tOptions * pOpts, tOptState * o_st)
590
0
{
591
    /*
592
     *  No option argument.  Make sure next time around we find
593
     *  the correct option flag character for short options
594
     */
595
0
    if (o_st->optType == TOPT_SHORT)
596
0
        (pOpts->pzCurOpt)++;
597
598
    /*
599
     *  It is a long option.  Make sure there was no ``=xxx'' argument
600
     */
601
0
    else if (o_st->pzOptArg != NULL) {
602
0
        fprintf(stderr, zNoArg, pOpts->pzProgPath, o_st->pOD->pz_Name);
603
0
        return FAILURE;
604
0
    }
605
606
    /*
607
     *  It is a long option.  Advance to next command line argument.
608
     */
609
0
    else
610
0
        pOpts->pzCurOpt = NULL;
611
612
0
    return SUCCESS;
613
0
}
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
623
get_opt_arg(tOptions * opts, tOptState * o_st)
624
0
{
625
0
    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
0
    if ((o_st->flags & OPTST_DISABLED) != 0)
633
0
        return get_opt_arg_none(opts, o_st);
634
635
0
    switch (OPTST_GET_ARGTYPE(o_st->flags)) {
636
0
    case OPARG_TYPE_STATIC:
637
0
    {
638
        /*
639
         * Propagate the static arg
640
         */
641
0
        tSuccess res = get_opt_arg_none(opts, o_st);
642
0
        o_st->pzOptArg = o_st->pOD->optArg.argString;
643
0
        return res;
644
0
    }
645
646
0
    case OPARG_TYPE_NONE:
647
0
        return get_opt_arg_none(opts, o_st);
648
0
    }
649
650
0
    if (o_st->flags & OPTST_ARG_OPTIONAL)
651
0
        return get_opt_arg_may( opts, o_st);
652
    
653
0
    return get_opt_arg_must(opts, o_st);
654
0
}
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
664
find_opt(tOptions * opts, tOptState * o_st)
665
0
{
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
0
    if ((opts->pzCurOpt != NULL) && (*opts->pzCurOpt != NUL))
672
0
        return opt_find_short(opts, (uint8_t)*(opts->pzCurOpt), o_st);
673
674
0
    if (opts->curOptIdx >= opts->origArgCt)
675
0
        return PROBLEM; /* NORMAL COMPLETION */
676
677
0
    opts->pzCurOpt = opts->origArgVect[ opts->curOptIdx ];
678
679
    /*
680
     *  IF all arguments must be named options, ...
681
     */
682
0
    if (NAMED_OPTS(opts)) {
683
0
        char *      pz  = opts->pzCurOpt;
684
0
        int         def;
685
0
        tSuccess    res;
686
0
        uint16_t *  def_opt;
687
688
0
        opts->curOptIdx++;
689
690
0
        if (*pz != '-')
691
0
            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
0
        while (*(++pz) == '-')   ;
699
0
        def_opt  = VOIDP(&(opts->specOptIdx.default_opt));
700
0
        def      = *def_opt;
701
0
        *def_opt = NO_EQUIVALENT;
702
0
        res      = opt_find_long(opts, pz, o_st);
703
0
        *def_opt = (uint16_t)def;
704
0
        return res;
705
0
    }
706
707
    /*
708
     *  Note the kind of flag/option marker
709
     */
710
0
    if (*((opts->pzCurOpt)++) != '-')
711
0
        return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
712
713
    /*
714
     *  Special hack for a hyphen by itself
715
     */
716
0
    if (*(opts->pzCurOpt) == NUL)
717
0
        return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
718
719
    /*
720
     *  The current argument is to be processed as an option argument
721
     */
722
0
    opts->curOptIdx++;
723
724
    /*
725
     *  We have an option marker.
726
     *  Test the next character for long option indication
727
     */
728
0
    if (opts->pzCurOpt[0] == '-') {
729
0
        if (*++(opts->pzCurOpt) == NUL)
730
            /*
731
             *  NORMAL COMPLETION - NOT this arg, but rest are operands
732
             */
733
0
            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
0
        if ((opts->fOptSet & OPTPROC_LONGOPT) == 0) {
740
0
            fprintf(stderr, zIllOptStr, opts->pzProgPath, opts->pzCurOpt-2);
741
0
            return FAILURE;
742
0
        }
743
744
0
        return opt_find_long(opts, opts->pzCurOpt, o_st);
745
0
    }
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
0
    if ((opts->fOptSet & OPTPROC_SHORTOPT) != 0)
753
0
        return opt_find_short(opts, (uint8_t)*(opts->pzCurOpt), o_st);
754
755
0
    return opt_find_long(opts, opts->pzCurOpt, o_st);
756
0
}
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 */