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
    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 <[email protected]>
     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
     60
     61
     62
     63
    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";
     122
     123
     124
     125
     126
     127
     128
     129
     130
     131
    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 ;
    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
     195
     196
     197
     198
     199
     200
     201
     202
     203
     204
     205
     206
     207
     208
     209
     210
     211
     212
     213
     214
     215
     216
     217
     218
     219
     220
     221
     222
     223
     224
     225
     226
     227
     228
     229
     230
     231
     232
     233
     234
     235
     236
     237
     238
     239
     240
     241
     242
     243
     244
     245
     246
     247
     248
     249
     250
     251
     252
     253
     254
     255
     256
     257
     258
     259
     260
     261
     262
     263
     264
     265
     266
     267
     268
     269
     270
     271
     272
     273
     274
     275
     276
     277
     278
     279
     280
     281
     282
     283
     284
     285
     286
     287
     288
     289
     290
     291
     292
     293
     294
     295
     296
     297
     298
     299
     300
     301
     302
     303
     304
     305
     306
     307
     308
     309
     310
     311
     312
     313
     314
     315
     316
     317
     318
     319
     320
     321
     322
     323
     324
     325
     326
     327
     328
     329
     330
     331
     332
     333
     334
     335
     336
     337
     338
     339
     340
     341
     342
     343
     344
     345
     346
     347
     348
     349
     350
     351
     352
     353
     354
     355
     356
     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 ;
    238438                        }
    239                         if (!PERMUTE) {
     439                        if (!) {
    240440                                /*
    241                                  * if no permutation wanted, stop parsing
    242                                  * at first non-option
     441                                 * f no permutation wanted, stop parsing
     442                                 * at first non-option
    243443                                 */
    244                                 return -1;
     444                                return ;
    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
     524
     525
     526
     527
    272528                if (PRINT_ERROR)
    273529                        warnx(illoptchar, optchar);
     530
    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 ;
    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 ;
    311569                        } else
    312570                                optarg = nargv[optind];
     571
     572
     573
     574
     575
     576
     577
     578
    313579                }
    314580                place = EMSG;
     
    316582        }
    317583        /* dump back option letter */
    318         return optchar;
     584        return ;
    319585}
    320586
     
    324590 *      Parse argc/argv argument vector.
    325591 *
    326  * [eventually this will replace the real getopt]
     592 * [eventually this will replace the 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
    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.