]> mj.ucw.cz Git - libucw.git/blob - lib/conf2.c
conf2: verified and fixed all parsers
[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 byte *
400 cf_parse_int(byte *str, int *ptr)
401 {
402   byte *msg = NULL;
403   if (!*str)
404     msg = "Missing number";
405   else {
406     const struct unit *u;
407     char *end;
408     errno = 0;
409     uns x = strtoul(str, &end, 0);
410     if (errno == ERANGE)
411       msg = cf_rngerr;
412     else if (u = lookup_unit(str, end, &msg)) {
413       u64 y = (u64)x * u->num;
414       if (y % u->den)
415         msg = "Number is not an integer";
416       else {
417         y /= u->den;
418         if (y > 0xffffffff)
419           msg = cf_rngerr;
420         *ptr = y;
421       }
422     } else
423       *ptr = x;
424   }
425   return msg;
426 }
427
428 byte *
429 cf_parse_u64(byte *str, u64 *ptr)
430 {
431   byte *msg = NULL;
432   if (!*str)
433     msg = "Missing number";
434   else {
435     const struct unit *u;
436     char *end;
437     errno = 0;
438     u64 x = strtoull(str, &end, 0);
439     if (errno == ERANGE)
440       msg = cf_rngerr;
441     else if (u = lookup_unit(str, end, &msg)) {
442       if (x > ~(u64)0 / u->num)
443         msg = "Number out of range";
444       else {
445         x *= u->num;
446         if (x % u->den)
447           msg = "Number is not an integer";
448         else
449           *ptr = x / u->den;
450       }
451     } else
452       *ptr = x;
453   }
454   return msg;
455 }
456
457 byte *
458 cf_parse_double(byte *str, double *ptr)
459 {
460   byte *msg = NULL;
461   if (!*str)
462     msg = "Missing number";
463   else {
464     const struct unit *u;
465     double x;
466     uns read_chars;
467     if (sscanf(str, "%lf%n", &x, &read_chars) != 1)
468       msg = "Invalid number";
469     else if (u = lookup_unit(str, str + read_chars, &msg))
470       *ptr = x * u->num / u->den;
471     else
472       *ptr = x;
473   }
474   return msg;
475 }
476
477 byte *
478 cf_parse_ip(byte *p, u32 *varp)
479 {
480   if (!*p)
481     return "Missing IP address";
482   uns x = 0;
483   char *p2;
484   if (*p == '0' && p[1] | 32 == 'X') {
485     errno = 0;
486     x = strtoul(p + 2, &p2, 16);
487     if (errno == ERANGE || p2 == (char*) (p+2) || x > 0xffffffff)
488       goto error;
489     p = p2;
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       uns y = strtoul(p, &p2, 10);
499       if (errno == ERANGE || p2 == (char*) p || y > 255)
500         goto error;
501       p = p2;
502       x = (x << 8) + y;
503     }
504   *varp = x;
505   return *p ? "Trailing characters" : NULL;
506 error:
507   return "Invalid IP address";
508 }
509
510 static byte *
511 cf_parse_string(byte *str, byte **ptr)
512 {
513   *ptr = cf_strdup(str);
514   return NULL;
515 }
516
517 /* Register size of and parser for each basic type */
518
519 typedef byte *cf_basic_parser(byte *str, void *ptr);
520 static struct {
521   uns size;
522   void *parser;
523 } parsers[] = {
524   { sizeof(int), cf_parse_int },
525   { sizeof(u64), cf_parse_u64 },
526   { sizeof(double), cf_parse_double },
527   { sizeof(u32), cf_parse_ip },
528   { sizeof(byte*), cf_parse_string }
529 };
530
531 static byte *
532 cf_parse_ary(uns number, byte **pars, void *ptr, enum cf_type type)
533 {
534   for (uns i=0; i<number; i++)
535   {
536     byte *msg = ((cf_basic_parser*) parsers[type].parser) (pars[i], ptr + i * parsers[type].size);
537     if (msg)
538       return cf_printf("Cannot parse item %d: %s", i+1, msg);
539   }
540   return NULL;
541 }
542
543 /* Interpreter */
544
545 #define T(x) #x,
546 static byte *op_names[] = { CF_OPERATIONS };
547 #undef T
548
549 #define OP_MASK 0xff            // only get the operation
550 #define OP_OPEN 0x100           // here we only get an opening brace instead of parameters
551 #define OP_1ST 0x200            // in the 1st phase selectors are recorded into the mask
552 #define OP_2ND 0x400            // in the 2nd phase real data are entered
553
554 static byte *
555 interpret_set_dynamic(struct cf_item *item, int number, byte **pars, void **ptr)
556 {
557   enum cf_type type = item->u.type;
558   cf_journal_block(ptr, sizeof(void*));
559   // boundary checks done by the caller
560   *ptr = cf_malloc((number+1) * parsers[type].size) + parsers[type].size;
561   * (uns*) (*ptr - parsers[type].size) = number;
562   return cf_parse_ary(number, pars, *ptr, type);
563 }
564
565 static byte *
566 interpret_add_dynamic(struct cf_item *item, int number, byte **pars, int *processed, void **ptr, enum operation op)
567 {
568   enum cf_type type = item->u.type;
569   void *old_p = *ptr;
570   int old_nr = * (int*) (old_p - parsers[type].size);
571   int taken = MIN(number, item->number-old_nr);
572   *processed = taken;
573   // stretch the dynamic array
574   void *new_p = cf_malloc((old_nr + taken + 1) * parsers[type].size) + parsers[type].size;
575   * (uns*) (new_p - parsers[type].size) = old_nr + taken;
576   cf_journal_block(ptr, sizeof(void*));
577   *ptr = new_p;
578   if (op == OP_APPEND) {
579     memcpy(new_p, old_p, old_nr * parsers[type].size);
580     return cf_parse_ary(taken, pars, new_p + old_nr * parsers[type].size, type);
581   } else if (op == OP_PREPEND) {
582     memcpy(new_p + taken * parsers[type].size, old_p, old_nr * parsers[type].size);
583     return cf_parse_ary(taken, pars, new_p, type);
584   } else
585     return cf_printf("Dynamic arrays do not support operation %s", op_names[op]);
586 }
587
588 static byte *interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic);
589
590 static byte *
591 interpret_section(struct cf_section *sec, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic)
592 {
593   *processed = 0;
594   for (struct cf_item *ci=sec->cfg; ci->cls; ci++)
595   {
596     int taken;
597     byte *msg = interpret_set_item(ci, number, pars, &taken, ptr + (addr_int_t) ci->ptr, allow_dynamic && !ci[1].cls);
598     if (msg)
599       return cf_printf("Item %s: %s", ci->name, msg);
600     *processed += taken;
601     number -= taken;
602     pars += taken;
603     if (!number)                // stop parsing, because many parsers would otherwise complain that number==0
604       break;
605   }
606   return NULL;
607 }
608
609 static void
610 add_to_list(struct cnode *where, struct cnode *new_node, enum operation op)
611 {
612   switch (op)
613   {
614     case OP_EDIT:               // edition has been done in-place
615       break;
616     case OP_REMOVE:
617       cf_journal_block(&where->prev->next, sizeof(void*));
618       cf_journal_block(&where->next->prev, sizeof(void*));
619       clist_remove(where);
620       break;
621     case OP_AFTER:              // implementation dependend (prepend_head = after(list)), and where==list, see clists.h:74
622     case OP_PREPEND:
623       cf_journal_block(&where->next->prev, sizeof(void*));
624       cf_journal_block(&where->next, sizeof(void*));
625       clist_insert_after(new_node, where);
626       break;
627     case OP_BEFORE:             // implementation dependend (append_tail = before(list))
628     case OP_APPEND:
629     case OP_SET:
630       cf_journal_block(&where->prev->next, sizeof(void*));
631       cf_journal_block(&where->prev, sizeof(void*));
632       clist_insert_before(new_node, where);
633       break;
634     default:
635       ASSERT(0);
636   }
637 }
638
639 static byte *
640 interpret_add_list(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, enum operation op)
641 {
642   if (op >= OP_REMOVE)
643     return cf_printf("You have to open a block for operation %s", op_names[op]);
644   if (!number)
645     return "Nothing to add to the list";
646   struct cf_section *sec = item->u.sec;
647   *processed = 0;
648   while (number > 0)
649   {
650     void *node = cf_malloc(sec->size);
651     cf_init_section(item->name, sec, node);
652     add_to_list(ptr, node, op);
653     int taken;
654     /* If the node contains any dynamic attribute at the end, we suppress
655      * auto-repetition here and pass the flag inside instead.  */
656     TRY( interpret_section(sec, number, pars, &taken, node, sec->flags & SEC_FLAG_DYNAMIC) );
657     *processed += taken;
658     number -= taken;
659     pars += taken;
660     if (sec->flags & SEC_FLAG_DYNAMIC)
661       break;
662   }
663   return NULL;
664 }
665
666 static byte *
667 interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic)
668 {
669   int taken;
670   switch (item->cls)
671   {
672     case CC_STATIC:
673       if (!number)
674         return "Missing value";
675       taken = MIN(number, item->number);
676       *processed = taken;
677       cf_journal_block(ptr, taken * parsers[item->u.type].size);
678       return cf_parse_ary(taken, pars, ptr, item->u.type);
679     case CC_DYNAMIC:
680       if (!allow_dynamic)
681         return "Dynamic array cannot be used here";
682       taken = MIN(number, item->number);
683       *processed = taken;
684       return interpret_set_dynamic(item, taken, pars, ptr);
685     case CC_PARSER:
686       if (item->number < 0 && !allow_dynamic)
687         return "Parsers with variable number of parameters cannot be used here";
688       if (item->number > 0 && number < item->number)
689         return "Not enough parameters available for the parser";
690       taken = MIN(number, ABS(item->number));
691       *processed = taken;
692       for (int i=0; i<taken; i++)
693         pars[i] = cf_strdup(pars[i]);
694       return item->u.par(taken, pars, ptr);
695     case CC_SECTION:
696       return interpret_section(item->u.sec, number, pars, processed, ptr, allow_dynamic);
697     case CC_LIST:
698       if (!allow_dynamic)
699         return "Lists cannot be used here";
700       return interpret_add_list(item, number, pars, processed, ptr, OP_SET);
701     default:
702       ASSERT(0);
703   }
704 }
705
706 static byte *
707 interpret_clear(struct cf_item *item, void *ptr)
708 {
709   if (item->cls == CC_LIST) {
710     cf_journal_block(ptr, sizeof(struct clist));
711     clist_init(ptr);
712   } else if (item->cls == CC_DYNAMIC) {
713     cf_journal_block(ptr, sizeof(void *));
714     * (void**) ptr = NULL;
715   } else
716     return "The item is not a list or a dynamic array";
717   return NULL;
718 }
719
720 static int
721 cmp_items(void *i1, void *i2, struct cf_item *item)
722 {
723   ASSERT(item->cls == CC_STATIC);
724   i1 += (addr_int_t) item->ptr;
725   i2 += (addr_int_t) item->ptr;
726   if (item->u.type == CT_STRING)
727     return strcmp(* (byte**) i1, * (byte**) i2);
728   else                          // all numeric types
729     return memcmp(i1, i2, parsers[item->u.type].size);
730 }
731
732 static void *
733 find_list_node(struct clist *list, void *query, struct cf_section *sec, u32 mask)
734 {
735   struct cnode *n;
736   CLIST_WALK(n, *list)
737   {
738     uns found = 1;
739     for (uns i=0; i<32; i++)
740       if (mask & (1<<i))
741         if (cmp_items(n, query, sec->cfg+i))
742         {
743           found = 0;
744           break;
745         }
746     if (found)
747       return n;
748   }
749   return NULL;
750 }
751
752 static byte *
753 record_selector(struct cf_item *item, struct cf_section *sec, u32 *mask)
754 {
755   uns nr = sec->flags & SEC_FLAG_NUMBER;
756   if (item >= sec->cfg && item < sec->cfg + nr) // setting an attribute relative to this section
757   {
758     uns i = item - sec->cfg;
759     if (i >= 32)
760       return "Cannot select list nodes by this attribute";
761     if (sec->cfg[i].cls != CC_STATIC)
762       return "Selection can only be done based on basic attributes";
763     *mask |= 1 << i;
764   }
765   return NULL;
766 }
767
768 #define MAX_STACK_SIZE  100
769 static struct item_stack {
770   struct cf_section *sec;       // nested section
771   void *base_ptr;               // because original pointers are often relative
772   enum operation op;            // it is performed when a closing brace is encountered
773   void *list;                   // list the operations should be done on
774   u32 mask;                     // bit array of selectors searching in a list
775   struct cf_item *item;         // cf_item of the list
776 } stack[MAX_STACK_SIZE];
777 static uns level;
778
779 static byte *
780 opening_brace(struct cf_item *item, void *ptr, enum operation op)
781 {
782   if (level >= MAX_STACK_SIZE-1)
783     return "Too many nested sections";
784   stack[++level] = (struct item_stack) {
785     .sec = NULL,
786     .base_ptr = NULL,
787     .op = op & OP_MASK,
788     .list = NULL,
789     .mask = 0,
790     .item = NULL,
791   };
792   if (!item)                    // unknown is ignored; we just need to trace recursion
793     return NULL;
794   stack[level].sec = item->u.sec;
795   if (item->cls == CC_SECTION)
796   {
797     stack[level].base_ptr = ptr;
798     stack[level].op = OP_EDIT | OP_2ND; // this list operation does nothing
799   }
800   else if (item->cls == CC_LIST)
801   {
802     stack[level].base_ptr = cf_malloc(item->u.sec->size);
803     cf_init_section(item->name, item->u.sec, stack[level].base_ptr);
804     stack[level].list = ptr;
805     stack[level].item = item;
806     stack[level].op |= (op & OP_MASK) < OP_REMOVE ? OP_2ND : OP_1ST;
807   }
808   else
809     return "Opening brace can only be used on sections and lists";
810   return NULL;
811 }
812
813 static byte *
814 closing_brace(struct item_stack *st, enum operation op, int number, byte **pars)
815 {
816   if (st->op == OP_CLOSE)       // top-level
817     return "Unmatched } parenthese";
818   if (!st->sec) {               // dummy run on unknown section
819     if (!(op & OP_OPEN))
820       level--;
821     return NULL;
822   }
823   enum operation pure_op = st->op & OP_MASK;
824   if (st->op & OP_1ST)
825   {
826     st->list = find_list_node(st->list, st->base_ptr, st->sec, st->mask);
827     if (!st->list)
828       return "Cannot find a node matching the query";
829     if (pure_op != OP_REMOVE)
830     {
831       if (pure_op == OP_EDIT)
832         st->base_ptr = st->list;
833       else if (pure_op == OP_AFTER || pure_op == OP_BEFORE)
834         cf_init_section(st->item->name, st->sec, st->base_ptr);
835       else
836         ASSERT(0);
837       if (op & OP_OPEN) {       // stay at the same recursion level
838         st->op = (st->op | OP_2ND) & ~OP_1ST;
839         return NULL;
840       }
841       int taken;                // parse parameters on 1 line immediately
842       TRY( interpret_section(st->sec, number, pars, &taken, st->base_ptr, 1) );
843       number -= taken;
844       pars += taken;
845       // and fall-thru to the 2nd phase
846     }
847   }
848   add_to_list(st->list, st->base_ptr, pure_op);
849   level--;
850   if (number)
851     return "No parameters expected after the }";
852   else if (op & OP_OPEN)
853     return "No { is expected";
854   else
855     return NULL;
856 }
857
858 static byte *
859 interpret_line(byte *name, enum operation op, int number, byte **pars)
860 {
861   byte *msg;
862   if ((op & OP_MASK) == OP_CLOSE)
863     return closing_brace(stack+level, op, number, pars);
864   void *ptr = stack[level].base_ptr;
865   struct cf_item *item = find_item(stack[level].sec, name, &msg, &ptr);
866   if (msg)
867     return msg;
868   if (stack[level].op & OP_1ST)
869     TRY( record_selector(item, stack[level].sec, &stack[level].mask) );
870   if (op & OP_OPEN)             // the operation will be performed after the closing brace
871     return opening_brace(item, ptr, op);
872   if (!item)                    // ignored item in an unknown section
873     return NULL;
874   op &= OP_MASK;
875
876   int taken;                    // process as many parameters as possible
877   if (op == OP_CLEAR)
878     taken = 0, msg = interpret_clear(item, ptr);
879   else if (op == OP_SET)
880     msg = interpret_set_item(item, number, pars, &taken, ptr, 1);
881   else if (item->cls == CC_DYNAMIC)
882     msg = interpret_add_dynamic(item, number, pars, &taken, ptr, op);
883   else if (item->cls == CC_LIST)
884     msg = interpret_add_list(item, number, pars, &taken, ptr, op);
885   else
886     return cf_printf("Operation %s not supported on attribute class %d", op_names[op], item->cls);
887   if (msg)
888     return msg;
889   if (taken < number)
890     return cf_printf("Too many parameters: %d>%d", number, taken);
891
892   return NULL;
893 }
894
895 byte *
896 cf_write_item(struct cf_item *item, enum operation op, int number, byte **pars)
897 {
898   byte *msg;
899   int taken;
900   switch (op) {
901     case OP_SET:
902       msg = interpret_set_item(item, number, pars, &taken, item->ptr, 1);
903       break;
904     case OP_CLEAR:
905       taken = 0;
906       msg = interpret_clear(item, item->ptr);
907       break;
908     case OP_APPEND:
909     case OP_PREPEND:
910       if (item->cls == CC_DYNAMIC)
911         msg = interpret_add_dynamic(item, number, pars, &taken, item->ptr, op);
912       else if (item->cls == CC_LIST)
913         msg = interpret_add_list(item, number, pars, &taken, item->ptr, op);
914       else
915         return "The attribute class does not support append/prepend";
916       break;
917     default:
918       return "Unsupported operation";
919   }
920   if (msg)
921     return msg;
922   if (taken < number)
923     return "Too many parameters";
924   return NULL;
925 }
926
927 static void
928 init_stack(void)
929 {
930   global_init();
931   level = 0;
932   stack[0] = (struct item_stack) {
933     .sec = &sections,
934     .base_ptr = NULL,
935     .op = OP_CLOSE,
936     .list = NULL,
937     .mask = 0,
938     .item = NULL
939   };
940 }
941
942 static int
943 done_stack(void)
944 {
945   if (level > 0) {
946     log(L_ERROR, "Unterminated block");
947     return 1;
948   }
949   if (commit_section("top-level", &sections, NULL))
950     return 1;
951   return 0;
952 }
953
954 /* Text file parser */
955
956 static struct fastbuf *parse_fb;
957 static uns line_num;
958
959 #define MAX_LINE        4096
960 static byte line_buf[MAX_LINE];
961 static byte *line = line_buf;
962
963 #include "lib/bbuf.h"
964 static bb_t copy_buf;
965 static uns copied;
966
967 #define GBUF_TYPE       uns
968 #define GBUF_PREFIX(x)  split_##x
969 #include "lib/gbuf.h"
970 static split_t word_buf;
971 static uns words;
972 static uns ends_by_brace;               // the line is ended by "{"
973
974 static int
975 get_line(void)
976 {
977   if (!bgets(parse_fb, line_buf, MAX_LINE))
978     return 0;
979   line_num++;
980   line = line_buf;
981   while (Cblank(*line))
982     line++;
983   return 1;
984 }
985
986 static void
987 append(byte *start, byte *end)
988 {
989   uns len = end - start;
990   bb_grow(&copy_buf, copied + len + 1);
991   memcpy(copy_buf.ptr + copied, start, len);
992   copied += len + 1;
993   copy_buf.ptr[copied-1] = 0;
994 }
995
996 #define CONTROL_CHAR(x) (x == '{' || x == '}' || x == ';')
997   // these characters separate words like blanks
998
999 static byte *
1000 get_word(uns is_command_name)
1001 {
1002   if (*line == '\'') {
1003     line++;
1004     while (1) {
1005       byte *start = line;
1006       while (*line && *line != '\'')
1007         line++;
1008       append(start, line);
1009       if (*line)
1010         break;
1011       copy_buf.ptr[copied-1] = '\n';
1012       if (!get_line())
1013         return "Unterminated apostrophe word at the end";
1014     }
1015     line++;
1016
1017   } else if (*line == '"') {
1018     line++;
1019     uns start_copy = copied;
1020     while (1) {
1021       byte *start = line;
1022       uns escape = 0;
1023       while (*line) {
1024         if (*line == '"' && !escape)
1025           break;
1026         else if (*line == '\\')
1027           escape ^= 1;
1028         else
1029           escape = 0;
1030         line++;
1031       }
1032       append(start, line);
1033       if (*line)
1034         break;
1035       if (!escape)
1036         copy_buf.ptr[copied-1] = '\n';
1037       else // merge two lines
1038         copied -= 2;
1039       if (!get_line())
1040         return "Unterminated quoted word at the end";
1041     }
1042     line++;
1043
1044     for (byte *c=copy_buf.ptr+start_copy; *c; c++)
1045       if (*c == '%') {
1046         if (c[1] != '%')
1047           return "Formating sequences are not allowed";
1048         else
1049           c++;
1050       }
1051     byte *tmp = cf_printf(copy_buf.ptr + start_copy);
1052     uns l = strlen(tmp);
1053     bb_grow(&copy_buf, start_copy + l + 1);
1054     strcpy(copy_buf.ptr + start_copy, tmp);
1055     copied = start_copy + l + 1;
1056
1057   } else {
1058     // promised that *line is non-null and non-blank
1059     byte *start = line;
1060     while (*line && !Cblank(*line) && !CONTROL_CHAR(*line)
1061         && (*line != '=' || !is_command_name))
1062       line++;
1063     if (*line == '=') {                         // nice for setting from a command-line
1064       if (line == start)
1065         return "Assignment without a variable";
1066       *line = ' ';
1067     }
1068     if (line == start)                          // already the first char is control
1069       line++;
1070     append(start, line);
1071   }
1072   while (Cblank(*line))
1073     line++;
1074   return NULL;
1075 }
1076
1077 static byte *
1078 get_token(uns is_command_name, byte **msg)
1079 {
1080   *msg = NULL;
1081   while (1) {
1082     if (!*line || *line == '#') {
1083       if (!is_command_name || !get_line())
1084         return NULL;
1085     } else if (*line == ';') {
1086       *msg = get_word(0);
1087       if (!is_command_name || *msg)
1088         return NULL;
1089     } else if (*line == '\\' && !line[1]) {
1090       if (!get_line()) {
1091         *msg = "Last line ends by a backslash";
1092         return NULL;
1093       }
1094       if (!*line || *line == '#')
1095         log(L_WARN, "The line following the backslash is empty");
1096     } else {
1097       split_grow(&word_buf, words+1);
1098       uns start = copied;
1099       word_buf.ptr[words++] = copied;
1100       *msg = get_word(is_command_name);
1101       return *msg ? NULL : copy_buf.ptr + start;
1102     }
1103   }
1104 }
1105
1106 static byte *
1107 split_command(void)
1108 {
1109   words = copied = ends_by_brace = 0;
1110   byte *msg, *start_word;
1111   if (!(start_word = get_token(1, &msg)))
1112     return msg;
1113   if (*start_word == '{')                       // only one opening brace
1114     return "Unexpected opening brace";
1115   while (*line != '}')                          // stays for the next time
1116   {
1117     if (!(start_word = get_token(0, &msg)))
1118       return msg;
1119     if (*start_word == '{') {
1120       words--;                                  // discard the brace
1121       ends_by_brace = 1;
1122       break;
1123     }
1124   }
1125   return NULL;
1126 }
1127
1128 /* Parsing multiple files */
1129
1130 static byte *
1131 parse_fastbuf(byte *name_fb, struct fastbuf *fb, uns depth)
1132 {
1133   byte *msg;
1134   parse_fb = fb;
1135   line_num = 0;
1136   line = line_buf;
1137   *line = 0;
1138   while (1)
1139   {
1140     msg = split_command();
1141     if (msg)
1142       goto error;
1143     if (!words)
1144       return NULL;
1145     byte *name = copy_buf.ptr + word_buf.ptr[0];
1146     byte *pars[words-1];
1147     for (uns i=1; i<words; i++)
1148       pars[i-1] = copy_buf.ptr + word_buf.ptr[i];
1149     if (!strcasecmp(name, "include"))
1150     {
1151       if (words != 2) {
1152         msg = "Expecting one filename";
1153         goto error;
1154       }
1155       if (depth > 8) {
1156         msg = "Too many nested files";
1157         goto error;
1158       }
1159       struct fastbuf *new_fb = bopen(pars[0], O_RDONLY, 1<<14);
1160       uns ll = line_num;
1161       msg = parse_fastbuf(pars[0], new_fb, depth+1);
1162       bclose(new_fb);
1163       if (msg)
1164         goto error;
1165       line_num = ll;
1166       parse_fb = fb;
1167     }
1168     enum operation op;
1169     byte *c = strchr(name, ':');
1170     if (!c)
1171       op = strcmp(name, "}") ? OP_SET : OP_CLOSE;
1172     else {
1173       *c++ = 0;
1174       switch (Clocase(*c)) {
1175         case 's': op = OP_SET; break;
1176         case 'c': op = OP_CLEAR; break;
1177         case 'a': op = Clocase(c[1]) == 'p' ? OP_APPEND : OP_AFTER; break;
1178         case 'p': op = OP_PREPEND; break;
1179         case 'r': op = OP_REMOVE; break;
1180         case 'e': op = OP_EDIT; break;
1181         case 'b': op = OP_BEFORE; break;
1182         default: op = OP_SET; break;
1183       }
1184       if (strcasecmp(c, op_names[op])) {
1185         msg = cf_printf("Unknown operation %s", c);
1186         goto error;
1187       }
1188     }
1189     if (ends_by_brace)
1190       op |= OP_OPEN;
1191     msg = interpret_line(name, op, words-1, pars);
1192     if (msg)
1193       goto error;
1194   }
1195 error:
1196   log(L_ERROR, "File %s, line %d: %s", name_fb, line_num, msg);
1197   return "included from here";
1198 }
1199
1200 #ifndef DEFAULT_CONFIG
1201 #define DEFAULT_CONFIG NULL
1202 #endif
1203 byte *cf_def_file = DEFAULT_CONFIG;
1204
1205 static int
1206 load_file(byte *file)
1207 {
1208   init_stack();
1209   struct fastbuf *fb = bopen(file, O_RDONLY, 1<<14);
1210   byte *msg = parse_fastbuf(file, fb, 0);
1211   bclose(fb);
1212   int err = !!msg || done_stack();
1213   if (!err)
1214     cf_def_file = NULL;
1215   return err;
1216 }
1217
1218 static int
1219 load_string(byte *string)
1220 {
1221   init_stack();
1222   struct fastbuf fb;
1223   fbbuf_init_read(&fb, string, strlen(string), 0);
1224   byte *msg = parse_fastbuf("memory string", &fb, 0);
1225   return !!msg || done_stack();
1226 }
1227
1228 /* Command-line parser */
1229
1230 static void
1231 load_default(void)
1232 {
1233   if (cf_def_file)
1234     if (cf_load(cf_def_file))
1235       die("Cannot load default config %s", cf_def_file);
1236 }
1237
1238 int
1239 cf_get_opt(int argc, char * const argv[], const char *short_opts, const struct option *long_opts, int *long_index)
1240 {
1241   static int other_options = 0;
1242   while (1) {
1243     int res = getopt_long (argc, argv, short_opts, long_opts, long_index);
1244     if (res == 'S' || res == 'C')
1245     {
1246       if (other_options)
1247         die("The -S and -C options must precede all other arguments");
1248       if (res == 'S') {
1249         load_default();
1250         if (cf_set(optarg))
1251           die("Cannot set %s", optarg);
1252       } else {
1253         if (cf_load(optarg))
1254           die("Cannot load %s", optarg);
1255       }
1256     } else {
1257       /* unhandled option or end of options */
1258       load_default();
1259       other_options++;
1260       return res;
1261     }
1262   }
1263 }
1264
1265 /* Debug dumping */
1266
1267 #include "fastbuf.h"
1268
1269 static void
1270 spaces(struct fastbuf *fb, uns nr)
1271 {
1272   for (uns i=0; i<nr; i++)
1273     bputs(fb, "  ");
1274 }
1275
1276 static void
1277 dump_basic(struct fastbuf *fb, void *ptr, enum cf_type type)
1278 {
1279   switch (type) {
1280     case CT_INT:        bprintf(fb, "%d ", *(uns*)ptr); break;
1281     case CT_U64:        bprintf(fb, "%llu ", *(u64*)ptr); break;
1282     case CT_DOUBLE:     bprintf(fb, "%lg ", *(double*)ptr); break;
1283     case CT_IP:         bprintf(fb, "%08x ", *(uns*)ptr); break;
1284     case CT_STRING:     bprintf(fb, "'%s' ", *(byte**)ptr); break;
1285   }
1286 }
1287
1288 static void dump_section(struct fastbuf *fb, struct cf_section *sec, int level, void *ptr);
1289
1290 static void
1291 dump_item(struct fastbuf *fb, struct cf_item *item, int level, void *ptr)
1292 {
1293   ptr += (addr_int_t) item->ptr;
1294   enum cf_type type = item->u.type;
1295   int i;
1296   spaces(fb, level);
1297   bprintf(fb, "%s: c%d #%d ", item->name, item->cls, item->number);
1298   if (item->cls == CC_STATIC || item->cls == CC_DYNAMIC)
1299     bprintf(fb, "t%d ", type);
1300   if (item->cls == CC_STATIC) {
1301     for (i=0; i<item->number; i++)
1302       dump_basic(fb, ptr + i * parsers[type].size, type);
1303   } else if (item->cls == CC_DYNAMIC) {
1304     ptr = * (void**) ptr;
1305     if (ptr) {
1306       int real_nr = * (int*) (ptr - parsers[type].size);
1307       bprintf(fb, "##%d ", real_nr);
1308       for (i=0; i<real_nr; i++)
1309         dump_basic(fb, ptr + i * parsers[type].size, type);
1310     } else
1311       bprintf(fb, "NULL ");
1312   }
1313   bputc(fb, '\n');
1314   if (item->cls == CC_SECTION)
1315     dump_section(fb, item->u.sec, level+1, ptr);
1316   else if (item->cls == CC_LIST) {
1317     uns idx = 0;
1318     struct cnode *n;
1319     CLIST_WALK(n, * (clist*) ptr) {
1320       spaces(fb, level+1);
1321       bprintf(fb, "item %d\n", ++idx);
1322       dump_section(fb, item->u.sec, level+2, n);
1323     }
1324   }
1325 }
1326
1327 static void
1328 dump_section(struct fastbuf *fb, struct cf_section *sec, int level, void *ptr)
1329 {
1330   spaces(fb, level);
1331   bprintf(fb, "S%d F%x:\n", sec->size, sec->flags);
1332   for (struct cf_item *item=sec->cfg; item->cls; item++)
1333     dump_item(fb, item, level, ptr);
1334 }
1335
1336 void
1337 cf_dump_sections(struct fastbuf *fb)
1338 {
1339   dump_section(fb, &sections, 0, NULL);
1340 }