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