]> mj.ucw.cz Git - libucw.git/blob - ucw/doc/conf.txt
43f838ec22a92aaadac5fde721e8edbc6b590bad
[libucw.git] / ucw / doc / conf.txt
1 Configuration parser
2 ====================
3
4 Libucw contains a parser for configuration files. The syntax of the
5 configuration files is described in <<config:>>, here we explain the
6 interface of the parser.
7
8 Basically, you write a description of the configuration file syntax,
9 which maps configuration items to variables of your program. Then
10 Then you run the parser and it fills your variables with the values
11 from the configuration file.
12
13 The descriptions are modular. The configuration can be split to sections,
14 each section declared at a separate place. You can also define your own
15 data types.
16
17 - <<example,Example>>
18   * <<ex_structure,The structure>>
19   * <<ex_load,Loading configuration>>
20 - <<deep,Getting deeper>>
21   * <<conf_multi,Arrays and lists>>
22   * <<reload,Reloading configuration>>
23   * <<custom_parser,Creating custom parsers>>
24   * <<hooks,Hooks>>
25 - <<conf_h,ucw/conf.h>>
26   * <<conf_ctxt,Configuration contexts>>
27   * <<conf_load,Safe configuration loading>>
28   * <<conf_types,Data types>>
29   * <<conf_macros,Convenience macros>>
30   * <<alloc,Memory allocation>>
31   * <<journal,Undo journal>>
32   * <<declare,Section declaration>>
33   * <<bparser,Parsers for basic types>>
34   * <<conf_direct,Direct access>>
35   * <<conf_dump,Debug dumping>>
36 - <<getopt_h,ucw/getopt.h>>
37   * <<conf_getopt,Loading configuration by cf_getopt()>> (obsolete)
38   * <<getopt_example,Example>> (obsolete)
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 at the <<conf_macros,convenience macros>> section to see list of
46 supported data types, sections, etc.
47
48 [[ex_cfile]]
49 Suppose you have configuration file with the following content and you
50 want to 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 defaults, 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 tells the parser that the section exists (alternatively,
88 you can call @cf_declare_section() at the start of your main()).
89
90 You can plug in as many configuration sections as you like, from
91 various places across your code.
92
93 [[ex_load]]
94 Loading configuration
95 ~~~~~~~~~~~~~~~~~~~~~
96 You can load the configuration explicitly by calling @cf_load().
97 That can be convenient when writing a library, but in normal programs,
98 you can ask the <<opt:,option parser>> to handle it for you.
99
100 A typical example follows, please see the <<opt:conf,interface between
101 conf and opt>> for details.
102
103   #include <ucw/lib.h>
104   #include <ucw/opt.h>
105   
106   static struct opt_section options = {
107     OPT_ITEMS {
108       // More options can be specified here
109       OPT_HELP("Configuration options:"),
110       OPT_CONF_OPTIONS,
111       OPT_END
112     }
113   };
114   
115   int main(int argc, char **argv)
116   {
117     cf_def_file = "default.cf";
118     opt_parse(&options, argv+1);
119     // Configuration file is already loaded here
120     return 0;
121   }
122
123 [[deep]]
124 Getting deeper
125 --------------
126
127 Since the configuration system is somehow complicated, this part gives
128 you a little overview of what you can find and where.
129
130 [[conf_multi]]
131 Arrays and lists
132 ~~~~~~~~~~~~~~~~
133
134 It is sometime needed to have multiple items of the same type. There
135 are three ways to do that:
136
137 *Static arrays*::
138   An array with fixed maximum length. You provide
139   the length and already allocated array which is filled with items.
140   The configuration may contain less than the maximum length items.
141 +
142 For example, you can have an static array of five unsigned integers:
143 +
144   static uns array[] = { 1, 2, 3, 4, 5 };
145 +
146   static struct cf_section section = {
147     CF_ITEMS {
148       CF_UNS_ARY("array", array, 5),
149       CF_END
150     }
151   };
152
153 *Dynamic arrays*::
154   Similar to static array, but you provide pointer
155   to pointer to the given item (eg. if you want dynamic array of
156   integers, you give `**int`). The parser allocates an array of needed
157   size. You can use the <<def_DARY_LEN,`DARY_LEN`>> macro to find out
158   the number of elements actually loaded.
159 +
160 If you want dynamic array of strings, you would use:
161 +
162   static char *array[];
163 +
164   static struct cf_section section = {
165     CF_ITEMS {
166       CF_STRING_DYN("array", &array, CF_ANY_NUM),
167       CF_END
168     }
169   };
170
171 *Lists*::
172   Linked lists based on <<lists:clists,clists>>. You provide description
173   of single node and pointer to the
174   <<lists:struct_clist,`struct clist`>> variable. All the nodes will
175   be created dynamically and put there.
176 +
177 First element of your structure must be <<lists:struct_cnode,`cnode`>>.
178 +
179 The first example is list of strings and uses <<lists:simple_lists,simple
180 lists>>:
181 +
182   static struct clist list;
183 +
184   static struct cf_section section = {
185     CF_ITEMS {
186       CF_LIST("list", &list, &cf_string_list_config),
187       CF_END
188     }
189   };
190 +
191 Another example, describing how to create more complicated list node
192 than just a string can be found at the <<def_CF_TYPE,`CF_TYPE`>> macro.
193
194 [[reload]]
195 Reloading configuration
196 ~~~~~~~~~~~~~~~~~~~~~~~
197
198 The configuration system allows you to reload configuration at
199 runtime. The new config changes the values against the default values.
200 It means, if the default value for variable `A` is `10`, the currently
201 loaded config sets it to `42` and the new config does not talk about
202 this variable, `A` will have a value of `10` after a successful load.
203
204 Furthermore, if the loading of a new configuration fails, the current
205 configuration is preserved.
206
207 All this is done with <<journal,config journalling>>. The load of the
208 first config creates a journal entry. If you try to load some new
209 configuration, it is partially rolled back to defaults (the rollback
210 happens, but instead of removing the journal entry, another journal
211 entry is added for the rollback). If the loading succeeds, the two
212 journal entries are removed and a new one, for the new configuration,
213 is added. If it fails, the first one is replayed and the rollback
214 entry is removed.
215
216 See <<cf_reload()>>.
217
218 [[custom_parser]]
219 Creating custom parsers
220 ~~~~~~~~~~~~~~~~~~~~~~~
221
222 If you need to parse some data type the configuration system can't
223 handle, you can write your own parser. But before you start, you
224 should know a few things.
225
226 The parser needs to support <<journal,journalling>>. To accomplish that,
227 you have to use the <<alloc,configuration mempool>> for memory allocation.
228
229 Now, you need a function with the same signature as
230 <<type_cf_parser1,`cf_parser1`>>. Parse the first parameter (the
231 string) and store the data in the second parameter. You may want to
232 write a dumper function, with signature of
233 <<type_cf_dumper1,`cf_dumper1`>> (needed for debug dumps).
234
235 Fill in a structure <<struct_cf_user_type,cf_user_type>> and use the
236 new data type in your configuration description with
237 <<def_CF_USER,`CF_USER`>> macro as its @t parameter.
238
239 You do not need to call @cf_journal_block() on the variable you store
240 the result. It is true you change it, but it was stored to journal
241 before your parser function was called.
242
243 [[hooks]]
244 Hooks
245 ~~~~~
246
247 The configuration system supports hooks. They are used to initialize the
248 configuration (if simple default value of variable is not enough) and
249 to check the sanity of loaded data.
250
251 Each hook is of type <<type_cf_hook,`cf_hook`>> and you can include
252 them in configuration description using <<def_CF_INIT,`CF_INIT`>> and
253 <<def_CF_COMMIT,`CF_COMMIT`>> macros.
254
255 The hooks should follow similar guidelines as custom parsers (well,
256 init hooks do not need to call @cf_journal_block()) to support
257 journalling. If you change nothing in the commit hook, you do not need
258 to care about the journalling either.
259
260 You may use the return value to inform about errors. Just return the
261 error message, or NULL if everything went well.
262
263 Another similar function is a copy function. It is very similar to a
264 hook and is used when the item is copied and is too complicated to use
265 simple memcpy(). Its type is <<type_cf_copier,`cf_copier`>> and is
266 specified by the <<def_CF_COPY,`CF_COPY`>> macro. It's return value is
267 the same as the one of a hook.
268
269 [[conf_h]]
270 ucw/conf.h
271 ----------
272
273 This header file contains the public interface of the configuration module.
274
275 !!ucw/conf.h
276
277 [[getopt_h]]
278 ucw/getopt.h
279 ------------
280
281 This header contains routines for parsing command line arguments and
282 loading the default configuration.
283
284 In new programs, please consider using the new <<opt:,option parser>>
285 instead. The getopt interface is already considered obsolete and may
286 be removed in the future.
287
288 !!ucw/getopt.h
289
290 Example
291 ~~~~~~~
292 Typically, @cf_getopt() is used as follows: it works like
293 the traditional @getopt_long() from the C library, but it also handles
294 configuration files.
295
296   #include <ucw/lib.h>
297   #include <ucw/conf.h>
298   #include <ucw/getopt.h>
299
300   static char short_opts[] = CF_SHORT_OPTS "v";
301   static struct option long_opts[] = {
302     CF_LONG_OPTS
303     { "verbose", 0, 0, 'v' },
304     { NULL, 0, 0, 0 }
305   };
306
307   static int verbose;
308
309   int main(int argc, char *argv[]) {
310     cf_def_file = "default.cf";
311     int opt;
312     while((opt = cf_getopt(argc, argv, short_opts, long_opts, NULL)) >= 0)
313       switch(opt) {
314         case 'v': verbose = 1; break;
315         default: fprintf("Unknown option %c\n", opt); return 1;
316       }
317   }
318
319 The `short_opts` and `long_opts` variables describe the command line
320 arguments. Notice the `CF_SHORT_OPTS` and `CF_LONG_OPTS` macros. They
321 add the `-S` and `-C` options for the configuration parser as described
322 in <<config:>>. These options are handled internally by @cf_getopt().
323
324 You can rely on the configuration files having been loaded before the
325 first of your program's options is parsed.