summaryrefslogtreecommitdiff
path: root/getopt.c
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2010-07-16 12:49:45 +0300
committerArnold D. Robbins <arnold@skeeve.com>2010-07-16 12:49:45 +0300
commit6607eb3d5e40b98d2acc8f6b0d6a0b5a4b0f56bd (patch)
treec1eb39be8cc5c19101385e171ec0c58f95d521cc /getopt.c
parent6719bb6e1c5576e857ab6fc121ec31a75161a3e7 (diff)
downloadgawk-6607eb3d5e40b98d2acc8f6b0d6a0b5a4b0f56bd.tar.gz
Move to gawk-3.0.3.gawk-3.0.3
Diffstat (limited to 'getopt.c')
-rw-r--r--getopt.c217
1 files changed, 163 insertions, 54 deletions
diff --git a/getopt.c b/getopt.c
index cdd5a965..eac576b8 100644
--- a/getopt.c
+++ b/getopt.c
@@ -3,23 +3,26 @@
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!
- Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
+ This file is part of the GNU C Library. Its master source is NOT part of
+ the C library, however. The master source lives in /gd/gnu/lib.
- This program is distributed in the hope that it will be useful,
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-*/
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
Ditto for AIX 3.2 and <stdlib.h>. */
@@ -49,10 +52,16 @@
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
-/* Unfortunately, for gawk, this version is New And Improved, and must
- be used. This will be fixed for GNU LIBC 2
-#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
-*/
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
+
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
@@ -60,14 +69,31 @@
/* Don't include stdlib.h for non-GNU C libraries because some of them
contain conflicting prototypes for getopt. */
#include <stdlib.h>
+#include <unistd.h>
#endif /* GNU C library. */
+#ifdef VMS
+#include <unixlib.h>
+#if HAVE_STRING_H - 0
+#include <string.h>
+#endif
+#endif
+
+#if defined (WIN32) && !defined (__CYGWIN32__)
+/* It's not Unix, really. See? Capital letters. */
+#include <windows.h>
+#define getpid() GetCurrentProcessId()
+#endif
+
+#ifndef _
/* This is for other GNU distributions with internationalized messages.
- The GNU C Library itself does not yet support such messages. */
-#if HAVE_LIBINTL_H
+ When compiling libc, the _ macro is predefined. */
+#ifdef HAVE_LIBINTL_H
# include <libintl.h>
+# define _(msgid) gettext (msgid)
#else
-# define gettext(msgid) (msgid)
+# define _(msgid) (msgid)
+#endif
#endif
/* This version of `getopt' appears to the caller like standard Unix `getopt'
@@ -100,14 +126,20 @@ char *optarg = NULL;
On entry to `getopt', zero means this is the first call; initialize.
- When `getopt' returns EOF, this is the index of the first of the
+ When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
-/* XXX 1003.2 says this must be 1 before any call. */
-int optind = 0;
+/* 1003.2 says this must be 1 before any call. */
+int optind = 1;
+
+/* Formerly, initialization of getopt depended on optind==0, which
+ causes problems with re-calling getopt as programs generally don't
+ know that. */
+
+int __getopt_initialized = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
@@ -156,7 +188,7 @@ int optopt = '?';
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' to return EOF with `optind' != ARGC. */
+ `--' can cause `getopt' to return -1 with `optind' != ARGC. */
static enum
{
@@ -217,6 +249,31 @@ extern int strlen (const char *);
static int first_nonopt;
static int last_nonopt;
+#ifdef _LIBC
+/* Bash 2.0 gives us an environment variable containing flags
+ indicating ARGV elements that should not be considered arguments. */
+
+static const char *nonoption_flags;
+static int nonoption_flags_len;
+
+static int original_argc;
+static char *const *original_argv;
+
+/* Make sure the environment variable bash 2.0 puts in the environment
+ is valid for the getopt call we must make sure that the ARGV passed
+ to getopt is that one passed to the process. */
+static void store_args (int argc, char *const *argv) __attribute__ ((unused));
+static void
+store_args (int argc, char *const *argv)
+{
+ /* XXX This is no good solution. We should rather copy the args so
+ that we can compare them later. But we must not use malloc(3). */
+ original_argc = argc;
+ original_argv = argv;
+}
+text_set_element (__libc_subinit, store_args);
+#endif
+
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
@@ -226,6 +283,10 @@ static int last_nonopt;
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
+#if defined (__STDC__) && __STDC__
+static void exchange (char **);
+#endif
+
static void
exchange (argv)
char **argv;
@@ -284,8 +345,13 @@ exchange (argv)
/* Initialize the internal data when the first call is made. */
+#if defined (__STDC__) && __STDC__
+static const char *_getopt_initialize (int, char *const *, const char *);
+#endif
static const char *
-_getopt_initialize (optstring)
+_getopt_initialize (argc, argv, optstring)
+ int argc;
+ char *const *argv;
const char *optstring;
{
/* Start processing options with ARGV-element 1 (since ARGV-element 0
@@ -315,6 +381,26 @@ _getopt_initialize (optstring)
else
ordering = PERMUTE;
+#ifdef _LIBC
+ if (posixly_correct == NULL
+ && argc == original_argc && argv == original_argv)
+ {
+ /* Bash 2.0 puts a special variable in the environment for each
+ command it runs, specifying which ARGV elements are the results of
+ file name wildcard expansion and therefore should not be
+ considered as options. */
+ char var[100];
+ sprintf (var, "_%d_GNU_nonoption_argv_flags_", getpid ());
+ nonoption_flags = getenv (var);
+ if (nonoption_flags == NULL)
+ nonoption_flags_len = 0;
+ else
+ nonoption_flags_len = strlen (nonoption_flags);
+ }
+ else
+ nonoption_flags_len = 0;
+#endif
+
return optstring;
}
@@ -331,7 +417,7 @@ _getopt_initialize (optstring)
updating `optind' and `nextchar' so that the next call to `getopt' can
resume the scan with the following option character or ARGV-element.
- If there are no more option characters, `getopt' returns `EOF'.
+ If there are no more option characters, `getopt' returns -1.
Then `optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
@@ -385,16 +471,36 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
optarg = NULL;
- if (optind == 0)
+ if (!__getopt_initialized || optind == 0)
{
- optstring = _getopt_initialize (optstring);
+ optstring = _getopt_initialize (argc, argv, optstring);
optind = 1; /* Don't scan ARGV[0], the program name. */
+ __getopt_initialized = 1;
}
+ /* Test whether ARGV[optind] points to a non-option argument.
+ Either it does not have option syntax, or there is an environment flag
+ from the shell indicating it is not an option. The later information
+ is only used when the used in the GNU libc. */
+#ifdef _LIBC
+#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
+ || (optind < nonoption_flags_len \
+ && nonoption_flags[optind] == '1'))
+#else
+#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#endif
+
if (nextchar == NULL || *nextchar == '\0')
{
/* Advance to the next ARGV-element. */
+ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+ moved back by the user (who may also have changed the arguments). */
+ if (last_nonopt > optind)
+ last_nonopt = optind;
+ if (first_nonopt > optind)
+ first_nonopt = optind;
+
if (ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
@@ -408,8 +514,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
/* Skip any additional non-options
and extend the range of non-options previously skipped. */
- while (optind < argc
- && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ while (optind < argc && NONOPTION_P)
optind++;
last_nonopt = optind;
}
@@ -441,16 +546,16 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
- return EOF;
+ return -1;
}
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
- if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ if (NONOPTION_P)
{
if (ordering == REQUIRE_ORDER)
- return EOF;
+ return -1;
optarg = argv[optind++];
return 1;
}
@@ -486,7 +591,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
const struct option *pfound = NULL;
int exact = 0;
int ambig = 0;
- int indfound = 0;
+ int indfound = -1;
int option_index;
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
@@ -497,7 +602,8 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp (p->name, nextchar, nameend - nextchar))
{
- if (nameend - nextchar == strlen (p->name))
+ if ((unsigned int) (nameend - nextchar)
+ == (unsigned int) strlen (p->name))
{
/* Exact match found. */
pfound = p;
@@ -519,10 +625,11 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (ambig && !exact)
{
if (opterr)
- fprintf (stderr, gettext ("%s: option `%s' is ambiguous\n"),
+ fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
+ optopt = 0;
return '?';
}
@@ -542,15 +649,17 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (argv[optind - 1][1] == '-')
/* --option */
fprintf (stderr,
- gettext ("%s: option `--%s' doesn't allow an argument\n"),
+ _("%s: option `--%s' doesn't allow an argument\n"),
argv[0], pfound->name);
else
/* +option or -option */
fprintf (stderr,
- gettext ("%s: option `%c%s' doesn't allow an argument\n"),
+ _("%s: option `%c%s' doesn't allow an argument\n"),
argv[0], argv[optind - 1][0], pfound->name);
nextchar += strlen (nextchar);
+
+ optopt = pfound->val;
return '?';
}
}
@@ -562,9 +671,10 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
if (opterr)
fprintf (stderr,
- gettext ("%s: option `%s' requires an argument\n"),
+ _("%s: option `%s' requires an argument\n"),
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
+ optopt = pfound->val;
return optstring[0] == ':' ? ':' : '?';
}
}
@@ -590,15 +700,16 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
if (argv[optind][1] == '-')
/* --option */
- fprintf (stderr, gettext ("%s: unrecognized option `--%s'\n"),
+ fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
argv[0], nextchar);
else
/* +option or -option */
- fprintf (stderr, gettext ("%s: unrecognized option `%c%s'\n"),
+ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
argv[0], argv[optind][0], nextchar);
}
nextchar = (char *) "";
optind++;
+ optopt = 0;
return '?';
}
}
@@ -619,10 +730,10 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
if (posixly_correct)
/* 1003.2 specifies the format of this message. */
- fprintf (stderr, gettext ("%s: illegal option -- %c\n"),
+ fprintf (stderr, _("%s: illegal option -- %c\n"),
argv[0], c);
else
- fprintf (stderr, gettext ("%s: invalid option -- %c\n"),
+ fprintf (stderr, _("%s: invalid option -- %c\n"),
argv[0], c);
}
optopt = c;
@@ -652,8 +763,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (opterr)
{
/* 1003.2 specifies the format of this message. */
- fprintf (stderr,
- gettext ("%s: option requires an argument -- %c\n"),
+ fprintf (stderr, _("%s: option requires an argument -- %c\n"),
argv[0], c);
}
optopt = c;
@@ -679,7 +789,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp (p->name, nextchar, nameend - nextchar))
{
- if (nameend - nextchar == strlen (p->name))
+ if ((unsigned int) (nameend - nextchar) == strlen (p->name))
{
/* Exact match found. */
pfound = p;
@@ -700,7 +810,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
if (ambig && !exact)
{
if (opterr)
- fprintf (stderr, gettext ("%s: option `-W %s' is ambiguous\n"),
+ fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
@@ -718,9 +828,9 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
else
{
if (opterr)
- fprintf (stderr,
- gettext ("%s: option `-W %s' doesn't allow an argument\n"),
- argv[0], pfound->name);
+ fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
nextchar += strlen (nextchar);
return '?';
@@ -734,7 +844,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
if (opterr)
fprintf (stderr,
- gettext ("%s: option `%s' requires an argument\n"),
+ _("%s: option `%s' requires an argument\n"),
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
return optstring[0] == ':' ? ':' : '?';
@@ -783,7 +893,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
/* 1003.2 specifies the format of this message. */
fprintf (stderr,
- gettext ("%s: option requires an argument -- %c\n"),
+ _("%s: option requires an argument -- %c\n"),
argv[0], c);
}
optopt = c;
@@ -815,8 +925,7 @@ getopt (argc, argv, optstring)
0);
}
-/* no close on purpose (gawk)
-#endif /* _LIBC or not __GNU_LIBRARY__. */
+#endif /* Not ELIDE_CODE. */
#ifdef TEST
@@ -836,7 +945,7 @@ main (argc, argv)
int this_option_optind = optind ? optind : 1;
c = getopt (argc, argv, "abc:d:0123456789");
- if (c == EOF)
+ if (c == -1)
break;
switch (c)