Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
configitem.c
Go to the documentation of this file.
1/*
2 Configitem - generalised hierarchy of configuration items
3
4 Copyright (C)
5 2008, Christian Thaeter <ct@pipapo.org>
6 Simeon Voelkel <simeon_voelkel@arcor.de>
7
8  **Lumiera** is free software; you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published by the
10  Free Software Foundation; either version 2 of the License, or (at your
11  option) any later version. See the file COPYING for further details.
12*/
13
14
23#include "include/logging.h"
24#include "lib/llist.h"
25#include "lib/safeclib.h"
26#include "lib/tmpbuf.h"
27
28#include "common/config.h"
29#include "common/configitem.h"
30#include "common/configentry.h"
31
32#include <ctype.h>
33#include <stdint.h>
34
35
37
39
41
42
43
44
45
48{
49 TRACE (configitem_dbg);
50 REQUIRE (self);
51
52 llist_init (&self->link);
53 self->parent = NULL;
54 llist_init (&self->children);
55
56 llist_init (&self->lookup);
57
58 self->line = NULL;
59
60 self->key = NULL;
61 self->key_size = 0;
62 self->delim = NULL;
63 self->vtable = NULL;
64
65 return self;
66}
67
68
71{
72 TRACE (configitem_dbg);
73
74 if (self)
75 {
76 LLIST_WHILE_HEAD (&self->children, node)
78
79 ENSURE (llist_is_empty (&self->children), "destructor didn't remove children");
80
81 if (self->vtable && self->vtable->destroy)
82 self->vtable->destroy (self);
83
84 if (!llist_is_empty (&self->lookup))
85 lumiera_config_lookup_remove (lookup, self);
86
87 llist_unlink (&self->link);
88 lumiera_free (self->line);
89 }
90
91 return self;
92}
93
94
96lumiera_configitem_new (const char* line)
97{
98 TRACE (configitem_dbg, "%s", line);
99
100 lumiera_configitem tmp;
102
103 lumiera_configitem_parse (&tmp, line);
104
105 LumieraConfigitem self = tmp.vtable && tmp.vtable->newitem
106 ? tmp.vtable->newitem (&tmp)
107 : lumiera_configitem_move (lumiera_malloc (sizeof (*self)), &tmp);
108
109 return self;
110}
111
112
113void
115{
116 TRACE (configitem_dbg);
118}
119
120
122lumiera_configitem_set_value (LumieraConfigitem self, const char* delim_value)
123{
124 REQUIRE (self->key);
125 REQUIRE (self->delim);
126
127 char* line = lumiera_tmpbuf_snprintf (SIZE_MAX, "%.*s%s", self->delim - self->line, self->line, delim_value);
128 lumiera_configitem_parse (self, line);
129
130 return self;
131}
132
133
136{
137 TRACE (configitem_dbg);
138 REQUIRE (self);
139 REQUIRE (source);
140
141 llist_init (&self->link);
142 llist_insertlist_next (&self->link, &source->link);
143
144 self->parent = source->parent;
145
146 llist_init (&self->children);
147 llist_insertlist_next (&self->children, &source->children);
148
149 llist_init (&self->lookup);
150 llist_insertlist_next (&self->lookup, &source->lookup);
151
152 self->line = source->line;
153 source->line = NULL;
154
155 self->key = source->key;
156 self->key_size = source->key_size;
157 self->delim = source->delim;
158 self->vtable = source->vtable;
159
160 return self;
161}
162
163
166{
167 TRACE (configitem_dbg);
168
169 lumiera_free (self->line);
170 self->line = lumiera_strndup (line, SIZE_MAX);
171
173
174 char* itr = self->line;
175
176 /* skip leading whitespace */
177 while (*itr && isspace (*itr))
178 itr++;
179
180 /* decide what this line represents */
181 if (!*itr || *itr == '#' )
182 {
183 /* this is an empty line or a a comment */
184 }
185 else if (*itr == '@' )
186 {
187 /* this is a directive */
188 self = parse_directive (self, itr);
189 }
190 else if (*itr == '[' )
191 {
192 /* this is a section */
193 self = parse_section (self, itr);
194 }
195 else
196 {
197 /* this is probably a configentry */
198 self = parse_configentry (self, itr);
199 }
200
201 return self;
202}
203
204
207{
208 /* itr points now to @ */
209 self->key = itr;
210
211 /* check whether there are illegal whitespace after @ */
212 itr++;
213 if (*itr && !isspace(*itr))
214 {
215 /* now look for the end of the directive and set the keysize */
216 self->key_size = strspn (itr, LUMIERA_CONFIG_KEY_CHARS);
217
218 itr += self->key_size;
219
220 /* we need a key with a length greater than zero and */
221 /* either end of line or whitespace after key */
222
223 if ( self->key_size && ( !*itr || (*itr && isspace(*itr)) ))
224 {
225 /* look for given arguments */
226
227 /* skip blanks */
228 while (*itr && isspace (*itr))
229 itr++;
230
231 if (*itr)
232 {
233 /* there are arguments given, thus set delim */
234 self->delim = itr - 1;
235 }
236 else
237 {
238 /* no arguments were given */
239 self->delim = NULL;
240 }
241 }
242 else
243 {
244 /* malformed lines shall be treated like if they were comments */
245 self->key = NULL;
246 self->key_size = 0;
247
248 LUMIERA_ERROR_SET (config, CONFIG_SYNTAX, self->line);
249 }
250 }
251 else
252 {
253 /* there occurred already an error right after the @! */
254 /* malformed lines shall be treated like if they were comments */
255 self->key = NULL;
256 self->key_size = 0;
257
258 LUMIERA_ERROR_SET (config, CONFIG_SYNTAX, self->line);
259 }
260 return self;
261}
262
263
266{
267 /* skip blanks before prefix */
268 itr++;
269 while (*itr && isspace(*itr))
270 itr++;
271
272 /* itr points now to the begin of the key */
273 self->key = itr;
274
275 /* now look for the end of the key and set the keysize */
276 self->key_size = strspn (itr, LUMIERA_CONFIG_KEY_CHARS);
277
278 itr += self->key_size;
279
280 /* if the line ends ends with prefix] delim points to ] */
281 /* and not the last (blank) character before the final square bracket */
282 if (self->key_size && *itr && *itr == ']')
283 {
284 self->delim = itr;
285 TODO("self->vtable = &lumiera_configsection_funcs;");
286 }
287 else if (self->key_size && *itr && isspace(*itr))
288 {
289 /* skip blanks until we reach the suffix or the final square bracket */
290 while (*itr && isspace(*itr))
291 itr++;
292
293 if (*itr && *itr == ']')
294 {
295 /* final square bracket reached, so place delim one char before the */
296 /* actual position which must be a whitespace: no extra check necessary */
297 self->delim = itr - 1;
298 TODO("self->vtable = &lumiera_configsection_funcs;");
299 }
300 else if (*itr)
301 {
302 TODO("check wheter suffix is made of legal characters");
303
304 /* delim points to the last whitespace before the actual position; */
305 /* no extra check needed */
306 self->delim = itr - 1;
307 TODO("self->vtable = &lumiera_configsection_funcs;");
308 }
309 else
310 {
311 /* malformed section line, treat this line like a comment */
312 self->key = NULL;
313 self->key_size = 0;
314
315 LUMIERA_ERROR_SET (config, CONFIG_SYNTAX, self->line);
316 }
317 }
318 else
319 {
320 /* error: either *itr is false, points neither to a blank nor to a closed square */
321 /* bracket or the key_size is zero */
322
323 /* treat this line like a comment */
324 self->key = NULL;
325 self->key_size = 0;
326
327 LUMIERA_ERROR_SET (config, CONFIG_SYNTAX, self->line);
328 }
329
330 return self;
331}
332
333
336{
337 /* itr points now to the first not-whitespace-character */
338 self->key = itr;
339
340 /* now look for the end of the key and set the keysize */
341 self->key_size = strspn (itr, LUMIERA_CONFIG_KEY_CHARS);
342
343 /* skip blanks */
344 itr += self->key_size;
345 while (*itr && isspace (*itr))
346 itr++;
347
348 if (self->key_size && *itr == '=')
349 {
350 /* this configentry assigns a value to a key */
351 self->delim = itr;
352 self->vtable = &lumiera_configentry_funcs;
353 }
354 else if (self->key_size && *itr == '<')
355 {
356 /* this configentry is a redirect */
357 self->delim = itr;
358 self->vtable = &lumiera_configentry_funcs;
359 }
360 else
361 {
362 /* this is not a valid configentry; treat this line like a comment */
363 self->key = NULL;
364 self->key_size = 0;
365
366 LUMIERA_ERROR_SET (config, CONFIG_SYNTAX, self->line);
367 }
368
369 return self;
370}
371
372
373/*
374// Local Variables:
375// mode: C
376// c-file-style: "gnu"
377// indent-tabs-mode: nil
378// End:
379*/
LumieraConfigitem lumiera_config_lookup_remove(LumieraConfigLookup self, LumieraConfigitem item)
Remove a config item from a lookup structure.
lumiera_config_lookup * LumieraConfigLookup
Interface for a lumiera configuration system (draft).
#define LUMIERA_CONFIG_KEY_CHARS
Definition config.h:50
struct lumiera_configitem_vtable lumiera_configentry_funcs
Definition configentry.c:47
Draft for a configuration system (2008).
LumieraConfigitem lumiera_configitem_set_value(LumieraConfigitem self, const char *delim_value)
Definition configitem.c:122
LumieraConfigitem lumiera_configitem_new(const char *line)
Definition configitem.c:96
void lumiera_configitem_delete(LumieraConfigitem self, LumieraConfigLookup lookup)
Definition configitem.c:114
LumieraConfigitem lumiera_configitem_parse(LumieraConfigitem self, const char *line)
Definition configitem.c:165
LumieraConfigitem lumiera_configitem_destroy(LumieraConfigitem self, LumieraConfigLookup lookup)
Definition configitem.c:70
LumieraConfigitem lumiera_configitem_init(LumieraConfigitem self)
Definition configitem.c:47
LumieraConfigitem lumiera_configitem_move(LumieraConfigitem self, LumieraConfigitem source)
Definition configitem.c:135
static LumieraConfigitem parse_directive(LumieraConfigitem self, char *itr)
Definition configitem.c:206
static LumieraConfigitem parse_configentry(LumieraConfigitem self, char *itr)
Definition configitem.c:335
static LumieraConfigitem parse_section(LumieraConfigitem self, char *itr)
Definition configitem.c:265
Draft for a configuration system (2008).
lumiera_configitem * LumieraConfigitem
Definition configitem.h:53
#define LUMIERA_ERROR_SET(flag, err, extra)
Helper macro to raise an error for the current thread.
Definition error.h:82
Intrusive cyclic double linked list There is only one node type which contains a forward and a backwa...
return NULL
Definition llist.h:586
#define LLIST_WHILE_HEAD(list, head)
Consume a list from head.
Definition llist.h:164
This header is for including and configuring NoBug.
char * lumiera_strndup(const char *str, size_t len)
Duplicate a C string.
Definition safeclib.c:166
void * lumiera_malloc(size_t size)
Allocate memory.
Definition safeclib.c:113
Portable and safe wrappers around some C-Lib functions.
static void lumiera_free(void *mem)
Free previously allocated memory.
Definition safeclib.h:73
char * lumiera_tmpbuf_snprintf(size_t size, const char *fmt,...)
Construct a string in a tmpbuf.
Definition tmpbuf.c:116
Round robin temporary buffers.