cleanup: Silence compilation warnings on MinGW-w64
[mplayer.git] / parser-cfg.c
blobe2c5d208e22c437e552e2d68c769371a2855f486
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 "parser-cfg.h"
29 #include "mp_msg.h"
30 #include "m_option.h"
31 #include "m_config.h"
33 /// Maximal include depth.
34 #define MAX_RECURSION_DEPTH 8
36 /// Current include depth.
37 static int recursion_depth = 0;
39 /// Setup the \ref Config from a config file.
40 /** \param config The config object.
41 * \param conffile Path to the config file.
42 * \return 1 on sucess, -1 on error.
44 int m_config_parse_config_file(m_config_t *config, const char *conffile)
46 #define PRINT_LINENUM mp_msg(MSGT_CFGPARSER, MSGL_V, "%s(%d): ", conffile, line_num)
47 #define MAX_LINE_LEN 10000
48 #define MAX_OPT_LEN 1000
49 #define MAX_PARAM_LEN 1500
50 FILE *fp;
51 char *line;
52 char opt[MAX_OPT_LEN + 1];
53 char param[MAX_PARAM_LEN + 1];
54 char c; /* for the "" and '' check */
55 int tmp;
56 int line_num = 0;
57 int line_pos; /* line pos */
58 int opt_pos; /* opt pos */
59 int param_pos; /* param pos */
60 int ret = 1;
61 int errors = 0;
62 int prev_mode = config->mode;
63 m_profile_t *profile = NULL;
65 mp_msg(MSGT_CFGPARSER, MSGL_V, "Reading config file %s", conffile);
67 if (recursion_depth > MAX_RECURSION_DEPTH) {
68 mp_msg(MSGT_CFGPARSER, MSGL_ERR,
69 ": too deep 'include'. check your configfiles\n");
70 ret = -1;
71 goto out;
72 } else
74 config->mode = M_CONFIG_FILE;
76 if ((line = malloc(MAX_LINE_LEN + 1)) == NULL) {
77 mp_msg(MSGT_CFGPARSER, MSGL_FATAL,
78 "\ncan't get memory for 'line': %s", strerror(errno));
79 ret = -1;
80 goto out;
81 } else
83 mp_msg(MSGT_CFGPARSER, MSGL_V, "\n");
85 if ((fp = fopen(conffile, "r")) == NULL) {
86 mp_msg(MSGT_CFGPARSER, MSGL_V, ": %s\n", strerror(errno));
87 free(line);
88 ret = 0;
89 goto out;
92 while (fgets(line, MAX_LINE_LEN, fp)) {
93 if (errors >= 16) {
94 mp_msg(MSGT_CFGPARSER, MSGL_FATAL, "too many errors\n");
95 goto out;
98 line_num++;
99 line_pos = 0;
101 /* skip whitespaces */
102 while (isspace(line[line_pos]))
103 ++line_pos;
105 /* EOL / comment */
106 if (line[line_pos] == '\0' || line[line_pos] == '#')
107 continue;
109 /* read option. */
110 for (opt_pos = 0; isprint(line[line_pos]) &&
111 line[line_pos] != ' ' &&
112 line[line_pos] != '#' &&
113 line[line_pos] != '='; /* NOTHING */) {
114 opt[opt_pos++] = line[line_pos++];
115 if (opt_pos >= MAX_OPT_LEN) {
116 PRINT_LINENUM;
117 mp_msg(MSGT_CFGPARSER, MSGL_ERR,
118 "too long option at line %d\n", line_num);
119 errors++;
120 ret = -1;
121 goto nextline;
124 if (opt_pos == 0) {
125 PRINT_LINENUM;
126 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parse error at line %d\n",
127 line_num);
128 ret = -1;
129 errors++;
130 continue;
132 opt[opt_pos] = '\0';
134 /* Profile declaration */
135 if (opt_pos > 2 && opt[0] == '[' && opt[opt_pos - 1] == ']') {
136 opt[opt_pos - 1] = '\0';
137 if (strcmp(opt + 1, "default"))
138 profile = m_config_add_profile(config, opt + 1);
139 else
140 profile = NULL;
141 continue;
144 /* skip whitespaces */
145 while (isspace(line[line_pos]))
146 ++line_pos;
148 /* check '=' */
149 if (line[line_pos++] != '=') {
150 PRINT_LINENUM;
151 mp_msg(MSGT_CFGPARSER, MSGL_ERR,
152 "Option %s needs a parameter at line %d\n", opt, line_num);
153 ret = -1;
154 errors++;
155 continue;
158 /* whitespaces... */
159 while (isspace(line[line_pos]))
160 ++line_pos;
162 /* read the parameter */
163 if (line[line_pos] == '"' || line[line_pos] == '\'') {
164 c = line[line_pos];
165 ++line_pos;
166 for (param_pos = 0; line[line_pos] != c; /* NOTHING */) {
167 param[param_pos++] = line[line_pos++];
168 if (param_pos >= MAX_PARAM_LEN) {
169 PRINT_LINENUM;
170 mp_msg(MSGT_CFGPARSER, MSGL_ERR,
171 "Option %s has a too long parameter at line %d\n",
172 opt, line_num);
173 ret = -1;
174 errors++;
175 goto nextline;
178 line_pos++; /* skip the closing " or ' */
179 } else {
180 for (param_pos = 0; isprint(line[line_pos])
181 && !isspace(line[line_pos])
182 && line[line_pos] != '#'; /* NOTHING */) {
183 param[param_pos++] = line[line_pos++];
184 if (param_pos >= MAX_PARAM_LEN) {
185 PRINT_LINENUM;
186 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "too long parameter\n");
187 ret = -1;
188 errors++;
189 goto nextline;
193 param[param_pos] = '\0';
195 /* did we read a parameter? */
196 if (param_pos == 0) {
197 PRINT_LINENUM;
198 mp_msg(MSGT_CFGPARSER, MSGL_ERR,
199 "Option %s needs a parameter at line %d\n", opt, line_num);
200 ret = -1;
201 errors++;
202 continue;
205 /* now, check if we have some more chars on the line */
206 /* whitespace... */
207 while (isspace(line[line_pos]))
208 ++line_pos;
210 /* EOL / comment */
211 if (line[line_pos] != '\0' && line[line_pos] != '#') {
212 PRINT_LINENUM;
213 mp_msg(MSGT_CFGPARSER, MSGL_WARN,
214 "extra characters on line %d: %s\n",
215 line_num, line + line_pos);
216 ret = -1;
219 if (profile) {
220 if (!strcmp(opt, "profile-desc"))
221 m_profile_set_desc(profile, param), tmp = 1;
222 else
223 tmp = m_config_set_profile_option(config, profile,
224 opt, param);
225 } else
226 tmp = m_config_set_option0(config, opt, param, false);
227 if (tmp < 0) {
228 PRINT_LINENUM;
229 if (tmp == M_OPT_UNKNOWN) {
230 mp_msg(MSGT_CFGPARSER, MSGL_WARN,
231 "Warning unknown option %s at line %d\n",
232 opt, line_num);
233 continue;
235 mp_msg(MSGT_CFGPARSER, MSGL_ERR,
236 "Error parsing option %s=%s at line %d\n",
237 opt, param, line_num);
238 ret = -1;
239 errors++;
240 continue;
241 /* break */
243 nextline:
247 free(line);
248 fclose(fp);
249 out:
250 config->mode = prev_mode;
251 --recursion_depth;
252 return ret;