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