diff --git a/parse-options.c b/parse-options.c index 469831d21b99e2ea6d5d0be51555d853d68a7682..ae88885d4da573c85dbfbeea3061f3b026223710 100644 --- a/parse-options.c +++ b/parse-options.c @@ -5,17 +5,6 @@ #define OPT_SHORT 1 #define OPT_UNSET 2 -static inline const char *get_arg(struct parse_opt_ctx_t *p) -{ - if (p->opt) { - const char *res = p->opt; - p->opt = NULL; - return res; - } - p->argc--; - return *++p->argv; -} - static inline const char *skip_prefix(const char *str, const char *prefix) { size_t len = strlen(prefix); @@ -31,8 +20,24 @@ static int opterror(const struct option *opt, const char *reason, int flags) return error("option `%s' %s", opt->long_name, reason); } +static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt, + int flags, const char **arg) +{ + if (p->opt) { + *arg = p->opt; + p->opt = NULL; + } else if (p->argc == 1 && (opt->flags & PARSE_OPT_LASTARG_DEFAULT)) { + *arg = (const char *)opt->defval; + } else if (p->argc) { + p->argc--; + *arg = *++p->argv; + } else + return opterror(opt, "requires a value", flags); + return 0; +} + static int get_value(struct parse_opt_ctx_t *p, - const struct option *opt, int flags) + const struct option *opt, int flags) { const char *s, *arg; const int unset = flags & OPT_UNSET; @@ -58,7 +63,6 @@ static int get_value(struct parse_opt_ctx_t *p, } } - arg = p->opt ? p->opt : (p->argc > 1 ? p->argv[1] : NULL); switch (opt->type) { case OPTION_BIT: if (unset) @@ -80,17 +84,12 @@ static int get_value(struct parse_opt_ctx_t *p, return 0; case OPTION_STRING: - if (unset) { + if (unset) *(const char **)opt->value = NULL; - return 0; - } - if (opt->flags & PARSE_OPT_OPTARG && !p->opt) { + else if (opt->flags & PARSE_OPT_OPTARG && !p->opt) *(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); + else + return get_arg(p, opt, flags, (const char **)opt->value); return 0; case OPTION_CALLBACK: @@ -100,9 +99,9 @@ static int get_value(struct parse_opt_ctx_t *p, return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; if (opt->flags & PARSE_OPT_OPTARG && !p->opt) return (*opt->callback)(opt, NULL, 0) ? (-1) : 0; - if (!arg) - return opterror(opt, "requires a value", flags); - return (*opt->callback)(opt, get_arg(p), 0) ? (-1) : 0; + if (get_arg(p, opt, flags, &arg)) + return -1; + return (*opt->callback)(opt, arg, 0) ? (-1) : 0; case OPTION_INTEGER: if (unset) { @@ -113,9 +112,9 @@ static int get_value(struct parse_opt_ctx_t *p, *(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 (get_arg(p, opt, flags, &arg)) + return -1; + *(int *)opt->value = strtol(arg, (char **)&s, 10); if (*s) return opterror(opt, "expects a numerical value", flags); return 0; diff --git a/parse-options.h b/parse-options.h index c5f0b4b4dabb5a40027c0cc588549904e0efcc6f..bc317e7512af7a1cc86641a651ae5415d28e71c4 100644 --- a/parse-options.h +++ b/parse-options.h @@ -28,6 +28,7 @@ enum parse_opt_option_flags { PARSE_OPT_NOARG = 2, PARSE_OPT_NONEG = 4, PARSE_OPT_HIDDEN = 8, + PARSE_OPT_LASTARG_DEFAULT = 16, }; struct option;