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