libdap Updated for version 3.20.11
libdap4 is an implementation of OPeNDAP's DAP protocol.
GetOpt.cc
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, 59 Temple Place - Fifth Floor, Boston, MA 02110-1301, USA.
17*/
18
19#include "config.h"
20
21/* AIX requires the alloca decl to be the first thing in the file. */
22#ifdef __GNUC__
23#define alloca __builtin_alloca
24#elif defined(sparc)
25#include <alloca.h>
26#elif defined(_AIX)
27#pragma alloca
28#elif defined(WIN32)
29#include <malloc.h>
30#else
31char *alloca ();
32#endif
33
34#include <vector>
35
36#ifdef HAVE_UNISTD_H
37#include <unistd.h>
38#endif
39#include <cstdio>
40#include <cstring> // Added these. 10/20/98 jhrg
41#include <cstdlib>
42
43#include "GetOpt.h"
44
45//#include <string.h>
46
47char* GetOpt::nextchar = 0;
48int GetOpt::first_nonopt = 0;
49int GetOpt::last_nonopt = 0;
50
51GetOpt::GetOpt (int argc, char **argv, const char *optstring)
52 :opterr (1), nargc (argc), nargv (argv), noptstring (optstring)
53{
54 /* Initialize the internal data when the first call is made.
55 Start processing options with ARGV-element 1 (since ARGV-element 0
56 is the program name); the sequence of previously skipped
57 non-option ARGV-elements is empty. */
58
59 first_nonopt = last_nonopt = optind = 1;
60 optarg = nextchar = 0;
61
62 /* Determine how to handle the ordering of options and nonoptions. */
63
64 if (optstring[0] == '-')
65 ordering = RETURN_IN_ORDER;
66 else if (getenv ("_POSIX_OPTION_ORDER") != 0)
67 ordering = REQUIRE_ORDER;
68 else
69 ordering = PERMUTE;
70}
71
72void
73GetOpt::exchange (char **argv)
74{
75 int nonopts_size = (last_nonopt - first_nonopt) * sizeof(char *);
76 /* char **temp = (char **) alloca (nonopts_size); */
77 /* char **temp = (char **)malloc(nonopts_size); */
78 std::vector<char> temp(nonopts_size);
79
80 /* Interchange the two blocks of data in argv. */
81
82 memcpy (temp.data(), &argv[first_nonopt], nonopts_size);
83
84 /* valgrind complains about this because in some cases the memory areas
85 overlap. I switched to memmove. See the memcpy & memmove man pages.
86 02/12/04 jhrg */
87#if 0
88 memcpy (&argv[first_nonopt], &argv[last_nonopt],
89 (optind - last_nonopt) * sizeof (char *));
90#endif
91 memmove (&argv[first_nonopt], &argv[last_nonopt],
92 (optind - last_nonopt) * sizeof (char *));
93
94 memcpy (&argv[first_nonopt + optind - last_nonopt], temp.data(),
95 nonopts_size);
96
97 /* Update records for the slots the non-options now occupy. */
98
99 first_nonopt += (optind - last_nonopt);
100 last_nonopt = optind;
101
102 //free(temp);
103}
104
105/* Scan elements of ARGV (whose length is ARGC) for option characters
106 given in OPTSTRING.
107
108 If an element of ARGV starts with '-', and is not exactly "-" or "--",
109 then it is an option element. The characters of this element
110 (aside from the initial '-') are option characters. If `getopt'
111 is called repeatedly, it returns successively each of theoption characters
112 from each of the option elements.
113
114 If `getopt' finds another option character, it returns that character,
115 updating `optind' and `nextchar' so that the next call to `getopt' can
116 resume the scan with the following option character or ARGV-element.
117
118 If there are no more option characters, `getopt' returns `EOF'.
119 Then `optind' is the index in ARGV of the first ARGV-element
120 that is not an option. (The ARGV-elements have been permuted
121 so that those that are not options now come last.)
122
123 OPTSTRING is a string containing the legitimate option characters.
124 A colon in OPTSTRING means that the previous character is an option
125 that wants an argument. The argument is taken from the rest of the
126 current ARGV-element, or from the following ARGV-element,
127 and returned in `optarg'.
128
129 If an option character is seen that is not listed in OPTSTRING,
130 return '?' after printing an error message. If you set `opterr' to
131 zero, the error message is suppressed but we still return '?'.
132
133 If a char in OPTSTRING is followed by a colon, that means it wants an arg,
134 so the following text in the same ARGV-element, or the text of the following
135 ARGV-element, is returned in `optarg. Two colons mean an option that
136 wants an optional arg; if there is text in the current ARGV-element,
137 it is returned in `optarg'.
138
139 If OPTSTRING starts with `-', it requests a different method of handling the
140 non-option ARGV-elements. See the comments about RETURN_IN_ORDER, above. */
141
142int
143GetOpt::operator () (void)
144{
145 if (nextchar == 0 || *nextchar == 0)
146 {
147 if (ordering == PERMUTE)
148 {
149 /* If we have just processed some options following some non-options,
150 exchange them so that the options come first. */
151
152 if (first_nonopt != last_nonopt && last_nonopt != optind)
153 exchange (nargv);
154 else if (last_nonopt != optind)
155 first_nonopt = optind;
156
157 /* Now skip any additional non-options
158 and extend the range of non-options previously skipped. */
159
160 while (optind < nargc
161 && (nargv[optind][0] != '-'
162 || nargv[optind][1] == 0))
163 optind++;
164 last_nonopt = optind;
165 }
166
167 /* Special ARGV-element `--' means premature end of options.
168 Skip it like a null option,
169 then exchange with previous non-options as if it were an option,
170 then skip everything else like a non-option. */
171
172 if (optind != nargc && !strcmp (nargv[optind], "--"))
173 {
174 optind++;
175
176 if (first_nonopt != last_nonopt && last_nonopt != optind)
177 exchange (nargv);
178 else if (first_nonopt == last_nonopt)
179 first_nonopt = optind;
180 last_nonopt = nargc;
181
182 optind = nargc;
183 }
184
185 /* If we have done all the ARGV-elements, stop the scan
186 and back over any non-options that we skipped and permuted. */
187
188 if (optind == nargc)
189 {
190 /* Set the next-arg-index to point at the non-options
191 that we previously skipped, so the caller will digest them. */
192 if (first_nonopt != last_nonopt)
193 optind = first_nonopt;
194 return EOF;
195 }
196
197 /* If we have come to a non-option and did not permute it,
198 either stop the scan or describe it to the caller and pass it by. */
199
200 if (nargv[optind][0] != '-' || nargv[optind][1] == 0)
201 {
202 if (ordering == REQUIRE_ORDER)
203 return EOF;
204 optarg = nargv[optind++];
205 return 0;
206 }
207
208 /* We have found another option-ARGV-element.
209 Start decoding its characters. */
210
211 nextchar = nargv[optind] + 1;
212 }
213
214 /* Look at and handle the next option-character. */
215
216 {
217 char c = *nextchar++;
218 char *temp = (char *) strchr (noptstring, c);
219
220 /* Increment `optind' when we start to process its last character. */
221 if (*nextchar == 0)
222 optind++;
223
224 if (temp == 0 || c == ':')
225 {
226 if (opterr != 0)
227 {
228 if (c < 040 || c >= 0177)
229 fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
230 nargv[0], c);
231 else
232 fprintf (stderr, "%s: unrecognized option `-%c'\n",
233 nargv[0], c);
234 }
235 return '?';
236 }
237 if (temp[1] == ':')
238 {
239 if (temp[2] == ':')
240 {
241 /* This is an option that accepts an argument optionally. */
242 if (*nextchar != 0)
243 {
244 optarg = nextchar;
245 optind++;
246 }
247 else
248 optarg = 0;
249 nextchar = 0;
250 }
251 else
252 {
253 /* This is an option that requires an argument. */
254 if (*nextchar != 0)
255 {
256 optarg = nextchar;
257 /* If we end this ARGV-element by taking the rest as an arg,
258 we must advance to the next element now. */
259 optind++;
260 }
261 else if (optind == nargc)
262 {
263 if (opterr != 0)
264 fprintf (stderr, "%s: no argument for `-%c' option\n",
265 nargv[0], c);
266 c = '?';
267 }
268 else
269 /* We already incremented `optind' once;
270 increment it again when taking next ARGV-elt as argument. */
271 optarg = nargv[optind++];
272 nextchar = 0;
273 }
274 }
275 return c;
276 }
277}