From eb15151705d47d23da844449126cc6b4879f110e Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 17 Dec 2013 02:02:25 +0100 Subject: Move options/config related files from mpvcore/ to options/ Since m_option.h and options.h are extremely often included, a lot of files have to be changed. Moving path.c/h to options/ is a bit questionable, but since this is mainly about access to config files (which are also handled in options/), it's probably ok. --- options/parse_configfile.c | 277 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 options/parse_configfile.c (limited to 'options/parse_configfile.c') diff --git a/options/parse_configfile.c b/options/parse_configfile.c new file mode 100644 index 0000000000..f82e740df9 --- /dev/null +++ b/options/parse_configfile.c @@ -0,0 +1,277 @@ +/* + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "osdep/io.h" + +#include "parse_configfile.h" +#include "mpvcore/mp_msg.h" +#include "m_option.h" +#include "m_config.h" + +/// Maximal include depth. +#define MAX_RECURSION_DEPTH 8 + +/// Current include depth. +static int recursion_depth = 0; + +/// Setup the \ref Config from a config file. +/** \param config The config object. + * \param conffile Path to the config file. + * \param flags M_SETOPT_* bits + * \return 1 on sucess, -1 on error, 0 if file not accessible. + */ +int m_config_parse_config_file(m_config_t *config, const char *conffile, + int flags) +{ +#define PRINT_LINENUM mp_msg(MSGT_CFGPARSER, MSGL_ERR, "%s:%d: ", conffile, line_num) +#define MAX_LINE_LEN 10000 +#define MAX_OPT_LEN 1000 +#define MAX_PARAM_LEN 1500 + FILE *fp = NULL; + char *line = NULL; + char opt[MAX_OPT_LEN + 1]; + char param[MAX_PARAM_LEN + 1]; + char c; /* for the "" and '' check */ + int tmp; + int line_num = 0; + int line_pos; /* line pos */ + int opt_pos; /* opt pos */ + int param_pos; /* param pos */ + int ret = 1; + int errors = 0; + m_profile_t *profile = NULL; + + flags = flags | M_SETOPT_FROM_CONFIG_FILE; + + mp_msg(MSGT_CFGPARSER, MSGL_V, "Reading config file %s", conffile); + + if (recursion_depth > MAX_RECURSION_DEPTH) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + ": too deep 'include'. check your configfiles\n"); + ret = -1; + goto out; + } + + if ((line = malloc(MAX_LINE_LEN + 1)) == NULL) { + mp_msg(MSGT_CFGPARSER, MSGL_FATAL, + "\ncan't get memory for 'line': %s", strerror(errno)); + ret = -1; + goto out; + } else + + mp_msg(MSGT_CFGPARSER, MSGL_V, "\n"); + + if ((fp = fopen(conffile, "r")) == NULL) { + mp_msg(MSGT_CFGPARSER, MSGL_V, ": %s\n", strerror(errno)); + ret = 0; + goto out; + } + + while (fgets(line, MAX_LINE_LEN, fp)) { + if (errors >= 16) { + mp_msg(MSGT_CFGPARSER, MSGL_FATAL, "too many errors\n"); + goto out; + } + + line_num++; + line_pos = 0; + + /* skip whitespaces */ + while (isspace(line[line_pos])) + ++line_pos; + + /* EOL / comment */ + if (line[line_pos] == '\0' || line[line_pos] == '#') + continue; + + /* read option. */ + for (opt_pos = 0; isprint(line[line_pos]) && + line[line_pos] != ' ' && + line[line_pos] != '#' && + line[line_pos] != '='; /* NOTHING */) { + opt[opt_pos++] = line[line_pos++]; + if (opt_pos >= MAX_OPT_LEN) { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "too long option\n"); + errors++; + ret = -1; + goto nextline; + } + } + if (opt_pos == 0) { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parse error\n"); + ret = -1; + errors++; + continue; + } + opt[opt_pos] = '\0'; + + /* Profile declaration */ + if (opt_pos > 2 && opt[0] == '[' && opt[opt_pos - 1] == ']') { + opt[opt_pos - 1] = '\0'; + if (strcmp(opt + 1, "default")) + profile = m_config_add_profile(config, opt + 1); + else + profile = NULL; + continue; + } + + /* skip whitespaces */ + while (isspace(line[line_pos])) + ++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; + + /* read the parameter */ + if (line[line_pos] == '"' || line[line_pos] == '\'') { + c = line[line_pos]; + ++line_pos; + for (param_pos = 0; line[line_pos] != c; /* NOTHING */) { + param[param_pos++] = line[line_pos++]; + if (param_pos >= MAX_PARAM_LEN) { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "option %s has a too long parameter\n", opt); + ret = -1; + errors++; + goto nextline; + } + } + line_pos++; /* skip the closing " or ' */ + goto param_done; + } + + if (line[line_pos] == '%') { + char *start = &line[line_pos + 1]; + char *end = start; + unsigned long len = strtoul(start, &end, 10); + if (start != end && end[0] == '%') { + if (len >= MAX_PARAM_LEN - 1 || + strlen(end + 1) < len) + { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "bogus %% length\n"); + ret = -1; + errors++; + goto nextline; + } + param_pos = snprintf(param, sizeof(param), "%.*s", + (int)len, end + 1); + line_pos += 1 + (end - start) + 1 + len; + goto param_done; + } + } + + for (param_pos = 0; isprint(line[line_pos]) + && !isspace(line[line_pos]) + && line[line_pos] != '#'; /* NOTHING */) { + param[param_pos++] = line[line_pos++]; + if (param_pos >= MAX_PARAM_LEN) { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "too long parameter\n"); + ret = -1; + errors++; + goto nextline; + } + } + + param_done: + + while (isspace(line[line_pos])) + ++line_pos; + } + param[param_pos] = '\0'; + + /* EOL / comment */ + if (line[line_pos] != '\0' && line[line_pos] != '#') { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "extra characters: %s\n", line + line_pos); + ret = -1; + } + + bstr bopt = bstr0(opt); + bstr bparam = bstr0(param); + + if (bopt.len >= 3) + bstr_eatstart0(&bopt, "--"); + + if (profile && bstr_equals0(bopt, "profile-desc")) { + m_profile_set_desc(profile, bparam); + goto nextline; + } + + tmp = m_config_option_requires_param(config, bopt); + 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", + BSTR_P(bopt), BSTR_P(bparam), m_option_strerror(tmp)); + continue; + } + + if (profile) { + tmp = m_config_set_profile_option(config, profile, bopt, bparam); + } else { + tmp = m_config_set_option_ext(config, bopt, bparam, flags); + } + if (tmp < 0) { + PRINT_LINENUM; + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "setting option %.*s='%.*s' failed.\n", + BSTR_P(bopt), BSTR_P(bparam)); + continue; + /* break */ + } +nextline: + ; + } + +out: + free(line); + if (fp) + fclose(fp); + --recursion_depth; + if (ret < 0) { + mp_msg(MSGT_CFGPARSER, MSGL_FATAL, "Error loading config file %s.\n", + conffile); + } + return ret; +} -- cgit v1.2.3