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
GetOpt(int argc,char ** argv,const char * optstring)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
exchange(char ** argv)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
operator ()(void)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