]> mj.ucw.cz Git - libucw.git/blob - ucw/opt-conf.c
Opt: Generalization of hooks
[libucw.git] / ucw / opt-conf.c
1 /*
2  *      UCW Library -- Interface between command-line options and configuration
3  *
4  *      (c) 2013 Jan Moskyto Matejka <mq@ucw.cz>
5  *      (c) 2014 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 <ucw/lib.h>
12 #include <ucw/opt.h>
13 #include <ucw/opt-internal.h>
14 #include <ucw/conf.h>
15 #include <ucw/conf-internal.h>
16 #include <ucw/fastbuf.h>
17
18 #include <alloca.h>
19 #include <math.h>
20 #include <stdbool.h>
21
22 static void opt_conf_end_of_options(struct cf_context *cc) {
23   cf_load_default(cc);
24   if (cc->postpone_commit && cf_close_group())
25     opt_failure("Loading of configuration failed");
26 }
27
28 void opt_handle_config(struct opt_item * opt UNUSED, const char * value, void * data UNUSED)
29 {
30   if (cf_load(value))
31     exit(1);            // Error message is already printed by cf_load()
32 }
33
34 void opt_handle_set(struct opt_item * opt UNUSED, const char * value, void * data UNUSED)
35 {
36   struct cf_context *cc = cf_get_context();
37   cf_load_default(cc);
38   if (cf_set(value))
39     opt_failure("Cannot set %s", value);
40 }
41
42 void opt_handle_dumpconfig(struct opt_item * opt UNUSED, const char * value UNUSED, void * data UNUSED)
43 {
44   struct cf_context *cc = cf_get_context();
45   opt_conf_end_of_options(cc);
46   struct fastbuf *b = bfdopen(1, 4096);
47   cf_dump_sections(b);
48   bclose(b);
49   exit(0);
50 }
51
52 void opt_conf_hook_internal(struct opt_item * opt, uns event, const char * value UNUSED, void * data UNUSED) {
53   static enum {
54     OPT_CONF_HOOK_BEGIN,
55     OPT_CONF_HOOK_CONFIG,
56     OPT_CONF_HOOK_OTHERS
57   } state = OPT_CONF_HOOK_BEGIN;
58   struct cf_context *cc = cf_get_context();
59
60   if (event == OPT_HOOK_FINAL) {
61       opt_conf_end_of_options(cc);
62       return;
63   }
64
65   ASSERT(event == OPT_HOOK_BEFORE_VALUE);
66
67   bool confopt = opt->flags & OPT_BEFORE_CONFIG;
68
69   switch (state) {
70     case OPT_CONF_HOOK_BEGIN:
71       if (confopt)
72         state = OPT_CONF_HOOK_CONFIG;
73       else {
74         opt_conf_end_of_options(cc);
75         state = OPT_CONF_HOOK_OTHERS;
76       }
77       break;
78     case OPT_CONF_HOOK_CONFIG:
79       if (!confopt) {
80         opt_conf_end_of_options(cc);
81         state = OPT_CONF_HOOK_OTHERS;
82       }
83       break;
84     case OPT_CONF_HOOK_OTHERS:
85       if (confopt)
86         opt_failure("Config options must stand before other options.");
87       break;
88     default:
89       ASSERT(0);
90   }
91 }