Changeset 1623


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

Attempted 5.1 -> 5.3 join up.

File:
1 edited

Legend:

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

    • Property cvs2svn:cvs-rev changed from 1.2 to 1.3
    r1622 r1623  
     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#ifdef __EMX__
     60#include "namespace.h"
     61#endif
     62
     63#if 0
     64#if defined(LIBC_SCCS) && !defined(lint)
     65static char *rcsid = "$OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 millert Exp $";
     66#endif /* LIBC_SCCS and not lint */
     67#endif
    4068#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>
     69__FBSDID("$FreeBSD: src/lib/libc/stdlib/getopt_long.c,v 1.12 2004/07/06 13:58:45 ache Exp $");
     70
    4871#include <err.h>
    4972#include <errno.h>
     
    5679#endif
    5780
    58 /* not part of the original file */
    59 #ifndef _DIAGASSERT
    60 #define _DIAGASSERT(X)
    61 #endif
    62 
    63 #if HAVE_CONFIG_H && !HAVE_GETOPT_LONG && !HAVE_DECL_OPTIND
    64 #define REPLACE_GETOPT
     81#define GNU_COMPATIBLE          /* Be more compatible, configure's use us! */
     82
     83#ifndef GNU_COMPATIBLE
     84#define REPLACE_GETOPT          /* use this getopt as the system getopt(3) */
    6585#endif
    6686
    6787#ifdef REPLACE_GETOPT
    68 #ifdef __weak_alias
    69 __weak_alias(getopt,_getopt)
    70 #endif
    7188int     opterr = 1;             /* if error message should be printed */
    7289int     optind = 1;             /* index into parent argv vector */
     
    7491int     optreset;               /* reset getopt */
    7592char    *optarg;                /* argument associated with option */
    76 #elif HAVE_CONFIG_H && !HAVE_DECL_OPTRESET
    77 static int optreset;
    78 #endif
    79 
    80 #ifdef __weak_alias
    81 __weak_alias(getopt_long,_getopt_long)
    82 #endif
    83 
    84 #if !HAVE_GETOPT_LONG
    85 #define IGNORE_FIRST    (*options == '-' || *options == '+')
    86 #define PRINT_ERROR     ((opterr) && ((*options != ':') \
    87                                       || (IGNORE_FIRST && options[1] != ':')))
    88 #define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL)
    89 #define PERMUTE         (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
    90 /* XXX: GNU ignores PC if *options == '-' */
    91 #define IN_ORDER        (!IS_POSIXLY_CORRECT && *options == '-')
     93#endif
     94
     95#define PRINT_ERROR     ((opterr) && (*options != ':'))
     96
     97#define FLAG_PERMUTE    0x01    /* permute non-options to the end of argv */
     98#define FLAG_ALLARGS    0x02    /* treat non-options as args to option "-1" */
     99#define FLAG_LONGONLY   0x04    /* operate as getopt_long_only */
    92100
    93101/* return values */
    94 #define BADCH   (int)'?'
    95 #define BADARG          ((IGNORE_FIRST && options[1] == ':') \
    96                          || (*options == ':') ? (int)':' : (int)'?')
    97 #define INORDER (int)1
    98 
    99 #define EMSG    ""
    100 
    101 static int getopt_internal(int, char * const *, const char *);
     102#define BADCH           (int)'?'
     103#define BADARG          ((*options == ':') ? (int)':' : (int)'?')
     104#define INORDER         (int)1
     105
     106#define EMSG            ""
     107
     108#ifdef GNU_COMPATIBLE
     109#define NO_PREFIX       (-1)
     110#define D_PREFIX        0
     111#define DD_PREFIX       1
     112#define W_PREFIX        2
     113#endif
     114
     115static int getopt_internal(int, char * const *, const char *,
     116                           const struct option *, int *, int);
     117static int parse_long_options(char * const *, const char *,
     118                              const struct option *, int *, int, int);
    102119static int gcd(int, int);
    103120static void permute_args(int, int, int, char * const *);
     
    111128/* Error messages */
    112129static const char recargchar[] = "option requires an argument -- %c";
     130static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */
     131#ifdef GNU_COMPATIBLE
     132static int dash_prefix = NO_PREFIX;
     133static const char gnuoptchar[] = "invalid option -- %c";
     134
     135static const char recargstring[] = "option `%s%s' requires an argument";
     136static const char ambig[] = "option `%s%.*s' is ambiguous";
     137static const char noarg[] = "option `%s%.*s' doesn't allow an argument";
     138static const char illoptstring[] = "unrecognized option `%s%s'";
     139#else
    113140static const char recargstring[] = "option requires an argument -- %s";
    114141static const char ambig[] = "ambiguous option -- %.*s";
    115142static const char noarg[] = "option doesn't take an argument -- %.*s";
    116 static const char illoptchar[] = "unknown option -- %c";
    117143static const char illoptstring[] = "unknown option -- %s";
    118 
     144#endif
    119145
    120146/*
     
    122148 */
    123149static int
    124 gcd(a, b)
    125         int a;
    126         int b;
     150gcd(int a, int b)
    127151{
    128152        int c;
     
    134158                c = a % b;
    135159        }
    136        
    137         return b;
     160        return (b);
    138161}
    139162
     
    144167 */
    145168static void
    146 permute_args(panonopt_start, panonopt_end, opt_end, nargv)
    147         int panonopt_start;
    148         int panonopt_end;
    149         int opt_end;
    150         char * const *nargv;
     169permute_args(int panonopt_start, int panonopt_end, int opt_end,
     170        char * const *nargv)
    151171{
    152172        int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
    153173        char *swap;
    154 
    155         _DIAGASSERT(nargv != NULL);
    156174
    157175        /*
     
    181199
    182200/*
     201 * parse_long_options --
     202 *      Parse long options in argc/argv argument vector.
     203 * Returns -1 if short_too is set and the option does not match long_options.
     204 */
     205static int
     206parse_long_options(char * const *nargv, const char *options,
     207        const struct option *long_options, int *idx, int short_too, int flags)
     208{
     209        char *current_argv, *has_equal;
     210#ifdef GNU_COMPATIBLE
     211        char *current_dash;
     212#endif
     213        size_t current_argv_len;
     214        int i, match, exact_match, second_partial_match;
     215
     216        current_argv = place;
     217#ifdef GNU_COMPATIBLE
     218        switch (dash_prefix) {
     219                case D_PREFIX:
     220                        current_dash = "-";
     221                        break;
     222                case DD_PREFIX:
     223                        current_dash = "--";
     224                        break;
     225                case W_PREFIX:
     226                        current_dash = "-W ";
     227                        break;
     228                default:
     229                        current_dash = "";
     230                        break;
     231        }
     232#endif
     233        match = -1;
     234        exact_match = 0;
     235        second_partial_match = 0;
     236
     237        optind++;
     238
     239        if ((has_equal = strchr(current_argv, '=')) != NULL) {
     240                /* argument found (--option=arg) */
     241                current_argv_len = has_equal - current_argv;
     242                has_equal++;
     243        } else
     244                current_argv_len = strlen(current_argv);
     245
     246        for (i = 0; long_options[i].name; i++) {
     247                /* find matching long option */
     248                if (strncmp(current_argv, long_options[i].name,
     249                    current_argv_len))
     250                        continue;
     251
     252                if (strlen(long_options[i].name) == current_argv_len) {
     253                        /* exact match */
     254                        match = i;
     255                        exact_match = 1;
     256                        break;
     257                }
     258                /*
     259                 * If this is a known short option, don't allow
     260                 * a partial match of a single character.
     261                 */
     262                if (short_too && current_argv_len == 1)
     263                        continue;
     264
     265                if (match == -1)        /* first partial match */
     266                        match = i;
     267                else if ((flags & FLAG_LONGONLY) ||
     268                         long_options[i].has_arg !=
     269                             long_options[match].has_arg ||
     270                         long_options[i].flag != long_options[match].flag ||
     271                         long_options[i].val != long_options[match].val)
     272                        second_partial_match = 1;
     273        }
     274        if (!exact_match && second_partial_match) {
     275                /* ambiguous abbreviation */
     276                if (PRINT_ERROR)
     277                        warnx(ambig,
     278#ifdef GNU_COMPATIBLE
     279                             current_dash,
     280#endif
     281                             (int)current_argv_len,
     282                             current_argv);
     283                optopt = 0;
     284                return (BADCH);
     285        }
     286        if (match != -1) {              /* option found */
     287                if (long_options[match].has_arg == no_argument
     288                    && has_equal) {
     289                        if (PRINT_ERROR)
     290                                warnx(noarg,
     291#ifdef GNU_COMPATIBLE
     292                                     current_dash,
     293#endif
     294                                     (int)current_argv_len,
     295                                     current_argv);
     296                        /*
     297                         * XXX: GNU sets optopt to val regardless of flag
     298                         */
     299                        if (long_options[match].flag == NULL)
     300                                optopt = long_options[match].val;
     301                        else
     302                                optopt = 0;
     303#ifdef GNU_COMPATIBLE
     304                        return (BADCH);
     305#else
     306                        return (BADARG);
     307#endif
     308                }
     309                if (long_options[match].has_arg == required_argument ||
     310                    long_options[match].has_arg == optional_argument) {
     311                        if (has_equal)
     312                                optarg = has_equal;
     313                        else if (long_options[match].has_arg ==
     314                            required_argument) {
     315                                /*
     316                                 * optional argument doesn't use next nargv
     317                                 */
     318                                optarg = nargv[optind++];
     319                        }
     320                }
     321                if ((long_options[match].has_arg == required_argument)
     322                    && (optarg == NULL)) {
     323                        /*
     324                         * Missing argument; leading ':' indicates no error
     325                         * should be generated.
     326                         */
     327                        if (PRINT_ERROR)
     328                                warnx(recargstring,
     329#ifdef GNU_COMPATIBLE
     330                                    current_dash,
     331#endif
     332                                    current_argv);
     333                        /*
     334                         * XXX: GNU sets optopt to val regardless of flag
     335                         */
     336                        if (long_options[match].flag == NULL)
     337                                optopt = long_options[match].val;
     338                        else
     339                                optopt = 0;
     340                        --optind;
     341                        return (BADARG);
     342                }
     343        } else {                        /* unknown option */
     344                if (short_too) {
     345                        --optind;
     346                        return (-1);
     347                }
     348                if (PRINT_ERROR)
     349                        warnx(illoptstring,
     350#ifdef GNU_COMPATIBLE
     351                              current_dash,
     352#endif
     353                              current_argv);
     354                optopt = 0;
     355                return (BADCH);
     356        }
     357        if (idx)
     358                *idx = match;
     359        if (long_options[match].flag) {
     360                *long_options[match].flag = long_options[match].val;
     361                return (0);
     362        } else
     363                return (long_options[match].val);
     364}
     365
     366/*
    183367 * getopt_internal --
    184368 *      Parse argc/argv argument vector.  Called by user level routines.
    185  *  Returns -2 if -- is found (can be long option or end of options marker).
    186369 */
    187370static int
    188 getopt_internal(nargc, nargv, options)
    189         int nargc;
    190         char * const *nargv;
    191         const char *options;
     371getopt_internal(int nargc, char * const *nargv, const char *options,
     372        const struct option *long_options, int *idx, int flags)
    192373{
    193374        char *oli;                              /* option letter list index */
    194         int optchar;
    195 
    196         _DIAGASSERT(nargv != NULL);
    197         _DIAGASSERT(options != NULL);
    198 
    199         optarg = NULL;
     375        int optchar, short_too;
     376        int posixly_correct;
     377
     378        if (options == NULL)
     379                return (-1);
    200380
    201381        /*
    202          * XXX Some programs (like rsyncd) expect to be able to
    203          * XXX re-initialize optind to 0 and have getopt_long(3)
    204          * XXX properly function again.  Work around this braindamage.
     382         * Disable GNU extensions if POSIXLY_CORRECT is set or options
     383         * string begins with a '+'.
     384         */
     385        posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
     386#ifdef GNU_COMPATIBLE
     387        if (*options == '-')
     388                flags |= FLAG_ALLARGS;
     389        else if (posixly_correct || *options == '+')
     390                flags &= ~FLAG_PERMUTE;
     391#else
     392        if (posixly_correct || *options == '+')
     393                flags &= ~FLAG_PERMUTE;
     394        else if (*options == '-')
     395                flags |= FLAG_ALLARGS;
     396#endif
     397        if (*options == '+' || *options == '-')
     398                options++;
     399
     400        /*
     401         * XXX Some GNU programs (like cvs) set optind to 0 instead of
     402         * XXX using optreset.  Work around this braindamage.
    205403         */
    206404        if (optind == 0)
    207                 optind = 1;
    208 
     405                optind = optreset = 1;
     406
     407        optarg = NULL;
    209408        if (optreset)
    210409                nonopt_start = nonopt_end = -1;
     
    228427                        }
    229428                        nonopt_start = nonopt_end = -1;
    230                         return -1;
    231                 }
    232                 if ((*(place = nargv[optind]) != '-')
    233                     || (place[1] == '\0')) {    /* found non-option */
    234                         place = EMSG;
    235                         if (IN_ORDER) {
     429                        return (-1);
     430                }
     431                if (*(place = nargv[optind]) != '-' ||
     432#ifdef GNU_COMPATIBLE
     433                    place[1] == '\0') {
     434#else
     435                    (place[1] == '\0' && strchr(options, '-') == NULL)) {
     436#endif
     437                        place = EMSG;           /* found non-option */
     438                        if (flags & FLAG_ALLARGS) {
    236439                                /*
    237440                                 * GNU extension:
     
    239442                                 */
    240443                                optarg = nargv[optind++];
    241                                 return INORDER;
     444                                return (INORDER);
    242445                        }
    243                         if (!PERMUTE) {
     446                        if (!(flags & FLAG_PERMUTE)) {
    244447                                /*
    245                                  * if no permutation wanted, stop parsing
    246                                  * at first non-option
     448                                 * If no permutation wanted, stop parsing
     449                                 * at first non-option.
    247450                                 */
    248                                 return -1;
     451                                return (-1);
    249452                        }
    250453                        /* do permutation */
     
    264467                if (nonopt_start != -1 && nonopt_end == -1)
    265468                        nonopt_end = optind;
    266                 if (place[1] && *++place == '-') {      /* found "--" */
    267                         place++;
    268                         return -2;
    269                 }
    270         }
     469
     470                /*
     471                 * If we have "-" do nothing, if "--" we are done.
     472                 */
     473                if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
     474                        optind++;
     475                        place = EMSG;
     476                        /*
     477                         * We found an option (--), so if we skipped
     478                         * non-options, we have to permute.
     479                         */
     480                        if (nonopt_end != -1) {
     481                                permute_args(nonopt_start, nonopt_end,
     482                                    optind, nargv);
     483                                optind -= nonopt_end - nonopt_start;
     484                        }
     485                        nonopt_start = nonopt_end = -1;
     486                        return (-1);
     487                }
     488        }
     489
     490        /*
     491         * Check long options if:
     492         *  1) we were passed some
     493         *  2) the arg is not just "-"
     494         *  3) either the arg starts with -- we are getopt_long_only()
     495         */
     496        if (long_options != NULL && place != nargv[optind] &&
     497            (*place == '-' || (flags & FLAG_LONGONLY))) {
     498                short_too = 0;
     499#ifdef GNU_COMPATIBLE
     500                dash_prefix = D_PREFIX;
     501#endif
     502                if (*place == '-') {
     503                        place++;                /* --foo long option */
     504#ifdef GNU_COMPATIBLE
     505                        dash_prefix = DD_PREFIX;
     506#endif
     507                } else if (*place != ':' && strchr(options, *place) != NULL)
     508                        short_too = 1;          /* could be short option too */
     509
     510                optchar = parse_long_options(nargv, options, long_options,
     511                    idx, short_too, flags);
     512                if (optchar != -1) {
     513                        place = EMSG;
     514                        return (optchar);
     515                }
     516        }
     517
    271518        if ((optchar = (int)*place++) == (int)':' ||
    272             (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
    273                 /* option letter unknown or ':' */
     519            (optchar == (int)'-' && *place != '\0') ||
     520            (oli = strchr(options, optchar)) == NULL) {
     521                /*
     522                 * If the user specified "-" and  '-' isn't listed in
     523                 * options, return -1 (non-option) as per POSIX.
     524                 * Otherwise, it is an unknown option character (or ':').
     525                 */
     526                if (optchar == (int)'-' && *place == '\0')
     527                        return (-1);
    274528                if (!*place)
    275529                        ++optind;
     530#ifdef GNU_COMPATIBLE
     531                if (PRINT_ERROR)
     532                        warnx(posixly_correct ? illoptchar : gnuoptchar,
     533                              optchar);
     534#else
    276535                if (PRINT_ERROR)
    277536                        warnx(illoptchar, optchar);
     537#endif
    278538                optopt = optchar;
    279                 return BADCH;
    280         }
    281         if (optchar == 'W' && oli[1] == ';') {          /* -W long-option */
    282                 /* XXX: what if no long options provided (called by getopt)? */
    283                 if (*place)
    284                         return -2;
    285 
    286                 if (++optind >= nargc) {        /* no arg */
     539                return (BADCH);
     540        }
     541        if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
     542                /* -W long-option */
     543                if (*place)                     /* no space */
     544                        /* NOTHING */;
     545                else if (++optind >= nargc) {   /* no arg */
    287546                        place = EMSG;
    288547                        if (PRINT_ERROR)
    289548                                warnx(recargchar, optchar);
    290549                        optopt = optchar;
    291                         return BADARG;
     550                        return (BADARG);
    292551                } else                          /* white space */
    293552                        place = nargv[optind];
    294                 /*
    295                  * Handle -W arg the same as --arg (which causes getopt to
    296                  * stop parsing).
    297                  */
    298                 return -2;
     553#ifdef GNU_COMPATIBLE
     554                dash_prefix = W_PREFIX;
     555#endif
     556                optchar = parse_long_options(nargv, options, long_options,
     557                    idx, 0, flags);
     558                place = EMSG;
     559                return (optchar);
    299560        }
    300561        if (*++oli != ':') {                    /* doesn't take argument */
     
    312573                                        warnx(recargchar, optchar);
    313574                                optopt = optchar;
    314                                 return BADARG;
     575                                return (BADARG);
    315576                        } else
    316577                                optarg = nargv[optind];
     578                } else if (!(flags & FLAG_PERMUTE)) {
     579                        /*
     580                         * If permutation is disabled, we can accept an
     581                         * optional arg separated by whitespace so long
     582                         * as it does not start with a dash (-).
     583                         */
     584                        if (optind + 1 < nargc && *nargv[optind + 1] != '-')
     585                                optarg = nargv[++optind];
    317586                }
    318587                place = EMSG;
     
    320589        }
    321590        /* dump back option letter */
    322         return optchar;
     591        return (optchar);
    323592}
    324593
     
    328597 *      Parse argc/argv argument vector.
    329598 *
    330  * [eventually this will replace the real getopt]
     599 * [eventually this will replace the BSD getopt]
    331600 */
    332601int
    333 _STD(getopt)(nargc, nargv, options)
    334         int nargc;
    335         char * const *nargv;
    336         const char *options;
     602_STD(getopt)(int nargc, char * const *nargv, const char *options)
    337603{
    338         int retval;
    339 
    340         _DIAGASSERT(nargv != NULL);
    341         _DIAGASSERT(options != NULL);
    342 
    343         if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
    344                 ++optind;
    345                 /*
    346                  * We found an option (--), so if we skipped non-options,
    347                  * we have to permute.
    348                  */
    349                 if (nonopt_end != -1) {
    350                         permute_args(nonopt_start, nonopt_end, optind,
    351                                        nargv);
    352                         optind -= nonopt_end - nonopt_start;
    353                 }
    354                 nonopt_start = nonopt_end = -1;
    355                 retval = -1;
    356         }
    357         return retval;
     604
     605        /*
     606         * We don't pass FLAG_PERMUTE to getopt_internal() since
     607         * the BSD getopt(3) (unlike GNU) has never done this.
     608         *
     609         * Furthermore, since many privileged programs call getopt()
     610         * before dropping privileges it makes sense to keep things
     611         * as simple (and bug-free) as possible.
     612         */
     613        return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
    358614}
    359 #endif
     615#endif /* REPLACE_GETOPT */
    360616
    361617/*
     
    364620 */
    365621int
    366 getopt_long(nargc, nargv, options, long_options, idx)
     622_STD(getopt_long)(nargc, nargv, options, long_options, idx)
    367623        int nargc;
    368624        char * const *nargv;
     
    371627        int *idx;
    372628{
    373         int retval;
    374 
    375         _DIAGASSERT(nargv != NULL);
    376         _DIAGASSERT(options != NULL);
    377         _DIAGASSERT(long_options != NULL);
    378         /* idx may be NULL */
    379 
    380         if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
    381                 char *current_argv, *has_equal;
    382                 size_t current_argv_len;
    383                 int i, match;
    384 
    385                 current_argv = place;
    386                 match = -1;
    387 
    388                 optind++;
    389                 place = EMSG;
    390 
    391                 if (*current_argv == '\0') {            /* found "--" */
    392                         /*
    393                          * We found an option (--), so if we skipped
    394                          * non-options, we have to permute.
    395                          */
    396                         if (nonopt_end != -1) {
    397                                 permute_args(nonopt_start, nonopt_end,
    398                                     optind, nargv);
    399                                 optind -= nonopt_end - nonopt_start;
    400                         }
    401                         nonopt_start = nonopt_end = -1;
    402                         return -1;
    403                 }
    404                 if ((has_equal = strchr(current_argv, '=')) != NULL) {
    405                         /* argument found (--option=arg) */
    406                         current_argv_len = has_equal - current_argv;
    407                         has_equal++;
    408                 } else
    409                         current_argv_len = strlen(current_argv);
    410        
    411                 for (i = 0; long_options[i].name; i++) {
    412                         /* find matching long option */
    413                         if (strncmp(current_argv, long_options[i].name,
    414                             current_argv_len))
    415                                 continue;
    416 
    417                         if (strlen(long_options[i].name) ==
    418                             (unsigned)current_argv_len) {
    419                                 /* exact match */
    420                                 match = i;
    421                                 break;
    422                         }
    423                         if (match == -1)                /* partial match */
    424                                 match = i;
    425                         else {
    426                                 /* ambiguous abbreviation */
    427                                 if (PRINT_ERROR)
    428                                         warnx(ambig, (int)current_argv_len,
    429                                              current_argv);
    430                                 optopt = 0;
    431                                 return BADCH;
    432                         }
    433                 }
    434                 if (match != -1) {                      /* option found */
    435                         if (long_options[match].has_arg == no_argument
    436                             && has_equal) {
    437                                 if (PRINT_ERROR)
    438                                         warnx(noarg, (int)current_argv_len,
    439                                              current_argv);
    440                                 /*
    441                                  * XXX: GNU sets optopt to val regardless of
    442                                  * flag
    443                                  */
    444                                 if (long_options[match].flag == NULL)
    445                                         optopt = long_options[match].val;
    446                                 else
    447                                         optopt = 0;
    448                                 return BADARG;
    449                         }
    450                         if (long_options[match].has_arg == required_argument ||
    451                             long_options[match].has_arg == optional_argument) {
    452                                 if (has_equal)
    453                                         optarg = has_equal;
    454                                 else if (long_options[match].has_arg ==
    455                                     required_argument) {
    456                                         /*
    457                                          * optional argument doesn't use
    458                                          * next nargv
    459                                          */
    460                                         optarg = nargv[optind++];
    461                                 }
    462                         }
    463                         if ((long_options[match].has_arg == required_argument)
    464                             && (optarg == NULL)) {
    465                                 /*
    466                                  * Missing argument; leading ':'
    467                                  * indicates no error should be generated
    468                                  */
    469                                 if (PRINT_ERROR)
    470                                         warnx(recargstring, current_argv);
    471                                 /*
    472                                  * XXX: GNU sets optopt to val regardless
    473                                  * of flag
    474                                  */
    475                                 if (long_options[match].flag == NULL)
    476                                         optopt = long_options[match].val;
    477                                 else
    478                                         optopt = 0;
    479                                 --optind;
    480                                 return BADARG;
    481                         }
    482                 } else {                        /* unknown option */
    483                         if (PRINT_ERROR)
    484                                 warnx(illoptstring, current_argv);
    485                         optopt = 0;
    486                         return BADCH;
    487                 }
    488                 if (long_options[match].flag) {
    489                         *long_options[match].flag = long_options[match].val;
    490                         retval = 0;
    491                 } else
    492                         retval = long_options[match].val;
    493                 if (idx)
    494                         *idx = match;
    495         }
    496         return retval;
     629
     630        return (getopt_internal(nargc, nargv, options, long_options, idx,
     631            FLAG_PERMUTE));
    497632}
    498 #endif /* !GETOPT_LONG */
     633
     634/*
     635 * getopt_long_only --
     636 *      Parse argc/argv argument vector.
     637 */
     638int
     639_STD(getopt_long_only)(nargc, nargv, options, long_options, idx)
     640        int nargc;
     641        char * const *nargv;
     642        const char *options;
     643        const struct option *long_options;
     644        int *idx;
     645{
     646
     647        return (getopt_internal(nargc, nargv, options, long_options, idx,
     648            FLAG_PERMUTE|FLAG_LONGONLY));
     649}
Note: See TracChangeset for help on using the changeset viewer.