|
Packit |
a4aae4 |
/*
|
|
Packit |
a4aae4 |
Getopt for GNU.
|
|
Packit |
a4aae4 |
Copyright (C) 1987, 1989 Free Software Foundation, Inc.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
(Modified by Douglas C. Schmidt for use with GNU G++.)
|
|
Packit |
a4aae4 |
This file is part of the GNU C++ Library. This library is free
|
|
Packit |
a4aae4 |
software; you can redistribute it and/or modify it under the terms of
|
|
Packit |
a4aae4 |
the GNU Library General Public License as published by the Free
|
|
Packit |
a4aae4 |
Software Foundation; either version 2 of the License, or (at your
|
|
Packit |
a4aae4 |
option) any later version. This library is distributed in the hope
|
|
Packit |
a4aae4 |
that it will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
Packit |
a4aae4 |
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
Packit |
a4aae4 |
PURPOSE. See the GNU Library General Public License for more details.
|
|
Packit |
a4aae4 |
You should have received a copy of the GNU Library General Public
|
|
Packit |
a4aae4 |
License along with this library; if not, write to the Free Software
|
|
Packit |
a4aae4 |
Foundation, 59 Temple Place - Fifth Floor, Boston, MA 02110-1301, USA.
|
|
Packit |
a4aae4 |
*/
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "config.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* AIX requires the alloca decl to be the first thing in the file. */
|
|
Packit |
a4aae4 |
#ifdef __GNUC__
|
|
Packit |
a4aae4 |
#define alloca __builtin_alloca
|
|
Packit |
a4aae4 |
#elif defined(sparc)
|
|
Packit |
a4aae4 |
#include <alloca.h>
|
|
Packit |
a4aae4 |
#elif defined(_AIX)
|
|
Packit |
a4aae4 |
#pragma alloca
|
|
Packit |
a4aae4 |
#elif defined(WIN32)
|
|
Packit |
a4aae4 |
#include <malloc.h>
|
|
Packit |
a4aae4 |
#else
|
|
Packit |
a4aae4 |
char *alloca ();
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include <vector>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#ifdef HAVE_UNISTD_H
|
|
Packit |
a4aae4 |
#include <unistd.h>
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
#include <cstdio>
|
|
Packit |
a4aae4 |
#include <cstring> // Added these. 10/20/98 jhrg
|
|
Packit |
a4aae4 |
#include <cstdlib>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
#include "GetOpt.h"
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//#include <string.h>
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
char* GetOpt::nextchar = 0;
|
|
Packit |
a4aae4 |
int GetOpt::first_nonopt = 0;
|
|
Packit |
a4aae4 |
int GetOpt::last_nonopt = 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
GetOpt::GetOpt (int argc, char **argv, const char *optstring)
|
|
Packit |
a4aae4 |
:opterr (1), nargc (argc), nargv (argv), noptstring (optstring)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
/* Initialize the internal data when the first call is made.
|
|
Packit |
a4aae4 |
Start processing options with ARGV-element 1 (since ARGV-element 0
|
|
Packit |
a4aae4 |
is the program name); the sequence of previously skipped
|
|
Packit |
a4aae4 |
non-option ARGV-elements is empty. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
first_nonopt = last_nonopt = optind = 1;
|
|
Packit |
a4aae4 |
optarg = nextchar = 0;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* Determine how to handle the ordering of options and nonoptions. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (optstring[0] == '-')
|
|
Packit |
a4aae4 |
ordering = RETURN_IN_ORDER;
|
|
Packit |
a4aae4 |
else if (getenv ("_POSIX_OPTION_ORDER") != 0)
|
|
Packit |
a4aae4 |
ordering = REQUIRE_ORDER;
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
ordering = PERMUTE;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
void
|
|
Packit |
a4aae4 |
GetOpt::exchange (char **argv)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
int nonopts_size = (last_nonopt - first_nonopt) * sizeof(char *);
|
|
Packit |
a4aae4 |
/* char **temp = (char **) alloca (nonopts_size); */
|
|
Packit |
a4aae4 |
/* char **temp = (char **)malloc(nonopts_size); */
|
|
Packit |
a4aae4 |
std::vector<char> temp(nonopts_size);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* Interchange the two blocks of data in argv. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
memcpy (&temp[0], &argv[first_nonopt], nonopts_size);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* valgrind complains about this because in some cases the memory areas
|
|
Packit |
a4aae4 |
overlap. I switched to memmove. See the memcpy & memmove man pages.
|
|
Packit |
a4aae4 |
02/12/04 jhrg */
|
|
Packit |
a4aae4 |
#if 0
|
|
Packit |
a4aae4 |
memcpy (&argv[first_nonopt], &argv[last_nonopt],
|
|
Packit |
a4aae4 |
(optind - last_nonopt) * sizeof (char *));
|
|
Packit |
a4aae4 |
#endif
|
|
Packit |
a4aae4 |
memmove (&argv[first_nonopt], &argv[last_nonopt],
|
|
Packit |
a4aae4 |
(optind - last_nonopt) * sizeof (char *));
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
memcpy (&argv[first_nonopt + optind - last_nonopt], &temp[0],
|
|
Packit |
a4aae4 |
nonopts_size);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* Update records for the slots the non-options now occupy. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
first_nonopt += (optind - last_nonopt);
|
|
Packit |
a4aae4 |
last_nonopt = optind;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
//free(temp);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* Scan elements of ARGV (whose length is ARGC) for option characters
|
|
Packit |
a4aae4 |
given in OPTSTRING.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
If an element of ARGV starts with '-', and is not exactly "-" or "--",
|
|
Packit |
a4aae4 |
then it is an option element. The characters of this element
|
|
Packit |
a4aae4 |
(aside from the initial '-') are option characters. If `getopt'
|
|
Packit |
a4aae4 |
is called repeatedly, it returns successively each of theoption characters
|
|
Packit |
a4aae4 |
from each of the option elements.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
If `getopt' finds another option character, it returns that character,
|
|
Packit |
a4aae4 |
updating `optind' and `nextchar' so that the next call to `getopt' can
|
|
Packit |
a4aae4 |
resume the scan with the following option character or ARGV-element.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
If there are no more option characters, `getopt' returns `EOF'.
|
|
Packit |
a4aae4 |
Then `optind' is the index in ARGV of the first ARGV-element
|
|
Packit |
a4aae4 |
that is not an option. (The ARGV-elements have been permuted
|
|
Packit |
a4aae4 |
so that those that are not options now come last.)
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
OPTSTRING is a string containing the legitimate option characters.
|
|
Packit |
a4aae4 |
A colon in OPTSTRING means that the previous character is an option
|
|
Packit |
a4aae4 |
that wants an argument. The argument is taken from the rest of the
|
|
Packit |
a4aae4 |
current ARGV-element, or from the following ARGV-element,
|
|
Packit |
a4aae4 |
and returned in `optarg'.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
If an option character is seen that is not listed in OPTSTRING,
|
|
Packit |
a4aae4 |
return '?' after printing an error message. If you set `opterr' to
|
|
Packit |
a4aae4 |
zero, the error message is suppressed but we still return '?'.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
|
|
Packit |
a4aae4 |
so the following text in the same ARGV-element, or the text of the following
|
|
Packit |
a4aae4 |
ARGV-element, is returned in `optarg. Two colons mean an option that
|
|
Packit |
a4aae4 |
wants an optional arg; if there is text in the current ARGV-element,
|
|
Packit |
a4aae4 |
it is returned in `optarg'.
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
If OPTSTRING starts with `-', it requests a different method of handling the
|
|
Packit |
a4aae4 |
non-option ARGV-elements. See the comments about RETURN_IN_ORDER, above. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
int
|
|
Packit |
a4aae4 |
GetOpt::operator () (void)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (nextchar == 0 || *nextchar == 0)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (ordering == PERMUTE)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
/* If we have just processed some options following some non-options,
|
|
Packit |
a4aae4 |
exchange them so that the options come first. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (first_nonopt != last_nonopt && last_nonopt != optind)
|
|
Packit |
a4aae4 |
exchange (nargv);
|
|
Packit |
a4aae4 |
else if (last_nonopt != optind)
|
|
Packit |
a4aae4 |
first_nonopt = optind;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* Now skip any additional non-options
|
|
Packit |
a4aae4 |
and extend the range of non-options previously skipped. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
while (optind < nargc
|
|
Packit |
a4aae4 |
&& (nargv[optind][0] != '-'
|
|
Packit |
a4aae4 |
|| nargv[optind][1] == 0))
|
|
Packit |
a4aae4 |
optind++;
|
|
Packit |
a4aae4 |
last_nonopt = optind;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* Special ARGV-element `--' means premature end of options.
|
|
Packit |
a4aae4 |
Skip it like a null option,
|
|
Packit |
a4aae4 |
then exchange with previous non-options as if it were an option,
|
|
Packit |
a4aae4 |
then skip everything else like a non-option. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (optind != nargc && !strcmp (nargv[optind], "--"))
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
optind++;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (first_nonopt != last_nonopt && last_nonopt != optind)
|
|
Packit |
a4aae4 |
exchange (nargv);
|
|
Packit |
a4aae4 |
else if (first_nonopt == last_nonopt)
|
|
Packit |
a4aae4 |
first_nonopt = optind;
|
|
Packit |
a4aae4 |
last_nonopt = nargc;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
optind = nargc;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* If we have done all the ARGV-elements, stop the scan
|
|
Packit |
a4aae4 |
and back over any non-options that we skipped and permuted. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (optind == nargc)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
/* Set the next-arg-index to point at the non-options
|
|
Packit |
a4aae4 |
that we previously skipped, so the caller will digest them. */
|
|
Packit |
a4aae4 |
if (first_nonopt != last_nonopt)
|
|
Packit |
a4aae4 |
optind = first_nonopt;
|
|
Packit |
a4aae4 |
return EOF;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* If we have come to a non-option and did not permute it,
|
|
Packit |
a4aae4 |
either stop the scan or describe it to the caller and pass it by. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (nargv[optind][0] != '-' || nargv[optind][1] == 0)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (ordering == REQUIRE_ORDER)
|
|
Packit |
a4aae4 |
return EOF;
|
|
Packit |
a4aae4 |
optarg = nargv[optind++];
|
|
Packit |
a4aae4 |
return 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* We have found another option-ARGV-element.
|
|
Packit |
a4aae4 |
Start decoding its characters. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
nextchar = nargv[optind] + 1;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* Look at and handle the next option-character. */
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
char c = *nextchar++;
|
|
Packit |
a4aae4 |
char *temp = (char *) strchr (noptstring, c);
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
/* Increment `optind' when we start to process its last character. */
|
|
Packit |
a4aae4 |
if (*nextchar == 0)
|
|
Packit |
a4aae4 |
optind++;
|
|
Packit |
a4aae4 |
|
|
Packit |
a4aae4 |
if (temp == 0 || c == ':')
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (opterr != 0)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (c < 040 || c >= 0177)
|
|
Packit |
a4aae4 |
fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
|
|
Packit |
a4aae4 |
nargv[0], c);
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
fprintf (stderr, "%s: unrecognized option `-%c'\n",
|
|
Packit |
a4aae4 |
nargv[0], c);
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return '?';
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
if (temp[1] == ':')
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (temp[2] == ':')
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
/* This is an option that accepts an argument optionally. */
|
|
Packit |
a4aae4 |
if (*nextchar != 0)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
optarg = nextchar;
|
|
Packit |
a4aae4 |
optind++;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
optarg = 0;
|
|
Packit |
a4aae4 |
nextchar = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
/* This is an option that requires an argument. */
|
|
Packit |
a4aae4 |
if (*nextchar != 0)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
optarg = nextchar;
|
|
Packit |
a4aae4 |
/* If we end this ARGV-element by taking the rest as an arg,
|
|
Packit |
a4aae4 |
we must advance to the next element now. */
|
|
Packit |
a4aae4 |
optind++;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else if (optind == nargc)
|
|
Packit |
a4aae4 |
{
|
|
Packit |
a4aae4 |
if (opterr != 0)
|
|
Packit |
a4aae4 |
fprintf (stderr, "%s: no argument for `-%c' option\n",
|
|
Packit |
a4aae4 |
nargv[0], c);
|
|
Packit |
a4aae4 |
c = '?';
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
else
|
|
Packit |
a4aae4 |
/* We already incremented `optind' once;
|
|
Packit |
a4aae4 |
increment it again when taking next ARGV-elt as argument. */
|
|
Packit |
a4aae4 |
optarg = nargv[optind++];
|
|
Packit |
a4aae4 |
nextchar = 0;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
return c;
|
|
Packit |
a4aae4 |
}
|
|
Packit |
a4aae4 |
}
|