summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/mpv.rst23
-rw-r--r--core/cfg-mplayer.h8
-rw-r--r--core/m_config.c126
-rw-r--r--core/m_config.h56
-rw-r--r--core/m_option.c23
-rw-r--r--core/m_option.h23
-rw-r--r--core/parser-cfg.c38
-rw-r--r--core/parser-mpcmd.c85
8 files changed, 175 insertions, 207 deletions
diff --git a/DOCS/man/en/mpv.rst b/DOCS/man/en/mpv.rst
index 60f8d0cabc..5f6a659e69 100644
--- a/DOCS/man/en/mpv.rst
+++ b/DOCS/man/en/mpv.rst
@@ -285,29 +285,6 @@ the *XXX* option or if *XXX* is compiled in.
| Or in a script:
| `mpv --ao=pcm:file=%\`expr length "$NAME"\`%"$NAME" test.avi`
-Single dash versus double dash options
---------------------------------------
-
-There are actually two option syntaxes: one which uses a single dash (``-opt``),
-and one with double dashes (``--opt``). The double dash syntax always requires
-a ``=`` to separate option name and value, while single dash options use a
-space.
-
-
-| Both of these examples pass the value `pcm:file=test.wav` to the `ao` option:
-| `mpv -ao pcm:file=test.wav`
-| `mpv --ao=pcm:file=test.wav`
-
-| This passes the empty string to `ao`, while `pcm:file=test.wav` is interpreted
- as filename (common mistake):
-| `mpv --ao pcm:file=test.wav`
-
-It's best to stick to one syntax to avoid usage errors. The double dash syntax
-is preferred, and used throughout the manpage.
-
-*NOTE*: the differences between these syntaxes might be removed in the future.
-However, this has not happened yet.
-
Per-file options
----------------
diff --git a/core/cfg-mplayer.h b/core/cfg-mplayer.h
index c581fe59fe..edab5f37e4 100644
--- a/core/cfg-mplayer.h
+++ b/core/cfg-mplayer.h
@@ -549,10 +549,10 @@ const m_option_t mplayer_opts[]={
OPT_FLOATRANGE("softvol-max", softvol_max, 0, 10, 10000),
{"volstep", &volstep, CONF_TYPE_INT, CONF_RANGE, 0, 100, NULL},
OPT_FLOATRANGE("volume", mixer_init_volume, 0, -1, 10000),
- OPT_CHOICE("mute", mixer_init_mute, 0,
+ OPT_CHOICE("mute", mixer_init_mute, M_OPT_OPTIONAL_PARAM,
({"auto", -1},
{"no", 0},
- {"yes", 1})),
+ {"yes", 1}, {"", 1})),
OPT_MAKE_FLAGS("gapless-audio", gapless_audio, 0),
// override audio buffer size (used only by -ao oss/win32, obsolete)
OPT_INT("abs", ao_buffersize, 0),
@@ -635,7 +635,7 @@ const m_option_t mplayer_opts[]={
OPT_CHOICE("framedrop", frame_dropping, 0,
({"no", 0},
- {"yes", 1}, {"", 1},
+ {"yes", 1},
{"hard", 2})),
OPT_FLAG_ON("untimed", untimed, 0),
@@ -673,7 +673,7 @@ const m_option_t mplayer_opts[]={
OPT_CHOICE("term-osd", term_osd, 0,
({"force", 1},
- {"auto", 2}, {"", 2},
+ {"auto", 2},
{"no", 0})),
OPT_STRING("term-osd-esc", term_osd_esc, 0, OPTDEF_STR("\x1b[A\r\x1b[K")),
diff --git a/core/m_config.c b/core/m_config.c
index f95af2baea..2d994bb802 100644
--- a/core/m_config.c
+++ b/core/m_config.c
@@ -384,20 +384,18 @@ struct m_config_option *m_config_get_co(const struct m_config *config,
}
static int parse_subopts(struct m_config *config, void *optstruct, char *name,
- char *prefix, struct bstr param, bool set);
+ char *prefix, struct bstr param, int flags);
static int m_config_parse_option(struct m_config *config, void *optstruct,
- struct bstr name, struct bstr param, bool set)
+ struct bstr name, struct bstr param, int flags)
{
assert(config != NULL);
assert(name.len != 0);
+ bool set = !(flags & M_SETOPT_CHECK_ONLY);
- if (m_config_map_option(config, &name, &param) == M_OPT_INVALID) {
- mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,
- "A no-* option can't take parameters: --%.*s=%.*s\n",
- BSTR_P(name), BSTR_P(param));
- return M_OPT_INVALID;
- }
+ 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)
@@ -406,8 +404,11 @@ static int m_config_parse_option(struct m_config *config, void *optstruct,
// This is the only mandatory function
assert(co->opt->type->parse);
+ if ((flags & M_SETOPT_PRE_PARSE_ONLY) && !(co->opt->flags & M_OPT_PRE_PARSE))
+ return 0;
+
// Check if this option isn't forbidden in the current mode
- if ((config->mode == M_CONFIG_FILE) && (co->opt->flags & M_OPT_NOCFG)) {
+ if ((flags & M_SETOPT_FROM_CONFIG_FILE) && (co->opt->flags & M_OPT_NOCFG)) {
mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,
"The %.*s option can't be used in a config file.\n",
BSTR_P(name));
@@ -430,7 +431,7 @@ static int m_config_parse_option(struct m_config *config, void *optstruct,
char prefix[110];
assert(strlen(co->name) < 100);
sprintf(prefix, "%s:", co->name);
- return parse_subopts(config, optstruct, co->name, prefix, param, set);
+ return parse_subopts(config, optstruct, co->name, prefix, param, flags);
}
if (set)
@@ -440,7 +441,7 @@ static int m_config_parse_option(struct m_config *config, void *optstruct,
}
static int parse_subopts(struct m_config *config, void *optstruct, char *name,
- char *prefix, struct bstr param, bool set)
+ char *prefix, struct bstr param, int flags)
{
char **lst = NULL;
// Split the argument into child options
@@ -453,21 +454,15 @@ static int parse_subopts(struct m_config *config, void *optstruct, char *name,
char n[110];
if (snprintf(n, 110, "%s%s", prefix, lst[2 * i]) > 100)
abort();
- int sr = m_config_parse_option(config, optstruct, bstr0(n),
- bstr0(lst[2 * i + 1]), set);
- if (sr < 0) {
- if (sr == M_OPT_UNKNOWN) {
- mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,
- "Error: option '%s' has no suboption '%s'.\n",
- name, lst[2 * i]);
- r = M_OPT_INVALID;
- } else if (sr == M_OPT_MISSING_PARAM) {
+ r = m_config_parse_option(config, optstruct, bstr0(n),
+ bstr0(lst[2 * i + 1]), flags);
+ if (r < 0) {
+ if (r > M_OPT_EXIT) {
mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,
- "Error: suboption '%s' of '%s' must have "
- "a parameter!\n", lst[2 * i], name);
+ "Error parsing suboption %s/%s (%s)\n",
+ name, lst[2 * i], m_option_strerror(r));
r = M_OPT_INVALID;
- } else
- r = sr;
+ }
break;
}
}
@@ -475,39 +470,38 @@ static int parse_subopts(struct m_config *config, void *optstruct, char *name,
return r;
}
-int m_config_set_option(struct m_config *config, struct bstr name,
- struct bstr param)
+int m_config_parse_suboptions(struct m_config *config, char *name,
+ char *subopts)
{
- mp_msg(MSGT_CFGPARSER, MSGL_DBG2, "Setting %.*s=%.*s\n", BSTR_P(name),
- BSTR_P(param));
- return m_config_parse_option(config, config->optstruct, name, param, true);
+ if (!subopts || !*subopts)
+ return 0;
+ int r = parse_subopts(config, config->optstruct, name, "", bstr0(subopts), 0);
+ if (r < 0 && r > M_OPT_EXIT) {
+ mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, "Error parsing suboption %s (%s)\n",
+ name, m_option_strerror(r));
+ r = M_OPT_INVALID;
+ }
+ return r;
}
-int m_config_check_option(struct m_config *config, struct bstr name,
- struct bstr param)
+int m_config_set_option_ext(struct m_config *config, struct bstr name,
+ struct bstr param, int flags)
{
- int r;
- mp_msg(MSGT_CFGPARSER, MSGL_DBG2, "Checking %.*s=%.*s\n", BSTR_P(name),
- BSTR_P(param));
- r = m_config_parse_option(config, NULL, name, param, 0);
- if (r == M_OPT_MISSING_PARAM) {
- mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,
- "Error: option '%.*s' must have a parameter!\n", BSTR_P(name));
- return M_OPT_INVALID;
+ int r = m_config_parse_option(config, config->optstruct, name, param, flags);
+ if (r < 0 && r > M_OPT_EXIT) {
+ mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, "Error parsing option %.*s (%s)\n",
+ BSTR_P(name), m_option_strerror(r));
+ r = M_OPT_INVALID;
}
return r;
}
-int m_config_parse_suboptions(struct m_config *config, char *name,
- char *subopts)
+int m_config_set_option(struct m_config *config, struct bstr name,
+ struct bstr param)
{
- if (!subopts || !*subopts)
- return 0;
- return parse_subopts(config, config->optstruct, name, "", bstr0(subopts),
- true);
+ return m_config_set_option_ext(config, name, param, 0);
}
-
const struct m_option *m_config_get_option(const struct m_config *config,
struct bstr name)
{
@@ -522,16 +516,24 @@ 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)
+int m_config_map_option(struct m_config *config, bstr *name, bstr *param,
+ bool ambiguous)
{
bstr s = *name;
- if (m_config_get_option(config, s))
- return 0;
+ const struct m_option *opt = m_config_get_option(config, s);
+ 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)))
+ return 0;
+ return 1;
+ }
if (!bstr_eatstart0(&s, "no-"))
return M_OPT_UNKNOWN;
- const struct m_option *opt = m_config_get_option(config, s);
+ 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;
@@ -539,7 +541,7 @@ int m_config_map_option(struct m_config *config, bstr *name, bstr *param)
if (bstr_startswith(bstr0(opt->name), bstr0("no-")))
return M_OPT_UNKNOWN;
if (param->len)
- return M_OPT_INVALID;
+ return M_OPT_DISALLOW_PARAM;
*name = s;
*param = bstr0("no");
return 0;
@@ -610,14 +612,16 @@ void m_profile_set_desc(struct m_profile *p, char *desc)
}
int m_config_set_profile_option(struct m_config *config, struct m_profile *p,
- char *name, char *val)
+ bstr name, bstr val)
{
- int i = m_config_check_option0(config, name, val);
+ int i = m_config_set_option_ext(config, name, val,
+ M_SETOPT_CHECK_ONLY |
+ M_SETOPT_FROM_CONFIG_FILE);
if (i < 0)
return i;
p->opts = talloc_realloc(p, p->opts, char *, 2 * (p->num_opts + 2));
- p->opts[p->num_opts * 2] = talloc_strdup(p, name);
- p->opts[p->num_opts * 2 + 1] = talloc_strdup(p, val);
+ p->opts[p->num_opts * 2] = bstrdup0(p, name);
+ p->opts[p->num_opts * 2 + 1] = bstrdup0(p, val);
p->num_opts++;
p->opts[p->num_opts * 2] = p->opts[p->num_opts * 2 + 1] = NULL;
return 1;
@@ -625,19 +629,19 @@ int m_config_set_profile_option(struct m_config *config, struct m_profile *p,
void m_config_set_profile(struct m_config *config, struct m_profile *p)
{
- int i;
if (config->profile_depth > MAX_PROFILE_DEPTH) {
mp_tmsg(MSGT_CFGPARSER, MSGL_WARN,
"WARNING: Profile inclusion too deep.\n");
return;
}
- int prev_mode = config->mode;
- config->mode = M_CONFIG_FILE;
config->profile_depth++;
- for (i = 0; i < p->num_opts; i++)
- m_config_set_option0(config, p->opts[2 * i], p->opts[2 * i + 1]);
+ for (int i = 0; i < p->num_opts; i++) {
+ m_config_set_option_ext(config,
+ bstr0(p->opts[2 * i]),
+ bstr0(p->opts[2 * i + 1]),
+ M_SETOPT_FROM_CONFIG_FILE);
+ }
config->profile_depth--;
- config->mode = prev_mode;
}
void *m_config_alloc_struct(void *talloc_parent,
diff --git a/core/m_config.h b/core/m_config.h
index 8b9b0dc7f7..57170cf48a 100644
--- a/core/m_config.h
+++ b/core/m_config.h
@@ -64,13 +64,6 @@ struct m_profile {
char **opts;
};
-enum option_source {
- // Set when parsing command line arguments.
- M_COMMAND_LINE,
- // Set when parsing from a config file.
- M_CONFIG_FILE,
-};
-
// Config object
/** \ingroup Config */
typedef struct m_config {
@@ -78,7 +71,6 @@ typedef struct m_config {
/** This contains all options and suboptions.
*/
struct m_config_option *opts;
- enum option_source mode;
// When options are set (via m_config_set_option or m_config_set_profile),
// back up the old value (unless it's already backed up). Used for restoring
// global options when per-file options are set.
@@ -114,7 +106,19 @@ void m_config_leave_file_local(struct m_config *config);
int m_config_register_options(struct m_config *config,
const struct m_option *args);
-/* Set an option.
+enum {
+ M_SETOPT_PRE_PARSE_ONLY = 1, // Silently ignore non-M_OPT_PRE_PARSE opt.
+ M_SETOPT_CHECK_ONLY = 2, // Don't set, just check name/value
+ M_SETOPT_FROM_CONFIG_FILE = 4, // Reject M_OPT_NOCFG opt. (print error)
+};
+
+// Set the named option to the given string.
+// flags: combination of M_SETOPT_* flags (0 for normal operation)
+// Returns >= 0 on success, otherwise see OptionParserReturn.
+int m_config_set_option_ext(struct m_config *config, struct bstr name,
+ struct bstr param, int flags);
+
+/* Set an option. (Like: m_config_set_option_ext(config, name, param, 0))
* \param config The config object.
* \param name The option's name.
* \param param The value of the option, can be NULL.
@@ -129,18 +133,6 @@ static inline int m_config_set_option0(struct m_config *config,
return m_config_set_option(config, bstr0(name), bstr0(param));
}
-/* Check if an option setting is valid.
- * Same as above m_config_set_option() but doesn't actually set anything.
- */
-int m_config_check_option(struct m_config *config, struct bstr name,
- struct bstr param);
-
-static inline int m_config_check_option0(struct m_config *config,
- const char *name, const char *param)
-{
- return m_config_check_option(config, bstr0(name), bstr0(param));
-}
-
int m_config_parse_suboptions(struct m_config *config, char *name,
char *subopts);
@@ -156,15 +148,19 @@ 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 The config object.
- * \param name The option's name. May be set to a new name.
- * \param param The option value. May be set to a new value.
- * \return The following error codes:
- * M_OPT_UNKNOWN: option not found
- * M_OPT_INVALID: parameter non-empty in map case, prevents the mapping
- * 0: success, *name and *param have been changed (or not)
+ * 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 *param);
+int m_config_map_option(struct m_config *config, bstr *name, bstr *value,
+ bool ambiguous);
/* Print a list of all registered options.
* \param config The config object.
@@ -204,7 +200,7 @@ void m_profile_set_desc(struct m_profile *p, char *desc);
* \param val The option's value.
*/
int m_config_set_profile_option(struct m_config *config, struct m_profile *p,
- char *name, char *val);
+ bstr name, bstr val);
/* Enables profile usage
* Used by the config file parser when loading a profile.
diff --git a/core/m_option.c b/core/m_option.c
index 078f9f327b..595675cebb 100644
--- a/core/m_option.c
+++ b/core/m_option.c
@@ -43,17 +43,18 @@ char *m_option_strerror(int code)
{
switch (code) {
case M_OPT_UNKNOWN:
- return mp_gtext("Unrecognized option name");
+ return mp_gtext("option not found");
case M_OPT_MISSING_PARAM:
- return mp_gtext("Required parameter for option missing");
+ return mp_gtext("option requires parameter");
case M_OPT_INVALID:
- return mp_gtext("Option parameter could not be parsed");
+ return mp_gtext("option parameter could not be parsed");
case M_OPT_OUT_OF_RANGE:
- return mp_gtext("Parameter is outside values allowed for option");
+ return mp_gtext("parameter is outside values allowed for option");
+ case M_OPT_DISALLOW_PARAM:
+ return mp_gtext("option doesn't take a parameter");
case M_OPT_PARSER_ERR:
- return mp_gtext("Parser error");
default:
- return NULL;
+ return mp_gtext("parser error");
}
}
@@ -144,7 +145,7 @@ const m_option_type_t m_option_type_flag = {
// need yes or no in config files
.name = "Flag",
.size = sizeof(int),
- .flags = M_OPT_TYPE_OLD_SYNTAX_NO_PARAM,
+ .flags = M_OPT_TYPE_OPTIONAL_PARAM,
.parse = parse_flag,
.print = print_flag,
.copy = copy_opt,
@@ -165,7 +166,7 @@ static int parse_store(const m_option_t *opt, struct bstr name,
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
"Invalid parameter for %.*s flag: %.*s\n",
BSTR_P(name), BSTR_P(param));
- return M_OPT_INVALID;
+ return M_OPT_DISALLOW_PARAM;
}
}
@@ -173,7 +174,7 @@ const m_option_type_t m_option_type_store = {
// can only be activated
.name = "Flag",
.size = sizeof(int),
- .flags = M_OPT_TYPE_OLD_SYNTAX_NO_PARAM,
+ .flags = M_OPT_TYPE_OPTIONAL_PARAM,
.parse = parse_store,
};
@@ -1039,7 +1040,7 @@ static int parse_print(const m_option_t *opt, struct bstr name,
const m_option_type_t m_option_type_print = {
.name = "Print",
- .flags = M_OPT_TYPE_OLD_SYNTAX_NO_PARAM,
+ .flags = M_OPT_TYPE_OPTIONAL_PARAM,
.parse = parse_print,
};
@@ -1051,7 +1052,7 @@ const m_option_type_t m_option_type_print_func_param = {
const m_option_type_t m_option_type_print_func = {
.name = "Print",
- .flags = M_OPT_TYPE_ALLOW_WILDCARD | M_OPT_TYPE_OLD_SYNTAX_NO_PARAM,
+ .flags = M_OPT_TYPE_ALLOW_WILDCARD | M_OPT_TYPE_OPTIONAL_PARAM,
.parse = parse_print,
};
diff --git a/core/m_option.h b/core/m_option.h
index a3da08ea7a..e63bf3610f 100644
--- a/core/m_option.h
+++ b/core/m_option.h
@@ -363,6 +363,9 @@ struct m_option {
// (e.g. "--parent=child=value" becomes "--child=value")
#define M_OPT_MERGE (1 << 9)
+// See M_OPT_TYPE_OPTIONAL_PARAM.
+#define M_OPT_OPTIONAL_PARAM (1 << 10)
+
// These are kept for compatibility with older code.
#define CONF_MIN M_OPT_MIN
#define CONF_MAX M_OPT_MAX
@@ -397,10 +400,11 @@ struct m_option {
*/
#define M_OPT_TYPE_DYNAMIC (1 << 2)
-// The parameter is optional and by default no parameter is preferred. If the
-// "old syntax" is used, the command line parser will assume that the argument
-// takes no parameter.
-#define M_OPT_TYPE_OLD_SYNTAX_NO_PARAM (1 << 3)
+// The parameter is optional and by default no parameter is preferred. If
+// ambiguous syntax is used ("--opt value"), the command line parser will
+// assume that the argument takes no parameter. In config files, these
+// options can be used without "=" and value.
+#define M_OPT_TYPE_OPTIONAL_PARAM (1 << 3)
// modify M_OPT_TYPE_HAS_CHILD so that m_option::p points to
// struct m_sub_options, instead of a direct m_option array.
@@ -408,7 +412,9 @@ struct m_option {
///////////////////////////// Parser flags /////////////////////////////////
-// On success parsers return the number of arguments consumed: 0 or 1.
+// OptionParserReturn
+//
+// On success parsers return a number >= 0.
//
// To indicate that MPlayer should exit without playing anything,
// parsers return M_OPT_EXIT minus the number of parameters they
@@ -429,13 +435,16 @@ struct m_option {
// vary from type to type.
#define M_OPT_OUT_OF_RANGE -4
+// The option doesn't take a parameter.
+#define M_OPT_DISALLOW_PARAM -5
+
// Returned if the parser failed for any other reason than a bad parameter.
-#define M_OPT_PARSER_ERR -5
+#define M_OPT_PARSER_ERR -6
// Returned when MPlayer should exit. Used by various help stuff.
/** M_OPT_EXIT must be the lowest number on this list.
*/
-#define M_OPT_EXIT -6
+#define M_OPT_EXIT -7
char *m_option_strerror(int code);
diff --git a/core/parser-cfg.c b/core/parser-cfg.c
index 1a67389854..e5bf6eb3b5 100644
--- a/core/parser-cfg.c
+++ b/core/parser-cfg.c
@@ -61,7 +61,6 @@ int m_config_parse_config_file(m_config_t *config, const char *conffile)
int param_pos; /* param pos */
int ret = 1;
int errors = 0;
- int prev_mode = config->mode;
m_profile_t *profile = NULL;
mp_msg(MSGT_CFGPARSER, MSGL_V, "Reading config file %s", conffile);
@@ -71,9 +70,7 @@ int m_config_parse_config_file(m_config_t *config, const char *conffile)
": too deep 'include'. check your configfiles\n");
ret = -1;
goto out;
- } else
-
- config->mode = M_CONFIG_FILE;
+ }
if ((line = malloc(MAX_LINE_LEN + 1)) == NULL) {
mp_msg(MSGT_CFGPARSER, MSGL_FATAL,
@@ -145,10 +142,13 @@ int m_config_parse_config_file(m_config_t *config, const char *conffile)
++line_pos;
param_pos = 0;
+ bool param_set = false;
/* check '=' */
if (line[line_pos] == '=') {
line_pos++;
+ param_set = true;
+
/* whitespaces... */
while (isspace(line[line_pos]))
++line_pos;
@@ -197,23 +197,34 @@ int m_config_parse_config_file(m_config_t *config, const char *conffile)
ret = -1;
}
+ bstr bopt = bstr0(opt);
+ bstr bparam = bstr0(param);
+
+ tmp = m_config_map_option(config, &bopt, &bparam, false);
+ if (tmp > 0 && !param_set)
+ tmp = M_OPT_MISSING_PARAM;
+ if (tmp < 0) {
+ PRINT_LINENUM;
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR,
+ "error parsing option %s=%s: %s\n",
+ opt, param, m_option_strerror(tmp));
+ continue;
+ }
+
if (profile) {
if (!strcmp(opt, "profile-desc"))
m_profile_set_desc(profile, param), tmp = 1;
else
tmp = m_config_set_profile_option(config, profile,
- opt, param);
- } else
- tmp = m_config_set_option0(config, opt, param);
+ bopt, bparam);
+ } else {
+ tmp = m_config_set_option_ext(config, bopt, bparam,
+ M_SETOPT_FROM_CONFIG_FILE);
+ }
if (tmp < 0) {
PRINT_LINENUM;
- if (tmp == M_OPT_UNKNOWN) {
- mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "unknown option '%s'\n", opt);
- continue;
- }
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
- "setting option %s='%s' failed\n", opt, param);
+ "setting option %s='%s' failed.\n", opt, param);
continue;
/* break */
}
@@ -225,7 +236,6 @@ out:
free(line);
if (fp)
fclose(fp);
- config->mode = prev_mode;
--recursion_depth;
if (ret < 0) {
mp_msg(MSGT_CFGPARSER, MSGL_FATAL, "Error loading config file %s.\n",
diff --git a/core/parser-mpcmd.c b/core/parser-mpcmd.c
index 025c7faf97..9914e7a614 100644
--- a/core/parser-mpcmd.c
+++ b/core/parser-mpcmd.c
@@ -47,7 +47,7 @@ struct parse_state {
bool no_more_opts;
bool error;
- const struct m_option *mp_opt; // NULL <=> it's a file arg
+ bool is_opt;
struct bstr arg;
struct bstr param;
};
@@ -60,7 +60,7 @@ static int split_opt_silent(struct parse_state *p)
if (p->argc < 1)
return 1;
- p->mp_opt = NULL;
+ p->is_opt = false;
p->arg = bstr0(p->argv[0]);
p->param = bstr0(NULL);
@@ -75,35 +75,20 @@ static int split_opt_silent(struct parse_state *p)
return split_opt_silent(p);
}
- bool old_syntax = !bstr_startswith0(p->arg, "--");
- if (old_syntax) {
- p->arg = bstr_cut(p->arg, 1);
- } else {
- p->arg = bstr_cut(p->arg, 2);
- int idx = bstrchr(p->arg, '=');
- if (idx > 0) {
- p->param = bstr_cut(p->arg, idx + 1);
- p->arg = bstr_splice(p->arg, 0, idx);
- }
- }
+ p->is_opt = true;
- if (m_config_map_option(p->config, &p->arg, &p->param) == M_OPT_INVALID)
- return -2;
+ if (!bstr_eatstart0(&p->arg, "--"))
+ bstr_eatstart0(&p->arg, "-");
- p->mp_opt = m_config_get_option(p->config, p->arg);
- if (!p->mp_opt)
- return -1;
+ bool ambiguous = !bstr_split_tok(p->arg, "=", &p->arg, &p->param);
- if ((p->mp_opt->type->flags & M_OPT_TYPE_OLD_SYNTAX_NO_PARAM)
- || p->param.len
- || bstr_endswith0(p->arg, "-clr"))
- {
- old_syntax = false;
- }
+ int r = m_config_map_option(p->config, &p->arg, &p->param, ambiguous);
+ if (r < 0)
+ return r;
- if (old_syntax) {
+ if (ambiguous && r > 0) {
if (p->argc < 1)
- return -3;
+ return M_OPT_MISSING_PARAM;
p->param = bstr0(p->argv[0]);
p->argc--;
p->argv++;
@@ -119,17 +104,10 @@ static bool split_opt(struct parse_state *p)
if (r >= 0)
return r == 0;
p->error = true;
- if (r == -2)
- mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,
- "A no-* option can't take parameters: --%.*s=%.*s\n",
- BSTR_P(p->arg), BSTR_P(p->param));
- else if (r == -3)
- mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,
- "Option %.*s needs a parameter.\n", BSTR_P(p->arg));
- else
- mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,
- "Unknown option on the command line: %.*s\n",
- BSTR_P(p->arg));
+
+ mp_tmsg(MSGT_CFGPARSER, MSGL_FATAL,
+ "Error parsing commandline option %.*s: %s\n",
+ BSTR_P(p->arg), m_option_strerror(r));
return false;
}
@@ -154,7 +132,6 @@ bool m_config_parse_mp_command_line(m_config_t *config, struct playlist *files,
assert(config != NULL);
assert(!config->file_local_mode);
- config->mode = M_COMMAND_LINE;
mode = GLOBAL;
#ifdef CONFIG_MACOSX_FINDER
if (macosx_finder_args(config, files, argc, argv))
@@ -163,22 +140,16 @@ bool m_config_parse_mp_command_line(m_config_t *config, struct playlist *files,
struct parse_state p = {config, argc, argv};
while (split_opt(&p)) {
- if (p.mp_opt) {
+ if (p.is_opt) {
int r;
- if (mode == GLOBAL && !(p.mp_opt->flags & M_OPT_PRE_PARSE)) {
- r = m_config_set_option(config, p.arg, p.param);
- } else {
- r = m_config_check_option(config, p.arg, p.param);
- }
+ r = m_config_set_option_ext(config, p.arg, p.param,
+ mode == LOCAL ? M_SETOPT_CHECK_ONLY : 0);
if (r <= M_OPT_EXIT)
goto err_out;
if (r < 0) {
- char *msg = m_option_strerror(r);
- if (!msg)
- goto print_err;
mp_tmsg(MSGT_CFGPARSER, MSGL_FATAL,
- "Error parsing commandline option %.*s: %s\n",
- BSTR_P(p.arg), msg);
+ "Setting commandline option --%.*s=%.*s failed.\n",
+ BSTR_P(p.arg), BSTR_P(p.param));
goto err_out;
}
@@ -237,8 +208,11 @@ bool m_config_parse_mp_command_line(m_config_t *config, struct playlist *files,
char *param0 = bstrdup0(NULL, p.param);
struct playlist *pl = playlist_parse_file(param0);
talloc_free(param0);
- if (!pl)
- goto print_err;
+ if (!pl) {
+ mp_tmsg(MSGT_CFGPARSER, MSGL_FATAL,
+ "Error reading playlist '%.*s'", BSTR_P(p.param));
+ goto err_out;
+ }
playlist_transfer_entries(files, pl);
talloc_free(pl);
continue;
@@ -305,9 +279,6 @@ bool m_config_parse_mp_command_line(m_config_t *config, struct playlist *files,
assert(!config->file_local_mode);
return true;
-print_err:
- mp_tmsg(MSGT_CFGPARSER, MSGL_FATAL,
- "Error parsing option on the command line: %.*s\n", BSTR_P(p.arg));
err_out:
talloc_free(local_params);
if (config->file_local_mode)
@@ -330,11 +301,11 @@ void m_config_preparse_command_line(m_config_t *config, int argc, char **argv)
struct parse_state p = {config, argc, argv};
while (split_opt_silent(&p) == 0) {
- if (p.mp_opt) {
+ if (p.is_opt) {
// Ignore non-pre-parse options. They will be set later.
// Option parsing errors will be handled later as well.
- if (p.mp_opt->flags & M_OPT_PRE_PARSE)
- m_config_set_option(config, p.arg, p.param);
+ m_config_set_option_ext(config, p.arg, p.param,
+ M_SETOPT_PRE_PARSE_ONLY);
if (bstrcmp0(p.arg, "v") == 0)
verbose++;
}