Changeset 1623 for trunk/src


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
    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
     64
     65
     66
     67
    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";
     130
     131
     132
     133
     134
     135
     136
     137
     138
     139
    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
     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
     360
     361
     362
     363
     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 ;
    242445                        }
    243                         if (!PERMUTE) {
     446                        if (!) {
    244447                                /*
    245                                  * if no permutation wanted, stop parsing
    246                                  * at first non-option
     448                                 * f no permutation wanted, stop parsing
     449                                 * at first non-option
    247450                                 */
    248                                 return -1;
     451                                return ;
    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
     531
     532
     533
     534
    276535                if (PRINT_ERROR)
    277536                        warnx(illoptchar, optchar);
     537
    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 ;
    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 ;
    315576                        } else
    316577                                optarg = nargv[optind];
     578
     579
     580
     581
     582
     583
     584
     585
    317586                }
    318587                place = EMSG;
     
    320589        }
    321590        /* dump back option letter */
    322         return optchar;
     591        return ;
    323592}
    324593
     
    328597 *      Parse argc/argv argument vector.
    329598 *
    330  * [eventually this will replace the real getopt]
     599 * [eventually this will replace the 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
    360616
    361617/*
     
    364620 */
    365621int
    366 getopt_long(nargc, nargv, options, long_options, idx)
     622(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.