5 changed files with 644 additions and 1058 deletions
-
749src/misc/getopt.c
-
129src/misc/getopt.h
-
180src/misc/getopt1.c
-
86src/misc/getopt_bsd.h
-
558src/misc/getopt_long_bsd.c
@ -1,749 +0,0 @@ |
|||||
/* Getopt for GNU. |
|
||||
NOTE: getopt is now part of the C library, so if you don't know what |
|
||||
"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 |
|
||||
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 program 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. |
|
||||
|
|
||||
You should have received a copy of the GNU General Public License |
|
||||
along with this program; if not, write to the Free Software |
|
||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
||||
|
|
||||
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. |
|
||||
Ditto for AIX 3.2 and <stdlib.h>. */ |
|
||||
#ifndef _NO_PROTO |
|
||||
#define _NO_PROTO |
|
||||
#endif |
|
||||
|
|
||||
#ifdef HAVE_CONFIG_H |
|
||||
#include <config.h> |
|
||||
#endif |
|
||||
|
|
||||
#ifndef __STDC__ |
|
||||
/* This is a separate conditional since some stdc systems |
|
||||
reject `defined (const)'. */ |
|
||||
#ifndef const |
|
||||
#define const |
|
||||
#endif |
|
||||
#endif |
|
||||
|
|
||||
#include <stdio.h> |
|
||||
#include <string.h> |
|
||||
|
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not |
|
||||
actually compiling the library itself. This code is part of the GNU C |
|
||||
Library, but also included in many other GNU distributions. Compiling |
|
||||
and linking in this code is a waste when using the GNU C library |
|
||||
(especially if it is a shared library). Rather than having every GNU |
|
||||
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. */ |
|
||||
|
|
||||
#if defined (_LIBC) || !defined (__GNU_LIBRARY__) |
|
||||
|
|
||||
|
|
||||
/* This needs to come after some library #include |
|
||||
to get __GNU_LIBRARY__ defined. */ |
|
||||
#ifdef __GNU_LIBRARY__ |
|
||||
/* Don't include stdlib.h for non-GNU C libraries because some of them |
|
||||
contain conflicting prototypes for getopt. */ |
|
||||
#include <stdlib.h> |
|
||||
#endif /* GNU C library. */ |
|
||||
|
|
||||
/* This version of `getopt' appears to the caller like standard Unix `getopt' |
|
||||
but it behaves differently for the user, since it allows the user |
|
||||
to intersperse the options with the other arguments. |
|
||||
|
|
||||
As `getopt' works, it permutes the elements of ARGV so that, |
|
||||
when it is done, all the options precede everything else. Thus |
|
||||
all application programs are extended to handle flexible argument order. |
|
||||
|
|
||||
Setting the environment variable POSIXLY_CORRECT disables permutation. |
|
||||
Then the behavior is completely standard. |
|
||||
|
|
||||
GNU application programs can use a third alternative mode in which |
|
||||
they can distinguish the relative order of options and other arguments. */ |
|
||||
|
|
||||
#include "getopt.h" |
|
||||
|
|
||||
/* For communication from `getopt' to the caller. |
|
||||
When `getopt' finds an option that takes an argument, |
|
||||
the argument value is returned here. |
|
||||
Also, when `ordering' is RETURN_IN_ORDER, |
|
||||
each non-option ARGV-element is returned here. */ |
|
||||
|
|
||||
char *optarg = NULL; |
|
||||
|
|
||||
/* Index in ARGV of the next element to be scanned. |
|
||||
This is used for communication to and from the caller |
|
||||
and for communication between successive calls to `getopt'. |
|
||||
|
|
||||
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 |
|
||||
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; |
|
||||
|
|
||||
/* The next char to be scanned in the option-element |
|
||||
in which the last option character we returned was found. |
|
||||
This allows us to pick up the scan where we left off. |
|
||||
|
|
||||
If this is zero, or a null string, it means resume the scan |
|
||||
by advancing to the next ARGV-element. */ |
|
||||
|
|
||||
static char *nextchar; |
|
||||
|
|
||||
/* Callers store zero here to inhibit the error message |
|
||||
for unrecognized options. */ |
|
||||
|
|
||||
int opterr = 1; |
|
||||
|
|
||||
/* Set to an option character which was unrecognized. |
|
||||
This must be initialized on some systems to avoid linking in the |
|
||||
system's own getopt implementation. */ |
|
||||
|
|
||||
int optopt = '?'; |
|
||||
|
|
||||
/* 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 list of option characters. |
|
||||
|
|
||||
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 list of option characters |
|
||||
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' to return EOF with `optind' != ARGC. */ |
|
||||
|
|
||||
static enum |
|
||||
{ |
|
||||
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER |
|
||||
} ordering; |
|
||||
|
|
||||
/* Value of POSIXLY_CORRECT environment variable. */ |
|
||||
static char *posixly_correct; |
|
||||
|
|
||||
#ifdef __GNU_LIBRARY__ |
|
||||
/* We want to avoid inclusion of string.h with non-GNU libraries |
|
||||
because there are many ways it can cause trouble. |
|
||||
On some systems, it contains special magic macros that don't work |
|
||||
in GCC. */ |
|
||||
#include <string.h> |
|
||||
#define my_index strchr |
|
||||
#else |
|
||||
|
|
||||
/* Avoid depending on library functions or files |
|
||||
whose names are inconsistent. */ |
|
||||
|
|
||||
char *getenv (); |
|
||||
|
|
||||
static char * |
|
||||
my_index (str, chr) |
|
||||
const char *str; |
|
||||
int chr; |
|
||||
{ |
|
||||
while (*str) |
|
||||
{ |
|
||||
if (*str == chr) |
|
||||
return (char *) str; |
|
||||
str++; |
|
||||
} |
|
||||
return 0; |
|
||||
} |
|
||||
|
|
||||
/* If using GCC, we can safely declare strlen this way. |
|
||||
If not using GCC, it is ok not to declare it. */ |
|
||||
#ifdef __GNUC__ |
|
||||
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. |
|
||||
That was relevant to code that was here before. */ |
|
||||
#ifndef __STDC__ |
|
||||
/* gcc with -traditional declares the built-in strlen to return int, |
|
||||
and has done so at least since version 2.4.5. -- rms. */ |
|
||||
extern int strlen (const char *); |
|
||||
#endif /* not __STDC__ */ |
|
||||
#endif /* __GNUC__ */ |
|
||||
|
|
||||
#endif /* not __GNU_LIBRARY__ */ |
|
||||
|
|
||||
/* Handle permutation of arguments. */ |
|
||||
|
|
||||
/* Describe the part of ARGV that contains non-options that have |
|
||||
been skipped. `first_nonopt' is the index in ARGV of the first of them; |
|
||||
`last_nonopt' is the index after the last of them. */ |
|
||||
|
|
||||
static int first_nonopt; |
|
||||
static int last_nonopt; |
|
||||
|
|
||||
/* 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. |
|
||||
The other is elements [last_nonopt,optind), which contains all |
|
||||
the options processed since those non-options were skipped. |
|
||||
|
|
||||
`first_nonopt' and `last_nonopt' are relocated so that they describe |
|
||||
the new indices of the non-options in ARGV after they are moved. */ |
|
||||
|
|
||||
static void |
|
||||
exchange (argv) |
|
||||
char **argv; |
|
||||
{ |
|
||||
int bottom = first_nonopt; |
|
||||
int middle = last_nonopt; |
|
||||
int top = optind; |
|
||||
char *tem; |
|
||||
|
|
||||
/* Exchange the shorter segment with the far end of the longer segment. |
|
||||
That puts the shorter segment into the right place. |
|
||||
It leaves the longer segment in the right place overall, |
|
||||
but it consists of two parts that need to be swapped next. */ |
|
||||
|
|
||||
while (top > middle && middle > bottom) |
|
||||
{ |
|
||||
if (top - middle > middle - bottom) |
|
||||
{ |
|
||||
/* Bottom segment is the short one. */ |
|
||||
int len = middle - bottom; |
|
||||
register int i; |
|
||||
|
|
||||
/* Swap it with the top part of the top segment. */ |
|
||||
for (i = 0; i < len; i++) |
|
||||
{ |
|
||||
tem = argv[bottom + i]; |
|
||||
argv[bottom + i] = argv[top - (middle - bottom) + i]; |
|
||||
argv[top - (middle - bottom) + i] = tem; |
|
||||
} |
|
||||
/* Exclude the moved bottom segment from further swapping. */ |
|
||||
top -= len; |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
/* Top segment is the short one. */ |
|
||||
int len = top - middle; |
|
||||
register int i; |
|
||||
|
|
||||
/* Swap it with the bottom part of the bottom segment. */ |
|
||||
for (i = 0; i < len; i++) |
|
||||
{ |
|
||||
tem = argv[bottom + i]; |
|
||||
argv[bottom + i] = argv[middle + i]; |
|
||||
argv[middle + i] = tem; |
|
||||
} |
|
||||
/* Exclude the moved top segment from further swapping. */ |
|
||||
bottom += len; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/* Update records for the slots the non-options now occupy. */ |
|
||||
|
|
||||
first_nonopt += (optind - last_nonopt); |
|
||||
last_nonopt = optind; |
|
||||
} |
|
||||
|
|
||||
/* Initialize the internal data when the first call is made. */ |
|
||||
|
|
||||
static const char * |
|
||||
_getopt_initialize (optstring) |
|
||||
const char *optstring; |
|
||||
{ |
|
||||
/* Start processing options with ARGV-element 1 (since ARGV-element 0 |
|
||||
is the program name); the sequence of previously skipped |
|
||||
non-option ARGV-elements is empty. */ |
|
||||
|
|
||||
first_nonopt = last_nonopt = optind = 1; |
|
||||
|
|
||||
nextchar = NULL; |
|
||||
|
|
||||
posixly_correct = getenv ("POSIXLY_CORRECT"); |
|
||||
|
|
||||
/* Determine how to handle the ordering of options and nonoptions. */ |
|
||||
|
|
||||
if (optstring[0] == '-') |
|
||||
{ |
|
||||
ordering = RETURN_IN_ORDER; |
|
||||
++optstring; |
|
||||
} |
|
||||
else if (optstring[0] == '+') |
|
||||
{ |
|
||||
ordering = REQUIRE_ORDER; |
|
||||
++optstring; |
|
||||
} |
|
||||
else if (posixly_correct != NULL) |
|
||||
ordering = REQUIRE_ORDER; |
|
||||
else |
|
||||
ordering = PERMUTE; |
|
||||
|
|
||||
return optstring; |
|
||||
} |
|
||||
|
|
||||
/* Scan elements of ARGV (whose length is ARGC) for option characters |
|
||||
given in OPTSTRING. |
|
||||
|
|
||||
If an element of ARGV starts with '-', and is not exactly "-" or "--", |
|
||||
then it is an option element. The characters of this element |
|
||||
(aside from the initial '-') are option characters. If `getopt' |
|
||||
is called repeatedly, it returns successively each of the option characters |
|
||||
from each of the option elements. |
|
||||
|
|
||||
If `getopt' finds another option character, it returns that character, |
|
||||
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'. |
|
||||
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.) |
|
||||
|
|
||||
OPTSTRING is a string containing the legitimate option characters. |
|
||||
If an option character is seen that is not listed in OPTSTRING, |
|
||||
return '?' after printing an error message. If you set `opterr' to |
|
||||
zero, the error message is suppressed but we still return '?'. |
|
||||
|
|
||||
If a char in OPTSTRING is followed by a colon, that means it wants an arg, |
|
||||
so the following text in the same ARGV-element, or the text of the following |
|
||||
ARGV-element, is returned in `optarg'. Two colons mean an option that |
|
||||
wants an optional arg; if there is text in the current ARGV-element, |
|
||||
it is returned in `optarg', otherwise `optarg' is set to zero. |
|
||||
|
|
||||
If OPTSTRING starts with `-' or `+', it requests different methods of |
|
||||
handling the non-option ARGV-elements. |
|
||||
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. |
|
||||
|
|
||||
Long-named options begin with `--' instead of `-'. |
|
||||
Their names may be abbreviated as long as the abbreviation is unique |
|
||||
or is an exact match for some defined option. If they have an |
|
||||
argument, it follows the option name in the same ARGV-element, separated |
|
||||
from the option name by a `=', or else the in next ARGV-element. |
|
||||
When `getopt' finds a long-named option, it returns 0 if that option's |
|
||||
`flag' field is nonzero, the value of the option's `val' field |
|
||||
if the `flag' field is zero. |
|
||||
|
|
||||
The elements of ARGV aren't really const, because we permute them. |
|
||||
But we pretend they're const in the prototype to be compatible |
|
||||
with other systems. |
|
||||
|
|
||||
LONGOPTS is a vector of `struct option' terminated by an |
|
||||
element containing a name which is zero. |
|
||||
|
|
||||
LONGIND returns the index in LONGOPT of the long-named option found. |
|
||||
It is only valid when a long-named option has been found by the most |
|
||||
recent call. |
|
||||
|
|
||||
If LONG_ONLY is nonzero, '-' as well as '--' can introduce |
|
||||
long-named options. */ |
|
||||
|
|
||||
int |
|
||||
_getopt_internal (argc, argv, optstring, longopts, longind, long_only) |
|
||||
int argc; |
|
||||
char *const *argv; |
|
||||
const char *optstring; |
|
||||
const struct option *longopts; |
|
||||
int *longind; |
|
||||
int long_only; |
|
||||
{ |
|
||||
optarg = NULL; |
|
||||
|
|
||||
if (optind == 0) |
|
||||
optstring = _getopt_initialize (optstring); |
|
||||
|
|
||||
if (nextchar == NULL || *nextchar == '\0') |
|
||||
{ |
|
||||
/* Advance to the next ARGV-element. */ |
|
||||
|
|
||||
if (ordering == PERMUTE) |
|
||||
{ |
|
||||
/* If we have just processed some options following some non-options, |
|
||||
exchange them so that the options come first. */ |
|
||||
|
|
||||
if (first_nonopt != last_nonopt && last_nonopt != optind) |
|
||||
exchange ((char **) argv); |
|
||||
else if (last_nonopt != optind) |
|
||||
first_nonopt = optind; |
|
||||
|
|
||||
/* Skip any additional non-options |
|
||||
and extend the range of non-options previously skipped. */ |
|
||||
|
|
||||
while (optind < argc |
|
||||
&& (argv[optind][0] != '-' || argv[optind][1] == '\0')) |
|
||||
optind++; |
|
||||
last_nonopt = optind; |
|
||||
} |
|
||||
|
|
||||
/* The special ARGV-element `--' means premature end of options. |
|
||||
Skip it like a null option, |
|
||||
then exchange with previous non-options as if it were an option, |
|
||||
then skip everything else like a non-option. */ |
|
||||
|
|
||||
if (optind != argc && !strcmp (argv[optind], "--")) |
|
||||
{ |
|
||||
optind++; |
|
||||
|
|
||||
if (first_nonopt != last_nonopt && last_nonopt != optind) |
|
||||
exchange ((char **) argv); |
|
||||
else if (first_nonopt == last_nonopt) |
|
||||
first_nonopt = optind; |
|
||||
last_nonopt = argc; |
|
||||
|
|
||||
optind = argc; |
|
||||
} |
|
||||
|
|
||||
/* If we have done all the ARGV-elements, stop the scan |
|
||||
and back over any non-options that we skipped and permuted. */ |
|
||||
|
|
||||
if (optind == argc) |
|
||||
{ |
|
||||
/* Set the next-arg-index to point at the non-options |
|
||||
that we previously skipped, so the caller will digest them. */ |
|
||||
if (first_nonopt != last_nonopt) |
|
||||
optind = first_nonopt; |
|
||||
return EOF; |
|
||||
} |
|
||||
|
|
||||
/* 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 (ordering == REQUIRE_ORDER) |
|
||||
return EOF; |
|
||||
optarg = argv[optind++]; |
|
||||
return 1; |
|
||||
} |
|
||||
|
|
||||
/* We have found another option-ARGV-element. |
|
||||
Skip the initial punctuation. */ |
|
||||
|
|
||||
nextchar = (argv[optind] + 1 |
|
||||
+ (longopts != NULL && argv[optind][1] == '-')); |
|
||||
} |
|
||||
|
|
||||
/* Decode the current option-ARGV-element. */ |
|
||||
|
|
||||
/* Check whether the ARGV-element is a long option. |
|
||||
|
|
||||
If long_only and the ARGV-element has the form "-f", where f is |
|
||||
a valid short option, don't consider it an abbreviated form of |
|
||||
a long option that starts with f. Otherwise there would be no |
|
||||
way to give the -f short option. |
|
||||
|
|
||||
On the other hand, if there's a long option "fubar" and |
|
||||
the ARGV-element is "-fu", do consider that an abbreviation of |
|
||||
the long option, just like "--fu", and not "-f" with arg "u". |
|
||||
|
|
||||
This distinction seems to be the most useful approach. */ |
|
||||
|
|
||||
if (longopts != NULL |
|
||||
&& (argv[optind][1] == '-' |
|
||||
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) |
|
||||
{ |
|
||||
char *nameend; |
|
||||
const struct option *p; |
|
||||
const struct option *pfound = NULL; |
|
||||
int exact = 0; |
|
||||
int ambig = 0; |
|
||||
int indfound; |
|
||||
int option_index; |
|
||||
|
|
||||
for (nameend = nextchar; *nameend && *nameend != '='; nameend++) |
|
||||
/* Do nothing. */ ; |
|
||||
|
|
||||
/* Test all long options for either exact match |
|
||||
or abbreviated matches. */ |
|
||||
for (p = longopts, option_index = 0; p->name; p++, option_index++) |
|
||||
if (!strncmp (p->name, nextchar, nameend - nextchar)) |
|
||||
{ |
|
||||
if (nameend - nextchar == strlen (p->name)) |
|
||||
{ |
|
||||
/* Exact match found. */ |
|
||||
pfound = p; |
|
||||
indfound = option_index; |
|
||||
exact = 1; |
|
||||
break; |
|
||||
} |
|
||||
else if (pfound == NULL) |
|
||||
{ |
|
||||
/* First nonexact match found. */ |
|
||||
pfound = p; |
|
||||
indfound = option_index; |
|
||||
} |
|
||||
else |
|
||||
/* Second or later nonexact match found. */ |
|
||||
ambig = 1; |
|
||||
} |
|
||||
|
|
||||
if (ambig && !exact) |
|
||||
{ |
|
||||
if (opterr) |
|
||||
fprintf (stderr, "%s: option `%s' is ambiguous\n", |
|
||||
argv[0], argv[optind]); |
|
||||
nextchar += strlen (nextchar); |
|
||||
optind++; |
|
||||
return '?'; |
|
||||
} |
|
||||
|
|
||||
if (pfound != NULL) |
|
||||
{ |
|
||||
option_index = indfound; |
|
||||
optind++; |
|
||||
if (*nameend) |
|
||||
{ |
|
||||
/* Don't test has_arg with >, because some C compilers don't |
|
||||
allow it to be used on enums. */ |
|
||||
if (pfound->has_arg) |
|
||||
optarg = nameend + 1; |
|
||||
else |
|
||||
{ |
|
||||
if (opterr) |
|
||||
{ |
|
||||
if (argv[optind - 1][1] == '-') |
|
||||
/* --option */ |
|
||||
fprintf (stderr, |
|
||||
"%s: option `--%s' doesn't allow an argument\n", |
|
||||
argv[0], pfound->name); |
|
||||
else |
|
||||
/* +option or -option */ |
|
||||
fprintf (stderr, |
|
||||
"%s: option `%c%s' doesn't allow an argument\n", |
|
||||
argv[0], argv[optind - 1][0], pfound->name); |
|
||||
} |
|
||||
nextchar += strlen (nextchar); |
|
||||
return '?'; |
|
||||
} |
|
||||
} |
|
||||
else if (pfound->has_arg == 1) |
|
||||
{ |
|
||||
if (optind < argc) |
|
||||
optarg = argv[optind++]; |
|
||||
else |
|
||||
{ |
|
||||
if (opterr) |
|
||||
fprintf (stderr, "%s: option `%s' requires an argument\n", |
|
||||
argv[0], argv[optind - 1]); |
|
||||
nextchar += strlen (nextchar); |
|
||||
return optstring[0] == ':' ? ':' : '?'; |
|
||||
} |
|
||||
} |
|
||||
nextchar += strlen (nextchar); |
|
||||
if (longind != NULL) |
|
||||
*longind = option_index; |
|
||||
if (pfound->flag) |
|
||||
{ |
|
||||
*(pfound->flag) = pfound->val; |
|
||||
return 0; |
|
||||
} |
|
||||
return pfound->val; |
|
||||
} |
|
||||
|
|
||||
/* Can't find it as a long option. If this is not getopt_long_only, |
|
||||
or the option starts with '--' or is not a valid short |
|
||||
option, then it's an error. |
|
||||
Otherwise interpret it as a short option. */ |
|
||||
if (!long_only || argv[optind][1] == '-' |
|
||||
|| my_index (optstring, *nextchar) == NULL) |
|
||||
{ |
|
||||
if (opterr) |
|
||||
{ |
|
||||
if (argv[optind][1] == '-') |
|
||||
/* --option */ |
|
||||
fprintf (stderr, "%s: unrecognized option `--%s'\n", |
|
||||
argv[0], nextchar); |
|
||||
else |
|
||||
/* +option or -option */ |
|
||||
fprintf (stderr, "%s: unrecognized option `%c%s'\n", |
|
||||
argv[0], argv[optind][0], nextchar); |
|
||||
} |
|
||||
nextchar = (char *) ""; |
|
||||
optind++; |
|
||||
return '?'; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/* Look at and handle the next short option-character. */ |
|
||||
|
|
||||
{ |
|
||||
char c = *nextchar++; |
|
||||
char *temp = my_index (optstring, c); |
|
||||
|
|
||||
/* Increment `optind' when we start to process its last character. */ |
|
||||
if (*nextchar == '\0') |
|
||||
++optind; |
|
||||
|
|
||||
if (temp == NULL || c == ':') |
|
||||
{ |
|
||||
if (opterr) |
|
||||
{ |
|
||||
if (posixly_correct) |
|
||||
/* 1003.2 specifies the format of this message. */ |
|
||||
fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); |
|
||||
else |
|
||||
fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c); |
|
||||
} |
|
||||
optopt = c; |
|
||||
return '?'; |
|
||||
} |
|
||||
if (temp[1] == ':') |
|
||||
{ |
|
||||
if (temp[2] == ':') |
|
||||
{ |
|
||||
/* This is an option that accepts an argument optionally. */ |
|
||||
if (*nextchar != '\0') |
|
||||
{ |
|
||||
optarg = nextchar; |
|
||||
optind++; |
|
||||
} |
|
||||
else |
|
||||
optarg = NULL; |
|
||||
nextchar = NULL; |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
/* This is an option that requires an argument. */ |
|
||||
if (*nextchar != '\0') |
|
||||
{ |
|
||||
optarg = nextchar; |
|
||||
/* If we end this ARGV-element by taking the rest as an arg, |
|
||||
we must advance to the next element now. */ |
|
||||
optind++; |
|
||||
} |
|
||||
else if (optind == argc) |
|
||||
{ |
|
||||
if (opterr) |
|
||||
{ |
|
||||
/* 1003.2 specifies the format of this message. */ |
|
||||
fprintf (stderr, "%s: option requires an argument -- %c\n", |
|
||||
argv[0], c); |
|
||||
} |
|
||||
optopt = c; |
|
||||
if (optstring[0] == ':') |
|
||||
c = ':'; |
|
||||
else |
|
||||
c = '?'; |
|
||||
} |
|
||||
else |
|
||||
/* We already incremented `optind' once; |
|
||||
increment it again when taking next ARGV-elt as argument. */ |
|
||||
optarg = argv[optind++]; |
|
||||
nextchar = NULL; |
|
||||
} |
|
||||
} |
|
||||
return c; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
int |
|
||||
getopt (argc, argv, optstring) |
|
||||
int argc; |
|
||||
char *const *argv; |
|
||||
const char *optstring; |
|
||||
{ |
|
||||
return _getopt_internal (argc, argv, optstring, |
|
||||
(const struct option *) 0, |
|
||||
(int *) 0, |
|
||||
0); |
|
||||
} |
|
||||
|
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */ |
|
||||
|
|
||||
#ifdef TEST |
|
||||
|
|
||||
/* Compile with -DTEST to make an executable for use in testing |
|
||||
the above definition of `getopt'. */ |
|
||||
|
|
||||
int |
|
||||
main (argc, argv) |
|
||||
int argc; |
|
||||
char **argv; |
|
||||
{ |
|
||||
int c; |
|
||||
int digit_optind = 0; |
|
||||
|
|
||||
while (1) |
|
||||
{ |
|
||||
int this_option_optind = optind ? optind : 1; |
|
||||
|
|
||||
c = getopt (argc, argv, "abc:d:0123456789"); |
|
||||
if (c == EOF) |
|
||||
break; |
|
||||
|
|
||||
switch (c) |
|
||||
{ |
|
||||
case '0': |
|
||||
case '1': |
|
||||
case '2': |
|
||||
case '3': |
|
||||
case '4': |
|
||||
case '5': |
|
||||
case '6': |
|
||||
case '7': |
|
||||
case '8': |
|
||||
case '9': |
|
||||
if (digit_optind != 0 && digit_optind != this_option_optind) |
|
||||
printf ("digits occur in two different argv-elements.\n"); |
|
||||
digit_optind = this_option_optind; |
|
||||
printf ("option %c\n", c); |
|
||||
break; |
|
||||
|
|
||||
case 'a': |
|
||||
printf ("option a\n"); |
|
||||
break; |
|
||||
|
|
||||
case 'b': |
|
||||
printf ("option b\n"); |
|
||||
break; |
|
||||
|
|
||||
case 'c': |
|
||||
printf ("option c with value `%s'\n", optarg); |
|
||||
break; |
|
||||
|
|
||||
case '?': |
|
||||
break; |
|
||||
|
|
||||
default: |
|
||||
printf ("?? getopt returned character code 0%o ??\n", c); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (optind < argc) |
|
||||
{ |
|
||||
printf ("non-option ARGV-elements: "); |
|
||||
while (optind < argc) |
|
||||
printf ("%s ", argv[optind++]); |
|
||||
printf ("\n"); |
|
||||
} |
|
||||
|
|
||||
exit (0); |
|
||||
} |
|
||||
|
|
||||
#endif /* TEST */ |
|
||||
@ -1,129 +0,0 @@ |
|||||
/* Declarations for getopt. |
|
||||
Copyright (C) 1989, 1990, 1991, 1992, 1993 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 program 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. |
|
||||
|
|
||||
You should have received a copy of the GNU General Public License |
|
||||
along with this program; if not, write to the Free Software |
|
||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
||||
|
|
||||
#ifndef _GETOPT_H |
|
||||
#define _GETOPT_H 1 |
|
||||
|
|
||||
#ifdef __cplusplus |
|
||||
extern "C" { |
|
||||
#endif |
|
||||
|
|
||||
/* For communication from `getopt' to the caller. |
|
||||
When `getopt' finds an option that takes an argument, |
|
||||
the argument value is returned here. |
|
||||
Also, when `ordering' is RETURN_IN_ORDER, |
|
||||
each non-option ARGV-element is returned here. */ |
|
||||
|
|
||||
extern char *optarg; |
|
||||
|
|
||||
/* Index in ARGV of the next element to be scanned. |
|
||||
This is used for communication to and from the caller |
|
||||
and for communication between successive calls to `getopt'. |
|
||||
|
|
||||
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 |
|
||||
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. */ |
|
||||
|
|
||||
extern int optind; |
|
||||
|
|
||||
/* Callers store zero here to inhibit the error message `getopt' prints |
|
||||
for unrecognized options. */ |
|
||||
|
|
||||
extern int opterr; |
|
||||
|
|
||||
/* Set to an option character which was unrecognized. */ |
|
||||
|
|
||||
extern int optopt; |
|
||||
|
|
||||
/* Describe the long-named options requested by the application. |
|
||||
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector |
|
||||
of `struct option' terminated by an element containing a name which is |
|
||||
zero. |
|
||||
|
|
||||
The field `has_arg' is: |
|
||||
no_argument (or 0) if the option does not take an argument, |
|
||||
required_argument (or 1) if the option requires an argument, |
|
||||
optional_argument (or 2) if the option takes an optional argument. |
|
||||
|
|
||||
If the field `flag' is not NULL, it points to a variable that is set |
|
||||
to the value given in the field `val' when the option is found, but |
|
||||
left unchanged if the option is not found. |
|
||||
|
|
||||
To have a long-named option do something other than set an `int' to |
|
||||
a compiled-in constant, such as set a value from `optarg', set the |
|
||||
option's `flag' field to zero and its `val' field to a nonzero |
|
||||
value (the equivalent single-letter option character, if there is |
|
||||
one). For long options that have a zero `flag' field, `getopt' |
|
||||
returns the contents of the `val' field. */ |
|
||||
|
|
||||
struct option |
|
||||
{ |
|
||||
#if __STDC__ |
|
||||
const char *name; |
|
||||
#else |
|
||||
char *name; |
|
||||
#endif |
|
||||
/* has_arg can't be an enum because some compilers complain about |
|
||||
type mismatches in all the code that assumes it is an int. */ |
|
||||
int has_arg; |
|
||||
int *flag; |
|
||||
int val; |
|
||||
}; |
|
||||
|
|
||||
/* Names for the values of the `has_arg' field of `struct option'. */ |
|
||||
|
|
||||
#define no_argument 0 |
|
||||
#define required_argument 1 |
|
||||
#define optional_argument 2 |
|
||||
|
|
||||
#if __STDC__ |
|
||||
#if defined(__GNU_LIBRARY__) |
|
||||
/* Many other libraries have conflicting prototypes for getopt, with |
|
||||
differences in the consts, in stdlib.h. To avoid compilation |
|
||||
errors, only prototype getopt for the GNU C library. */ |
|
||||
extern int getopt (int argc, char *const *argv, const char *shortopts); |
|
||||
#else /* not __GNU_LIBRARY__ */ |
|
||||
extern int getopt (); |
|
||||
#endif /* not __GNU_LIBRARY__ */ |
|
||||
extern int getopt_long (int argc, char *const *argv, const char *shortopts, |
|
||||
const struct option *longopts, int *longind); |
|
||||
extern int getopt_long_only (int argc, char *const *argv, |
|
||||
const char *shortopts, |
|
||||
const struct option *longopts, int *longind); |
|
||||
|
|
||||
/* Internal only. Users should not call this directly. */ |
|
||||
extern int _getopt_internal (int argc, char *const *argv, |
|
||||
const char *shortopts, |
|
||||
const struct option *longopts, int *longind, |
|
||||
int long_only); |
|
||||
#else /* not __STDC__ */ |
|
||||
extern int getopt (); |
|
||||
extern int getopt_long (); |
|
||||
extern int getopt_long_only (); |
|
||||
|
|
||||
extern int _getopt_internal (); |
|
||||
#endif /* not __STDC__ */ |
|
||||
|
|
||||
#ifdef __cplusplus |
|
||||
} |
|
||||
#endif |
|
||||
|
|
||||
#endif /* _GETOPT_H */ |
|
||||
@ -1,180 +0,0 @@ |
|||||
/* getopt_long and getopt_long_only entry points for GNU getopt. |
|
||||
Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 |
|
||||
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 program 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. |
|
||||
|
|
||||
You should have received a copy of the GNU General Public License |
|
||||
along with this program; if not, write to the Free Software |
|
||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
||||
|
|
||||
#ifdef HAVE_CONFIG_H |
|
||||
#include <config.h> |
|
||||
#endif |
|
||||
|
|
||||
#include "getopt.h" |
|
||||
|
|
||||
#ifndef __STDC__ |
|
||||
/* This is a separate conditional since some stdc systems |
|
||||
reject `defined (const)'. */ |
|
||||
#ifndef const |
|
||||
#define const |
|
||||
#endif |
|
||||
#endif |
|
||||
|
|
||||
#include <stdio.h> |
|
||||
|
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not |
|
||||
actually compiling the library itself. This code is part of the GNU C |
|
||||
Library, but also included in many other GNU distributions. Compiling |
|
||||
and linking in this code is a waste when using the GNU C library |
|
||||
(especially if it is a shared library). Rather than having every GNU |
|
||||
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. */ |
|
||||
|
|
||||
#if defined (_LIBC) || !defined (__GNU_LIBRARY__) |
|
||||
|
|
||||
|
|
||||
/* This needs to come after some library #include |
|
||||
to get __GNU_LIBRARY__ defined. */ |
|
||||
#ifdef __GNU_LIBRARY__ |
|
||||
#include <stdlib.h> |
|
||||
#else |
|
||||
char *getenv (); |
|
||||
#endif |
|
||||
|
|
||||
#ifndef NULL |
|
||||
#define NULL 0 |
|
||||
#endif |
|
||||
|
|
||||
int |
|
||||
getopt_long (argc, argv, options, long_options, opt_index) |
|
||||
int argc; |
|
||||
char *const *argv; |
|
||||
const char *options; |
|
||||
const struct option *long_options; |
|
||||
int *opt_index; |
|
||||
{ |
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 0); |
|
||||
} |
|
||||
|
|
||||
/* Like getopt_long, but '-' as well as '--' can indicate a long option. |
|
||||
If an option that starts with '-' (not '--') doesn't match a long option, |
|
||||
but does match a short option, it is parsed as a short option |
|
||||
instead. */ |
|
||||
|
|
||||
int |
|
||||
getopt_long_only (argc, argv, options, long_options, opt_index) |
|
||||
int argc; |
|
||||
char *const *argv; |
|
||||
const char *options; |
|
||||
const struct option *long_options; |
|
||||
int *opt_index; |
|
||||
{ |
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 1); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */ |
|
||||
|
|
||||
#ifdef TEST |
|
||||
|
|
||||
#include <stdio.h> |
|
||||
|
|
||||
int |
|
||||
main (argc, argv) |
|
||||
int argc; |
|
||||
char **argv; |
|
||||
{ |
|
||||
int c; |
|
||||
int digit_optind = 0; |
|
||||
|
|
||||
while (1) |
|
||||
{ |
|
||||
int this_option_optind = optind ? optind : 1; |
|
||||
int option_index = 0; |
|
||||
static struct option long_options[] = |
|
||||
{ |
|
||||
{"add", 1, 0, 0}, |
|
||||
{"append", 0, 0, 0}, |
|
||||
{"delete", 1, 0, 0}, |
|
||||
{"verbose", 0, 0, 0}, |
|
||||
{"create", 0, 0, 0}, |
|
||||
{"file", 1, 0, 0}, |
|
||||
{0, 0, 0, 0} |
|
||||
}; |
|
||||
|
|
||||
c = getopt_long (argc, argv, "abc:d:0123456789", |
|
||||
long_options, &option_index); |
|
||||
if (c == EOF) |
|
||||
break; |
|
||||
|
|
||||
switch (c) |
|
||||
{ |
|
||||
case 0: |
|
||||
printf ("option %s", long_options[option_index].name); |
|
||||
if (optarg) |
|
||||
printf (" with arg %s", optarg); |
|
||||
printf ("\n"); |
|
||||
break; |
|
||||
|
|
||||
case '0': |
|
||||
case '1': |
|
||||
case '2': |
|
||||
case '3': |
|
||||
case '4': |
|
||||
case '5': |
|
||||
case '6': |
|
||||
case '7': |
|
||||
case '8': |
|
||||
case '9': |
|
||||
if (digit_optind != 0 && digit_optind != this_option_optind) |
|
||||
printf ("digits occur in two different argv-elements.\n"); |
|
||||
digit_optind = this_option_optind; |
|
||||
printf ("option %c\n", c); |
|
||||
break; |
|
||||
|
|
||||
case 'a': |
|
||||
printf ("option a\n"); |
|
||||
break; |
|
||||
|
|
||||
case 'b': |
|
||||
printf ("option b\n"); |
|
||||
break; |
|
||||
|
|
||||
case 'c': |
|
||||
printf ("option c with value `%s'\n", optarg); |
|
||||
break; |
|
||||
|
|
||||
case 'd': |
|
||||
printf ("option d with value `%s'\n", optarg); |
|
||||
break; |
|
||||
|
|
||||
case '?': |
|
||||
break; |
|
||||
|
|
||||
default: |
|
||||
printf ("?? getopt returned character code 0%o ??\n", c); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (optind < argc) |
|
||||
{ |
|
||||
printf ("non-option ARGV-elements: "); |
|
||||
while (optind < argc) |
|
||||
printf ("%s ", argv[optind++]); |
|
||||
printf ("\n"); |
|
||||
} |
|
||||
|
|
||||
exit (0); |
|
||||
} |
|
||||
|
|
||||
#endif /* TEST */ |
|
||||
@ -0,0 +1,86 @@ |
|||||
|
/* |
||||
|
* Copyright (c) 1987, 1993, 1994, 1996 |
||||
|
* 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. |
||||
|
*/ |
||||
|
|
||||
|
/* from MINGW gcc 345, H. Vogt 04/10/09 */ |
||||
|
|
||||
|
#ifndef __GETOPT_BSD_H__ |
||||
|
#define __GETOPT_BSD_H__ |
||||
|
|
||||
|
#ifdef __cplusplus |
||||
|
extern "C" { |
||||
|
#endif |
||||
|
|
||||
|
extern int opterr; /* if error message should be printed */ |
||||
|
extern int optind; /* index into parent argv vector */ |
||||
|
extern int optopt; /* character checked for validity */ |
||||
|
extern int optreset; /* reset getopt */ |
||||
|
extern char *optarg; /* argument associated with option */ |
||||
|
|
||||
|
int getopt (int, char * const *, const char *); |
||||
|
|
||||
|
#ifdef __cplusplus |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#endif /* __GETOPT_H__ */ |
||||
|
|
||||
|
#ifndef __UNISTD_GETOPT__ |
||||
|
#ifndef __GETOPT_LONG_BSD_H__ |
||||
|
#define __GETOPT_LONG_BSD_H__ |
||||
|
|
||||
|
#ifdef __cplusplus |
||||
|
extern "C" { |
||||
|
#endif |
||||
|
|
||||
|
struct option { |
||||
|
const char *name; |
||||
|
int has_arg; |
||||
|
int *flag; |
||||
|
int val; |
||||
|
}; |
||||
|
|
||||
|
int getopt_long (int, char *const *, const char *, const struct option *, int *); |
||||
|
#ifndef HAVE_DECL_GETOPT |
||||
|
#define HAVE_DECL_GETOPT 1 |
||||
|
#endif |
||||
|
|
||||
|
#define no_argument 0 |
||||
|
#define required_argument 1 |
||||
|
#define optional_argument 2 |
||||
|
|
||||
|
#ifdef __cplusplus |
||||
|
} |
||||
|
#endif |
||||
|
|
||||
|
#endif /* __GETOPT_LONG_H__ */ |
||||
|
#endif /* __UNISTD_GETOPT__ */ |
||||
@ -0,0 +1,558 @@ |
|||||
|
/* $Id$ */ |
||||
|
/* $OpenBSD: getopt_long.c,v 1.11 2002/12/10 17:51:42 millert Exp $ */ |
||||
|
/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ |
||||
|
|
||||
|
/* |
||||
|
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com> |
||||
|
* 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. The name of the author may not be used to endorse or promote products |
||||
|
* derived from this software without specific prior written permission. |
||||
|
* |
||||
|
* THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. |
||||
|
*/ |
||||
|
/*- |
||||
|
* Copyright (c) 2000 The NetBSD Foundation, Inc. |
||||
|
* All rights reserved. |
||||
|
* |
||||
|
* This code is derived from software contributed to The NetBSD Foundation |
||||
|
* by Dieter Baron and Thomas Klausner. |
||||
|
* |
||||
|
* 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 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 |
||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION 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. |
||||
|
*/ |
||||
|
|
||||
|
/* downloaded from http://www.koders.com/c/fid5FCCD794DA3E7129AC307C40B5D31C268ED04FF5.aspx |
||||
|
at 04/10/09 by H. Vogt */ |
||||
|
|
||||
|
#include "ngspice.h" |
||||
|
#include <errno.h> |
||||
|
|
||||
|
/* If configure finds getopt.h and fcn getopt_long(), then the rest of this file |
||||
|
will not be used. Otherwise (as in MS Visual Studio) this file provides the fcn |
||||
|
getopt_long(), used in main() of ngspice |
||||
|
*/ |
||||
|
#if !defined(HAVE_GETOPT_LONG) || !defined(HAVE_GETOPT_H) |
||||
|
|
||||
|
#include "getopt_bsd.h" |
||||
|
|
||||
|
#include <stdlib.h> |
||||
|
#include <string.h> |
||||
|
#include <stdio.h> |
||||
|
#include <stdarg.h> |
||||
|
|
||||
|
//#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 */ |
||||
|
char *optarg = NULL; /* argument associated with option */ |
||||
|
//#endif |
||||
|
int optreset = 0; /* reset getopt */ |
||||
|
|
||||
|
#define PRINT_ERROR ((opterr) && (*options != ':')) |
||||
|
|
||||
|
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ |
||||
|
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ |
||||
|
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ |
||||
|
|
||||
|
/* return values */ |
||||
|
#define BADCH (int)'?' |
||||
|
#define BADARG ((*options == ':') ? (int)':' : (int)'?') |
||||
|
#define INORDER (int)1 |
||||
|
|
||||
|
#define EMSG "" |
||||
|
|
||||
|
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); |
||||
|
static int gcd(int, int); |
||||
|
static void permute_args(int, int, int, char * const *); |
||||
|
|
||||
|
static char *place = EMSG; /* option letter processing */ |
||||
|
|
||||
|
/* XXX: set optreset to 1 rather than these two */ |
||||
|
static int nonopt_start = -1; /* first non option argument (for permute) */ |
||||
|
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 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"; |
||||
|
|
||||
|
|
||||
|
static void |
||||
|
warnxx(const char *fmt, ...) |
||||
|
{ |
||||
|
va_list args; |
||||
|
va_start(args, fmt); |
||||
|
vfprintf(stderr, fmt, args); |
||||
|
fprintf(stderr,"\n"); |
||||
|
va_end(args); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Compute the greatest common divisor of a and b. |
||||
|
*/ |
||||
|
static int |
||||
|
gcd(int a, int b) |
||||
|
{ |
||||
|
int c; |
||||
|
|
||||
|
c = a % b; |
||||
|
while (c != 0) { |
||||
|
a = b; |
||||
|
b = c; |
||||
|
c = a % b; |
||||
|
} |
||||
|
|
||||
|
return (b); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Exchange the block from nonopt_start to nonopt_end with the block |
||||
|
* from nonopt_end to opt_end (keeping the same order of arguments |
||||
|
* in each block). |
||||
|
*/ |
||||
|
static void |
||||
|
permute_args(int panonopt_start, int panonopt_end, int opt_end, |
||||
|
char * const *nargv) |
||||
|
{ |
||||
|
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; |
||||
|
char *swap; |
||||
|
|
||||
|
/* |
||||
|
* compute lengths of blocks and number and size of cycles |
||||
|
*/ |
||||
|
nnonopts = panonopt_end - panonopt_start; |
||||
|
nopts = opt_end - panonopt_end; |
||||
|
ncycle = gcd(nnonopts, nopts); |
||||
|
cyclelen = (opt_end - panonopt_start) / ncycle; |
||||
|
|
||||
|
for (i = 0; i < ncycle; i++) { |
||||
|
cstart = panonopt_end+i; |
||||
|
pos = cstart; |
||||
|
for (j = 0; j < cyclelen; j++) { |
||||
|
if (pos >= panonopt_end) |
||||
|
pos -= nnonopts; |
||||
|
else |
||||
|
pos += nopts; |
||||
|
swap = nargv[pos]; |
||||
|
/* LINTED const cast */ |
||||
|
((char **) nargv)[pos] = nargv[cstart]; |
||||
|
/* LINTED const cast */ |
||||
|
((char **)nargv)[cstart] = swap; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* parse_long_options -- |
||||
|
* Parse long options in argc/argv argument vector. |
||||
|
* Returns -1 if short_too is set and the option does not match long_options. |
||||
|
*/ |
||||
|
static int |
||||
|
parse_long_options(char * const *nargv, const char *options, |
||||
|
const struct option *long_options, int *idx, int short_too) |
||||
|
{ |
||||
|
char *current_argv, *has_equal; |
||||
|
size_t current_argv_len; |
||||
|
int i, match; |
||||
|
|
||||
|
current_argv = place; |
||||
|
match = -1; |
||||
|
|
||||
|
optind++; |
||||
|
|
||||
|
if ((has_equal = strchr(current_argv, '=')) != NULL) { |
||||
|
/* argument found (--option=arg) */ |
||||
|
current_argv_len = has_equal - current_argv; |
||||
|
has_equal++; |
||||
|
} else |
||||
|
current_argv_len = strlen(current_argv); |
||||
|
|
||||
|
for (i = 0; long_options[i].name; i++) { |
||||
|
/* find matching long option */ |
||||
|
if (strncmp(current_argv, long_options[i].name, |
||||
|
current_argv_len)) |
||||
|
continue; |
||||
|
|
||||
|
if (strlen(long_options[i].name) == current_argv_len) { |
||||
|
/* exact match */ |
||||
|
match = i; |
||||
|
break; |
||||
|
} |
||||
|
/* |
||||
|
* If this is a known short option, don't allow |
||||
|
* a partial match of a single character. |
||||
|
*/ |
||||
|
if (short_too && current_argv_len == 1) |
||||
|
continue; |
||||
|
|
||||
|
if (match == -1) /* partial match */ |
||||
|
match = i; |
||||
|
else { |
||||
|
/* ambiguous abbreviation */ |
||||
|
if (PRINT_ERROR) |
||||
|
warnxx(ambig, (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) |
||||
|
warnxx(noarg, (int)current_argv_len, |
||||
|
current_argv); |
||||
|
/* |
||||
|
* XXX: GNU sets optopt to val regardless of flag |
||||
|
*/ |
||||
|
if (long_options[match].flag == NULL) |
||||
|
optopt = long_options[match].val; |
||||
|
else |
||||
|
optopt = 0; |
||||
|
return (BADARG); |
||||
|
} |
||||
|
if (long_options[match].has_arg == required_argument || |
||||
|
long_options[match].has_arg == optional_argument) { |
||||
|
if (has_equal) |
||||
|
optarg = has_equal; |
||||
|
else if (long_options[match].has_arg == |
||||
|
required_argument) { |
||||
|
/* |
||||
|
* optional argument doesn't use next nargv |
||||
|
*/ |
||||
|
optarg = nargv[optind++]; |
||||
|
} |
||||
|
} |
||||
|
if ((long_options[match].has_arg == required_argument) |
||||
|
&& (optarg == NULL)) { |
||||
|
/* |
||||
|
* Missing argument; leading ':' indicates no error |
||||
|
* should be generated. |
||||
|
*/ |
||||
|
if (PRINT_ERROR) |
||||
|
warnxx(recargstring, |
||||
|
current_argv); |
||||
|
/* |
||||
|
* XXX: GNU sets optopt to val regardless of flag |
||||
|
*/ |
||||
|
if (long_options[match].flag == NULL) |
||||
|
optopt = long_options[match].val; |
||||
|
else |
||||
|
optopt = 0; |
||||
|
--optind; |
||||
|
return (BADARG); |
||||
|
} |
||||
|
} else { /* unknown option */ |
||||
|
if (short_too) { |
||||
|
--optind; |
||||
|
return (-1); |
||||
|
} |
||||
|
if (PRINT_ERROR) |
||||
|
warnxx(illoptstring, current_argv); |
||||
|
optopt = 0; |
||||
|
return (BADCH); |
||||
|
} |
||||
|
if (idx) |
||||
|
*idx = match; |
||||
|
if (long_options[match].flag) { |
||||
|
*long_options[match].flag = long_options[match].val; |
||||
|
return (0); |
||||
|
} else |
||||
|
return (long_options[match].val); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* getopt_internal -- |
||||
|
* Parse argc/argv argument vector. Called by user level routines. |
||||
|
*/ |
||||
|
static int |
||||
|
getopt_internal(int nargc, char * const *nargv, const char *options, |
||||
|
const struct option *long_options, int *idx, int flags) |
||||
|
{ |
||||
|
char *oli; /* option letter list index */ |
||||
|
int optchar, short_too; |
||||
|
static int posixly_correct = -1; |
||||
|
|
||||
|
if (options == NULL) |
||||
|
return (-1); |
||||
|
|
||||
|
/* |
||||
|
* Disable GNU extensions if POSIXLY_CORRECT is set or options |
||||
|
* string begins with a '+'. |
||||
|
*/ |
||||
|
if (posixly_correct == -1) |
||||
|
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); |
||||
|
if (posixly_correct || *options == '+') |
||||
|
flags &= ~FLAG_PERMUTE; |
||||
|
else if (*options == '-') |
||||
|
flags |= FLAG_ALLARGS; |
||||
|
if (*options == '+' || *options == '-') |
||||
|
options++; |
||||
|
|
||||
|
/* |
||||
|
* XXX Some GNU programs (like cvs) set optind to 0 instead of |
||||
|
* XXX using optreset. Work around this braindamage. |
||||
|
*/ |
||||
|
if (optind == 0) |
||||
|
optind = optreset = 1; |
||||
|
|
||||
|
optarg = NULL; |
||||
|
if (optreset) |
||||
|
nonopt_start = nonopt_end = -1; |
||||
|
start: |
||||
|
if (optreset || !*place) { /* update scanning pointer */ |
||||
|
optreset = 0; |
||||
|
if (optind >= nargc) { /* end of argument vector */ |
||||
|
place = EMSG; |
||||
|
if (nonopt_end != -1) { |
||||
|
/* do permutation, if we have to */ |
||||
|
permute_args(nonopt_start, nonopt_end, |
||||
|
optind, nargv); |
||||
|
optind -= nonopt_end - nonopt_start; |
||||
|
} |
||||
|
else if (nonopt_start != -1) { |
||||
|
/* |
||||
|
* If we skipped non-options, set optind |
||||
|
* to the first of them. |
||||
|
*/ |
||||
|
optind = nonopt_start; |
||||
|
} |
||||
|
nonopt_start = nonopt_end = -1; |
||||
|
return (-1); |
||||
|
} |
||||
|
if (*(place = nargv[optind]) != '-' || |
||||
|
(place[1] == '\0' && strchr(options, '-') == NULL)) { |
||||
|
place = EMSG; /* found non-option */ |
||||
|
if (flags & FLAG_ALLARGS) { |
||||
|
/* |
||||
|
* GNU extension: |
||||
|
* return non-option as argument to option 1 |
||||
|
*/ |
||||
|
optarg = nargv[optind++]; |
||||
|
return (INORDER); |
||||
|
} |
||||
|
if (!(flags & FLAG_PERMUTE)) { |
||||
|
/* |
||||
|
* If no permutation wanted, stop parsing |
||||
|
* at first non-option. |
||||
|
*/ |
||||
|
return (-1); |
||||
|
} |
||||
|
/* do permutation */ |
||||
|
if (nonopt_start == -1) |
||||
|
nonopt_start = optind; |
||||
|
else if (nonopt_end != -1) { |
||||
|
permute_args(nonopt_start, nonopt_end, |
||||
|
optind, nargv); |
||||
|
nonopt_start = optind - |
||||
|
(nonopt_end - nonopt_start); |
||||
|
nonopt_end = -1; |
||||
|
} |
||||
|
optind++; |
||||
|
/* process next argument */ |
||||
|
goto start; |
||||
|
} |
||||
|
if (nonopt_start != -1 && nonopt_end == -1) |
||||
|
nonopt_end = optind; |
||||
|
|
||||
|
/* |
||||
|
* Check for "--" or "--foo" with no long options |
||||
|
* but if place is simply "-" leave it unmolested. |
||||
|
*/ |
||||
|
if (place[1] != '\0' && *++place == '-' && |
||||
|
(place[1] == '\0' || long_options == NULL)) { |
||||
|
optind++; |
||||
|
place = EMSG; |
||||
|
/* |
||||
|
* We found an option (--), so if we skipped |
||||
|
* non-options, we have to permute. |
||||
|
*/ |
||||
|
if (nonopt_end != -1) { |
||||
|
permute_args(nonopt_start, nonopt_end, |
||||
|
optind, nargv); |
||||
|
optind -= nonopt_end - nonopt_start; |
||||
|
} |
||||
|
nonopt_start = nonopt_end = -1; |
||||
|
return (-1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* Check long options if: |
||||
|
* 1) we were passed some |
||||
|
* 2) the arg is not just "-" |
||||
|
* 3) either the arg starts with -- we are getopt_long_only() |
||||
|
*/ |
||||
|
if (long_options != NULL && place != nargv[optind] && |
||||
|
(*place == '-' || (flags & FLAG_LONGONLY))) { |
||||
|
short_too = 0; |
||||
|
if (*place == '-') |
||||
|
place++; /* --foo long option */ |
||||
|
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); |
||||
|
if (optchar != -1) { |
||||
|
place = EMSG; |
||||
|
return (optchar); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if ((optchar = (int)*place++) == (int)':' || |
||||
|
(oli = strchr(options, optchar)) == NULL) { |
||||
|
/* |
||||
|
* If the user didn't specify '-' as an option, |
||||
|
* assume it means -1 as POSIX specifies. |
||||
|
*/ |
||||
|
if (optchar == (int)'-') |
||||
|
return (-1); |
||||
|
/* option letter unknown or ':' */ |
||||
|
if (!*place) |
||||
|
++optind; |
||||
|
if (PRINT_ERROR) |
||||
|
warnxx(illoptchar, optchar); |
||||
|
optopt = optchar; |
||||
|
return (BADCH); |
||||
|
} |
||||
|
if (long_options != NULL && optchar == 'W' && oli[1] == ';') { |
||||
|
/* -W long-option */ |
||||
|
if (*place) /* no space */ |
||||
|
/* NOTHING */; |
||||
|
else if (++optind >= nargc) { /* no arg */ |
||||
|
place = EMSG; |
||||
|
if (PRINT_ERROR) |
||||
|
warnxx(recargchar, optchar); |
||||
|
optopt = optchar; |
||||
|
return (BADARG); |
||||
|
} else /* white space */ |
||||
|
place = nargv[optind]; |
||||
|
optchar = parse_long_options(nargv, options, long_options, |
||||
|
idx, 0); |
||||
|
place = EMSG; |
||||
|
return (optchar); |
||||
|
} |
||||
|
if (*++oli != ':') { /* doesn't take argument */ |
||||
|
if (!*place) |
||||
|
++optind; |
||||
|
} else { /* takes (optional) argument */ |
||||
|
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) |
||||
|
warnxx(recargchar, optchar); |
||||
|
optopt = optchar; |
||||
|
return (BADARG); |
||||
|
} else |
||||
|
optarg = nargv[optind]; |
||||
|
} |
||||
|
place = EMSG; |
||||
|
++optind; |
||||
|
} |
||||
|
/* dump back option letter */ |
||||
|
return (optchar); |
||||
|
} |
||||
|
|
||||
|
#ifdef REPLACE_GETOPT |
||||
|
/* |
||||
|
* getopt -- |
||||
|
* Parse argc/argv argument vector. |
||||
|
* |
||||
|
* [eventually this will replace the BSD getopt] |
||||
|
*/ |
||||
|
int |
||||
|
getopt(int nargc, char * const *nargv, const char *options) |
||||
|
{ |
||||
|
|
||||
|
/* |
||||
|
* We dont' pass FLAG_PERMUTE to getopt_internal() since |
||||
|
* the BSD getopt(3) (unlike GNU) has never done this. |
||||
|
* |
||||
|
* Furthermore, since many privileged programs call getopt() |
||||
|
* before dropping privileges it makes sense to keep things |
||||
|
* as simple (and bug-free) as possible. |
||||
|
*/ |
||||
|
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); |
||||
|
} |
||||
|
#endif /* REPLACE_GETOPT */ |
||||
|
|
||||
|
/* |
||||
|
* getopt_long -- |
||||
|
* Parse argc/argv argument vector. |
||||
|
*/ |
||||
|
int |
||||
|
getopt_long(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx) |
||||
|
{ |
||||
|
|
||||
|
return (getopt_internal(nargc, nargv, options, long_options, idx, |
||||
|
FLAG_PERMUTE)); |
||||
|
} |
||||
|
|
||||
|
/* |
||||
|
* getopt_long_only -- |
||||
|
* Parse argc/argv argument vector. |
||||
|
*/ |
||||
|
int |
||||
|
getopt_long_only(int nargc, char * const *nargv, const char *options, |
||||
|
const struct option *long_options, int *idx) |
||||
|
{ |
||||
|
|
||||
|
return (getopt_internal(nargc, nargv, options, long_options, idx, |
||||
|
FLAG_PERMUTE|FLAG_LONGONLY)); |
||||
|
} |
||||
|
|
||||
|
#endif /* HAVE_GETOPT_LONG */ |
||||
|
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue