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