xref: /freebsd-src/contrib/llvm-project/lldb/source/Host/common/GetOptInc.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
15ffd83dbSDimitry Andric //===-- GetOptInc.cpp -----------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Host/common/GetOptInc.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #if defined(REPLACE_GETOPT) || defined(REPLACE_GETOPT_LONG) ||                 \
120b57cec5SDimitry Andric     defined(REPLACE_GETOPT_LONG_ONLY)
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric // getopt.cpp
15*fe6060f1SDimitry Andric #include <cerrno>
16*fe6060f1SDimitry Andric #include <cstdlib>
17*fe6060f1SDimitry Andric #include <cstring>
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #if defined(REPLACE_GETOPT)
200b57cec5SDimitry Andric int opterr = 1;   /* if error message should be printed */
210b57cec5SDimitry Andric int optind = 1;   /* index into parent argv vector */
220b57cec5SDimitry Andric int optopt = '?'; /* character checked for validity */
230b57cec5SDimitry Andric int optreset;     /* reset getopt */
240b57cec5SDimitry Andric char *optarg;     /* argument associated with option */
250b57cec5SDimitry Andric #endif
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric #define PRINT_ERROR ((opterr) && (*options != ':'))
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric #define FLAG_PERMUTE 0x01  /* permute non-options to the end of argv */
300b57cec5SDimitry Andric #define FLAG_ALLARGS 0x02  /* treat non-options as args to option "-1" */
310b57cec5SDimitry Andric #define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric /* return values */
340b57cec5SDimitry Andric #define BADCH (int)'?'
350b57cec5SDimitry Andric #define BADARG ((*options == ':') ? (int)':' : (int)'?')
360b57cec5SDimitry Andric #define INORDER (int)1
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric #define EMSG ""
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric static int getopt_internal(int, char *const *, const char *,
410b57cec5SDimitry Andric                            const struct option *, int *, int);
420b57cec5SDimitry Andric static int parse_long_options(char *const *, const char *,
430b57cec5SDimitry Andric                               const struct option *, int *, int);
440b57cec5SDimitry Andric static int gcd(int, int);
450b57cec5SDimitry Andric static void permute_args(int, int, int, char *const *);
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric static const char *place = EMSG; /* option letter processing */
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric /* XXX: set optreset to 1 rather than these two */
500b57cec5SDimitry Andric static int nonopt_start = -1; /* first non option argument (for permute) */
510b57cec5SDimitry Andric static int nonopt_end = -1;   /* first option after non options (for permute) */
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric /*
540b57cec5SDimitry Andric * Compute the greatest common divisor of a and b.
550b57cec5SDimitry Andric */
gcd(int a,int b)560b57cec5SDimitry Andric static int gcd(int a, int b) {
570b57cec5SDimitry Andric   int c;
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   c = a % b;
600b57cec5SDimitry Andric   while (c != 0) {
610b57cec5SDimitry Andric     a = b;
620b57cec5SDimitry Andric     b = c;
630b57cec5SDimitry Andric     c = a % b;
640b57cec5SDimitry Andric   }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric   return (b);
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric 
pass()690b57cec5SDimitry Andric static void pass() {}
700b57cec5SDimitry Andric #define warnx(a, ...) pass();
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric /*
730b57cec5SDimitry Andric * Exchange the block from nonopt_start to nonopt_end with the block
740b57cec5SDimitry Andric * from nonopt_end to opt_end (keeping the same order of arguments
750b57cec5SDimitry Andric * in each block).
760b57cec5SDimitry Andric */
permute_args(int panonopt_start,int panonopt_end,int opt_end,char * const * nargv)770b57cec5SDimitry Andric static void permute_args(int panonopt_start, int panonopt_end, int opt_end,
780b57cec5SDimitry Andric                          char *const *nargv) {
790b57cec5SDimitry Andric   int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
800b57cec5SDimitry Andric   char *swap;
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   /*
830b57cec5SDimitry Andric   * compute lengths of blocks and number and size of cycles
840b57cec5SDimitry Andric   */
850b57cec5SDimitry Andric   nnonopts = panonopt_end - panonopt_start;
860b57cec5SDimitry Andric   nopts = opt_end - panonopt_end;
870b57cec5SDimitry Andric   ncycle = gcd(nnonopts, nopts);
880b57cec5SDimitry Andric   cyclelen = (opt_end - panonopt_start) / ncycle;
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   for (i = 0; i < ncycle; i++) {
910b57cec5SDimitry Andric     cstart = panonopt_end + i;
920b57cec5SDimitry Andric     pos = cstart;
930b57cec5SDimitry Andric     for (j = 0; j < cyclelen; j++) {
940b57cec5SDimitry Andric       if (pos >= panonopt_end)
950b57cec5SDimitry Andric         pos -= nnonopts;
960b57cec5SDimitry Andric       else
970b57cec5SDimitry Andric         pos += nopts;
980b57cec5SDimitry Andric       swap = nargv[pos];
990b57cec5SDimitry Andric       /* LINTED const cast */
1000b57cec5SDimitry Andric       const_cast<char **>(nargv)[pos] = nargv[cstart];
1010b57cec5SDimitry Andric       /* LINTED const cast */
1020b57cec5SDimitry Andric       const_cast<char **>(nargv)[cstart] = swap;
1030b57cec5SDimitry Andric     }
1040b57cec5SDimitry Andric   }
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric /*
1080b57cec5SDimitry Andric * parse_long_options --
1090b57cec5SDimitry Andric *  Parse long options in argc/argv argument vector.
1100b57cec5SDimitry Andric * Returns -1 if short_too is set and the option does not match long_options.
1110b57cec5SDimitry Andric */
parse_long_options(char * const * nargv,const char * options,const struct option * long_options,int * idx,int short_too)1120b57cec5SDimitry Andric static int parse_long_options(char *const *nargv, const char *options,
1130b57cec5SDimitry Andric                               const struct option *long_options, int *idx,
1140b57cec5SDimitry Andric                               int short_too) {
1150b57cec5SDimitry Andric   char *current_argv, *has_equal;
1160b57cec5SDimitry Andric   size_t current_argv_len;
1170b57cec5SDimitry Andric   int i, match;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   current_argv = const_cast<char *>(place);
1200b57cec5SDimitry Andric   match = -1;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   optind++;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   if ((has_equal = strchr(current_argv, '=')) != NULL) {
1250b57cec5SDimitry Andric     /* argument found (--option=arg) */
1260b57cec5SDimitry Andric     current_argv_len = has_equal - current_argv;
1270b57cec5SDimitry Andric     has_equal++;
1280b57cec5SDimitry Andric   } else
1290b57cec5SDimitry Andric     current_argv_len = strlen(current_argv);
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   for (i = 0; long_options[i].name; i++) {
1320b57cec5SDimitry Andric     /* find matching long option */
1330b57cec5SDimitry Andric     if (strncmp(current_argv, long_options[i].name, current_argv_len))
1340b57cec5SDimitry Andric       continue;
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric     if (strlen(long_options[i].name) == current_argv_len) {
1370b57cec5SDimitry Andric       /* exact match */
1380b57cec5SDimitry Andric       match = i;
1390b57cec5SDimitry Andric       break;
1400b57cec5SDimitry Andric     }
1410b57cec5SDimitry Andric     /*
1420b57cec5SDimitry Andric     * If this is a known short option, don't allow
1430b57cec5SDimitry Andric     * a partial match of a single character.
1440b57cec5SDimitry Andric     */
1450b57cec5SDimitry Andric     if (short_too && current_argv_len == 1)
1460b57cec5SDimitry Andric       continue;
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric     if (match == -1) /* partial match */
1490b57cec5SDimitry Andric       match = i;
1500b57cec5SDimitry Andric     else {
1510b57cec5SDimitry Andric       /* ambiguous abbreviation */
1520b57cec5SDimitry Andric       if (PRINT_ERROR)
1530b57cec5SDimitry Andric         warnx(ambig, (int)current_argv_len, current_argv);
1540b57cec5SDimitry Andric       optopt = 0;
1550b57cec5SDimitry Andric       return (BADCH);
1560b57cec5SDimitry Andric     }
1570b57cec5SDimitry Andric   }
1580b57cec5SDimitry Andric   if (match != -1) { /* option found */
1590b57cec5SDimitry Andric     if (long_options[match].has_arg == no_argument && has_equal) {
1600b57cec5SDimitry Andric       if (PRINT_ERROR)
1610b57cec5SDimitry Andric         warnx(noarg, (int)current_argv_len, current_argv);
1620b57cec5SDimitry Andric       /*
1630b57cec5SDimitry Andric       * XXX: GNU sets optopt to val regardless of flag
1640b57cec5SDimitry Andric       */
1650b57cec5SDimitry Andric       if (long_options[match].flag == NULL)
1660b57cec5SDimitry Andric         optopt = long_options[match].val;
1670b57cec5SDimitry Andric       else
1680b57cec5SDimitry Andric         optopt = 0;
1690b57cec5SDimitry Andric       return (BADARG);
1700b57cec5SDimitry Andric     }
1710b57cec5SDimitry Andric     if (long_options[match].has_arg == required_argument ||
1720b57cec5SDimitry Andric         long_options[match].has_arg == optional_argument) {
1730b57cec5SDimitry Andric       if (has_equal)
1740b57cec5SDimitry Andric         optarg = has_equal;
1750b57cec5SDimitry Andric       else if (long_options[match].has_arg == required_argument) {
1760b57cec5SDimitry Andric         /*
1770b57cec5SDimitry Andric         * optional argument doesn't use next nargv
1780b57cec5SDimitry Andric         */
1790b57cec5SDimitry Andric         optarg = nargv[optind++];
1800b57cec5SDimitry Andric       }
1810b57cec5SDimitry Andric     }
1820b57cec5SDimitry Andric     if ((long_options[match].has_arg == required_argument) &&
1830b57cec5SDimitry Andric         (optarg == NULL)) {
1840b57cec5SDimitry Andric       /*
1850b57cec5SDimitry Andric       * Missing argument; leading ':' indicates no error
1860b57cec5SDimitry Andric       * should be generated.
1870b57cec5SDimitry Andric       */
1880b57cec5SDimitry Andric       if (PRINT_ERROR)
1890b57cec5SDimitry Andric         warnx(recargstring, current_argv);
1900b57cec5SDimitry Andric       /*
1910b57cec5SDimitry Andric       * XXX: GNU sets optopt to val regardless of flag
1920b57cec5SDimitry Andric       */
1930b57cec5SDimitry Andric       if (long_options[match].flag == NULL)
1940b57cec5SDimitry Andric         optopt = long_options[match].val;
1950b57cec5SDimitry Andric       else
1960b57cec5SDimitry Andric         optopt = 0;
1970b57cec5SDimitry Andric       --optind;
1980b57cec5SDimitry Andric       return (BADARG);
1990b57cec5SDimitry Andric     }
2000b57cec5SDimitry Andric   } else { /* unknown option */
2010b57cec5SDimitry Andric     if (short_too) {
2020b57cec5SDimitry Andric       --optind;
2030b57cec5SDimitry Andric       return (-1);
2040b57cec5SDimitry Andric     }
2050b57cec5SDimitry Andric     if (PRINT_ERROR)
2060b57cec5SDimitry Andric       warnx(illoptstring, current_argv);
2070b57cec5SDimitry Andric     optopt = 0;
2080b57cec5SDimitry Andric     return (BADCH);
2090b57cec5SDimitry Andric   }
2100b57cec5SDimitry Andric   if (idx)
2110b57cec5SDimitry Andric     *idx = match;
2120b57cec5SDimitry Andric   if (long_options[match].flag) {
2130b57cec5SDimitry Andric     *long_options[match].flag = long_options[match].val;
2140b57cec5SDimitry Andric     return (0);
2150b57cec5SDimitry Andric   } else
2160b57cec5SDimitry Andric     return (long_options[match].val);
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric /*
2200b57cec5SDimitry Andric * getopt_internal --
2210b57cec5SDimitry Andric *  Parse argc/argv argument vector.  Called by user level routines.
2220b57cec5SDimitry Andric */
getopt_internal(int nargc,char * const * nargv,const char * options,const struct option * long_options,int * idx,int flags)2230b57cec5SDimitry Andric static int getopt_internal(int nargc, char *const *nargv, const char *options,
2240b57cec5SDimitry Andric                            const struct option *long_options, int *idx,
2250b57cec5SDimitry Andric                            int flags) {
2260b57cec5SDimitry Andric   const char *oli; /* option letter list index */
2270b57cec5SDimitry Andric   int optchar, short_too;
2280b57cec5SDimitry Andric   static int posixly_correct = -1;
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   if (options == NULL)
2310b57cec5SDimitry Andric     return (-1);
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric   /*
2340b57cec5SDimitry Andric   * XXX Some GNU programs (like cvs) set optind to 0 instead of
2350b57cec5SDimitry Andric   * XXX using optreset.  Work around this braindamage.
2360b57cec5SDimitry Andric   */
2370b57cec5SDimitry Andric   if (optind == 0)
2380b57cec5SDimitry Andric     optind = optreset = 1;
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   /*
2410b57cec5SDimitry Andric   * Disable GNU extensions if POSIXLY_CORRECT is set or options
2420b57cec5SDimitry Andric   * string begins with a '+'.
2430b57cec5SDimitry Andric   */
2440b57cec5SDimitry Andric   if (posixly_correct == -1 || optreset)
2450b57cec5SDimitry Andric     posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
2460b57cec5SDimitry Andric   if (*options == '-')
2470b57cec5SDimitry Andric     flags |= FLAG_ALLARGS;
2480b57cec5SDimitry Andric   else if (posixly_correct || *options == '+')
2490b57cec5SDimitry Andric     flags &= ~FLAG_PERMUTE;
2500b57cec5SDimitry Andric   if (*options == '+' || *options == '-')
2510b57cec5SDimitry Andric     options++;
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric   optarg = NULL;
2540b57cec5SDimitry Andric   if (optreset)
2550b57cec5SDimitry Andric     nonopt_start = nonopt_end = -1;
2560b57cec5SDimitry Andric start:
2570b57cec5SDimitry Andric   if (optreset || !*place) { /* update scanning pointer */
2580b57cec5SDimitry Andric     optreset = 0;
2590b57cec5SDimitry Andric     if (optind >= nargc) { /* end of argument vector */
2600b57cec5SDimitry Andric       place = EMSG;
2610b57cec5SDimitry Andric       if (nonopt_end != -1) {
2620b57cec5SDimitry Andric         /* do permutation, if we have to */
2630b57cec5SDimitry Andric         permute_args(nonopt_start, nonopt_end, optind, nargv);
2640b57cec5SDimitry Andric         optind -= nonopt_end - nonopt_start;
2650b57cec5SDimitry Andric       } else if (nonopt_start != -1) {
2660b57cec5SDimitry Andric         /*
2670b57cec5SDimitry Andric         * If we skipped non-options, set optind
2680b57cec5SDimitry Andric         * to the first of them.
2690b57cec5SDimitry Andric         */
2700b57cec5SDimitry Andric         optind = nonopt_start;
2710b57cec5SDimitry Andric       }
2720b57cec5SDimitry Andric       nonopt_start = nonopt_end = -1;
2730b57cec5SDimitry Andric       return (-1);
2740b57cec5SDimitry Andric     }
2750b57cec5SDimitry Andric     if (*(place = nargv[optind]) != '-' ||
2760b57cec5SDimitry Andric         (place[1] == '\0' && strchr(options, '-') == NULL)) {
2770b57cec5SDimitry Andric       place = EMSG; /* found non-option */
2780b57cec5SDimitry Andric       if (flags & FLAG_ALLARGS) {
2790b57cec5SDimitry Andric         /*
2800b57cec5SDimitry Andric         * GNU extension:
2810b57cec5SDimitry Andric         * return non-option as argument to option 1
2820b57cec5SDimitry Andric         */
2830b57cec5SDimitry Andric         optarg = nargv[optind++];
2840b57cec5SDimitry Andric         return (INORDER);
2850b57cec5SDimitry Andric       }
2860b57cec5SDimitry Andric       if (!(flags & FLAG_PERMUTE)) {
2870b57cec5SDimitry Andric         /*
2880b57cec5SDimitry Andric         * If no permutation wanted, stop parsing
2890b57cec5SDimitry Andric         * at first non-option.
2900b57cec5SDimitry Andric         */
2910b57cec5SDimitry Andric         return (-1);
2920b57cec5SDimitry Andric       }
2930b57cec5SDimitry Andric       /* do permutation */
2940b57cec5SDimitry Andric       if (nonopt_start == -1)
2950b57cec5SDimitry Andric         nonopt_start = optind;
2960b57cec5SDimitry Andric       else if (nonopt_end != -1) {
2970b57cec5SDimitry Andric         permute_args(nonopt_start, nonopt_end, optind, nargv);
2980b57cec5SDimitry Andric         nonopt_start = optind - (nonopt_end - nonopt_start);
2990b57cec5SDimitry Andric         nonopt_end = -1;
3000b57cec5SDimitry Andric       }
3010b57cec5SDimitry Andric       optind++;
3020b57cec5SDimitry Andric       /* process next argument */
3030b57cec5SDimitry Andric       goto start;
3040b57cec5SDimitry Andric     }
3050b57cec5SDimitry Andric     if (nonopt_start != -1 && nonopt_end == -1)
3060b57cec5SDimitry Andric       nonopt_end = optind;
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric     /*
3090b57cec5SDimitry Andric     * If we have "-" do nothing, if "--" we are done.
3100b57cec5SDimitry Andric     */
3110b57cec5SDimitry Andric     if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
3120b57cec5SDimitry Andric       optind++;
3130b57cec5SDimitry Andric       place = EMSG;
3140b57cec5SDimitry Andric       /*
3150b57cec5SDimitry Andric       * We found an option (--), so if we skipped
3160b57cec5SDimitry Andric       * non-options, we have to permute.
3170b57cec5SDimitry Andric       */
3180b57cec5SDimitry Andric       if (nonopt_end != -1) {
3190b57cec5SDimitry Andric         permute_args(nonopt_start, nonopt_end, optind, nargv);
3200b57cec5SDimitry Andric         optind -= nonopt_end - nonopt_start;
3210b57cec5SDimitry Andric       }
3220b57cec5SDimitry Andric       nonopt_start = nonopt_end = -1;
3230b57cec5SDimitry Andric       return (-1);
3240b57cec5SDimitry Andric     }
3250b57cec5SDimitry Andric   }
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   /*
3280b57cec5SDimitry Andric   * Check long options if:
3290b57cec5SDimitry Andric   *  1) we were passed some
3300b57cec5SDimitry Andric   *  2) the arg is not just "-"
3310b57cec5SDimitry Andric   *  3) either the arg starts with -- we are getopt_long_only()
3320b57cec5SDimitry Andric   */
3330b57cec5SDimitry Andric   if (long_options != NULL && place != nargv[optind] &&
3340b57cec5SDimitry Andric       (*place == '-' || (flags & FLAG_LONGONLY))) {
3350b57cec5SDimitry Andric     short_too = 0;
3360b57cec5SDimitry Andric     if (*place == '-')
3370b57cec5SDimitry Andric       place++; /* --foo long option */
3380b57cec5SDimitry Andric     else if (*place != ':' && strchr(options, *place) != NULL)
3390b57cec5SDimitry Andric       short_too = 1; /* could be short option too */
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric     optchar = parse_long_options(nargv, options, long_options, idx, short_too);
3420b57cec5SDimitry Andric     if (optchar != -1) {
3430b57cec5SDimitry Andric       place = EMSG;
3440b57cec5SDimitry Andric       return (optchar);
3450b57cec5SDimitry Andric     }
3460b57cec5SDimitry Andric   }
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric   if ((optchar = (int)*place++) == (int)':' ||
3490b57cec5SDimitry Andric       (optchar == (int)'-' && *place != '\0') ||
3500b57cec5SDimitry Andric       (oli = strchr(options, optchar)) == NULL) {
3510b57cec5SDimitry Andric     /*
3520b57cec5SDimitry Andric     * If the user specified "-" and  '-' isn't listed in
3530b57cec5SDimitry Andric     * options, return -1 (non-option) as per POSIX.
3540b57cec5SDimitry Andric     * Otherwise, it is an unknown option character (or ':').
3550b57cec5SDimitry Andric     */
3560b57cec5SDimitry Andric     if (optchar == (int)'-' && *place == '\0')
3570b57cec5SDimitry Andric       return (-1);
3580b57cec5SDimitry Andric     if (!*place)
3590b57cec5SDimitry Andric       ++optind;
3600b57cec5SDimitry Andric     if (PRINT_ERROR)
3610b57cec5SDimitry Andric       warnx(illoptchar, optchar);
3620b57cec5SDimitry Andric     optopt = optchar;
3630b57cec5SDimitry Andric     return (BADCH);
3640b57cec5SDimitry Andric   }
3650b57cec5SDimitry Andric   if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
3660b57cec5SDimitry Andric     /* -W long-option */
3670b57cec5SDimitry Andric     if (*place) /* no space */
3680b57cec5SDimitry Andric       /* NOTHING */;
3690b57cec5SDimitry Andric     else if (++optind >= nargc) { /* no arg */
3700b57cec5SDimitry Andric       place = EMSG;
3710b57cec5SDimitry Andric       if (PRINT_ERROR)
3720b57cec5SDimitry Andric         warnx(recargchar, optchar);
3730b57cec5SDimitry Andric       optopt = optchar;
3740b57cec5SDimitry Andric       return (BADARG);
3750b57cec5SDimitry Andric     } else /* white space */
3760b57cec5SDimitry Andric       place = nargv[optind];
3770b57cec5SDimitry Andric     optchar = parse_long_options(nargv, options, long_options, idx, 0);
3780b57cec5SDimitry Andric     place = EMSG;
3790b57cec5SDimitry Andric     return (optchar);
3800b57cec5SDimitry Andric   }
3810b57cec5SDimitry Andric   if (*++oli != ':') { /* doesn't take argument */
3820b57cec5SDimitry Andric     if (!*place)
3830b57cec5SDimitry Andric       ++optind;
3840b57cec5SDimitry Andric   } else { /* takes (optional) argument */
3850b57cec5SDimitry Andric     optarg = NULL;
3860b57cec5SDimitry Andric     if (*place) /* no white space */
3870b57cec5SDimitry Andric       optarg = const_cast<char *>(place);
3880b57cec5SDimitry Andric     else if (oli[1] != ':') {  /* arg not optional */
3890b57cec5SDimitry Andric       if (++optind >= nargc) { /* no arg */
3900b57cec5SDimitry Andric         place = EMSG;
3910b57cec5SDimitry Andric         if (PRINT_ERROR)
3920b57cec5SDimitry Andric           warnx(recargchar, optchar);
3930b57cec5SDimitry Andric         optopt = optchar;
3940b57cec5SDimitry Andric         return (BADARG);
3950b57cec5SDimitry Andric       } else
3960b57cec5SDimitry Andric         optarg = nargv[optind];
3970b57cec5SDimitry Andric     }
3980b57cec5SDimitry Andric     place = EMSG;
3990b57cec5SDimitry Andric     ++optind;
4000b57cec5SDimitry Andric   }
4010b57cec5SDimitry Andric   /* dump back option letter */
4020b57cec5SDimitry Andric   return (optchar);
4030b57cec5SDimitry Andric }
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric /*
4060b57cec5SDimitry Andric * getopt --
4070b57cec5SDimitry Andric *  Parse argc/argv argument vector.
4080b57cec5SDimitry Andric *
4090b57cec5SDimitry Andric * [eventually this will replace the BSD getopt]
4100b57cec5SDimitry Andric */
4110b57cec5SDimitry Andric #if defined(REPLACE_GETOPT)
getopt(int nargc,char * const * nargv,const char * options)4120b57cec5SDimitry Andric int getopt(int nargc, char *const *nargv, const char *options) {
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   /*
4150b57cec5SDimitry Andric   * We don't pass FLAG_PERMUTE to getopt_internal() since
4160b57cec5SDimitry Andric   * the BSD getopt(3) (unlike GNU) has never done this.
4170b57cec5SDimitry Andric   *
4180b57cec5SDimitry Andric   * Furthermore, since many privileged programs call getopt()
4190b57cec5SDimitry Andric   * before dropping privileges it makes sense to keep things
4200b57cec5SDimitry Andric   * as simple (and bug-free) as possible.
4210b57cec5SDimitry Andric   */
4220b57cec5SDimitry Andric   return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
4230b57cec5SDimitry Andric }
4240b57cec5SDimitry Andric #endif
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric /*
4270b57cec5SDimitry Andric * getopt_long --
4280b57cec5SDimitry Andric *  Parse argc/argv argument vector.
4290b57cec5SDimitry Andric */
4300b57cec5SDimitry Andric #if defined(REPLACE_GETOPT_LONG)
getopt_long(int nargc,char * const * nargv,const char * options,const struct option * long_options,int * idx)4310b57cec5SDimitry Andric int getopt_long(int nargc, char *const *nargv, const char *options,
4320b57cec5SDimitry Andric                 const struct option *long_options, int *idx) {
4330b57cec5SDimitry Andric   return (
4340b57cec5SDimitry Andric       getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE));
4350b57cec5SDimitry Andric }
4360b57cec5SDimitry Andric #endif
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric /*
4390b57cec5SDimitry Andric * getopt_long_only --
4400b57cec5SDimitry Andric *  Parse argc/argv argument vector.
4410b57cec5SDimitry Andric */
4420b57cec5SDimitry Andric #if defined(REPLACE_GETOPT_LONG_ONLY)
getopt_long_only(int nargc,char * const * nargv,const char * options,const struct option * long_options,int * idx)4430b57cec5SDimitry Andric int getopt_long_only(int nargc, char *const *nargv, const char *options,
4440b57cec5SDimitry Andric                      const struct option *long_options, int *idx) {
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   return (getopt_internal(nargc, nargv, options, long_options, idx,
4470b57cec5SDimitry Andric                           FLAG_PERMUTE | FLAG_LONGONLY));
4480b57cec5SDimitry Andric }
4490b57cec5SDimitry Andric #endif
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric #endif
452