]> mj.ucw.cz Git - libucw.git/blob - lib/conf2.c
conf2: insert a node into a list as soon as possible instead of at the end
[libucw.git] / lib / conf2.c
1 /*
2  *      UCW Library -- Reading of configuration files
3  *
4  *      (c) 2001--2006 Robert Spalek <robert@ucw.cz>
5  *      (c) 2003--2006 Martin Mares <mj@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #include "lib/lib.h"
12 #include "lib/conf2.h"
13 #include "lib/mempool.h"
14 #include "lib/clists.h"
15 #include "lib/fastbuf.h"
16 #include "lib/chartype.h"
17 #include "lib/lfs.h"
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <stdarg.h>
23 #include <fcntl.h>
24 #include <getopt.h>
25
26 #define TRY(f)  do { byte *_msg = f; if (_msg) return _msg; } while (0)
27
28 /* Memory allocation */
29
30 struct mempool *cf_pool;        // current pool for loading new configuration
31 static struct old_pools {
32   struct old_pools *prev;
33   struct mempool *pool;
34 } *pools;                       // link-list of older cf_pool's
35
36 void *
37 cf_malloc(uns size)
38 {
39   return mp_alloc(cf_pool, size);
40 }
41
42 void *
43 cf_malloc_zero(uns size)
44 {
45   return mp_alloc_zero(cf_pool, size);
46 }
47
48 byte *
49 cf_strdup(byte *s)
50 {
51   return mp_strdup(cf_pool, s);
52 }
53
54 byte *
55 cf_printf(char *fmt, ...)
56 {
57   va_list args;
58   va_start(args, fmt);
59   byte *res = mp_vprintf(cf_pool, fmt, args);
60   va_end(args);
61   return res;
62 }
63
64 /* Undo journal */
65
66 uns cf_need_journal = 1;        // some programs do not need journal
67 static struct journal_item {
68   struct journal_item *prev;
69   byte *ptr;
70   uns len;
71   byte copy[0];
72 } *journal;
73
74 void
75 cf_journal_block(void *ptr, uns len)
76 {
77   if (!cf_need_journal)
78     return;
79   struct journal_item *ji = cf_malloc(sizeof(struct journal_item) + len);
80   ji->prev = journal;
81   ji->ptr = ptr;
82   ji->len = len;
83   memcpy(ji->copy, ptr, len);
84   journal = ji;
85 }
86
87 static void
88 journal_swap(void)
89   // swaps the contents of the memory and the journal, and reverses the list
90 {
91   struct journal_item *curr, *prev, *next;
92   for (next=NULL, curr=journal; curr; next=curr, curr=prev)
93   {
94     prev = curr->prev;
95     curr->prev = next;
96     for (uns i=0; i<curr->len; i++)
97     {
98       byte x = curr->copy[i];
99       curr->copy[i] = curr->ptr[i];
100       curr->ptr[i] = x;
101     }
102   }
103   journal = next;
104 }
105
106 static struct journal_item *
107 journal_new_transaction(uns new_pool)
108 {
109   if (new_pool)
110     cf_pool = mp_new(1<<10);
111   struct journal_item *oldj = journal;
112   journal = NULL;
113   return oldj;
114 }
115
116 static void
117 journal_commit_transaction(uns new_pool, struct journal_item *oldj)
118 {
119   if (new_pool)
120   {
121     struct old_pools *p = cf_malloc(sizeof(struct old_pools));
122     p->prev = pools;
123     p->pool = cf_pool;
124     pools = p;
125   }
126   if (oldj)
127   {
128     struct journal_item **j = &journal;
129     while (*j)
130       j = &(*j)->prev;
131     *j = oldj;
132   }
133 }
134
135 static void
136 journal_rollback_transaction(uns new_pool, struct journal_item *oldj)
137 {
138   if (!cf_need_journal)
139     die("Cannot rollback the configuration, because the journal is disabled.");
140   journal_swap();
141   journal = oldj;
142   if (new_pool)
143   {
144     mp_delete(cf_pool);
145     cf_pool = pools ? pools->pool : NULL;
146   }
147 }
148
149 /* Initialization */
150
151 #define SEC_FLAG_DYNAMIC        0x80000000      // contains a dynamic attribute
152 #define SEC_FLAG_UNKNOWN        0x40000000      // ignore unknown entriies
153 #define SEC_FLAG_NUMBER         0x0fffffff      // number of entries
154
155 static struct cf_section sections;      // root section
156
157 static struct cf_item *
158 find_subitem(struct cf_section *sec, byte *name)
159 {
160   struct cf_item *ci = sec->cfg;
161   for (; ci->cls; ci++)
162     if (!strcasecmp(ci->name, name))
163       return ci;
164   return ci;
165 }
166
167 static void
168 inspect_section(struct cf_section *sec)
169 {
170   sec->flags = 0;
171   struct cf_item *ci;
172   for (ci=sec->cfg; ci->cls; ci++)
173     if (ci->cls == CC_SECTION) {
174       inspect_section(ci->u.sec);
175       sec->flags |= ci->u.sec->flags & SEC_FLAG_DYNAMIC;
176     } else if (ci->cls == CC_LIST) {
177       inspect_section(ci->u.sec);
178       sec->flags |= SEC_FLAG_DYNAMIC;
179     } else if (ci->cls == CC_DYNAMIC || ci->cls == CC_PARSER && ci->number < 0)
180       sec->flags |= SEC_FLAG_DYNAMIC;
181   sec->flags |= ci - sec->cfg;          // record the number of entries
182 }
183
184 void
185 cf_declare_section(byte *name, struct cf_section *sec, uns allow_unknown)
186 {
187   if (!sections.cfg)
188   {
189     sections.size = 50;
190     sections.cfg = xmalloc_zero(sections.size * sizeof(struct cf_item));
191   }
192   struct cf_item *ci = find_subitem(&sections, name);
193   if (ci->cls)
194     die("Cannot register section %s twice", name);
195   ci->cls = CC_SECTION;
196   ci->name = name;
197   ci->number = 1;
198   ci->ptr = NULL;
199   ci->u.sec = sec;
200   inspect_section(sec);
201   if (allow_unknown)
202     sec->flags |= SEC_FLAG_UNKNOWN;
203   ci++;
204   if (ci - sections.cfg >= (int) sections.size)
205   {
206     sections.cfg = xrealloc(sections.cfg, 2*sections.size * sizeof(struct cf_item));
207     bzero(sections.cfg + sections.size, sections.size * sizeof(struct cf_item));
208     sections.size *= 2;
209   }
210 }
211
212 void
213 cf_init_section(byte *name, struct cf_section *sec, void *ptr, uns do_bzero)
214 {
215   if (do_bzero) {
216     ASSERT(sec->size);
217     bzero(ptr, sec->size);
218   }
219   for (uns i=0; sec->cfg[i].cls; i++)
220     if (sec->cfg[i].cls == CC_SECTION)
221       cf_init_section(sec->cfg[i].name, sec->cfg[i].u.sec, ptr + (addr_int_t) sec->cfg[i].ptr, 0);
222     else if (sec->cfg[i].cls == CC_LIST)
223       clist_init(ptr + (addr_int_t) sec->cfg[i].ptr);
224   if (sec->init) {
225     byte *msg = sec->init(ptr);
226     if (msg)
227       die("Cannot initialize section %s: %s", name, msg);
228   }
229 }
230
231 static void
232 global_init(void)
233 {
234   static uns initialized = 0;
235   if (initialized++)
236     return;
237   sections.flags |= SEC_FLAG_UNKNOWN;
238   sections.size = 0;                    // size of allocated array used to be stored here
239   cf_init_section("top-level", &sections, NULL, 0);
240 }
241
242 static int
243 commit_section(byte *name, struct cf_section *sec, void *ptr)
244 {
245   struct cf_item *ci;
246   for (ci=sec->cfg; ci->cls; ci++)
247     if (ci->cls == CC_SECTION) {
248       if (commit_section(ci->name, ci->u.sec, ptr + (addr_int_t) ci->ptr)) {
249         log(L_ERROR, "It happened in section %s", ci->name);
250         return 1;
251       }
252     } else if (ci->cls == CC_LIST) {
253       struct cnode *n;
254       uns idx = 0;
255       CLIST_WALK(n, * (clist*) (ptr + (addr_int_t) ci->ptr))
256         if (idx++, commit_section(ci->name, ci->u.sec, n)) {
257           log(L_ERROR, "It happened in node #%d of list %s", idx, ci->name);
258           return 1;
259         }
260     }
261   if (sec->commit) {
262     byte *msg = sec->commit(ptr);
263     if (msg) {
264       log(L_ERROR, "Cannot commit section %s: %s", name, msg);
265       return 1;
266     }
267   }
268   return 0;
269 }
270
271 static struct cf_item *
272 find_item(struct cf_section *curr_sec, byte *name, byte **msg, void **ptr)
273 {
274   *msg = NULL;
275   if (name[0] == '^')                           // absolute name instead of relative
276     name++, curr_sec = &sections, *ptr = NULL;
277   if (!curr_sec)                                // don't even search in an unknown section
278     return NULL;
279   while (1)
280   {
281     byte *c = strchr(name, '.');
282     if (c)
283       *c++ = 0;
284     struct cf_item *ci = find_subitem(curr_sec, name);
285     if (!ci->cls)
286     {
287       if (!(curr_sec->flags & SEC_FLAG_UNKNOWN))        // ignore silently unknown top-level sections and unknown attributes in flagged sections
288         *msg = cf_printf("Unknown item %s", name);
289       return NULL;
290     }
291     *ptr += (addr_int_t) ci->ptr;
292     if (!c)
293       return ci;
294     if (ci->cls != CC_SECTION)
295     {
296       *msg = cf_printf("Item %s is not a section", name);
297       return NULL;
298     }
299     curr_sec = ci->u.sec;
300     name = c;
301   }
302 }
303
304 byte *
305 cf_find_item(byte *name, struct cf_item *item)
306 {
307   byte *msg;
308   void *ptr;
309   struct cf_item *ci = find_item(&sections, name, &msg, &ptr);
310   if (msg)
311     return msg;
312   *item = *ci;
313   item->ptr = ptr;
314   return NULL;
315 }
316
317 /* Safe loading and reloading */
318
319 static int load_file(byte *file);
320 static int load_string(byte *string);
321
322 int
323 cf_reload(byte *file)
324 {
325   journal_swap();
326   struct journal_item *oldj = journal_new_transaction(1);
327   int err = load_file(file);
328   if (!err)
329   {
330     for (struct old_pools *p=pools; p; p=pools)
331     {
332       pools = p->prev;
333       mp_delete(p->pool);
334     }
335     journal_commit_transaction(1, NULL);
336   }
337   else
338   {
339     journal_rollback_transaction(1, oldj);
340     journal_swap();
341   }
342   return err;
343 }
344
345 int
346 cf_load(byte *file)
347 {
348   struct journal_item *oldj = journal_new_transaction(1);
349   int err = load_file(file);
350   if (!err)
351     journal_commit_transaction(1, oldj);
352   else
353     journal_rollback_transaction(1, oldj);
354   return err;
355 }
356
357 int
358 cf_set(byte *string)
359 {
360   struct journal_item *oldj = journal_new_transaction(0);
361   int err = load_string(string);
362   if (!err)
363     journal_commit_transaction(0, oldj);
364   else
365     journal_rollback_transaction(0, oldj);
366   return err;
367 }
368
369 /* Parsers for standard types */
370
371 struct unit {
372   uns name;                     // one-letter name of the unit
373   uns num, den;                 // fraction
374 };
375
376 static const struct unit units[] = {
377   { 'd', 86400, 1 },
378   { 'h', 3600, 1 },
379   { 'k', 1000, 1 },
380   { 'm', 1000000, 1 },
381   { 'g', 1000000000, 1 },
382   { 'K', 1024, 1 },
383   { 'M', 1048576, 1 },
384   { 'G', 1073741824, 1 },
385   { '%', 1, 100 },
386   { 0, 0, 0 }
387 };
388
389 static const struct unit *
390 lookup_unit(byte *value, byte *end, byte **msg)
391 {
392   if (end && *end) {
393     if (end == value || end[1] || *end >= '0' && *end <= '9')
394       *msg = "Invalid number";
395     else {
396       for (const struct unit *u=units; u->name; u++)
397         if (u->name == *end)
398           return u;
399       *msg = "Invalid unit";
400     }
401   }
402   return NULL;
403 }
404
405 static char cf_rngerr[] = "Number out of range";
406
407 byte *
408 cf_parse_int(byte *str, int *ptr)
409 {
410   byte *msg = NULL;
411   if (!*str)
412     msg = "Missing number";
413   else {
414     const struct unit *u;
415     char *end;
416     errno = 0;
417     uns x = strtoul(str, &end, 0);
418     if (errno == ERANGE)
419       msg = cf_rngerr;
420     else if (u = lookup_unit(str, end, &msg)) {
421       u64 y = (u64)x * u->num;
422       if (y % u->den)
423         msg = "Number is not an integer";
424       else {
425         y /= u->den;
426         if (y > 0xffffffff)
427           msg = cf_rngerr;
428         *ptr = y;
429       }
430     } else
431       *ptr = x;
432   }
433   return msg;
434 }
435
436 byte *
437 cf_parse_u64(byte *str, u64 *ptr)
438 {
439   byte *msg = NULL;
440   if (!*str)
441     msg = "Missing number";
442   else {
443     const struct unit *u;
444     char *end;
445     errno = 0;
446     u64 x = strtoull(str, &end, 0);
447     if (errno == ERANGE)
448       msg = cf_rngerr;
449     else if (u = lookup_unit(str, end, &msg)) {
450       if (x > ~(u64)0 / u->num)
451         msg = "Number out of range";
452       else {
453         x *= u->num;
454         if (x % u->den)
455           msg = "Number is not an integer";
456         else
457           *ptr = x / u->den;
458       }
459     } else
460       *ptr = x;
461   }
462   return msg;
463 }
464
465 byte *
466 cf_parse_double(byte *str, double *ptr)
467 {
468   byte *msg = NULL;
469   if (!*str)
470     msg = "Missing number";
471   else {
472     const struct unit *u;
473     double x;
474     uns read_chars;
475     if (sscanf(str, "%lf%n", &x, &read_chars) != 1)
476       msg = "Invalid number";
477     else if (u = lookup_unit(str, str + read_chars, &msg))
478       *ptr = x * u->num / u->den;
479     else
480       *ptr = x;
481   }
482   return msg;
483 }
484
485 byte *
486 cf_parse_ip(byte *p, u32 *varp)
487 {
488   if (!*p)
489     return "Missing IP address";
490   uns x = 0;
491   char *p2;
492   if (*p == '0' && p[1] | 32 == 'X') {
493     errno = 0;
494     x = strtoul(p + 2, &p2, 16);
495     if (errno == ERANGE || p2 == (char*) (p+2) || x > 0xffffffff)
496       goto error;
497     p = p2;
498   }
499   else
500     for (uns i = 0; i < 4; i++) {
501       if (i) {
502         if (*p++ != '.')
503           goto error;
504       }
505       errno = 0;
506       uns y = strtoul(p, &p2, 10);
507       if (errno == ERANGE || p2 == (char*) p || y > 255)
508         goto error;
509       p = p2;
510       x = (x << 8) + y;
511     }
512   *varp = x;
513   return *p ? "Trailing characters" : NULL;
514 error:
515   return "Invalid IP address";
516 }
517
518 static byte *
519 cf_parse_string(byte *str, byte **ptr)
520 {
521   *ptr = cf_strdup(str);
522   return NULL;
523 }
524
525 /* Register size of and parser for each basic type */
526
527 typedef byte *cf_basic_parser(byte *str, void *ptr);
528 static struct {
529   uns size;
530   void *parser;
531 } parsers[] = {
532   { sizeof(int), cf_parse_int },
533   { sizeof(u64), cf_parse_u64 },
534   { sizeof(double), cf_parse_double },
535   { sizeof(u32), cf_parse_ip },
536   { sizeof(byte*), cf_parse_string }
537 };
538
539 static byte *
540 cf_parse_ary(uns number, byte **pars, void *ptr, enum cf_type type)
541 {
542   for (uns i=0; i<number; i++)
543   {
544     byte *msg = ((cf_basic_parser*) parsers[type].parser) (pars[i], ptr + i * parsers[type].size);
545     if (msg)
546       return cf_printf("Cannot parse item %d: %s", i+1, msg);
547   }
548   return NULL;
549 }
550
551 /* Interpreter */
552
553 #define T(x) #x,
554 static byte *op_names[] = { CF_OPERATIONS };
555 #undef T
556
557 #define OP_MASK 0xff            // only get the operation
558 #define OP_OPEN 0x100           // here we only get an opening brace instead of parameters
559 #define OP_1ST 0x200            // in the 1st phase selectors are recorded into the mask
560 #define OP_2ND 0x400            // in the 2nd phase real data are entered
561
562 static byte *
563 interpret_set_dynamic(struct cf_item *item, int number, byte **pars, void **ptr)
564 {
565   enum cf_type type = item->u.type;
566   cf_journal_block(ptr, sizeof(void*));
567   // boundary checks done by the caller
568   *ptr = cf_malloc((number+1) * parsers[type].size) + parsers[type].size;
569   * (uns*) (*ptr - parsers[type].size) = number;
570   return cf_parse_ary(number, pars, *ptr, type);
571 }
572
573 static byte *
574 interpret_add_dynamic(struct cf_item *item, int number, byte **pars, int *processed, void **ptr, enum cf_operation op)
575 {
576   enum cf_type type = item->u.type;
577   void *old_p = *ptr;
578   int old_nr = * (int*) (old_p - parsers[type].size);
579   int taken = MIN(number, item->number-old_nr);
580   *processed = taken;
581   // stretch the dynamic array
582   void *new_p = cf_malloc((old_nr + taken + 1) * parsers[type].size) + parsers[type].size;
583   * (uns*) (new_p - parsers[type].size) = old_nr + taken;
584   cf_journal_block(ptr, sizeof(void*));
585   *ptr = new_p;
586   if (op == OP_APPEND) {
587     memcpy(new_p, old_p, old_nr * parsers[type].size);
588     return cf_parse_ary(taken, pars, new_p + old_nr * parsers[type].size, type);
589   } else if (op == OP_PREPEND) {
590     memcpy(new_p + taken * parsers[type].size, old_p, old_nr * parsers[type].size);
591     return cf_parse_ary(taken, pars, new_p, type);
592   } else
593     return cf_printf("Dynamic arrays do not support operation %s", op_names[op]);
594 }
595
596 static byte *interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic);
597
598 static byte *
599 interpret_section(struct cf_section *sec, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic)
600 {
601   *processed = 0;
602   for (struct cf_item *ci=sec->cfg; ci->cls; ci++)
603   {
604     int taken;
605     byte *msg = interpret_set_item(ci, number, pars, &taken, ptr + (addr_int_t) ci->ptr, allow_dynamic && !ci[1].cls);
606     if (msg)
607       return cf_printf("Item %s: %s", ci->name, msg);
608     *processed += taken;
609     number -= taken;
610     pars += taken;
611     if (!number)                // stop parsing, because many parsers would otherwise complain that number==0
612       break;
613   }
614   return NULL;
615 }
616
617 static void
618 add_to_list(struct cnode *where, struct cnode *new_node, enum cf_operation op)
619 {
620   switch (op)
621   {
622     case OP_EDIT:               // edition has been done in-place
623       break;
624     case OP_REMOVE:
625       cf_journal_block(&where->prev->next, sizeof(void*));
626       cf_journal_block(&where->next->prev, sizeof(void*));
627       clist_remove(where);
628       break;
629     case OP_AFTER:              // implementation dependend (prepend_head = after(list)), and where==list, see clists.h:74
630     case OP_PREPEND:
631       cf_journal_block(&where->next->prev, sizeof(void*));
632       cf_journal_block(&where->next, sizeof(void*));
633       clist_insert_after(new_node, where);
634       break;
635     case OP_BEFORE:             // implementation dependend (append_tail = before(list))
636     case OP_APPEND:
637     case OP_SET:
638       cf_journal_block(&where->prev->next, sizeof(void*));
639       cf_journal_block(&where->prev, sizeof(void*));
640       clist_insert_before(new_node, where);
641       break;
642     default:
643       ASSERT(0);
644   }
645 }
646
647 static byte *
648 interpret_add_list(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, enum cf_operation op)
649 {
650   if (op >= OP_REMOVE)
651     return cf_printf("You have to open a block for operation %s", op_names[op]);
652   if (!number)
653     return "Nothing to add to the list";
654   struct cf_section *sec = item->u.sec;
655   *processed = 0;
656   while (number > 0)
657   {
658     void *node = cf_malloc(sec->size);
659     cf_init_section(item->name, sec, node, 1);
660     add_to_list(ptr, node, op);
661     int taken;
662     /* If the node contains any dynamic attribute at the end, we suppress
663      * auto-repetition here and pass the flag inside instead.  */
664     TRY( interpret_section(sec, number, pars, &taken, node, sec->flags & SEC_FLAG_DYNAMIC) );
665     *processed += taken;
666     number -= taken;
667     pars += taken;
668     if (sec->flags & SEC_FLAG_DYNAMIC)
669       break;
670   }
671   return NULL;
672 }
673
674 static byte *
675 interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic)
676 {
677   int taken;
678   switch (item->cls)
679   {
680     case CC_STATIC:
681       if (!number)
682         return "Missing value";
683       taken = MIN(number, item->number);
684       *processed = taken;
685       cf_journal_block(ptr, taken * parsers[item->u.type].size);
686       return cf_parse_ary(taken, pars, ptr, item->u.type);
687     case CC_DYNAMIC:
688       if (!allow_dynamic)
689         return "Dynamic array cannot be used here";
690       taken = MIN(number, item->number);
691       *processed = taken;
692       return interpret_set_dynamic(item, taken, pars, ptr);
693     case CC_PARSER:
694       if (item->number < 0 && !allow_dynamic)
695         return "Parsers with variable number of parameters cannot be used here";
696       if (item->number > 0 && number < item->number)
697         return "Not enough parameters available for the parser";
698       taken = MIN(number, ABS(item->number));
699       *processed = taken;
700       for (int i=0; i<taken; i++)
701         pars[i] = cf_strdup(pars[i]);
702       return item->u.par(taken, pars, ptr);
703     case CC_SECTION:
704       return interpret_section(item->u.sec, number, pars, processed, ptr, allow_dynamic);
705     case CC_LIST:
706       if (!allow_dynamic)
707         return "Lists cannot be used here";
708       return interpret_add_list(item, number, pars, processed, ptr, OP_SET);
709     default:
710       ASSERT(0);
711   }
712 }
713
714 static byte *
715 interpret_clear(struct cf_item *item, void *ptr)
716 {
717   if (item->cls == CC_LIST) {
718     cf_journal_block(ptr, sizeof(struct clist));
719     clist_init(ptr);
720   } else if (item->cls == CC_DYNAMIC) {
721     cf_journal_block(ptr, sizeof(void *));
722     * (void**) ptr = NULL;
723   } else
724     return "The item is not a list or a dynamic array";
725   return NULL;
726 }
727
728 static int
729 cmp_items(void *i1, void *i2, struct cf_item *item)
730 {
731   ASSERT(item->cls == CC_STATIC);
732   i1 += (addr_int_t) item->ptr;
733   i2 += (addr_int_t) item->ptr;
734   if (item->u.type == CT_STRING)
735     return strcmp(* (byte**) i1, * (byte**) i2);
736   else                          // all numeric types
737     return memcmp(i1, i2, parsers[item->u.type].size);
738 }
739
740 static void *
741 find_list_node(struct clist *list, void *query, struct cf_section *sec, u32 mask)
742 {
743   struct cnode *n;
744   CLIST_WALK(n, *list)
745   {
746     uns found = 1;
747     for (uns i=0; i<32; i++)
748       if (mask & (1<<i))
749         if (cmp_items(n, query, sec->cfg+i))
750         {
751           found = 0;
752           break;
753         }
754     if (found)
755       return n;
756   }
757   return NULL;
758 }
759
760 static byte *
761 record_selector(struct cf_item *item, struct cf_section *sec, u32 *mask)
762 {
763   uns nr = sec->flags & SEC_FLAG_NUMBER;
764   if (item >= sec->cfg && item < sec->cfg + nr) // setting an attribute relative to this section
765   {
766     uns i = item - sec->cfg;
767     if (i >= 32)
768       return "Cannot select list nodes by this attribute";
769     if (sec->cfg[i].cls != CC_STATIC)
770       return "Selection can only be done based on basic attributes";
771     *mask |= 1 << i;
772   }
773   return NULL;
774 }
775
776 #define MAX_STACK_SIZE  100
777 static struct item_stack {
778   struct cf_section *sec;       // nested section
779   void *base_ptr;               // because original pointers are often relative
780   enum cf_operation op;         // it is performed when a closing brace is encountered
781   void *list;                   // list the operations should be done on
782   u32 mask;                     // bit array of selectors searching in a list
783   struct cf_item *item;         // cf_item of the list
784 } stack[MAX_STACK_SIZE];
785 static uns level;
786
787 static byte *
788 opening_brace(struct cf_item *item, void *ptr, enum cf_operation op)
789 {
790   if (level >= MAX_STACK_SIZE-1)
791     return "Too many nested sections";
792   stack[++level] = (struct item_stack) {
793     .sec = NULL,
794     .base_ptr = NULL,
795     .op = op & OP_MASK,
796     .list = NULL,
797     .mask = 0,
798     .item = NULL,
799   };
800   if (!item)                    // unknown is ignored; we just need to trace recursion
801     return NULL;
802   stack[level].sec = item->u.sec;
803   if (item->cls == CC_SECTION)
804   {
805     stack[level].base_ptr = ptr;
806     stack[level].op = OP_EDIT | OP_2ND; // this list operation does nothing
807   }
808   else if (item->cls == CC_LIST)
809   {
810     stack[level].base_ptr = cf_malloc(item->u.sec->size);
811     cf_init_section(item->name, item->u.sec, stack[level].base_ptr, 1);
812     stack[level].list = ptr;
813     stack[level].item = item;
814     if ((op & OP_MASK) < OP_REMOVE) {
815       add_to_list(ptr, stack[level].base_ptr, op & OP_MASK);
816       stack[level].op |= OP_2ND;
817     } else
818       stack[level].op |= OP_1ST;
819   }
820   else
821     return "Opening brace can only be used on sections and lists";
822   return NULL;
823 }
824
825 static byte *
826 closing_brace(struct item_stack *st, enum cf_operation op, int number, byte **pars)
827 {
828   if (st->op == OP_CLOSE)       // top-level
829     return "Unmatched } parenthesis";
830   if (!st->sec) {               // dummy run on unknown section
831     if (!(op & OP_OPEN))
832       level--;
833     return NULL;
834   }
835   enum cf_operation pure_op = st->op & OP_MASK;
836   if (st->op & OP_1ST)
837   {
838     st->list = find_list_node(st->list, st->base_ptr, st->sec, st->mask);
839     if (!st->list)
840       return "Cannot find a node matching the query";
841     if (pure_op != OP_REMOVE)
842     {
843       if (pure_op == OP_EDIT)
844         st->base_ptr = st->list;
845       else if (pure_op == OP_AFTER || pure_op == OP_BEFORE)
846         cf_init_section(st->item->name, st->sec, st->base_ptr, 1);
847       else
848         ASSERT(0);
849       if (op & OP_OPEN) {       // stay at the same recursion level
850         st->op = (st->op | OP_2ND) & ~OP_1ST;
851         add_to_list(st->list, st->base_ptr, pure_op);
852         return NULL;
853       }
854       int taken;                // parse parameters on 1 line immediately
855       TRY( interpret_section(st->sec, number, pars, &taken, st->base_ptr, 1) );
856       number -= taken;
857       pars += taken;
858       // and fall-thru to the 2nd phase
859     }
860     add_to_list(st->list, st->base_ptr, pure_op);
861   }
862   level--;
863   if (number)
864     return "No parameters expected after the }";
865   else if (op & OP_OPEN)
866     return "No { is expected";
867   else
868     return NULL;
869 }
870
871 static byte *
872 interpret_line(byte *name, enum cf_operation op, int number, byte **pars)
873 {
874   byte *msg;
875   if ((op & OP_MASK) == OP_CLOSE)
876     return closing_brace(stack+level, op, number, pars);
877   void *ptr = stack[level].base_ptr;
878   struct cf_item *item = find_item(stack[level].sec, name, &msg, &ptr);
879   if (msg)
880     return msg;
881   if (stack[level].op & OP_1ST)
882     TRY( record_selector(item, stack[level].sec, &stack[level].mask) );
883   if (op & OP_OPEN)             // the operation will be performed after the closing brace
884     return opening_brace(item, ptr, op);
885   if (!item)                    // ignored item in an unknown section
886     return NULL;
887   op &= OP_MASK;
888
889   int taken;                    // process as many parameters as possible
890   if (op == OP_CLEAR)
891     taken = 0, msg = interpret_clear(item, ptr);
892   else if (op == OP_SET)
893     msg = interpret_set_item(item, number, pars, &taken, ptr, 1);
894   else if (item->cls == CC_DYNAMIC)
895     msg = interpret_add_dynamic(item, number, pars, &taken, ptr, op);
896   else if (item->cls == CC_LIST)
897     msg = interpret_add_list(item, number, pars, &taken, ptr, op);
898   else
899     return cf_printf("Operation %s not supported on attribute %s", op_names[op], name);
900   if (msg)
901     return msg;
902   if (taken < number)
903     return cf_printf("Too many parameters: %d>%d", number, taken);
904
905   return NULL;
906 }
907
908 byte *
909 cf_write_item(struct cf_item *item, enum cf_operation op, int number, byte **pars)
910 {
911   byte *msg;
912   int taken;
913   switch (op) {
914     case OP_SET:
915       msg = interpret_set_item(item, number, pars, &taken, item->ptr, 1);
916       break;
917     case OP_CLEAR:
918       taken = 0;
919       msg = interpret_clear(item, item->ptr);
920       break;
921     case OP_APPEND:
922     case OP_PREPEND:
923       if (item->cls == CC_DYNAMIC)
924         msg = interpret_add_dynamic(item, number, pars, &taken, item->ptr, op);
925       else if (item->cls == CC_LIST)
926         msg = interpret_add_list(item, number, pars, &taken, item->ptr, op);
927       else
928         return "The attribute class does not support append/prepend";
929       break;
930     default:
931       return "Unsupported operation";
932   }
933   if (msg)
934     return msg;
935   if (taken < number)
936     return "Too many parameters";
937   return NULL;
938 }
939
940 static void
941 init_stack(void)
942 {
943   global_init();
944   level = 0;
945   stack[0] = (struct item_stack) {
946     .sec = &sections,
947     .base_ptr = NULL,
948     .op = OP_CLOSE,
949     .list = NULL,
950     .mask = 0,
951     .item = NULL
952   };
953 }
954
955 static int
956 done_stack(void)
957 {
958   if (level > 0) {
959     log(L_ERROR, "Unterminated block");
960     return 1;
961   }
962   if (commit_section("top-level", &sections, NULL))
963     return 1;
964   return 0;
965 }
966
967 /* Text file parser */
968
969 static byte *name_parse_fb;
970 static struct fastbuf *parse_fb;
971 static uns line_num;
972
973 #define MAX_LINE        4096
974 static byte line_buf[MAX_LINE];
975 static byte *line = line_buf;
976
977 #include "lib/bbuf.h"
978 static bb_t copy_buf;
979 static uns copied;
980
981 #define GBUF_TYPE       uns
982 #define GBUF_PREFIX(x)  split_##x
983 #include "lib/gbuf.h"
984 static split_t word_buf;
985 static uns words;
986 static uns ends_by_brace;               // the line is ended by "{"
987
988 static int
989 get_line(void)
990 {
991   if (!bgets(parse_fb, line_buf, MAX_LINE))
992     return 0;
993   line_num++;
994   line = line_buf;
995   while (Cblank(*line))
996     line++;
997   return 1;
998 }
999
1000 static void
1001 append(byte *start, byte *end)
1002 {
1003   uns len = end - start;
1004   bb_grow(&copy_buf, copied + len + 1);
1005   memcpy(copy_buf.ptr + copied, start, len);
1006   copied += len + 1;
1007   copy_buf.ptr[copied-1] = 0;
1008 }
1009
1010 #define CONTROL_CHAR(x) (x == '{' || x == '}' || x == ';')
1011   // these characters separate words like blanks
1012
1013 static byte *
1014 get_word(uns is_command_name)
1015 {
1016   if (*line == '\'') {
1017     line++;
1018     while (1) {
1019       byte *start = line;
1020       while (*line && *line != '\'')
1021         line++;
1022       append(start, line);
1023       if (*line)
1024         break;
1025       copy_buf.ptr[copied-1] = '\n';
1026       if (!get_line())
1027         return "Unterminated apostrophe word at the end";
1028     }
1029     line++;
1030
1031   } else if (*line == '"') {
1032     line++;
1033     uns start_copy = copied;
1034     while (1) {
1035       byte *start = line;
1036       uns escape = 0;
1037       while (*line) {
1038         if (*line == '"' && !escape)
1039           break;
1040         else if (*line == '\\')
1041           escape ^= 1;
1042         else
1043           escape = 0;
1044         line++;
1045       }
1046       append(start, line);
1047       if (*line)
1048         break;
1049       if (!escape)
1050         copy_buf.ptr[copied-1] = '\n';
1051       else // merge two lines
1052         copied -= 2;
1053       if (!get_line())
1054         return "Unterminated quoted word at the end";
1055     }
1056     line++;
1057
1058     // FIXME: this is utterly bogus, since printf() only expands these
1059     // percents, and the \n, \x1b codes are actually expanded by the compiler
1060     for (byte *c=copy_buf.ptr+start_copy; *c; c++)
1061       if (*c == '%') {
1062         if (c[1] != '%')
1063           return "Formating sequences are not allowed";
1064         else
1065           c++;
1066       }
1067     byte *tmp = cf_printf(copy_buf.ptr + start_copy);
1068     uns l = strlen(tmp);
1069     bb_grow(&copy_buf, start_copy + l + 1);
1070     strcpy(copy_buf.ptr + start_copy, tmp);
1071     copied = start_copy + l + 1;
1072
1073   } else {
1074     // promised that *line is non-null and non-blank
1075     byte *start = line;
1076     while (*line && !Cblank(*line) && !CONTROL_CHAR(*line)
1077         && (*line != '=' || !is_command_name))
1078       line++;
1079     if (*line == '=') {                         // nice for setting from a command-line
1080       if (line == start)
1081         return "Assignment without a variable";
1082       *line = ' ';
1083     }
1084     if (line == start)                          // already the first char is control
1085       line++;
1086     append(start, line);
1087   }
1088   while (Cblank(*line))
1089     line++;
1090   return NULL;
1091 }
1092
1093 static byte *
1094 get_token(uns is_command_name, byte **msg)
1095 {
1096   *msg = NULL;
1097   while (1) {
1098     if (!*line || *line == '#') {
1099       if (!is_command_name || !get_line())
1100         return NULL;
1101     } else if (*line == ';') {
1102       *msg = get_word(0);
1103       if (!is_command_name || *msg)
1104         return NULL;
1105     } else if (*line == '\\' && !line[1]) {
1106       if (!get_line()) {
1107         *msg = "Last line ends by a backslash";
1108         return NULL;
1109       }
1110       if (!*line || *line == '#')
1111         log(L_WARN, "The line %s:%d following a backslash is empty", name_parse_fb, line_num);
1112     } else {
1113       split_grow(&word_buf, words+1);
1114       uns start = copied;
1115       word_buf.ptr[words++] = copied;
1116       *msg = get_word(is_command_name);
1117       return *msg ? NULL : copy_buf.ptr + start;
1118     }
1119   }
1120 }
1121
1122 static byte *
1123 split_command(void)
1124 {
1125   words = copied = ends_by_brace = 0;
1126   byte *msg, *start_word;
1127   if (!(start_word = get_token(1, &msg)))
1128     return msg;
1129   if (*start_word == '{')                       // only one opening brace
1130     return "Unexpected opening brace";
1131   while (*line != '}')                          // stays for the next time
1132   {
1133     if (!(start_word = get_token(0, &msg)))
1134       return msg;
1135     if (*start_word == '{') {
1136       words--;                                  // discard the brace
1137       ends_by_brace = 1;
1138       break;
1139     }
1140   }
1141   return NULL;
1142 }
1143
1144 /* Parsing multiple files */
1145
1146 static struct fastbuf *
1147 bopen_safe(byte *name)
1148 {
1149   int fd = sh_open(name, O_RDONLY);
1150   if (fd < 0) {
1151     log(L_ERROR, "Cannot open %s", name);
1152     return NULL;
1153   }
1154   return bopen(name, O_RDONLY, 1<<14);
1155 }
1156
1157 static byte *
1158 parse_fastbuf(byte *name_fb, struct fastbuf *fb, uns depth)
1159 {
1160   byte *msg;
1161   name_parse_fb = name_fb;
1162   parse_fb = fb;
1163   line_num = 0;
1164   line = line_buf;
1165   *line = 0;
1166   while (1)
1167   {
1168     msg = split_command();
1169     if (msg)
1170       goto error;
1171     if (!words)
1172       return NULL;
1173     byte *name = copy_buf.ptr + word_buf.ptr[0];
1174     byte *pars[words-1];
1175     for (uns i=1; i<words; i++)
1176       pars[i-1] = copy_buf.ptr + word_buf.ptr[i];
1177     if (!strcasecmp(name, "include"))
1178     {
1179       if (words != 2)
1180         msg = "Expecting one filename";
1181       else if (depth > 8)
1182         msg = "Too many nested files";
1183       else if (*line && *line != '#')           // because the contents of line_buf is not re-entrant and will be cleared
1184         msg = "The input command must be the last one on a line";
1185       if (msg)
1186         goto error;
1187       struct fastbuf *new_fb = bopen_safe(pars[0]);
1188       if (!new_fb) {
1189         msg = "Cannot open file";
1190         goto error;
1191       }
1192       uns ll = line_num;
1193       msg = parse_fastbuf(pars[0], new_fb, depth+1);
1194       bclose(new_fb);
1195       if (msg)
1196         goto error;
1197       line_num = ll;
1198       parse_fb = fb;
1199     }
1200     enum cf_operation op;
1201     byte *c = strchr(name, ':');
1202     if (!c)
1203       op = strcmp(name, "}") ? OP_SET : OP_CLOSE;
1204     else {
1205       *c++ = 0;
1206       switch (Clocase(*c)) {
1207         case 's': op = OP_SET; break;
1208         case 'c': op = OP_CLEAR; break;
1209         case 'a': op = Clocase(c[1]) == 'p' ? OP_APPEND : OP_AFTER; break;
1210         case 'p': op = OP_PREPEND; break;
1211         case 'r': op = OP_REMOVE; break;
1212         case 'e': op = OP_EDIT; break;
1213         case 'b': op = OP_BEFORE; break;
1214         default: op = OP_SET; break;
1215       }
1216       if (strcasecmp(c, op_names[op])) {
1217         msg = cf_printf("Unknown operation %s", c);
1218         goto error;
1219       }
1220     }
1221     if (ends_by_brace)
1222       op |= OP_OPEN;
1223     msg = interpret_line(name, op, words-1, pars);
1224     if (msg)
1225       goto error;
1226   }
1227 error:
1228   log(L_ERROR, "File %s, line %d: %s", name_fb, line_num, msg);
1229   return "included from here";
1230 }
1231
1232 #ifndef DEFAULT_CONFIG
1233 #define DEFAULT_CONFIG NULL
1234 #endif
1235 byte *cf_def_file = DEFAULT_CONFIG;
1236
1237 static int
1238 load_file(byte *file)
1239 {
1240   init_stack();
1241   struct fastbuf *fb = bopen_safe(file);
1242   if (!fb)
1243     return 1;
1244   byte *msg = parse_fastbuf(file, fb, 0);
1245   bclose(fb);
1246   int err = !!msg || done_stack();
1247   if (!err)
1248     cf_def_file = NULL;
1249   return err;
1250 }
1251
1252 static int
1253 load_string(byte *string)
1254 {
1255   init_stack();
1256   struct fastbuf fb;
1257   fbbuf_init_read(&fb, string, strlen(string), 0);
1258   byte *msg = parse_fastbuf("memory string", &fb, 0);
1259   return !!msg || done_stack();
1260 }
1261
1262 /* Command-line parser */
1263
1264 static void
1265 load_default(void)
1266 {
1267   if (cf_def_file)
1268     if (cf_load(cf_def_file))
1269       die("Cannot load default config %s", cf_def_file);
1270 }
1271
1272 int
1273 cf_get_opt(int argc, char * const argv[], const char *short_opts, const struct option *long_opts, int *long_index)
1274 {
1275   static int other_options = 0;
1276   while (1) {
1277     int res = getopt_long (argc, argv, short_opts, long_opts, long_index);
1278     if (res == 'S' || res == 'C')
1279     {
1280       if (other_options)
1281         die("The -S and -C options must precede all other arguments");
1282       if (res == 'S') {
1283         load_default();
1284         if (cf_set(optarg))
1285           die("Cannot set %s", optarg);
1286       } else {
1287         if (cf_load(optarg))
1288           die("Cannot load %s", optarg);
1289       }
1290     } else {
1291       /* unhandled option or end of options */
1292       load_default();
1293       other_options++;
1294       return res;
1295     }
1296   }
1297 }
1298
1299 /* Debug dumping */
1300
1301 static void
1302 spaces(struct fastbuf *fb, uns nr)
1303 {
1304   for (uns i=0; i<nr; i++)
1305     bputs(fb, "  ");
1306 }
1307
1308 static void
1309 dump_basic(struct fastbuf *fb, void *ptr, enum cf_type type)
1310 {
1311   switch (type) {
1312     case CT_INT:        bprintf(fb, "%d ", *(uns*)ptr); break;
1313     case CT_U64:        bprintf(fb, "%llu ", *(u64*)ptr); break;
1314     case CT_DOUBLE:     bprintf(fb, "%lg ", *(double*)ptr); break;
1315     case CT_IP:         bprintf(fb, "%08x ", *(uns*)ptr); break;
1316     case CT_STRING:     bprintf(fb, "'%s' ", *(byte**)ptr); break;
1317   }
1318 }
1319
1320 static void dump_section(struct fastbuf *fb, struct cf_section *sec, int level, void *ptr);
1321
1322 static void
1323 dump_item(struct fastbuf *fb, struct cf_item *item, int level, void *ptr)
1324 {
1325   ptr += (addr_int_t) item->ptr;
1326   enum cf_type type = item->u.type;
1327   int i;
1328   spaces(fb, level);
1329   bprintf(fb, "%s: c%d #%d ", item->name, item->cls, item->number);
1330   if (item->cls == CC_STATIC || item->cls == CC_DYNAMIC)
1331     bprintf(fb, "t%d ", type);
1332   if (item->cls == CC_STATIC) {
1333     for (i=0; i<item->number; i++)
1334       dump_basic(fb, ptr + i * parsers[type].size, type);
1335   } else if (item->cls == CC_DYNAMIC) {
1336     ptr = * (void**) ptr;
1337     if (ptr) {
1338       int real_nr = * (int*) (ptr - parsers[type].size);
1339       bprintf(fb, "##%d ", real_nr);
1340       for (i=0; i<real_nr; i++)
1341         dump_basic(fb, ptr + i * parsers[type].size, type);
1342     } else
1343       bprintf(fb, "NULL ");
1344   }
1345   bputc(fb, '\n');
1346   if (item->cls == CC_SECTION)
1347     dump_section(fb, item->u.sec, level+1, ptr);
1348   else if (item->cls == CC_LIST) {
1349     uns idx = 0;
1350     struct cnode *n;
1351     CLIST_WALK(n, * (clist*) ptr) {
1352       spaces(fb, level+1);
1353       bprintf(fb, "item %d\n", ++idx);
1354       dump_section(fb, item->u.sec, level+2, n);
1355     }
1356   }
1357 }
1358
1359 static void
1360 dump_section(struct fastbuf *fb, struct cf_section *sec, int level, void *ptr)
1361 {
1362   spaces(fb, level);
1363   bprintf(fb, "S%d F%x:\n", sec->size, sec->flags);
1364   for (struct cf_item *item=sec->cfg; item->cls; item++)
1365     dump_item(fb, item, level, ptr);
1366 }
1367
1368 void
1369 cf_dump_sections(struct fastbuf *fb)
1370 {
1371   dump_section(fb, &sections, 0, NULL);
1372 }
1373
1374 /* TODO
1375  * - more space efficient journal
1376  * - don't commit all, but recognize from the journal which sections have been changed
1377  */