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.
28 #include "parser-cfg.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
52 char opt
[MAX_OPT_LEN
+ 1];
53 char param
[MAX_PARAM_LEN
+ 1];
54 char c
; /* for the "" and '' check */
57 int line_pos
; /* line pos */
58 int opt_pos
; /* opt pos */
59 int param_pos
; /* param pos */
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");
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
));
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
));
92 while (fgets(line
, MAX_LINE_LEN
, fp
)) {
94 mp_msg(MSGT_CFGPARSER
, MSGL_FATAL
, "too many errors\n");
101 /* skip whitespaces */
102 while (isspace(line
[line_pos
]))
106 if (line
[line_pos
] == '\0' || line
[line_pos
] == '#')
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
) {
117 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
118 "too long option at line %d\n", line_num
);
126 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "parse error at line %d\n",
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);
144 /* skip whitespaces */
145 while (isspace(line
[line_pos
]))
149 if (line
[line_pos
++] != '=') {
151 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
152 "Option %s needs a parameter at line %d\n", opt
, line_num
);
159 while (isspace(line
[line_pos
]))
162 /* read the parameter */
163 if (line
[line_pos
] == '"' || line
[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
) {
170 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
171 "Option %s has a too long parameter at line %d\n",
178 line_pos
++; /* skip the closing " or ' */
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
) {
186 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
, "too long parameter\n");
193 param
[param_pos
] = '\0';
195 /* did we read a parameter? */
196 if (param_pos
== 0) {
198 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
199 "Option %s needs a parameter at line %d\n", opt
, line_num
);
205 /* now, check if we have some more chars on the line */
207 while (isspace(line
[line_pos
]))
211 if (line
[line_pos
] != '\0' && line
[line_pos
] != '#') {
213 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
,
214 "extra characters on line %d: %s\n",
215 line_num
, line
+ line_pos
);
220 if (!strcmp(opt
, "profile-desc"))
221 m_profile_set_desc(profile
, param
), tmp
= 1;
223 tmp
= m_config_set_profile_option(config
, profile
,
226 tmp
= m_config_set_option0(config
, opt
, param
, false);
229 if (tmp
== M_OPT_UNKNOWN
) {
230 mp_msg(MSGT_CFGPARSER
, MSGL_WARN
,
231 "Warning unknown option %s at line %d\n",
235 mp_msg(MSGT_CFGPARSER
, MSGL_ERR
,
236 "Error parsing option %s=%s at line %d\n",
237 opt
, param
, line_num
);
250 config
->mode
= prev_mode
;