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