Lumiera  0.pre.03
»edit your freedom«
config.c
Go to the documentation of this file.
1 /*
2  Config - Lumiera configuration system
3 
4  Copyright (C) Lumiera.org
5  2008, Christian Thaeter <ct@pipapo.org>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
23 
31 #include "include/logging.h"
32 #include "lib/safeclib.h"
33 #include "lib/tmpbuf.h"
34 #include "common/config.h"
35 
36 #include <stdint.h>
37 #include <stdlib.h>
38 #include <ctype.h>
39 
40 
41 LUMIERA_ERROR_DEFINE (CONFIG_SYNTAX, "syntax error in configfile");
42 LUMIERA_ERROR_DEFINE (CONFIG_SYNTAX_KEY, "syntax error in key");
43 LUMIERA_ERROR_DEFINE (CONFIG_SYNTAX_VALUE, "syntax error in value");
44 LUMIERA_ERROR_DEFINE (CONFIG_NO_ENTRY, "no configuration entry");
45 
46 
50 const char* lumiera_config_defaults[] =
51  {
52  /* Low level formating, don't change these */
53  "config.formatstr.link = '< %s'",
54  "config.formatstr.number.dec = '= %lld'",
55  "config.formatstr.number.hex = '= 0x%llX'",
56  "config.formatstr.number.oct = '= 0%llo'",
57  "config.formatstr.real = '= %Lg'",
58  "config.formatstr.real.dec = '= %Lf'",
59  "config.formatstr.real.sci = '= %Le'",
60  "config.formatstr.string = '= %s'",
61  "config.formatstr.string.dquoted = '= \"%s\"'",
62  "config.formatstr.string.quoted = '= ''%s'''",
63  "config.formatstr.word = '= %s'",
64  "config.formatstr.bool = '= %d'",
65 
66  /* default representations per type */
67  "config.formatdef.link < config.formatstr.link",
68  "config.formatdef.number < config.formatstr.number.dec",
69  "config.formatdef.real < config.formatstr.real",
70  "config.formatdef.string < config.formatstr.string",
71  "config.formatdef.word < config.formatstr.word",
72  "config.formatdef.bool < config.formatstr.bool",
73 
74  /* per key formatting override stored under */
75  "config.formatkey ='config.format.%s'",
76 
77  NULL
78  };
79 
80 
81 /* singleton config */
82 LumieraConfig lumiera_global_config = NULL;
83 
84 
85 int
86 lumiera_config_init (const char* path)
87 {
88  TRACE (config_dbg);
89  REQUIRE (!lumiera_global_config, "Configuration subsystem already initialised");
90  REQUIRE (path);
91 
92 
93  lumiera_global_config = lumiera_malloc (sizeof (*lumiera_global_config));
94  lumiera_config_lookup_init (&lumiera_global_config->keys);
95 
96  lumiera_configitem_init (&lumiera_global_config->defaults);
97  lumiera_configitem_init (&lumiera_global_config->files);
98  lumiera_configitem_init (&lumiera_global_config->TODO_unknown);
99 
100  lumiera_mutex_init (&lumiera_global_config->lock, "config mutex", &NOBUG_FLAG (mutex_dbg), NOBUG_CONTEXT);
101 
102  lumiera_config_setdefault (lumiera_tmpbuf_snprintf (SIZE_MAX, "config.path = %s", path));
103 
104  for (const char** itr = lumiera_config_defaults; *itr; ++itr)
105  {
107  }
108 
109  return 0;
110 }
111 
112 
113 void
115 {
116  TRACE (config_dbg);
117  if (lumiera_global_config)
118  {
119  lumiera_mutex_destroy (&lumiera_global_config->lock, &NOBUG_FLAG (mutex_dbg), NOBUG_CONTEXT);
120  lumiera_configitem_destroy (&lumiera_global_config->defaults, &lumiera_global_config->keys);
121  lumiera_configitem_destroy (&lumiera_global_config->files, &lumiera_global_config->keys);
122  lumiera_configitem_destroy (&lumiera_global_config->TODO_unknown, &lumiera_global_config->keys);
123  lumiera_config_lookup_destroy (&lumiera_global_config->keys);
124  lumiera_free (lumiera_global_config);
125  lumiera_global_config = NULL;
126  }
127  else
128  WARN (config_dbg, "Config system not initialised or already destroyed");
129 }
130 
131 
132 int
133 lumiera_config_load (const char* file)
134 {
135  (void) file;
136  TRACE (config_dbg);
137  UNIMPLEMENTED();
138  return -1;
139 }
140 
141 
142 int
143 lumiera_config_save ()
144 {
145  TRACE (config_dbg);
146  UNIMPLEMENTED();
147  return -1;
148 }
149 
150 
151 int
152 lumiera_config_purge (const char* filename)
153 {
154  (void) filename;
155  TRACE (config_dbg);
156 
157  UNIMPLEMENTED();
158  return -1;
159 }
160 
161 
162 const char*
163 lumiera_config_get (const char* key, const char** value)
164 {
165  TRACE (config_dbg);
166  REQUIRE (key);
167  REQUIRE (value);
168 
169  *value = NULL;
170 
171  /* we translate the key for the env var override by making it uppercase and replace . with _,
172  as side effect, this also checks the key syntax */
173  char* tr_key = lumiera_tmpbuf_tr (key,
174  LUMIERA_CONFIG_KEY_CHARS,
175  LUMIERA_CONFIG_ENV_CHARS,
176  NULL);
177 
178  if (tr_key)
179  {
180  char* env = lumiera_tmpbuf_snprintf (2048, "LUMIERA_%s", tr_key);
181 
182  *value = getenv (env);
183  if (*value)
184  {
185  NOTICE (config, "envvar override for config %s = %s", env, *value);
186  }
187  else
188  {
190  LumieraConfigitem item = lumiera_config_lookup_item_find (&lumiera_global_config->keys, key);
191 
192  if (item)
193  {
194  *value = item->delim+1;
195  }
196  else
197  LUMIERA_ERROR_SET_WARNING (config, CONFIG_NO_ENTRY, key);
198  }
199  }
200  else
201  {
202  LUMIERA_ERROR_SET (config, CONFIG_SYNTAX_KEY, key);
203  }
204 
205  return *value;
206 }
207 
208 
209 const char*
210 lumiera_config_get_default (const char* key, const char** value)
211 {
212  TRACE (config_dbg);
213  REQUIRE (key);
214  REQUIRE (value);
215 
216  *value = NULL;
217 
220  LumieraConfigitem item = lumiera_config_lookup_item_tail_find (&lumiera_global_config->keys, key);
221 
222  if (item && item->parent == &lumiera_global_config->defaults)
223  {
224  *value = item->delim+1;
225  }
226 
227  return *value;
228 }
229 
230 
231 LumieraConfigitem
232 lumiera_config_set (const char* key, const char* delim_value)
233 {
234  TRACE (config_dbg);
235 
236  LumieraConfigitem item = lumiera_config_lookup_item_find (&lumiera_global_config->keys, key);
237  if (item && item->parent != &lumiera_global_config->defaults)
238  {
239  TODO ("is a user writable file?");
240  TODO (" replace delim_value");
241  lumiera_configitem_set_value (item, delim_value);
242  }
243  else
244  {
245  TODO ("create item");
246  TODO (" find matching prefix");
247  TODO (" find matching suffix");
248  TODO (" find proper prefix indentation, else use config.indent");
249  TODO (" create configitem with prefix/suffix removed");
250 
251  char* line = lumiera_tmpbuf_snprintf (SIZE_MAX, "%s %s", key, delim_value);
252  item = lumiera_configitem_new (line);
253 
254  if (item)
255  {
256  TODO ("next 2 ensure must generate runtime errors");
257  ENSURE (item->delim, "syntax error");
258  ENSURE (*item->delim == '=' || *item->delim == '<', "syntax error,");
259 
260  TODO ("insert in proper parent (file)");
261  llist_insert_tail (&lumiera_global_config->TODO_unknown.children, &item->link);
262  item->parent = &lumiera_global_config->TODO_unknown;
263  lumiera_config_lookup_insert (&lumiera_global_config->keys, item);
264 
265  TODO ("tag file as dirty");
266  }
267  }
268 
269  return item;
270 }
271 
272 
273 LumieraConfigitem
274 lumiera_config_setdefault (const char* line)
275 {
276  TRACE (config_dbg);
277  REQUIRE (line);
278 
279  LumieraConfigitem item = NULL;
280 
281  LUMIERA_MUTEX_SECTION (mutex_sync, &lumiera_global_config->lock)
282  {
283  const char* key = line;
284  while (*key && isspace (*key))
285  key++;
286 
287  key = lumiera_tmpbuf_strndup (line, strspn (line, LUMIERA_CONFIG_KEY_CHARS));
288 
289  if (!(item = lumiera_config_lookup_item_find (&lumiera_global_config->keys, key)) || item->parent != &lumiera_global_config->defaults)
290  {
291  item = lumiera_configitem_new (line);
292 
293  if (item)
294  {
295  ENSURE (item->delim, "default must be a configentry with key=value or key<delegate syntax");
296  ENSURE (*item->delim == '=' || *item->delim == '<', "default must be a configentry with key=value or key<delegate syntax");
297  TRACE (config_dbg, "registering default: '%s'", item->line);
298 
299  llist_insert_head (&lumiera_global_config->defaults.children, &item->link);
300  item->parent = &lumiera_global_config->defaults;
301 
302  lumiera_config_lookup_insert (&lumiera_global_config->keys, item);
303  }
304  }
305  }
306 
307  return item;
308 }
309 
310 
311 void
313 {
314  fprintf (out, "# registered defaults:\n");
315 
316  LLIST_FOREACH (&lumiera_global_config->defaults.children, node)
317  fprintf (out, "%s\n", ((LumieraConfigitem) node)->line);
318 
319  fprintf (out, "# end of defaults\n\n");
320 
321 #if 0 /*TODO UNIMPLEMENTED */
322  fprintf (out, "# files:\n");
323  lumiera_configitem files;
324  fprintf (out, "# volatiles:")
325  lumiera_configitem TODO_unknown;
326 #endif
327 }
328 
329 
330 int
331 lumiera_config_reset (const char* key)
332 {
333  (void) key;
334  TRACE (config_dbg);
335  UNIMPLEMENTED();
336  return -1;
337 }
338 
339 
340 int
341 lumiera_config_info (const char* key, const char** filename, unsigned* line)
342 {
343  (void) key;
344  (void) filename;
345  (void) line;
346  TRACE (config_dbg);
347  UNIMPLEMENTED();
348  return -1;
349 }
350 
351 /*
352 // Local Variables:
353 // mode: C
354 // c-file-style: "gnu"
355 // indent-tabs-mode: nil
356 // End:
357 */
Portable and safe wrappers around some C-Lib functions.
LumieraConfigLookupentry lumiera_config_lookup_insert(LumieraConfigLookup self, LumieraConfigitem item)
Add a config item to a lookup structure.
Definition: config-lookup.c:78
#define LUMIERA_ERROR_SET(flag, err, extra)
Helper macro to raise an error for the current thread.
Definition: error.h:91
LumieraConfigitem lumiera_config_lookup_item_find(LumieraConfigLookup self, const char *key)
Find a the topmost config item stored to a given key.
#define LUMIERA_ERROR_SET_WARNING(flag, err, extra)
Helper macro to raise an error for the current thread.
Definition: error.h:136
char * lumiera_tmpbuf_strndup(const char *src, size_t size)
Duplicate string to a tmpbuf.
Definition: tmpbuf.c:111
const char * lumiera_config_defaults[]
defaults for the configuration system itself
Definition: config.c:50
Interface for a lumiera configuration system (draft).
#define LUMIERA_MUTEX_SECTION(nobugflag, mtx)
Mutual exclusive section.
Definition: mutex.h:41
LumieraConfigitem lumiera_config_lookup_item_tail_find(LumieraConfigLookup self, const char *key)
Find a the bottom most config item stored to a given key.
This header is for including and configuring NoBug.
Round robin temporary buffers.
static void lumiera_free(void *mem)
Free previously allocated memory.
Definition: safeclib.h:82
LumieraConfigitem lumiera_config_setdefault(const char *line)
Installs a default value for a config key.
Definition: config.c:274
void * lumiera_malloc(size_t size)
Allocate memory.
Definition: safeclib.c:122
char * lumiera_tmpbuf_tr(const char *in, const char *from, const char *to, const char *def)
Translates characters in a string, similar to the shell &#39;tr&#39; utility.
Definition: tmpbuf.c:156
void lumiera_config_destroy()
Destroys the configuration subsystem.
Definition: config.c:114
void lumiera_config_dump(FILE *out)
Does a diagnostic dump of the whole config database.
Definition: config.c:312
#define LLIST_FOREACH(list, node)
Iterate forward over a list.
Definition: llist.h:129
LumieraConfigLookup lumiera_config_lookup_destroy(LumieraConfigLookup self)
Destroy a lookup structure.
Definition: config-lookup.c:68
LumieraMutex lumiera_mutex_init(LumieraMutex self, const char *purpose, struct nobug_flag *flag, const struct nobug_context ctx)
Initialise a mutex variable This initialises a &#39;fast&#39; default mutex which must not be locked recursiv...
Definition: mutex.c:30
LumieraConfigLookup lumiera_config_lookup_init(LumieraConfigLookup self)
Initialise a lookup structure.
Definition: config-lookup.c:59
LumieraConfigitem lumiera_config_set(const char *key, const char *delim_value)
Definition: config.c:232
int lumiera_config_init(const char *path)
Initialise the configuration subsystem.
Definition: config.c:86
LumieraMutex lumiera_mutex_destroy(LumieraMutex self, struct nobug_flag *flag, const struct nobug_context ctx)
Destroy a mutex variable.
Definition: mutex.c:48
#define LUMIERA_ERROR_DEFINE(err, msg)
Definition and initialisation of an error constant.
Definition: error.h:80
char * lumiera_tmpbuf_snprintf(size_t size, const char *fmt,...)
Construct a string in a tmpbuf.
Definition: tmpbuf.c:125