Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
getopt_long_W32.cpp
1 // must be first:
2 //#include "precompiled.h"
3 
4 /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
5 /* $FreeBSD: src/lib/libc/stdlib/getopt_long.c,v 1.2 2002/10/16 22:18:42 alfred Exp $ */
6 
7 /*-
8  * Copyright (c) 2000 The NetBSD Foundation, Inc.
9  * All rights reserved.
10  *
11  * This code is derived from software contributed to The NetBSD Foundation
12  * by Dieter Baron and Thomas Klausner.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  * notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  * notice, this list of conditions and the following disclaimer in the
21  * documentation and/or other materials provided with the distribution.
22  * 3. All advertising materials mentioning features or use of this software
23  * must display the following acknowledgement:
24  * This product includes software developed by the NetBSD
25  * Foundation, Inc. and its contributors.
26  * 4. Neither the name of The NetBSD Foundation nor the names of its
27  * contributors may be used to endorse or promote products derived
28  * from this software without specific prior written permission.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
31  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
32  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
34  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40  * POSSIBILITY OF SUCH DAMAGE.
41  */
42 
43 #define _CRT_SECURE_NO_DEPRECATE
44 #include <stdio.h>
45 
46 #include "getopt_W32.h"
47 #include <stdlib.h>
48 #include <string.h>
49 
50 #ifdef _WIN32
51 
52 /* Windows needs warnx(). We change the definition though:
53  * 1. (another) global is defined, opterrmsg, which holds the error message
54  * 2. errors are always printed out on stderr w/o the program name
55  * Note that opterrmsg always gets set no matter what opterr is set to. The
56  * error message will not be printed if opterr is 0 as usual.
57  */
58 
59 #include <stdio.h>
60 #include <stdarg.h>
61 
62 extern char opterrmsg[128];
63 char opterrmsg[128]; /* last error message is stored here */
64 
65 static void warnx(int print_error, const char *fmt, ...)
66 {
67  va_list ap;
68  va_start(ap, fmt);
69  if (fmt != NULL)
70  _vsnprintf(opterrmsg, 128, fmt, ap);
71  else
72  opterrmsg[0]='\0';
73  va_end(ap);
74  if (print_error) {
75  fprintf(stderr, opterrmsg);
76  fprintf(stderr, "\n");
77  }
78 }
79 
80 #endif /*_WIN32*/
81 
82 /* not part of the original file */
83 #ifndef _DIAGASSERT
84 # define _DIAGASSERT(X)
85 #endif
86 
87 #if HAVE_CONFIG_H && !HAVE_GETOPT_LONG && !HAVE_DECL_OPTIND
88 # define REPLACE_GETOPT
89 #endif
90 
91 #ifdef REPLACE_GETOPT
92 # ifdef __weak_alias
93  __weak_alias(getopt,_getopt)
94 # endif
95 
96  int opterr = 1; /* if error message should be printed */
97  int optind = 1; /* index into parent argv vector */
98  int optopt = '?'; /* character checked for validity */
99  int optreset; /* reset getopt */
100  char *optarg; /* argument associated with option */
101 #elif HAVE_CONFIG_H && !HAVE_DECL_OPTRESET
102  static int optreset;
103 #endif
104 
105 #ifdef __weak_alias
106 __weak_alias(getopt_long,_getopt_long)
107 #endif
108 
109 #if !HAVE_GETOPT_LONG
110 #define IGNORE_FIRST (*options == '-' || *options == '+')
111 #define PRINT_ERROR ((opterr) && ((*options != ':') \
112  || (IGNORE_FIRST && options[1] != ':')))
113 #define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL)
114 #define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
115 /* XXX: GNU ignores PC if *options == '-' */
116 #define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-')
117 
118 /* return values */
119 #define BADCH (int)'?'
120 #define BADARG ((IGNORE_FIRST && options[1] == ':') \
121  || (*options == ':') ? (int)':' : (int)'?')
122 #define INORDER (int)1
123 
124 #define EMSG ""
125 
126 static int getopt_internal(int, char * const *, const char *);
127 static int gcd(int, int);
128 static void permute_args(int, int, int, char * const *);
129 
130 static char *place = EMSG; /* option letter processing */
131 
132 /* XXX: set optreset to 1 rather than these two */
133 static int nonopt_start = -1; /* first non option argument (for permute) */
134 static int nonopt_end = -1; /* first option after non options (for permute) */
135 
136 /* Error messages */
137 static const char recargchar[] = "option requires an argument -- %c";
138 static const char recargstring[] = "option requires an argument -- %s";
139 static const char ambig[] = "ambiguous option -- %.*s";
140 static const char noarg[] = "option doesn't take an argument -- %.*s";
141 static const char illoptchar[] = "unknown option -- %c";
142 static const char illoptstring[] = "unknown option -- %s";
143 
144 
145 /*
146  * Compute the greatest common divisor of a and b.
147  */
148 static int
149 gcd(int a, int b)
150 {
151  int c;
152 
153  c = a % b;
154  while (c != 0) {
155  a = b;
156  b = c;
157  c = a % b;
158  }
159 
160  return b;
161 }
162 
163 /*
164  * Exchange the block from nonopt_start to nonopt_end with the block
165  * from nonopt_end to opt_end (keeping the same order of arguments
166  * in each block).
167  */
168 static void
169 permute_args(int panonopt_start, int panonopt_end,int opt_end, char * const * nargv)
170 {
171  int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
172  char *swap;
173 
174  _DIAGASSERT(nargv != NULL);
175 
176  /*
177  * compute lengths of blocks and number and size of cycles
178  */
179  nnonopts = panonopt_end - panonopt_start;
180  nopts = opt_end - panonopt_end;
181  ncycle = gcd(nnonopts, nopts);
182  cyclelen = (opt_end - panonopt_start) / ncycle;
183 
184  for (i = 0; i < ncycle; i++) {
185  cstart = panonopt_end+i;
186  pos = cstart;
187  for (j = 0; j < cyclelen; j++) {
188  if (pos >= panonopt_end)
189  pos -= nnonopts;
190  else
191  pos += nopts;
192  swap = nargv[pos];
193  /* LINTED const cast */
194  ((char **) nargv)[pos] = nargv[cstart];
195  /* LINTED const cast */
196  ((char **)nargv)[cstart] = swap;
197  }
198  }
199 }
200 
201 /*
202  * getopt_internal --
203  * Parse argc/argv argument vector. Called by user level routines.
204  * Returns -2 if -- is found (can be long option or end of options marker).
205  */
206 static
207 int getopt_internal (int nargc, char * const *nargv, const char *options)
208 {
209  char *oli; /* option letter list index */
210  int optchar;
211 
212  _DIAGASSERT(nargv != NULL);
213  _DIAGASSERT(options != NULL);
214 
215  optarg = NULL;
216 
217  /*
218  * XXX Some programs (like rsyncd) expect to be able to
219  * XXX re-initialize optind to 0 and have getopt_long(3)
220  * XXX properly function again. Work around this braindamage.
221  */
222  if (optind == 0)
223  optind = 1;
224 
225  if (optreset)
226  nonopt_start = nonopt_end = -1;
227 start:
228  if (optreset || !*place) { /* update scanning pointer */
229  optreset = 0;
230  if (optind >= nargc) { /* end of argument vector */
231  place = EMSG;
232  if (nonopt_end != -1) {
233  /* do permutation, if we have to */
234  permute_args(nonopt_start, nonopt_end,
235  optind, nargv);
236  optind -= nonopt_end - nonopt_start;
237  }
238  else if (nonopt_start != -1) {
239  /*
240  * If we skipped non-options, set optind
241  * to the first of them.
242  */
243  optind = nonopt_start;
244  }
245  nonopt_start = nonopt_end = -1;
246  return -1;
247  }
248  if ((*(place = nargv[optind]) != '-')
249  || (place[1] == '\0')) { /* found non-option */
250  place = EMSG;
251  if (IN_ORDER) {
252  /*
253  * GNU extension:
254  * return non-option as argument to option 1
255  */
256  optarg = nargv[optind++];
257  return INORDER;
258  }
259  if (!PERMUTE) {
260  /*
261  * if no permutation wanted, stop parsing
262  * at first non-option
263  */
264  return -1;
265  }
266  /* do permutation */
267  if (nonopt_start == -1)
268  nonopt_start = optind;
269  else if (nonopt_end != -1) {
270  permute_args(nonopt_start, nonopt_end,
271  optind, nargv);
272  nonopt_start = optind -
273  (nonopt_end - nonopt_start);
274  nonopt_end = -1;
275  }
276  optind++;
277  /* process next argument */
278  goto start;
279  }
280  if (nonopt_start != -1 && nonopt_end == -1)
281  nonopt_end = optind;
282  if (place[1] && *++place == '-') { /* found "--" */
283  place++;
284  return -2;
285  }
286  }
287  if ((optchar = (int)*place++) == (int)':' ||
288  (oli = (char*)strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
289  /* option letter unknown or ':' */
290  if (!*place)
291  ++optind;
292 #ifndef _WIN32
293  if (PRINT_ERROR)
294  warnx(illoptchar, optchar);
295 #else
296  warnx(PRINT_ERROR, illoptchar, optchar);
297 #endif
298  optopt = optchar;
299  return BADCH;
300  }
301  if (optchar == 'W' && oli[1] == ';') { /* -W long-option */
302  /* XXX: what if no long options provided (called by getopt)? */
303  if (*place)
304  return -2;
305 
306  if (++optind >= nargc) { /* no arg */
307  place = EMSG;
308 #ifndef _WIN32
309  if (PRINT_ERROR)
310  warnx(recargchar, optchar);
311 #else
312  warnx(PRINT_ERROR, recargchar, optchar);
313 #endif
314  optopt = optchar;
315  return BADARG;
316  } else /* white space */
317  place = nargv[optind];
318  /*
319  * Handle -W arg the same as --arg (which causes getopt to
320  * stop parsing).
321  */
322  return -2;
323  }
324  if (*++oli != ':') { /* doesn't take argument */
325  if (!*place)
326  ++optind;
327  } else { /* takes (optional) argument */
328  optarg = NULL;
329  if (*place) /* no white space */
330  optarg = place;
331  /* XXX: disable test for :: if PC? (GNU doesn't) */
332  else if (oli[1] != ':') { /* arg not optional */
333  if (++optind >= nargc) { /* no arg */
334  place = EMSG;
335 #ifndef _WIN32
336  if (PRINT_ERROR)
337  warnx(recargchar, optchar);
338 #else
339  warnx(PRINT_ERROR, recargchar, optchar);
340 #endif
341  optopt = optchar;
342  return BADARG;
343  } else
344  optarg = nargv[optind];
345  }
346  place = EMSG;
347  ++optind;
348  }
349  /* dump back option letter */
350  return optchar;
351 }
352 
353 #ifdef REPLACE_GETOPT
354 /*
355  * getopt --
356  * Parse argc/argv argument vector.
357  *
358  * [eventually this will replace the real getopt]
359  */
360 int
361 BIASCommon_EXPORT getopt(nargc, nargv, options)
362  int nargc;
363  char * const *nargv;
364  const char *options;
365 {
366  int retval;
367 
368  _DIAGASSERT(nargv != NULL);
369  _DIAGASSERT(options != NULL);
370 
371  if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
372  ++optind;
373  /*
374  * We found an option (--), so if we skipped non-options,
375  * we have to permute.
376  */
377  if (nonopt_end != -1) {
378  permute_args(nonopt_start, nonopt_end, optind,
379  nargv);
380  optind -= nonopt_end - nonopt_start;
381  }
382  nonopt_start = nonopt_end = -1;
383  retval = -1;
384  }
385  return retval;
386 }
387 #endif
388 
389 /*
390  * getopt_long --
391  * Parse argc/argv argument vector.
392  */
393 int
394 getopt_long(int nargc, char * const * nargv, const char *options,
395  const struct option *long_options, int *idx)
396 {
397  int retval;
398 
399  _DIAGASSERT(nargv != NULL);
400  _DIAGASSERT(options != NULL);
401  _DIAGASSERT(long_options != NULL);
402  /* idx may be NULL */
403 
404  if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
405  char *current_argv, *has_equal;
406  size_t current_argv_len;
407  int i, match;
408 
409  current_argv = place;
410  match = -1;
411 
412  optind++;
413  place = EMSG;
414 
415  if (*current_argv == '\0') { /* found "--" */
416  /*
417  * We found an option (--), so if we skipped
418  * non-options, we have to permute.
419  */
420  if (nonopt_end != -1) {
421  permute_args(nonopt_start, nonopt_end,
422  optind, nargv);
423  optind -= nonopt_end - nonopt_start;
424  }
425  nonopt_start = nonopt_end = -1;
426  return -1;
427  }
428  if ((has_equal = strchr(current_argv, '=')) != NULL) {
429  /* argument found (--option=arg) */
430  current_argv_len = has_equal - current_argv;
431  has_equal++;
432  } else
433  current_argv_len = strlen(current_argv);
434 
435  for (i = 0; long_options[i].name; i++) {
436  /* find matching long option */
437  if (strncmp(current_argv, long_options[i].name,
438  current_argv_len))
439  continue;
440 
441  if (strlen(long_options[i].name) ==
442  (unsigned)current_argv_len) {
443  /* exact match */
444  match = i;
445  break;
446  }
447  if (match == -1) /* partial match */
448  match = i;
449  else {
450  /* ambiguous abbreviation */
451 #ifndef _WIN32
452  if (PRINT_ERROR)
453  warnx(ambig, (int)current_argv_len,
454  current_argv);
455 #else
456  warnx(PRINT_ERROR, ambig, (int)current_argv_len,
457  current_argv);
458 #endif
459  optopt = 0;
460  return BADCH;
461  }
462  }
463  if (match != -1) { /* option found */
464  if (long_options[match].has_arg == no_argument
465  && has_equal) {
466 #ifndef _WIN32
467  if (PRINT_ERROR)
468  warnx(noarg, (int)current_argv_len,
469  current_argv);
470 #else
471  warnx(PRINT_ERROR, noarg, (int)current_argv_len,
472  current_argv);
473 #endif
474  /*
475  * XXX: GNU sets optopt to val regardless of
476  * flag
477  */
478  if (long_options[match].flag == NULL)
479  optopt = long_options[match].val;
480  else
481  optopt = 0;
482  return BADARG;
483  }
484  if (long_options[match].has_arg == required_argument ||
485  long_options[match].has_arg == optional_argument) {
486  if (has_equal)
487  optarg = has_equal;
488  else if (long_options[match].has_arg ==
489  required_argument) {
490  /*
491  * optional argument doesn't use
492  * next nargv
493  */
494  optarg = nargv[optind++];
495  }
496  }
497  if ((long_options[match].has_arg == required_argument)
498  && (optarg == NULL)) {
499  /*
500  * Missing argument; leading ':'
501  * indicates no error should be generated
502  */
503 #ifndef _WIN32
504  if (PRINT_ERROR)
505  warnx(recargstring, current_argv);
506 #else
507  warnx(PRINT_ERROR, recargstring, current_argv);
508 #endif
509  /*
510  * XXX: GNU sets optopt to val regardless
511  * of flag
512  */
513  if (long_options[match].flag == NULL)
514  optopt = long_options[match].val;
515  else
516  optopt = 0;
517  --optind;
518  return BADARG;
519  }
520  } else { /* unknown option */
521 #ifndef _WIN32
522  if (PRINT_ERROR)
523  warnx(illoptstring, current_argv);
524 #else
525  warnx(PRINT_ERROR, illoptstring, current_argv);
526 #endif
527  optopt = 0;
528  return BADCH;
529  }
530  if (long_options[match].flag) {
531  *long_options[match].flag = long_options[match].val;
532  retval = 0;
533  } else
534  retval = long_options[match].val;
535  if (idx)
536  *idx = match;
537  }
538  return retval;
539 }
540 #endif /* !GETOPT_LONG */
int val
Definition: getopt_W32.h:77
const char * name
Definition: getopt_W32.h:68
int * flag
Definition: getopt_W32.h:75