summaryrefslogtreecommitdiff
path: root/parse-options.c
diff options
context:
space:
mode:
Diffstat (limited to 'parse-options.c')
-rw-r--r--parse-options.c53
1 files changed, 31 insertions, 22 deletions
diff --git a/parse-options.c b/parse-options.c
index 62e9b1cc68..80106c06bc 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -14,8 +14,12 @@ static int parse_options_usage(struct parse_opt_ctx_t *ctx,
int optbug(const struct option *opt, const char *reason)
{
- if (opt->long_name)
+ if (opt->long_name) {
+ if (opt->short_name)
+ return error("BUG: switch '%c' (--%s) %s",
+ opt->short_name, opt->long_name, reason);
return error("BUG: option '%s' %s", opt->long_name, reason);
+ }
return error("BUG: switch '%c' %s", opt->short_name, reason);
}
@@ -127,10 +131,6 @@ static int get_value(struct parse_opt_ctx_t *p,
*(int *)opt->value = 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;
@@ -223,13 +223,10 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
const struct option *options)
{
const struct option *all_opts = options;
- const char *arg_end = strchr(arg, '=');
+ const char *arg_end = strchrnul(arg, '=');
const struct option *abbrev_option = NULL, *ambiguous_option = NULL;
int abbrev_flags = 0, ambiguous_flags = 0;
- if (!arg_end)
- arg_end = arg + strlen(arg);
-
for (; options->type != OPTION_END; options++) {
const char *rest, *long_name = options->long_name;
int flags = 0, opt_flags = 0;
@@ -238,7 +235,8 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
continue;
again:
- rest = skip_prefix(arg, long_name);
+ if (!skip_prefix(arg, long_name, &rest))
+ rest = NULL;
if (options->type == OPTION_ARGUMENT) {
if (!rest)
continue;
@@ -273,13 +271,13 @@ is_abbreviated:
if (options->flags & PARSE_OPT_NONEG)
continue;
/* negated and abbreviated very much? */
- if (!prefixcmp("no-", arg)) {
+ if (starts_with("no-", arg)) {
flags |= OPT_UNSET;
goto is_abbreviated;
}
/* negated? */
- if (prefixcmp(arg, "no-")) {
- if (!prefixcmp(long_name, "no-")) {
+ if (!starts_with(arg, "no-")) {
+ if (starts_with(long_name, "no-")) {
long_name += 3;
opt_flags |= OPT_UNSET;
goto again;
@@ -287,12 +285,13 @@ is_abbreviated:
continue;
}
flags |= OPT_UNSET;
- rest = skip_prefix(arg + 3, long_name);
- /* abbreviated and negated? */
- if (!rest && !prefixcmp(long_name, arg + 3))
- goto is_abbreviated;
- if (!rest)
- continue;
+ if (!skip_prefix(arg + 3, long_name, &rest)) {
+ /* abbreviated and negated? */
+ if (starts_with(long_name, arg + 3))
+ goto is_abbreviated;
+ else
+ continue;
+ }
}
if (*rest) {
if (*rest != '=')
@@ -334,7 +333,7 @@ static void check_typos(const char *arg, const struct option *options)
if (strlen(arg) < 3)
return;
- if (!prefixcmp(arg, "no-")) {
+ if (starts_with(arg, "no-")) {
error ("did you mean `--%s` (with two dashes ?)", arg);
exit(129);
}
@@ -342,7 +341,7 @@ static void check_typos(const char *arg, const struct option *options)
for (; options->type != OPTION_END; options++) {
if (!options->long_name)
continue;
- if (!prefixcmp(options->long_name, arg)) {
+ if (starts_with(options->long_name, arg)) {
error ("did you mean `--%s` (with two dashes ?)", arg);
exit(129);
}
@@ -352,12 +351,20 @@ static void check_typos(const char *arg, const struct option *options)
static void parse_options_check(const struct option *opts)
{
int err = 0;
+ char short_opts[128];
+ memset(short_opts, '\0', sizeof(short_opts));
for (; opts->type != OPTION_END; opts++) {
if ((opts->flags & PARSE_OPT_LASTARG_DEFAULT) &&
(opts->flags & PARSE_OPT_OPTARG))
err |= optbug(opts, "uses incompatible flags "
"LASTARG_DEFAULT and OPTARG");
+ if (opts->short_name) {
+ if (0x7F <= opts->short_name)
+ err |= optbug(opts, "invalid short name");
+ else if (short_opts[opts->short_name]++)
+ err |= optbug(opts, "short name already used");
+ }
if (opts->flags & PARSE_OPT_NODASH &&
((opts->flags & PARSE_OPT_OPTARG) ||
!(opts->flags & PARSE_OPT_NOARG) ||
@@ -370,7 +377,6 @@ static void parse_options_check(const struct option *opts)
case OPTION_BIT:
case OPTION_NEGBIT:
case OPTION_SET_INT:
- case OPTION_SET_PTR:
case OPTION_NUMBER:
if ((opts->flags & PARSE_OPT_OPTARG) ||
!(opts->flags & PARSE_OPT_NOARG))
@@ -378,6 +384,9 @@ static void parse_options_check(const struct option *opts)
default:
; /* ok. (usually accepts an argument) */
}
+ if (opts->argh &&
+ strcspn(opts->argh, " _") != strlen(opts->argh))
+ err |= optbug(opts, "multi-word argh should use dash to separate words");
}
if (err)
exit(128);