X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=inline;f=ucw%2Fdoc%2Fconf.txt;h=777dbe10facca83e30255028803bca7296a2a71b;hb=f1155256f7a168f5e2c0097cb4e7197b79c4f041;hp=2bc7cf081e0b75ca88ff0b73fd8c1ea18dd42794;hpb=8cb58409406045bf50c67f4b0988a2e7b189b550;p=libucw.git diff --git a/ucw/doc/conf.txt b/ucw/doc/conf.txt index 2bc7cf08..777dbe10 100644 --- a/ucw/doc/conf.txt +++ b/ucw/doc/conf.txt @@ -1,55 +1,53 @@ -Configuration and command line parser -===================================== +Configuration parser +==================== -Libucw contains a parser for configuration files described in -<>. +Libucw contains a parser for configuration files. The syntax of the +configuration files is described in <>, here we explain the +interface of the parser. -The principle is you specify the structure of the configuration file, -the section names, variable names and types and your C variables that -are assigned to them. Then you run the parser and it fills your -variables with the values from the configuration file. +Basically, you write a description of the configuration file syntax, +which maps configuration items to variables of your program. Then +Then you run the parser and it fills your variables with the values +from the configuration file. -It is modular. It means you do not have to write all configuration at -the same place, you just declare the parts you need locally and do not -care about the other parts. - -The command line parser has the same interface as unix getopt_long(), -but handles setting of configuration files and configuration values -from command line. +The descriptions are modular. The configuration can be split to sections, +each section declared at a separate place. You can also define your own +data types. - <> * <> - * <> + * <> - <> * <> * <> * <> * <> - <> + * <> + * <> * <> * <> * <> * <> * <> * <> -- <> - * <> * <> * <> - * <> - * <> +- <> + * <> (obsolete) + * <> (obsolete) [[example]] Example ------- If you want to just load simple configuration, this is the part you want to read. This simple example should give you the overview. Look -into the <> section to see list of +at the <> section to see list of supported data types, sections, etc. [[ex_cfile]] -Let's say you have configuration file with this content and want to -load it: +Suppose you have configuration file with the following content and you +want to load it: HelloWorld { Text "Hello planet" @@ -83,54 +81,45 @@ it exists. } The variables are used to store the loaded values. Their initial -values work as default, if nothing else is loaded. The hw_config() +values work as defaults, if nothing else is loaded. The hw_config() structure assigns the variables to configuration names. The hw_init() function (because of the `CONSTRUCTOR` macro) is run before main() -is called and it plugs in the whole section to the parser (alternatively, +is called and it tells the parser that the section exists (alternatively, you can call @cf_declare_section() at the start of your main()). You can plug in as many configuration sections as you like, from various places across your code. [[ex_load]] -Loading of the values +Loading configuration ~~~~~~~~~~~~~~~~~~~~~ -Suppose you need to parse the command line arguments and load the -configuration. Then @cf_getopt() is there for you: it works like -the the traditional @getopt() from the C library, but it also handles -configuration files. +You can load the configuration explicitly by calling @cf_load(). +That can be convenient when writing a library, but in normal programs, +you can ask the <> to handle it for you. - #include - #include - #include +A typical example follows, please see the <> for details. - static char short_opts[] = CF_SHORT_OPTS "v"; - static struct option long_opts[] = { - CF_LONG_OPTS - { "verbose", 0, 0, 'v' }, - { NULL, 0, 0, 0 } + #include + #include + + static struct opt_section options = { + OPT_ITEMS { + // More options can be specified here + OPT_HELP("Configuration options:"), + OPT_CONF_OPTIONS, + OPT_END + } }; - - static int verbose; - - int main(int argc, char *argv[]) { + + int main(int argc, char **argv) + { cf_def_file = "default.cf"; - int opt; - while((opt = cf_getopt(argc, argv, short_opts, long_opts, NULL)) >= 0) - switch(opt) { - case 'v': verbose = 1; break; - default: fprintf("Unknown option %c\n", opt); return 1; - } + opt_parse(&options, argv+1); + // Configuration file is already loaded here + return 0; } -The `short_opts` and `long_opts` variables describe the command line -arguments. Notice the `CF_SHORT_OPTS` and `CF_LONG_OPTS` macros. They -add the `-S` and `-C` options for the configuration parser as described -in <>. These options are handled internally by @cf_getopt(). - -You can rely on the configuration files having been loaded before the -first of your program's options is parsed. - [[deep]] Getting deeper -------------- @@ -152,11 +141,11 @@ are three ways to do that: + For example, you can have an static array of five unsigned integers: + - static uns array = { 1, 2, 3, 4, 5 }; + static uint array[] = { 1, 2, 3, 4, 5 }; + static struct cf_section section = { CF_ITEMS { - CF_UNS_ARY("array", array, 5), + CF_UINT_ARY("array", array, 5), CF_END } }; @@ -164,9 +153,8 @@ For example, you can have an static array of five unsigned integers: *Dynamic arrays*:: Similar to static array, but you provide pointer to pointer to the given item (eg. if you want dynamic array of - integers, you give `**int`). The parser allocates an array of needed - size. You can use the <> macro to find out - the number of elements actually loaded. + integers, you give `**int`). The parser allocates a <> + of the required size. + If you want dynamic array of strings, you would use: + @@ -180,20 +168,21 @@ If you want dynamic array of strings, you would use: }; *Lists*:: - Linked lists based on <>. You provide description + Linked lists based on <>. You provide description of single node and pointer to the - <> variable. All the nodes will + <> variable. All the nodes will be created dynamically and put there. + -First element of your structure must be <>. +First element of your structure must be <>. + -The first example is list of strings and uses <>: - struct clist list; ++ + static struct clist list; + static struct cf_section section = { CF_ITEMS { - CF_LIST("list", &list, &cf_string_list_cofnig), + CF_LIST("list", &list, &cf_string_list_config), CF_END } }; @@ -214,7 +203,7 @@ this variable, `A` will have a value of `10` after a successful load. Furthermore, if the loading of a new configuration fails, the current configuration is preserved. -All this is done with <>. The load of the +All this is done with <>. The load of the first config creates a journal entry. If you try to load some new configuration, it is partially rolled back to defaults (the rollback happens, but instead of removing the journal entry, another journal @@ -223,7 +212,7 @@ journal entries are removed and a new one, for the new configuration, is added. If it fails, the first one is replayed and the rollback entry is removed. -See <>. +See @cf_reload(). [[custom_parser]] Creating custom parsers @@ -233,7 +222,7 @@ If you need to parse some data type the configuration system can't handle, you can write your own parser. But before you start, you should know a few things. -The parser needs to support <>. To accomplish that, +The parser needs to support <>. To accomplish that, you have to use the <> for memory allocation. Now, you need a function with the same signature as @@ -264,8 +253,8 @@ them in configuration description using <> and The hooks should follow similar guidelines as custom parsers (well, init hooks do not need to call @cf_journal_block()) to support -journaling. If you change nothing in the commit hook, you do not need -to care about the journaling either. +journalling. If you change nothing in the commit hook, you do not need +to care about the journalling either. You may use the return value to inform about errors. Just return the error message, or NULL if everything went well. @@ -280,8 +269,7 @@ the same as the one of a hook. ucw/conf.h ---------- -Use this file if you want define a configuration section, request -loading of some variables or create new item type. +This header file contains the public interface of the configuration module. !!ucw/conf.h @@ -290,6 +278,47 @@ ucw/getopt.h ------------ This header contains routines for parsing command line arguments and -loading the configuration. +loading the default configuration. + +In new programs, please consider using the new <> +instead. The getopt interface is already considered obsolete and may +be removed in the future. !!ucw/getopt.h + +Example +~~~~~~~ +Typically, @cf_getopt() is used as follows: it works like +the traditional @getopt_long() from the C library, but it also handles +configuration files. + + #include + #include + #include + + static char short_opts[] = CF_SHORT_OPTS "v"; + static struct option long_opts[] = { + CF_LONG_OPTS + { "verbose", 0, 0, 'v' }, + { NULL, 0, 0, 0 } + }; + + static int verbose; + + int main(int argc, char *argv[]) { + cf_def_file = "default.cf"; + int opt; + while((opt = cf_getopt(argc, argv, short_opts, long_opts, NULL)) >= 0) + switch(opt) { + case 'v': verbose = 1; break; + default: fprintf("Unknown option %c\n", opt); return 1; + } + } + +The `short_opts` and `long_opts` variables describe the command line +arguments. Notice the `CF_SHORT_OPTS` and `CF_LONG_OPTS` macros. They +add the `-S` and `-C` options for the configuration parser as described +in <>. These options are handled internally by @cf_getopt(). + +You can rely on the configuration files having been loaded before the +first of your program's options is parsed.