Annotation of embedaddon/confuse/doc/tutorial.xml, revision 1.1.1.2
1.1 misho 1: <?xml version="1.0" standalone="no"?>
2: <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
3: "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
4: [
5: <!ENTITY listing1 SYSTEM "listing1.xml">
6: <!ENTITY listing2 SYSTEM "listing2.xml">
7: <!ENTITY listing3 SYSTEM "listing3.xml">
8: <!ENTITY listing4 SYSTEM "listing4.xml">
9: <!ENTITY listing5 SYSTEM "listing5.xml">
10: <!ENTITY listing6 SYSTEM "listing6.xml">
11: <!ENTITY listing7 SYSTEM "listing7.xml">
12: <!ENTITY listing8 SYSTEM "listing8.xml">
13: ]>
14: <article>
15: <articleinfo>
16: <title>libConfuse tutorial</title>
17: <author><firstname>Martin</firstname> <surname>Hedenfalk</surname></author>
18: </articleinfo>
19: <sect1>
20: <title>Introducing libConfuse in an existing program</title>
21: <para>Consider this simple program:</para>
22: &listing1;
23: <para>
24: Simple enough, but we want to extend the program so we can greet
25: others. Maybe we don't want to greet the whole world, just our
26: neighbour. We use libConfuse to let the user decide whom to greet.
27: </para>
28: &listing2;
29: <para>
30: All programs using libConfuse must first include the
31: <filename>confuse.h</filename> header file. This is done on line
32: 2.
33: </para>
34: <para>
35: On line 6 - 10, the options that should be recognized are defined in an
36: array of cfg_opt_t structs. This is passed to the
37: <function>cfg_init</function> function on line 13. The resulting
38: <structname>cfg_t</structname> context is used by
39: <function>cfg_parse()</function>, which reads the configuration file
40: "hello.conf". When reading the configuration file, only options defined in
41: the array of options passed to <function>cfg_init()</function> are
42: recognized.
43: </para>
44: <para>
45: The friendly greeting is now replaced with a parameter read from the
46: configuration file. The value of the <varname>target</varname> option is retrieved with
47: <function>cfg_getstr(cfg, "target")</function>.
48: </para>
49: <para>
50: Lets take a look at the configuration file hello.conf:
51: </para>
52:
53: <programlisting>
54: # this is the configuration file for the hello program
55:
56: target = "Neighbour"
57: </programlisting>
58: <para>
59: Here, the target option is set to the string value "Neighbour".
60: What if the configuration file was empty or didn't exist? Then the
61: default value for the <varname>target</varname> option would be
62: used. When we initialized our options, the second parameter to the
63: <function>CFG_STR()</function> macro specified the default value.
64: Thus, if no <varname>target</varname> option was specified in the
65: configuration file, the hello program would have printed the
66: standard greeting "Hello, World".
67: </para>
68:
69: <sect2>
70: <title>Environment variables in values</title>
71:
72: <para>
73: What else can we do in the configuration file? We can set the value to an
74: environment variable:
75: </para>
76: <programlisting>
77: target = ${USER}
78: </programlisting>
79: <para>
80: This results in the hello program greeting the user who runs it. On some
81: systems, the USER variable might not be available, so we want to specify a
82: default value in those cases:
83: </para>
84: <programlisting>
85: target = ${USER:-User}
86: </programlisting>
87: <para>
88: Now, if the USER environment variable is unset, the string "User" will be
89: used instead.
90: </para>
91: </sect2>
92: </sect1>
93: <sect1>
94: <title>Other types of options</title>
95:
96: <para>
97: Of course, not only strings can be specified in the configuration file.
98: libConfuse can parse strings, integers, booleans and floating point values.
99: These are the fundamental values, and they are all also available as lists.
100: We'll talk more about lists in the next chapter.
101: </para>
102: <para>
103: The macros used to initialize a string, integer, boolean and a
104: float is, respectively, <function>CFG_STR()</function>,
105: <function>CFG_INT()</function>, <function>CFG_BOOL()</function>,
106: <function>CFG_FLOAT()</function> and
107: <function>CFG_PTR()</function>. All macros take three parameters:
108: the name of the option, a default value and flags. To retrieve the
109: values, use <function>cfg_getstr()</function>,
110: <function>cfg_getint()</function>,
111: <function>cfg_getbool()</function>,
112: <function>cfg_getfloat()</function> or
113: <function>cfg_getptr()</function>, respectively.
114: </para>
115: <para>
116: Let's introduce an integer option that tells us how many times to print the
117: greeting:
118: </para>
119: &listing3;
120: <para>
121: Here we have used the <function>CFG_INT()</function> macro to
122: initialize an integer option named "repeat". The default value is 1
123: as in the standard greeting. The value is retrieved with
124: <function>cfg_getint()</function>.
125: </para>
126: <para id="negative-repeat-problem">
127: But, wait a moment, what if the user specified a negative value for
128: "repeat"? Or a too large positive value? libConfuse can handle
129: that with a so-called validating callback. We'll come back to this
130: problem later on, but we will first take a look at lists.
131: </para>
132: </sect1>
133:
134: <sect1>
135: <title>Introducing lists</title>
136:
137: <para>
138: That was easy. Now let's extend the program a bit so we can greet more than one
139: "target". We'd like to be able to specify a list of targets to greet.
140: </para>
141: <para>
142: The list versions of the initialization macros are named
143: <function>CFG_STR_LIST()</function>,
144: <function>CFG_INT_LIST()</function>,
145: <function>CFG_BOOL_LIST()</function> and
146: <function>CFG_FLOAT_LIST()</function>. They take the same
147: parameters as the non-list versions, except the default value must
148: be a string surrounded by curly braces.
149: </para>
150: <para>
151: The modified program is shown below:
152: </para>
153: &listing4;
154: <para>
155: Three things are a bit different here. First, the macro to
156: initialize the "targets" option is
157: <function>CFG_STR_LIST()</function>. This tells libConfuse that
158: "targets" is a list of strings. Second, the default value in the
159: second parameter is surrounded by curly braces. This is needed to
160: indicate to libConfuse where the list of values ends.
161: </para>
162: <para>
163: The third change is in the printing of the greeting. First we print
164: the "Hello" string. Then we loop through all values found for the
165: "targets" option. The number of values is retrieved with the
166: <function>cfg_size()</function> function. The string values are
167: then retrieved with <function>cfg_getnstr()</function>, which is an
168: indexed version of <function>cfg_getstr()</function>. In fact,
169: <function>cfg_getstr()</function> is equivalent to
170: <function>cfg_getnstr()</function> with an index of zero.
171: </para>
172: <para>
173: In the configuration file hello.conf, we can now specify a list of targets to
174: greet:
175: </para>
176: <programlisting>
177: # this is the configuration file for the hello program
178:
179: targets = {"Life", "Universe", "Everything"}
180: repeat = 1
181: </programlisting>
182: <para>
183: The output of the hello program, run with the above configuration file, is:
184: "Hello, Life, Universe, Everything!"
185: </para>
186: <para>
187: Again, if no targets were configured, the greeting would have been the standard
188: "Hello, World!".
189: </para>
190:
191: </sect1>
192: <sect1>
193: <title>Using sections</title>
194:
195: <para>
196: So far, we have only use a flat configuration file. libConfuse can also handle
197: sections to build a hierarchy of options. Sections can be used to group options
198: in logical blocks, and those blocks can (optionally) be specified multiple
199: times.
200: </para>
201: <para>
202: Sections are initialized with the <function>CFG_SEC()</function> macro. It also takes three
203: parameters: the name of the option, an array of options allowed in the section
204: and flags.
205: </para>
206: <para>
207: We'll extend the, now rather complex, hello program so we can do other kinds of
208: greetings, not just "Hello". Each greeting will have its own settings for
209: targets and repeat.
210: </para>
211: &listing5;
212: <para>
213: We have renamed the option array from "opts" to "greet_opts", and introduced a
214: new "opts" array that only has one option: a "greeting" section.
215: The second parameter of the <function>CFG_SEC()</function> macro
216: points to the old greeting options "targets" and "repeat".
217: </para>
218: <para>
219: We have also used a couple of flags to alter the behaviour of the
220: section: CFGF_TITLE means that a greeting section should have a
221: title and the CFGF_MULTI flag tells libConfuse that this section
222: may be specified multiple times in the configuration file. The
223: title of a section is retrieved with the
224: <function>cfg_title()</function> function.
225: </para>
226: <para>
227: The outmost loop (with index j) now loops through all given
228: sections in the configuration file. We retrieve a section with a
229: <function>cfg_getnsec()</function> call. The value returned is a
230: pointer to a cfg_t struct, the same type as returned by
231: <function>cfg_init()</function>. Thus we can use the ordinary value
232: retrieval functions <function>cfg_getstr()</function>,
233: <function>cfg_getint()</function> and so on to retrieve values of
234: options inside the section.
235: </para>
236: <para>
237: Ok, so how does the configuration file look like for this setup?
238: </para>
239: <programlisting>
240: # this is the configuration file for the hello program
241:
242: greeting Hello
243: {
244: targets = {"Life", "Universe", "Everything"}
245: repeat = 1
246: }
247:
248: greeting Bye
249: {
250: targets = {Adams}
251: repeat = 1
252: }
253: </programlisting>
254: <para>
255: The program will loop through the sections in the order specified
256: in the configuration file. First it will find the "Hello" section.
257: It prints the title of the section, "Hello", retrieved with
258: <function>cfg_title()</function>. Then the targets are printed just
1.1.1.2 ! misho 259: as in the previous examples, but this time the values are retrieved
1.1 misho 260: from the cfg_greet section. Next, the section titled "Bye" is
261: found, and the values are retrieved from that section.
262: </para>
263: <para>
264: When run, the program produces the following:
265: </para>
266: <programlisting>
267: $ ./listing5
268: Hello, Life, Universe, Everything!
269: Bye, Adams!
270: $
271: </programlisting>
272:
273: </sect1>
274: <sect1>
275: <title>Parsing from internal buffers</title>
276: <para>
277: So far, we have only parsed configuration data from files.
278: libConfuse can also parse buffers, or in-memory character
279: strings. We will use this to fix a problem in the previous code.
280: </para>
281: <para>
282: The problem is that without a configuration file, the hello program
283: will not print anything. We want it to at least print the standard
284: greeting "Hello, World!" if no configuration file is available.
285: </para>
286: <para>
287: We can't have a default value for a section that can be specified
288: multiple times (ie, a section with the CFGF_MULTI flag set).
289: Instead we will parse a default configuration string if no section
290: has been parsed:
291: </para>
292: &listing6;
293: <para>
294: Only the changes from the previous code is shown here. We check if
295: the size of the "greeting" section is zero (ie, no section has been
296: defined). In that case we call <function>cfg_parse_buf()</function>
297: to parse a default in-memory string "greeting Hello {}". This
298: string defines a greeting section with title Hello, but without any
299: sub-options. This way we rely on the default values of the
300: (sub-)options "targets" and "repeat".
301: </para>
302: <para>
303: When this program is run, it issues the well-known standard greeting
304: "Hello, World!" if no configuration file is present.
305: </para>
306: </sect1>
307:
308: <sect1>
309: <title>Validating callback functions</title>
310: <para>
311: Remember the problem about a negative or too large "repeat" value
312: in <xref linkend="negative-repeat-problem"/>? The code that prints
313: the greeting has those lines:
314: </para>
315: <programlisting>
316: ...
317: repeat = cfg_getint(cfg_greet, "repeat");
318: while(repeat--)
319: ...
320: </programlisting>
321: <para>
322: The repeat variable is defined as an int, a signed integer. If the user
323: specified a negative repeat value in the configuration file, this code
324: would continue to decrease the repeat variable until it eventually
325: underflowed.
326: </para>
327: <para>
328: We'll fix this by not allowing a negative value in the configuration
329: file. Of course we could first just check if the value is negative
330: and then abort, using <function>cfg_getint()</function> and a test.
331: But we will use a validating callback function instead. This way
332: <function>cfg_parse()</function> will return an error directly when
333: parsing the file, additionally indicating on which line the error
334: is.
335: </para>
336: <para>
337: A validating callback function is defined as:
338: </para>
339: <programlisting>
340: typedef int (*cfg_validate_callback_t)(cfg_t *cfg, cfg_opt_t *opt);
341: </programlisting>
342: <para>
343: This function takes two arguments: the section and the option. It
344: should return 0 on success (ie, the value validated ok). All other
345: values indicates an error, and the parsing is aborted. The callback
346: function should notify the error itself, for example by calling
347: <function>cfg_error()</function>.
348: </para>
349: <para>
350: Here is the code for the callback function:
351: </para>
352: &listing7;
353: <para>
354: Only the last value is validated, because libConfuse will call this
355: function once for every value corresponding to the option. Since
356: the "repeat" option is not a list, we could instead have used
357: <function>cfg_opt_getint(opt)</function> to retrieve the only
358: value. However, if we later want to use this callback to validate
359: an integer list, it is already lists-aware.
360: </para>
361:
362: <sect2>
363: <title>Installing the callback</title>
364: <para>
365: The validating callback is installed with
366: <function>cfg_set_validate_func()</function>. It is called with
367: a string specifying which option is affected, and a pointer to
368: the callback function. To specify an option in a subsection,
369: the section and the option must be separated with a vertical
370: bar ("|").
371: </para>
372: <para>
373: We're now also looking at the return code from
374: <function>cfg_parse()</function> to verify that the parsing was
375: successful. The complete program is now:
376: </para>
377: &listing8;
378: </sect2>
379: </sect1>
380:
381: <sect1>
382: <title>Value parsing callback</title>
383: <para>
384: A value parsing callback is another kind of callback function
385: available in libConfuse. This function is used to map a string into
1.1.1.2 ! misho 386: some other value. One example is to extend a boolean option
1.1 misho 387: to accept the values "yes", "no" and "ask" (or perhaps "true",
388: "false" and "maybe"). Those values should be mapped to the integers
389: 1, 2 and 3.
390: </para>
391: <programlisting>
392: typedef int (*cfg_callback_t)(cfg_t *cfg, cfg_opt_t *opt,
393: const char *value, void *result);
394: </programlisting>
395: <para>
396:
397: </para>
398: </sect1>
399:
400: <sect1>
401: <title>Functions</title>
402: <para>
403: libConfuse supports functions to parse options that does not fit
404: well in the general syntax. Functions can be called with a variable
405: number of arguments. No data from the function or any arguments are
406: stored by libConfuse after the function has run. It is up to the caller
407: to process and/or save the data.
408: </para>
409: <para>
410: A function is defined with a <function>CFG_FUNC</function> macro.
411: It takes two arguments: the name of the function and a function
412: callback. The callback is defined as:
413: </para>
414: <programlisting>
415: typedef int (*cfg_func_t)(cfg_t *cfg, cfg_opt_t *opt,
416: int argc, const char **argv);
417: </programlisting>
418: <para>
419: </para>
420:
421: <sect2>
422: <title>Predefined functions</title>
423: <para>
424: Currently there is only one pre-defined function:
425: <function>cfg_include()</function>. This function includes
426: another configuration file. Configuration data is immediately
427: read from the included file, and is returned to the position
428: right after the include() statement upon end of file.
429: </para>
430: <para>
431: To use this function, include a <function>CFG_FUNC()</function>
432: entry in your options:
433: </para>
434: <programlisting>
435: cfg_opt_t opts[] = {
436: CFG_FUNC("include", cfg_include),
437: CFG_END()
438: };
439: </programlisting>
440: <para>
441: In the configuration file, it is used in the following way:
442: </para>
443: <programlisting>
444: include("included.conf")
445: </programlisting>
446: </sect2>
447: </sect1>
448:
449: <sect1>
450: <title>Saving configuration files</title>
451: <para>
452: </para>
453:
454: <sect2>
455: <title>Altering the printing of certain options</title>
456: <para>
457: </para>
458: </sect2>
459: </sect1>
460:
461: </article>
462:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>