libdap  Updated for version 3.20.6
libdap4 is an implementation of OPeNDAP's DAP protocol.
GetOpt.cc
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, 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
31 char *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 
47 char* GetOpt::nextchar = 0;
48 int GetOpt::first_nonopt = 0;
49 int GetOpt::last_nonopt = 0;
50 
51 GetOpt::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 
72 void
73 GetOpt::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[0], &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[0],
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 
142 int
143 GetOpt::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 }