libcdio
[mplayer.git] / parser-cfg.c
blob587a348e3cdb11b14efd9bb0fb8eb3f94b1f33a0
1 #include "config.h"
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <ctype.h>
9 #ifdef MP_DEBUG
10 #include <assert.h>
11 #endif
13 #include "mp_msg.h"
14 #include "m_option.h"
15 #include "m_config.h"
17 #define MAX_RECURSION_DEPTH 8
19 static int recursion_depth = 0;
21 int m_config_parse_config_file(m_config_t* config, char *conffile)
23 #define PRINT_LINENUM mp_msg(MSGT_CFGPARSER,MSGL_V,"%s(%d): ", conffile, line_num)
24 #define MAX_LINE_LEN 10000
25 #define MAX_OPT_LEN 1000
26 #define MAX_PARAM_LEN 1000
27 FILE *fp;
28 char *line;
29 char opt[MAX_OPT_LEN + 1];
30 char param[MAX_PARAM_LEN + 1];
31 char c; /* for the "" and '' check */
32 int tmp;
33 int line_num = 0;
34 int line_pos; /* line pos */
35 int opt_pos; /* opt pos */
36 int param_pos; /* param pos */
37 int ret = 1;
38 int errors = 0;
39 int prev_mode = config->mode;
41 #ifdef MP_DEBUG
42 assert(config != NULL);
43 // assert(conf_list != NULL);
44 #endif
45 mp_msg(MSGT_CFGPARSER,MSGL_V,"Reading config file %s", conffile);
47 if (recursion_depth > MAX_RECURSION_DEPTH) {
48 mp_msg(MSGT_CFGPARSER,MSGL_ERR,": too deep 'include'. check your configfiles\n");
49 ret = -1;
50 goto out;
51 } else
53 config->mode = M_CONFIG_FILE;
55 if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) {
56 mp_msg(MSGT_CFGPARSER,MSGL_FATAL,"\ncan't get memory for 'line': %s", strerror(errno));
57 ret = -1;
58 goto out;
61 if ((fp = fopen(conffile, "r")) == NULL) {
62 mp_msg(MSGT_CFGPARSER,MSGL_V,": %s\n", strerror(errno));
63 free(line);
64 ret = 0;
65 goto out;
67 mp_msg(MSGT_CFGPARSER,MSGL_INFO,"\n");
69 while (fgets(line, MAX_LINE_LEN, fp)) {
70 if (errors >= 16) {
71 mp_msg(MSGT_CFGPARSER,MSGL_FATAL,"too many errors\n");
72 goto out;
75 line_num++;
76 line_pos = 0;
78 /* skip whitespaces */
79 while (isspace(line[line_pos]))
80 ++line_pos;
82 /* EOL / comment */
83 if (line[line_pos] == '\0' || line[line_pos] == '#')
84 continue;
86 /* read option. */
87 for (opt_pos = 0; isprint(line[line_pos]) &&
88 line[line_pos] != ' ' &&
89 line[line_pos] != '#' &&
90 line[line_pos] != '='; /* NOTHING */) {
91 opt[opt_pos++] = line[line_pos++];
92 if (opt_pos >= MAX_OPT_LEN) {
93 PRINT_LINENUM;
94 mp_msg(MSGT_CFGPARSER,MSGL_ERR,"too long option at line %d\n",line_num);
95 errors++;
96 ret = -1;
97 goto nextline;
100 if (opt_pos == 0) {
101 PRINT_LINENUM;
102 mp_msg(MSGT_CFGPARSER,MSGL_ERR,"parse error at line %d\n",line_num);
103 ret = -1;
104 errors++;
105 continue;
107 opt[opt_pos] = '\0';
109 #ifdef MP_DEBUG
110 PRINT_LINENUM;
111 mp_msg(MSGT_CFGPARSER,MSGL_V,"option: %s\n", opt);
112 #endif
114 /* skip whitespaces */
115 while (isspace(line[line_pos]))
116 ++line_pos;
118 /* check '=' */
119 if (line[line_pos++] != '=') {
120 PRINT_LINENUM;
121 mp_msg(MSGT_CFGPARSER,MSGL_ERR,"Option %s needs a parameter at line %d\n",opt,line_num);
122 ret = -1;
123 errors++;
124 continue;
127 /* whitespaces... */
128 while (isspace(line[line_pos]))
129 ++line_pos;
131 /* read the parameter */
132 if (line[line_pos] == '"' || line[line_pos] == '\'') {
133 c = line[line_pos];
134 ++line_pos;
135 for (param_pos = 0; line[line_pos] != c; /* NOTHING */) {
136 param[param_pos++] = line[line_pos++];
137 if (param_pos >= MAX_PARAM_LEN) {
138 PRINT_LINENUM;
139 mp_msg(MSGT_CFGPARSER,MSGL_ERR,"Option %s has a too long parameter at line %d\n",opt,line_num);
140 ret = -1;
141 errors++;
142 goto nextline;
145 line_pos++; /* skip the closing " or ' */
146 } else {
147 for (param_pos = 0; isprint(line[line_pos]) && !isspace(line[line_pos])
148 && line[line_pos] != '#'; /* NOTHING */) {
149 param[param_pos++] = line[line_pos++];
150 if (param_pos >= MAX_PARAM_LEN) {
151 PRINT_LINENUM;
152 mp_msg(MSGT_CFGPARSER,MSGL_ERR,"too long parameter\n");
153 ret = -1;
154 errors++;
155 goto nextline;
159 param[param_pos] = '\0';
161 /* did we read a parameter? */
162 if (param_pos == 0) {
163 PRINT_LINENUM;
164 mp_msg(MSGT_CFGPARSER,MSGL_ERR,"Option %s needs a parameter at line %d\n",opt,line_num);
165 ret = -1;
166 errors++;
167 continue;
170 #ifdef MP_DEBUG
171 PRINT_LINENUM;
172 mp_msg(MSGT_CFGPARSER,MSGL_V,"parameter: %s\n", param);
173 #endif
175 /* now, check if we have some more chars on the line */
176 /* whitespace... */
177 while (isspace(line[line_pos]))
178 ++line_pos;
180 /* EOL / comment */
181 if (line[line_pos] != '\0' && line[line_pos] != '#') {
182 PRINT_LINENUM;
183 mp_msg(MSGT_CFGPARSER,MSGL_WARN,"extra characters on line %d: %s\n",line_num, line+line_pos);
184 ret = -1;
187 tmp = m_config_set_option(config, opt, param);
188 if (tmp < 0) {
189 PRINT_LINENUM;
190 if(tmp == M_OPT_UNKNOWN) {
191 mp_msg(MSGT_CFGPARSER,MSGL_WARN,"Warning unknown option %s at line %d\n", opt,line_num);
192 continue;
194 mp_msg(MSGT_CFGPARSER,MSGL_ERR,"Error parsing option %s=%s at line %d\n",opt,param,line_num);
195 ret = -1;
196 errors++;
197 continue;
198 /* break */
200 nextline:
204 free(line);
205 fclose(fp);
206 out:
207 config->mode = prev_mode;
208 --recursion_depth;
209 return ret;