/* * Copyright (c) 2010 Philippe Pepiot * Copyright (c) 2011 Martin Duquesnoy * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _BSD_SOURCE #define _BSD_SOURCE #endif #include #include #include #include "wmfs.h" #include "parse.h" #include "util.h" extern TAILQ_HEAD(, conf_sec) config; static const struct opt_type opt_type_null = { 0, 0, false, NULL }; static struct opt_type string_to_opt(char *s) { struct opt_type ret = opt_type_null; if(!s || !strlen(s)) return ret; ret.num = strtol(s, (char**)NULL, 10); ret.fnum = strtod(s, NULL); ret.boolean = (!strcmp(s, "true") || !strcmp(s, "True") || !strcmp(s, "TRUE") || !strcmp(s, "1")); ret.str = s; return ret; } void print_unused(struct conf_sec *sec) { struct conf_sec *s; struct conf_opt *o; if(!sec) { TAILQ_FOREACH(s, &config, entry) print_unused(s); return; } SLIST_FOREACH(o, &sec->optlist, entry) if(!o->used) warnxl("%s:%d, unused param %s", o->filename, o->line, o->name); TAILQ_FOREACH(s, &sec->sub, entry) if(!TAILQ_EMPTY(&s->sub)) print_unused(s); } struct conf_sec ** fetch_section(struct conf_sec *s, char *name) { struct conf_sec **ret; struct conf_sec *sec; size_t i = 0; if(!name) return NULL; if(!s) { ret = xcalloc(2, sizeof(struct conf_sec *)); TAILQ_FOREACH(sec, &config, entry) if(!strcmp(sec->name, name)) { ret[0] = sec; ret[1] = NULL; break; } } else { ret = xcalloc(s->nsub + 1, sizeof(struct conf_sec *)); TAILQ_FOREACH(sec, &s->sub, entry) if(!strcmp(sec->name, name) && i < s->nsub) ret[i++] = sec; ret[i] = NULL; } return ret; } struct conf_sec * fetch_section_first(struct conf_sec *s, char *name) { struct conf_sec *sec, *ret = NULL; TAILQ_HEAD(cshead, conf_sec) *head = (s ? (struct cshead*)&s->sub : (struct cshead*)&config); if(!name) return NULL; TAILQ_FOREACH(sec, head, entry) if(sec->name && !strcmp(sec->name, name)) { ret = sec; break; } return ret; } size_t fetch_section_count(struct conf_sec **s) { size_t ret = 0; while(s[ret]) ++ret; return ret; } struct opt_type * fetch_opt(struct conf_sec *s, char *dfl, char *name) { struct conf_opt *o; struct opt_type *ret; size_t i = 0; if(!name) return NULL; ret = xcalloc(10, sizeof(struct opt_type)); if(s) { SLIST_FOREACH(o, &s->optlist, entry) if(!strcmp(o->name, name)) { while(o->val[i]) { o->used = true; ret[i] = string_to_opt(o->val[i]); ++i; } ret[i] = opt_type_null; return ret; } } ret[0] = string_to_opt(dfl); ret[1] = opt_type_null; return ret; } struct opt_type fetch_opt_first(struct conf_sec *s, char *dfl, char *name) { struct conf_opt *o; if(!name) return opt_type_null; else if(s) { SLIST_FOREACH(o, &s->optlist, entry) if(!strcmp(o->name, name)) { o->used = true; return string_to_opt(o->val[0]); } } return string_to_opt(dfl); } size_t fetch_opt_count(struct opt_type *o) { size_t ret = 0; while(o[ret].str) ++ret; return ret; }