Coverage Report

Created: 2023-05-19 06:16

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