Mercurial > mplayer.hg
annotate cfgparser.c @ 179:6f890e61739b
fix...
author | szabii |
---|---|
date | Wed, 21 Mar 2001 02:56:06 +0000 |
parents | 554c6e5f36ef |
children | aa52cdb712d8 |
rev | line source |
---|---|
147 | 1 /* |
2 * command line and config file parser | |
3 */ | |
4 | |
5 //#define DEBUG | |
6 | |
7 #include <stdlib.h> | |
8 #include <stdio.h> | |
9 #include <ctype.h> | |
10 #include <unistd.h> | |
11 #include <fcntl.h> | |
12 #include <string.h> | |
13 | |
14 #define ERR_NOT_AN_OPTION -1 | |
15 #define ERR_MISSING_PARAM -2 | |
16 #define ERR_OUT_OF_RANGE -3 | |
150 | 17 #define ERR_FUNC_ERR -4 |
147 | 18 |
19 #define COMMAND_LINE 0 | |
20 #define CONFIG_FILE 1 | |
21 | |
177 | 22 #define MAX_RECURSION_DEPTH 8 |
166 | 23 |
147 | 24 #ifdef DEBUG |
25 #include <assert.h> | |
26 #endif | |
27 | |
28 #include "cfgparser.h" | |
29 | |
30 static struct config *config; | |
31 static int nr_options; /* number of options in 'conf' */ | |
32 static int parser_mode; /* COMMAND_LINE or CONFIG_FILE */ | |
166 | 33 static int recursion_depth = 0; |
147 | 34 |
35 static int init_conf(struct config *conf, int mode) | |
36 { | |
37 #ifdef DEBUG | |
38 assert(conf != NULL); | |
39 #endif | |
40 | |
41 /* calculate the number of options in 'conf' */ | |
42 for (nr_options = 0; conf[nr_options].name != NULL; nr_options++) | |
43 /* NOTHING */; | |
44 | |
45 config = conf; | |
46 #ifdef DEBUG | |
47 if (mode != COMMAND_LINE && mode != CONFIG_FILE) { | |
150 | 48 printf("init_conf: wrong mode!\n"); |
147 | 49 return -1; |
50 } | |
51 #endif | |
52 parser_mode = mode; | |
53 return 1; | |
54 } | |
55 | |
56 static int read_option(char *opt, char *param) | |
57 { | |
58 int i; | |
59 int tmp_int; | |
60 float tmp_float; | |
160 | 61 int ret = -1; |
147 | 62 |
63 for (i = 0; i < nr_options; i++) { | |
64 if (!strcasecmp(opt, config[i].name)) | |
65 break; | |
66 } | |
160 | 67 if (i == nr_options) { |
68 printf("invalid option:\n"); | |
69 ret = ERR_NOT_AN_OPTION; | |
70 goto out; | |
71 } | |
72 if (config[i].flags & CONF_NOCFG && parser_mode == CONFIG_FILE) { | |
73 printf("this option can only be used on command line:\n"); | |
74 ret = ERR_NOT_AN_OPTION; | |
75 goto out; | |
76 } | |
77 if (config[i].flags & CONF_NOCMD && parser_mode == COMMAND_LINE) { | |
78 printf("this option can only be used in config file:\n"); | |
79 ret = ERR_NOT_AN_OPTION; | |
80 goto out; | |
81 } | |
150 | 82 |
147 | 83 switch (config[i].type) { |
84 case CONF_TYPE_FLAG: | |
85 /* flags need a parameter in config file */ | |
86 if (parser_mode == CONFIG_FILE) { | |
87 if (!strcasecmp(param, "yes") || /* any other language? */ | |
88 !strcasecmp(param, "ja") || | |
161
9008302e2dc0
Added support for spanish (Yes, I'm a C programer also ;o)
telenieko
parents:
160
diff
changeset
|
89 !strcasecmp(param, "si") || |
147 | 90 !strcasecmp(param, "igen") || |
91 !strcasecmp(param, "y") || | |
92 !strcasecmp(param, "i") || | |
93 !strcmp(param, "1")) | |
94 *((int *) config[i].p) = config[i].max; | |
151 | 95 else if (!strcasecmp(param, "no") || |
147 | 96 !strcasecmp(param, "nein") || |
97 !strcasecmp(param, "nicht") || | |
98 !strcasecmp(param, "nem") || | |
99 !strcasecmp(param, "n") || | |
100 !strcmp(param, "0")) | |
101 *((int *) config[i].p) = config[i].min; | |
160 | 102 else { |
103 printf("invalid parameter for flag:\n"); | |
104 ret = ERR_OUT_OF_RANGE; | |
105 goto out; | |
106 } | |
107 ret = 1; | |
147 | 108 } else { /* parser_mode == COMMAND_LINE */ |
109 *((int *) config[i].p) = config[i].max; | |
160 | 110 ret = 0; |
147 | 111 } |
112 break; | |
113 case CONF_TYPE_INT: | |
114 if (param == NULL) | |
160 | 115 goto err_missing_param; |
116 if (!isdigit(*param)) { | |
117 printf("parameter must be an integer:\n"); | |
118 ret = ERR_OUT_OF_RANGE; | |
119 goto out; | |
120 } | |
147 | 121 |
122 tmp_int = atoi(param); | |
123 | |
153 | 124 if (config[i].flags & CONF_MIN) |
160 | 125 if (tmp_int < config[i].min) { |
126 printf("parameter must be >= %d:\n", (int) config[i].min); | |
127 ret = ERR_OUT_OF_RANGE; | |
128 goto out; | |
129 } | |
147 | 130 |
153 | 131 if (config[i].flags & CONF_MAX) |
160 | 132 if (tmp_int > config[i].max) { |
133 printf("parameter must be <= %d:\n", (int) config[i].max); | |
134 ret = ERR_OUT_OF_RANGE; | |
135 goto out; | |
136 } | |
147 | 137 |
138 *((int *) config[i].p) = tmp_int; | |
160 | 139 ret = 1; |
147 | 140 break; |
141 case CONF_TYPE_FLOAT: | |
142 if (param == NULL) | |
160 | 143 goto err_missing_param; |
144 if (!isdigit(*param)) { | |
145 printf("parameter must be a floating point number:\n"); | |
146 ret = ERR_MISSING_PARAM; | |
147 goto out; | |
148 } | |
147 | 149 |
150 tmp_float = atof(param); | |
151 | |
153 | 152 if (config[i].flags & CONF_MIN) |
160 | 153 if (tmp_float < config[i].min) { |
154 printf("parameter must be >= %f:\n", config[i].min); | |
155 ret = ERR_OUT_OF_RANGE; | |
156 goto out; | |
157 } | |
147 | 158 |
153 | 159 if (config[i].flags & CONF_MAX) |
160 | 160 if (tmp_float > config[i].max) { |
161 printf("parameter must be <= %f:\n", config[i].max); | |
162 ret = ERR_OUT_OF_RANGE; | |
163 goto out; | |
164 } | |
147 | 165 |
166 *((float *) config[i].p) = tmp_float; | |
160 | 167 ret = 1; |
147 | 168 break; |
169 case CONF_TYPE_STRING: | |
170 if (param == NULL) | |
160 | 171 goto err_missing_param; |
147 | 172 |
153 | 173 if (config[i].flags & CONF_MIN) |
160 | 174 if (strlen(param) < config[i].min) { |
175 printf("parameter must be >= %d chars:\n", | |
176 (int) config[i].min); | |
177 ret = ERR_OUT_OF_RANGE; | |
178 goto out; | |
179 } | |
147 | 180 |
153 | 181 if (config[i].flags & CONF_MAX) |
160 | 182 if (strlen(param) > config[i].max) { |
183 printf("parameter must be <= %d chars:\n", | |
184 (int) config[i].max); | |
185 ret = ERR_OUT_OF_RANGE; | |
186 goto out; | |
187 } | |
147 | 188 |
189 *((char **) config[i].p) = strdup(param); | |
160 | 190 ret = 1; |
147 | 191 break; |
151 | 192 case CONF_TYPE_FUNC_PARAM: |
193 if (param == NULL) | |
160 | 194 goto err_missing_param; |
195 if ((((cfg_func_param_t) config[i].p)(config + i, param)) < 0) { | |
196 ret = ERR_FUNC_ERR; | |
197 goto out; | |
198 } | |
199 ret = 1; | |
151 | 200 break; |
150 | 201 case CONF_TYPE_FUNC: |
160 | 202 if ((((cfg_func_t) config[i].p)(config + i)) < 0) { |
203 ret = ERR_FUNC_ERR; | |
204 goto out; | |
205 } | |
206 ret = 0; | |
150 | 207 break; |
152 | 208 case CONF_TYPE_PRINT: |
209 printf("%s", (char *) config[i].p); | |
210 exit(1); | |
147 | 211 default: |
212 printf("picsaba\n"); | |
213 break; | |
214 } | |
160 | 215 out: |
216 return ret; | |
217 err_missing_param: | |
218 printf("missing parameter:\n"); | |
219 ret = ERR_MISSING_PARAM; | |
220 goto out; | |
147 | 221 } |
222 | |
223 int parse_config_file(struct config *conf, char *conffile) | |
224 { | |
225 #define PRINT_LINENUM printf("%s(%d): ", conffile, line_num) | |
226 #define MAX_LINE_LEN 1000 | |
227 #define MAX_OPT_LEN 100 | |
228 #define MAX_PARAM_LEN 100 | |
229 FILE *fp; | |
230 char *line; | |
179 | 231 char opt[MAX_OPT_LEN + 1]; |
232 char param[MAX_PARAM_LEN + 1]; | |
167 | 233 char c; /* for the "" and '' check */ |
147 | 234 int tmp; |
235 int line_num = 0; | |
236 int line_pos; /* line pos */ | |
237 int opt_pos; /* opt pos */ | |
238 int param_pos; /* param pos */ | |
239 int ret = 1; | |
240 | |
241 #ifdef DEBUG | |
242 assert(conffile != NULL); | |
243 #endif | |
166 | 244 if (++recursion_depth > MAX_RECURSION_DEPTH) { |
245 printf("too deep 'include'. check your configfiles\n"); | |
179 | 246 --recursion_depth; |
166 | 247 return -1; |
248 } | |
249 | |
147 | 250 printf("Reading config file: %s\n", conffile); |
251 | |
166 | 252 if (init_conf(conf, CONFIG_FILE) == -1) { |
253 ret = -1; | |
254 goto out; | |
255 } | |
147 | 256 |
179 | 257 if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) { |
147 | 258 perror("parse_config_file: can't get memory for 'line'"); |
166 | 259 ret = -1; |
260 goto out; | |
147 | 261 } |
262 | |
263 if ((fp = fopen(conffile, "r")) == NULL) { | |
264 perror("parse_config_file: can't open filename"); | |
265 free(line); | |
166 | 266 ret = 0; |
267 goto out; | |
147 | 268 } |
269 | |
270 while (fgets(line, MAX_LINE_LEN, fp)) { | |
271 line_num++; | |
272 line_pos = 0; | |
273 | |
274 /* skip whitespaces */ | |
275 while (isspace(line[line_pos])) | |
276 ++line_pos; | |
277 | |
278 /* EOL / comment */ | |
279 if (line[line_pos] == '\0' || line[line_pos] == '#') | |
280 continue; | |
281 | |
282 /* read option. accept char if isalnum(char) */ | |
283 for (opt_pos = 0; isalnum(line[line_pos]); /* NOTHING */) { | |
284 opt[opt_pos++] = line[line_pos++]; | |
285 if (opt_pos >= MAX_OPT_LEN) { | |
286 PRINT_LINENUM; | |
287 printf("too long option\n"); | |
288 ret = -1; | |
289 continue; | |
290 } | |
291 } | |
292 if (opt_pos == 0) { | |
293 PRINT_LINENUM; | |
294 printf("parse error\n"); | |
295 ret = -1; | |
296 continue; | |
297 } | |
298 opt[opt_pos] = '\0'; | |
299 #ifdef DEBUG | |
300 PRINT_LINENUM; | |
301 printf("option: %s\n", opt); | |
302 #endif | |
303 | |
304 /* skip whitespaces */ | |
305 while (isspace(line[line_pos])) | |
306 ++line_pos; | |
307 | |
308 /* check '=' */ | |
309 if (line[line_pos++] != '=') { | |
310 PRINT_LINENUM; | |
311 printf("option without parameter\n"); | |
312 ret = -1; | |
313 continue; | |
314 } | |
315 | |
316 /* whitespaces... */ | |
317 while (isspace(line[line_pos])) | |
318 ++line_pos; | |
319 | |
320 /* read the parameter */ | |
167 | 321 if (line[line_pos] == '"' || line[line_pos] == '\'') { |
322 c = line[line_pos]; | |
323 ++line_pos; | |
324 for (param_pos = 0; line[line_pos] != c; /* NOTHING */) { | |
325 param[param_pos++] = line[line_pos++]; | |
326 if (param_pos >= MAX_PARAM_LEN) { | |
327 PRINT_LINENUM; | |
328 printf("too long parameter\n"); | |
329 ret = -1; | |
330 continue; | |
331 } | |
332 } | |
333 line_pos++; /* skip the closing " or ' */ | |
334 } else { | |
335 for (param_pos = 0; isprint(line[line_pos]) && !isspace(line[line_pos]) | |
336 && line[line_pos] != '#'; /* NOTHING */) { | |
337 param[param_pos++] = line[line_pos++]; | |
338 if (param_pos >= MAX_PARAM_LEN) { | |
339 PRINT_LINENUM; | |
340 printf("too long parameter\n"); | |
341 ret = -1; | |
342 continue; | |
343 } | |
147 | 344 } |
345 } | |
346 param[param_pos] = '\0'; | |
347 | |
348 /* did we read a parameter? */ | |
349 if (param_pos == 0) { | |
350 PRINT_LINENUM; | |
351 printf("option without parameter\n"); | |
352 ret = -1; | |
353 continue; | |
354 } | |
355 #ifdef DEBUG | |
356 PRINT_LINENUM; | |
357 printf("parameter: %s\n", param); | |
358 #endif | |
359 /* now, check if we have some more chars on the line */ | |
360 /* whitespace... */ | |
361 while (isspace(line[line_pos])) | |
362 ++line_pos; | |
363 | |
364 /* EOL / comment */ | |
365 if (line[line_pos] != '\0' && line[line_pos] != '#') { | |
366 PRINT_LINENUM; | |
367 printf("extra characters on line: %s\n", line+line_pos); | |
368 ret = -1; | |
369 } | |
370 | |
371 tmp = read_option(opt, param); | |
372 switch (tmp) { | |
373 case ERR_NOT_AN_OPTION: | |
374 case ERR_MISSING_PARAM: | |
375 case ERR_OUT_OF_RANGE: | |
150 | 376 case ERR_FUNC_ERR: |
377 PRINT_LINENUM; | |
160 | 378 printf("%s\n", opt); |
150 | 379 ret = -1; |
380 continue; | |
381 /* break */ | |
147 | 382 } |
383 } | |
384 | |
385 free(line); | |
386 fclose(fp); | |
166 | 387 out: |
388 --recursion_depth; | |
147 | 389 return ret; |
390 } | |
391 | |
392 int parse_command_line(struct config *conf, int argc, char **argv, char **envp, char **filename) | |
393 { | |
394 int i; | |
395 int found_filename = 0; | |
396 int tmp; | |
397 char *opt; | |
398 | |
399 #ifdef DEBUG | |
400 assert(argv != NULL); | |
401 assert(envp != NULL); | |
402 assert(argc >= 1); | |
403 #endif | |
404 | |
405 if (init_conf(conf, COMMAND_LINE) == -1) | |
406 return -1; | |
407 | |
408 for (i = 1; i < argc; i++) { | |
409 opt = argv[i]; | |
410 if (*opt != '-') | |
411 goto not_an_option; | |
412 | |
413 /* remove trailing '-' */ | |
414 opt++; | |
415 | |
416 tmp = read_option(opt, argv[i + 1]); | |
417 | |
418 switch (tmp) { | |
419 case ERR_NOT_AN_OPTION: | |
420 not_an_option: | |
421 /* opt is not an option -> treat it as a filename */ | |
422 if (found_filename) { | |
423 /* we already have a filename */ | |
160 | 424 goto err_out; |
147 | 425 } else { |
426 found_filename = 1; | |
427 *filename = argv[i]; | |
428 printf("parse_command_line: found filename: %s\n", *filename); | |
429 continue; /* next option */ | |
430 } | |
431 break; | |
432 case ERR_MISSING_PARAM: | |
433 case ERR_OUT_OF_RANGE: | |
150 | 434 case ERR_FUNC_ERR: |
160 | 435 goto err_out; |
150 | 436 /* break; */ |
147 | 437 } |
438 | |
439 i += tmp; /* we already processed the params (if there was any) */ | |
160 | 440 } |
147 | 441 return found_filename; |
160 | 442 err_out: |
443 printf("parse_command_line: %s\n", argv[i]); | |
444 return -1; | |
147 | 445 } |