DLLIMPORT cfg_t *cfg_init(cfg_opt_t *opts, cfg_flag_t flags) { cfg_t *cfg; cfg = (cfg_t *)malloc(sizeof(cfg_t)); assert(cfg); memset(cfg, 0, sizeof(cfg_t)); cfg->name = strdup("root"); cfg->opts = cfg_dupopt_array(opts); cfg->flags = flags; cfg->filename = 0; cfg->line = 0; cfg->errfunc = 0; cfg_init_defaults(cfg); #if defined(ENABLE_NLS) && defined(HAVE_GETTEXT) setlocale(LC_MESSAGES, ""); setlocale(LC_CTYPE, ""); bindtextdomain(PACKAGE, LOCALEDIR); #endif return cfg; }
static cfg_opt_t *cfg_dupopt_array(cfg_opt_t *opts) { int i; cfg_opt_t *dupopts; int n = cfg_numopts(opts); dupopts = calloc(n + 1, sizeof(cfg_opt_t)); memcpy(dupopts, opts, n * sizeof(cfg_opt_t)); for (i = 0; i < n; i++) { dupopts[i].name = strdup(opts[i].name); if (opts[i].type == CFGT_SEC && opts[i].subopts) dupopts[i].subopts = cfg_dupopt_array(opts[i].subopts); if (is_set(CFGF_LIST, opts[i].flags) || opts[i].type == CFGT_FUNC) dupopts[i].def.parsed = opts[i].def.parsed ? strdup(opts[i].def.parsed) : 0; else if (opts[i].type == CFGT_STR) dupopts[i].def.string = opts[i].def.string ? strdup(opts[i].def.string) : 0; } return dupopts; }
static cfg_value_t *cfg_setopt(cfg_t *cfg, cfg_opt_t *opt, char *value) { cfg_value_t *val = 0; int b; char *s; double f; long int i; void *p; char *endptr; assert(cfg && opt); if(opt->simple_value) { assert(opt->type != CFGT_SEC); val = (cfg_value_t *)opt->simple_value; } else { if(is_set(CFGF_RESET, opt->flags)) { cfg_free_value(opt); opt->flags &= ~CFGF_RESET; } if(opt->nvalues == 0 || is_set(CFGF_MULTI, opt->flags) || is_set(CFGF_LIST, opt->flags)) { val = 0; if(opt->type == CFGT_SEC && is_set(CFGF_TITLE, opt->flags)) { unsigned int i; /* check if there already is a section with the same title */ assert(value); for(i = 0; i < opt->nvalues; i++) { cfg_t *sec = opt->values[i]->section; if(is_set(CFGF_NOCASE, cfg->flags)) { if(strcasecmp(value, sec->title) == 0) val = opt->values[i]; } else { if(strcmp(value, sec->title) == 0) val = opt->values[i]; } } } if(val == 0) val = cfg_addval(opt); } else val = opt->values[0]; } switch(opt->type) { case CFGT_INT: if(opt->parsecb) { if((*opt->parsecb)(cfg, opt, value, &i) != 0) return 0; val->number = i; } else { val->number = strtol(value, &endptr, 0); if(*endptr != '\0') { cfg_error(cfg, _("invalid integer value for option '%s'"), opt->name); return 0; } if(errno == ERANGE) { cfg_error(cfg, _("integer value for option '%s' is out of range"), opt->name); return 0; } } break; case CFGT_FLOAT: if(opt->parsecb) { if((*opt->parsecb)(cfg, opt, value, &f) != 0) return 0; val->fpnumber = f; } else { val->fpnumber = strtod(value, &endptr); if(*endptr != '\0') { cfg_error(cfg, _("invalid floating point value for option '%s'"), opt->name); return 0; } if(errno == ERANGE) { cfg_error(cfg, _("floating point value for option '%s' is out of range"), opt->name); return 0; } } break; case CFGT_STR: free(val->string); if(opt->parsecb) { s = 0; if((*opt->parsecb)(cfg, opt, value, &s) != 0) return 0; val->string = strdup(s); } else val->string = strdup(value); break; case CFGT_SEC: if(is_set(CFGF_MULTI, opt->flags) || val->section == 0) { cfg_free(val->section); val->section = (cfg_t *)malloc(sizeof(cfg_t)); assert(val->section); memset(val->section, 0, sizeof(cfg_t)); val->section->name = strdup(opt->name); val->section->opts = cfg_dupopt_array(opt->subopts); val->section->flags = cfg->flags; val->section->filename = cfg->filename ? strdup(cfg->filename) : 0; val->section->line = cfg->line; val->section->errfunc = cfg->errfunc; val->section->title = value; } if(!is_set(CFGF_DEFINIT, opt->flags)) cfg_init_defaults(val->section); break; case CFGT_BOOL: if(opt->parsecb) { if((*opt->parsecb)(cfg, opt, value, &b) != 0) return 0; } else { b = cfg_parse_boolean(value); if(b == -1) { cfg_error(cfg, _("invalid boolean value for option '%s'"), opt->name); return 0; } } val->boolean = (cfg_bool_t)b; break; case CFGT_PTR: assert(opt->parsecb); if((*opt->parsecb)(cfg, opt, value, &p) != 0) return 0; val->ptr = p; break; default: cfg_error(cfg, "internal error in cfg_setopt(%s, %s)", opt->name, value); assert(0); break; } return val; }