libdap  Updated for version 3.17.0
GetOpt.cc
00001 /*
00002 Getopt for GNU. 
00003 Copyright (C) 1987, 1989 Free Software Foundation, Inc.
00004 
00005 (Modified by Douglas C. Schmidt for use with GNU G++.)
00006 This file is part of the GNU C++ Library.  This library is free
00007 software; you can redistribute it and/or modify it under the terms of
00008 the GNU Library General Public License as published by the Free
00009 Software Foundation; either version 2 of the License, or (at your
00010 option) any later version.  This library is distributed in the hope
00011 that it will be useful, but WITHOUT ANY WARRANTY; without even the
00012 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00013 PURPOSE.  See the GNU Library General Public License for more details.
00014 You should have received a copy of the GNU Library General Public
00015 License along with this library; if not, write to the Free Software
00016 Foundation, 59 Temple Place - Fifth Floor, Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #include "config.h"
00020 
00021 /* AIX requires the alloca decl to be the first thing in the file. */
00022 #ifdef __GNUC__
00023 #define alloca __builtin_alloca
00024 #elif defined(sparc)
00025 #include <alloca.h>
00026 #elif defined(_AIX)
00027 #pragma alloca
00028 #elif defined(WIN32)
00029 #include <malloc.h>
00030 #else
00031 char *alloca ();
00032 #endif
00033 
00034 #include <vector>
00035 
00036 #ifdef HAVE_UNISTD_H
00037 #include <unistd.h>
00038 #endif
00039 #include <cstdio>
00040 #include <cstring>              // Added these. 10/20/98 jhrg
00041 #include <cstdlib>
00042 
00043 #include "GetOpt.h"
00044 
00045 //#include <string.h>
00046 
00047 char* GetOpt::nextchar = 0;
00048 int GetOpt::first_nonopt = 0;
00049 int GetOpt::last_nonopt = 0;
00050 
00051 GetOpt::GetOpt (int argc, char **argv, const char *optstring)
00052  :opterr (1), nargc (argc), nargv (argv), noptstring (optstring)
00053 {
00054   /* Initialize the internal data when the first call is made.
00055      Start processing options with ARGV-element 1 (since ARGV-element 0
00056      is the program name); the sequence of previously skipped
00057      non-option ARGV-elements is empty.  */
00058 
00059   first_nonopt = last_nonopt = optind = 1;
00060   optarg = nextchar = 0;
00061 
00062   /* Determine how to handle the ordering of options and nonoptions.  */
00063 
00064   if (optstring[0] == '-')
00065     ordering = RETURN_IN_ORDER;
00066   else if (getenv ("_POSIX_OPTION_ORDER") != 0)
00067     ordering = REQUIRE_ORDER;
00068   else
00069     ordering = PERMUTE;
00070 }
00071 
00072 void
00073 GetOpt::exchange (char **argv)
00074 {
00075   int nonopts_size = (last_nonopt - first_nonopt) * sizeof(char *);
00076   /* char **temp = (char **) alloca (nonopts_size); */
00077   /* char **temp = (char **)malloc(nonopts_size); */
00078   std::vector<char> temp(nonopts_size);
00079   
00080   /* Interchange the two blocks of data in argv.  */
00081 
00082   memcpy (&temp[0], &argv[first_nonopt], nonopts_size);
00083 
00084   /* valgrind complains about this because in some cases the memory areas
00085      overlap. I switched to memmove. See the memcpy & memmove man pages.
00086      02/12/04 jhrg */
00087 #if 0
00088   memcpy (&argv[first_nonopt], &argv[last_nonopt],
00089          (optind - last_nonopt) * sizeof (char *));
00090 #endif
00091   memmove (&argv[first_nonopt], &argv[last_nonopt],
00092          (optind - last_nonopt) * sizeof (char *));
00093 
00094   memcpy (&argv[first_nonopt + optind - last_nonopt], &temp[0],
00095          nonopts_size);
00096 
00097   /* Update records for the slots the non-options now occupy.  */
00098 
00099   first_nonopt += (optind - last_nonopt);
00100   last_nonopt = optind;
00101   
00102   //free(temp);
00103 }
00104 
00105 /* Scan elements of ARGV (whose length is ARGC) for option characters
00106    given in OPTSTRING.
00107 
00108    If an element of ARGV starts with '-', and is not exactly "-" or "--",
00109    then it is an option element.  The characters of this element
00110    (aside from the initial '-') are option characters.  If `getopt'
00111    is called repeatedly, it returns successively each of theoption characters
00112    from each of the option elements.
00113 
00114    If `getopt' finds another option character, it returns that character,
00115    updating `optind' and `nextchar' so that the next call to `getopt' can
00116    resume the scan with the following option character or ARGV-element.
00117 
00118    If there are no more option characters, `getopt' returns `EOF'.
00119    Then `optind' is the index in ARGV of the first ARGV-element
00120    that is not an option.  (The ARGV-elements have been permuted
00121    so that those that are not options now come last.)
00122 
00123    OPTSTRING is a string containing the legitimate option characters.
00124    A colon in OPTSTRING means that the previous character is an option
00125    that wants an argument.  The argument is taken from the rest of the
00126    current ARGV-element, or from the following ARGV-element,
00127    and returned in `optarg'.
00128 
00129    If an option character is seen that is not listed in OPTSTRING,
00130    return '?' after printing an error message.  If you set `opterr' to
00131    zero, the error message is suppressed but we still return '?'.
00132 
00133    If a char in OPTSTRING is followed by a colon, that means it wants an arg,
00134    so the following text in the same ARGV-element, or the text of the following
00135    ARGV-element, is returned in `optarg.  Two colons mean an option that
00136    wants an optional arg; if there is text in the current ARGV-element,
00137    it is returned in `optarg'.
00138 
00139    If OPTSTRING starts with `-', it requests a different method of handling the
00140    non-option ARGV-elements.  See the comments about RETURN_IN_ORDER, above.  */
00141 
00142 int
00143 GetOpt::operator () (void)
00144 {
00145   if (nextchar == 0 || *nextchar == 0)
00146     {
00147       if (ordering == PERMUTE)
00148         {
00149           /* If we have just processed some options following some non-options,
00150              exchange them so that the options come first.  */
00151 
00152           if (first_nonopt != last_nonopt && last_nonopt != optind)
00153             exchange (nargv);
00154           else if (last_nonopt != optind)
00155             first_nonopt = optind;
00156 
00157           /* Now skip any additional non-options
00158              and extend the range of non-options previously skipped.  */
00159 
00160           while (optind < nargc
00161                  && (nargv[optind][0] != '-'
00162                      || nargv[optind][1] == 0))
00163             optind++;
00164           last_nonopt = optind;
00165         }
00166 
00167       /* Special ARGV-element `--' means premature end of options.
00168          Skip it like a null option,
00169          then exchange with previous non-options as if it were an option,
00170          then skip everything else like a non-option.  */
00171 
00172       if (optind != nargc && !strcmp (nargv[optind], "--"))
00173         {
00174           optind++;
00175 
00176           if (first_nonopt != last_nonopt && last_nonopt != optind)
00177             exchange (nargv);
00178           else if (first_nonopt == last_nonopt)
00179             first_nonopt = optind;
00180           last_nonopt = nargc;
00181 
00182           optind = nargc;
00183         }
00184 
00185       /* If we have done all the ARGV-elements, stop the scan
00186          and back over any non-options that we skipped and permuted.  */
00187 
00188       if (optind == nargc)
00189         {
00190           /* Set the next-arg-index to point at the non-options
00191              that we previously skipped, so the caller will digest them.  */
00192           if (first_nonopt != last_nonopt)
00193             optind = first_nonopt;
00194           return EOF;
00195         }
00196          
00197       /* If we have come to a non-option and did not permute it,
00198          either stop the scan or describe it to the caller and pass it by.  */
00199 
00200       if (nargv[optind][0] != '-' || nargv[optind][1] == 0)
00201         {
00202           if (ordering == REQUIRE_ORDER)
00203             return EOF;
00204           optarg = nargv[optind++];
00205           return 0;
00206         }
00207 
00208       /* We have found another option-ARGV-element.
00209          Start decoding its characters.  */
00210 
00211       nextchar = nargv[optind] + 1;
00212     }
00213 
00214   /* Look at and handle the next option-character.  */
00215 
00216   {
00217     char c = *nextchar++;
00218     char *temp = (char *) strchr (noptstring, c);
00219 
00220     /* Increment `optind' when we start to process its last character.  */
00221     if (*nextchar == 0)
00222       optind++;
00223 
00224     if (temp == 0 || c == ':')
00225       {
00226         if (opterr != 0)
00227           {
00228             if (c < 040 || c >= 0177)
00229               fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
00230                        nargv[0], c);
00231             else
00232               fprintf (stderr, "%s: unrecognized option `-%c'\n",
00233                        nargv[0], c);
00234           }
00235         return '?';
00236       }
00237     if (temp[1] == ':')
00238       {
00239         if (temp[2] == ':')
00240           {
00241             /* This is an option that accepts an argument optionally.  */
00242             if (*nextchar != 0)
00243               {
00244                 optarg = nextchar;
00245                 optind++;
00246               }
00247             else
00248               optarg = 0;
00249             nextchar = 0;
00250           }
00251         else
00252           {
00253             /* This is an option that requires an argument.  */
00254             if (*nextchar != 0)
00255               {
00256                 optarg = nextchar;
00257                 /* If we end this ARGV-element by taking the rest as an arg,
00258                    we must advance to the next element now.  */
00259                 optind++;
00260               }
00261             else if (optind == nargc)
00262               {
00263                 if (opterr != 0)
00264                   fprintf (stderr, "%s: no argument for `-%c' option\n",
00265                            nargv[0], c);
00266                 c = '?';
00267               }
00268             else
00269               /* We already incremented `optind' once;
00270                  increment it again when taking next ARGV-elt as argument.  */
00271               optarg = nargv[optind++];
00272             nextchar = 0;
00273           }
00274       }
00275     return c;
00276   }
00277 }