Signed-off-by: Pierre Habouzit <madcoder@xxxxxxxxxx> --- parse-options.c | 115 ++++++++++++++++++++++++++++--------------------------- 1 files changed, 59 insertions(+), 56 deletions(-) diff --git a/parse-options.c b/parse-options.c index d716ccc..f3f0f2a 100644 --- a/parse-options.c +++ b/parse-options.c @@ -7,15 +7,14 @@ struct optparse_t { const char *opt; }; -static inline const char *get_arg(struct optparse_t *p) +static inline void use_arg(struct optparse_t *p) { if (p->opt) { - const char *res = p->opt; p->opt = NULL; - return res; + } else { + p->argc--; + ++p->argv; } - p->argc--; - return *++p->argv; } static inline const char *skip_prefix(const char *str, const char *prefix) @@ -33,15 +32,62 @@ static int opterror(const struct option *opt, const char *reason, int flags) return error("option `%s' %s", opt->long_name, reason); } +static int parse_opt_string(const struct option *opt, + const char *arg, int flags) +{ + *(const char **)opt->value = flags & PARSE_OPT_UNSET ? NULL : arg; + return 0; +} + +static int parse_opt_integer(const struct option *opt, + const char *arg, int flags) +{ + int v = flags & PARSE_OPT_UNSET ? 0 : opt->defval; + if (arg) { + v = strtol(arg, (char **)&arg, 10); + if (*arg) { + if (flags & PARSE_OPT_MAY_IGN) { + *(int *)opt->value = opt->defval; + return PARSE_OPT_IGNORE; + } + return opterror(opt, "expects a numerical value", 0); + } + } + *(int *)opt->value = v; + return 0; +} + +static int run_callback(struct optparse_t *p, parse_opt_cb *cb, + const struct option *opt, int flags) +{ + const char *arg = p->opt ? p->opt : (p->argc > 1 ? p->argv[1] : NULL); + int may_ign = 0; + + if (!p->opt && (opt->flags & PARSE_OPT_OPTARG)) + may_ign = PARSE_OPT_MAY_IGN; + if ((flags & PARSE_OPT_UNSET) || (opt->flags & PARSE_OPT_NOARG)) + return (*cb)(opt, NULL, flags); + if (!may_ign && !arg) + return opterror(opt, "requires a value", flags); + if (may_ign && arg && arg[0] == '-' && arg[1]) + return (*cb)(opt, NULL, flags); + switch ((*cb)(opt, arg, flags | may_ign)) { + case PARSE_OPT_OK: + use_arg(p); + return PARSE_OPT_OK; + case PARSE_OPT_IGNORE: + if (!may_ign) + die("should not happen: MAY_IGN unset, but arg was IGNOREd"); + return PARSE_OPT_IGNORE; + default: + return PARSE_OPT_ERR; + } +} + static int get_value(struct optparse_t *p, const struct option *opt, int flags) { - const char *s, *arg; const int unset = flags & PARSE_OPT_UNSET; - int may_ign = 0, res; - - if (!unset && !p->opt && (opt->flags & PARSE_OPT_OPTARG)) - may_ign = PARSE_OPT_MAY_IGN; if (unset && p->opt) return opterror(opt, "takes no value", flags); if (unset && (opt->flags & PARSE_OPT_NONEG)) @@ -63,7 +109,6 @@ static int get_value(struct optparse_t *p, } } - arg = p->opt ? p->opt : (p->argc > 1 ? p->argv[1] : NULL); switch (opt->type) { case OPTION_BIT: if (unset) @@ -71,63 +116,21 @@ static int get_value(struct optparse_t *p, else *(int *)opt->value |= opt->defval; return 0; - case OPTION_BOOLEAN: *(int *)opt->value = unset ? 0 : *(int *)opt->value + 1; return 0; - case OPTION_SET_INT: *(int *)opt->value = unset ? 0 : opt->defval; return 0; - case OPTION_SET_PTR: *(void **)opt->value = unset ? NULL : (void *)opt->defval; return 0; - case OPTION_STRING: - if (unset) { - *(const char **)opt->value = NULL; - return 0; - } - if (may_ign && (!arg || *arg == '-')) { - *(const char **)opt->value = (const char *)opt->defval; - return 0; - } - if (!arg) - return opterror(opt, "requires a value", flags); - *(const char **)opt->value = get_arg(p); - return 0; - + return run_callback(p, &parse_opt_string, opt, flags); case OPTION_CALLBACK: - if (unset || (opt->flags & PARSE_OPT_NOARG)) - return (*opt->callback)(opt, NULL, flags); - if (!may_ign && !arg) - return opterror(opt, "requires a value", flags); - if (may_ign && arg && arg[0] == '-' && arg[1]) - return (*opt->callback)(opt, NULL, flags); - res = (*opt->callback)(opt, arg, flags); - if (!may_ign && res == PARSE_OPT_IGNORE) - die("should not happen: MAY_IGN unset, but arg was IGNOREd"); - if (res == PARSE_OPT_IGNORE) - get_arg(p); - return res; - + return run_callback(p, opt->callback, opt, flags); case OPTION_INTEGER: - if (unset) { - *(int *)opt->value = 0; - return 0; - } - if (may_ign && (!arg || !isdigit(*arg))) { - *(int *)opt->value = opt->defval; - return 0; - } - if (!arg) - return opterror(opt, "requires a value", flags); - *(int *)opt->value = strtol(get_arg(p), (char **)&s, 10); - if (*s) - return opterror(opt, "expects a numerical value", flags); - return 0; - + return run_callback(p, &parse_opt_integer, opt, flags); default: die("should not happen, someone must be hit on the forehead"); } -- 1.5.4.rc0.1148.ga3ab1-dirty - 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