/* https://git.datadissipation.net */
#ifndef GETOPT_LONG_H_
- #define GETOPT_LONG_H_ 1
+ #define GETOPT_LONG_H_ 1
#ifdef GETOPT_LONG_INCLUDE_LIBC
#include <stdarg.h>
#endif /* GETOPT_LONG_INCLUDE_LIBC */
#ifndef HAVE_GETOPT_LONG
- #define HAVE_GETOPT_LONG 1
-
- #define no_argument 0
- #define required_argument 1
- #define optional_argument 2
-
- /*
- * structs are in their own namespace, so this should be OK
- * the worst it can do is make compiler messages worse
- */
- #define option i_option_
-
- #define optarg i_optarg_
- #define suboptarg i_suboptarg_
- #define optind i_optind_
- #define opterr i_opterr_
- #define optopt i_optopt_
- #define optreset i_optreset_
-
- #define getopt i_getopt_
- #define getsubopt i_getsubopt_
- #define getopt_long i_getopt_long_
- #define getopt_long_only i_getopt_long_only_
+ #define HAVE_GETOPT_LONG 1
+
+ #define no_argument 0
+ #define required_argument 1
+ #define optional_argument 2
+
+/*
+ * structs are in their own namespace, so this should be OK
+ * the worst it can do is make compiler messages worse
+ */
+ #define option i_option_
+
+ #define optarg i_optarg_
+ #define suboptarg i_suboptarg_
+ #define optind i_optind_
+ #define opterr i_opterr_
+ #define optopt i_optopt_
+ #define optreset i_optreset_
+
+ #define getopt i_getopt_
+ #define getsubopt i_getsubopt_
+ #define getopt_long i_getopt_long_
+ #define getopt_long_only i_getopt_long_only_
#ifndef GETOPT_LONG_IMPLEMENTATION
- extern char *i_optarg_;
- extern char *i_suboptarg_;
- extern int i_optind_, i_opterr_, i_optopt_, i_optreset_;
+extern char *i_optarg_;
+extern char *i_suboptarg_;
+extern int i_optind_, i_opterr_, i_optopt_, i_optreset_;
#endif /* !GETOPT_LONG_IMPLEMENTATION */
- struct i_option_ {
+struct i_option_ {
const char *name;
/*
* one of no_argument, required_argument, and optional_argument:
int *flag;
/* if flag not NULL, value to set *flag to; else return value */
int val;
- };
+};
- int i_getopt_(int argc, char * const *argv, const char *optstring);
- int i_getsubopt_(char **optionp, char * const *tokens, char **valuep);
- int i_getopt_long_(int argc, char * const *argv, const char *optstring,
- const struct option *longopts, int *longindex);
- int i_getopt_long_only_(int argc, char * const *argv, const char *optstring,
- const struct option *longopts, int *longindex);
+int i_getopt_(int argc, char * const *argv, const char *optstring);
+int i_getsubopt_(char **optionp, char * const *tokens, char **valuep);
+int i_getopt_long_(int argc, char * const *argv, const char *optstring,
+ const struct option *longopts, int *longindex);
+int i_getopt_long_only_(int argc, char * const *argv, const char *optstring,
+ const struct option *longopts, int *longindex);
#endif /* !HAVE_GETOPT_LONG */
-
+
#ifdef GETOPT_LONG_IMPLEMENTATION
#define I_PRINT_ERROR_ ((i_opterr_) && (*options != ':'))
- #define I_FLAG_PERMUTE_ 0x01 /* permute non-options to the end of argv */
- #define I_FLAG_ALLARGS_ 0x02 /* treat non-options as args to option "-1" */
- #define I_FLAG_LONGONLY_ 0x04 /* operate as getopt_long_only */
-
- /* return values */
- #define I_BADCH_ (int)'?'
- #define I_BADARG_ ((*options == ':') ? (int)':' : (int)'?')
- #define I_INORDER_ (int)1
-
- #define I_EMSG_ ""
-
- int i_opterr_ = 1; /* if error message should be printed */
- int i_optind_ = 1; /* index into parent argv vector */
- int i_optopt_ = '?'; /* character checked for validity */
- int i_optreset_; /* reset getopt */
- char *i_optarg_; /* argument associated with option */
- char *i_suboptarg_; /* argument associated with suboption */
-
- /* XXX: set optreset to 1 rather than these two */
- static int i_nonopt_start_ = -1; /* first non option argument (for permute) */
- static int i_nonopt_end_ = -1; /* first option after non options (for permute) */
- static char *i_place_ = I_EMSG_; /* option letter processing */
-
- /* Error messages */
- static const char i_recargchar_[] = "option requires an argument -- %c";
- static const char i_recargstring_[] = "option requires an argument -- %s";
- static const char i_ambig_[] = "i_ambig_uous option -- %.*s";
- static const char i_noarg_[] = "option doesn't take an argument -- %.*s";
- static const char i_illoptchar_[] = "unknown option -- %c";
- static const char i_illoptstring_[] = "unknown option -- %s";
-
- static void i_warnx_(const char *, ...);
- static int i_getopt_internal_(int, char * const *, const char *,
- const struct option *, int *, int);
- static int i_parse_long_options__(char * const *, const char *,
- const struct option *, int *, int);
- static int i_gcd_(int, int);
- static void i_permute_args_(int, int, int, char * const *);
-
- /*
- * Own warnx() for portability
- */
- void
- i_warnx_(const char *fmt, ...)
- {
- va_list args;
-
- /* Linux "program_invocation_short_name" is a GNU extension, so we don't use it */
- #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
- #define I_GET_PROG_NAME_() getprogname()
- #else
- #define I_GET_PROG_NAME_() "warnx"
- #endif
-
- va_start(args, fmt);
- fprintf(stderr, "%s: ", I_GET_PROG_NAME_());
- vfprintf(stderr, fmt, args);
- fputc('\n', stderr);
- va_end(args);
- }
-
- /*
- * Compute the greatest common divisor of a and b.
- */
- static int
- i_gcd_(int a, int b)
- {
- int c;
-
- c = a % b;
- while (c != 0) {
- a = b;
- b = c;
- c = a % b;
- }
-
- return (b);
- }
-
- /*
- * Exchange the block from nonopt_start to nonopt_end with the block
- * from nonopt_end to opt_end (keeping the same order of arguments
- * in each block).
- */
- static void
- i_permute_args_(int panonopt_start, int panonopt_end, int opt_end,
- char * const *nargv)
- {
- int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
- char *swap;
-
- /*
- * compute lengths of blocks and number and size of cycles
- */
- nnonopts = panonopt_end - panonopt_start;
- nopts = opt_end - panonopt_end;
- ncycle = i_gcd_(nnonopts, nopts);
- cyclelen = (opt_end - panonopt_start) / ncycle;
-
- for (i = 0; i < ncycle; i++) {
+ #define I_FLAG_PERMUTE_ 0x01 /* permute non-options to the end of argv */
+ #define I_FLAG_ALLARGS_ 0x02 /* treat non-options as args to option "-1" */
+ #define I_FLAG_LONGONLY_ 0x04 /* operate as getopt_long_only */
+
+/* return values */
+ #define I_BADCH_ (int) '?'
+ #define I_BADARG_ ((*options == ':') ? (int) ':' : (int) '?')
+ #define I_INORDER_ (int) 1
+
+ #define I_EMSG_ ""
+
+int i_opterr_ = 1; /* if error message should be printed */
+int i_optind_ = 1; /* index into parent argv vector */
+int i_optopt_ = '?'; /* character checked for validity */
+int i_optreset_; /* reset getopt */
+char *i_optarg_; /* argument associated with option */
+char *i_suboptarg_; /* argument associated with suboption */
+
+/* XXX: set optreset to 1 rather than these two */
+static int i_nonopt_start_ = -1; /* first non option argument (for permute) */
+static int i_nonopt_end_ = -1; /* first option after non options (for permute) */
+static char *i_place_ = I_EMSG_; /* option letter processing */
+static char *i_progname_; /* program name == argv[0] */
+
+/* Error messages */
+static const char i_recargchar_[] = "option requires an argument -- %c";
+static const char i_recargstring_[] = "option requires an argument -- %s";
+static const char i_ambig_[] = "i_ambig_uous option -- %.*s";
+static const char i_noarg_[] = "option doesn't take an argument -- %.*s";
+static const char i_illoptchar_[] = "unknown option -- %c";
+static const char i_illoptstring_[] = "unknown option -- %s";
+
+static void i_warnx_(const char *, ...);
+static int i_getopt_internal_(int, char * const *, const char *,
+ const struct option *, int *, int);
+static int i_parse_long_options__(char * const *, const char *,
+ const struct option *, int *, int);
+static int i_gcd_(int, int);
+static void i_permute_args_(int, int, int, char * const *);
+
+/*
+ * Own warnx() for portability
+ */
+void
+i_warnx_(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ fprintf(stderr, "%s: ", i_progname_);
+ vfprintf(stderr, fmt, args);
+ fputc('\n', stderr);
+ va_end(args);
+}
+
+/*
+ * Compute the greatest common divisor of a and b.
+ */
+static int
+i_gcd_(int a, int b)
+{
+ int c;
+
+ c = a % b;
+ while (c != 0) {
+ a = b;
+ b = c;
+ c = a % b;
+ }
+
+ return (b);
+}
+
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+i_permute_args_(int panonopt_start, int panonopt_end, int opt_end,
+ char * const *nargv)
+{
+ int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+ char *swap;
+
+ /*
+ * compute lengths of blocks and number and size of cycles
+ */
+ nnonopts = panonopt_end - panonopt_start;
+ nopts = opt_end - panonopt_end;
+ ncycle = i_gcd_(nnonopts, nopts);
+ cyclelen = (opt_end - panonopt_start) / ncycle;
+
+ for (i = 0; i < ncycle; i++) {
cstart = panonopt_end+i;
pos = cstart;
for (j = 0; j < cyclelen; j++) {
- if (pos >= panonopt_end)
- pos -= nnonopts;
- else
- pos += nopts;
- swap = nargv[pos];
- /* LINTED const cast */
- ((char **) nargv)[pos] = nargv[cstart];
- /* LINTED const cast */
- ((char **)nargv)[cstart] = swap;
- }
- }
- }
-
- /*
- * i_parse_long_options__ --
- * Parse long options in argc/argv argument vector.
- * Returns -1 if short_too is set and the option does not match long_options.
- */
- static int
- i_parse_long_options__(char * const *nargv, const char *options,
- const struct option *long_options, int *idx, int short_too)
- {
- char *current_argv, *has_equal;
- size_t current_argv_len;
- int i, match;
-
- current_argv = i_place_;
- match = -1;
-
- i_optind_++;
-
- if ((has_equal = strchr(current_argv, '=')) != NULL) {
- /* argument found (--option=arg) */
- current_argv_len = has_equal - current_argv;
- has_equal++;
- } else {
- current_argv_len = strlen(current_argv);
- }
- for (i = 0; long_options[i].name; i++) {
- /* find matching long option */
- if (strncmp(current_argv, long_options[i].name,
- current_argv_len))
- continue;
-
- if (strlen(long_options[i].name) == current_argv_len) {
- /* exact match */
- match = i;
- break;
- }
- /*
- * If this is a known short option, don't allow
- * a partial match of a single character.
- */
- if (short_too && current_argv_len == 1)
- continue;
-
- if (match == -1) { /* partial match */
- match = i;
- } else {
- /* ambiguous abbreviation */
- if (I_PRINT_ERROR_)
- i_warnx_(i_ambig_, (int)current_argv_len,
- current_argv);
- i_optopt_ = 0;
- return (I_BADCH_);
- }
- }
- if (match != -1) { /* option found */
- if (long_options[match].has_arg == no_argument
- && has_equal) {
- if (I_PRINT_ERROR_)
- i_warnx_(i_noarg_, (int)current_argv_len,
- current_argv);
- /*
- * XXX: GNU sets optopt to val regardless of flag
- */
- if (long_options[match].flag == NULL)
- i_optopt_ = long_options[match].val;
- else
- i_optopt_ = 0;
- return (I_BADARG_);
- }
- if (long_options[match].has_arg == required_argument ||
- long_options[match].has_arg == optional_argument) {
- if (has_equal)
- i_optarg_ = has_equal;
- else if (long_options[match].has_arg ==
- required_argument) {
+ if (pos >= panonopt_end)
+ pos -= nnonopts;
+ else
+ pos += nopts;
+ swap = nargv[pos];
+ /* LINTED const cast */
+ ((char **) nargv)[pos] = nargv[cstart];
+ /* LINTED const cast */
+ ((char **) nargv)[cstart] = swap;
+ }
+ }
+}
+
+/*
+ * i_parse_long_options__ --
+ * Parse long options in argc/argv argument vector.
+ * Returns -1 if short_too is set and the option does not match long_options.
+ */
+static int
+i_parse_long_options__(char * const *nargv, const char *options,
+ const struct option *long_options, int *idx, int
+ short_too)
+{
+ char *current_argv, *has_equal;
+ size_t current_argv_len;
+ int i, match;
+
+ current_argv = i_place_;
+ match = -1;
+
+ i_optind_++;
+
+ if ((has_equal = strchr(current_argv, '=')) != NULL) {
+ /* argument found (--option=arg) */
+ current_argv_len = has_equal - current_argv;
+ has_equal++;
+ } else {
+ current_argv_len = strlen(current_argv);
+ }
+ for (i = 0; long_options[i].name; i++) {
+ /* find matching long option */
+ if (strncmp(current_argv, long_options[i].name,
+ current_argv_len))
+ continue;
+
+ if (strlen(long_options[i].name) == current_argv_len) {
+ /* exact match */
+ match = i;
+ break;
+ }
+ /*
+ * If this is a known short option, don't allow
+ * a partial match of a single character.
+ */
+ if (short_too && current_argv_len == 1)
+ continue;
+
+ if (match == -1) { /* partial match */
+ match = i;
+ } else {
+ /* ambiguous abbreviation */
+ if (I_PRINT_ERROR_)
+ i_warnx_(i_ambig_, (int) current_argv_len,
+ current_argv);
+ i_optopt_ = 0;
+ return (I_BADCH_);
+ }
+ }
+ if (match != -1) { /* option found */
+ if (long_options[match].has_arg == no_argument
+ && has_equal) {
+ if (I_PRINT_ERROR_)
+ i_warnx_(i_noarg_, (int) current_argv_len,
+ current_argv);
+ /*
+ * XXX: GNU sets optopt to val regardless of flag
+ */
+ if (long_options[match].flag == NULL)
+ i_optopt_ = long_options[match].val;
+ else
+ i_optopt_ = 0;
+ return (I_BADARG_);
+ }
+ if (long_options[match].has_arg == required_argument ||
+ long_options[match].has_arg == optional_argument) {
+ if (has_equal){
+ i_optarg_ = has_equal;
+ } else if (long_options[match].has_arg ==
+ required_argument) {
/*
* optional argument doesn't use next nargv
*/
- i_optarg_ = nargv[i_optind_++];
- }
- }
- if ((long_options[match].has_arg == required_argument)
- && (i_optarg_ == NULL)) {
+ i_optarg_ = nargv[i_optind_++];
+ }
+ }
+ if ((long_options[match].has_arg == required_argument)
+ && (i_optarg_ == NULL)) {
/*
* Missing argument; leading ':' indicates no error
* should be generated.
*/
if (I_PRINT_ERROR_)
i_warnx_(i_recargstring_,
- current_argv);
+ current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
i_optopt_ = 0;
--i_optind_;
return (I_BADARG_);
- }
- } else { /* unknown option */
- if (short_too) {
- --i_optind_;
- return (-1);
- }
- if (I_PRINT_ERROR_)
- i_warnx_(i_illoptstring_, current_argv);
- i_optopt_ = 0;
- return (I_BADCH_);
- }
- if (idx)
- *idx = match;
- if (long_options[match].flag) {
- *long_options[match].flag = long_options[match].val;
- return (0);
- } else
- return (long_options[match].val);
- }
-
- /*
- * i_getopt_internal_ --
- * Parse argc/argv argument vector. Called by user level routines.
- */
- static int
- i_getopt_internal_(int nargc, char *const *nargv, const char *options,
- const struct option *long_options, int *idx, int flags)
- {
- char *oli; /* option letter list index */
- int optchar, short_too;
- static int posix_me_harder = -1;
-
- if (options == NULL)
- return (-1);
-
- /*
- * XXX Some GNU programs (like cvs) set optind to 0 instead of
- * XXX using optreset. Work around this braindamage.
- */
- if (i_optind_ == 0)
- i_optind_ = i_optreset_ = 1;
-
- /*
- * Disable GNU extensions if POSIXLY_CORRECT is set or options
- * string begins with a '+'.
- */
- if (posix_me_harder == -1 || i_optreset_)
- posix_me_harder = (getenv("POSIXLY_CORRECT") != NULL);
- if (*options == '-')
- flags |= I_FLAG_ALLARGS_;
- else if (posix_me_harder || *options == '+')
- flags &= ~I_FLAG_PERMUTE_;
- if (*options == '+' || *options == '-')
- options++;
-
- i_optarg_ = NULL;
- if (i_optreset_)
- i_nonopt_start_ = i_nonopt_end_ = -1;
- start:
- if (i_optreset_ || !*i_place_) { /* update scanning pointer */
- i_optreset_ = 0;
- if (i_optind_ >= nargc) { /* end of argument vector */
- i_place_ = I_EMSG_;
- if (i_nonopt_end_ != -1) {
- /* do permutation, if we have to */
- i_permute_args_(i_nonopt_start_, i_nonopt_end_,
- i_optind_, nargv);
- i_optind_ -= i_nonopt_end_ - i_nonopt_start_;
- } else if (i_nonopt_start_ != -1) {
- /*
- * If we skipped non-options, set optind
- * to the first of them.
- */
- i_optind_ = i_nonopt_start_;
- }
- i_nonopt_start_ = i_nonopt_end_ = -1;
- return (-1);
- }
- if (*(i_place_ = nargv[i_optind_]) != '-' ||
- (i_place_[1] == '\0' && strchr(options, '-') == NULL)) {
- i_place_ = I_EMSG_; /* found non-option */
- if (flags & I_FLAG_ALLARGS_) {
- /*
- * GNU extension:
- * return non-option as argument to option 1
- */
- i_optarg_ = nargv[i_optind_++];
- return (I_INORDER_);
- }
- if (!(flags & I_FLAG_PERMUTE_)) {
+ }
+ } else { /* unknown option */
+ if (short_too) {
+ --i_optind_;
+ return (-1);
+ }
+ if (I_PRINT_ERROR_)
+ i_warnx_(i_illoptstring_, current_argv);
+ i_optopt_ = 0;
+ return (I_BADCH_);
+ }
+ if (idx)
+ *idx = match;
+ if (long_options[match].flag) {
+ *long_options[match].flag = long_options[match].val;
+ return (0);
+ } else {
+ return (long_options[match].val);
+ }
+}
+
+/*
+ * i_getopt_internal_ --
+ * Parse argc/argv argument vector. Called by user level routines.
+ */
+static int
+i_getopt_internal_(int nargc, char *const *nargv, const char *options,
+ const struct option *long_options, int *idx, int flags)
+{
+ char *oli; /* option letter list index */
+ int optchar, short_too;
+ static int posix_me_harder = -1;
+
+ i_progname_ = nargv[0];
+
+ if (options == NULL)
+ return (-1);
+
+ /*
+ * XXX Some GNU programs (like cvs) set optind to 0 instead of
+ * XXX using optreset. Work around this braindamage.
+ */
+ if (i_optind_ == 0)
+ i_optind_ = i_optreset_ = 1;
+
+ /*
+ * Disable GNU extensions if POSIXLY_CORRECT is set or options
+ * string begins with a '+'.
+ */
+ if (posix_me_harder == -1 || i_optreset_)
+ posix_me_harder = (getenv("POSIXLY_CORRECT") != NULL);
+ if (*options == '-')
+ flags |= I_FLAG_ALLARGS_;
+ else if (posix_me_harder || *options == '+')
+ flags &= ~I_FLAG_PERMUTE_;
+ if (*options == '+' || *options == '-')
+ options++;
+
+ i_optarg_ = NULL;
+ if (i_optreset_)
+ i_nonopt_start_ = i_nonopt_end_ = -1;
+start:
+ if (i_optreset_ || !*i_place_) { /* update scanning pointer */
+ i_optreset_ = 0;
+ if (i_optind_ >= nargc) { /* end of argument vector */
+ i_place_ = I_EMSG_;
+ if (i_nonopt_end_ != -1) {
+ /* do permutation, if we have to */
+ i_permute_args_(i_nonopt_start_, i_nonopt_end_,
+ i_optind_, nargv);
+ i_optind_ -= i_nonopt_end_ - i_nonopt_start_;
+ } else if (i_nonopt_start_ != -1) {
+ /*
+ * If we skipped non-options, set optind
+ * to the first of them.
+ */
+ i_optind_ = i_nonopt_start_;
+ }
+ i_nonopt_start_ = i_nonopt_end_ = -1;
+ return (-1);
+ }
+ if (*(i_place_ = nargv[i_optind_]) != '-' ||
+ (i_place_[1] == '\0' && strchr(options, '-') == NULL)) {
+ i_place_ = I_EMSG_; /* found non-option */
+ if (flags & I_FLAG_ALLARGS_) {
+ /*
+ * GNU extension:
+ * return non-option as argument to option 1
+ */
+ i_optarg_ = nargv[i_optind_++];
+ return (I_INORDER_);
+ }
+ if (!(flags & I_FLAG_PERMUTE_)) {
/*
* If no permutation wanted, stop parsing
* at first non-option.
*/
return (-1);
- }
- /* do permutation */
- if (i_nonopt_start_ == -1) {
- i_nonopt_start_ = i_optind_;
- } else if (i_nonopt_end_ != -1) {
- i_permute_args_(i_nonopt_start_, i_nonopt_end_,
- i_optind_, nargv);
- i_nonopt_start_ = i_optind_ -
- (i_nonopt_end_ - i_nonopt_start_);
- i_nonopt_end_ = -1;
- }
- i_optind_++;
- /* process next argument */
- goto start;
- }
- if (i_nonopt_start_ != -1 && i_nonopt_end_ == -1)
- i_nonopt_end_ = i_optind_;
-
- /*
- * If we have "-" do nothing, if "--" we are done.
- */
- if (i_place_[1] != '\0' && *++i_place_ == '-' && i_place_[1] == '\0') {
- i_optind_++;
- i_place_ = I_EMSG_;
- /*
- * We found an option (--), so if we skipped
- * non-options, we have to permute.
- */
- if (i_nonopt_end_ != -1) {
- i_permute_args_(i_nonopt_start_, i_nonopt_end_,
- i_optind_, nargv);
- i_optind_ -= i_nonopt_end_ - i_nonopt_start_;
- }
- i_nonopt_start_ = i_nonopt_end_ = -1;
- return (-1);
- }
- }
-
- /*
- * Check long options if:
- * 1) we were passed some
- * 2) the arg is not just "-"
- * 3) either the arg starts with -- we are i_getopt_long_only()
- */
- if (long_options != NULL && i_place_ != nargv[i_optind_] &&
- (*i_place_ == '-' || (flags & I_FLAG_LONGONLY_))) {
- short_too = 0;
- if (*i_place_ == '-')
- i_place_++; /* --foo long option */
- else if (*i_place_ != ':'
- && strchr(options, *i_place_) != NULL)
- short_too = 1; /* could be short option too */
-
- optchar = i_parse_long_options__(nargv, options, long_options,
- idx, short_too);
- if (optchar != -1) {
- i_place_ = I_EMSG_;
- return (optchar);
- }
- }
-
- if ((optchar = (int)*i_place_++) == (int)':' ||
- (optchar == (int)'-' && *i_place_ != '\0') ||
+ }
+ /* do permutation */
+ if (i_nonopt_start_ == -1) {
+ i_nonopt_start_ = i_optind_;
+ } else if (i_nonopt_end_ != -1) {
+ i_permute_args_(i_nonopt_start_, i_nonopt_end_,
+ i_optind_, nargv);
+ i_nonopt_start_ = i_optind_ -
+ (i_nonopt_end_ -
+ i_nonopt_start_);
+ i_nonopt_end_ = -1;
+ }
+ i_optind_++;
+ /* process next argument */
+ goto start;
+ }
+ if (i_nonopt_start_ != -1 && i_nonopt_end_ == -1)
+ i_nonopt_end_ = i_optind_;
+
+ /*
+ * If we have "-" do nothing, if "--" we are done.
+ */
+ if (i_place_[1] != '\0' && *++i_place_ == '-' && i_place_[1] ==
+ '\0') {
+ i_optind_++;
+ i_place_ = I_EMSG_;
+ /*
+ * We found an option (--), so if we skipped
+ * non-options, we have to permute.
+ */
+ if (i_nonopt_end_ != -1) {
+ i_permute_args_(i_nonopt_start_, i_nonopt_end_,
+ i_optind_, nargv);
+ i_optind_ -= i_nonopt_end_ - i_nonopt_start_;
+ }
+ i_nonopt_start_ = i_nonopt_end_ = -1;
+ return (-1);
+ }
+ }
+
+ /*
+ * Check long options if:
+ * 1) we were passed some
+ * 2) the arg is not just "-"
+ * 3) either the arg starts with -- we are i_getopt_long_only()
+ */
+ if (long_options != NULL && i_place_ != nargv[i_optind_] &&
+ (*i_place_ == '-' || (flags & I_FLAG_LONGONLY_))) {
+ short_too = 0;
+ if (*i_place_ == '-')
+ i_place_++; /* --foo long option */
+ else if (*i_place_ != ':'
+ && strchr(options, *i_place_) != NULL)
+ short_too = 1; /* could be short option too */
+
+ optchar = i_parse_long_options__(nargv, options, long_options,
+ idx, short_too);
+ if (optchar != -1) {
+ i_place_ = I_EMSG_;
+ return (optchar);
+ }
+ }
+
+ if ((optchar = (int) *i_place_++) == (int) ':' ||
+ (optchar == (int) '-' && *i_place_ != '\0') ||
(oli = strchr(options, optchar)) == NULL) {
- /*
- * If the user specified "-" and '-' isn't listed in
- * options, return -1 (non-option) as per POSIX.
- * Otherwise, it is an unknown option character (or ':').
- */
- if (optchar == (int)'-' && *i_place_ == '\0')
- return (-1);
- if (!*i_place_)
- ++i_optind_;
- if (I_PRINT_ERROR_)
- i_warnx_(i_illoptchar_, optchar);
- i_optopt_ = optchar;
- return (I_BADCH_);
- }
- if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
- /* -W long-option */
- if (*i_place_) { /* no space */
- /* NOTHING */;
- } else if (++i_optind_ >= nargc) { /* no arg */
- i_place_ = I_EMSG_;
- if (I_PRINT_ERROR_)
- i_warnx_(i_recargchar_, optchar);
- i_optopt_ = optchar;
- return (I_BADARG_);
- } else { /* white space */
- i_place_ = nargv[i_optind_];
- }
- optchar = i_parse_long_options__(nargv, options, long_options,
- idx, 0);
- i_place_ = I_EMSG_;
- return (optchar);
- }
- if (*++oli != ':') { /* doesn't take argument */
- if (!*i_place_)
- ++i_optind_;
- } else { /* takes (optional) argument */
- i_optarg_ = NULL;
- if (*i_place_) /* no white space */
- i_optarg_ = i_place_;
- else if (oli[1] != ':') { /* arg not optional */
- if (++i_optind_ >= nargc) { /* no arg */
- i_place_ = I_EMSG_;
- if (I_PRINT_ERROR_)
- i_warnx_(i_recargchar_, optchar);
- i_optopt_ = optchar;
- return (I_BADARG_);
- } else {
- i_optarg_ = nargv[i_optind_];
- }
- }
- i_place_ = I_EMSG_;
- ++i_optind_;
- }
- /* dump back option letter */
- return (optchar);
- }
-
- int
- i_getsubopt_(char **optionp, char * const *tokens, char **valuep)
- {
- int cnt;
- char *p;
-
- i_suboptarg_ = *valuep = NULL;
-
- if (!optionp || !*optionp)
- return(-1);
-
- /* skip leading white-space, commas */
- for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
-
- if (!*p) {
- *optionp = p;
- return(-1);
- }
-
- /* save the start of the token, and skip the rest of the token. */
- for (i_suboptarg_ = p;
- *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';);
-
- if (*p) {
- /*
- * If there's an equals sign, set the value pointer, and
- * skip over the value part of the token. Terminate the
- * token.
- */
- if (*p == '=') {
- *p = '\0';
- for (*valuep = ++p;
- *p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
- if (*p)
- *p++ = '\0';
- } else {
- *p++ = '\0';
- }
- /* Skip any whitespace or commas after this token. */
- for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
- }
-
- /* set optionp for next round. */
- *optionp = p;
-
- for (cnt = 0; *tokens; ++tokens, ++cnt)
- if (!strcmp(i_suboptarg_, *tokens))
- return(cnt);
- return(-1);
- }
-
- int
- i_getopt_(int argc, char * const *argv, const char *optstring)
- {
- #ifdef GETOPT_PERMUTE_ARGS
- return (i_getopt_internal_(argc, argv, optstring, NULL, NULL,
- I_FLAG_PERMUTE_));
- #else
- return (i_getopt_internal_(argc, argv, optstring, NULL, NULL, 0));
- #endif
- }
-
- int
- i_getopt_long_(int argc, char * const *argv, const char *optstring,
- const struct option *longopts, int *longindex)
- {
- #ifdef GETOPT_LONG_PERMUTE_ARGS
- return (i_getopt_internal_(argc, argv, optstring, longopts, longindex,
- I_FLAG_PERMUTE_));
- #else
- return (i_getopt_internal_(argc, argv, optstring, longopts, longindex, 0));
- #endif
-
- }
-
- int
- i_getopt_long_only_(int argc, char * const *argv, const char *optstring,
- const struct option *longopts, int *longindex)
- {
- #ifdef GETOPT_LONG_ONLY_PERMUTE_ARGS
- return (i_getopt_internal_(argc, argv, optstring, longopts, longindex,
- I_FLAG_PERMUTE_ | I_FLAG_LONGONLY_));
- #else
- return (i_getopt_internal_(argc, argv, optstring, longopts, longindex,
- I_FLAG_LONGONLY_));
- #endif
- }
+ /*
+ * If the user specified "-" and '-' isn't listed in
+ * options, return -1 (non-option) as per POSIX.
+ * Otherwise, it is an unknown option character (or ':').
+ */
+ if (optchar == (int) '-' && *i_place_ == '\0')
+ return (-1);
+ if (!*i_place_)
+ ++i_optind_;
+ if (I_PRINT_ERROR_)
+ i_warnx_(i_illoptchar_, optchar);
+ i_optopt_ = optchar;
+ return (I_BADCH_);
+ }
+ if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
+ /* -W long-option */
+ if (*i_place_) { /* no space */
+ /* NOTHING */
+ ;
+ } else if (++i_optind_ >= nargc) { /* no arg */
+ i_place_ = I_EMSG_;
+ if (I_PRINT_ERROR_)
+ i_warnx_(i_recargchar_, optchar);
+ i_optopt_ = optchar;
+ return (I_BADARG_);
+ } else { /* white space */
+ i_place_ = nargv[i_optind_];
+ }
+ optchar = i_parse_long_options__(nargv, options, long_options,
+ idx, 0);
+ i_place_ = I_EMSG_;
+ return (optchar);
+ }
+ if (*++oli != ':') { /* doesn't take argument */
+ if (!*i_place_)
+ ++i_optind_;
+ } else { /* takes (optional) argument */
+ i_optarg_ = NULL;
+ if (*i_place_){ /* no white space */
+ i_optarg_ = i_place_;
+ } else if (oli[1] != ':'){ /* arg not optional */
+ if (++i_optind_ >= nargc) { /* no arg */
+ i_place_ = I_EMSG_;
+ if (I_PRINT_ERROR_)
+ i_warnx_(i_recargchar_, optchar);
+ i_optopt_ = optchar;
+ return (I_BADARG_);
+ } else {
+ i_optarg_ = nargv[i_optind_];
+ }
+ }
+ i_place_ = I_EMSG_;
+ ++i_optind_;
+ }
+ /* dump back option letter */
+ return (optchar);
+}
+
+int
+i_getsubopt_(char **optionp, char * const *tokens, char **valuep)
+{
+ int cnt;
+ char *p;
+
+ i_suboptarg_ = *valuep = NULL;
+
+ if (!optionp || !*optionp)
+ return (-1);
+
+ /* skip leading white-space, commas */
+ for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p) ;
+
+ if (!*p) {
+ *optionp = p;
+ return (-1);
+ }
+
+ /* save the start of the token, and skip the rest of the token. */
+ for (i_suboptarg_ = p;
+ *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';) ;
+
+ if (*p) {
+ /*
+ * If there's an equals sign, set the value pointer, and
+ * skip over the value part of the token. Terminate the
+ * token.
+ */
+ if (*p == '=') {
+ *p = '\0';
+ for (*valuep = ++p;
+ *p && *p != ',' && *p != ' ' && *p != '\t'; ++p) ;
+ if (*p)
+ *p++ = '\0';
+ } else {
+ *p++ = '\0';
+ }
+ /* Skip any whitespace or commas after this token. */
+ for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p) ;
+ }
+
+ /* set optionp for next round. */
+ *optionp = p;
+
+ for (cnt = 0; *tokens; ++tokens, ++cnt)
+ if (!strcmp(i_suboptarg_, *tokens))
+ return (cnt);
+ return (-1);
+}
+
+int
+i_getopt_(int argc, char * const *argv, const char *optstring)
+{
+#ifdef GETOPT_PERMUTE_ARGS
+ return (i_getopt_internal_(argc, argv, optstring, NULL, NULL,
+ I_FLAG_PERMUTE_));
+#else
+ return (i_getopt_internal_(argc, argv, optstring, NULL, NULL, 0));
+#endif
+}
+
+int
+i_getopt_long_(int argc, char * const *argv, const char *optstring,
+ const struct option *longopts, int *longindex)
+{
+#ifdef GETOPT_LONG_PERMUTE_ARGS
+ return (i_getopt_internal_(argc, argv, optstring, longopts, longindex,
+ I_FLAG_PERMUTE_));
+#else
+ return (i_getopt_internal_(argc, argv, optstring, longopts, longindex, 0
+ ));
+#endif
+}
+
+int
+i_getopt_long_only_(int argc, char * const *argv, const char *optstring,
+ const struct option *longopts, int *longindex)
+{
+#ifdef GETOPT_LONG_ONLY_PERMUTE_ARGS
+ return (i_getopt_internal_(argc, argv, optstring, longopts, longindex,
+ I_FLAG_PERMUTE_ | I_FLAG_LONGONLY_));
+#else
+ return (i_getopt_internal_(argc, argv, optstring, longopts, longindex,
+ I_FLAG_LONGONLY_));
+#endif
+}
#endif /* GETOPT_LONG_IMPLEMENTATION */
#endif /* !GETOPT_LONG_H_ */