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>