]> mj.ucw.cz Git - libucw.git/blob - ucw/doc/conf.txt
8c10ac9bd5302b66f0aaf8609b9fda8cde11ae50
[libucw.git] / ucw / doc / conf.txt
1 Configuration and command line parser
2 =====================================
3
4 Libucw contains a parser for configuration files described in
5 <<config:>>.
6
7 The principle is you specify the structure of the configuration file,
8 the section names, variable names and types and your C variables that
9 are assigned to them. Then you run the parser and it fills your
10 variables with the values from the configuration file.
11
12 It is modular. It means you do not have to write all configuration at
13 the same place, you just declare the parts you need locally and do not
14 care about the other parts.
15
16 The command line parser has the same interface as unix getopt_long(),
17 but handles setting of configuration files and configuration values
18 from command line.
19
20 - <<example,Example>>
21   * <<ex_structure,The structure>>
22   * <<ex_load,Loading>>
23 - <<deep,Getting deeper>>
24   * <<reload,Reloading configuration>>
25   * <<custom_parser,Creating custom parsers>>
26   * <<hooks,Hooks>>
27 - <<conf_h,ucw/conf.h>>
28   * <<conf_types,Data types>>
29   * <<conf_macros,Convenience macros>>
30   * <<alloc,Memory allocation>>
31   * <<journal,Undo journal>>
32   * <<bparser,Parsers for basic types>>
33 - <<getopt_h,ucw/getopt.h>>
34   * <<conf_load,Safe configuration loading>>
35   * <<conf_direct,Direct access>>
36   * <<conf_dump,Debug dumping>>
37   * <<conf_journal,Journaling control>>
38   * <<conf_getopt,Loading by cf_getopt()>>
39
40 [[example]]
41 Example
42 -------
43 If you want to just load simple configuration, this is the part you
44 want to read. This simple example should give you the overview. Look
45 into the <<conf_macros,convenience macros>> section to see list of
46 supported data types, sections, etc.
47
48 [[ex_cfile]]
49 Let's say you have configuration file with this content and want to
50 load it:
51
52   HelloWorld {
53     Text        "Hello planet"
54     Count       3
55   }
56
57 [[ex_structure]]
58 The structure
59 ~~~~~~~~~~~~~
60 First, you declare the structure and let the configuration parser know
61 it exists.
62
63   #include <ucw/lib.h>
64   #include <ucw/conf.h>
65
66   static char *hw_text = "Hello world";
67   static int hw_count = 1;
68   static int hw_wait_answer = 0;
69
70   static struct cf_section hw_config = {
71     CF_ITEMS {
72       CF_STRING("Text", &hw_text),
73       CF_INT("Count", &hw_count),
74       CF_INT("WaitAnswer", &hw_wait_answer),
75       CF_END
76     }
77   };
78
79   static void CONSTRUCTOR hw_init(void) {
80     cf_declare_section("HelloWorld", &hw_config, 0);
81   }
82
83 The variables are used to store the loaded values. Their initial
84 values work as default, if nothing else is loaded. The hw_config()
85 structure assigns the variables to configuration names. The hw_init()
86 function (because of the `CONSTRUCTOR` macro) is run before main()
87 is called and it plugs in the whole section to the parser.
88
89 You can plug in as many configuration sections as you like, from
90 various places across your code.
91
92 [[ex_load]]
93 Loading of the values
94 ~~~~~~~~~~~~~~~~~~~~~
95 You need to parse the command line arguments and load the
96 configuration. You can do it in a similar way to this example.
97
98   #include <ucw/lib.h>
99   #include <ucw/conf.h>
100   #include <ucw/getopt.h>
101
102   static byte short_opts[] = CF_SHORT_OPTS "v";
103   static struct option long_opts[] = {
104     CF_LONG_OPTS
105     { "verbose", 0, 0, 'v' },
106     { NULL, 0, 0, 0 }
107   };
108
109   int verbose;
110
111   int main(int argc, char *argv[]) {
112     cf_def_file = "default.cf";
113     int opt;
114     while((opt = cf_getopt(argc, argv, short_opts, long_opts, NULL)) >= 0)
115       switch(opt) {
116         case 'v': verbose = 1; break;
117         default: fprintf("Unknown option %c\n", opt); return 1;
118       }
119
120 The `short_opts` and `long_opts` variables describe the command line
121 arguments. Notice the `CF_SHORT_OPTS` and `CF_LONG_OPTS` macros. They
122 add options for the configuration parser. These options are handled
123 internally by @cf_getopt(). It loads the configuration before it starts
124 giving you your program's options.
125
126 See documentation of unix getopt_long() function.
127
128 [[deep]]
129 Getting deeper
130 --------------
131
132 Since the configuration system is somehow complicated, this part gives
133 you a little overview of what you can find and where.
134
135 [[reload]]
136 Reloading configuration
137 ~~~~~~~~~~~~~~~~~~~~~~~
138
139 The configuration system allows you to reload configuration at
140 runtime. The new config changes the values against the default values.
141 It means, if the default value for variable `A` is `10`, the currently
142 loaded config sets it to `42` and the new config does not talk about
143 this variable, `A` will have a value of `10` after a successful load.
144
145 Furthermore, if the loading of a new configuration fails, the current
146 configuration is preserved.
147
148 All this is done with <<journal,config journaling>>. The load of the
149 first config creates a journal entry. If you try to load some new
150 configuration, it is partially rolled back to defaults (the rollback
151 happens, but instead of removing the journal entry, another journal
152 entry is added for the rollback). If the loading succeeds, the two
153 journal entries are removed and a new one, for the new configuration,
154 is added. If it fails, the first one is replayed and the rollback
155 entry is removed.
156
157 See <<cf_reload()>>.
158
159 [[custom_parser]]
160 Creating custom parsers
161 ~~~~~~~~~~~~~~~~~~~~~~~
162
163 If you need to parse some data type the configuration system can't
164 handle, you can write your own parser. But before you start, you
165 should know a few things.
166
167 The parser needs to support <<journal,journaling>>. To accomplish that,
168 you have to use the <<alloc,configuration mempool>> for memory allocation.
169 Furthermore, you need to call @cf_journal_block() before you change
170 the configuration (eg. before you save the parsed value to the destination
171 variable). You can use <<def_CF_JOURNAL_VAR,`CF_JOURNAL_VAR`>> macro
172 instead if it is a simple variable.
173
174 Now, you need a function with the same signature as
175 <<type_cf_parser1,`cf_parser1`>>. Parse the first parameter (the
176 string), call @cf_journal_block() on the second parameter and store
177 the data there. You may want to write a dumper function, with
178 signature of <<type_cf_dumper1,`cf_dumper1`>> (needed for debug
179 dumps).
180
181 Fill in a <<struct_cf_user_type,structure cf_user_type>> and use the
182 new data type in your configuration description with
183 <<def_CF_USER,`CF_USER` macro>>.
184
185 [[hooks]]
186 Hooks
187 ~~~~~
188
189 The configuration system supports hooks. They are used to initialize the
190 configuration (if simple default value of variable is not enough) and
191 to check the sanity of loaded data.
192
193 Each hook is of type <<type_cf_hook,`cf_hook`>> and you can include
194 them in configuration description using <<def_CF_INIT,`CF_INIT`>> and
195 <<def_CF_COMMIT,`CF_COMMIT`>> macros.
196
197 The hooks should follow similar guidelines as custom parsers (well,
198 init hooks do not need to call @cf_journal_block()) to support
199 journaling. If you change nothing in the commit hook, you do not need
200 to care about the journaling either.
201
202 You may use the return value to inform about errors. Just return the
203 error message, or NULL if everything went well.
204
205 Another similar function is a copy function. It is very similar to a
206 hook and is used when the item is copied and is too complicated to use
207 simple memcpy(). Its type is <<type_cf_copier,`cf_copier`>> and is
208 specified by the <<def_CF_COPY,`CF_COPY`>> macro. It's return value is
209 the same as the one of a hook.
210
211 [[conf_h]]
212 ucw/conf.h
213 ----------
214
215 Use this file if you want define a configuration section, request
216 loading of some variables or create new item type.
217
218 !!ucw/conf.h
219
220 [[getopt_h]]
221 ucw/getopt.h
222 ------------
223
224 This header contains routines for parsing command line arguments and
225 loading the configuration.
226
227 !!ucw/getopt.h