This manual is for parse_conf library (version 1.0pre, 16 September 2008), the library to parse standard configuration files with string references resolution.
parse_conf is a library for parsing standard configuration or
initialization files and supports some extensions over the standard
syntax. It supports the separation of config files into different groups
and reading strings and numbers. The library is written in ANSI~C and
designed to be fine with C++. Originally (in 2002, 2004) it was designed
for reading initial values for scientific applications of special
type. It was rewritten and extended to be a flexible general purpose
library. Since version 1.0, a very extensive reference substitution
system is included into the library. The library is designed to be
thread-safety and you can read/write as many configuration files
simultaneously as you would like.
The configuration file consists of sections, led by a
[section] header and followed by name: value entries,
name=value is also accepted. You also can concatenate a string to
the previous value using name += value or name +: value
commands. Note that leading and ending whitespaces are removed from
string values and ignored from numeric values. To add a whitespace to a
string, the string should be quoted by quote " sign or you may
use \s and \t values for spaces and tabulations. The rest
of lines from # or ; are ignored and may be used to
provide comments.
Any variable definition can contain references to other values. See
documentation for the details. For example, to substitute the value from
variable a of the same group or from the global variables, one
may use $a reference or Pythonish %(a)s.
To install the library and pcnfdump utility to a standard location, use
./configure
make
su -c "make install"
In the case you installing it locally, use
./configure --prefix=/desired/location
make
make install
instead. Do not forget to change LIBRARY_PATH and C_INCLUDE_PATH accordingly to be able to reach the library. You can also generate tests if you wish by using --enable-tests option for configure.
parse_conf library reads a very common format for configuration
or initialization files that is widely used. However, many important
extensions are also supported. One of such an extension is a reference
substitutions feature. The configuration file consists of sections or
groups with variable string definitions (fields) that belong to
these sections. You can make references to other fields and the
library will substitute the values. You can reference to the variables
defined anywhere else in the configuration file.
Sections start with a section declaration like [section
name] on a separate line. Such a line must contain only this
declaration and possibly comments after it. All spaces around the
declaration are ignored. All spaces around the name of the section are
also ignored. Thus, [ section name ] is a valid declaration
equivalent to that does not have spaces around the name. Section names
can contain spaces between words and they are meaningful. Section
names are also case sensitive. Every section declaration ends the
previous section. More formally, the section name must start with an
alpha-numeric symbol and must end with an alpha-numeric symbol. Other
symbols can contain everything except a new line, (, ),
[, ], :, and =.
The global section is the only section that does not have a section declaration. Every variable defined before the first section declaration belongs to that global section (known also as a NULL section). Every configuration file contains at least one global section which may have no field in it. Thus, no section declaration are necessary in the configuration file. In such a file without section declarations, all variables belong to the global section.
All other lines can be used to read information from the configuration
file. These lines contain either signs : or = as a
separator of the variable (field name) and its definition line. It is
possible to have more : or = in the line which are
considered as a part of the definition line. The field also can use an
increment sign (either +: or +=). If used, the increment
sign will add the string to its previous value (concatenation) or will
be treated as a simple initialization if there were no such field was
defined before. Spaces around the definition line are ignored.
There are in the line that are treated
differently that usual signs. First of all, the backslash \ is
a control sign that changes the meaning of the succeeding
character. To type a \ itself one need to use
\\. \s represents a space and \t represents
tabulation. These signs are useful if definition line must contain
spaces at the beginning or the end due to spaces around the definition
line are ignored. Any appearance of \" are replaced by "
in the definition lines. This may be useful if your definition line
starts with ". You cannot use just this double quote "q
at the beginning of the line due to it will switch the input mode to
quoted definition lines. See Quoted Format. \ at the end of
the line (with possible spaces or comments followed) indicates that
the definition will continue at the next line. It is used to split
long lines. \# stays for #, and \; stays for
;.
Comments are any lines started with # or ;, or the
rest of any line from this sign unless (1) these signs appear inside
the quoted strings See Quoted Format, or (2) these signs appear in
a regular string and preceded by backslash \. See special sequences. Comments can appear in any part of your configuration
file. Any lines besides the comments, section names, and fields are
considered to be a syntax error. These lines will cause your program
to exit with an error message.
Field name or variable name is the part of a string before
first =, :, +=, or +: without leading and
trailing spaces. That is all leading and finishing spaces are deleted
from the line. The name convention for field names is the same as for
section names. See Sections.
Definition lines of the fields can contains references to other fields. In this case the library will substitute the value of referenced field instead of the reference.
To make a reference to a field x defined in the same section one
needs to use one of the following format: $x, $(x), or
%(x)s. All these references will first search for x
definition in the same section. If not found, the search will be made in
the global section. The last format is provided to make the library
capable to read configuration files provided for ConfigParser
Python module. The important difference from most of other libraries is
that the references can reference to the fields defined later in the
file.
You cannot use simple reference like $x if the name of the field
in the reference contains spaces or any characters besides
alpha-numeric, -, or _. For example to make a reference to
the field Three Words Field one can use $(Three Words
Field) or %(Three Words Field)s references only.
You can make a reference from one section to another. The form of such a
reference to a variable x in a section y can be
$x@y, $(x)@y, $x@[y], or in most general case
$(x)@[y]. The last form is suitable when both a field name and a
group name contain spaces in them. To make a reference to the global
section, one may use $x@ or $(x)@ form. In this case
x will not be searched in the local section first.
One need to use a special sequences to be able to use $,
%, and @ in their configuration files. They are
\\$, \\%, and \\@ correspondingly. Please notice
two backslashes, not one. It is because of the References Substitution
Rule. The first parsing replaces two backslashes by one.
One may ask what would happen if the field has been changed a few times in the file. To understand what happens in this case, one should understand how substitutions work. The parsing of the configuration file contains two independent stages. First, the configuration file is read without any substitutions and all references are treated as a plain text. This may be the last stage if you wish and use special flags for your library. See Interface. However, there may be the second stage of substitutions.
After the file initially parsed, every definition line is parsed for references. However, it may be not the same definition line as it was in the file. Thus, if you have a few definitions or increments of the same field, then the combined results will be parsed for references. Suppose you have in you ini-file:
field1 = Hello $x, field1 += \sBye $x.
Then the definition line to be parsed will be “Hello $x,
Bye $x”.
At the second stage the resolution does not care when the variable was defined. It parses and makes substitutions for the resulted definitions. The referenced fields can contain other references as well. The only evident exception is that no recursive references are allowed. If they occur, the library will notify about the error and will not resolve that references.
Quotes can be used in the field definition lines as below:
a = "This is a quoted definition line"If such a form is used, other special characters are defined.
#,
; can be used without \. In addition \" for a quote
is necessary. It is defined in a standard format as well but need to be
used there only if the string starts from a quote.
Continuing long lines is easy, just put a backslash \ at the end
of the definition line. You can put comments and spaces after this
backslash but nothing else. The following long definition is all
considered on one line:
SRC_FILES = application.cc \ # files to compile
filelister.cc menu\ # # a word split!
item.cc \
usepix.cc
Thus the field SRC_FILES will be defined as “application.cc
filelister.cc menuitem.cc usepix.cc”.
There is an example of simple initialization file:
default group string: "just a string"
[ INITIAL CONDITIONS ]
# velocity
v = 100.5 # km/s
n = 5.1 # 1/m^3
[ DATE ] # the date of the event
# What month is to be output (just a number, f.e. 4 is April)
Month = 3 #this value will be read
[ FILENAMES ]
# Kp and Ap index:
Kp, Ap data file: "2001KpAp.txt"
# Solar Activity
Solar wind data file: "ace_merge_25944.lst"
There are four sections in this file: global (or NULL) section,
INITIAL CONDITIONS, DATE, and FILENAMES.
Another example with references:
usr dir: /home/bubukin/usr
[programs]
bin = $(usr dir)/bin
include = $(usr dir)/include
The value of bin field will be /home/bubukin/usr/bin etc.
When you work with parse_conf library you should include a
description file first.
#include <parse_conf.h> /* C/C++ code */
The library is designed to be thread-safety and you can read/write as
many configuration files simultaneously as you would like. The special
handler type pcnf_t is defined in parse_conf.h. You
should declare a pointer to this type in your code to work with.
pcnf_t* pcnf;
Before working with the library you need to get a pcnf instance using
pcnf_alloc function:
pcnf_t *pcnf = pcnf_alloc();
As usual, the function would return NULL if memory allocation
would fail by any reason. When the work with the handler is finished,
it need to be freed with pcnf_free:
pcnf_free( pcnf );
Allocates a pointer to the instance of
pcnf_ttype. ReturnsNULLpointer on error.
Flags change the behavior of the library. There are following flags are defined:
If set (unset by default),
pcnf_dumpprints the configuration in quoted format. See Quoted Format.
If set (default), functions
pcnf_readandpcnf_appendwill resolve references in the field definition lines. You can usepcnf_resolvefunction later for references resolution, if this flag is not set.
To set or drop flags the following functions are used:
Sets the flags for pcnf to value flags. For example, to set quoted dump with
=as a field separator, usepcnf_flags_set( pcnf, PCNF_F_DUMP_QUOTED | PCNF_F_DUMP_EQUAL );
Drops the flags flags for pcnf. For example, to set unquoted dump, use
pcnf_flags_drop( pcnf, PCNF_F_DUMP_QUOTED );
To read/parse your configuration file you need to use pcnf_read
or pcnf_append functions. They are not different when called
first. However, the later one would append an additional information
from the second file read to your pcnf structure while
pcnf_read would clean the content before reading the next
file. Any of the function will fail if your configuration file
contains a syntax error. There is no reading from streams supported
at the moment due to the way error messages are reported.
Reads and parses the file filename. All previous values from the pcnf are removed. Function returns PCNF_OK on success.
Reads and parses the file filename. All previous values from the pcnf are saved unless they are replaced by same names from filename. As usual, += or := in the fields definitions from filename will increment values in pcnf, not replace them. Function returns PCNF_OK on success.
After you get your file into the pcnf structure, you can get field
values. All values are stored as stings in the pcnf structure. Integers
and floats are produced using atoi and atof functions.
Returns the pointer to the field value from section gname with filed name fname. You are not supposed to change it. Consider this as a constant string. To change the meaning of the field, use
pcnf_setorpcnf_incfunctions.
Returns the integer value from section gname with filed name fname.
Returns the double value of the field from section gname with filed name fname.
You can set different values if desired. It can be useful for generation configuration files. It also can be useful to replace some values in other configuration files or to resolve some undefined variables if you use your configuration files as templates.
Sets the string value of field fname in section gname to value. Function actually duplicates the string value.
Appends the string value to the value of the field fname in section gname.
Dumps the configuration into the stream fp. To print the configuration in a standard parse_conf format to the screen, use
pcnf_dump( pcnf, stdout );
which can be useful even for test what variables were read.
Removes all content from PCNF. It does not free the memory though.
Resolves all references. This function is useful when flag
PCNF_F_RESOLVE_REFSis not set. You can combine a few configuration files together and resolve cross references in them. Another application would be to provide a reference to the file with undefined references in it. For example, you can decide to use this if reference values can be known only during an execution time of your program.
After you properly installed the library, you can include the header in your program by
#include <parse_conf.h>
and compile it. To link your code against the library, you need
-lparse_conf flag for your linker. For example,
gcc <you_program_files> -lparse_conf -o program_name
pcnfdump Utility
pcnfdump is a utility to read the configuration file and dump its
content resolving references if necessary. It reads a configuration file
specified with -c option and outputs what it have read in some of
the standard format that parse_conf library can read. It is
useful to check the substitutions of references made. It also can be
used to generate simpler configuration files without references from
more general parse_conf library format.
Usage: pcnfdump -c input_file [-o output_file] [-xQnhV]
-x variable definitions with : instead of =
-Q variable definitions should be quoted
-n do not resolve references in definition lines
-V version and other information about the program
-h this usage message
\": Quoted Formatpcnf_alloc: Handler Allocationpcnf_append: Configuration Readingpcnf_clean: Cleaning Configurationpcnf_dump: Printing ConfigurationPCNF_F_DUMP_EQUAL: FlagsPCNF_F_DUMP_QUOTED: FlagsPCNF_F_RESOLVE_REFS: Flagspcnf_fget: Getting Field Valuespcnf_flags_drop: Flagspcnf_flags_set: Flagspcnf_free: Handler Allocationpcnf_iget: Getting Field Valuespcnf_inc: Setting Field Valuespcnf_read: Configuration Readingpcnf_resolve: Resolving Referencespcnf_set: Setting Field Valuespcnf_sget: Getting Field Valuespcnf_t: Handler Allocation