OSDN Git Service

Switch to current upstream getopt_long.
authorElliott Hughes <enh@google.com>
Tue, 25 Jun 2013 21:48:10 +0000 (14:48 -0700)
committerElliott Hughes <enh@google.com>
Tue, 25 Jun 2013 21:56:17 +0000 (14:56 -0700)
Change-Id: I4c646dcb8be9e88dd54d069a03bbc5fbfd92de03

libc/Android.mk
libc/NOTICE
libc/include/getopt.h
libc/upstream-freebsd/freebsd-compat.h
libc/upstream-freebsd/lib/libc/stdlib/getopt_long.c [moved from libc/unistd/getopt_long.c with 79% similarity]

index 04741be..b239b74 100644 (file)
@@ -9,7 +9,6 @@ libc_common_src_files := \
        unistd/alarm.c \
        unistd/exec.c \
        unistd/fnmatch.c \
-       unistd/getopt_long.c \
        unistd/syslog.c \
        unistd/system.c \
        unistd/time.c \
@@ -279,6 +278,7 @@ libc_upstream_freebsd_src_files := \
     upstream-freebsd/lib/libc/stdio/tempnam.c \
     upstream-freebsd/lib/libc/stdio/tmpnam.c \
     upstream-freebsd/lib/libc/stdio/wsetup.c \
+    upstream-freebsd/lib/libc/stdlib/getopt_long.c \
     upstream-freebsd/lib/libc/stdlib/qsort.c \
     upstream-freebsd/lib/libc/stdlib/realpath.c \
     upstream-freebsd/lib/libc/string/wcpcpy.c \
index 2937518..f31d2f6 100644 (file)
@@ -3060,13 +3060,6 @@ are met:
 2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-       This product includes software developed by the NetBSD
-       Foundation, Inc. and its contributors.
-4. Neither the name of The NetBSD Foundation nor the names of its
-   contributors may be used to endorse or promote products derived
-   from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
index 56f1983..4451941 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: getopt.h,v 1.1 2002/12/03 20:24:29 millert Exp $      */
 /*     $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $    */
+/*     $FreeBSD$ */
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -43,7 +36,8 @@
 #include <sys/cdefs.h>
 
 /*
- * GNU-like getopt_long() and 4.4BSD getsubopt()/optreset extensions
+ * GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension.
+ * getopt() is declared here too for GNU programs.
  */
 #define no_argument        0
 #define required_argument  1
@@ -64,26 +58,20 @@ struct option {
 };
 
 __BEGIN_DECLS
-int     getopt_long(int, char * const *, const char *,
-           const struct option *, int *);
-int     getopt_long_only(int, char * const *, const char *,
-           const struct option *, int *);
-#ifndef _GETOPT_DEFINED_
-#define _GETOPT_DEFINED_
-int     getopt(int, char * const *, const char *);
-
-
-extern   char *optarg;                  /* getopt(3) external variables */
-extern   int opterr;
-extern   int optind;
-extern   int optopt;
-extern   int optreset;
-
-#if 0 /* MISSING FROM BIONIC */
-int       getsubopt(char **, char * const *, char **);
-extern   char *suboptarg;               /* getsubopt(3) external variable */
-#endif /* MISSING */
+int    getopt_long(int, char * const *, const char *,
+       const struct option *, int *);
+int    getopt_long_only(int, char * const *, const char *,
+       const struct option *, int *);
+#ifndef _GETOPT_DECLARED
+#define        _GETOPT_DECLARED
+int     getopt(int, char * const [], const char *);
 
+extern char *optarg;                   /* getopt(3) external variables */
+extern int optind, opterr, optopt;
+#endif
+#ifndef _OPTRESET_DECLARED
+#define        _OPTRESET_DECLARED
+extern int optreset;                   /* getopt(3) external variable */
 #endif
 __END_DECLS
  
index 5298663..8030eea 100644 (file)
@@ -18,6 +18,7 @@
 #define _BIONIC_FREEBSD_COMPAT_H_included
 
 #define __USE_BSD
+#define REPLACE_GETOPT
 
 #define _close close
 #define _fcntl fcntl
similarity index 79%
rename from libc/unistd/getopt_long.c
rename to libc/upstream-freebsd/lib/libc/stdlib/getopt_long.c
index dbdf01a..9f7f6d5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: getopt_long.c,v 1.20 2005/10/25 15:49:37 jmc Exp $    */
+/*     $OpenBSD: getopt_long.c,v 1.22 2006/10/04 21:29:04 jmc Exp $    */
 /*     $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $      */
 
 /*
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *        This product includes software developed by the NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 millert Exp $";
+#endif /* LIBC_SCCS and not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
 #include <err.h>
 #include <errno.h>
 #include <getopt.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdio.h>
 
+#define GNU_COMPATIBLE         /* Be more compatible, configure's use us! */
+
+#if 0                          /* we prefer to keep our getopt(3) */
 #define        REPLACE_GETOPT          /* use this getopt as the system getopt(3) */
+#endif
 
 #ifdef REPLACE_GETOPT
 int    opterr = 1;             /* if error message should be printed */
 int    optind = 1;             /* index into parent argv vector */
 int    optopt = '?';           /* character checked for validity */
+int    optreset;               /* reset getopt */
 char    *optarg;               /* argument associated with option */
 #endif
-int    optreset;               /* reset getopt */
 
 #define PRINT_ERROR    ((opterr) && (*options != ':'))
 
@@ -86,10 +90,17 @@ int optreset;               /* reset getopt */
 
 #define        EMSG            ""
 
+#ifdef GNU_COMPATIBLE
+#define NO_PREFIX      (-1)
+#define D_PREFIX       0
+#define DD_PREFIX      1
+#define W_PREFIX       2
+#endif
+
 static int getopt_internal(int, char * const *, const char *,
                           const struct option *, int *, int);
 static int parse_long_options(char * const *, const char *,
-                             const struct option *, int *, int);
+                             const struct option *, int *, int, int);
 static int gcd(int, int);
 static void permute_args(int, int, int, char * const *);
 
@@ -101,11 +112,21 @@ static int nonopt_end = -1;   /* first option after non options (for permute) */
 
 /* Error messages */
 static const char recargchar[] = "option requires an argument -- %c";
+static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */
+#ifdef GNU_COMPATIBLE
+static int dash_prefix = NO_PREFIX;
+static const char gnuoptchar[] = "invalid option -- %c";
+
+static const char recargstring[] = "option `%s%s' requires an argument";
+static const char ambig[] = "option `%s%.*s' is ambiguous";
+static const char noarg[] = "option `%s%.*s' doesn't allow an argument";
+static const char illoptstring[] = "unrecognized option `%s%s'";
+#else
 static const char recargstring[] = "option requires an argument -- %s";
 static const char ambig[] = "ambiguous option -- %.*s";
 static const char noarg[] = "option doesn't take an argument -- %.*s";
-static const char illoptchar[] = "unknown option -- %c";
 static const char illoptstring[] = "unknown option -- %s";
+#endif
 
 /*
  * Compute the greatest common divisor of a and b.
@@ -169,14 +190,35 @@ permute_args(int panonopt_start, int panonopt_end, int opt_end,
  */
 static int
 parse_long_options(char * const *nargv, const char *options,
-       const struct option *long_options, int *idx, int short_too)
+       const struct option *long_options, int *idx, int short_too, int flags)
 {
        char *current_argv, *has_equal;
+#ifdef GNU_COMPATIBLE
+       char *current_dash;
+#endif
        size_t current_argv_len;
-       int i, match;
+       int i, match, exact_match, second_partial_match;
 
        current_argv = place;
+#ifdef GNU_COMPATIBLE
+       switch (dash_prefix) {
+               case D_PREFIX:
+                       current_dash = "-";
+                       break;
+               case DD_PREFIX:
+                       current_dash = "--";
+                       break;
+               case W_PREFIX:
+                       current_dash = "-W ";
+                       break;
+               default:
+                       current_dash = "";
+                       break;
+       }
+#endif
        match = -1;
+       exact_match = 0;
+       second_partial_match = 0;
 
        optind++;
 
@@ -196,6 +238,7 @@ parse_long_options(char * const *nargv, const char *options,
                if (strlen(long_options[i].name) == current_argv_len) {
                        /* exact match */
                        match = i;
+                       exact_match = 1;
                        break;
                }
                /*
@@ -205,25 +248,37 @@ parse_long_options(char * const *nargv, const char *options,
                if (short_too && current_argv_len == 1)
                        continue;
 
-               if (match == -1)        /* partial match */
+               if (match == -1)        /* first partial match */
                        match = i;
-               else {
-                       /* ambiguous abbreviation */
-                       if (PRINT_ERROR)
-                               fprintf(stderr, 
-                        ambig, (int)current_argv_len,
-                        current_argv);
-                       optopt = 0;
-                       return (BADCH);
-               }
+               else if ((flags & FLAG_LONGONLY) ||
+                        long_options[i].has_arg !=
+                            long_options[match].has_arg ||
+                        long_options[i].flag != long_options[match].flag ||
+                        long_options[i].val != long_options[match].val)
+                       second_partial_match = 1;
+       }
+       if (!exact_match && second_partial_match) {
+               /* ambiguous abbreviation */
+               if (PRINT_ERROR)
+                       warnx(ambig,
+#ifdef GNU_COMPATIBLE
+                            current_dash,
+#endif
+                            (int)current_argv_len,
+                            current_argv);
+               optopt = 0;
+               return (BADCH);
        }
        if (match != -1) {              /* option found */
                if (long_options[match].has_arg == no_argument
                    && has_equal) {
                        if (PRINT_ERROR)
-                               fprintf(stderr,
-                        noarg, (int)current_argv_len,
-                        current_argv);
+                               warnx(noarg,
+#ifdef GNU_COMPATIBLE
+                                    current_dash,
+#endif
+                                    (int)current_argv_len,
+                                    current_argv);
                        /*
                         * XXX: GNU sets optopt to val regardless of flag
                         */
@@ -231,7 +286,11 @@ parse_long_options(char * const *nargv, const char *options,
                                optopt = long_options[match].val;
                        else
                                optopt = 0;
+#ifdef GNU_COMPATIBLE
+                       return (BADCH);
+#else
                        return (BADARG);
+#endif
                }
                if (long_options[match].has_arg == required_argument ||
                    long_options[match].has_arg == optional_argument) {
@@ -252,9 +311,11 @@ parse_long_options(char * const *nargv, const char *options,
                         * should be generated.
                         */
                        if (PRINT_ERROR)
-                               fprintf(stderr, 
-                        recargstring,
-                        current_argv);
+                               warnx(recargstring,
+#ifdef GNU_COMPATIBLE
+                                   current_dash,
+#endif
+                                   current_argv);
                        /*
                         * XXX: GNU sets optopt to val regardless of flag
                         */
@@ -271,7 +332,11 @@ parse_long_options(char * const *nargv, const char *options,
                        return (-1);
                }
                if (PRINT_ERROR)
-                       fprintf(stderr, illoptstring, current_argv);
+                       warnx(illoptstring,
+#ifdef GNU_COMPATIBLE
+                             current_dash,
+#endif
+                             current_argv);
                optopt = 0;
                return (BADCH);
        }
@@ -294,7 +359,7 @@ getopt_internal(int nargc, char * const *nargv, const char *options,
 {
        char *oli;                              /* option letter list index */
        int optchar, short_too;
-       static int posixly_correct = -1;
+       int posixly_correct;    /* no static, can be changed on the fly */
 
        if (options == NULL)
                return (-1);
@@ -303,12 +368,18 @@ getopt_internal(int nargc, char * const *nargv, const char *options,
         * Disable GNU extensions if POSIXLY_CORRECT is set or options
         * string begins with a '+'.
         */
-       if (posixly_correct == -1)
-               posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+       posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+#ifdef GNU_COMPATIBLE
+       if (*options == '-')
+               flags |= FLAG_ALLARGS;
+       else if (posixly_correct || *options == '+')
+               flags &= ~FLAG_PERMUTE;
+#else
        if (posixly_correct || *options == '+')
                flags &= ~FLAG_PERMUTE;
        else if (*options == '-')
                flags |= FLAG_ALLARGS;
+#endif
        if (*options == '+' || *options == '-')
                options++;
 
@@ -344,7 +415,11 @@ start:
                        return (-1);
                }
                if (*(place = nargv[optind]) != '-' ||
+#ifdef GNU_COMPATIBLE
+                   place[1] == '\0') {
+#else
                    (place[1] == '\0' && strchr(options, '-') == NULL)) {
+#endif
                        place = EMSG;           /* found non-option */
                        if (flags & FLAG_ALLARGS) {
                                /*
@@ -407,20 +482,26 @@ start:
        if (long_options != NULL && place != nargv[optind] &&
            (*place == '-' || (flags & FLAG_LONGONLY))) {
                short_too = 0;
-               if (*place == '-')
+#ifdef GNU_COMPATIBLE
+               dash_prefix = D_PREFIX;
+#endif
+               if (*place == '-') {
                        place++;                /* --foo long option */
-               else if (*place != ':' && strchr(options, *place) != NULL)
+#ifdef GNU_COMPATIBLE
+                       dash_prefix = DD_PREFIX;
+#endif
+               } else if (*place != ':' && strchr(options, *place) != NULL)
                        short_too = 1;          /* could be short option too */
 
                optchar = parse_long_options(nargv, options, long_options,
-                   idx, short_too);
+                   idx, short_too, flags);
                if (optchar != -1) {
                        place = EMSG;
                        return (optchar);
                }
        }
 
-       if (((optchar = (int)*place++) == (int)':') ||
+       if ((optchar = (int)*place++) == (int)':' ||
            (optchar == (int)'-' && *place != '\0') ||
            (oli = strchr(options, optchar)) == NULL) {
                /*
@@ -432,8 +513,14 @@ start:
                        return (-1);
                if (!*place)
                        ++optind;
+#ifdef GNU_COMPATIBLE
                if (PRINT_ERROR)
-                       fprintf(stderr, illoptchar, optchar);
+                       warnx(posixly_correct ? illoptchar : gnuoptchar,
+                             optchar);
+#else
+               if (PRINT_ERROR)
+                       warnx(illoptchar, optchar);
+#endif
                optopt = optchar;
                return (BADCH);
        }
@@ -444,13 +531,16 @@ start:
                else if (++optind >= nargc) {   /* no arg */
                        place = EMSG;
                        if (PRINT_ERROR)
-                               fprintf(stderr, recargchar, optchar);
+                               warnx(recargchar, optchar);
                        optopt = optchar;
                        return (BADARG);
                } else                          /* white space */
                        place = nargv[optind];
+#ifdef GNU_COMPATIBLE
+               dash_prefix = W_PREFIX;
+#endif
                optchar = parse_long_options(nargv, options, long_options,
-                   idx, 0);
+                   idx, 0, flags);
                place = EMSG;
                return (optchar);
        }
@@ -461,24 +551,15 @@ start:
                optarg = NULL;
                if (*place)                     /* no white space */
                        optarg = place;
-               /* XXX: disable test for :: if PC? (GNU doesn't) */
                else if (oli[1] != ':') {       /* arg not optional */
                        if (++optind >= nargc) {        /* no arg */
                                place = EMSG;
                                if (PRINT_ERROR)
-                                       fprintf(stderr, recargchar, optchar);
+                                       warnx(recargchar, optchar);
                                optopt = optchar;
                                return (BADARG);
                        } else
                                optarg = nargv[optind];
-               } else if (!(flags & FLAG_PERMUTE)) {
-                       /*
-                        * If permutation is disabled, we can accept an
-                        * optional arg separated by whitespace so long
-                        * as it does not start with a dash (-).
-                        */
-                       if (optind + 1 < nargc && *nargv[optind + 1] != '-')
-                               optarg = nargv[++optind];
                }
                place = EMSG;
                ++optind;
@@ -516,7 +597,7 @@ getopt(int nargc, char * const *nargv, const char *options)
  */
 int
 getopt_long(int nargc, char * const *nargv, const char *options,
-    const struct option *long_options, int *idx)
+       const struct option *long_options, int *idx)
 {
 
        return (getopt_internal(nargc, nargv, options, long_options, idx,
@@ -529,7 +610,7 @@ getopt_long(int nargc, char * const *nargv, const char *options,
  */
 int
 getopt_long_only(int nargc, char * const *nargv, const char *options,
-    const struct option *long_options, int *idx)
+       const struct option *long_options, int *idx)
 {
 
        return (getopt_internal(nargc, nargv, options, long_options, idx,