comparison cfgparser.c @ 147:0a0d7dd8fb51

new command line/config file parser
author szabii
date Sun, 18 Mar 2001 23:32:31 +0000
parents
children 2f3e01a1fd87
comparison
equal deleted inserted replaced
146:f3eb963d1370 147:0a0d7dd8fb51
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
17
18 #define COMMAND_LINE 0
19 #define CONFIG_FILE 1
20
21 #ifdef DEBUG
22 #include <assert.h>
23 #endif
24
25 #include "cfgparser.h"
26 #include "version.h"
27 #include "help_mp.h"
28
29 static struct config *config;
30 static int nr_options; /* number of options in 'conf' */
31 static int parser_mode; /* COMMAND_LINE or CONFIG_FILE */
32
33 static int init_conf(struct config *conf, int mode)
34 {
35 #ifdef DEBUG
36 assert(conf != NULL);
37 #endif
38
39 /* calculate the number of options in 'conf' */
40 for (nr_options = 0; conf[nr_options].name != NULL; nr_options++)
41 /* NOTHING */;
42
43 config = conf;
44 #ifdef DEBUG
45 if (mode != COMMAND_LINE && mode != CONFIG_FILE) {
46 printf("init_conf: wrong flag!\n");
47 return -1;
48 }
49 #endif
50 parser_mode = mode;
51 return 1;
52 }
53
54 static int read_option(char *opt, char *param)
55 {
56 int i;
57 int need_param = -1;
58 int tmp_int;
59 float tmp_float;
60
61 for (i = 0; i < nr_options; i++) {
62 if (!strcasecmp(opt, config[i].name))
63 break;
64 }
65 if (i == nr_options)
66 return ERR_NOT_AN_OPTION;
67
68 switch (config[i].type) {
69 case CONF_TYPE_FLAG:
70 /* flags need a parameter in config file */
71 if (parser_mode == CONFIG_FILE) {
72 if (!strcasecmp(param, "yes") || /* any other language? */
73 !strcasecmp(param, "ja") ||
74 !strcasecmp(param, "igen") ||
75 !strcasecmp(param, "y") ||
76 !strcasecmp(param, "i") ||
77 !strcmp(param, "1"))
78 *((int *) config[i].p) = config[i].max;
79 if (!strcasecmp(param, "no") ||
80 !strcasecmp(param, "nein") ||
81 !strcasecmp(param, "nicht") ||
82 !strcasecmp(param, "nem") ||
83 !strcasecmp(param, "n") ||
84 !strcmp(param, "0"))
85 *((int *) config[i].p) = config[i].min;
86 need_param = 1;
87 } else { /* parser_mode == COMMAND_LINE */
88 *((int *) config[i].p) = config[i].max;
89 need_param = 0;
90 }
91 break;
92 case CONF_TYPE_INT:
93 if (param == NULL)
94 return ERR_MISSING_PARAM;
95 if (!isdigit(*param))
96 return ERR_MISSING_PARAM;
97
98 tmp_int = atoi(param);
99
100 if (config[i].flags & CONF_CHK_MIN)
101 if (tmp_int < config[i].min)
102 return ERR_OUT_OF_RANGE;
103
104 if (config[i].flags & CONF_CHK_MAX)
105 if (tmp_int > config[i].max)
106 return ERR_OUT_OF_RANGE;
107
108 *((int *) config[i].p) = tmp_int;
109 need_param = 1;
110 break;
111 case CONF_TYPE_FLOAT:
112 if (param == NULL)
113 return ERR_MISSING_PARAM;
114 if (!isdigit(*param))
115 return ERR_MISSING_PARAM;
116
117 tmp_float = atof(param);
118
119 if (config[i].flags & CONF_CHK_MIN)
120 if (tmp_float < config[i].min)
121 return ERR_OUT_OF_RANGE;
122
123 if (config[i].flags & CONF_CHK_MAX)
124 if (tmp_float > config[i].max)
125 return ERR_OUT_OF_RANGE;
126
127 *((float *) config[i].p) = tmp_float;
128 need_param = 1;
129 break;
130 case CONF_TYPE_STRING:
131 if (param == NULL)
132 return ERR_MISSING_PARAM;
133
134 if (config[i].flags & CONF_CHK_MIN)
135 if (strlen(param) < config[i].min)
136 return ERR_OUT_OF_RANGE;
137
138 if (config[i].flags & CONF_CHK_MAX)
139 if (strlen(param) > config[i].max)
140 return ERR_OUT_OF_RANGE;
141
142 *((char **) config[i].p) = strdup(param);
143 need_param = 1;
144 break;
145 default:
146 printf("picsaba\n");
147 break;
148 }
149 return need_param;
150 }
151
152 int parse_config_file(struct config *conf, char *conffile)
153 {
154 #define PRINT_LINENUM printf("%s(%d): ", conffile, line_num)
155 #define MAX_LINE_LEN 1000
156 #define MAX_OPT_LEN 100
157 #define MAX_PARAM_LEN 100
158 FILE *fp;
159 char *line;
160 char opt[MAX_OPT_LEN];
161 char param[MAX_PARAM_LEN];
162 int tmp;
163 int line_num = 0;
164 int line_pos; /* line pos */
165 int opt_pos; /* opt pos */
166 int param_pos; /* param pos */
167 int ret = 1;
168
169 #ifdef DEBUG
170 assert(conffile != NULL);
171 #endif
172 printf("Reading config file: %s\n", conffile);
173
174 if (init_conf(conf, CONFIG_FILE) == -1)
175 return -1;
176
177 if ((line = (char *) malloc(MAX_LINE_LEN)) == NULL) {
178 perror("parse_config_file: can't get memory for 'line'");
179 return -1;
180 }
181
182 if ((fp = fopen(conffile, "r")) == NULL) {
183 perror("parse_config_file: can't open filename");
184 free(line);
185 return 0;
186 }
187
188 while (fgets(line, MAX_LINE_LEN, fp)) {
189 line_num++;
190 line_pos = 0;
191
192 /* skip whitespaces */
193 while (isspace(line[line_pos]))
194 ++line_pos;
195
196 /* EOL / comment */
197 if (line[line_pos] == '\0' || line[line_pos] == '#')
198 continue;
199
200 /* read option. accept char if isalnum(char) */
201 for (opt_pos = 0; isalnum(line[line_pos]); /* NOTHING */) {
202 opt[opt_pos++] = line[line_pos++];
203 if (opt_pos >= MAX_OPT_LEN) {
204 PRINT_LINENUM;
205 printf("too long option\n");
206 ret = -1;
207 continue;
208 }
209 }
210 if (opt_pos == 0) {
211 PRINT_LINENUM;
212 printf("parse error\n");
213 ret = -1;
214 continue;
215 }
216 opt[opt_pos] = '\0';
217 #ifdef DEBUG
218 PRINT_LINENUM;
219 printf("option: %s\n", opt);
220 #endif
221
222 /* skip whitespaces */
223 while (isspace(line[line_pos]))
224 ++line_pos;
225
226 /* check '=' */
227 if (line[line_pos++] != '=') {
228 PRINT_LINENUM;
229 printf("option without parameter\n");
230 ret = -1;
231 continue;
232 }
233
234 /* whitespaces... */
235 while (isspace(line[line_pos]))
236 ++line_pos;
237
238 /* read the parameter */
239 for (param_pos = 0; isalnum(line[line_pos]); /* NOTHING */) {
240 param[param_pos++] = line[line_pos++];
241 if (param_pos >= MAX_PARAM_LEN) {
242 PRINT_LINENUM;
243 printf("too long parameter\n");
244 ret = -1;
245 continue;
246 }
247 }
248 param[param_pos] = '\0';
249
250 /* did we read a parameter? */
251 if (param_pos == 0) {
252 PRINT_LINENUM;
253 printf("option without parameter\n");
254 ret = -1;
255 continue;
256 }
257 #ifdef DEBUG
258 PRINT_LINENUM;
259 printf("parameter: %s\n", param);
260 #endif
261 /* now, check if we have some more chars on the line */
262 /* whitespace... */
263 while (isspace(line[line_pos]))
264 ++line_pos;
265
266 /* EOL / comment */
267 if (line[line_pos] != '\0' && line[line_pos] != '#') {
268 PRINT_LINENUM;
269 printf("extra characters on line: %s\n", line+line_pos);
270 ret = -1;
271 }
272
273 tmp = read_option(opt, param);
274 switch (tmp) {
275 case ERR_NOT_AN_OPTION:
276 PRINT_LINENUM;
277 printf("invalid option: %s\n", opt);
278 ret = -1;
279 continue;
280 /* break; */
281 case ERR_MISSING_PARAM:
282 PRINT_LINENUM;
283 printf("missing parameter: %s\n", opt);
284 ret = -1;
285 continue;
286 /* break; */
287 case ERR_OUT_OF_RANGE:
288 PRINT_LINENUM;
289 printf("parameter of %s out of range\n", opt);
290 ret = -1;
291 continue;
292 /* break; */
293 }
294 }
295
296 free(line);
297 fclose(fp);
298 return ret;
299 }
300
301 int parse_command_line(struct config *conf, int argc, char **argv, char **envp, char **filename)
302 {
303 int i;
304 int found_filename = 0;
305 int tmp;
306 char *opt;
307
308 #ifdef DEBUG
309 assert(argv != NULL);
310 assert(envp != NULL);
311 assert(argc >= 1);
312 #endif
313
314 if (init_conf(conf, COMMAND_LINE) == -1)
315 return -1;
316
317 for (i = 1; i < argc; i++) {
318 opt = argv[i];
319 if (*opt != '-')
320 goto not_an_option;
321
322 /* remove trailing '-' */
323 opt++;
324
325 /* check for --help, -h, and --version */
326 if (!strcasecmp(opt, "-help") || !strcasecmp(opt, "h")) {
327 printf("%s%s", banner_text, help_text);
328 continue;
329 }
330 if (!strcasecmp(opt, "-version")) {
331 printf("%s", banner_text);
332 continue;
333 }
334
335 tmp = read_option(opt, argv[i + 1]);
336
337 switch (tmp) {
338 case ERR_NOT_AN_OPTION:
339 not_an_option:
340 /* opt is not an option -> treat it as a filename */
341 if (found_filename) {
342 /* we already have a filename */
343 printf("parse_command_line: invalid option: %s\n", argv[i]);
344 return -1;
345 } else {
346 found_filename = 1;
347 *filename = argv[i];
348 printf("parse_command_line: found filename: %s\n", *filename);
349 continue; /* next option */
350 }
351 break;
352 case ERR_MISSING_PARAM:
353 printf("parse_command_line: missing parameter: %s\n", argv[i]);
354 return -1;
355 /* break; */
356 case ERR_OUT_OF_RANGE:
357 printf("parse_command_line: parameter of '%s' is out of range\n", argv[i]);
358 return -1;
359 /* break; */
360 }
361
362 i += tmp; /* we already processed the params (if there was any) */
363 }
364 return found_filename;
365 }