]> mj.ucw.cz Git - libucw.git/blob - ucw/doc/conf.txt
UCW doc: minor fixes to the introduction to config parsing
[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 (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 of the values
95 ~~~~~~~~~~~~~~~~~~~~~
96 Suppose you need to parse the command line arguments and load the
97 configuration. Then @cf_getopt() is there for you: it works like
98 the the traditional @getopt() from the C library, but it also handles
99 configuration files.
100
101   #include <ucw/lib.h>
102   #include <ucw/conf.h>
103   #include <ucw/getopt.h>
104
105   static byte short_opts[] = CF_SHORT_OPTS "v";
106   static struct option long_opts[] = {
107     CF_LONG_OPTS
108     { "verbose", 0, 0, 'v' },
109     { NULL, 0, 0, 0 }
110   };
111
112   int verbose;
113
114   int main(int argc, char *argv[]) {
115     cf_def_file = "default.cf";
116     int opt;
117     while((opt = cf_getopt(argc, argv, short_opts, long_opts, NULL)) >= 0)
118       switch(opt) {
119         case 'v': verbose = 1; break;
120         default: fprintf("Unknown option %c\n", opt); return 1;
121       }
122   }
123
124 The `short_opts` and `long_opts` variables describe the command line
125 arguments. Notice the `CF_SHORT_OPTS` and `CF_LONG_OPTS` macros. They
126 add the `-S` and `-C` options for the configuration parser as described
127 in <<config:>>. These options are handled internally by @cf_getopt().
128
129 You can rely on the configuration files having been loaded before the
130 first of your program's options is parsed.
131
132 [[deep]]
133 Getting deeper
134 --------------
135
136 Since the configuration system is somehow complicated, this part gives
137 you a little overview of what you can find and where.
138
139 [[reload]]
140 Reloading configuration
141 ~~~~~~~~~~~~~~~~~~~~~~~
142
143 The configuration system allows you to reload configuration at
144 runtime. The new config changes the values against the default values.
145 It means, if the default value for variable `A` is `10`, the currently
146 loaded config sets it to `42` and the new config does not talk about
147 this variable, `A` will have a value of `10` after a successful load.
148
149 Furthermore, if the loading of a new configuration fails, the current
150 configuration is preserved.
151
152 All this is done with <<journal,config journaling>>. The load of the
153 first config creates a journal entry. If you try to load some new
154 configuration, it is partially rolled back to defaults (the rollback
155 happens, but instead of removing the journal entry, another journal
156 entry is added for the rollback). If the loading succeeds, the two
157 journal entries are removed and a new one, for the new configuration,
158 is added. If it fails, the first one is replayed and the rollback
159 entry is removed.
160
161 See <<cf_reload()>>.
162
163 [[custom_parser]]
164 Creating custom parsers
165 ~~~~~~~~~~~~~~~~~~~~~~~
166
167 If you need to parse some data type the configuration system can't
168 handle, you can write your own parser. But before you start, you
169 should know a few things.
170
171 The parser needs to support <<journal,journaling>>. To accomplish that,
172 you have to use the <<alloc,configuration mempool>> for memory allocation.
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) and store the data in the second parameter. You may want to
177 write a dumper function, with signature of
178 <<type_cf_dumper1,`cf_dumper1`>> (needed for debug dumps).
179
180 Fill in a structure <<struct_cf_user_type,cf_user_type>> and use the
181 new data type in your configuration description with
182 <<def_CF_USER,`CF_USER`>> macro as its @t parameter.
183
184 You do not need to call @cf_journal_block() on the variable you store
185 the result. It is true you change it, but it was stored to journal
186 before your parser function was called.
187
188 [[hooks]]
189 Hooks
190 ~~~~~
191
192 The configuration system supports hooks. They are used to initialize the
193 configuration (if simple default value of variable is not enough) and
194 to check the sanity of loaded data.
195
196 Each hook is of type <<type_cf_hook,`cf_hook`>> and you can include
197 them in configuration description using <<def_CF_INIT,`CF_INIT`>> and
198 <<def_CF_COMMIT,`CF_COMMIT`>> macros.
199
200 The hooks should follow similar guidelines as custom parsers (well,
201 init hooks do not need to call @cf_journal_block()) to support
202 journaling. If you change nothing in the commit hook, you do not need
203 to care about the journaling either.
204
205 You may use the return value to inform about errors. Just return the
206 error message, or NULL if everything went well.
207
208 Another similar function is a copy function. It is very similar to a
209 hook and is used when the item is copied and is too complicated to use
210 simple memcpy(). Its type is <<type_cf_copier,`cf_copier`>> and is
211 specified by the <<def_CF_COPY,`CF_COPY`>> macro. It's return value is
212 the same as the one of a hook.
213
214 [[conf_h]]
215 ucw/conf.h
216 ----------
217
218 Use this file if you want define a configuration section, request
219 loading of some variables or create new item type.
220
221 !!ucw/conf.h
222
223 [[getopt_h]]
224 ucw/getopt.h
225 ------------
226
227 This header contains routines for parsing command line arguments and
228 loading the configuration.
229
230 !!ucw/getopt.h