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