Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Johnston <jjohnstn@redhat.com>2006-01-05 00:21:52 +0300
committerJeff Johnston <jjohnstn@redhat.com>2006-01-05 00:21:52 +0300
commit791c9bda57bd3785f3e1c0bce8658eccee56652a (patch)
tree93681642c6da443c89861a831ea87966a41aaab0
parent4b2985b50b56469535f7732fdaa1662343be0a2f (diff)
2006-01-04 Gregory Pietsch <gpietsch@comcast.net>
* libc/stdlib/getopt.c: Replaced with version that adds getopt_long and getopt_long_only support. * libc/include/getopt.h: New file.
-rw-r--r--newlib/ChangeLog6
-rw-r--r--newlib/libc/include/getopt.h136
-rw-r--r--newlib/libc/stdlib/getopt.c503
3 files changed, 538 insertions, 107 deletions
diff --git a/newlib/ChangeLog b/newlib/ChangeLog
index 73ffd7102..c714a1631 100644
--- a/newlib/ChangeLog
+++ b/newlib/ChangeLog
@@ -1,3 +1,9 @@
+2006-01-04 Gregory Pietsch <gpietsch@comcast.net>
+
+ * libc/stdlib/getopt.c: Replaced with version
+ that adds getopt_long and getopt_long_only support.
+ * libc/include/getopt.h: New file.
+
2005-12-16 Jeff Johnston <jjohnstn@redhat.com>
* NEWS: Update with 1.14.0 info.
diff --git a/newlib/libc/include/getopt.h b/newlib/libc/include/getopt.h
new file mode 100644
index 000000000..7179298ae
--- /dev/null
+++ b/newlib/libc/include/getopt.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+
+getopt.h - Read command line options
+
+AUTHOR: Gregory Pietsch
+CREATED Thu Jan 09 22:37:00 1997
+
+DESCRIPTION:
+
+The getopt() function parses the command line arguments. Its arguments argc
+and argv are the argument count and array as passed to the main() function
+on program invocation. The argument optstring is a list of available option
+characters. If such a character is followed by a colon (`:'), the option
+takes an argument, which is placed in optarg. If such a character is
+followed by two colons, the option takes an optional argument, which is
+placed in optarg. If the option does not take an argument, optarg is NULL.
+
+The external variable optind is the index of the next array element of argv
+to be processed; it communicates from one call to the next which element to
+process.
+
+The getopt_long() function works like getopt() except that it also accepts
+long options started by two dashes `--'. If these take values, it is either
+in the form
+
+--arg=value
+
+ or
+
+--arg value
+
+It takes the additional arguments longopts which is a pointer to the first
+element of an array of type GETOPT_LONG_OPTION_T, defined below. The last
+element of the array has to be filled with NULL for the name field.
+
+The longind pointer points to the index of the current long option relative
+to longopts if it is non-NULL.
+
+The getopt() function returns the option character if the option was found
+successfully, `:' if there was a missing parameter for one of the options,
+`?' for an unknown option character, and EOF for the end of the option list.
+
+The getopt_long() function's return value is described below.
+
+The function getopt_long_only() is identical to getopt_long(), except that a
+plus sign `+' can introduce long options as well as `--'.
+
+Describe how to deal with options that follow non-option ARGV-elements.
+
+If the caller did not specify anything, the default is REQUIRE_ORDER if the
+environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+REQUIRE_ORDER means don't recognize them as options; stop option processing
+when the first non-option is seen. This is what Unix does. This mode of
+operation is selected by either setting the environment variable
+POSIXLY_CORRECT, or using `+' as the first character of the optstring
+parameter.
+
+PERMUTE is the default. We permute the contents of ARGV as we scan, so that
+eventually all the non-options are at the end. This allows options to be
+given in any order, even with programs that were not written to expect this.
+
+RETURN_IN_ORDER is an option available to programs that were written to
+expect options and other ARGV-elements in any order and that care about the
+ordering of the two. We describe each non-option ARGV-element as if it were
+the argument of an option with character code 1. Using `-' as the first
+character of the optstring parameter selects this mode of operation.
+
+The special argument `--' forces an end of option-scanning regardless of the
+value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause
+getopt() and friends to return EOF with optind != argc.
+
+COPYRIGHT NOTICE AND DISCLAIMER:
+
+Copyright (C) 1997 Gregory Pietsch
+
+This file and the accompanying getopt.c implementation file are hereby
+placed in the public domain without restrictions. Just give the author
+credit, don't claim you wrote it or prevent anyone else from using it.
+
+Gregory Pietsch's current e-mail address:
+gpietsch@comcast.net
+****************************************************************************/
+
+#ifndef GETOPT_H
+#define GETOPT_H
+
+#include <_ansi.h>
+
+/* include files needed by this include file */
+
+/* macros defined by this include file */
+#define NO_ARG 0
+#define REQUIRED_ARG 1
+#define OPTIONAL_ARG 2
+
+/* types defined by this include file */
+
+struct option
+{
+ char *name; /* the name of the long option */
+ int has_arg; /* one of the above macros */
+ int *flag; /* determines if getopt_long() returns a
+ * value for a long option; if it is
+ * non-NULL, 0 is returned as a function
+ * value and the value of val is stored in
+ * the area pointed to by flag. Otherwise,
+ * val is returned. */
+ int val; /* determines the value to return if flag is
+ * NULL. */
+};
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /* externally-defined variables */
+ extern char *optarg;
+ extern int optind;
+ extern int opterr;
+ extern int optopt;
+
+ /* function prototypes */
+ int _EXFUN (getopt, (int __argc, char *const __argv[], const char *__optstring));
+ int _EXFUN (getopt_long, (int __argc, char *const __argv[], const char *__shortopts, const struct option *__longopts, int *__longind));
+ int _EXFUN (getopt_long_only, (int __argc, char *const __argv[], const char *__shortopts, const struct option *__longopts, int *__longind));
+
+#ifdef __cplusplus
+};
+
+#endif
+
+#endif /* GETOPT_H */
+
+/* END OF FILE getopt.h */
diff --git a/newlib/libc/stdlib/getopt.c b/newlib/libc/stdlib/getopt.c
index b38938d5f..10002ed6b 100644
--- a/newlib/libc/stdlib/getopt.c
+++ b/newlib/libc/stdlib/getopt.c
@@ -1,117 +1,406 @@
-/*
- * Copyright (c) 1987, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 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 University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University 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 REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if defined(LIBC_SCCS) && !defined(lint)
-/* static char sccsid[] = "from: @(#)getopt.c 8.2 (Berkeley) 4/2/94"; */
-static char *rcsid = "$Id$";
-#endif /* LIBC_SCCS and not lint */
+/****************************************************************************
+getopt.c - Read command line options
+
+AUTHOR: Gregory Pietsch
+CREATED Fri Jan 10 21:13:05 1997
+
+DESCRIPTION:
+
+The getopt() function parses the command line arguments. Its arguments argc
+and argv are the argument count and array as passed to the main() function
+on program invocation. The argument optstring is a list of available option
+characters. If such a character is followed by a colon (`:'), the option
+takes an argument, which is placed in optarg. If such a character is
+followed by two colons, the option takes an optional argument, which is
+placed in optarg. If the option does not take an argument, optarg is NULL.
+
+The external variable optind is the index of the next array element of argv
+to be processed; it communicates from one call to the next which element to
+process.
+
+The getopt_long() function works like getopt() except that it also accepts
+long options started by two dashes `--'. If these take values, it is either
+in the form
+
+--arg=value
+
+ or
+
+--arg value
+
+It takes the additional arguments longopts which is a pointer to the first
+element of an array of type struct option. The last element of the array
+has to be filled with NULL for the name field.
+
+The longind pointer points to the index of the current long option relative
+to longopts if it is non-NULL.
+
+The getopt() function returns the option character if the option was found
+successfully, `:' if there was a missing parameter for one of the options,
+`?' for an unknown option character, and EOF for the end of the option list.
+
+The getopt_long() function's return value is described in the header file.
+
+The function getopt_long_only() is identical to getopt_long(), except that a
+plus sign `+' can introduce long options as well as `--'.
+
+The following describes how to deal with options that follow non-option
+argv-elements.
+
+If the caller did not specify anything, the default is REQUIRE_ORDER if the
+environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+REQUIRE_ORDER means don't recognize them as options; stop option processing
+when the first non-option is seen. This is what Unix does. This mode of
+operation is selected by either setting the environment variable
+POSIXLY_CORRECT, or using `+' as the first character of the optstring
+parameter.
+
+PERMUTE is the default. We permute the contents of ARGV as we scan, so that
+eventually all the non-options are at the end. This allows options to be
+given in any order, even with programs that were not written to expect this.
+
+RETURN_IN_ORDER is an option available to programs that were written to
+expect options and other argv-elements in any order and that care about the
+ordering of the two. We describe each non-option argv-element as if it were
+the argument of an option with character code 1. Using `-' as the first
+character of the optstring parameter selects this mode of operation.
+
+The special argument `--' forces an end of option-scanning regardless of the
+value of ordering. In the case of RETURN_IN_ORDER, only `--' can cause
+getopt() and friends to return EOF with optind != argc.
+
+COPYRIGHT NOTICE AND DISCLAIMER:
+
+Copyright (C) 1997 Gregory Pietsch
+
+This file and the accompanying getopt.h header file are hereby placed in the
+public domain without restrictions. Just give the author credit, don't
+claim you wrote it or prevent anyone else from using it.
+
+Gregory Pietsch's current e-mail address:
+gpietsch@comcast.net
+****************************************************************************/
+
+/* include files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <getopt.h>
-int opterr = 1, /* if error message should be printed */
- optind = 1, /* index into parent argv vector */
- optopt, /* character checked for validity */
- optreset; /* reset getopt */
-char *optarg; /* argument associated with option */
+/* macros */
-#define BADCH (int)'?'
-#define BADARG (int)':'
-#define EMSG ""
+/* types */
+typedef enum GETOPT_ORDERING_T
+{
+ PERMUTE,
+ RETURN_IN_ORDER,
+ REQUIRE_ORDER
+} GETOPT_ORDERING_T;
+
+/* globally-defined variables */
+char *optarg = NULL;
+int optind = 0;
+int opterr = 1;
+int optopt = '?';
+
+/* functions */
+
+/* reverse_argv_elements: reverses num elements starting at argv */
+static void
+reverse_argv_elements (char ** argv, int num)
+{
+ int i;
+ char *tmp;
+
+ for (i = 0; i < (num >> 1); i++)
+ {
+ tmp = argv[i];
+ argv[i] = argv[num - i - 1];
+ argv[num - i - 1] = tmp;
+ }
+}
+
+/* permute: swap two blocks of argv-elements given their lengths */
+static void
+permute (char *const argv[], int len1, int len2)
+{
+ reverse_argv_elements ((char **)argv, len1);
+ reverse_argv_elements ((char **)argv, len1 + len2);
+ reverse_argv_elements ((char **)argv, len2);
+}
+
+/* is_option: is this argv-element an option or the end of the option list? */
+static int
+is_option (char *argv_element, int only)
+{
+ return ((argv_element == NULL)
+ || (argv_element[0] == '-') || (only && argv_element[0] == '+'));
+}
+
+/* getopt_internal: the function that does all the dirty work */
+static int
+getopt_internal (int argc, char *const argv[], const char *shortopts,
+ const struct option *longopts, int *longind, int only)
+{
+ GETOPT_ORDERING_T ordering = PERMUTE;
+ static size_t optwhere = 0;
+ size_t permute_from = 0;
+ int num_nonopts = 0;
+ int optindex = 0;
+ size_t match_chars = 0;
+ char *possible_arg = NULL;
+ int longopt_match = -1;
+ int has_arg = -1;
+ char *cp;
+ int arg_next = 0;
+
+ /* first, deal with silly parameters and easy stuff */
+ if (argc == 0 || argv == NULL || (shortopts == NULL && longopts == NULL))
+ return EOF;
+ if (optind >= argc || argv[optind] == NULL)
+ return EOF;
+ if (strcmp (argv[optind], "--") == 0)
+ {
+ optind++;
+ return EOF;
+ }
+ /* if this is our first time through */
+ if (optind == 0)
+ optind = optwhere = 1;
+
+ /* define ordering */
+ if (shortopts != NULL && (*shortopts == '-' || *shortopts == '+'))
+ {
+ ordering = (*shortopts == '-') ? RETURN_IN_ORDER : REQUIRE_ORDER;
+ shortopts++;
+ }
+ else
+ ordering = (getenv ("POSIXLY_CORRECT") != NULL) ? REQUIRE_ORDER : PERMUTE;
+
+ /*
+ * based on ordering, find our next option, if we're at the beginning of
+ * one
+ */
+ if (optwhere == 1)
+ {
+ switch (ordering)
+ {
+ case PERMUTE:
+ permute_from = optind;
+ num_nonopts = 0;
+ while (!is_option (argv[optind], only))
+ {
+ optind++;
+ num_nonopts++;
+ }
+ if (argv[optind] == NULL)
+ {
+ /* no more options */
+ optind = permute_from;
+ return EOF;
+ }
+ else if (strcmp (argv[optind], "--") == 0)
+ {
+ /* no more options, but have to get `--' out of the way */
+ permute (argv + permute_from, num_nonopts, 1);
+ optind = permute_from + 1;
+ return EOF;
+ }
+ break;
+ case RETURN_IN_ORDER:
+ if (!is_option (argv[optind], only))
+ {
+ optarg = argv[optind++];
+ return (optopt = 1);
+ }
+ break;
+ case REQUIRE_ORDER:
+ if (!is_option (argv[optind], only))
+ return EOF;
+ break;
+ }
+ }
+ /* we've got an option, so parse it */
+
+ /* first, is it a long option? */
+ if (longopts != NULL
+ && (memcmp (argv[optind], "--", 2) == 0
+ || (only && argv[optind][0] == '+')) && optwhere == 1)
+ {
+ /* handle long options */
+ if (memcmp (argv[optind], "--", 2) == 0)
+ optwhere = 2;
+ longopt_match = -1;
+ possible_arg = strchr (argv[optind] + optwhere, '=');
+ if (possible_arg == NULL)
+ {
+ /* no =, so next argv might be arg */
+ match_chars = strlen (argv[optind]);
+ possible_arg = argv[optind] + match_chars;
+ match_chars = match_chars - optwhere;
+ }
+ else
+ match_chars = (possible_arg - argv[optind]) - optwhere;
+ for (optindex = 0; longopts[optindex].name != NULL; optindex++)
+ {
+ if (memcmp (argv[optind] + optwhere,
+ longopts[optindex].name, match_chars) == 0)
+ {
+ /* do we have an exact match? */
+ if (match_chars == (int) (strlen (longopts[optindex].name)))
+ {
+ longopt_match = optindex;
+ break;
+ }
+ /* do any characters match? */
+ else
+ {
+ if (longopt_match < 0)
+ longopt_match = optindex;
+ else
+ {
+ /* we have ambiguous options */
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' is ambiguous "
+ "(could be `--%s' or `--%s')\n",
+ argv[0],
+ argv[optind],
+ longopts[longopt_match].name,
+ longopts[optindex].name);
+ return (optopt = '?');
+ }
+ }
+ }
+ }
+ if (longopt_match >= 0)
+ has_arg = longopts[longopt_match].has_arg;
+ }
+ /* if we didn't find a long option, is it a short option? */
+ if (longopt_match < 0 && shortopts != NULL)
+ {
+ cp = strchr (shortopts, argv[optind][optwhere]);
+ if (cp == NULL)
+ {
+ /* couldn't find option in shortopts */
+ if (opterr)
+ fprintf (stderr,
+ "%s: invalid option -- `-%c'\n",
+ argv[0], argv[optind][optwhere]);
+ optwhere++;
+ if (argv[optind][optwhere] == '\0')
+ {
+ optind++;
+ optwhere = 1;
+ }
+ return (optopt = '?');
+ }
+ has_arg = ((cp[1] == ':')
+ ? ((cp[2] == ':') ? OPTIONAL_ARG : REQUIRED_ARG) : NO_ARG);
+ possible_arg = argv[optind] + optwhere + 1;
+ optopt = *cp;
+ }
+ /* get argument and reset optwhere */
+ arg_next = 0;
+ switch (has_arg)
+ {
+ case OPTIONAL_ARG:
+ if (*possible_arg == '=')
+ possible_arg++;
+ if (*possible_arg != '\0')
+ {
+ optarg = possible_arg;
+ optwhere = 1;
+ }
+ else
+ optarg = NULL;
+ break;
+ case REQUIRED_ARG:
+ if (*possible_arg == '=')
+ possible_arg++;
+ if (*possible_arg != '\0')
+ {
+ optarg = possible_arg;
+ optwhere = 1;
+ }
+ else if (optind + 1 >= argc)
+ {
+ if (opterr)
+ {
+ fprintf (stderr, "%s: argument required for option `", argv[0]);
+ if (longopt_match >= 0)
+ fprintf (stderr, "--%s'\n", longopts[longopt_match].name);
+ else
+ fprintf (stderr, "-%c'\n", *cp);
+ }
+ optind++;
+ return (optopt = ':');
+ }
+ else
+ {
+ optarg = argv[optind + 1];
+ arg_next = 1;
+ optwhere = 1;
+ }
+ break;
+ case NO_ARG:
+ if (longopt_match < 0)
+ {
+ optwhere++;
+ if (argv[optind][optwhere] == '\0')
+ optwhere = 1;
+ }
+ else
+ optwhere = 1;
+ optarg = NULL;
+ break;
+ }
+
+ /* do we have to permute or otherwise modify optind? */
+ if (ordering == PERMUTE && optwhere == 1 && num_nonopts != 0)
+ {
+ permute (argv + permute_from, num_nonopts, 1 + arg_next);
+ optind = permute_from + 1 + arg_next;
+ }
+ else if (optwhere == 1)
+ optind = optind + 1 + arg_next;
+
+ /* finally return */
+ if (longopt_match >= 0)
+ {
+ if (longind != NULL)
+ *longind = longopt_match;
+ if (longopts[longopt_match].flag != NULL)
+ {
+ *(longopts[longopt_match].flag) = longopts[longopt_match].val;
+ return 0;
+ }
+ else
+ return longopts[longopt_match].val;
+ }
+ else
+ return optopt;
+}
-/*
- * getopt --
- * Parse argc/argv argument vector.
- */
int
-getopt(nargc, nargv, ostr)
- int nargc;
- char * const *nargv;
- const char *ostr;
+getopt (int argc, char *const argv[], const char *optstring)
{
- static char *place = EMSG; /* option letter processing */
- char *oli; /* option letter list index */
-
- if (optreset || !*place) { /* update scanning pointer */
- optreset = 0;
- if (optind >= nargc || *(place = nargv[optind]) != '-') {
- place = EMSG;
- return (-1);
- }
- if (place[1] && *++place == '-') { /* found "--" */
- ++optind;
- place = EMSG;
- return (-1);
- }
- } /* option letter okay? */
- if ((optopt = (int)*place++) == (int)':' ||
- !(oli = strchr(ostr, optopt))) {
- /*
- * if the user didn't specify '-' as an option,
- * assume it means -1.
- */
- if (optopt == (int)'-')
- return (-1);
- if (!*place)
- ++optind;
- if (opterr && *ostr != ':')
- (void)fprintf(stderr,
- "%s: illegal option -- %c\n", nargv[0], optopt);
- return (BADCH);
- }
- if (*++oli != ':') { /* don't need argument */
- optarg = NULL;
- if (!*place)
- ++optind;
- }
- else { /* need an argument */
- if (*place) /* no white space */
- optarg = place;
- else if (nargc <= ++optind) { /* no arg */
- place = EMSG;
- if (*ostr == ':')
- return (BADARG);
- if (opterr)
- (void)fprintf(stderr,
- "%s: option requires an argument -- %c\n",
- nargv[0], optopt);
- return (BADCH);
- }
- else /* white space */
- optarg = nargv[optind];
- place = EMSG;
- ++optind;
- }
- return (optopt); /* dump back option letter */
+ return getopt_internal (argc, argv, optstring, NULL, NULL, 0);
}
+
+int
+getopt_long (int argc, char *const argv[], const char *shortopts,
+ const struct option *longopts, int *longind)
+{
+ return getopt_internal (argc, argv, shortopts, longopts, longind, 0);
+}
+
+int
+getopt_long_only (int argc, char *const argv[], const char *shortopts,
+ const struct option *longopts, int *longind)
+{
+ return getopt_internal (argc, argv, shortopts, longopts, longind, 1);
+}
+
+/* end of file GETOPT.C */