libdap
Updated for version 3.17.0
|
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 }