vo_gl3: call glFlush() after frame drawing is complete
[mplayer.git] / parser-cfg.c
blobf6a4c67d3a8a95dba8988c918fb12bdf23f0d257
1 /*
2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "config.h"
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <ctype.h>
26 #include <assert.h>
28 #include "osdep/io.h"
30 #include "parser-cfg.h"
31 #include "mp_msg.h"
32 #include "m_option.h"
33 #include "m_config.h"
35 /// Maximal include depth.
36 #define MAX_RECURSION_DEPTH 8
38 /// Current include depth.
39 static int recursion_depth = 0;
41 /// Setup the \ref Config from a config file.
42 /** \param config The config object.
43 * \param conffile Path to the config file.
44 * \return 1 on sucess, -1 on error.
46 int m_config_parse_config_file(m_config_t *config, const char *conffile)
48 #define PRINT_LINENUM mp_msg(MSGT_CFGPARSER, MSGL_V, "%s(%d): ", conffile, line_num)
49 #define MAX_LINE_LEN 10000
50 #define MAX_OPT_LEN 1000
51 #define MAX_PARAM_LEN 1500
52 FILE *fp;
53 char *line;
54 char opt[MAX_OPT_LEN + 1];
55 char param[MAX_PARAM_LEN + 1];
56 char c; /* for the "" and '' check */
57 int tmp;
58 int line_num = 0;
59 int line_pos; /* line pos */
60 int opt_pos; /* opt pos */
61 int param_pos; /* param pos */
62 int ret = 1;
63 int errors = 0;
64 int prev_mode = config->mode;
65 m_profile_t *profile = NULL;
67 mp_msg(MSGT_CFGPARSER, MSGL_V, "Reading config file %s", conffile);
69 if (recursion_depth > MAX_RECURSION_DEPTH) {
70 mp_msg(MSGT_CFGPARSER, MSGL_ERR,
71 ": too deep 'include'. check your configfiles\n");
72 ret = -1;
73 goto out;
74 } else
76 config->mode = M_CONFIG_FILE;
78 if ((line = malloc(MAX_LINE_LEN + 1)) == NULL) {
79 mp_msg(MSGT_CFGPARSER, MSGL_FATAL,
80 "\ncan't get memory for 'line': %s", strerror(errno));
81 ret = -1;
82 goto out;
83 } else
85 mp_msg(MSGT_CFGPARSER, MSGL_V, "\n");
87 if ((fp = fopen(conffile, "r")) == NULL) {
88 mp_msg(MSGT_CFGPARSER, MSGL_V, ": %s\n", strerror(errno));
89 free(line);
90 ret = 0;
91 goto out;
94 while (fgets(line, MAX_LINE_LEN, fp)) {
95 if (errors >= 16) {
96 mp_msg(MSGT_CFGPARSER, MSGL_FATAL, "too many errors\n");
97 goto out;
100 line_num++;
101 line_pos = 0;
103 /* skip whitespaces */
104 while (isspace(line[line_pos]))
105 ++line_pos;
107 /* EOL / comment */
108 if (line[line_pos] == '\0' || line[line_pos] == '#')
109 continue;
111 /* read option. */
112 for (opt_pos = 0; isprint(line[line_pos]) &&
113 line[line_pos] != ' ' &&
114 line[line_pos] != '#' &&
115 line[line_pos] != '='; /* NOTHING */) {
116 opt[opt_pos++] = line[line_pos++];
117 if (opt_pos >= MAX_OPT_LEN) {
118 PRINT_LINENUM;
119 mp_msg(MSGT_CFGPARSER, MSGL_ERR,
120 "too long option at line %d\n", line_num);
121 errors++;
122 ret = -1;
123 goto nextline;
126 if (opt_pos == 0) {
127 PRINT_LINENUM;
128 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parse error at line %d\n",
129 line_num);
130 ret = -1;
131 errors++;
132 continue;
134 opt[opt_pos] = '\0';
136 /* Profile declaration */
137 if (opt_pos > 2 && opt[0] == '[' && opt[opt_pos - 1] == ']') {
138 opt[opt_pos - 1] = '\0';
139 if (strcmp(opt + 1, "default"))
140 profile = m_config_add_profile(config, opt + 1);
141 else
142 profile = NULL;
143 continue;
146 /* skip whitespaces */
147 while (isspace(line[line_pos]))
148 ++line_pos;
150 /* check '=' */
151 if (line[line_pos++] != '=') {
152 PRINT_LINENUM;
153 mp_msg(MSGT_CFGPARSER, MSGL_ERR,
154 "Option %s needs a parameter at line %d\n", opt, line_num);
155 ret = -1;
156 errors++;
157 continue;
160 /* whitespaces... */
161 while (isspace(line[line_pos]))
162 ++line_pos;
164 /* read the parameter */
165 if (line[line_pos] == '"' || line[line_pos] == '\'') {
166 c = line[line_pos];
167 ++line_pos;
168 for (param_pos = 0; line[line_pos] != c; /* NOTHING */) {
169 param[param_pos++] = line[line_pos++];
170 if (param_pos >= MAX_PARAM_LEN) {
171 PRINT_LINENUM;
172 mp_msg(MSGT_CFGPARSER, MSGL_ERR,
173 "Option %s has a too long parameter at line %d\n",
174 opt, line_num);
175 ret = -1;
176 errors++;
177 goto nextline;
180 line_pos++; /* skip the closing " or ' */
181 } else {
182 for (param_pos = 0; isprint(line[line_pos])
183 && !isspace(line[line_pos])
184 && line[line_pos] != '#'; /* NOTHING */) {
185 param[param_pos++] = line[line_pos++];
186 if (param_pos >= MAX_PARAM_LEN) {
187 PRINT_LINENUM;
188 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "too long parameter\n");
189 ret = -1;
190 errors++;
191 goto nextline;
195 param[param_pos] = '\0';
197 /* did we read a parameter? */
198 if (param_pos == 0) {
199 PRINT_LINENUM;
200 mp_msg(MSGT_CFGPARSER, MSGL_ERR,
201 "Option %s needs a parameter at line %d\n", opt, line_num);
202 ret = -1;
203 errors++;
204 continue;
207 /* now, check if we have some more chars on the line */
208 /* whitespace... */
209 while (isspace(line[line_pos]))
210 ++line_pos;
212 /* EOL / comment */
213 if (line[line_pos] != '\0' && line[line_pos] != '#') {
214 PRINT_LINENUM;
215 mp_msg(MSGT_CFGPARSER, MSGL_WARN,
216 "extra characters on line %d: %s\n",
217 line_num, line + line_pos);
218 ret = -1;
221 if (profile) {
222 if (!strcmp(opt, "profile-desc"))
223 m_profile_set_desc(profile, param), tmp = 1;
224 else
225 tmp = m_config_set_profile_option(config, profile,
226 opt, param);
227 } else
228 tmp = m_config_set_option0(config, opt, param, false);
229 if (tmp < 0) {
230 PRINT_LINENUM;
231 if (tmp == M_OPT_UNKNOWN) {
232 mp_msg(MSGT_CFGPARSER, MSGL_WARN,
233 "Warning unknown option %s at line %d\n",
234 opt, line_num);
235 continue;
237 mp_msg(MSGT_CFGPARSER, MSGL_ERR,
238 "Error parsing option %s=%s at line %d\n",
239 opt, param, line_num);
240 ret = -1;
241 errors++;
242 continue;
243 /* break */
245 nextline:
249 free(line);
250 fclose(fp);
251 out:
252 config->mode = prev_mode;
253 --recursion_depth;
254 return ret;