Mercurial > mplayer.hg
annotate cfgparser.c @ 3715:c39bedc45423
Hint #2 -> Hint
"also try i420 colorspace"
author | gabucino |
---|---|
date | Mon, 24 Dec 2001 15:53:15 +0000 |
parents | 00bd914b6fb1 |
children | b66a62f332d6 |
rev | line source |
---|---|
147 | 1 /* |
2 * command line and config file parser | |
336 | 3 * by Szabolcs Berecz <szabi@inf.elte.hu> |
4 * (C) 2001 | |
2619 | 5 * |
6 * subconfig support by alex | |
147 | 7 */ |
8 | |
9 //#define DEBUG | |
10 | |
11 #include <stdlib.h> | |
12 #include <stdio.h> | |
13 #include <ctype.h> | |
14 #include <unistd.h> | |
15 #include <fcntl.h> | |
16 #include <string.h> | |
336 | 17 #include <errno.h> |
147 | 18 |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
19 #include "mp_msg.h" |
147 | 20 |
21 #define COMMAND_LINE 0 | |
22 #define CONFIG_FILE 1 | |
23 | |
177 | 24 #define MAX_RECURSION_DEPTH 8 |
166 | 25 |
147 | 26 #ifdef DEBUG |
27 #include <assert.h> | |
28 #endif | |
29 | |
30 #include "cfgparser.h" | |
31 | |
32 static struct config *config; | |
33 static int nr_options; /* number of options in 'conf' */ | |
34 static int parser_mode; /* COMMAND_LINE or CONFIG_FILE */ | |
166 | 35 static int recursion_depth = 0; |
147 | 36 |
37 static int init_conf(struct config *conf, int mode) | |
38 { | |
39 #ifdef DEBUG | |
40 assert(conf != NULL); | |
41 #endif | |
42 | |
43 /* calculate the number of options in 'conf' */ | |
44 for (nr_options = 0; conf[nr_options].name != NULL; nr_options++) | |
45 /* NOTHING */; | |
46 | |
47 config = conf; | |
48 #ifdef DEBUG | |
49 if (mode != COMMAND_LINE && mode != CONFIG_FILE) { | |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
50 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "init_conf: wrong mode!\n"); |
147 | 51 return -1; |
52 } | |
53 #endif | |
54 parser_mode = mode; | |
55 return 1; | |
56 } | |
57 | |
2619 | 58 static int read_option(struct config *conf, int conf_optnr, char *opt, char *param) |
147 | 59 { |
60 int i; | |
195 | 61 long tmp_int; |
62 double tmp_float; | |
160 | 63 int ret = -1; |
195 | 64 char *endptr; |
147 | 65 |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
66 mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "read_option: conf=%p optnr=%d opt='%s' param='%s'\n", |
2621 | 67 conf, conf_optnr, opt, param); |
2619 | 68 for (i = 0; i < conf_optnr; i++) { |
1536
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
69 int namelength; |
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
70 /* allow 'aa*' in config.name */ |
2619 | 71 namelength=strlen(conf[i].name); |
72 if ( (conf[i].name[namelength-1]=='*') && | |
73 !memcmp(opt, conf[i].name, namelength-1)) | |
1536
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
74 break; |
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
75 |
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
76 |
2619 | 77 if (!strcasecmp(opt, conf[i].name)) |
147 | 78 break; |
79 } | |
2619 | 80 if (i == conf_optnr) { |
2380 | 81 if (parser_mode == CONFIG_FILE) |
3684
00bd914b6fb1
subconfig fix (if sscanf()==1, then null out second (non-present) parameter) and some errormessage fixes
alex
parents:
3613
diff
changeset
|
82 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid option: %s\n", opt); |
160 | 83 ret = ERR_NOT_AN_OPTION; |
84 goto out; | |
85 } | |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
86 mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "read_option: name='%s' p=%p type=%d\n", |
2621 | 87 conf[i].name, conf[i].p, conf[i].type); |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
88 |
2619 | 89 if (conf[i].flags & CONF_NOCFG && parser_mode == CONFIG_FILE) { |
3684
00bd914b6fb1
subconfig fix (if sscanf()==1, then null out second (non-present) parameter) and some errormessage fixes
alex
parents:
3613
diff
changeset
|
90 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "this option can only be used on command line: %s\n", opt); |
160 | 91 ret = ERR_NOT_AN_OPTION; |
92 goto out; | |
93 } | |
2619 | 94 if (conf[i].flags & CONF_NOCMD && parser_mode == COMMAND_LINE) { |
3684
00bd914b6fb1
subconfig fix (if sscanf()==1, then null out second (non-present) parameter) and some errormessage fixes
alex
parents:
3613
diff
changeset
|
95 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "this option can only be used in config file: %s\n", opt); |
160 | 96 ret = ERR_NOT_AN_OPTION; |
97 goto out; | |
98 } | |
150 | 99 |
2619 | 100 switch (conf[i].type) { |
147 | 101 case CONF_TYPE_FLAG: |
102 /* flags need a parameter in config file */ | |
103 if (parser_mode == CONFIG_FILE) { | |
104 if (!strcasecmp(param, "yes") || /* any other language? */ | |
105 !strcasecmp(param, "ja") || | |
161
9008302e2dc0
Added support for spanish (Yes, I'm a C programer also ;o)
telenieko
parents:
160
diff
changeset
|
106 !strcasecmp(param, "si") || |
147 | 107 !strcasecmp(param, "igen") || |
108 !strcasecmp(param, "y") || | |
1536
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
109 !strcasecmp(param, "j") || |
147 | 110 !strcasecmp(param, "i") || |
111 !strcmp(param, "1")) | |
2619 | 112 *((int *) conf[i].p) = conf[i].max; |
151 | 113 else if (!strcasecmp(param, "no") || |
147 | 114 !strcasecmp(param, "nein") || |
115 !strcasecmp(param, "nicht") || | |
116 !strcasecmp(param, "nem") || | |
117 !strcasecmp(param, "n") || | |
118 !strcmp(param, "0")) | |
2619 | 119 *((int *) conf[i].p) = conf[i].min; |
160 | 120 else { |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
121 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "invalid parameter for flag: %s\n", param); |
160 | 122 ret = ERR_OUT_OF_RANGE; |
123 goto out; | |
124 } | |
125 ret = 1; | |
147 | 126 } else { /* parser_mode == COMMAND_LINE */ |
2619 | 127 *((int *) conf[i].p) = conf[i].max; |
160 | 128 ret = 0; |
147 | 129 } |
130 break; | |
131 case CONF_TYPE_INT: | |
132 if (param == NULL) | |
160 | 133 goto err_missing_param; |
195 | 134 |
135 tmp_int = strtol(param, &endptr, 0); | |
136 if (*endptr) { | |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
137 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be an integer: %s\n", param); |
160 | 138 ret = ERR_OUT_OF_RANGE; |
139 goto out; | |
140 } | |
147 | 141 |
2619 | 142 if (conf[i].flags & CONF_MIN) |
143 if (tmp_int < conf[i].min) { | |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
144 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %d: %s\n", (int) conf[i].min, param); |
160 | 145 ret = ERR_OUT_OF_RANGE; |
146 goto out; | |
147 } | |
147 | 148 |
2619 | 149 if (conf[i].flags & CONF_MAX) |
150 if (tmp_int > conf[i].max) { | |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
151 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %d: %s\n", (int) conf[i].max, param); |
160 | 152 ret = ERR_OUT_OF_RANGE; |
153 goto out; | |
154 } | |
147 | 155 |
2619 | 156 *((int *) conf[i].p) = tmp_int; |
160 | 157 ret = 1; |
147 | 158 break; |
159 case CONF_TYPE_FLOAT: | |
160 if (param == NULL) | |
160 | 161 goto err_missing_param; |
195 | 162 |
163 tmp_float = strtod(param, &endptr); | |
2031
624df8ea0e0e
New aspect prescale code, parses aspect value from mpeg sequence header or commandline.
atmos4
parents:
1629
diff
changeset
|
164 |
624df8ea0e0e
New aspect prescale code, parses aspect value from mpeg sequence header or commandline.
atmos4
parents:
1629
diff
changeset
|
165 if ((*endptr == ':') || (*endptr == '/')) |
624df8ea0e0e
New aspect prescale code, parses aspect value from mpeg sequence header or commandline.
atmos4
parents:
1629
diff
changeset
|
166 tmp_float /= strtod(endptr+1, &endptr); |
624df8ea0e0e
New aspect prescale code, parses aspect value from mpeg sequence header or commandline.
atmos4
parents:
1629
diff
changeset
|
167 |
195 | 168 if (*endptr) { |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
169 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be a floating point number" |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
170 " or a ratio (numerator[:/]denominator): %s\n", param); |
160 | 171 ret = ERR_MISSING_PARAM; |
172 goto out; | |
173 } | |
147 | 174 |
2619 | 175 if (conf[i].flags & CONF_MIN) |
176 if (tmp_float < conf[i].min) { | |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
177 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %f: %s\n", conf[i].min, param); |
160 | 178 ret = ERR_OUT_OF_RANGE; |
179 goto out; | |
180 } | |
147 | 181 |
2619 | 182 if (conf[i].flags & CONF_MAX) |
183 if (tmp_float > conf[i].max) { | |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
184 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %f: %s\n", conf[i].max, param); |
160 | 185 ret = ERR_OUT_OF_RANGE; |
186 goto out; | |
187 } | |
147 | 188 |
2619 | 189 *((float *) conf[i].p) = tmp_float; |
160 | 190 ret = 1; |
147 | 191 break; |
192 case CONF_TYPE_STRING: | |
193 if (param == NULL) | |
160 | 194 goto err_missing_param; |
147 | 195 |
2619 | 196 if (conf[i].flags & CONF_MIN) |
197 if (strlen(param) < conf[i].min) { | |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
198 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be >= %d chars: %s\n", |
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
199 (int) conf[i].min, param); |
160 | 200 ret = ERR_OUT_OF_RANGE; |
201 goto out; | |
202 } | |
147 | 203 |
2619 | 204 if (conf[i].flags & CONF_MAX) |
205 if (strlen(param) > conf[i].max) { | |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
206 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "parameter must be <= %d chars: %s\n", |
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
207 (int) conf[i].max, param); |
160 | 208 ret = ERR_OUT_OF_RANGE; |
209 goto out; | |
210 } | |
2619 | 211 *((char **) conf[i].p) = strdup(param); |
160 | 212 ret = 1; |
147 | 213 break; |
151 | 214 case CONF_TYPE_FUNC_PARAM: |
215 if (param == NULL) | |
160 | 216 goto err_missing_param; |
2619 | 217 if ((((cfg_func_param_t) conf[i].p)(config + i, param)) < 0) { |
160 | 218 ret = ERR_FUNC_ERR; |
219 goto out; | |
220 } | |
221 ret = 1; | |
151 | 222 break; |
1536
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
223 case CONF_TYPE_FUNC_FULL: |
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
224 if (param!=NULL && param[0]=='-'){ |
2619 | 225 ret=((cfg_func_arg_param_t) conf[i].p)(config + i, opt, NULL); |
1536
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
226 if (ret>=0) ret=0; |
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
227 /* if we return >=0: param is processed again (if there is any) */ |
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
228 }else{ |
2619 | 229 ret=((cfg_func_arg_param_t) conf[i].p)(config + i, opt, param); |
1536
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
230 /* if we return 0: need no param, precess it again */ |
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
231 /* if we return 1: accepted param */ |
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
232 } |
e89233dab4da
New feature for option processing: CONF_TYPE_FUNC_FULL
folke
parents:
1304
diff
changeset
|
233 break; |
150 | 234 case CONF_TYPE_FUNC: |
2619 | 235 if ((((cfg_func_t) conf[i].p)(config + i)) < 0) { |
160 | 236 ret = ERR_FUNC_ERR; |
237 goto out; | |
238 } | |
239 ret = 0; | |
150 | 240 break; |
2619 | 241 case CONF_TYPE_SUBCONFIG: |
242 { | |
243 char *subparam; | |
244 char *subopt; | |
245 int subconf_optnr; | |
246 struct config *subconf; | |
247 char *token; | |
248 | |
249 if (param == NULL) | |
250 goto err_missing_param; | |
251 | |
3613 | 252 subparam = malloc(strlen(param)+1); |
253 subopt = malloc(strlen(param)+1); | |
2619 | 254 |
255 subconf = conf[i].p; | |
256 for (subconf_optnr = 0; subconf[subconf_optnr].name != NULL; subconf_optnr++) | |
257 /* NOTHING */; | |
258 | |
259 token = strtok(param, (char *)&(":")); | |
260 while(token) | |
261 { | |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
262 int sscanf_ret; |
2619 | 263 |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
264 sscanf_ret = sscanf(token, "%[^=]=%s", subopt, subparam); |
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
265 switch(sscanf_ret) |
2621 | 266 { |
267 case 1: | |
3684
00bd914b6fb1
subconfig fix (if sscanf()==1, then null out second (non-present) parameter) and some errormessage fixes
alex
parents:
3613
diff
changeset
|
268 subparam = NULL; |
2621 | 269 case 2: |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
270 if ((ret = read_option((struct config *)subconf, subconf_optnr, subopt, subparam)) < 0) |
2621 | 271 { |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
272 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Subconfig parsing returned error: %d in token: %s\n", |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
273 ret, token); |
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
274 goto out; |
2621 | 275 } |
276 break; | |
277 default: | |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
278 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Invalid subconfig argument! ('%s')\n", token); |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
279 ret = ERR_NOT_AN_OPTION; |
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
280 goto out; |
2621 | 281 } |
3559
f61dcc63be5f
exchanged return with goto out in subconfig parsing and fixed error messages
alex
parents:
2650
diff
changeset
|
282 mp_dbg(MSGT_CFGPARSER, MSGL_DBG3, "token: '%s', i=%d, subopt='%s, subparam='%s'\n", token, i, subopt, subparam); |
2619 | 283 token = strtok(NULL, (char *)&(":")); |
284 } | |
285 | |
286 free(subparam); | |
287 free(subopt); | |
288 ret = 1; | |
289 break; | |
290 } | |
152 | 291 case CONF_TYPE_PRINT: |
2619 | 292 printf("%s", (char *) conf[i].p); |
152 | 293 exit(1); |
147 | 294 default: |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
295 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Unknown config type specified in conf-mplayer.h!\n"); |
147 | 296 break; |
297 } | |
160 | 298 out: |
299 return ret; | |
300 err_missing_param: | |
3684
00bd914b6fb1
subconfig fix (if sscanf()==1, then null out second (non-present) parameter) and some errormessage fixes
alex
parents:
3613
diff
changeset
|
301 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "missing parameter for option: %s\n", opt); |
160 | 302 ret = ERR_MISSING_PARAM; |
303 goto out; | |
147 | 304 } |
305 | |
306 int parse_config_file(struct config *conf, char *conffile) | |
307 { | |
308 #define PRINT_LINENUM printf("%s(%d): ", conffile, line_num) | |
309 #define MAX_LINE_LEN 1000 | |
310 #define MAX_OPT_LEN 100 | |
311 #define MAX_PARAM_LEN 100 | |
312 FILE *fp; | |
313 char *line; | |
179 | 314 char opt[MAX_OPT_LEN + 1]; |
315 char param[MAX_PARAM_LEN + 1]; | |
167 | 316 char c; /* for the "" and '' check */ |
147 | 317 int tmp; |
318 int line_num = 0; | |
319 int line_pos; /* line pos */ | |
320 int opt_pos; /* opt pos */ | |
321 int param_pos; /* param pos */ | |
322 int ret = 1; | |
1090 | 323 int errors = 0; |
147 | 324 |
325 #ifdef DEBUG | |
326 assert(conffile != NULL); | |
327 #endif | |
1089 | 328 if (++recursion_depth > 1) |
329 printf("Reading config file: %s", conffile); | |
330 | |
331 if (recursion_depth > MAX_RECURSION_DEPTH) { | |
332 printf(": too deep 'include'. check your configfiles\n"); | |
333 ret = -1; | |
334 goto out; | |
335 } | |
166 | 336 |
337 if (init_conf(conf, CONFIG_FILE) == -1) { | |
338 ret = -1; | |
339 goto out; | |
340 } | |
147 | 341 |
179 | 342 if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) { |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
343 printf("\ncan't get memory for 'line': %s", strerror(errno)); |
166 | 344 ret = -1; |
345 goto out; | |
147 | 346 } |
347 | |
348 if ((fp = fopen(conffile, "r")) == NULL) { | |
1089 | 349 if (recursion_depth > 1) |
350 printf(": %s\n", strerror(errno)); | |
147 | 351 free(line); |
166 | 352 ret = 0; |
353 goto out; | |
147 | 354 } |
1089 | 355 if (recursion_depth > 1) |
356 printf("\n"); | |
147 | 357 |
358 while (fgets(line, MAX_LINE_LEN, fp)) { | |
1090 | 359 if (errors >= 16) { |
360 printf("too many errors\n"); | |
361 goto out; | |
362 } | |
363 | |
147 | 364 line_num++; |
365 line_pos = 0; | |
366 | |
367 /* skip whitespaces */ | |
368 while (isspace(line[line_pos])) | |
369 ++line_pos; | |
370 | |
371 /* EOL / comment */ | |
372 if (line[line_pos] == '\0' || line[line_pos] == '#') | |
373 continue; | |
374 | |
480 | 375 /* read option. */ |
376 for (opt_pos = 0; isprint(line[line_pos]) && | |
377 line[line_pos] != ' ' && | |
378 line[line_pos] != '#' && | |
379 line[line_pos] != '='; /* NOTHING */) { | |
147 | 380 opt[opt_pos++] = line[line_pos++]; |
381 if (opt_pos >= MAX_OPT_LEN) { | |
382 PRINT_LINENUM; | |
383 printf("too long option\n"); | |
1090 | 384 errors++; |
147 | 385 ret = -1; |
1090 | 386 goto nextline; |
147 | 387 } |
388 } | |
389 if (opt_pos == 0) { | |
390 PRINT_LINENUM; | |
391 printf("parse error\n"); | |
392 ret = -1; | |
1090 | 393 errors++; |
147 | 394 continue; |
395 } | |
396 opt[opt_pos] = '\0'; | |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
397 |
147 | 398 #ifdef DEBUG |
399 PRINT_LINENUM; | |
400 printf("option: %s\n", opt); | |
401 #endif | |
402 | |
403 /* skip whitespaces */ | |
404 while (isspace(line[line_pos])) | |
405 ++line_pos; | |
406 | |
407 /* check '=' */ | |
408 if (line[line_pos++] != '=') { | |
409 PRINT_LINENUM; | |
410 printf("option without parameter\n"); | |
411 ret = -1; | |
1090 | 412 errors++; |
147 | 413 continue; |
414 } | |
415 | |
416 /* whitespaces... */ | |
417 while (isspace(line[line_pos])) | |
418 ++line_pos; | |
419 | |
420 /* read the parameter */ | |
167 | 421 if (line[line_pos] == '"' || line[line_pos] == '\'') { |
422 c = line[line_pos]; | |
423 ++line_pos; | |
424 for (param_pos = 0; line[line_pos] != c; /* NOTHING */) { | |
425 param[param_pos++] = line[line_pos++]; | |
426 if (param_pos >= MAX_PARAM_LEN) { | |
427 PRINT_LINENUM; | |
428 printf("too long parameter\n"); | |
429 ret = -1; | |
1090 | 430 errors++; |
431 goto nextline; | |
167 | 432 } |
433 } | |
434 line_pos++; /* skip the closing " or ' */ | |
435 } else { | |
436 for (param_pos = 0; isprint(line[line_pos]) && !isspace(line[line_pos]) | |
437 && line[line_pos] != '#'; /* NOTHING */) { | |
438 param[param_pos++] = line[line_pos++]; | |
439 if (param_pos >= MAX_PARAM_LEN) { | |
440 PRINT_LINENUM; | |
441 printf("too long parameter\n"); | |
442 ret = -1; | |
1090 | 443 errors++; |
444 goto nextline; | |
167 | 445 } |
147 | 446 } |
447 } | |
448 param[param_pos] = '\0'; | |
449 | |
450 /* did we read a parameter? */ | |
451 if (param_pos == 0) { | |
452 PRINT_LINENUM; | |
453 printf("option without parameter\n"); | |
454 ret = -1; | |
1090 | 455 errors++; |
147 | 456 continue; |
457 } | |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
458 |
147 | 459 #ifdef DEBUG |
460 PRINT_LINENUM; | |
461 printf("parameter: %s\n", param); | |
462 #endif | |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
463 |
147 | 464 /* now, check if we have some more chars on the line */ |
465 /* whitespace... */ | |
466 while (isspace(line[line_pos])) | |
467 ++line_pos; | |
468 | |
469 /* EOL / comment */ | |
470 if (line[line_pos] != '\0' && line[line_pos] != '#') { | |
471 PRINT_LINENUM; | |
472 printf("extra characters on line: %s\n", line+line_pos); | |
473 ret = -1; | |
474 } | |
475 | |
2619 | 476 tmp = read_option(config, nr_options, opt, param); |
147 | 477 switch (tmp) { |
478 case ERR_NOT_AN_OPTION: | |
479 case ERR_MISSING_PARAM: | |
480 case ERR_OUT_OF_RANGE: | |
150 | 481 case ERR_FUNC_ERR: |
482 PRINT_LINENUM; | |
160 | 483 printf("%s\n", opt); |
150 | 484 ret = -1; |
1090 | 485 errors++; |
150 | 486 continue; |
487 /* break */ | |
147 | 488 } |
1093 | 489 nextline: |
1304 | 490 ; |
147 | 491 } |
492 | |
493 free(line); | |
494 fclose(fp); | |
166 | 495 out: |
496 --recursion_depth; | |
147 | 497 return ret; |
498 } | |
499 | |
1629 | 500 int parse_command_line(struct config *conf, int argc, char **argv, char **envp, char ***filenames) |
147 | 501 { |
502 int i; | |
1629 | 503 char **f = NULL; |
504 int f_nr = 0; | |
147 | 505 int tmp; |
506 char *opt; | |
2615 | 507 int no_more_opts = 0; |
147 | 508 |
509 #ifdef DEBUG | |
510 assert(argv != NULL); | |
511 assert(envp != NULL); | |
512 assert(argc >= 1); | |
513 #endif | |
514 | |
515 if (init_conf(conf, COMMAND_LINE) == -1) | |
516 return -1; | |
517 | |
1089 | 518 /* in order to work recursion detection properly in parse_config_file */ |
519 ++recursion_depth; | |
520 | |
147 | 521 for (i = 1; i < argc; i++) { |
2615 | 522 next: |
147 | 523 opt = argv[i]; |
2650
bf7248edcc20
fixed commandline bug: handling '-' as option when '--' unused
alex
parents:
2624
diff
changeset
|
524 /* check for -- (no more options id.) except --help! */ |
2623 | 525 if ((*opt == '-') && (*(opt+1) == '-') && (*(opt+2) != 'h')) |
2615 | 526 { |
527 no_more_opts = 1; | |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
528 if (i+1 >= argc) |
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
529 { |
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
530 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "You added '--' but no filenames presented!\n"); |
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
531 goto err_out; |
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
532 } |
2615 | 533 i++; |
534 goto next; | |
535 } | |
536 | |
2650
bf7248edcc20
fixed commandline bug: handling '-' as option when '--' unused
alex
parents:
2624
diff
changeset
|
537 if ((no_more_opts == 0) && (*opt == '-') && (*(opt+1) != 0)) /* option */ |
2615 | 538 { |
539 /* remove trailing '-' */ | |
540 opt++; | |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
541 |
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
542 mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "this_opt = option: %s\n", opt); |
147 | 543 |
2619 | 544 tmp = read_option(config, nr_options, opt, argv[i + 1]); |
1629 | 545 |
2615 | 546 switch (tmp) { |
547 case ERR_NOT_AN_OPTION: | |
548 case ERR_MISSING_PARAM: | |
549 case ERR_OUT_OF_RANGE: | |
550 case ERR_FUNC_ERR: | |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
551 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Error %d while parsing option: '%s'!\n", |
2615 | 552 tmp, opt); |
160 | 553 goto err_out; |
2615 | 554 default: |
1075 | 555 i += tmp; |
2615 | 556 break; |
557 } | |
558 } | |
559 else /* filename */ | |
560 { | |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
561 mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "this_opt = filename: %s\n", opt); |
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
562 |
2615 | 563 /* opt is not an option -> treat it as a filename */ |
564 if (!(f = (char **) realloc(f, sizeof(*f) * (f_nr + 2)))) | |
565 goto err_out_mem; | |
566 | |
567 f[f_nr++] = argv[i]; | |
147 | 568 } |
1089 | 569 } |
2615 | 570 |
1629 | 571 if (f) |
572 f[f_nr] = NULL; | |
573 if (filenames) | |
574 *filenames = f; | |
1089 | 575 --recursion_depth; |
1629 | 576 return f_nr; //filenames_nr; |
577 err_out_mem: | |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
578 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "can't allocate memory for filenames (%s)\n", strerror(errno)); |
160 | 579 err_out: |
1089 | 580 --recursion_depth; |
2624
64844fccf623
partly upgraded to mp_msg and fixed minor bug in parse_command_line
alex
parents:
2623
diff
changeset
|
581 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "command line: %s\n", argv[i]); |
160 | 582 return -1; |
147 | 583 } |