summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/m_config.c74
-rw-r--r--core/m_config.h20
-rw-r--r--core/parser-cfg.c4
-rw-r--r--core/parser-mpcmd.c2
4 files changed, 55 insertions, 45 deletions
diff --git a/core/m_config.c b/core/m_config.c
index 2d994bb802..6ecfa13a39 100644
--- a/core/m_config.c
+++ b/core/m_config.c
@@ -257,6 +257,43 @@ void m_config_leave_file_local(struct m_config *config)
}
}
+// Given an option --opt, add --no-opt (if applicable).
+static void add_negation_option(struct m_config *config,
+ struct m_config_option *parent,
+ const struct m_option *opt)
+{
+ int value;
+ if (opt->type == CONF_TYPE_FLAG) {
+ value = opt->min;
+ } else if (opt->type == CONF_TYPE_CHOICE) {
+ // Find out whether there's a "no" choice.
+ // m_option_parse() should be used for this, but it prints
+ // unsilenceable error messages.
+ struct m_opt_choice_alternatives *alt = opt->priv;
+ for ( ; alt->name; alt++) {
+ if (strcmp(alt->name, "no") == 0)
+ break;
+ }
+ if (!alt->name)
+ return;
+ value = alt->value;
+ } else {
+ return;
+ }
+ struct m_option *no_opt = talloc_ptrtype(config, no_opt);
+ *no_opt = (struct m_option) {
+ .name = talloc_asprintf(no_opt, "no-%s", opt->name),
+ .type = CONF_TYPE_STORE,
+ .flags = opt->flags & (M_OPT_NOCFG | M_OPT_GLOBAL | M_OPT_LOCAL |
+ M_OPT_PRE_PARSE | M_OPT_PREFIXED | M_OPT_MERGE),
+ .new = opt->new,
+ .p = opt->p,
+ .offset = opt->offset,
+ .max = value,
+ };
+ m_config_add_option(config, parent, no_opt);
+}
+
static void add_options(struct m_config *config,
struct m_config_option *parent,
const struct m_option *defs)
@@ -352,6 +389,8 @@ static void m_config_add_option(struct m_config *config,
co->next = config->opts;
config->opts = co;
}
+
+ add_negation_option(config, parent, arg);
}
int m_config_register_options(struct m_config *config,
@@ -393,10 +432,6 @@ static int m_config_parse_option(struct m_config *config, void *optstruct,
assert(name.len != 0);
bool set = !(flags & M_SETOPT_CHECK_ONLY);
- int r = m_config_map_option(config, &name, &param, false);
- if (r < 0)
- return r;
-
struct m_config_option *co = m_config_get_co(config, name);
if (!co)
return M_OPT_UNKNOWN;
@@ -516,35 +551,18 @@ const struct m_option *m_config_get_option(const struct m_config *config,
return NULL;
}
-int m_config_map_option(struct m_config *config, bstr *name, bstr *param,
- bool ambiguous)
+int m_config_option_requires_param(struct m_config *config, bstr name)
{
- bstr s = *name;
- const struct m_option *opt = m_config_get_option(config, s);
+ const struct m_option *opt = m_config_get_option(config, name);
if (opt) {
- if (bstr_endswith0(s, "-clr"))
- return (ambiguous || !param->len) ? 0 : M_OPT_DISALLOW_PARAM;
- if (ambiguous && ((opt->flags & M_OPT_OPTIONAL_PARAM) ||
- (opt->type->flags & M_OPT_TYPE_OPTIONAL_PARAM)))
+ if (bstr_endswith0(name, "-clr"))
+ return 0;
+ if (((opt->flags & M_OPT_OPTIONAL_PARAM) ||
+ (opt->type->flags & M_OPT_TYPE_OPTIONAL_PARAM)))
return 0;
return 1;
}
-
- if (!bstr_eatstart0(&s, "no-"))
- return M_OPT_UNKNOWN;
-
- opt = m_config_get_option(config, s);
- if (!opt || (opt->type != &m_option_type_flag
- && opt->type != &m_option_type_choice))
- return M_OPT_UNKNOWN;
- // Avoid allowing "--no-no-opt".
- if (bstr_startswith(bstr0(opt->name), bstr0("no-")))
- return M_OPT_UNKNOWN;
- if (param->len)
- return M_OPT_DISALLOW_PARAM;
- *name = s;
- *param = bstr0("no");
- return 0;
+ return M_OPT_UNKNOWN;
}
void m_config_print_option_list(const struct m_config *config)
diff --git a/core/m_config.h b/core/m_config.h
index 57170cf48a..86376e4849 100644
--- a/core/m_config.h
+++ b/core/m_config.h
@@ -147,20 +147,12 @@ const struct m_option *m_config_get_option(const struct m_config *config,
struct m_config_option *m_config_get_co(const struct m_config *config,
struct bstr name);
-/* Map options like "no-opt=" to "opt=no".
- * config: config object.
- * name: option's name. May be set to a new name.
- * value: option value. May be set to a new value.
- * ambiguous: if true, "value" may be either an option value, or a separate,
- * unrelated option following the current option.
- * returns the following error codes:
- * < 0: one of the M_OPT_ error codes
- * 0: the option is valid, *value is set implicitly
- * ("--foo bar" maps to "--foo=yes" + "bar", *value == "yes")
- * 1: the option is valid, *value is a proper parameter
- */
-int m_config_map_option(struct m_config *config, bstr *name, bstr *value,
- bool ambiguous);
+// Return a hint to the option parser whether a parameter is/may be required.
+// The option may still accept empty/non-empty parameters independent from
+// this, and this function is useful only for handling ambiguous options like
+// flags (e.g. "--a" is ok, "--a=yes" is also ok).
+// Returns: error code (<0), or number of expected params (0, 1)
+int m_config_option_requires_param(struct m_config *config, bstr name);
/* Print a list of all registered options.
* \param config The config object.
diff --git a/core/parser-cfg.c b/core/parser-cfg.c
index e5bf6eb3b5..5d63d27c52 100644
--- a/core/parser-cfg.c
+++ b/core/parser-cfg.c
@@ -200,7 +200,7 @@ int m_config_parse_config_file(m_config_t *config, const char *conffile)
bstr bopt = bstr0(opt);
bstr bparam = bstr0(param);
- tmp = m_config_map_option(config, &bopt, &bparam, false);
+ tmp = m_config_option_requires_param(config, bopt);
if (tmp > 0 && !param_set)
tmp = M_OPT_MISSING_PARAM;
if (tmp < 0) {
@@ -213,7 +213,7 @@ int m_config_parse_config_file(m_config_t *config, const char *conffile)
if (profile) {
if (!strcmp(opt, "profile-desc"))
- m_profile_set_desc(profile, param), tmp = 1;
+ m_profile_set_desc(profile, param);
else
tmp = m_config_set_profile_option(config, profile,
bopt, bparam);
diff --git a/core/parser-mpcmd.c b/core/parser-mpcmd.c
index 1a7a4dcbc9..fd22a1e054 100644
--- a/core/parser-mpcmd.c
+++ b/core/parser-mpcmd.c
@@ -82,7 +82,7 @@ static int split_opt_silent(struct parse_state *p)
bool ambiguous = !bstr_split_tok(p->arg, "=", &p->arg, &p->param);
- int r = m_config_map_option(p->config, &p->arg, &p->param, ambiguous);
+ int r = m_config_option_requires_param(p->config, p->arg);
if (r < 0)
return r;