Changeset 1622 for branches/FREEBSD


Ignore:
Timestamp:
Nov 8, 2004, 1:35:00 AM (21 years ago)
Author:
bird
Message:

FreeBSD 5.3 libc sources.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/FREEBSD/src/emx/src/lib/bsd/stdlib/getopt_long.c

    • Property cvs2svn:cvs-rev changed from 1.1 to 1.1.1.2
    r1621 r1622  
     1/*      $OpenBSD: getopt_long.c,v 1.17 2004/06/03 18:46:52 millert Exp $        */
    12/*      $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $      */
    2 /*      $FreeBSD: src/lib/libc/stdlib/getopt_long.c,v 1.2 2002/10/16 22:18:42 alfred Exp $ */
    3 
     3
     4/*
     5 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
     6 *
     7 * Permission to use, copy, modify, and distribute this software for any
     8 * purpose with or without fee is hereby granted, provided that the above
     9 * copyright notice and this permission notice appear in all copies.
     10 *
     11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18 *
     19 * Sponsored in part by the Defense Advanced Research Projects
     20 * Agency (DARPA) and Air Force Research Laboratory, Air Force
     21 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
     22 */
    423/*-
    524 * Copyright (c) 2000 The NetBSD Foundation, Inc.
     
    3857 */
    3958
     59#if 0
     60#if defined(LIBC_SCCS) && !defined(lint)
     61static char *rcsid = "$OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 millert Exp $";
     62#endif /* LIBC_SCCS and not lint */
     63#endif
    4064#include <sys/cdefs.h>
    41 #if defined(LIBC_SCCS) && !defined(lint)
    42 __RCSID("$NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $");
    43 #endif /* LIBC_SCCS and not lint */
    44 
    45 #include "namespace.h"
    46 
    47 #include <assert.h>
     65__FBSDID("$FreeBSD: src/lib/libc/stdlib/getopt_long.c,v 1.12 2004/07/06 13:58:45 ache Exp $");
     66
    4867#include <err.h>
    4968#include <errno.h>
     
    5271#include <string.h>
    5372
    54 /* not part of the original file */
    55 #ifndef _DIAGASSERT
    56 #define _DIAGASSERT(X)
    57 #endif
    58 
    59 #if HAVE_CONFIG_H && !HAVE_GETOPT_LONG && !HAVE_DECL_OPTIND
    60 #define REPLACE_GETOPT
     73#define GNU_COMPATIBLE          /* Be more compatible, configure's use us! */
     74
     75#ifndef GNU_COMPATIBLE
     76#define REPLACE_GETOPT          /* use this getopt as the system getopt(3) */
    6177#endif
    6278
    6379#ifdef REPLACE_GETOPT
    64 #ifdef __weak_alias
    65 __weak_alias(getopt,_getopt)
    66 #endif
    6780int     opterr = 1;             /* if error message should be printed */
    6881int     optind = 1;             /* index into parent argv vector */
     
    7083int     optreset;               /* reset getopt */
    7184char    *optarg;                /* argument associated with option */
    72 #elif HAVE_CONFIG_H && !HAVE_DECL_OPTRESET
    73 static int optreset;
    74 #endif
    75 
    76 #ifdef __weak_alias
    77 __weak_alias(getopt_long,_getopt_long)
    78 #endif
    79 
    80 #if !HAVE_GETOPT_LONG
    81 #define IGNORE_FIRST    (*options == '-' || *options == '+')
    82 #define PRINT_ERROR     ((opterr) && ((*options != ':') \
    83                                       || (IGNORE_FIRST && options[1] != ':')))
    84 #define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL)
    85 #define PERMUTE         (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
    86 /* XXX: GNU ignores PC if *options == '-' */
    87 #define IN_ORDER        (!IS_POSIXLY_CORRECT && *options == '-')
     85#endif
     86
     87#define PRINT_ERROR     ((opterr) && (*options != ':'))
     88
     89#define FLAG_PERMUTE    0x01    /* permute non-options to the end of argv */
     90#define FLAG_ALLARGS    0x02    /* treat non-options as args to option "-1" */
     91#define FLAG_LONGONLY   0x04    /* operate as getopt_long_only */
    8892
    8993/* return values */
    90 #define BADCH   (int)'?'
    91 #define BADARG          ((IGNORE_FIRST && options[1] == ':') \
    92                          || (*options == ':') ? (int)':' : (int)'?')
    93 #define INORDER (int)1
    94 
    95 #define EMSG    ""
    96 
    97 static int getopt_internal(int, char * const *, const char *);
     94#define BADCH           (int)'?'
     95#define BADARG          ((*options == ':') ? (int)':' : (int)'?')
     96#define INORDER         (int)1
     97
     98#define EMSG            ""
     99
     100#ifdef GNU_COMPATIBLE
     101#define NO_PREFIX       (-1)
     102#define D_PREFIX        0
     103#define DD_PREFIX       1
     104#define W_PREFIX        2
     105#endif
     106
     107static int getopt_internal(int, char * const *, const char *,
     108                           const struct option *, int *, int);
     109static int parse_long_options(char * const *, const char *,
     110                              const struct option *, int *, int, int);
    98111static int gcd(int, int);
    99112static void permute_args(int, int, int, char * const *);
     
    107120/* Error messages */
    108121static const char recargchar[] = "option requires an argument -- %c";
     122static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */
     123#ifdef GNU_COMPATIBLE
     124static int dash_prefix = NO_PREFIX;
     125static const char gnuoptchar[] = "invalid option -- %c";
     126
     127static const char recargstring[] = "option `%s%s' requires an argument";
     128static const char ambig[] = "option `%s%.*s' is ambiguous";
     129static const char noarg[] = "option `%s%.*s' doesn't allow an argument";
     130static const char illoptstring[] = "unrecognized option `%s%s'";
     131#else
    109132static const char recargstring[] = "option requires an argument -- %s";
    110133static const char ambig[] = "ambiguous option -- %.*s";
    111134static const char noarg[] = "option doesn't take an argument -- %.*s";
    112 static const char illoptchar[] = "unknown option -- %c";
    113135static const char illoptstring[] = "unknown option -- %s";
    114 
     136#endif
    115137
    116138/*
     
    118140 */
    119141static int
    120 gcd(a, b)
    121         int a;
    122         int b;
     142gcd(int a, int b)
    123143{
    124144        int c;
     
    130150                c = a % b;
    131151        }
    132            
    133         return b;
     152
     153        return (b);
    134154}
    135155
     
    140160 */
    141161static void
    142 permute_args(panonopt_start, panonopt_end, opt_end, nargv)
    143         int panonopt_start;
    144         int panonopt_end;
    145         int opt_end;
    146         char * const *nargv;
     162permute_args(int panonopt_start, int panonopt_end, int opt_end,
     163        char * const *nargv)
    147164{
    148165        int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
    149166        char *swap;
    150 
    151         _DIAGASSERT(nargv != NULL);
    152167
    153168        /*
     
    177192
    178193/*
     194 * parse_long_options --
     195 *      Parse long options in argc/argv argument vector.
     196 * Returns -1 if short_too is set and the option does not match long_options.
     197 */
     198static int
     199parse_long_options(char * const *nargv, const char *options,
     200        const struct option *long_options, int *idx, int short_too, int flags)
     201{
     202        char *current_argv, *has_equal;
     203#ifdef GNU_COMPATIBLE
     204        char *current_dash;
     205#endif
     206        size_t current_argv_len;
     207        int i, match, exact_match, second_partial_match;
     208
     209        current_argv = place;
     210#ifdef GNU_COMPATIBLE
     211        switch (dash_prefix) {
     212                case D_PREFIX:
     213                        current_dash = "-";
     214                        break;
     215                case DD_PREFIX:
     216                        current_dash = "--";
     217                        break;
     218                case W_PREFIX:
     219                        current_dash = "-W ";
     220                        break;
     221                default:
     222                        current_dash = "";
     223                        break;
     224        }
     225#endif
     226        match = -1;
     227        exact_match = 0;
     228        second_partial_match = 0;
     229
     230        optind++;
     231
     232        if ((has_equal = strchr(current_argv, '=')) != NULL) {
     233                /* argument found (--option=arg) */
     234                current_argv_len = has_equal - current_argv;
     235                has_equal++;
     236        } else
     237                current_argv_len = strlen(current_argv);
     238
     239        for (i = 0; long_options[i].name; i++) {
     240                /* find matching long option */
     241                if (strncmp(current_argv, long_options[i].name,
     242                    current_argv_len))
     243                        continue;
     244
     245                if (strlen(long_options[i].name) == current_argv_len) {
     246                        /* exact match */
     247                        match = i;
     248                        exact_match = 1;
     249                        break;
     250                }
     251                /*
     252                 * If this is a known short option, don't allow
     253                 * a partial match of a single character.
     254                 */
     255                if (short_too && current_argv_len == 1)
     256                        continue;
     257
     258                if (match == -1)        /* first partial match */
     259                        match = i;
     260                else if ((flags & FLAG_LONGONLY) ||
     261                         long_options[i].has_arg !=
     262                             long_options[match].has_arg ||
     263                         long_options[i].flag != long_options[match].flag ||
     264                         long_options[i].val != long_options[match].val)
     265                        second_partial_match = 1;
     266        }
     267        if (!exact_match && second_partial_match) {
     268                /* ambiguous abbreviation */
     269                if (PRINT_ERROR)
     270                        warnx(ambig,
     271#ifdef GNU_COMPATIBLE
     272                             current_dash,
     273#endif
     274                             (int)current_argv_len,
     275                             current_argv);
     276                optopt = 0;
     277                return (BADCH);
     278        }
     279        if (match != -1) {              /* option found */
     280                if (long_options[match].has_arg == no_argument
     281                    && has_equal) {
     282                        if (PRINT_ERROR)
     283                                warnx(noarg,
     284#ifdef GNU_COMPATIBLE
     285                                     current_dash,
     286#endif
     287                                     (int)current_argv_len,
     288                                     current_argv);
     289                        /*
     290                         * XXX: GNU sets optopt to val regardless of flag
     291                         */
     292                        if (long_options[match].flag == NULL)
     293                                optopt = long_options[match].val;
     294                        else
     295                                optopt = 0;
     296#ifdef GNU_COMPATIBLE
     297                        return (BADCH);
     298#else
     299                        return (BADARG);
     300#endif
     301                }
     302                if (long_options[match].has_arg == required_argument ||
     303                    long_options[match].has_arg == optional_argument) {
     304                        if (has_equal)
     305                                optarg = has_equal;
     306                        else if (long_options[match].has_arg ==
     307                            required_argument) {
     308                                /*
     309                                 * optional argument doesn't use next nargv
     310                                 */
     311                                optarg = nargv[optind++];
     312                        }
     313                }
     314                if ((long_options[match].has_arg == required_argument)
     315                    && (optarg == NULL)) {
     316                        /*
     317                         * Missing argument; leading ':' indicates no error
     318                         * should be generated.
     319                         */
     320                        if (PRINT_ERROR)
     321                                warnx(recargstring,
     322#ifdef GNU_COMPATIBLE
     323                                    current_dash,
     324#endif
     325                                    current_argv);
     326                        /*
     327                         * XXX: GNU sets optopt to val regardless of flag
     328                         */
     329                        if (long_options[match].flag == NULL)
     330                                optopt = long_options[match].val;
     331                        else
     332                                optopt = 0;
     333                        --optind;
     334                        return (BADARG);
     335                }
     336        } else {                        /* unknown option */
     337                if (short_too) {
     338                        --optind;
     339                        return (-1);
     340                }
     341                if (PRINT_ERROR)
     342                        warnx(illoptstring,
     343#ifdef GNU_COMPATIBLE
     344                              current_dash,
     345#endif
     346                              current_argv);
     347                optopt = 0;
     348                return (BADCH);
     349        }
     350        if (idx)
     351                *idx = match;
     352        if (long_options[match].flag) {
     353                *long_options[match].flag = long_options[match].val;
     354                return (0);
     355        } else
     356                return (long_options[match].val);
     357}
     358
     359/*
    179360 * getopt_internal --
    180361 *      Parse argc/argv argument vector.  Called by user level routines.
    181  *  Returns -2 if -- is found (can be long option or end of options marker).
    182362 */
    183363static int
    184 getopt_internal(nargc, nargv, options)
    185         int nargc;
    186         char * const *nargv;
    187         const char *options;
     364getopt_internal(int nargc, char * const *nargv, const char *options,
     365        const struct option *long_options, int *idx, int flags)
    188366{
    189367        char *oli;                              /* option letter list index */
    190         int optchar;
    191 
    192         _DIAGASSERT(nargv != NULL);
    193         _DIAGASSERT(options != NULL);
    194 
    195         optarg = NULL;
     368        int optchar, short_too;
     369        int posixly_correct;
     370
     371        if (options == NULL)
     372                return (-1);
    196373
    197374        /*
    198          * XXX Some programs (like rsyncd) expect to be able to
    199          * XXX re-initialize optind to 0 and have getopt_long(3)
    200          * XXX properly function again.  Work around this braindamage.
     375         * Disable GNU extensions if POSIXLY_CORRECT is set or options
     376         * string begins with a '+'.
     377         */
     378        posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
     379#ifdef GNU_COMPATIBLE
     380        if (*options == '-')
     381                flags |= FLAG_ALLARGS;
     382        else if (posixly_correct || *options == '+')
     383                flags &= ~FLAG_PERMUTE;
     384#else
     385        if (posixly_correct || *options == '+')
     386                flags &= ~FLAG_PERMUTE;
     387        else if (*options == '-')
     388                flags |= FLAG_ALLARGS;
     389#endif
     390        if (*options == '+' || *options == '-')
     391                options++;
     392
     393        /*
     394         * XXX Some GNU programs (like cvs) set optind to 0 instead of
     395         * XXX using optreset.  Work around this braindamage.
    201396         */
    202397        if (optind == 0)
    203                 optind = 1;
    204 
     398                optind = optreset = 1;
     399
     400        optarg = NULL;
    205401        if (optreset)
    206402                nonopt_start = nonopt_end = -1;
     
    224420                        }
    225421                        nonopt_start = nonopt_end = -1;
    226                         return -1;
    227                 }
    228                 if ((*(place = nargv[optind]) != '-')
    229                     || (place[1] == '\0')) {    /* found non-option */
    230                         place = EMSG;
    231                         if (IN_ORDER) {
     422                        return (-1);
     423                }
     424                if (*(place = nargv[optind]) != '-' ||
     425#ifdef GNU_COMPATIBLE
     426                    place[1] == '\0') {
     427#else
     428                    (place[1] == '\0' && strchr(options, '-') == NULL)) {
     429#endif
     430                        place = EMSG;           /* found non-option */
     431                        if (flags & FLAG_ALLARGS) {
    232432                                /*
    233                                  * GNU extension: 
     433                                 * GNU extension:
    234434                                 * return non-option as argument to option 1
    235435                                 */
    236436                                optarg = nargv[optind++];
    237                                 return INORDER;
     437                                return (INORDER);
    238438                        }
    239                         if (!PERMUTE) {
     439                        if (!(flags & FLAG_PERMUTE)) {
    240440                                /*
    241                                  * if no permutation wanted, stop parsing
    242                                  * at first non-option
     441                                 * If no permutation wanted, stop parsing
     442                                 * at first non-option.
    243443                                 */
    244                                 return -1;
     444                                return (-1);
    245445                        }
    246446                        /* do permutation */
     
    260460                if (nonopt_start != -1 && nonopt_end == -1)
    261461                        nonopt_end = optind;
    262                 if (place[1] && *++place == '-') {      /* found "--" */
    263                         place++;
    264                         return -2;
    265                 }
    266         }
     462
     463                /*
     464                 * If we have "-" do nothing, if "--" we are done.
     465                 */
     466                if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
     467                        optind++;
     468                        place = EMSG;
     469                        /*
     470                         * We found an option (--), so if we skipped
     471                         * non-options, we have to permute.
     472                         */
     473                        if (nonopt_end != -1) {
     474                                permute_args(nonopt_start, nonopt_end,
     475                                    optind, nargv);
     476                                optind -= nonopt_end - nonopt_start;
     477                        }
     478                        nonopt_start = nonopt_end = -1;
     479                        return (-1);
     480                }
     481        }
     482
     483        /*
     484         * Check long options if:
     485         *  1) we were passed some
     486         *  2) the arg is not just "-"
     487         *  3) either the arg starts with -- we are getopt_long_only()
     488         */
     489        if (long_options != NULL && place != nargv[optind] &&
     490            (*place == '-' || (flags & FLAG_LONGONLY))) {
     491                short_too = 0;
     492#ifdef GNU_COMPATIBLE
     493                dash_prefix = D_PREFIX;
     494#endif
     495                if (*place == '-') {
     496                        place++;                /* --foo long option */
     497#ifdef GNU_COMPATIBLE
     498                        dash_prefix = DD_PREFIX;
     499#endif
     500                } else if (*place != ':' && strchr(options, *place) != NULL)
     501                        short_too = 1;          /* could be short option too */
     502
     503                optchar = parse_long_options(nargv, options, long_options,
     504                    idx, short_too, flags);
     505                if (optchar != -1) {
     506                        place = EMSG;
     507                        return (optchar);
     508                }
     509        }
     510
    267511        if ((optchar = (int)*place++) == (int)':' ||
    268             (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
    269                 /* option letter unknown or ':' */
     512            (optchar == (int)'-' && *place != '\0') ||
     513            (oli = strchr(options, optchar)) == NULL) {
     514                /*
     515                 * If the user specified "-" and  '-' isn't listed in
     516                 * options, return -1 (non-option) as per POSIX.
     517                 * Otherwise, it is an unknown option character (or ':').
     518                 */
     519                if (optchar == (int)'-' && *place == '\0')
     520                        return (-1);
    270521                if (!*place)
    271522                        ++optind;
     523#ifdef GNU_COMPATIBLE
     524                if (PRINT_ERROR)
     525                        warnx(posixly_correct ? illoptchar : gnuoptchar,
     526                              optchar);
     527#else
    272528                if (PRINT_ERROR)
    273529                        warnx(illoptchar, optchar);
     530#endif
    274531                optopt = optchar;
    275                 return BADCH;
    276         }
    277         if (optchar == 'W' && oli[1] == ';') {          /* -W long-option */
    278                 /* XXX: what if no long options provided (called by getopt)? */
    279                 if (*place)
    280                         return -2;
    281 
    282                 if (++optind >= nargc) {        /* no arg */
     532                return (BADCH);
     533        }
     534        if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
     535                /* -W long-option */
     536                if (*place)                     /* no space */
     537                        /* NOTHING */;
     538                else if (++optind >= nargc) {   /* no arg */
    283539                        place = EMSG;
    284540                        if (PRINT_ERROR)
    285541                                warnx(recargchar, optchar);
    286542                        optopt = optchar;
    287                         return BADARG;
     543                        return (BADARG);
    288544                } else                          /* white space */
    289545                        place = nargv[optind];
    290                 /*
    291                  * Handle -W arg the same as --arg (which causes getopt to
    292                  * stop parsing).
    293                  */
    294                 return -2;
     546#ifdef GNU_COMPATIBLE
     547                dash_prefix = W_PREFIX;
     548#endif
     549                optchar = parse_long_options(nargv, options, long_options,
     550                    idx, 0, flags);
     551                place = EMSG;
     552                return (optchar);
    295553        }
    296554        if (*++oli != ':') {                    /* doesn't take argument */
     
    308566                                        warnx(recargchar, optchar);
    309567                                optopt = optchar;
    310                                 return BADARG;
     568                                return (BADARG);
    311569                        } else
    312570                                optarg = nargv[optind];
     571                } else if (!(flags & FLAG_PERMUTE)) {
     572                        /*
     573                         * If permutation is disabled, we can accept an
     574                         * optional arg separated by whitespace so long
     575                         * as it does not start with a dash (-).
     576                         */
     577                        if (optind + 1 < nargc && *nargv[optind + 1] != '-')
     578                                optarg = nargv[++optind];
    313579                }
    314580                place = EMSG;
     
    316582        }
    317583        /* dump back option letter */
    318         return optchar;
     584        return (optchar);
    319585}
    320586
     
    324590 *      Parse argc/argv argument vector.
    325591 *
    326  * [eventually this will replace the real getopt]
     592 * [eventually this will replace the BSD getopt]
    327593 */
    328594int
    329 getopt(nargc, nargv, options)
    330         int nargc;
    331         char * const *nargv;
    332         const char *options;
     595getopt(int nargc, char * const *nargv, const char *options)
    333596{
    334         int retval;
    335 
    336         _DIAGASSERT(nargv != NULL);
    337         _DIAGASSERT(options != NULL);
    338 
    339         if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
    340                 ++optind;
    341                 /*
    342                  * We found an option (--), so if we skipped non-options,
    343                  * we have to permute.
    344                  */
    345                 if (nonopt_end != -1) {
    346                         permute_args(nonopt_start, nonopt_end, optind,
    347                                        nargv);
    348                         optind -= nonopt_end - nonopt_start;
    349                 }
    350                 nonopt_start = nonopt_end = -1;
    351                 retval = -1;
    352         }
    353         return retval;
     597
     598        /*
     599         * We don't pass FLAG_PERMUTE to getopt_internal() since
     600         * the BSD getopt(3) (unlike GNU) has never done this.
     601         *
     602         * Furthermore, since many privileged programs call getopt()
     603         * before dropping privileges it makes sense to keep things
     604         * as simple (and bug-free) as possible.
     605         */
     606        return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
    354607}
    355 #endif
     608#endif /* REPLACE_GETOPT */
    356609
    357610/*
     
    367620        int *idx;
    368621{
    369         int retval;
    370 
    371         _DIAGASSERT(nargv != NULL);
    372         _DIAGASSERT(options != NULL);
    373         _DIAGASSERT(long_options != NULL);
    374         /* idx may be NULL */
    375 
    376         if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
    377                 char *current_argv, *has_equal;
    378                 size_t current_argv_len;
    379                 int i, match;
    380 
    381                 current_argv = place;
    382                 match = -1;
    383 
    384                 optind++;
    385                 place = EMSG;
    386 
    387                 if (*current_argv == '\0') {            /* found "--" */
    388                         /*
    389                          * We found an option (--), so if we skipped
    390                          * non-options, we have to permute.
    391                          */
    392                         if (nonopt_end != -1) {
    393                                 permute_args(nonopt_start, nonopt_end,
    394                                     optind, nargv);
    395                                 optind -= nonopt_end - nonopt_start;
    396                         }
    397                         nonopt_start = nonopt_end = -1;
    398                         return -1;
    399                 }
    400                 if ((has_equal = strchr(current_argv, '=')) != NULL) {
    401                         /* argument found (--option=arg) */
    402                         current_argv_len = has_equal - current_argv;
    403                         has_equal++;
    404                 } else
    405                         current_argv_len = strlen(current_argv);
    406            
    407                 for (i = 0; long_options[i].name; i++) {
    408                         /* find matching long option */
    409                         if (strncmp(current_argv, long_options[i].name,
    410                             current_argv_len))
    411                                 continue;
    412 
    413                         if (strlen(long_options[i].name) ==
    414                             (unsigned)current_argv_len) {
    415                                 /* exact match */
    416                                 match = i;
    417                                 break;
    418                         }
    419                         if (match == -1)                /* partial match */
    420                                 match = i;
    421                         else {
    422                                 /* ambiguous abbreviation */
    423                                 if (PRINT_ERROR)
    424                                         warnx(ambig, (int)current_argv_len,
    425                                              current_argv);
    426                                 optopt = 0;
    427                                 return BADCH;
    428                         }
    429                 }
    430                 if (match != -1) {                      /* option found */
    431                         if (long_options[match].has_arg == no_argument
    432                             && has_equal) {
    433                                 if (PRINT_ERROR)
    434                                         warnx(noarg, (int)current_argv_len,
    435                                              current_argv);
    436                                 /*
    437                                  * XXX: GNU sets optopt to val regardless of
    438                                  * flag
    439                                  */
    440                                 if (long_options[match].flag == NULL)
    441                                         optopt = long_options[match].val;
    442                                 else
    443                                         optopt = 0;
    444                                 return BADARG;
    445                         }
    446                         if (long_options[match].has_arg == required_argument ||
    447                             long_options[match].has_arg == optional_argument) {
    448                                 if (has_equal)
    449                                         optarg = has_equal;
    450                                 else if (long_options[match].has_arg ==
    451                                     required_argument) {
    452                                         /*
    453                                          * optional argument doesn't use
    454                                          * next nargv
    455                                          */
    456                                         optarg = nargv[optind++];
    457                                 }
    458                         }
    459                         if ((long_options[match].has_arg == required_argument)
    460                             && (optarg == NULL)) {
    461                                 /*
    462                                  * Missing argument; leading ':'
    463                                  * indicates no error should be generated
    464                                  */
    465                                 if (PRINT_ERROR)
    466                                         warnx(recargstring, current_argv);
    467                                 /*
    468                                  * XXX: GNU sets optopt to val regardless
    469                                  * of flag
    470                                  */
    471                                 if (long_options[match].flag == NULL)
    472                                         optopt = long_options[match].val;
    473                                 else
    474                                         optopt = 0;
    475                                 --optind;
    476                                 return BADARG;
    477                         }
    478                 } else {                        /* unknown option */
    479                         if (PRINT_ERROR)
    480                                 warnx(illoptstring, current_argv);
    481                         optopt = 0;
    482                         return BADCH;
    483                 }
    484                 if (long_options[match].flag) {
    485                         *long_options[match].flag = long_options[match].val;
    486                         retval = 0;
    487                 } else
    488                         retval = long_options[match].val;
    489                 if (idx)
    490                         *idx = match;
    491         }
    492         return retval;
     622
     623        return (getopt_internal(nargc, nargv, options, long_options, idx,
     624            FLAG_PERMUTE));
    493625}
    494 #endif /* !GETOPT_LONG */
     626
     627/*
     628 * getopt_long_only --
     629 *      Parse argc/argv argument vector.
     630 */
     631int
     632getopt_long_only(nargc, nargv, options, long_options, idx)
     633        int nargc;
     634        char * const *nargv;
     635        const char *options;
     636        const struct option *long_options;
     637        int *idx;
     638{
     639
     640        return (getopt_internal(nargc, nargv, options, long_options, idx,
     641            FLAG_PERMUTE|FLAG_LONGONLY));
     642}
Note: See TracChangeset for help on using the changeset viewer.