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