From 507fa7e2c23623dcbecf20a392ee025002c83866 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Wed, 27 Jul 2011 20:59:44 +0300 Subject: options: indicate ambiguous option parameters explicitly Command line options like "-foo xyz" are ambiguous: "xyz" may be a parameter to the option "foo" or an unrelated argument. Instead of relying on the struct m_config mode field (commandline/file) pass parameters to specify ambiguous mode explicitly. Meant for "--foo" options which are never ambiguous on command line either. --- m_config.c | 33 +++++++++++++---------- m_config.h | 28 ++++++++++++++------ m_option.c | 65 +++++++++++++++++++++++----------------------- m_option.h | 27 +++++++------------ m_property.c | 3 +-- m_struct.c | 2 +- osdep/macosx_finder_args.c | 2 +- parser-cfg.c | 2 +- parser-mpcmd.c | 14 +++++----- playtree.c | 3 ++- stream/stream.c | 2 +- 11 files changed, 96 insertions(+), 85 deletions(-) diff --git a/m_config.c b/m_config.c index 47e893717c..b278877c3c 100644 --- a/m_config.c +++ b/m_config.c @@ -25,8 +25,10 @@ #include #include #include -#include "talloc.h" #include +#include + +#include "talloc.h" #include "m_config.h" #include "m_option.h" @@ -35,7 +37,7 @@ #define MAX_PROFILE_DEPTH 20 static int parse_profile(const struct m_option *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { struct m_config *config = opt->priv; char **list = NULL; @@ -55,7 +57,7 @@ static int parse_profile(const struct m_option *opt, const char *name, return M_OPT_EXIT - 1; } - r = m_option_type_string_list.parse(opt, name, param, &list, src); + r = m_option_type_string_list.parse(opt, name, param, false, &list); if (r < 0) return r; if (!list || !list[0]) @@ -402,7 +404,7 @@ static struct m_config_option *m_config_get_co(const struct m_config *config, } static int m_config_parse_option(const struct m_config *config, char *arg, - char *param, int set) + char *param, bool ambiguous_param, bool set) { struct m_config_option *co; int r = 0; @@ -443,7 +445,7 @@ static int m_config_parse_option(const struct m_config *config, char *arg, char **lst = NULL; int i, sr; // Parse the child options - r = m_option_parse(co->opt, arg, param, &lst, M_COMMAND_LINE); + r = m_option_parse(co->opt, arg, param, false, &lst); // Set them now if (r >= 0) for (i = 0; lst && lst[2 * i]; i++) { @@ -452,7 +454,8 @@ static int m_config_parse_option(const struct m_config *config, char *arg, // Build the full name char n[l]; sprintf(n, "%s:%s", co->name, lst[2 * i]); - sr = m_config_parse_option(config, n, lst[2 * i + 1], set); + sr = m_config_parse_option(config, n, lst[2 * i + 1], + false, set); if (sr < 0) { if (sr == M_OPT_UNKNOWN) { mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, @@ -473,8 +476,8 @@ static int m_config_parse_option(const struct m_config *config, char *arg, } talloc_free(lst); } else - r = m_option_parse(co->opt, arg, param, set ? co->slots->data : NULL, - config->mode); + r = m_option_parse(co->opt, arg, param, ambiguous_param, + set ? co->slots->data : NULL); // Parsing failed ? if (r < 0) @@ -488,17 +491,19 @@ static int m_config_parse_option(const struct m_config *config, char *arg, return r; } -int m_config_set_option(struct m_config *config, char *arg, char *param) +int m_config_set_option(struct m_config *config, char *arg, + char *param, bool ambiguous_param) { mp_msg(MSGT_CFGPARSER, MSGL_DBG2, "Setting %s=%s\n", arg, param); - return m_config_parse_option(config, arg, param, 1); + return m_config_parse_option(config, arg, param, ambiguous_param, 1); } -int m_config_check_option(const struct m_config *config, char *arg, char *param) +int m_config_check_option(const struct m_config *config, char *arg, + char *param, bool ambiguous_param) { int r; mp_msg(MSGT_CFGPARSER, MSGL_DBG2, "Checking %s=%s\n", arg, param); - r = m_config_parse_option(config, arg, param, 0); + r = m_config_parse_option(config, arg, param, ambiguous_param, 0); if (r == M_OPT_MISSING_PARAM) { mp_tmsg(MSGT_CFGPARSER, MSGL_ERR, "Error: option '%s' must have a parameter!\n", arg); @@ -592,7 +597,7 @@ 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) { - int i = m_config_check_option(config, name, val); + int i = m_config_check_option(config, name, val, false); if (i < 0) return i; p->opts = talloc_realloc(p, p->opts, char *, 2 * (p->num_opts + 2)); @@ -615,7 +620,7 @@ void m_config_set_profile(struct m_config *config, struct m_profile *p) config->mode = M_CONFIG_FILE; config->profile_depth++; for (i = 0; i < p->num_opts; i++) - m_config_set_option(config, p->opts[2 * i], p->opts[2 * i + 1]); + m_config_set_option(config, p->opts[2 * i], p->opts[2 * i + 1], false); config->profile_depth--; config->mode = prev_mode; } diff --git a/m_config.h b/m_config.h index a884a29a76..d2c3b9ee4e 100644 --- a/m_config.h +++ b/m_config.h @@ -19,6 +19,9 @@ #ifndef MPLAYER_M_CONFIG_H #define MPLAYER_M_CONFIG_H +#include + + // m_config provides an API to manipulate the config variables in MPlayer. // It makes use of the Options API to provide a context stack that // allows saving and later restoring the state of all variables. @@ -64,6 +67,15 @@ struct m_profile { char **opts; }; +enum option_source { + // Set when parsing from a config file. + M_CONFIG_FILE, + // Set when parsing command line arguments. + M_COMMAND_LINE, + // Set when pre-parsing the command line + M_COMMAND_LINE_PRE_PARSE, +}; + // Config object /** \ingroup Config */ typedef struct m_config { @@ -73,8 +85,7 @@ typedef struct m_config { struct m_config_option *opts; // Current stack level. int lvl; - // \ref OptionParserModes - int mode; + enum option_source mode; // List of defined profiles. struct m_profile *profiles; // Depth when recursively including profiles. @@ -120,18 +131,19 @@ int m_config_register_options(struct m_config *config, * \param config The config object. * \param arg The option's name. * \param param The value of the option, can be NULL. + * \param ambiguous_param: old style cmdline option, "param" may be a + parameter to this option or something entirely unrelated * \return See \ref OptionParserReturn. */ -int m_config_set_option(struct m_config *config, char *arg, char *param); +int m_config_set_option(struct m_config *config, char *arg, + char *param, bool ambiguous_param); /* Check if an option setting is valid. - * \param config The config object. - * \param arg The option's name. - * \param param The value of the option, can be NULL. - * \return See \ref OptionParserReturn. + * Same as above m_config_set_option() but doesn't actually set anything. */ int m_config_check_option(const struct m_config *config, char *arg, - char *param); + char *param, bool ambiguous_param); + /* Get the option matching the given name. * \param config The config object. diff --git a/m_option.c b/m_option.c index 17d039f23b..a1cc139f8d 100644 --- a/m_option.c +++ b/m_option.c @@ -64,11 +64,9 @@ static void copy_opt(const m_option_t *opt, void *dst, const void *src) #define VAL(x) (*(int *)(x)) static int parse_flag(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { - if (src == M_CONFIG_FILE) { - if (!param) - return M_OPT_MISSING_PARAM; + if (param && !ambiguous_param) { if (!strcasecmp(param, "yes") || /* any other language? */ !strcasecmp(param, "on") || !strcasecmp(param, "ja") || @@ -132,11 +130,10 @@ const m_option_type_t m_option_type_flag = { // Integer static int parse_int(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { long long tmp_int; char *endptr; - src = 0; if (param == NULL) return M_OPT_MISSING_PARAM; @@ -208,7 +205,7 @@ const m_option_type_t m_option_type_int64 = { }; static int parse_intpair(const struct m_option *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { if (param == NULL) return M_OPT_MISSING_PARAM; @@ -254,7 +251,7 @@ const struct m_option_type m_option_type_intpair = { }; static int parse_choice(const struct m_option *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { if (param == NULL) return M_OPT_MISSING_PARAM; @@ -303,11 +300,10 @@ const struct m_option_type m_option_type_choice = { #define VAL(x) (*(double *)(x)) static int parse_double(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { double tmp_float; char *endptr; - src = 0; if (param == NULL) return M_OPT_MISSING_PARAM; @@ -382,10 +378,10 @@ const m_option_type_t m_option_type_double = { #define VAL(x) (*(float *)(x)) static int parse_float(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { double tmp; - int r = parse_double(opt, name, param, &tmp, src); + int r = parse_double(opt, name, param, false, &tmp); if (r == 1 && dst) VAL(dst) = tmp; return r; @@ -415,7 +411,7 @@ const m_option_type_t m_option_type_float = { #define VAL(x) (*(off_t *)(x)) static int parse_position(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { off_t tmp_off; char dummy; @@ -475,7 +471,7 @@ const m_option_type_t m_option_type_position = { #define VAL(x) (*(char **)(x)) static int parse_str(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { @@ -661,7 +657,7 @@ static char *get_nextsep(char *ptr, char sep, int modify) } static int parse_str_list(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { int n = 0, len = strlen(opt->name); char *str; @@ -846,7 +842,7 @@ static void free_func_pf(void *src) // Parser for func_param static int parse_func_pf(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { struct m_func_save *s, *p; @@ -929,7 +925,7 @@ const m_option_type_t m_option_type_func_param = { #undef VAL static int parse_func(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { return 0; } @@ -955,7 +951,7 @@ const m_option_type_t m_option_type_func = { /////////////////// Print static int parse_print(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { if (opt->type == CONF_TYPE_PRINT_INDIRECT) mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s", *(char **) opt->p); @@ -1014,7 +1010,7 @@ const m_option_type_t m_option_type_print_func = { #define VAL(x) (*(char ***)(x)) static int parse_subconf(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { char *subparam; char *subopt; @@ -1091,7 +1087,8 @@ static int parse_subconf(const m_option_t *opt, const char *name, return M_OPT_UNKNOWN; } r = m_option_parse(&subopts[i], subopt, - subparam[0] == 0 ? NULL : subparam, NULL, src); + subparam[0] == 0 ? NULL : subparam, false, + NULL); if (r < 0) return r; if (dst) { @@ -1208,7 +1205,7 @@ static struct { }; static int parse_imgfmt(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { uint32_t fmt = 0; int i; @@ -1300,7 +1297,7 @@ static struct { }; static int parse_afmt(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { uint32_t fmt = 0; int i; @@ -1370,7 +1367,7 @@ int parse_timestring(const char *str, double *time, char endchar) static int parse_time(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { double time; @@ -1405,7 +1402,7 @@ const m_option_type_t m_option_type_time = { // Time or size (-endpos) static int parse_time_size(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { m_time_size_t ts; char unit[4]; @@ -1513,7 +1510,7 @@ static int get_obj_param(const char *opt_name, const char *obj_name, opt_name, obj_name, str); return M_OPT_UNKNOWN; } - r = m_option_parse(opt, str, p, NULL, M_CONFIG_FILE); + r = m_option_parse(opt, str, p, false, NULL); if (r < 0) { if (r > M_OPT_EXIT) mp_msg(MSGT_CFGPARSER, MSGL_ERR, @@ -1534,7 +1531,7 @@ static int get_obj_param(const char *opt_name, const char *obj_name, return M_OPT_OUT_OF_RANGE; } opt = &desc->fields[(*nold)]; - r = m_option_parse(opt, opt->name, str, NULL, M_CONFIG_FILE); + r = m_option_parse(opt, opt->name, str, false, NULL); if (r < 0) { if (r > M_OPT_EXIT) mp_msg(MSGT_CFGPARSER, MSGL_ERR, @@ -1656,7 +1653,7 @@ static int get_obj_params(const char *opt_name, const char *name, char *params, } static int parse_obj_params(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, void *dst) { char **opts; int r; @@ -1778,7 +1775,7 @@ static int parse_obj_settings(const char *opt, char *str, } static int obj_settings_list_del(const char *opt_name, const char *param, - void *dst, int src) + bool ambiguous_param, void *dst) { char **str_list = NULL; int r, i, idx_max = 0; @@ -1798,7 +1795,7 @@ static int obj_settings_list_del(const char *opt_name, const char *param, /* NOP */; } - r = m_option_parse(&list_opt, opt_name, param, &str_list, src); + r = m_option_parse(&list_opt, opt_name, param, false, &str_list); if (r < 0 || !str_list) return r; @@ -1862,7 +1859,8 @@ static void free_obj_settings_list(void *dst) } static int parse_obj_settings_list(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, + void *dst) { int n = 0, r, len = strlen(opt->name); char *str; @@ -1925,7 +1923,7 @@ static int parse_obj_settings_list(const m_option_t *opt, const char *name, queue = VAL(dst); break; case OP_DEL: - return obj_settings_list_del(name, param, dst, src); + return obj_settings_list_del(name, param, false, dst); case OP_NONE: if (dst && VAL(dst)) free_obj_settings_list(dst); @@ -2052,7 +2050,8 @@ const m_option_type_t m_option_type_obj_settings_list = { static int parse_obj_presets(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, + void *dst) { m_obj_presets_t *obj_p = (m_obj_presets_t *)opt->priv; const m_struct_t *in_desc; @@ -2134,7 +2133,7 @@ const m_option_type_t m_option_type_obj_presets = { }; static int parse_custom_url(const m_option_t *opt, const char *name, - const char *url, void *dst, int src) + const char *url, bool ambiguous_param, void *dst) { int pos1, pos2, r, v6addr = 0; char *ptr1 = NULL, *ptr2 = NULL, *ptr3 = NULL, *ptr4 = NULL; diff --git a/m_option.h b/m_option.h index 5fa503f0c7..76d3366d18 100644 --- a/m_option.h +++ b/m_option.h @@ -21,6 +21,7 @@ #include #include +#include #include "config.h" @@ -209,13 +210,15 @@ struct m_option_type { * \param opt The option that is parsed. * \param name The full option name. * \param param The parameter to parse. + * \param ambiguous_param: "param" old cmdline style, "param" may or + * may not be an argument meant for this option * \param dst Pointer to the memory where the data should be written. * If NULL the parameter validity should still be checked. - * \param src Source of the option, see \ref OptionParserModes. - * \return On error a negative value is returned, on success the number of arguments - * consumed. For details see \ref OptionParserReturn. + * \return On error a negative value is returned, on success the number + * of arguments consumed. For details see \ref OptionParserReturn. */ - int (*parse)(const m_option_t *opt, const char *name, const char *param, void *dst, int src); + int (*parse)(const m_option_t *opt, const char *name, const char *param, + bool ambiguous_param, void *dst); // Print back a value in string form. /** \param opt The option to print. @@ -383,17 +386,6 @@ struct m_option { ///////////////////////////// Parser flags ///////////////////////////////// -// Some parsers behave differently depending on the mode passed in the src -// parameter of m_option_type::parse. For example the flag type doesn't take -// an argument when parsing from the command line. - -// Set when parsing from a config file. -#define M_CONFIG_FILE 0 -// Set when parsing command line arguments. -#define M_COMMAND_LINE 1 -// Set when pre-parsing the command line -#define M_COMMAND_LINE_PRE_PARSE 2 - // On success parsers return the number of arguments consumed: 0 or 1. // // To indicate that MPlayer should exit without playing anything, @@ -449,9 +441,10 @@ static inline void *m_option_get_ptr(const struct m_option *opt, // Helper to parse options, see \ref m_option_type::parse. static inline int m_option_parse(const m_option_t *opt, const char *name, - const char *param, void *dst, int src) + const char *param, bool ambiguous_param, + void *dst) { - return opt->type->parse(opt, name, param, dst, src); + return opt->type->parse(opt, name, param, ambiguous_param, dst); } // Helper to print options, see \ref m_option_type::print. diff --git a/m_property.c b/m_property.c index 0bd01d4cf7..da0f54e2c1 100644 --- a/m_property.c +++ b/m_property.c @@ -108,8 +108,7 @@ int m_property_do(const m_option_t *prop_list, const char *name, if (!arg) return M_PROPERTY_ERROR; val = calloc(1, opt->type->size); - if ((r = - m_option_parse(opt, opt->name, arg, val, M_CONFIG_FILE)) <= 0) { + if ((r = m_option_parse(opt, opt->name, arg, false, val)) <= 0) { free(val); return r; } diff --git a/m_struct.c b/m_struct.c index 7813340e42..ca7c967ff2 100644 --- a/m_struct.c +++ b/m_struct.c @@ -77,7 +77,7 @@ m_struct_set(const m_struct_t* st, void* obj, const char* field, const char* par return 0; } - if(f->type->parse(f,field,param,M_ST_MB_P(obj,f->p),M_CONFIG_FILE) < 0) { + if(f->type->parse(f, field, param, false, M_ST_MB_P(obj,f->p)) < 0) { mp_msg(MSGT_CFGPARSER, MSGL_ERR,"Struct %s, field %s parsing error: %s\n", st->name,field,param); return 0; diff --git a/osdep/macosx_finder_args.c b/osdep/macosx_finder_args.c index baf11101c7..c3b5f99672 100644 --- a/osdep/macosx_finder_args.c +++ b/osdep/macosx_finder_args.c @@ -118,7 +118,7 @@ char myPsnStr[5+10+1+10+1]; myPsnStr[5+10+1+10]=0; if((argc==2) && !strcmp(myPsnStr, argv[1])) { - m_config_set_option(config, "quiet", NULL); + m_config_set_option(config, "quiet", NULL, false); InitCursor(); AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, NewAEEventHandlerUPP(AppleEventHandlerProc), 0, FALSE); RunApplicationEventLoop(); diff --git a/parser-cfg.c b/parser-cfg.c index 2d0e3ee3cd..8570bcefa0 100644 --- a/parser-cfg.c +++ b/parser-cfg.c @@ -237,7 +237,7 @@ int m_config_parse_config_file(m_config_t* config, const char *conffile) tmp = m_config_set_profile_option(config,profile, opt,param); } else - tmp = m_config_set_option(config, opt, param); + tmp = m_config_set_option(config, opt, param, false); if (tmp < 0) { PRINT_LINENUM; if(tmp == M_OPT_UNKNOWN) { diff --git a/parser-mpcmd.c b/parser-mpcmd.c index d1b5f45753..354d4fd7a5 100644 --- a/parser-mpcmd.c +++ b/parser-mpcmd.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "mp_msg.h" #include "m_option.h" @@ -186,11 +187,12 @@ play_tree_t *m_config_parse_mp_command_line(m_config_t *config, int argc, if (mp_opt != NULL) { // Option exist if (mode == GLOBAL || (mp_opt->flags & M_OPT_GLOBAL)) tmp = (i + 1 < argc) - ? m_config_set_option(config, opt, argv[i + 1]) - : m_config_set_option(config, opt, NULL); + ? m_config_set_option(config, opt, argv[i + 1], + true) + : m_config_set_option(config, opt, NULL, false); else { tmp = m_config_check_option(config, opt, - (i + 1 < argc) ? argv[i + 1] : NULL); + (i + 1 < argc) ? argv[i + 1] : NULL, true); if (tmp >= 0 && mode != DROP_LOCAL) { play_tree_t *pt = last_entry ? last_entry : last_parent; @@ -255,7 +257,7 @@ play_tree_t *m_config_parse_mp_command_line(m_config_t *config, int argc, // Lock stdin if it will be used as input if (strcasecmp(argv[i], "-") == 0) - m_config_set_option(config, "noconsolecontrols", NULL); + m_config_set_option(config, "consolecontrols", "no", false); add_entry(&last_parent, &last_entry, entry); mode = LOCAL; // We start entry specific options } @@ -304,8 +306,8 @@ int m_config_preparse_command_line(m_config_t *config, int argc, char **argv) if (!opt) continue; // Set, non-pre-parse options will be ignored - int r = m_config_set_option(config, arg, - i+1 < argc ? argv[i+1] : NULL); + int r = m_config_set_option(config, arg, i+1 < argc ? argv[i+1] : NULL, + true); if (r < 0) ret = r; else diff --git a/playtree.c b/playtree.c index 23859394b9..77c1927a8b 100644 --- a/playtree.c +++ b/playtree.c @@ -465,7 +465,8 @@ play_tree_iter_push_params(play_tree_iter_t* iter) { for(n = 0; pt->params[n].name != NULL ; n++) { int e; - if((e = m_config_set_option(iter->config,pt->params[n].name,pt->params[n].value)) < 0) { + if((e = m_config_set_option(iter->config, pt->params[n].name, + pt->params[n].value, false)) < 0) { mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Error %d while setting option '%s' with value '%s'\n",e, pt->params[n].name,pt->params[n].value); } diff --git a/stream/stream.c b/stream/stream.c index 26bbb7a55a..6217fe6283 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -166,7 +166,7 @@ static stream_t *open_stream_plugin(const stream_info_t *sinfo, if(sinfo->opts_url) { m_option_t url_opt = { "stream url", arg , CONF_TYPE_CUSTOM_URL, 0, 0 ,0, (void *)sinfo->opts }; - if(m_option_parse(&url_opt,"stream url",filename,arg,M_CONFIG_FILE) < 0) { + if (m_option_parse(&url_opt, "stream url", filename, false, arg) < 0) { mp_tmsg(MSGT_OPEN,MSGL_ERR, "URL parsing failed on url %s\n",filename); m_struct_free(desc,arg); return NULL; -- cgit v1.2.3