Signed-off-by: Kristian Høgsberg <krh@xxxxxxxxxx> --- Makefile | 2 +- parse-options.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ parse-options.h | 29 +++++++++++++++++++++ 3 files changed, 104 insertions(+), 1 deletions(-) create mode 100644 parse-options.c create mode 100644 parse-options.h diff --git a/Makefile b/Makefile index 62bdac6..d90e959 100644 --- a/Makefile +++ b/Makefile @@ -310,7 +310,7 @@ LIB_OBJS = \ alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \ color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \ convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \ - transport.o bundle.o + transport.o bundle.o parse-options.o BUILTIN_OBJS = \ builtin-add.o \ diff --git a/parse-options.c b/parse-options.c new file mode 100644 index 0000000..2fb30cd --- /dev/null +++ b/parse-options.c @@ -0,0 +1,74 @@ +#include "git-compat-util.h" +#include "parse-options.h" + +int parse_options(const char ***argv, + struct option *options, int count, + const char *usage_string) +{ + const char *value, *eq; + int i; + + if (**argv == NULL) + return 0; + if ((**argv)[0] != '-') + return 0; + if (!strcmp(**argv, "--")) + return 0; + + value = NULL; + for (i = 0; i < count; i++) { + if ((**argv)[1] == '-') { + if (!prefixcmp(options[i].long_name, **argv + 2)) { + if (options[i].type != OPTION_BOOLEAN) + value = *++(*argv); + goto match; + } + + eq = strchr(**argv + 2, '='); + if (eq && options[i].type != OPTION_BOOLEAN && + !strncmp(**argv + 2, + options[i].long_name, eq - **argv - 2)) { + value = eq + 1; + goto match; + } + } + + if ((**argv)[1] == options[i].short_name) { + if ((**argv)[2] == '\0') { + if (options[i].type != OPTION_BOOLEAN) + value = *++(*argv); + goto match; + } + + if (options[i].type != OPTION_BOOLEAN) { + value = **argv + 2; + goto match; + } + } + } + + usage(usage_string); + + match: + switch (options[i].type) { + case OPTION_BOOLEAN: + *(int *)options[i].value = 1; + break; + case OPTION_STRING: + if (value == NULL) + die("option %s requires a value.", (*argv)[-1]); + *(const char **)options[i].value = value; + break; + case OPTION_INTEGER: + if (value == NULL) + die("option %s requires a value.", (*argv)[-1]); + *(int *)options[i].value = atoi(value); + break; + default: + assert(0); + } + + (*argv)++; + + return 1; +} diff --git a/parse-options.h b/parse-options.h new file mode 100644 index 0000000..39399c3 --- /dev/null +++ b/parse-options.h @@ -0,0 +1,29 @@ +#ifndef PARSE_OPTIONS_H +#define PARSE_OPTIONS_H + +enum option_type { + OPTION_BOOLEAN, + OPTION_STRING, + OPTION_INTEGER, + OPTION_LAST, +}; + +struct option { + enum option_type type; + const char *long_name; + char short_name; + void *value; +}; + +/* Parse the given options against the list of known options. The + * order of the option structs matters, in that ambiguous + * abbreviations (eg, --in could be short for --include or + * --interactive) are matched by the first option that share the + * prefix. + */ + +extern int parse_options(const char ***argv, + struct option *options, int count, + const char *usage_string); + +#endif -- 1.5.2.GIT - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html