DPsim
getopt.h
1 #ifndef __GETOPT_H__
11 /*
12  * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
13  *
14  * Permission to use, copy, modify, and distribute this software for any
15  * purpose with or without fee is hereby granted, provided that the above
16  * copyright notice and this permission notice appear in all copies.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
19  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
20  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
21  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
23  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
24  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25  *
26  * Sponsored in part by the Defense Advanced Research Projects
27  * Agency (DARPA) and Air Force Research Laboratory, Air Force
28  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
29  */
30 /*-
31  * Copyright (c) 2000 The NetBSD Foundation, Inc.
32  * All rights reserved.
33  *
34  * This code is derived from software contributed to The NetBSD Foundation
35  * by Dieter Baron and Thomas Klausner.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  * notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  * notice, this list of conditions and the following disclaimer in the
44  * documentation and/or other materials provided with the distribution.
45  *
46  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
47  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
48  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
50  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
51  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
52  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
53  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
56  * POSSIBILITY OF SUCH DAMAGE.
57  */
58 
59 #pragma warning(disable : 4996)
60 
61 #define __GETOPT_H__
62 
63 /* All the headers include this file. */
64 #include <crtdefs.h>
65 #include <errno.h>
66 #include <stdarg.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <windows.h>
71 
72 #ifdef __cplusplus
73 extern "C" {
74 #endif
75 
76 #define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
77 
78 #ifdef REPLACE_GETOPT
79 int opterr = 1; /* if error message should be printed */
80 int optind = 1; /* index into parent argv vector */
81 int optopt = '?'; /* character checked for validity */
82 #undef optreset /* see getopt.h */
83 #define optreset __mingw_optreset
84 int optreset; /* reset getopt */
85 char *optarg; /* argument associated with option */
86 #endif
87 
88 //extern int optind; /* index of first non-option in argv */
89 //extern int optopt; /* single option character, as parsed */
90 //extern int opterr; /* flag to enable built-in diagnostics... */
91 // /* (user may set to zero, to suppress) */
92 //
93 //extern char *optarg; /* pointer to argument of current option */
94 
95 #define PRINT_ERROR ((opterr) && (*options != ':'))
96 
97 #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
98 #define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
99 #define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
100 
101 /* return values */
102 #define BADCH (int)'?'
103 #define BADARG ((*options == ':') ? (int)':' : (int)'?')
104 #define INORDER (int)1
105 
106 #ifndef __CYGWIN__
107 #define __progname __argv[0]
108 #else
109 extern char __declspec(dllimport) * __progname;
110 #endif
111 
112 #ifdef __CYGWIN__
113 static char EMSG[] = "";
114 #else
115 #define EMSG ""
116 #endif
117 
118 static int getopt_internal(int, char *const *, const char *,
119  const struct option *, int *, int);
120 static int parse_long_options(char *const *, const char *,
121  const struct option *, int *, int);
122 static int gcd(int, int);
123 static void permute_args(int, int, int, char *const *);
124 
125 static char *place = EMSG; /* option letter processing */
126 
127 /* XXX: set optreset to 1 rather than these two */
128 static int nonopt_start = -1; /* first non option argument (for permute) */
129 static int nonopt_end = -1; /* first option after non options (for permute) */
130 
131 /* Error messages */
132 static const char recargchar[] = "option requires an argument -- %c";
133 static const char recargstring[] = "option requires an argument -- %s";
134 static const char ambig[] = "ambiguous option -- %.*s";
135 static const char noarg[] = "option doesn't take an argument -- %.*s";
136 static const char illoptchar[] = "unknown option -- %c";
137 static const char illoptstring[] = "unknown option -- %s";
138 
139 static void _vwarnx(const char *fmt, va_list ap) {
140  (void)fprintf(stderr, "%s: ", __progname);
141  if (fmt != NULL)
142  (void)vfprintf(stderr, fmt, ap);
143  (void)fprintf(stderr, "\n");
144 }
145 
146 static void warnx(const char *fmt, ...) {
147  va_list ap;
148  va_start(ap, fmt);
149  _vwarnx(fmt, ap);
150  va_end(ap);
151 }
152 
153 /*
154  * Compute the greatest common divisor of a and b.
155  */
156 static int gcd(int a, int b) {
157  int c;
158 
159  c = a % b;
160  while (c != 0) {
161  a = b;
162  b = c;
163  c = a % b;
164  }
165 
166  return (b);
167 }
168 
169 /*
170  * Exchange the block from nonopt_start to nonopt_end with the block
171  * from nonopt_end to opt_end (keeping the same order of arguments
172  * in each block).
173  */
174 static void permute_args(int panonopt_start, int panonopt_end, int opt_end,
175  char *const *nargv) {
176  int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
177  char *swap;
178 
179  /*
180  * compute lengths of blocks and number and size of cycles
181  */
182  nnonopts = panonopt_end - panonopt_start;
183  nopts = opt_end - panonopt_end;
184  ncycle = gcd(nnonopts, nopts);
185  cyclelen = (opt_end - panonopt_start) / ncycle;
186 
187  for (i = 0; i < ncycle; i++) {
188  cstart = panonopt_end + i;
189  pos = cstart;
190  for (j = 0; j < cyclelen; j++) {
191  if (pos >= panonopt_end)
192  pos -= nnonopts;
193  else
194  pos += nopts;
195  swap = nargv[pos];
196  /* LINTED const cast */
197  ((char **)nargv)[pos] = nargv[cstart];
198  /* LINTED const cast */
199  ((char **)nargv)[cstart] = swap;
200  }
201  }
202 }
203 
204 #ifdef REPLACE_GETOPT
205 /*
206  * getopt --
207  * Parse argc/argv argument vector.
208  *
209  * [eventually this will replace the BSD getopt]
210  */
211 int getopt(int nargc, char *const *nargv, const char *options) {
212 
213  /*
214  * We don't pass FLAG_PERMUTE to getopt_internal() since
215  * the BSD getopt(3) (unlike GNU) has never done this.
216  *
217  * Furthermore, since many privileged programs call getopt()
218  * before dropping privileges it makes sense to keep things
219  * as simple (and bug-free) as possible.
220  */
221  return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
222 }
223 #endif /* REPLACE_GETOPT */
224 
225 //extern int getopt(int nargc, char * const *nargv, const char *options);
226 
227 #ifdef _BSD_SOURCE
228 /*
229  * BSD adds the non-standard `optreset' feature, for reinitialisation
230  * of `getopt' parsing. We support this feature, for applications which
231  * proclaim their BSD heritage, before including this header; however,
232  * to maintain portability, developers are advised to avoid it.
233  */
234 #define optreset __mingw_optreset
235 extern int optreset;
236 #endif
237 #ifdef __cplusplus
238 }
239 #endif
240 /*
241  * POSIX requires the `getopt' API to be specified in `unistd.h';
242  * thus, `unistd.h' includes this header. However, we do not want
243  * to expose the `getopt_long' or `getopt_long_only' APIs, when
244  * included in this manner. Thus, close the standard __GETOPT_H__
245  * declarations block, and open an additional __GETOPT_LONG_H__
246  * specific block, only when *not* __UNISTD_H_SOURCED__, in which
247  * to declare the extended API.
248  */
249 #endif /* !defined(__GETOPT_H__) */
250 
251 #if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
252 #define __GETOPT_LONG_H__
253 
254 #ifdef __cplusplus
255 extern "C" {
256 #endif
257 
258 struct option /* specification for a long form option... */
259 {
260  const char *name; /* option name, without leading hyphens */
261  int has_arg; /* does it take an argument? */
262  int *flag; /* where to save its status, or NULL */
263  int val; /* its associated status value */
264 };
265 
266 enum /* permitted values for its `has_arg' field... */
267 {
268  no_argument = 0, /* option never takes an argument */
269  required_argument, /* option always requires an argument */
270  optional_argument /* option may take an argument */
271 };
272 
273 /*
274  * parse_long_options --
275  * Parse long options in argc/argv argument vector.
276  * Returns -1 if short_too is set and the option does not match long_options.
277  */
278 static int parse_long_options(char *const *nargv, const char *options,
279  const struct option *long_options, int *idx,
280  int short_too) {
281  char *current_argv, *has_equal;
282  size_t current_argv_len;
283  int i, ambiguous, match;
284 
285 #define IDENTICAL_INTERPRETATION(_x, _y) \
286  (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
287  long_options[(_x)].flag == long_options[(_y)].flag && \
288  long_options[(_x)].val == long_options[(_y)].val)
289 
290  current_argv = place;
291  match = -1;
292  ambiguous = 0;
293 
294  optind++;
295 
296  if ((has_equal = strchr(current_argv, '=')) != NULL) {
297  /* argument found (--option=arg) */
298  current_argv_len = has_equal - current_argv;
299  has_equal++;
300  } else
301  current_argv_len = strlen(current_argv);
302 
303  for (i = 0; long_options[i].name; i++) {
304  /* find matching long option */
305  if (strncmp(current_argv, long_options[i].name, current_argv_len))
306  continue;
307 
308  if (strlen(long_options[i].name) == current_argv_len) {
309  /* exact match */
310  match = i;
311  ambiguous = 0;
312  break;
313  }
314  /*
315  * If this is a known short option, don't allow
316  * a partial match of a single character.
317  */
318  if (short_too && current_argv_len == 1)
319  continue;
320 
321  if (match == -1) /* partial match */
322  match = i;
323  else if (!IDENTICAL_INTERPRETATION(i, match))
324  ambiguous = 1;
325  }
326  if (ambiguous) {
327  /* ambiguous abbreviation */
328  if (PRINT_ERROR)
329  warnx(ambig, (int)current_argv_len, current_argv);
330  optopt = 0;
331  return (BADCH);
332  }
333  if (match != -1) { /* option found */
334  if (long_options[match].has_arg == no_argument && has_equal) {
335  if (PRINT_ERROR)
336  warnx(noarg, (int)current_argv_len, current_argv);
337  /*
338  * XXX: GNU sets optopt to val regardless of flag
339  */
340  if (long_options[match].flag == NULL)
341  optopt = long_options[match].val;
342  else
343  optopt = 0;
344  return (BADARG);
345  }
346  if (long_options[match].has_arg == required_argument ||
347  long_options[match].has_arg == optional_argument) {
348  if (has_equal)
349  optarg = has_equal;
350  else if (long_options[match].has_arg == required_argument) {
351  /*
352  * optional argument doesn't use next nargv
353  */
354  optarg = nargv[optind++];
355  }
356  }
357  if ((long_options[match].has_arg == required_argument) &&
358  (optarg == NULL)) {
359  /*
360  * Missing argument; leading ':' indicates no error
361  * should be generated.
362  */
363  if (PRINT_ERROR)
364  warnx(recargstring, current_argv);
365  /*
366  * XXX: GNU sets optopt to val regardless of flag
367  */
368  if (long_options[match].flag == NULL)
369  optopt = long_options[match].val;
370  else
371  optopt = 0;
372  --optind;
373  return (BADARG);
374  }
375  } else { /* unknown option */
376  if (short_too) {
377  --optind;
378  return (-1);
379  }
380  if (PRINT_ERROR)
381  warnx(illoptstring, current_argv);
382  optopt = 0;
383  return (BADCH);
384  }
385  if (idx)
386  *idx = match;
387  if (long_options[match].flag) {
388  *long_options[match].flag = long_options[match].val;
389  return (0);
390  } else
391  return (long_options[match].val);
392 #undef IDENTICAL_INTERPRETATION
393 }
394 
395 /*
396  * getopt_internal --
397  * Parse argc/argv argument vector. Called by user level routines.
398  */
399 static int getopt_internal(int nargc, char *const *nargv, const char *options,
400  const struct option *long_options, int *idx,
401  int flags) {
402  char *oli; /* option letter list index */
403  int optchar, short_too;
404  static int posixly_correct = -1;
405 
406  if (options == NULL)
407  return (-1);
408 
409  /*
410  * XXX Some GNU programs (like cvs) set optind to 0 instead of
411  * XXX using optreset. Work around this braindamage.
412  */
413  if (optind == 0)
414  optind = optreset = 1;
415 
416  /*
417  * Disable GNU extensions if POSIXLY_CORRECT is set or options
418  * string begins with a '+'.
419  *
420  * CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
421  * optreset != 0 for GNU compatibility.
422  */
423  if (posixly_correct == -1 || optreset != 0)
424  posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
425  if (*options == '-')
426  flags |= FLAG_ALLARGS;
427  else if (posixly_correct || *options == '+')
428  flags &= ~FLAG_PERMUTE;
429  if (*options == '+' || *options == '-')
430  options++;
431 
432  optarg = NULL;
433  if (optreset)
434  nonopt_start = nonopt_end = -1;
435 start:
436  if (optreset || !*place) { /* update scanning pointer */
437  optreset = 0;
438  if (optind >= nargc) { /* end of argument vector */
439  place = EMSG;
440  if (nonopt_end != -1) {
441  /* do permutation, if we have to */
442  permute_args(nonopt_start, nonopt_end, optind, nargv);
443  optind -= nonopt_end - nonopt_start;
444  } else if (nonopt_start != -1) {
445  /*
446  * If we skipped non-options, set optind
447  * to the first of them.
448  */
449  optind = nonopt_start;
450  }
451  nonopt_start = nonopt_end = -1;
452  return (-1);
453  }
454  if (*(place = nargv[optind]) != '-' ||
455  (place[1] == '\0' && strchr(options, '-') == NULL)) {
456  place = EMSG; /* found non-option */
457  if (flags & FLAG_ALLARGS) {
458  /*
459  * GNU extension:
460  * return non-option as argument to option 1
461  */
462  optarg = nargv[optind++];
463  return (INORDER);
464  }
465  if (!(flags & FLAG_PERMUTE)) {
466  /*
467  * If no permutation wanted, stop parsing
468  * at first non-option.
469  */
470  return (-1);
471  }
472  /* do permutation */
473  if (nonopt_start == -1)
474  nonopt_start = optind;
475  else if (nonopt_end != -1) {
476  permute_args(nonopt_start, nonopt_end, optind, nargv);
477  nonopt_start = optind - (nonopt_end - nonopt_start);
478  nonopt_end = -1;
479  }
480  optind++;
481  /* process next argument */
482  goto start;
483  }
484  if (nonopt_start != -1 && nonopt_end == -1)
485  nonopt_end = optind;
486 
487  /*
488  * If we have "-" do nothing, if "--" we are done.
489  */
490  if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
491  optind++;
492  place = EMSG;
493  /*
494  * We found an option (--), so if we skipped
495  * non-options, we have to permute.
496  */
497  if (nonopt_end != -1) {
498  permute_args(nonopt_start, nonopt_end, optind, nargv);
499  optind -= nonopt_end - nonopt_start;
500  }
501  nonopt_start = nonopt_end = -1;
502  return (-1);
503  }
504  }
505 
506  /*
507  * Check long options if:
508  * 1) we were passed some
509  * 2) the arg is not just "-"
510  * 3) either the arg starts with -- we are getopt_long_only()
511  */
512  if (long_options != NULL && place != nargv[optind] &&
513  (*place == '-' || (flags & FLAG_LONGONLY))) {
514  short_too = 0;
515  if (*place == '-')
516  place++; /* --foo long option */
517  else if (*place != ':' && strchr(options, *place) != NULL)
518  short_too = 1; /* could be short option too */
519 
520  optchar = parse_long_options(nargv, options, long_options, idx, short_too);
521  if (optchar != -1) {
522  place = EMSG;
523  return (optchar);
524  }
525  }
526 
527  if ((optchar = (int)*place++) == (int)':' ||
528  (optchar == (int)'-' && *place != '\0') ||
529  (oli = (char *)strchr(options, optchar)) == NULL) {
530  /*
531  * If the user specified "-" and '-' isn't listed in
532  * options, return -1 (non-option) as per POSIX.
533  * Otherwise, it is an unknown option character (or ':').
534  */
535  if (optchar == (int)'-' && *place == '\0')
536  return (-1);
537  if (!*place)
538  ++optind;
539  if (PRINT_ERROR)
540  warnx(illoptchar, optchar);
541  optopt = optchar;
542  return (BADCH);
543  }
544  if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
545  /* -W long-option */
546  if (*place) /* no space */
547  /* NOTHING */;
548  else if (++optind >= nargc) { /* no arg */
549  place = EMSG;
550  if (PRINT_ERROR)
551  warnx(recargchar, optchar);
552  optopt = optchar;
553  return (BADARG);
554  } else /* white space */
555  place = nargv[optind];
556  optchar = parse_long_options(nargv, options, long_options, idx, 0);
557  place = EMSG;
558  return (optchar);
559  }
560  if (*++oli != ':') { /* doesn't take argument */
561  if (!*place)
562  ++optind;
563  } else { /* takes (optional) argument */
564  optarg = NULL;
565  if (*place) /* no white space */
566  optarg = place;
567  else if (oli[1] != ':') { /* arg not optional */
568  if (++optind >= nargc) { /* no arg */
569  place = EMSG;
570  if (PRINT_ERROR)
571  warnx(recargchar, optchar);
572  optopt = optchar;
573  return (BADARG);
574  } else
575  optarg = nargv[optind];
576  }
577  place = EMSG;
578  ++optind;
579  }
580  /* dump back option letter */
581  return (optchar);
582 }
583 
584 /*
585  * getopt_long --
586  * Parse argc/argv argument vector.
587  */
588 int getopt_long(int nargc, char *const *nargv, const char *options,
589  const struct option *long_options, int *idx) {
590 
591  return (
592  getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE));
593 }
594 
595 /*
596  * getopt_long_only --
597  * Parse argc/argv argument vector.
598  */
599 int getopt_long_only(int nargc, char *const *nargv, const char *options,
600  const struct option *long_options, int *idx) {
601 
602  return (getopt_internal(nargc, nargv, options, long_options, idx,
603  FLAG_PERMUTE | FLAG_LONGONLY));
604 }
605 
606 //extern int getopt_long(int nargc, char * const *nargv, const char *options,
607 // const struct option *long_options, int *idx);
608 //extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
609 // const struct option *long_options, int *idx);
610 /*
611  * Previous MinGW implementation had...
612  */
613 #ifndef HAVE_DECL_GETOPT
614 /*
615  * ...for the long form API only; keep this for compatibility.
616  */
617 #define HAVE_DECL_GETOPT 1
618 #endif
619 
620 #ifdef __cplusplus
621 }
622 #endif
623 
624 #endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */
Definition: getopt.h:259