Small configuration file parser library for C.

libConfuse

Travis Status Coverity Status

Introduction

libConfuse is a configuration file parser library written in C. It supports sections and (lists of) values, as well as other features such as single/double quoted strings, environment variable expansion, functions and nested include statements. Values can be strings, integers, floats, booleans, and sections.

The goal is not to be the configuration file parser library with a gazillion of features. Instead, it aims to be easy to use and quick to integrate with your code.

Please ensure you download a versioned archive from: https://github.com/libconfuse/libconfuse/releases/

Documentation

Examples

Build & Install

libConfuse employs the GNU configure and build system. To list available build options, start by unpacking the tarball:

tar xf confuse-3.2.2.tar.xz
cd confuse-3.2.2/
./configure --help

For most users the following commands configures, builds and installs the library to /usr/local/:

./configure && make -j9
sudo make install
sudo ldconfig

See the INSTALL file for the full installation instructions.

When checking out the code from GitHub, use ./autogen.sh to generate a configure script. This means you also need the following tools:

  • autoconf
  • automake
  • libtool
  • gettext
  • autopoint
  • flex

To build the documentation you also need the following tools:

  • doxygen
  • xmlto

This is an optional step, so you must build it explicitly from its directory:

cd doc/
make documentation

Origin & References

libConfuse was created by Martin Hedenfalk and released as open source software under the terms of the ISC license. It was previously called libcfg, but the name was changed to not confuse with other similar libraries. It is currently developed and maintained at GitHub. Please use the issue tracker to report bugs and feature requests.

Comments
  • Msvc autotools

    Msvc autotools

    Ok, with all the talk about AppVeyor/MSYS2 I decided to try to build libconfuse using the original MSYS (which I have installed, I don't have MSYS2) and MSVC 2010. I bumped into a number of difficulties, all of which I have solved in this branch. Except one, namely the C99 initializers from when the simple option union was introduced (57b9738acd5dd976bac95270885ec3532b18b553). I reverted that commit on top of this branch and I was able to build with my old tools like this:

    Open a MSVC 2010 command shell, and launch MSYS from it. From within the MSYS shell, do .../configure --disable-examples CC=cl CFLAGS=-MD RANLIB=: NM="dumpbin -symbols" AR=lib make make check

    Everything passes. I think the C99 initializers are supported by newer MSVC, so that particular problem will solve itself over time. Other than that, for projects that I maintain, I detest multiple build systems. Therefore, I very much favor supporting MSVC through autotools instead of project files that always ends up lagging behind.

    However, that puts Windows user in a position where they have to install MSYS. But the patches in this branch doesn't look all that nasty, most of them just shows that building with older MSVC hasn't been done in a while. Has anybody built with newer MSVC recently? And these patches doesn't stop anyone from keeping maintaining the windows project files...

    Anyway, it should be possible to add a build with MSYS/MSVC on AppVeyor. But someone has to verify that the work I put into automake/libtool to support MSYS/MSVC a couple of years ago works with MSYS2 as well, I can't really see why it would fail, but I wouldn't be surprised if there is some quirk to figure out...

    Cheers, Peter

  • funopen() unavailable in gcc-mingw-w64-x86-64

    funopen() unavailable in gcc-mingw-w64-x86-64

    In upgrading to libconfuse 3.1, I am now receiving the following error on mingw builds for Windows:

    libconfuse.a(libconfuse_la-fmemopen.o): In function `fmemopen':
    fmemopen.c:110: undefined reference to `funopen'
    

    This can be reproduced on Debian/Ubuntu by installing the mingw crosscompiler:

    sudo apt install gcc-mingw-w64-x86-64
    cd confuse
    CC=x86_64-w64-mingw32-gcc ./configure --enable-shared=no --disable-examples
    make
    

    Then try linking libconfuse.a to a trivial app. Since I never build the libconfuse examples in my Windows builds, I hadn't realized that they didn't compile with mingw, but in theory, they could show the issue too. If nothing else, you can see the warning the funopen isn't defined when compiling fmemopen.c.

    I'm not completely sure how best to work around this issue. In the past when I've run into uses of fmemopen, it has been pretty easy to remove them, but I don't think that's the case here. However, I also don't know how one would implement fmemopen without funopen. Hence I'm posting here to see if there are any other ideas.

  • Add feature to deprecate config options

    Add feature to deprecate config options

    We use libconfuse in tilda and often have the problem that we want to deprecate config options but this leads to problems:

    When the config option is still present in the config file (e.g. for upgrading users) then libconfuse throws an error and we need to reset the config.

    We are currently discussing if we replace libconfuse with another config library due to this, or if we are going to add a new feature to libconfuse. I would like to know if this project is still being actively maintained/developed and how likely it is that a patch will be accepted into libconfuse. If a patch would be accepted, then we might add a CFGF_DEPRECATED to the list of flags that causes libconfuse to ignore the config value and drop it when the config file is saved next. Possibly we could also split this into separate flags with a CFGF_DROP flag.

    Please let us know what your plans with libconfuse are and if we can somehow help you.

  • Add cfg_setmulti and cfg_opt_setmulti.

    Add cfg_setmulti and cfg_opt_setmulti.

    No PR in sight, that can't be right :-)

    From the commit message:

    Consider that you have a command line parser, and have parsed a line into tokens. It turns out that the first token, the command, is a 'set-cfg-variable' type of command and that the other tokens describe the new value, and possibly what variable to set.

    I.e. you are given a command "set foo-list bar gazonk zilch"

    and as a response to this command you want to set the "foo-list" option to { "bar", "gazonk", "zilch" }. There is no current API to do this in a simple maner, if you want to cover up for the possibility of syntax errors during parsing and arbitrary number of command line arguments.

    So, add cfg_setmulti (and cfg_opt_setmulti) to support this.

  • more compiling error on MSVC(MSVC6/MSVC2010).

    more compiling error on MSVC(MSVC6/MSVC2010).

    1. lexer.c not generated when compile use MSVC.
    2. issue for coding. --------------------Configuration: libConfuse - Win32 Debug-------------------- Compiling... confuse.c e:\github\libconfuse\src\confuse.c(838) : error C2059: syntax error : '.' e:\github\libconfuse\src\confuse.c(1123) : error C2065: 'ssize_t' : undeclared identifier e:\github\libconfuse\src\confuse.c(1123) : error C2146: syntax error : missing ';' before identifier 'n' e:\github\libconfuse\src\confuse.c(1123) : error C2065: 'n' : undeclared identifier e:\github\libconfuse\src\confuse.c(1124) : error C2143: syntax error : missing ';' before 'type' e:\github\libconfuse\src\confuse.c(1126) : error C2065: 'path' : undeclared identifier e:\github\libconfuse\src\confuse.c(1128) : error C2143: syntax error : missing ';' before 'type' e:\github\libconfuse\src\confuse.c(1137) : error C2065: 'np' : undeclared identifier e:\github\libconfuse\src\confuse.c(1139) : warning C4047: 'return' : 'char *' differs in levels of indirection from 'int ' e:\github\libconfuse\src\confuse.c(1145) : error C2079: 'st' uses undefined struct 'stat' e:\github\libconfuse\src\confuse.c(1325) : warning C4090: 'function' : different 'const' qualifiers e:\github\libconfuse\src\confuse.c(1325) : warning C4022: 'free' : pointer mismatch for actual parameter 1 e:\github\libconfuse\src\confuse.c(1329) : warning C4090: 'function' : different 'const' qualifiers e:\github\libconfuse\src\confuse.c(1329) : warning C4022: 'free' : pointer mismatch for actual parameter 1 Error executing cl.exe.

    libConfuse.dll - 9 error(s), 5 warning(s)

  • Unconditional call to setlocale() in cfg_init()

    Unconditional call to setlocale() in cfg_init()

    setlocale might interfere with what the app wants, and a followup setlocale call might destroy the returned string from a previous setlocale call (by the app).

  • confuse.mo no such file or directory - I am following the instructions for building - to no avail

    confuse.mo no such file or directory - I am following the instructions for building - to no avail

    I follow the instructions as per INSTALL document and do the following. I have Win 7 and git bash console.```

    invoke the git bash console.

    cd c:/python36/confuse-3.2 ./configure # goes through all the checking - takes about one minute creates various files. configure: creating ./config.status config.status: creating Makefile config.status: creating src/Makefile config.status: creating examples/Makefile config.status: creating po/Makefile.in config.status: creating m4/Makefile config.status: creating tests/Makefile config.status: creating doc/Makefile config.status: creating doc/Doxyfile config.status: creating libconfuse.pc config.status: creating libconfuse.spec config.status: creating config.h config.status: config.h is unchanged config.status: executing depfiles commands config.status: executing libtool commands config.status: executing po-directories commands config.status: creating po/POTFILES config.status: creating po/Makefile sh: __git_ps1: command not found`

    The last line sh: __git_ps1:command not found # I don't understand how this may assist me.

    $ make C:/mingw64/bin/make all-recursive make[1]: Entering directory 'C:/python36/confuse-3.2' Making all in m4 make[2]: Entering directory 'C:/python36/confuse-3.2/m4' make[2]: Nothing to be done for 'all'. make[2]: Leaving directory 'C:/python36/confuse-3.2/m4' Making all in po make[2]: Entering directory 'C:/python36/confuse-3.2/po' make[2]: Nothing to be done for 'all'. make[2]: Leaving directory 'C:/python36/confuse-3.2/po' Making all in src make[2]: Entering directory 'C:/python36/confuse-3.2/src' C:/Program Files/Git/usr/bin/sh.exe ../libtool --tag=CC --mode=compile gcc -DLOCALEDIR="/usr/local/share/locale" -DHAVE_CONFIG_H -I. -I.. -D_GNU_SOURCE -DBUILDING_DLL -g -O2 -MT libconfuse_la-confuse.lo -MD -MP -MF .deps/libconfuse_la-confuse.Tpo -c -o libconfuse_la-confuse.lo test -f 'confuse.c' || echo './'confuse.c /usr/bin/sh: C:/Program: No such file or directory make[2]: *** [makefile:479: libconfuse_la-confuse.lo] Error 127 make[2]: Leaving directory 'C:/python36/confuse-3.2/src' make[1]: *** [makefile:521: all-recursive] Error 1 make[1]: Leaving directory 'C:/python36/confuse-3.2' make: *** [makefile:407: all] Error 2 sh: __git_ps1: command not found

    Why do I get all these errors, "no such file or directory" and sh:__git_ps1 command not found when I got the *.zip package confuse-3.2.zip without modifying it?

    Thank you in advance, Anthony of Sydney

  • Fixes to tests to support mingw-w64 (Windows)

    Fixes to tests to support mingw-w64 (Windows)

    This pull request fixes all the tests that were failing because of differences between mingw-w64 (a GCC compiler for Windows) and Linux. When I combined this pull request with pull request #27, I got all the tests to pass in MSYS2.

  • Fix for #92 causes ABI break

    Fix for #92 causes ABI break

    0285479 introduced a new field comment in the middle of struct cfg_t which causes an ABI break.

    See

    • i3/i3status#224
    • https://bugs.debian.org/872078

    Seems #81 does not catch this.

  • Fix issue #33: Reindent to Linux coding style

    Fix issue #33: Reindent to Linux coding style

    This pull request reindents the code base to Linux coding style, as proposed in issue #33, skipping only the Windows specific code in windows/ and examples/wincfgtest.c.

    Signed-off-by: Joachim Nilsson [email protected]

  • Memory leak - failure to free lexer allocated memory.

    Memory leak - failure to free lexer allocated memory.

    Hey, I've stumbled across a possible memory leak - not sure whether it's intentional or not -

    It appears as if the free_cfg() library function neglects to free the yy_buffer_stack global variable.

    I externed the cfg_yylex_destroy() function and used it straight after calling to free_cfg() and the memory leak was gone.

  • Annotate cfg_error with format attribute

    Annotate cfg_error with format attribute

    Format attributes help compilers to warn on format string misuses, like:

    cfg_error(cfg, user_defined_input)  // potential security issue
    cfg_error(cfg, "foo %d", "bar")
    
    
    confuse.c:1246:20: warning: format string is not a string literal [-Wformat-nonliteral]
                    vfprintf(stderr, fmt, ap);
                                     ^~~
    

    Guard the annotation with __GNUC__, defined by GCC and Clang, which support the GNU extension of function format attributes.

    TODO: Untested on Windows.

  • `cfg_t *cfg_addtsec()`: can't return the pointer to the section if already exists

    `cfg_t *cfg_addtsec()`: can't return the pointer to the section if already exists

    Description

    cfg_t *cfg_addtsec(cfg_t *cfg, const char *name, const char *title) can't return the pointer to the section if already exists.

    Source Code Snippet

    Definition

    DLLIMPORT cfg_t *cfg_addtsec(cfg_t *cfg, const char *name, const char *title)
    {
    	cfg_opt_t *opt;
    	cfg_value_t *val;
    
    	if (cfg_gettsec(cfg, name, title))
    		return NULL;
    
    	opt = cfg_getopt(cfg, name);
    	if (!opt) {
    		cfg_error(cfg, _("no such option '%s'"), name);
    		return NULL;
    	}
    	val = cfg_setopt(cfg, opt, title);
    	if (!val)
    		return NULL;
    
    	val->section->path = cfg->path; /* Remember global search path. */
    	val->section->line = 1;
    	val->section->errfunc = cfg->errfunc;
    
    	return val->section;
    }
    

    Declaration

    Note: * @return A pointer to the created section or***if the section already exists a pointer to that section***is returned. If the section could not be created or found, 0 is returned.

    /** Create a new titled config section.
     *
     * @param cfg The configuration file context.
     * @param name The name of the option.
     * @param title The title of this section.
     *
     * @return A pointer to the created section or if the section
     * already exists a pointer to that section is returned.
     * If the section could not be created or found, 0 is returned.
     */
    DLLIMPORT cfg_t *cfg_addtsec(cfg_t *cfg, const char *name, const char *title);
    

    Possible Resolution

     DLLIMPORT cfg_t *cfg_addtsec(cfg_t *cfg, const char *name, const char *title)
     {
    +	cfg_t *sec;
     	cfg_opt_t *opt;
     	cfg_value_t *val;
    
    +	sec = cfg_gettsec(cfg, name, title);
    +	if (sec)
    +		return sec;
    -	if (cfg_gettsec(cfg, name, title))
    -		return NULL;
     
     	opt = cfg_getopt(cfg, name);
     	if (!opt) {
     		cfg_error(cfg, _("no such option '%s'"), name);
     		return NULL;
     	}
     	val = cfg_setopt(cfg, opt, title);
     	if (!val)
     		return NULL;
     
     	val->section->path = cfg->path; /* Remember global search path. */
     	val->section->line = 1;
     	val->section->errfunc = cfg->errfunc;
     
     	return val->section;
     }
    
  • Const-qualified parameters in exported functions

    Const-qualified parameters in exported functions

    Hi! I wonder if there is any chance to make const-qualification of parameters in some exported functions?

    For example, change cfg_getopt(cfg_t *cfg, const char *name); to cfg_getopt(const cfg_t *cfg, const char *name);.

    This will allow to write more const (pure) functions, especially in C++ projects. However, it will be require to change the error reporting function prototype from: typedef void (*cfg_errfunc_t)(cfg_t *cfg, const char *fmt, va_list ap); to typedef void (*cfg_errfunc_t)(const cfg_t *cfg, const char *fmt, va_list ap);

    While I see no reason to change cfg_t data inside the callback for custom error reporting, I suppose there might be use cases for this. The above changes may also break backward compatibility. But the tests of this project pass successfully after such changes on my local machine.

  • Format support in IDEs

    Format support in IDEs

    I think it would be great to have a general syntax highlighting direction. As a naive user I don't know what format to choose in VSCode. This could be solved by giving a general syntax highlighting direction in the README or create a plugin for mainstream IDEs. I assume that there is an existing format that is fundamentally compatible.

  • Comments aren't parsed correctly

    Comments aren't parsed correctly

    When a comment appears as part of list it fails to parse correctly. See an example below:

    targets = {
        "Life", # Comment
        "Universe",
        "Everything"
    }
    

    In this list, a comment appears along with one of the list items and fails with the error:

    simple.conf:1: unexpected token 'Comment'
    

    The lexer suggests,

     /*
      * handle one-line comments
      *
      * Note: Comments with lots of leading #### or //// are fully
      *       consumed and are not included in CFGT_COMMENT yylval
      */
    "#"{1,}.*   return qstr(cfg, '#', CFGT_COMMENT);
    "/"{2,}.*   return qstr(cfg, '/', CFGT_COMMENT);
    

    So I added extra '#' to see if this goes away. But it didn't.

    Sometimes in our usage, we do comment out a few configuration items or leave a comment next items. The new parser in 3.3 (master) seems to be also collecting comments for some reason.

    Note, we were using libConfuse version 3.0 and were planning to move to 3.3 owing to some memory leak fixes. But there seems to be some feature about CFGF_COMMENTS for which I can't seem to find proper documentation on to understand the rationale behind it.

    What is the right way to comment out or put comments inside of lists?

Related tags
Simple .INI file parser in C, good for embedded systems

inih (INI Not Invented Here) inih (INI Not Invented Here) is a simple .INI file parser written in C. It's only a couple of pages of code, and it was d

Sep 27, 2022
ini file parser

Iniparser 4 I - Overview This modules offers parsing of ini files from the C level. See a complete documentation in HTML format, from this directory o

Sep 25, 2022
Simple and lightweight pathname parser for C. This module helps to parse dirname, basename, filename and file extension .
Simple and lightweight pathname parser for C. This module helps to parse dirname, basename, filename and file extension .

Path Module For C File name and extension parsing functionality are removed because it's difficult to distinguish between a hidden dir (ex: .git) and

Feb 25, 2022
A PE parser written as an exercise to study the PE file structure.

Description A PE parser written as an exercise to study the PE file structure. It parses the following parts of PE32 and PE32+ files: DOS Header Rich

Sep 9, 2022
A TreeSitter parser for the Neorg File Format

NFF TreeSitter Parser A TreeSitter grammar for Neorg. Available Commands Command Result yarn installs needed dependencies (only do if you don't have t

Sep 7, 2022
A small and portable INI file library with read/write support

minIni minIni is a portable and configurable library for reading and writing ".INI" files. At just below 900 lines of commented source code, minIni tr

Sep 17, 2022
convert elf file to single c/c++ header file

elf-to-c-header Split ELF to single C/C++ header file

Nov 4, 2021
Parser for argv that works similarly to getopt

About Most command-line programs have to parse options, so there are a lot of different solutions to this problem. Some offer many features, while oth

Sep 25, 2022
tiny recursive descent expression parser, compiler, and evaluation engine for math expressions
tiny recursive descent expression parser, compiler, and evaluation engine for math expressions

TinyExpr TinyExpr is a very small recursive descent parser and evaluation engine for math expressions. It's handy when you want to add the ability to

Sep 27, 2022
MiniCalculator with a simple parser.
MiniCalculator with a simple parser.

MiniCalculator with a simple parser. This is a homework-expanded project. To learn something about parser and basic theory of programmi

Oct 9, 2021
Very fast Markdown parser and HTML generator implemented in WebAssembly, based on md4c

Very fast Markdown parser and HTML generator implemented in WebAssembly, based on md4c

Oct 2, 2022
A simple YAML parser which produces a Node Tree Object representation of YAML Documents

A simple YAML parser which produces a Node Tree Object representation of YAML Documents and includes a find method to locate individual Nodes within the parsed Node Tree.

Sep 18, 2022
A markdown parser for tree-sitter

tree-sitter-markdown A markdown parser for tree-sitter Progress: Leaf blocks Thematic breaks ATX headings Setext headings Indented code blocks Fenced

Sep 28, 2022
Small header-only C++ library that helps to initialize Vulkan instance and device object

Vulkan Extensions & Features Help, or VkExtensionsFeaturesHelp, is a small, header-only, C++ library for developers who use Vulkan API.

Apr 13, 2022
libparser is a small C library that parses input based on a precompiled context-free grammar.

libparser is a small C library that parses input based on a precompiled context-free grammar.

Jul 19, 2022
Small Header only library to parse argv for flags

Small Header only library to parse argv for flags

Dec 8, 2021
A linux library to get the file path of the currently running shared library. Emulates use of Win32 GetModuleHandleEx/GetModuleFilename.

whereami A linux library to get the file path of the currently running shared library. Emulates use of Win32 GetModuleHandleEx/GetModuleFilename. usag

Sep 24, 2022
A small self-contained alternative to readline and libedit

Linenoise A minimal, zero-config, BSD licensed, readline replacement used in Redis, MongoDB, and Android. Single and multi line editing mode with the

Sep 22, 2022
A small proxy DLL which enables dev. console in Mass Effect 1, 2 and 3 (Legendary Edition).
A small proxy DLL which enables dev. console in Mass Effect 1, 2 and 3 (Legendary Edition).

LEBinkProxy A small proxy DLL which enables dev. console in Mass Effect 1, 2 and 3 (Legendary Edition). Usage In your game binary directory (Game\ME?\

Jan 6, 2022