5 #if defined(WIN32) || defined(__WIN32__)
13 struct optcfg_option *optlist;
15 optcfg_opt_callback opt_func;
17 optcfg_arg_callback arg_func;
22 /* argument parsing state */
27 /* config file parsing state */
28 const char *cfg_fname;
33 static int get_opt(struct optcfg *oc, const char *s, int *disable_opt);
34 static char *skip_spaces(char *s);
35 static void strip_comments(char *s);
36 static void strip_trailing_spaces(char *s);
37 static char *parse_keyval(char *line);
40 struct optcfg *optcfg_init(struct optcfg_option *optv)
44 if(!(oc = calloc(1, sizeof *oc))) {
52 void optcfg_destroy(struct optcfg *oc)
54 memset(oc, 0, sizeof *oc);
58 void optcfg_set_opt_callback(struct optcfg *oc, optcfg_opt_callback func, void *cls)
64 void optcfg_set_arg_callback(struct optcfg *oc, optcfg_arg_callback func, void *cls)
70 void optcfg_set_error_action(struct optcfg *oc, int act)
72 if(act == OPTCFG_ERROR_FAIL) {
74 } else if(act == OPTCFG_ERROR_IGNORE) {
79 int optcfg_parse_args(struct optcfg *oc, int argc, char **argv)
85 for(i=1; i<argc; i++) {
88 if(argv[i][0] == '-') {
90 int o = get_opt(oc, argv[i], &oc->disable_opt);
91 if(o == -1 || oc->opt_func(oc, o, oc->opt_cls) == -1) {
93 fprintf(stderr, "unexpected option: %s\n", argv[i]);
98 fprintf(stderr, "unexpected option: %s\n", argv[i]);
105 if(oc->arg_func(oc, argv[i], oc->arg_cls) == -1) {
107 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
112 fprintf(stderr, "unexpected argument: %s\n", argv[i]);
122 oc->argidx = 0; /* done parsing args */
126 int optcfg_parse_config_file(struct optcfg *oc, const char *fname)
129 FILE *fp = fopen(fname, "rb");
134 oc->cfg_fname = fname;
135 res = optcfg_parse_config_stream(oc, fp);
141 int optcfg_parse_config_stream(struct optcfg *oc, FILE *fp)
146 while(fgets(buf, sizeof buf, fp)) {
149 if(optcfg_parse_config_line(oc, buf) == -1) {
158 int optcfg_parse_config_line(struct optcfg *oc, const char *line)
161 char *start, *val, *buf;
164 buf = alloca(len + 1);
165 memcpy(buf, line, len + 1);
167 start = skip_spaces(buf);
168 strip_comments(start);
169 strip_trailing_spaces(start);
174 if(!(val = parse_keyval(start))) {
175 fprintf(stderr, "error parsing %s line %d: invalid syntax\n", oc->cfg_fname ? oc->cfg_fname : "", oc->cfg_nline);
179 if((opt = get_opt(oc, start, 0)) == -1) {
180 fprintf(stderr, "error parsing %s line %d: unknown option: %s\n", oc->cfg_fname ? oc->cfg_fname : "",
181 oc->cfg_nline, start);
186 if(oc->opt_func(oc, opt, oc->opt_cls) == -1) {
194 int optcfg_enabled_value(struct optcfg *oc, int *enabledp)
197 *enabledp = ~oc->disable_opt & 1;
199 char *val = optcfg_next_value(oc);
200 if(optcfg_bool_value(val, enabledp) == -1) {
208 char *optcfg_next_value(struct optcfg *oc)
210 if(oc->argidx) { /* we're in the middle of parsing arguments, so get the next one */
211 return oc->argv[++oc->argidx];
214 char *val = oc->cfg_value;
221 void optcfg_print_options(struct optcfg *oc)
224 for(i=0; oc->optlist[i].opt != -1; i++) {
225 struct optcfg_option *opt = oc->optlist + i;
228 printf(" -%c", opt->c);
233 printf("%c-%s: ", opt->c ? ',' : ' ', opt->s);
237 printf("%s\n", opt->desc ? opt->desc : "undocumented");
242 #define strcasecmp stricmp
245 int optcfg_bool_value(char *s, int *valret)
247 if(strcasecmp(s, "yes") == 0 || strcasecmp(s, "true") == 0 || strcmp(s, "1") == 0) {
251 if(strcasecmp(s, "no") == 0 || strcasecmp(s, "false") == 0 || strcmp(s, "0") == 0) {
258 int optcfg_int_value(char *str, int *valret)
261 *valret = strtol(str, &endp, 0);
268 int optcfg_float_value(char *str, float *valret)
271 *valret = strtod(str, &endp);
280 static int get_opt(struct optcfg *oc, const char *arg, int *disable_opt)
284 while(*arg && *arg == '-') {
295 if(ndashes && (strstr(arg, "no-") == arg || strstr(arg, "disable-") == arg)) {
297 arg = strchr(arg, '-') + 1; /* guaranteed to exist at this point */
303 if(arg[1]) { /* match long options */
304 for(i=0; oc->optlist[i].opt != -1; i++) {
305 if(strcmp(arg, oc->optlist[i].s) == 0) {
310 for(i=0; oc->optlist[i].opt != -1; i++) {
311 if(arg[0] == oc->optlist[i].c) {
319 static char *skip_spaces(char *s)
321 while(*s && isspace(*s)) ++s;
325 static void strip_comments(char *s)
327 while(*s && *s != '#') ++s;
328 if(*s == '#') *s = 0;
331 static void strip_trailing_spaces(char *s)
333 char *end = s + strlen(s) - 1;
334 while(end >= s && isspace(*end)) {
339 static char *parse_keyval(char *line)
342 char *eq = strchr(line, '=');
346 strip_trailing_spaces(line);
347 val = skip_spaces(eq + 1);
348 strip_trailing_spaces(val);
350 if(!*line || !*val) {