59 #pragma warning(disable : 4996)
76 #define REPLACE_GETOPT
83 #define optreset __mingw_optreset
95 #define PRINT_ERROR ((opterr) && (*options != ':'))
97 #define FLAG_PERMUTE 0x01
98 #define FLAG_ALLARGS 0x02
99 #define FLAG_LONGONLY 0x04
102 #define BADCH (int)'?'
103 #define BADARG ((*options == ':') ? (int)':' : (int)'?')
104 #define INORDER (int)1
107 #define __progname __argv[0]
109 extern char __declspec(dllimport) * __progname;
113 static char EMSG[] =
"";
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 *);
125 static char *place = EMSG;
128 static int nonopt_start = -1;
129 static int nonopt_end = -1;
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";
139 static void _vwarnx(
const char *fmt, va_list ap) {
140 (void)fprintf(stderr,
"%s: ", __progname);
142 (void)vfprintf(stderr, fmt, ap);
143 (void)fprintf(stderr,
"\n");
146 static void warnx(
const char *fmt, ...) {
156 static int gcd(
int a,
int b) {
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;
182 nnonopts = panonopt_end - panonopt_start;
183 nopts = opt_end - panonopt_end;
184 ncycle = gcd(nnonopts, nopts);
185 cyclelen = (opt_end - panonopt_start) / ncycle;
187 for (i = 0; i < ncycle; i++) {
188 cstart = panonopt_end + i;
190 for (j = 0; j < cyclelen; j++) {
191 if (pos >= panonopt_end)
197 ((
char **)nargv)[pos] = nargv[cstart];
199 ((
char **)nargv)[cstart] = swap;
204 #ifdef REPLACE_GETOPT
211 int getopt(
int nargc,
char *
const *nargv,
const char *options) {
221 return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
234 #define optreset __mingw_optreset
251 #if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
252 #define __GETOPT_LONG_H__
278 static int parse_long_options(
char *
const *nargv,
const char *options,
279 const struct option *long_options,
int *idx,
281 char *current_argv, *has_equal;
282 size_t current_argv_len;
283 int i, ambiguous, match;
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)
290 current_argv = place;
296 if ((has_equal = strchr(current_argv,
'=')) != NULL) {
298 current_argv_len = has_equal - current_argv;
301 current_argv_len = strlen(current_argv);
303 for (i = 0; long_options[i].name; i++) {
305 if (strncmp(current_argv, long_options[i].name, current_argv_len))
308 if (strlen(long_options[i].name) == current_argv_len) {
318 if (short_too && current_argv_len == 1)
323 else if (!IDENTICAL_INTERPRETATION(i, match))
329 warnx(ambig, (
int)current_argv_len, current_argv);
334 if (long_options[match].has_arg == no_argument && has_equal) {
336 warnx(noarg, (
int)current_argv_len, current_argv);
340 if (long_options[match].flag == NULL)
341 optopt = long_options[match].val;
346 if (long_options[match].has_arg == required_argument ||
347 long_options[match].has_arg == optional_argument) {
350 else if (long_options[match].has_arg == required_argument) {
354 optarg = nargv[optind++];
357 if ((long_options[match].has_arg == required_argument) &&
364 warnx(recargstring, current_argv);
368 if (long_options[match].flag == NULL)
369 optopt = long_options[match].val;
381 warnx(illoptstring, current_argv);
387 if (long_options[match].flag) {
388 *long_options[match].flag = long_options[match].val;
391 return (long_options[match].val);
392 #undef IDENTICAL_INTERPRETATION
399 static int getopt_internal(
int nargc,
char *
const *nargv,
const char *options,
400 const struct option *long_options,
int *idx,
403 int optchar, short_too;
404 static int posixly_correct = -1;
414 optind = optreset = 1;
423 if (posixly_correct == -1 || optreset != 0)
424 posixly_correct = (getenv(
"POSIXLY_CORRECT") != NULL);
426 flags |= FLAG_ALLARGS;
427 else if (posixly_correct || *options ==
'+')
428 flags &= ~FLAG_PERMUTE;
429 if (*options ==
'+' || *options ==
'-')
434 nonopt_start = nonopt_end = -1;
436 if (optreset || !*place) {
438 if (optind >= nargc) {
440 if (nonopt_end != -1) {
442 permute_args(nonopt_start, nonopt_end, optind, nargv);
443 optind -= nonopt_end - nonopt_start;
444 }
else if (nonopt_start != -1) {
449 optind = nonopt_start;
451 nonopt_start = nonopt_end = -1;
454 if (*(place = nargv[optind]) !=
'-' ||
455 (place[1] ==
'\0' && strchr(options,
'-') == NULL)) {
457 if (flags & FLAG_ALLARGS) {
462 optarg = nargv[optind++];
465 if (!(flags & FLAG_PERMUTE)) {
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);
484 if (nonopt_start != -1 && nonopt_end == -1)
490 if (place[1] !=
'\0' && *++place ==
'-' && place[1] ==
'\0') {
497 if (nonopt_end != -1) {
498 permute_args(nonopt_start, nonopt_end, optind, nargv);
499 optind -= nonopt_end - nonopt_start;
501 nonopt_start = nonopt_end = -1;
512 if (long_options != NULL && place != nargv[optind] &&
513 (*place ==
'-' || (flags & FLAG_LONGONLY))) {
517 else if (*place !=
':' && strchr(options, *place) != NULL)
520 optchar = parse_long_options(nargv, options, long_options, idx, short_too);
527 if ((optchar = (
int)*place++) == (
int)
':' ||
528 (optchar == (
int)
'-' && *place !=
'\0') ||
529 (oli = (
char *)strchr(options, optchar)) == NULL) {
535 if (optchar == (
int)
'-' && *place ==
'\0')
540 warnx(illoptchar, optchar);
544 if (long_options != NULL && optchar ==
'W' && oli[1] ==
';') {
548 else if (++optind >= nargc) {
551 warnx(recargchar, optchar);
555 place = nargv[optind];
556 optchar = parse_long_options(nargv, options, long_options, idx, 0);
567 else if (oli[1] !=
':') {
568 if (++optind >= nargc) {
571 warnx(recargchar, optchar);
575 optarg = nargv[optind];
588 int getopt_long(
int nargc,
char *
const *nargv,
const char *options,
589 const struct option *long_options,
int *idx) {
592 getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE));
599 int getopt_long_only(
int nargc,
char *
const *nargv,
const char *options,
600 const struct option *long_options,
int *idx) {
602 return (getopt_internal(nargc, nargv, options, long_options, idx,
603 FLAG_PERMUTE | FLAG_LONGONLY));
613 #ifndef HAVE_DECL_GETOPT
617 #define HAVE_DECL_GETOPT 1