libconfini
Yet another INI parser
|
What ./configure --without-io-api
does
Almost everything in libconfini is implemented from scratch, with the only notable exception of the I/O functions load_ini_file()
and load_ini_path()
, which rely on standard libraries – either the C Standard or the POSIX Standard, depending on the build settings. On some platforms, however, only a rather exotic I/O API is available, while for some other platforms the C Standard Library is simply too heavy or just not implementable.
In the past, the build environment of libconfini did not offer shortcuts for facing this kind of situations – although, thanks to the modularity of the source code, it was still relatively simple to get rid of every tie with the C Standard Library and compile libconfini as “bare metal”, with strip_ini_cache()
as the only parsing function (as this relies only on a buffer for its input), i.e. without load_ini_file()
and load_ini_path()
, and possibly even without including any header at all.
Starting from version 1.13.0 a “bare metal” version of libconfini has been made available by simply passing a --without-io-api
option to the configure
script. This modified version has the following characteristics:
char
buffers via strip_ini_cache()
)dev/hackings/baremetal/
subdirectoryWhen the configure
script is launched with the --without-io-api
option (or, equivalently, with --with-io-api=baremetal
), it assumes that no standard library at all could be present in the system. Hence it runs a series of tests and creates an inventory of what is present and what is not, in order to amend the source code accordingly – to ignore all the tests and assume that literally nothing from the C Standard Library is supported, use --without-libc
. The amendments are necessary (instead of just relying on the C preprocessor) because it is required to change the public header, not just the compiled code.
Only a very small amount of code in libconfini depends on the C Standard Library besides the I/O functions, so it is relatively easy to produce a “bare metal” fork with or without the latter. The dev/hackings/baremetal
subdirectory contains all the necessary amendments. These are automatically applied when launching make all
or make baremetal-source-code
after having launched ./configure --without-io-api
(the original source code will be preserved).
The str2num.c
file contains re-implementation of the functions ini_get_int()
, ini_get_lint()
, ini_get_llint()
, ini_get_float()
and ini_get_double()
, which in the original code are implemented as pointers to standard functions (see below). This file amends src/confini.c
.
The str2num.h
file, which amends src/confini.h
(i.e. the public header), exports the function headers of what str2num.c
implements.
The confini-header.c
file contains only a nominal workaround-amendment for src/confini.c
(for facilitating the build system) that does not change the final C code compiled.
To create the source code of a “bare metal” version of libconfini a fifth amendment to the public header is also required, containing some common C standard definitions. This amendment is automatically generated for each platform during the build process and will be located under no-dist/hackings/baremetal/c-standard-library.h
.
Here follows the summary of what is required by ./configure --without-io-api
:
dev/hackings/baremetal/confini-header.c
(pasted to the private module src/confini.c
)dev/hackings/baremetal/str2num.c
(pasted to the private module src/confini.c
)dev/hackings/baremetal/str2num.h
(pasted to the public header src/confini.h
)no-dist/hackings/baremetal/c-standard-library.h
(pasted to the public header src/confini.h
after having been automaticaly generated either by the configure
script, as an exact copy of dev/hackings/baremetal/c-standard-library.h
, or by make approve-revision
, in the few cases where manual user's intervention is required during the build process)The first four files (the ones located in the dev/hackings/baremetal
subdirectory) are static and do not need any intervention from the user, unless (s)he wants to participate in the development of libconfini. The fifth file might require manual intervention in some situations, depending on the platform or the user's will (the build system will emit a warning in such cases).
load_ini_file()
and load_ini_path()
for your platformWhether you are using the bare-metal version of libconfini for a regular computer, a fridge or a microwave oven, you might have eventually to deal with some kind of filesystem. If the C standard fopen()
, fseek()
, ftell()
, rewind()
, fread()
and fclose()
do not suit your needs, you can re-implement your own version of load_ini_file()
and load_ini_path()
. The only requirement is that at the end of the day you find a way to pass a disposable buffer containing an entire INI file to strip_ini_cache()
.
A good way to proceed is to hack the original pair of functions that rely on the C standard I/O API and adapt them to your platform:
If instead of using the --without-io-api
option you prefer to adapt the code manually, follow these simple steps (or adjust them according to your needs), which map verbatim what --without-io-api
does:
#include <stdio.h>
from confini.h
stddef.h
header (providing the typedef
for the size_t
data type) is available, add #include <stddef.h>
to confini.h
, otherwise provide your own implementation of the size_t
data typestdint.h
header (providing the typedef
for the int8_t
, uint8_t
, uint16_t
and uint32_t
data types) is not available, remove it from confini.h
and provide your own implementation of the int8_t
, uint8_t
, uint16_t
uint32_t
data typesload_ini_file()
and load_ini_path()
from both confini.h
and confini.c
stdlib.h
header is not available, remove #include <stdlib.h>
from confini.c
and remove the function pointers ini_get_int
, ini_get_lint
, ini_get_llint
and ini_get_double
from both confini.h
and confini.c
(you will have to use your own functions for converting strings to numbers) – for a set of possible replacements as actual functions instead of function pointers, please see below)After doing so libconfini will work even without a kernel.
As explained above, compiling libconfini without the C Standard Library requires getting rid of the function pointers ini_get_int()
, ini_get_lint()
, ini_get_llint()
and ini_get_double()
– as these are nothing but links to the standard functions atoi()
, atol()
, atoll()
and atof()
.
Instead of just removing these function pointers, it is also possible to provide novel functions implemented from scratch for parsing numbers.
What ./configure --without-io-api
does in fact is replacing in src/confini.h
the function pointers declared immediately after the comment /* PUBLIC LINKS */
with the following function headers:
The same configure
option amends in src/confini.c
(at the end of the file) the corresponding pointers with the code below. Note that the C language does not possess a templating mechanism, so the following code needs to rely on a macro for not repeating five times the same function body with only minimal variations.