aboutsummaryrefslogtreecommitdiff
path: root/src/optparse.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/optparse.h')
-rw-r--r--src/optparse.h455
1 files changed, 206 insertions, 249 deletions
diff --git a/src/optparse.h b/src/optparse.h
index bc1cc06..6f7ced0 100644
--- a/src/optparse.h
+++ b/src/optparse.h
@@ -48,29 +48,25 @@
#define OPTPARSE_H
#ifndef OPTPARSE_API
-# define OPTPARSE_API
+#define OPTPARSE_API
#endif
struct optparse {
- char **argv;
- int permute;
- int optind;
- int optopt;
- char *optarg;
- char errmsg[64];
- int subopt;
+ char **argv;
+ int permute;
+ int optind;
+ int optopt;
+ char *optarg;
+ char errmsg[64];
+ int subopt;
};
-enum optparse_argtype {
- OPTPARSE_NONE,
- OPTPARSE_REQUIRED,
- OPTPARSE_OPTIONAL
-};
+enum optparse_argtype { OPTPARSE_NONE, OPTPARSE_REQUIRED, OPTPARSE_OPTIONAL };
struct optparse_long {
- const char *longname;
- int shortname;
- enum optparse_argtype argtype;
+ const char *longname;
+ int shortname;
+ enum optparse_argtype argtype;
};
/**
@@ -99,8 +95,7 @@ int optparse(struct optparse *options, const char *optstring);
*/
OPTPARSE_API
int optparse_long(struct optparse *options,
- const struct optparse_long *longopts,
- int *longindex);
+ const struct optparse_long *longopts, int *longindex);
/**
* Used for stepping over non-option arguments.
@@ -121,284 +116,246 @@ char *optparse_arg(struct optparse *options);
#define OPTPARSE_MSG_MISSING "option requires an argument"
#define OPTPARSE_MSG_TOOMANY "option takes no arguments"
-static int
-optparse_error(struct optparse *options, const char *msg, const char *data)
-{
- unsigned p = 0;
- const char *sep = " -- '";
- while (*msg)
- options->errmsg[p++] = *msg++;
- while (*sep)
- options->errmsg[p++] = *sep++;
- while (p < sizeof(options->errmsg) - 2 && *data)
- options->errmsg[p++] = *data++;
- options->errmsg[p++] = '\'';
- options->errmsg[p++] = '\0';
- return '?';
+static int optparse_error(struct optparse *options, const char *msg,
+ const char *data) {
+ unsigned p = 0;
+ const char *sep = " -- '";
+ while (*msg) options->errmsg[p++] = *msg++;
+ while (*sep) options->errmsg[p++] = *sep++;
+ while (p < sizeof(options->errmsg) - 2 && *data)
+ options->errmsg[p++] = *data++;
+ options->errmsg[p++] = '\'';
+ options->errmsg[p++] = '\0';
+ return '?';
}
OPTPARSE_API
-void
-optparse_init(struct optparse *options, char **argv)
-{
- options->argv = argv;
- options->permute = 1;
- options->optind = 1;
- options->subopt = 0;
- options->optarg = 0;
- options->errmsg[0] = '\0';
+void optparse_init(struct optparse *options, char **argv) {
+ options->argv = argv;
+ options->permute = 1;
+ options->optind = 1;
+ options->subopt = 0;
+ options->optarg = 0;
+ options->errmsg[0] = '\0';
}
-static int
-optparse_is_dashdash(const char *arg)
-{
- return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] == '\0';
+static int optparse_is_dashdash(const char *arg) {
+ return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] == '\0';
}
-static int
-optparse_is_shortopt(const char *arg)
-{
- return arg != 0 && arg[0] == '-' && arg[1] != '-' && arg[1] != '\0';
+static int optparse_is_shortopt(const char *arg) {
+ return arg != 0 && arg[0] == '-' && arg[1] != '-' && arg[1] != '\0';
}
-static int
-optparse_is_longopt(const char *arg)
-{
- return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] != '\0';
+static int optparse_is_longopt(const char *arg) {
+ return arg != 0 && arg[0] == '-' && arg[1] == '-' && arg[2] != '\0';
}
-static void
-optparse_permute(struct optparse *options, int index)
-{
- char *nonoption = options->argv[index];
- int i;
- for (i = index; i < options->optind - 1; i++)
- options->argv[i] = options->argv[i + 1];
- options->argv[options->optind - 1] = nonoption;
+static void optparse_permute(struct optparse *options, int index) {
+ char *nonoption = options->argv[index];
+ int i;
+ for (i = index; i < options->optind - 1; i++)
+ options->argv[i] = options->argv[i + 1];
+ options->argv[options->optind - 1] = nonoption;
}
-static int
-optparse_argtype(const char *optstring, char c)
-{
- int count = OPTPARSE_NONE;
- if (c == ':')
- return -1;
- for (; *optstring && c != *optstring; optstring++);
- if (!*optstring)
- return -1;
- if (optstring[1] == ':')
- count += optstring[2] == ':' ? 2 : 1;
- return count;
+static int optparse_argtype(const char *optstring, char c) {
+ int count = OPTPARSE_NONE;
+ if (c == ':') return -1;
+ for (; *optstring && c != *optstring; optstring++)
+ ;
+ if (!*optstring) return -1;
+ if (optstring[1] == ':') count += optstring[2] == ':' ? 2 : 1;
+ return count;
}
OPTPARSE_API
-int
-optparse(struct optparse *options, const char *optstring)
-{
- int type;
- char *next;
- char *option = options->argv[options->optind];
- options->errmsg[0] = '\0';
- options->optopt = 0;
- options->optarg = 0;
- if (option == 0) {
- return -1;
- } else if (optparse_is_dashdash(option)) {
- options->optind++; /* consume "--" */
- return -1;
- } else if (!optparse_is_shortopt(option)) {
- if (options->permute) {
- int index = options->optind++;
- int r = optparse(options, optstring);
- optparse_permute(options, index);
- options->optind--;
- return r;
- } else {
- return -1;
- }
+int optparse(struct optparse *options, const char *optstring) {
+ int type;
+ char *next;
+ char *option = options->argv[options->optind];
+ options->errmsg[0] = '\0';
+ options->optopt = 0;
+ options->optarg = 0;
+ if (option == 0) {
+ return -1;
+ } else if (optparse_is_dashdash(option)) {
+ options->optind++; /* consume "--" */
+ return -1;
+ } else if (!optparse_is_shortopt(option)) {
+ if (options->permute) {
+ int index = options->optind++;
+ int r = optparse(options, optstring);
+ optparse_permute(options, index);
+ options->optind--;
+ return r;
+ } else {
+ return -1;
}
- option += options->subopt + 1;
- options->optopt = option[0];
- type = optparse_argtype(optstring, option[0]);
- next = options->argv[options->optind + 1];
- switch (type) {
+ }
+ option += options->subopt + 1;
+ options->optopt = option[0];
+ type = optparse_argtype(optstring, option[0]);
+ next = options->argv[options->optind + 1];
+ switch (type) {
case -1: {
- char str[2] = {0, 0};
- str[0] = option[0];
- options->optind++;
- return optparse_error(options, OPTPARSE_MSG_INVALID, str);
+ char str[2] = {0, 0};
+ str[0] = option[0];
+ options->optind++;
+ return optparse_error(options, OPTPARSE_MSG_INVALID, str);
}
case OPTPARSE_NONE:
- if (option[1]) {
- options->subopt++;
- } else {
- options->subopt = 0;
- options->optind++;
- }
- return option[0];
- case OPTPARSE_REQUIRED:
+ if (option[1]) {
+ options->subopt++;
+ } else {
options->subopt = 0;
options->optind++;
- if (option[1]) {
- options->optarg = option + 1;
- } else if (next != 0) {
- options->optarg = next;
- options->optind++;
- } else {
- char str[2] = {0, 0};
- str[0] = option[0];
- options->optarg = 0;
- return optparse_error(options, OPTPARSE_MSG_MISSING, str);
- }
- return option[0];
- case OPTPARSE_OPTIONAL:
- options->subopt = 0;
+ }
+ return option[0];
+ case OPTPARSE_REQUIRED:
+ options->subopt = 0;
+ options->optind++;
+ if (option[1]) {
+ options->optarg = option + 1;
+ } else if (next != 0) {
+ options->optarg = next;
options->optind++;
- if (option[1])
- options->optarg = option + 1;
- else
- options->optarg = 0;
- return option[0];
- }
- return 0;
+ } else {
+ char str[2] = {0, 0};
+ str[0] = option[0];
+ options->optarg = 0;
+ return optparse_error(options, OPTPARSE_MSG_MISSING, str);
+ }
+ return option[0];
+ case OPTPARSE_OPTIONAL:
+ options->subopt = 0;
+ options->optind++;
+ if (option[1])
+ options->optarg = option + 1;
+ else
+ options->optarg = 0;
+ return option[0];
+ }
+ return 0;
}
OPTPARSE_API
-char *
-optparse_arg(struct optparse *options)
-{
- char *option = options->argv[options->optind];
- options->subopt = 0;
- if (option != 0)
- options->optind++;
- return option;
+char *optparse_arg(struct optparse *options) {
+ char *option = options->argv[options->optind];
+ options->subopt = 0;
+ if (option != 0) options->optind++;
+ return option;
}
-static int
-optparse_longopts_end(const struct optparse_long *longopts, int i)
-{
- return !longopts[i].longname && !longopts[i].shortname;
+static int optparse_longopts_end(const struct optparse_long *longopts, int i) {
+ return !longopts[i].longname && !longopts[i].shortname;
}
-static void
-optparse_from_long(const struct optparse_long *longopts, char *optstring)
-{
- char *p = optstring;
- int i;
- for (i = 0; !optparse_longopts_end(longopts, i); i++) {
- if (longopts[i].shortname) {
- int a;
- *p++ = longopts[i].shortname;
- for (a = 0; a < (int)longopts[i].argtype; a++)
- *p++ = ':';
- }
+static void optparse_from_long(const struct optparse_long *longopts,
+ char *optstring) {
+ char *p = optstring;
+ int i;
+ for (i = 0; !optparse_longopts_end(longopts, i); i++) {
+ if (longopts[i].shortname) {
+ int a;
+ *p++ = longopts[i].shortname;
+ for (a = 0; a < (int)longopts[i].argtype; a++) *p++ = ':';
}
- *p = '\0';
+ }
+ *p = '\0';
}
/* Unlike strcmp(), handles options containing "=". */
-static int
-optparse_longopts_match(const char *longname, const char *option)
-{
- const char *a = option, *n = longname;
- if (longname == 0)
- return 0;
- for (; *a && *n && *a != '='; a++, n++)
- if (*a != *n)
- return 0;
- return *n == '\0' && (*a == '\0' || *a == '=');
+static int optparse_longopts_match(const char *longname, const char *option) {
+ const char *a = option, *n = longname;
+ if (longname == 0) return 0;
+ for (; *a && *n && *a != '='; a++, n++)
+ if (*a != *n) return 0;
+ return *n == '\0' && (*a == '\0' || *a == '=');
}
/* Return the part after "=", or NULL. */
-static char *
-optparse_longopts_arg(char *option)
-{
- for (; *option && *option != '='; option++);
- if (*option == '=')
- return option + 1;
- else
- return 0;
+static char *optparse_longopts_arg(char *option) {
+ for (; *option && *option != '='; option++)
+ ;
+ if (*option == '=')
+ return option + 1;
+ else
+ return 0;
}
-static int
-optparse_long_fallback(struct optparse *options,
- const struct optparse_long *longopts,
- int *longindex)
-{
- int result;
- char optstring[96 * 3 + 1]; /* 96 ASCII printable characters */
- optparse_from_long(longopts, optstring);
- result = optparse(options, optstring);
- if (longindex != 0) {
- *longindex = -1;
- if (result != -1) {
- int i;
- for (i = 0; !optparse_longopts_end(longopts, i); i++)
- if (longopts[i].shortname == options->optopt)
- *longindex = i;
- }
+static int optparse_long_fallback(struct optparse *options,
+ const struct optparse_long *longopts,
+ int *longindex) {
+ int result;
+ char optstring[96 * 3 + 1]; /* 96 ASCII printable characters */
+ optparse_from_long(longopts, optstring);
+ result = optparse(options, optstring);
+ if (longindex != 0) {
+ *longindex = -1;
+ if (result != -1) {
+ int i;
+ for (i = 0; !optparse_longopts_end(longopts, i); i++)
+ if (longopts[i].shortname == options->optopt) *longindex = i;
}
- return result;
+ }
+ return result;
}
OPTPARSE_API
-int
-optparse_long(struct optparse *options,
- const struct optparse_long *longopts,
- int *longindex)
-{
- int i;
- char *option = options->argv[options->optind];
- if (option == 0) {
- return -1;
- } else if (optparse_is_dashdash(option)) {
- options->optind++; /* consume "--" */
- return -1;
- } else if (optparse_is_shortopt(option)) {
- return optparse_long_fallback(options, longopts, longindex);
- } else if (!optparse_is_longopt(option)) {
- if (options->permute) {
- int index = options->optind++;
- int r = optparse_long(options, longopts, longindex);
- optparse_permute(options, index);
- options->optind--;
- return r;
- } else {
- return -1;
- }
+int optparse_long(struct optparse *options,
+ const struct optparse_long *longopts, int *longindex) {
+ int i;
+ char *option = options->argv[options->optind];
+ if (option == 0) {
+ return -1;
+ } else if (optparse_is_dashdash(option)) {
+ options->optind++; /* consume "--" */
+ return -1;
+ } else if (optparse_is_shortopt(option)) {
+ return optparse_long_fallback(options, longopts, longindex);
+ } else if (!optparse_is_longopt(option)) {
+ if (options->permute) {
+ int index = options->optind++;
+ int r = optparse_long(options, longopts, longindex);
+ optparse_permute(options, index);
+ options->optind--;
+ return r;
+ } else {
+ return -1;
}
+ }
- /* Parse as long option. */
- options->errmsg[0] = '\0';
- options->optopt = 0;
- options->optarg = 0;
- option += 2; /* skip "--" */
- options->optind++;
- for (i = 0; !optparse_longopts_end(longopts, i); i++) {
- const char *name = longopts[i].longname;
- if (optparse_longopts_match(name, option)) {
- char *arg;
- if (longindex)
- *longindex = i;
- options->optopt = longopts[i].shortname;
- arg = optparse_longopts_arg(option);
- if (longopts[i].argtype == OPTPARSE_NONE && arg != 0) {
- return optparse_error(options, OPTPARSE_MSG_TOOMANY, name);
- } if (arg != 0) {
- options->optarg = arg;
- } else if (longopts[i].argtype == OPTPARSE_REQUIRED) {
- options->optarg = options->argv[options->optind];
- if (options->optarg == 0)
- return optparse_error(options, OPTPARSE_MSG_MISSING, name);
- else
- options->optind++;
- }
- return options->optopt;
- }
+ /* Parse as long option. */
+ options->errmsg[0] = '\0';
+ options->optopt = 0;
+ options->optarg = 0;
+ option += 2; /* skip "--" */
+ options->optind++;
+ for (i = 0; !optparse_longopts_end(longopts, i); i++) {
+ const char *name = longopts[i].longname;
+ if (optparse_longopts_match(name, option)) {
+ char *arg;
+ if (longindex) *longindex = i;
+ options->optopt = longopts[i].shortname;
+ arg = optparse_longopts_arg(option);
+ if (longopts[i].argtype == OPTPARSE_NONE && arg != 0) {
+ return optparse_error(options, OPTPARSE_MSG_TOOMANY, name);
+ }
+ if (arg != 0) {
+ options->optarg = arg;
+ } else if (longopts[i].argtype == OPTPARSE_REQUIRED) {
+ options->optarg = options->argv[options->optind];
+ if (options->optarg == 0)
+ return optparse_error(options, OPTPARSE_MSG_MISSING, name);
+ else
+ options->optind++;
+ }
+ return options->optopt;
}
- return optparse_error(options, OPTPARSE_MSG_INVALID, option);
+ }
+ return optparse_error(options, OPTPARSE_MSG_INVALID, option);
}
#endif /* OPTPARSE_IMPLEMENTATION */
#endif /* OPTPARSE_H */
-