1 /* 2 Getopt for GNU. 3 Copyright (C) 1987, 1989 Free Software Foundation, Inc. 4 5 (Modified by Douglas C. Schmidt for use with GNU G++.) 6 This file is part of the GNU C++ Library. This library is free 7 software; you can redistribute it and/or modify it under the terms of 8 the GNU Library General Public License as published by the Free 9 Software Foundation; either version 2 of the License, or (at your 10 option) any later version. This library is distributed in the hope 11 that it will be useful, but WITHOUT ANY WARRANTY; without even the 12 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 13 PURPOSE. See the GNU Library General Public License for more details. 14 You should have received a copy of the GNU Library General Public 15 License along with this library; if not, write to the Free Software 16 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 17 */ 18 19 #ifdef __GNUG__ 20 #pragma implementation 21 #endif 22 /* AIX requires the alloca decl to be the first thing in the file. */ 23 #ifdef __GNUC__ 24 #define alloca alloca 25 #elif defined(sparc) 26 #include <alloca.h> 27 #elif defined(_AIX) 28 #pragma alloca 29 #else 30 char *alloca (); 31 #endif 32 #include <GetOpt.h> 33 34 char* GetOpt::nextchar = 0; 35 int GetOpt::first_nonopt = 0; 36 int GetOpt::last_nonopt = 0; 37 38 GetOpt::GetOpt (int argc, char **argv, const char *optstring) 39 :opterr (1), nargc (argc), nargv (argv), noptstring (optstring) 40 { 41 /* Initialize the internal data when the first call is made. 42 Start processing options with ARGV-element 1 (since ARGV-element 0 43 is the program name); the sequence of previously skipped 44 non-option ARGV-elements is empty. */ 45 46 first_nonopt = last_nonopt = optind = 1; 47 optarg = nextchar = 0; 48 49 /* Determine how to handle the ordering of options and nonoptions. */ 50 51 if (optstring[0] == '-') 52 ordering = RETURN_IN_ORDER; 53 else if (getenv ("_POSIX_OPTION_ORDER") != 0) 54 ordering = REQUIRE_ORDER; 55 else 56 ordering = PERMUTE; 57 } 58 59 void 60 GetOpt::exchange (char **argv) 61 { 62 int nonopts_size 63 = (last_nonopt - first_nonopt) * sizeof (char *); 64 char **temp = (char **) alloca (nonopts_size); 65 66 /* Interchange the two blocks of data in argv. */ 67 68 memcpy (temp, &argv[first_nonopt], nonopts_size); 69 memcpy (&argv[first_nonopt], &argv[last_nonopt], 70 (optind - last_nonopt) * sizeof (char *)); 71 memcpy (&argv[first_nonopt + optind - last_nonopt], temp, 72 nonopts_size); 73 74 /* Update records for the slots the non-options now occupy. */ 75 76 first_nonopt += (optind - last_nonopt); 77 last_nonopt = optind; 78 } 79 80 /* Scan elements of ARGV (whose length is ARGC) for option characters 81 given in OPTSTRING. 82 83 If an element of ARGV starts with '-', and is not exactly "-" or "--", 84 then it is an option element. The characters of this element 85 (aside from the initial '-') are option characters. If `getopt' 86 is called repeatedly, it returns successively each of theoption characters 87 from each of the option elements. 88 89 If `getopt' finds another option character, it returns that character, 90 updating `optind' and `nextchar' so that the next call to `getopt' can 91 resume the scan with the following option character or ARGV-element. 92 93 If there are no more option characters, `getopt' returns `EOF'. 94 Then `optind' is the index in ARGV of the first ARGV-element 95 that is not an option. (The ARGV-elements have been permuted 96 so that those that are not options now come last.) 97 98 OPTSTRING is a string containing the legitimate option characters. 99 A colon in OPTSTRING means that the previous character is an option 100 that wants an argument. The argument is taken from the rest of the 101 current ARGV-element, or from the following ARGV-element, 102 and returned in `optarg'. 103 104 If an option character is seen that is not listed in OPTSTRING, 105 return '?' after printing an error message. If you set `opterr' to 106 zero, the error message is suppressed but we still return '?'. 107 108 If a char in OPTSTRING is followed by a colon, that means it wants an arg, 109 so the following text in the same ARGV-element, or the text of the following 110 ARGV-element, is returned in `optarg. Two colons mean an option that 111 wants an optional arg; if there is text in the current ARGV-element, 112 it is returned in `optarg'. 113 114 If OPTSTRING starts with `-', it requests a different method of handling the 115 non-option ARGV-elements. See the comments about RETURN_IN_ORDER, above. */ 116 117 int 118 GetOpt::operator () (void) 119 { 120 if (nextchar == 0 || *nextchar == 0) 121 { 122 if (ordering == PERMUTE) 123 { 124 /* If we have just processed some options following some non-options, 125 exchange them so that the options come first. */ 126 127 if (first_nonopt != last_nonopt && last_nonopt != optind) 128 exchange (nargv); 129 else if (last_nonopt != optind) 130 first_nonopt = optind; 131 132 /* Now skip any additional non-options 133 and extend the range of non-options previously skipped. */ 134 135 while (optind < nargc 136 && (nargv[optind][0] != '-' 137 || nargv[optind][1] == 0)) 138 optind++; 139 last_nonopt = optind; 140 } 141 142 /* Special ARGV-element `--' means premature end of options. 143 Skip it like a null option, 144 then exchange with previous non-options as if it were an option, 145 then skip everything else like a non-option. */ 146 147 if (optind != nargc && !strcmp (nargv[optind], "--")) 148 { 149 optind++; 150 151 if (first_nonopt != last_nonopt && last_nonopt != optind) 152 exchange (nargv); 153 else if (first_nonopt == last_nonopt) 154 first_nonopt = optind; 155 last_nonopt = nargc; 156 157 optind = nargc; 158 } 159 160 /* If we have done all the ARGV-elements, stop the scan 161 and back over any non-options that we skipped and permuted. */ 162 163 if (optind == nargc) 164 { 165 /* Set the next-arg-index to point at the non-options 166 that we previously skipped, so the caller will digest them. */ 167 if (first_nonopt != last_nonopt) 168 optind = first_nonopt; 169 return EOF; 170 } 171 172 /* If we have come to a non-option and did not permute it, 173 either stop the scan or describe it to the caller and pass it by. */ 174 175 if (nargv[optind][0] != '-' || nargv[optind][1] == 0) 176 { 177 if (ordering == REQUIRE_ORDER) 178 return EOF; 179 optarg = nargv[optind++]; 180 return 0; 181 } 182 183 /* We have found another option-ARGV-element. 184 Start decoding its characters. */ 185 186 nextchar = nargv[optind] + 1; 187 } 188 189 /* Look at and handle the next option-character. */ 190 191 { 192 char c = *nextchar++; 193 char *temp = (char *) strchr (noptstring, c); 194 195 /* Increment `optind' when we start to process its last character. */ 196 if (*nextchar == 0) 197 optind++; 198 199 if (temp == 0 || c == ':') 200 { 201 if (opterr != 0) 202 { 203 if (c < 040 || c >= 0177) 204 fprintf (stderr, "%s: unrecognized option, character code 0%o\n", 205 nargv[0], c); 206 else 207 fprintf (stderr, "%s: unrecognized option `-%c'\n", 208 nargv[0], c); 209 } 210 return '?'; 211 } 212 if (temp[1] == ':') 213 { 214 if (temp[2] == ':') 215 { 216 /* This is an option that accepts an argument optionally. */ 217 if (*nextchar != 0) 218 { 219 optarg = nextchar; 220 optind++; 221 } 222 else 223 optarg = 0; 224 nextchar = 0; 225 } 226 else 227 { 228 /* This is an option that requires an argument. */ 229 if (*nextchar != 0) 230 { 231 optarg = nextchar; 232 /* If we end this ARGV-element by taking the rest as an arg, 233 we must advance to the next element now. */ 234 optind++; 235 } 236 else if (optind == nargc) 237 { 238 if (opterr != 0) 239 fprintf (stderr, "%s: no argument for `-%c' option\n", 240 nargv[0], c); 241 c = '?'; 242 } 243 else 244 /* We already incremented `optind' once; 245 increment it again when taking next ARGV-elt as argument. */ 246 optarg = nargv[optind++]; 247 nextchar = 0; 248 } 249 } 250 return c; 251 } 252 } 253