summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-09-21 09:22:25 +0200
committerwm4 <wm4@nowhere>2013-02-09 00:21:17 +0100
commit267a889cc2c5ca688a2b8fc93cf8e5349a3c8a44 (patch)
treeee2561f256db05092e61fa797be4b7ecaf3db991
parent5412993724aee1126bfc8dfbc0422ebe5251b9b6 (diff)
downloadmpv-267a889cc2c5ca688a2b8fc93cf8e5349a3c8a44.tar.bz2
mpv-267a889cc2c5ca688a2b8fc93cf8e5349a3c8a44.tar.xz
options: unify single dash and double dash options
There were two option syntax variations: "old": -opt value "new": --opt=value "-opt=value" was invalid, and "--opt value" meant "--opt=" followed by a separate option "value" (i.e. interpreted as filename). There isn't really any reason to do this. The "old" syntax used to be ambiguous (you had to call the option parser to know whether the following argument is an option value or a new option), but that has been removed. Further, using "=" in the option string is always unambiguous. Since the distinction between the two option variants is confusing, just remove the difference and allow "--opt value" and "-opt=value". To make this easier, do some other cleanups as well (e.g. avoid having to do a manual lookup of the option just to check for M_OPT_PRE_PARSE, which somehow ended up with finally getting rid of the m_config.mode member). Error reporting is still a mess, and we opt for reporting too many rather than too few errors to the user. There shouldn't be many user-visible changes. The --framedrop and --term-osd options now always require parameters. The --mute option is intentionally made ambiguous: it works like a flag option, but a value can be passed to it explicitly ("--mute=auto"). If the interpretation of the option is ambiguous (like "--mute auto"), the second string is interpreted as separate option or filename. (Normal flag options are actually ambiguous in this way too.)
-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++;
}