1 /* Skippy - Seduces Kids Into Perversion
3 * Copyright (C) 2004 Hyriand <hyriand@thegraveyard.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 char *section, *key, *value;
28 copy_match(const char *line, regmatch_t *match)
31 r = (char *)malloc(match->rm_eo + 1);
32 strncpy(r, line + match->rm_so, match->rm_eo - match->rm_so);
33 r[match->rm_eo - match->rm_so] = 0;
38 entry_new(const char *section, char *key, char *value)
40 ConfigEntry *e = (ConfigEntry *)malloc(sizeof(ConfigEntry));
41 e->section = strdup(section);
48 entry_set(dlist *config, const char *section, char *key, char *value)
50 dlist *iter = dlist_first(config);
52 for(; iter; iter = iter->next)
54 entry = (ConfigEntry *)iter->data;
55 if(! strcasecmp(entry->section, section) && ! strcasecmp(entry->key, key)) {
62 entry = entry_new(section, key, value);
63 return dlist_add(config, entry);
67 config_parse(char *config)
69 regex_t re_section, re_empty, re_entry;
70 regmatch_t matches[5];
71 char line[8192], *section = 0;
73 dlist *new_config = 0;
75 regcomp(&re_section, "^[[:space:]]*\\[[[:space:]]*([[:alnum:]]*?)[[:space:]]*\\][[:space:]]*$", REG_EXTENDED);
76 regcomp(&re_empty, "^[[:space:]]*#|^[[:space:]]*$", REG_EXTENDED);
77 regcomp(&re_entry, "^[[:space:]]*([[:alnum:]]+)[[:space:]]*=[[:space:]]*(.*?)[[:space:]]*$", REG_EXTENDED);
81 if((config[ix] == '\0' || config[ix] == '\n'))
84 if(regexec(&re_empty, line, 5, matches, 0) == 0) {
86 } else if(regexec(&re_section, line, 5, matches, 0) == 0) {
89 section = copy_match(line, &matches[1]);
90 } else if(section && regexec(&re_entry, line, 5, matches, 0) == 0) {
91 char *key = copy_match(line, &matches[1]),
92 *value = copy_match(line, &matches[2]);
93 new_config = entry_set(new_config, section, key, value);
95 fprintf(stderr, "WARNING: Ignoring invalid line: %s\n", line);
99 line[l_ix] = config[ix];
110 regfree(&re_section);
118 config_load(const char *path)
120 FILE *fin = fopen(path, "r");
127 fprintf(stderr, "WARNING: Couldn't load config file '%s'.\n", path);
131 fseek(fin, 0, SEEK_END);
136 fprintf(stderr, "WARNING: '%s' is empty.\n", path);
141 fseek(fin, 0, SEEK_SET);
143 data = (char *)malloc(flen + 1);
144 if(fread(data, 1, flen, fin) != flen)
146 fprintf(stderr, "WARNING: Couldn't read from config file '%s'.\n", path);
154 config = config_parse(data);
162 entry_free(ConfigEntry *entry)
164 free(entry->section);
171 config_free(dlist *config)
173 dlist_free_with_func(config, (dlist_free_func)entry_free);
177 entry_find_func(dlist *l, ConfigEntry *key)
179 ConfigEntry *entry = (ConfigEntry*)l->data;
180 return ! (strcasecmp(entry->section, key->section) || strcasecmp(entry->key, key->key));
184 config_get(dlist *config, const char *section, const char *key, const char *def)
189 needle.section = (char *)section;
190 needle.key = (char *)key;
192 iter = dlist_find(dlist_first(config), (dlist_match_func)entry_find_func, &needle);
197 return ((ConfigEntry*)iter->data)->value;