Blame GNU/GetOpt.cc

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
}