--- /dev/null
+From 8acdbd718b7828b5d8903a6254b2fa198b866491 Mon Sep 17 00:00:00 2001
+From: Florian Bezdeka <florian.bezdeka@siemens.com>
+Date: Thu, 12 Nov 2020 11:45:28 +0000
+Subject: [PATCH] lib/boilerplate/iniparser: Allow building with GCC 10.2
+ 2020101
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Updating to upstream revision f858275f7f307eecba84c2f5429483f9f28007f8.
+Upstream repository is located at [1].
+
+The reason for updating was the following compiler error when trying
+to compile with GCC 10.2 10.2.1 20201016. As it turned out the problem
+was already addressed upstream:
+
+iniparser/iniparser.c: In function ‘iniparser_load’:
+iniparser/iniparser.c:616:13: error: ‘sprintf’ arguments 3, 4 may
+overlap destination object ‘buf’ [-Werror=restrict]
+ 616 | sprintf(tmp, "%s:%s", section, key);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+I reviewed especially the API changes. Most of them are cleanups only
+but two things should be pointed out:
+
+ - The type of the size field of struct _dictionary_ changed from int
+ to ssize_t. The only user of this struct is
+ lib/analogy/calibration.c which uses this structure for internal
+ things only. It is never exposed to any public API so updating is
+ OK and fully backward compatible.
+
+ - dictionary_new changed its signature
+ from dictionary_new(int size)
+ to dictionary_new(size_t size).
+ This function is not part of any public API. So updating does not
+ break backward compatibility.
+
+[1] https://github.com/ndevilla/iniparser
+
+Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+
+[Retrieved from:
+https://gitlab.denx.de/Xenomai/xenomai/-/commit/8acdbd718b7828b5d8903a6254b2fa198b866491]
+Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
+---
+ lib/boilerplate/iniparser/dictionary.c | 409 ++++++++++----------
+ lib/boilerplate/iniparser/dictionary.h | 43 ++-
+ lib/boilerplate/iniparser/iniparser.c | 491 +++++++++++++++++--------
+ lib/boilerplate/iniparser/iniparser.h | 131 +++++--
+ 4 files changed, 646 insertions(+), 428 deletions(-)
+
+diff --git a/lib/boilerplate/iniparser/dictionary.c b/lib/boilerplate/iniparser/dictionary.c
+index 5299b77ed..cb7ccd49e 100644
+--- a/lib/boilerplate/iniparser/dictionary.c
++++ b/lib/boilerplate/iniparser/dictionary.c
+@@ -1,10 +1,8 @@
+ /*-------------------------------------------------------------------------*/
+ /**
+- @file dictionary.c
+- @author N. Devillard
+- @date Sep 2007
+- @version $Revision: 1.27 $
+- @brief Implements a dictionary for string variables.
++ @file dictionary.c
++ @author N. Devillard
++ @brief Implements a dictionary for string variables.
+
+ This module implements a simple dictionary object, i.e. a list
+ of string/string associations. This object is useful to store e.g.
+@@ -12,12 +10,8 @@
+ */
+ /*--------------------------------------------------------------------------*/
+
+-/*
+- $Id: dictionary.c,v 1.27 2007-11-23 21:39:18 ndevilla Exp $
+- $Revision: 1.27 $
+-*/
+ /*---------------------------------------------------------------------------
+- Includes
++ Includes
+ ---------------------------------------------------------------------------*/
+ #include "dictionary.h"
+
+@@ -27,33 +21,18 @@
+ #include <unistd.h>
+
+ /** Maximum value size for integers and doubles. */
+-#define MAXVALSZ 1024
++#define MAXVALSZ 1024
+
+ /** Minimal allocated number of entries in a dictionary */
+-#define DICTMINSZ 128
++#define DICTMINSZ 128
+
+ /** Invalid key token */
+ #define DICT_INVALID_KEY ((char*)-1)
+
+ /*---------------------------------------------------------------------------
+- Private functions
++ Private functions
+ ---------------------------------------------------------------------------*/
+
+-/* Doubles the allocated size associated to a pointer */
+-/* 'size' is the current allocated size. */
+-static void * mem_double(void * ptr, int size)
+-{
+- void * newptr ;
+-
+- newptr = calloc(2*size, 1);
+- if (newptr==NULL) {
+- return NULL ;
+- }
+- memcpy(newptr, ptr, size);
+- free(ptr);
+- return newptr ;
+-}
+-
+ /*-------------------------------------------------------------------------*/
+ /**
+ @brief Duplicate a string
+@@ -67,23 +46,68 @@ static void * mem_double(void * ptr, int size)
+ static char * xstrdup(const char * s)
+ {
+ char * t ;
++ size_t len ;
+ if (!s)
+ return NULL ;
+- t = malloc(strlen(s)+1) ;
++
++ len = strlen(s) + 1 ;
++ t = (char*) malloc(len) ;
+ if (t) {
+- strcpy(t,s);
++ memcpy(t, s, len) ;
+ }
+ return t ;
+ }
+
++/*-------------------------------------------------------------------------*/
++/**
++ @brief Double the size of the dictionary
++ @param d Dictionary to grow
++ @return This function returns non-zero in case of failure
++ */
++/*--------------------------------------------------------------------------*/
++static int dictionary_grow(dictionary * d)
++{
++ char ** new_val ;
++ char ** new_key ;
++ unsigned * new_hash ;
++
++ new_val = (char**) calloc(d->size * 2, sizeof *d->val);
++ new_key = (char**) calloc(d->size * 2, sizeof *d->key);
++ new_hash = (unsigned*) calloc(d->size * 2, sizeof *d->hash);
++ if (!new_val || !new_key || !new_hash) {
++ /* An allocation failed, leave the dictionary unchanged */
++ if (new_val)
++ free(new_val);
++ if (new_key)
++ free(new_key);
++ if (new_hash)
++ free(new_hash);
++ return -1 ;
++ }
++ /* Initialize the newly allocated space */
++ memcpy(new_val, d->val, d->size * sizeof(char *));
++ memcpy(new_key, d->key, d->size * sizeof(char *));
++ memcpy(new_hash, d->hash, d->size * sizeof(unsigned));
++ /* Delete previous data */
++ free(d->val);
++ free(d->key);
++ free(d->hash);
++ /* Actually update the dictionary */
++ d->size *= 2 ;
++ d->val = new_val;
++ d->key = new_key;
++ d->hash = new_hash;
++ return 0 ;
++}
++
+ /*---------------------------------------------------------------------------
+- Function codes
++ Function codes
+ ---------------------------------------------------------------------------*/
+ /*-------------------------------------------------------------------------*/
+ /**
+- @brief Compute the hash key for a string.
+- @param key Character string to use for key.
+- @return 1 unsigned int on at least 32 bits.
++ @brief Compute the hash key for a string.
++ @param key Character string to use for key.
++ @return 1 unsigned int on at least 32 bits.
+
+ This hash function has been taken from an Article in Dr Dobbs Journal.
+ This is normally a collision-free function, distributing keys evenly.
+@@ -93,84 +117,88 @@ static char * xstrdup(const char * s)
+ /*--------------------------------------------------------------------------*/
+ unsigned dictionary_hash(const char * key)
+ {
+- int len ;
+- unsigned hash ;
+- int i ;
+-
+- len = strlen(key);
+- for (hash=0, i=0 ; i<len ; i++) {
+- hash += (unsigned)key[i] ;
+- hash += (hash<<10);
+- hash ^= (hash>>6) ;
+- }
+- hash += (hash <<3);
+- hash ^= (hash >>11);
+- hash += (hash <<15);
+- return hash ;
++ size_t len ;
++ unsigned hash ;
++ size_t i ;
++
++ if (!key)
++ return 0 ;
++
++ len = strlen(key);
++ for (hash=0, i=0 ; i<len ; i++) {
++ hash += (unsigned)key[i] ;
++ hash += (hash<<10);
++ hash ^= (hash>>6) ;
++ }
++ hash += (hash <<3);
++ hash ^= (hash >>11);
++ hash += (hash <<15);
++ return hash ;
+ }
+
+ /*-------------------------------------------------------------------------*/
+ /**
+- @brief Create a new dictionary object.
+- @param size Optional initial size of the dictionary.
+- @return 1 newly allocated dictionary objet.
++ @brief Create a new dictionary object.
++ @param size Optional initial size of the dictionary.
++ @return 1 newly allocated dictionary objet.
+
+ This function allocates a new dictionary object of given size and returns
+ it. If you do not know in advance (roughly) the number of entries in the
+ dictionary, give size=0.
+ */
+-/*--------------------------------------------------------------------------*/
+-dictionary * dictionary_new(int size)
++/*-------------------------------------------------------------------------*/
++dictionary * dictionary_new(size_t size)
+ {
+- dictionary * d ;
+-
+- /* If no size was specified, allocate space for DICTMINSZ */
+- if (size<DICTMINSZ) size=DICTMINSZ ;
+-
+- if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) {
+- return NULL;
+- }
+- d->size = size ;
+- d->val = (char **)calloc(size, sizeof(char*));
+- d->key = (char **)calloc(size, sizeof(char*));
+- d->hash = (unsigned int *)calloc(size, sizeof(unsigned));
+- return d ;
++ dictionary * d ;
++
++ /* If no size was specified, allocate space for DICTMINSZ */
++ if (size<DICTMINSZ) size=DICTMINSZ ;
++
++ d = (dictionary*) calloc(1, sizeof *d) ;
++
++ if (d) {
++ d->size = size ;
++ d->val = (char**) calloc(size, sizeof *d->val);
++ d->key = (char**) calloc(size, sizeof *d->key);
++ d->hash = (unsigned*) calloc(size, sizeof *d->hash);
++ }
++ return d ;
+ }
+
+ /*-------------------------------------------------------------------------*/
+ /**
+- @brief Delete a dictionary object
+- @param d dictionary object to deallocate.
+- @return void
++ @brief Delete a dictionary object
++ @param d dictionary object to deallocate.
++ @return void
+
+ Deallocate a dictionary object and all memory associated to it.
+ */
+ /*--------------------------------------------------------------------------*/
+ void dictionary_del(dictionary * d)
+ {
+- int i ;
+-
+- if (d==NULL) return ;
+- for (i=0 ; i<d->size ; i++) {
+- if (d->key[i]!=NULL)
+- free(d->key[i]);
+- if (d->val[i]!=NULL)
+- free(d->val[i]);
+- }
+- free(d->val);
+- free(d->key);
+- free(d->hash);
+- free(d);
+- return ;
++ ssize_t i ;
++
++ if (d==NULL) return ;
++ for (i=0 ; i<d->size ; i++) {
++ if (d->key[i]!=NULL)
++ free(d->key[i]);
++ if (d->val[i]!=NULL)
++ free(d->val[i]);
++ }
++ free(d->val);
++ free(d->key);
++ free(d->hash);
++ free(d);
++ return ;
+ }
+
+ /*-------------------------------------------------------------------------*/
+ /**
+- @brief Get a value from a dictionary.
+- @param d dictionary object to search.
+- @param key Key to look for in the dictionary.
++ @brief Get a value from a dictionary.
++ @param d dictionary object to search.
++ @param key Key to look for in the dictionary.
+ @param def Default value to return if key not found.
+- @return 1 pointer to internally allocated character string.
++ @return 1 pointer to internally allocated character string.
+
+ This function locates a key in a dictionary and returns a pointer to its
+ value, or the passed 'def' pointer if no such key can be found in
+@@ -178,24 +206,24 @@ void dictionary_del(dictionary * d)
+ dictionary object, you should not try to free it or modify it.
+ */
+ /*--------------------------------------------------------------------------*/
+-const char * dictionary_get(dictionary * d, const char * key, const char * def)
++const char * dictionary_get(const dictionary * d, const char * key, const char * def)
+ {
+- unsigned hash ;
+- int i ;
++ unsigned hash ;
++ ssize_t i ;
+
+- hash = dictionary_hash(key);
+- for (i=0 ; i<d->size ; i++) {
++ hash = dictionary_hash(key);
++ for (i=0 ; i<d->size ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+ /* Compare hash */
+- if (hash==d->hash[i]) {
++ if (hash==d->hash[i]) {
+ /* Compare string, to avoid hash collisions */
+ if (!strcmp(key, d->key[i])) {
+- return d->val[i] ;
+- }
+- }
+- }
+- return def ;
++ return d->val[i] ;
++ }
++ }
++ }
++ return def ;
+ }
+
+ /*-------------------------------------------------------------------------*/
+@@ -226,66 +254,57 @@ const char * dictionary_get(dictionary * d, const char * key, const char * def)
+ /*--------------------------------------------------------------------------*/
+ int dictionary_set(dictionary * d, const char * key, const char * val)
+ {
+- int i ;
+- unsigned hash ;
+-
+- if (d==NULL || key==NULL) return -1 ;
+-
+- /* Compute hash for this key */
+- hash = dictionary_hash(key) ;
+- /* Find if value is already in dictionary */
+- if (d->n>0) {
+- for (i=0 ; i<d->size ; i++) {
++ ssize_t i ;
++ unsigned hash ;
++
++ if (d==NULL || key==NULL) return -1 ;
++
++ /* Compute hash for this key */
++ hash = dictionary_hash(key) ;
++ /* Find if value is already in dictionary */
++ if (d->n>0) {
++ for (i=0 ; i<d->size ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+- if (hash==d->hash[i]) { /* Same hash value */
+- if (!strcmp(key, d->key[i])) { /* Same key */
+- /* Found a value: modify and return */
+- if (d->val[i]!=NULL)
+- free(d->val[i]);
+- d->val[i] = val ? xstrdup(val) : NULL ;
++ if (hash==d->hash[i]) { /* Same hash value */
++ if (!strcmp(key, d->key[i])) { /* Same key */
++ /* Found a value: modify and return */
++ if (d->val[i]!=NULL)
++ free(d->val[i]);
++ d->val[i] = (val ? xstrdup(val) : NULL);
+ /* Value has been modified: return */
+- return 0 ;
+- }
+- }
+- }
+- }
+- /* Add a new value */
+- /* See if dictionary needs to grow */
+- if (d->n==d->size) {
+-
+- /* Reached maximum size: reallocate dictionary */
+- d->val = (char **)mem_double(d->val, d->size * sizeof(char*)) ;
+- d->key = (char **)mem_double(d->key, d->size * sizeof(char*)) ;
+- d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ;
+- if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) {
+- /* Cannot grow dictionary */
+- return -1 ;
++ return 0 ;
++ }
++ }
+ }
+- /* Double size */
+- d->size *= 2 ;
+- }
++ }
++ /* Add a new value */
++ /* See if dictionary needs to grow */
++ if (d->n==d->size) {
++ /* Reached maximum size: reallocate dictionary */
++ if (dictionary_grow(d) != 0)
++ return -1;
++ }
+
+- /* Insert key in the first empty slot */
+- for (i=0 ; i<d->size ; i++) {
+- if (d->key[i]==NULL) {
+- /* Add key here */
+- break ;
+- }
++ /* Insert key in the first empty slot. Start at d->n and wrap at
++ d->size. Because d->n < d->size this will necessarily
++ terminate. */
++ for (i=d->n ; d->key[i] ; ) {
++ if(++i == d->size) i = 0;
+ }
+- /* Copy key */
+- d->key[i] = xstrdup(key);
+- d->val[i] = val ? xstrdup(val) : NULL ;
+- d->hash[i] = hash;
+- d->n ++ ;
+- return 0 ;
++ /* Copy key */
++ d->key[i] = xstrdup(key);
++ d->val[i] = (val ? xstrdup(val) : NULL) ;
++ d->hash[i] = hash;
++ d->n ++ ;
++ return 0 ;
+ }
+
+ /*-------------------------------------------------------------------------*/
+ /**
+- @brief Delete a key in a dictionary
+- @param d dictionary object to modify.
+- @param key Key to remove.
++ @brief Delete a key in a dictionary
++ @param d dictionary object to modify.
++ @param key Key to remove.
+ @return void
+
+ This function deletes a key in a dictionary. Nothing is done if the
+@@ -294,26 +313,26 @@ int dictionary_set(dictionary * d, const char * key, const char * val)
+ /*--------------------------------------------------------------------------*/
+ void dictionary_unset(dictionary * d, const char * key)
+ {
+- unsigned hash ;
+- int i ;
++ unsigned hash ;
++ ssize_t i ;
+
+- if (key == NULL) {
+- return;
+- }
++ if (key == NULL || d == NULL) {
++ return;
++ }
+
+- hash = dictionary_hash(key);
+- for (i=0 ; i<d->size ; i++) {
++ hash = dictionary_hash(key);
++ for (i=0 ; i<d->size ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+ /* Compare hash */
+- if (hash==d->hash[i]) {
++ if (hash==d->hash[i]) {
+ /* Compare string, to avoid hash collisions */
+ if (!strcmp(key, d->key[i])) {
+ /* Found key */
+ break ;
+- }
+- }
+- }
++ }
++ }
++ }
+ if (i>=d->size)
+ /* Key not found */
+ return ;
+@@ -331,75 +350,31 @@ void dictionary_unset(dictionary * d, const char * key)
+
+ /*-------------------------------------------------------------------------*/
+ /**
+- @brief Dump a dictionary to an opened file pointer.
+- @param d Dictionary to dump
+- @param out Opened file pointer.
+- @return void
++ @brief Dump a dictionary to an opened file pointer.
++ @param d Dictionary to dump
++ @param f Opened file pointer.
++ @return void
+
+ Dumps a dictionary onto an opened file pointer. Key pairs are printed out
+ as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
+ output file pointers.
+ */
+ /*--------------------------------------------------------------------------*/
+-void dictionary_dump(dictionary * d, FILE * out)
++void dictionary_dump(const dictionary * d, FILE * out)
+ {
+- int i ;
+-
+- if (d==NULL || out==NULL) return ;
+- if (d->n<1) {
+- fprintf(out, "empty dictionary\n");
+- return ;
+- }
+- for (i=0 ; i<d->size ; i++) {
++ ssize_t i ;
++
++ if (d==NULL || out==NULL) return ;
++ if (d->n<1) {
++ fprintf(out, "empty dictionary\n");
++ return ;
++ }
++ for (i=0 ; i<d->size ; i++) {
+ if (d->key[i]) {
+ fprintf(out, "%20s\t[%s]\n",
+ d->key[i],
+ d->val[i] ? d->val[i] : "UNDEF");
+ }
+- }
+- return ;
+-}
+-
+-
+-/* Test code */
+-#ifdef TESTDIC
+-#define NVALS 20000
+-int main(int argc, char *argv[])
+-{
+- dictionary * d ;
+- char * val ;
+- int i ;
+- char cval[90] ;
+-
+- /* Allocate dictionary */
+- printf("allocating...\n");
+- d = dictionary_new(0);
+-
+- /* Set values in dictionary */
+- printf("setting %d values...\n", NVALS);
+- for (i=0 ; i<NVALS ; i++) {
+- sprintf(cval, "%04d", i);
+- dictionary_set(d, cval, "salut");
+- }
+- printf("getting %d values...\n", NVALS);
+- for (i=0 ; i<NVALS ; i++) {
+- sprintf(cval, "%04d", i);
+- val = dictionary_get(d, cval, DICT_INVALID_KEY);
+- if (val==DICT_INVALID_KEY) {
+- printf("cannot get value for key [%s]\n", cval);
+- }
+- }
+- printf("unsetting %d values...\n", NVALS);
+- for (i=0 ; i<NVALS ; i++) {
+- sprintf(cval, "%04d", i);
+- dictionary_unset(d, cval);
+- }
+- if (d->n != 0) {
+- printf("error deleting values\n");
+ }
+- printf("deallocating...\n");
+- dictionary_del(d);
+- return 0 ;
++ return ;
+ }
+-#endif
+-/* vim: set ts=4 et sw=4 tw=75 */
+diff --git a/lib/boilerplate/iniparser/dictionary.h b/lib/boilerplate/iniparser/dictionary.h
+index fa4dcb727..d04b6ce71 100644
+--- a/lib/boilerplate/iniparser/dictionary.h
++++ b/lib/boilerplate/iniparser/dictionary.h
+@@ -3,8 +3,6 @@
+ /**
+ @file dictionary.h
+ @author N. Devillard
+- @date Sep 2007
+- @version $Revision: 1.12 $
+ @brief Implements a dictionary for string variables.
+
+ This module implements a simple dictionary object, i.e. a list
+@@ -13,18 +11,11 @@
+ */
+ /*--------------------------------------------------------------------------*/
+
+-/*
+- $Id: dictionary.h,v 1.12 2007-11-23 21:37:00 ndevilla Exp $
+- $Author: ndevilla $
+- $Date: 2007-11-23 21:37:00 $
+- $Revision: 1.12 $
+-*/
+-
+ #ifndef _DICTIONARY_H_
+ #define _DICTIONARY_H_
+
+ /*---------------------------------------------------------------------------
+- Includes
++ Includes
+ ---------------------------------------------------------------------------*/
+
+ #include <stdio.h>
+@@ -32,14 +23,18 @@
+ #include <string.h>
+ #include <unistd.h>
+
++#ifdef __cplusplus
++extern "C" {
++#endif
++
+ /*---------------------------------------------------------------------------
+- New types
++ New types
+ ---------------------------------------------------------------------------*/
+
+
+ /*-------------------------------------------------------------------------*/
+ /**
+- @brief Dictionary object
++ @brief Dictionary object
+
+ This object contains a list of string/string associations. Each
+ association is identified by a unique string key. Looking up values
+@@ -48,16 +43,16 @@
+ */
+ /*-------------------------------------------------------------------------*/
+ typedef struct _dictionary_ {
+- int n ; /** Number of entries in dictionary */
+- int size ; /** Storage size */
+- char ** val ; /** List of string values */
+- char ** key ; /** List of string keys */
+- unsigned * hash ; /** List of hash values for keys */
++ int n ; /** Number of entries in dictionary */
++ ssize_t size ; /** Storage size */
++ char ** val ; /** List of string values */
++ char ** key ; /** List of string keys */
++ unsigned * hash ; /** List of hash values for keys */
+ } dictionary ;
+
+
+ /*---------------------------------------------------------------------------
+- Function prototypes
++ Function prototypes
+ ---------------------------------------------------------------------------*/
+
+ /*-------------------------------------------------------------------------*/
+@@ -85,7 +80,7 @@ unsigned dictionary_hash(const char * key);
+ dictionary, give size=0.
+ */
+ /*--------------------------------------------------------------------------*/
+-dictionary * dictionary_new(int size);
++dictionary * dictionary_new(size_t size);
+
+ /*-------------------------------------------------------------------------*/
+ /**
+@@ -112,7 +107,7 @@ void dictionary_del(dictionary * vd);
+ dictionary object, you should not try to free it or modify it.
+ */
+ /*--------------------------------------------------------------------------*/
+-const char * dictionary_get(dictionary * d, const char * key, const char * def);
++const char * dictionary_get(const dictionary * d, const char * key, const char * def);
+
+
+ /*-------------------------------------------------------------------------*/
+@@ -161,7 +156,7 @@ void dictionary_unset(dictionary * d, const char * key);
+ /**
+ @brief Dump a dictionary to an opened file pointer.
+ @param d Dictionary to dump
+- @param out Opened file pointer.
++ @param f Opened file pointer.
+ @return void
+
+ Dumps a dictionary onto an opened file pointer. Key pairs are printed out
+@@ -169,6 +164,10 @@ void dictionary_unset(dictionary * d, const char * key);
+ output file pointers.
+ */
+ /*--------------------------------------------------------------------------*/
+-void dictionary_dump(dictionary * d, FILE * out);
++void dictionary_dump(const dictionary * d, FILE * out);
++
++#ifdef __cplusplus
++}
++#endif
+
+ #endif
+diff --git a/lib/boilerplate/iniparser/iniparser.c b/lib/boilerplate/iniparser/iniparser.c
+index 5b2094a00..f1d165896 100644
+--- a/lib/boilerplate/iniparser/iniparser.c
++++ b/lib/boilerplate/iniparser/iniparser.c
+@@ -3,19 +3,12 @@
+ /**
+ @file iniparser.c
+ @author N. Devillard
+- @date Sep 2007
+- @version 3.0
+ @brief Parser for ini files.
+ */
+ /*--------------------------------------------------------------------------*/
+-/*
+- $Id: iniparser.c,v 2.18 2008-01-03 18:35:39 ndevilla Exp $
+- $Revision: 2.18 $
+- $Date: 2008-01-03 18:35:39 $
+-*/
+ /*---------------------------- Includes ------------------------------------*/
+ #include <ctype.h>
+-#include <errno.h>
++#include <stdarg.h>
+ #include "iniparser.h"
+
+ /*---------------------------- Defines -------------------------------------*/
+@@ -39,65 +32,115 @@ typedef enum _line_status_ {
+
+ /*-------------------------------------------------------------------------*/
+ /**
+- @brief Convert a string to lowercase.
+- @param s String to convert.
+- @return ptr to statically allocated string.
+-
+- This function returns a pointer to a statically allocated string
+- containing a lowercased version of the input string. Do not free
+- or modify the returned string! Since the returned string is statically
+- allocated, it will be modified at each function call (not re-entrant).
++ @brief Convert a string to lowercase.
++ @param in String to convert.
++ @param out Output buffer.
++ @param len Size of the out buffer.
++ @return ptr to the out buffer or NULL if an error occured.
++
++ This function convert a string into lowercase.
++ At most len - 1 elements of the input string will be converted.
+ */
+ /*--------------------------------------------------------------------------*/
+-
+-static char strbuf[ASCIILINESZ+1];
+-
+-static char * strlwc(const char * s)
++static const char * strlwc(const char * in, char *out, unsigned len)
+ {
+- int i ;
++ unsigned i ;
+
+- if (s==NULL) return NULL ;
+- memset(strbuf, 0, ASCIILINESZ+1);
++ if (in==NULL || out == NULL || len==0) return NULL ;
+ i=0 ;
+- while (s[i] && i<ASCIILINESZ) {
+- strbuf[i] = (char)tolower((int)s[i]);
++ while (in[i] != '\0' && i < len-1) {
++ out[i] = (char)tolower((int)in[i]);
+ i++ ;
+ }
+- strbuf[ASCIILINESZ]=(char)0;
+- return strbuf ;
++ out[i] = '\0';
++ return out ;
++}
++
++/*-------------------------------------------------------------------------*/
++/**
++ @brief Duplicate a string
++ @param s String to duplicate
++ @return Pointer to a newly allocated string, to be freed with free()
++
++ This is a replacement for strdup(). This implementation is provided
++ for systems that do not have it.
++ */
++/*--------------------------------------------------------------------------*/
++static char * xstrdup(const char * s)
++{
++ char * t ;
++ size_t len ;
++ if (!s)
++ return NULL ;
++
++ len = strlen(s) + 1 ;
++ t = (char*) malloc(len) ;
++ if (t) {
++ memcpy(t, s, len) ;
++ }
++ return t ;
++}
++
++/*-------------------------------------------------------------------------*/
++/**
++ @brief Remove blanks at the beginning and the end of a string.
++ @param str String to parse and alter.
++ @return unsigned New size of the string.
++ */
++/*--------------------------------------------------------------------------*/
++static unsigned strstrip(char * s)
++{
++ char *last = NULL ;
++ char *dest = s;
++
++ if (s==NULL) return 0;
++
++ last = s + strlen(s);
++ while (isspace((int)*s) && *s) s++;
++ while (last > s) {
++ if (!isspace((int)*(last-1)))
++ break ;
++ last -- ;
++ }
++ *last = (char)0;
++
++ memmove(dest,s,last - s + 1);
++ return last - s;
++}
++
++/*-------------------------------------------------------------------------*/
++/**
++ @brief Default error callback for iniparser: wraps `fprintf(stderr, ...)`.
++ */
++/*--------------------------------------------------------------------------*/
++static int default_error_callback(const char *format, ...)
++{
++ int ret;
++ va_list argptr;
++ va_start(argptr, format);
++ ret = vfprintf(stderr, format, argptr);
++ va_end(argptr);
++ return ret;
+ }
+
++static int (*iniparser_error_callback)(const char*, ...) = default_error_callback;
++
+ /*-------------------------------------------------------------------------*/
+ /**
+- @brief Remove blanks at the beginning and the end of a string.
+- @param s String to parse.
+- @return ptr to statically allocated string.
+-
+- This function returns a pointer to a statically allocated string,
+- which is identical to the input string, except that all blank
+- characters at the end and the beg. of the string have been removed.
+- Do not free or modify the returned string! Since the returned string
+- is statically allocated, it will be modified at each function call
+- (not re-entrant).
++ @brief Configure a function to receive the error messages.
++ @param errback Function to call.
++
++ By default, the error will be printed on stderr. If a null pointer is passed
++ as errback the error callback will be switched back to default.
+ */
+ /*--------------------------------------------------------------------------*/
+-static char * strstrip(const char * s)
++void iniparser_set_error_callback(int (*errback)(const char *, ...))
+ {
+- char * last ;
+-
+- if (s==NULL) return NULL ;
+-
+- while (isspace((int)*s) && *s) s++;
+- memset(strbuf, 0, ASCIILINESZ+1);
+- strcpy(strbuf, s);
+- last = strbuf + strlen(strbuf);
+- while (last > strbuf) {
+- if (!isspace((int)*(last-1)))
+- break ;
+- last -- ;
+- }
+- *last = (char)0;
+- return (char*)strbuf ;
++ if (errback) {
++ iniparser_error_callback = errback;
++ } else {
++ iniparser_error_callback = default_error_callback;
++ }
+ }
+
+ /*-------------------------------------------------------------------------*/
+@@ -118,7 +161,7 @@ static char * strstrip(const char * s)
+ This function returns -1 in case of error.
+ */
+ /*--------------------------------------------------------------------------*/
+-int iniparser_getnsec(dictionary * d)
++int iniparser_getnsec(const dictionary * d)
+ {
+ int i ;
+ int nsec ;
+@@ -149,7 +192,7 @@ int iniparser_getnsec(dictionary * d)
+ This function returns NULL in case of error.
+ */
+ /*--------------------------------------------------------------------------*/
+-const char * iniparser_getsecname(dictionary * d, int n)
++const char * iniparser_getsecname(const dictionary * d, int n)
+ {
+ int i ;
+ int foundsec ;
+@@ -184,7 +227,7 @@ const char * iniparser_getsecname(dictionary * d, int n)
+ purposes mostly.
+ */
+ /*--------------------------------------------------------------------------*/
+-void iniparser_dump(dictionary * d, FILE * f)
++void iniparser_dump(const dictionary * d, FILE * f)
+ {
+ int i ;
+
+@@ -212,13 +255,11 @@ void iniparser_dump(dictionary * d, FILE * f)
+ It is Ok to specify @c stderr or @c stdout as output files.
+ */
+ /*--------------------------------------------------------------------------*/
+-void iniparser_dump_ini(dictionary * d, FILE * f)
++void iniparser_dump_ini(const dictionary * d, FILE * f)
+ {
+- int i, j ;
+- char keym[ASCIILINESZ+1];
+- int nsec ;
+- const char * secname ;
+- int seclen ;
++ int i ;
++ int nsec ;
++ const char * secname ;
+
+ if (d==NULL || f==NULL) return ;
+
+@@ -234,24 +275,126 @@ void iniparser_dump_ini(dictionary * d, FILE * f)
+ }
+ for (i=0 ; i<nsec ; i++) {
+ secname = iniparser_getsecname(d, i) ;
+- seclen = (int)strlen(secname);
+- fprintf(f, "\n[%s]\n", secname);
+- sprintf(keym, "%s:", secname);
+- for (j=0 ; j<d->size ; j++) {
+- if (d->key[j]==NULL)
+- continue ;
+- if (!strncmp(d->key[j], keym, seclen+1)) {
+- fprintf(f,
+- "%-30s = %s\n",
+- d->key[j]+seclen+1,
+- d->val[j] ? d->val[j] : "");
+- }
++ iniparser_dumpsection_ini(d, secname, f);
++ }
++ fprintf(f, "\n");
++ return ;
++}
++
++/*-------------------------------------------------------------------------*/
++/**
++ @brief Save a dictionary section to a loadable ini file
++ @param d Dictionary to dump
++ @param s Section name of dictionary to dump
++ @param f Opened file pointer to dump to
++ @return void
++
++ This function dumps a given section of a given dictionary into a loadable ini
++ file. It is Ok to specify @c stderr or @c stdout as output files.
++ */
++/*--------------------------------------------------------------------------*/
++void iniparser_dumpsection_ini(const dictionary * d, const char * s, FILE * f)
++{
++ int j ;
++ char keym[ASCIILINESZ+1];
++ int seclen ;
++
++ if (d==NULL || f==NULL) return ;
++ if (! iniparser_find_entry(d, s)) return ;
++
++ seclen = (int)strlen(s);
++ fprintf(f, "\n[%s]\n", s);
++ sprintf(keym, "%s:", s);
++ for (j=0 ; j<d->size ; j++) {
++ if (d->key[j]==NULL)
++ continue ;
++ if (!strncmp(d->key[j], keym, seclen+1)) {
++ fprintf(f,
++ "%-30s = %s\n",
++ d->key[j]+seclen+1,
++ d->val[j] ? d->val[j] : "");
+ }
+ }
+ fprintf(f, "\n");
+ return ;
+ }
+
++/*-------------------------------------------------------------------------*/
++/**
++ @brief Get the number of keys in a section of a dictionary.
++ @param d Dictionary to examine
++ @param s Section name of dictionary to examine
++ @return Number of keys in section
++ */
++/*--------------------------------------------------------------------------*/
++int iniparser_getsecnkeys(const dictionary * d, const char * s)
++{
++ int seclen, nkeys ;
++ char keym[ASCIILINESZ+1];
++ int j ;
++
++ nkeys = 0;
++
++ if (d==NULL) return nkeys;
++ if (! iniparser_find_entry(d, s)) return nkeys;
++
++ seclen = (int)strlen(s);
++ strlwc(s, keym, sizeof(keym));
++ keym[seclen] = ':';
++
++ for (j=0 ; j<d->size ; j++) {
++ if (d->key[j]==NULL)
++ continue ;
++ if (!strncmp(d->key[j], keym, seclen+1))
++ nkeys++;
++ }
++
++ return nkeys;
++
++}
++
++/*-------------------------------------------------------------------------*/
++/**
++ @brief Get the number of keys in a section of a dictionary.
++ @param d Dictionary to examine
++ @param s Section name of dictionary to examine
++ @param keys Already allocated array to store the keys in
++ @return The pointer passed as `keys` argument or NULL in case of error
++
++ This function queries a dictionary and finds all keys in a given section.
++ The keys argument should be an array of pointers which size has been
++ determined by calling `iniparser_getsecnkeys` function prior to this one.
++
++ Each pointer in the returned char pointer-to-pointer is pointing to
++ a string allocated in the dictionary; do not free or modify them.
++ */
++/*--------------------------------------------------------------------------*/
++const char ** iniparser_getseckeys(const dictionary * d, const char * s, const char ** keys)
++{
++ int i, j, seclen ;
++ char keym[ASCIILINESZ+1];
++
++ if (d==NULL || keys==NULL) return NULL;
++ if (! iniparser_find_entry(d, s)) return NULL;
++
++ seclen = (int)strlen(s);
++ strlwc(s, keym, sizeof(keym));
++ keym[seclen] = ':';
++
++ i = 0;
++
++ for (j=0 ; j<d->size ; j++) {
++ if (d->key[j]==NULL)
++ continue ;
++ if (!strncmp(d->key[j], keym, seclen+1)) {
++ keys[i] = d->key[j];
++ i++;
++ }
++ }
++
++ return keys;
++}
++
+ /*-------------------------------------------------------------------------*/
+ /**
+ @brief Get the string associated to a key
+@@ -267,24 +410,27 @@ void iniparser_dump_ini(dictionary * d, FILE * f)
+ the dictionary, do not free or modify it.
+ */
+ /*--------------------------------------------------------------------------*/
+-const char * iniparser_getstring(dictionary * d, const char * key, const char * def)
++const char * iniparser_getstring(const dictionary * d, const char * key, const char * def)
+ {
+- char * lc_key ;
++ const char * lc_key ;
++ const char * sval ;
++ char tmp_str[ASCIILINESZ+1];
+
+ if (d==NULL || key==NULL)
+ return def ;
+
+- lc_key = strlwc(key);
+- return dictionary_get(d, lc_key, def);
++ lc_key = strlwc(key, tmp_str, sizeof(tmp_str));
++ sval = dictionary_get(d, lc_key, def);
++ return sval ;
+ }
+
+ /*-------------------------------------------------------------------------*/
+ /**
+- @brief Get the string associated to a key, convert to an int
++ @brief Get the string associated to a key, convert to an long int
+ @param d Dictionary to search
+ @param key Key string to look for
+ @param notfound Value to return in case of error
+- @return integer
++ @return long integer
+
+ This function queries a dictionary for a key. A key as read from an
+ ini file is given as "section:key". If the key cannot be found,
+@@ -305,13 +451,46 @@ const char * iniparser_getstring(dictionary * d, const char * key, const char *
+ Credits: Thanks to A. Becker for suggesting strtol()
+ */
+ /*--------------------------------------------------------------------------*/
+-int iniparser_getint(dictionary * d, const char * key, int notfound)
++long int iniparser_getlongint(const dictionary * d, const char * key, long int notfound)
+ {
+- const char * str ;
++ const char * str ;
+
+ str = iniparser_getstring(d, key, INI_INVALID_KEY);
+ if (str==INI_INVALID_KEY) return notfound ;
+- return (int)strtol(str, NULL, 0);
++ return strtol(str, NULL, 0);
++}
++
++
++/*-------------------------------------------------------------------------*/
++/**
++ @brief Get the string associated to a key, convert to an int
++ @param d Dictionary to search
++ @param key Key string to look for
++ @param notfound Value to return in case of error
++ @return integer
++
++ This function queries a dictionary for a key. A key as read from an
++ ini file is given as "section:key". If the key cannot be found,
++ the notfound value is returned.
++
++ Supported values for integers include the usual C notation
++ so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
++ are supported. Examples:
++
++ "42" -> 42
++ "042" -> 34 (octal -> decimal)
++ "0x42" -> 66 (hexa -> decimal)
++
++ Warning: the conversion may overflow in various ways. Conversion is
++ totally outsourced to strtol(), see the associated man page for overflow
++ handling.
++
++ Credits: Thanks to A. Becker for suggesting strtol()
++ */
++/*--------------------------------------------------------------------------*/
++int iniparser_getint(const dictionary * d, const char * key, int notfound)
++{
++ return (int)iniparser_getlongint(d, key, notfound);
+ }
+
+ /*-------------------------------------------------------------------------*/
+@@ -327,9 +506,9 @@ int iniparser_getint(dictionary * d, const char * key, int notfound)
+ the notfound value is returned.
+ */
+ /*--------------------------------------------------------------------------*/
+-double iniparser_getdouble(dictionary * d, const char * key, double notfound)
++double iniparser_getdouble(const dictionary * d, const char * key, double notfound)
+ {
+- const char * str ;
++ const char * str ;
+
+ str = iniparser_getstring(d, key, INI_INVALID_KEY);
+ if (str==INI_INVALID_KEY) return notfound ;
+@@ -368,10 +547,10 @@ double iniparser_getdouble(dictionary * d, const char * key, double notfound)
+ necessarily have to be 0 or 1.
+ */
+ /*--------------------------------------------------------------------------*/
+-int iniparser_getboolean(dictionary * d, const char * key, int notfound)
++int iniparser_getboolean(const dictionary * d, const char * key, int notfound)
+ {
+- const char * c ;
+- int ret ;
++ int ret ;
++ const char * c ;
+
+ c = iniparser_getstring(d, key, INI_INVALID_KEY);
+ if (c==INI_INVALID_KEY) return notfound ;
+@@ -397,10 +576,7 @@ int iniparser_getboolean(dictionary * d, const char * key, int notfound)
+ of querying for the presence of sections in a dictionary.
+ */
+ /*--------------------------------------------------------------------------*/
+-int iniparser_find_entry(
+- dictionary * ini,
+- const char * entry
+-)
++int iniparser_find_entry(const dictionary * ini, const char * entry)
+ {
+ int found=0 ;
+ if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
+@@ -418,13 +594,14 @@ int iniparser_find_entry(
+ @return int 0 if Ok, -1 otherwise.
+
+ If the given entry can be found in the dictionary, it is modified to
+- contain the provided value. If it cannot be found, -1 is returned.
++ contain the provided value. If it cannot be found, the entry is created.
+ It is Ok to set val to NULL.
+ */
+ /*--------------------------------------------------------------------------*/
+ int iniparser_set(dictionary * ini, const char * entry, const char * val)
+ {
+- return dictionary_set(ini, strlwc(entry), val) ;
++ char tmp_str[ASCIILINESZ+1];
++ return dictionary_set(ini, strlwc(entry, tmp_str, sizeof(tmp_str)), val) ;
+ }
+
+ /*-------------------------------------------------------------------------*/
+@@ -439,12 +616,13 @@ int iniparser_set(dictionary * ini, const char * entry, const char * val)
+ /*--------------------------------------------------------------------------*/
+ void iniparser_unset(dictionary * ini, const char * entry)
+ {
+- dictionary_unset(ini, strlwc(entry));
++ char tmp_str[ASCIILINESZ+1];
++ dictionary_unset(ini, strlwc(entry, tmp_str, sizeof(tmp_str)));
+ }
+
+ /*-------------------------------------------------------------------------*/
+ /**
+- @brief Load a single line from an INI file
++ @brief Load a single line from an INI file
+ @param input_line Input line, may be concatenated multi-line input
+ @param section Output space to store section
+ @param key Output space to store key
+@@ -457,34 +635,39 @@ static line_status iniparser_line(
+ char * section,
+ char * key,
+ char * value)
+-{
++{
+ line_status sta ;
+- char line[ASCIILINESZ+1];
+- int len ;
++ char * line = NULL;
++ size_t len ;
+
+- strcpy(line, strstrip(input_line));
+- len = (int)strlen(line);
++ line = xstrdup(input_line);
++ len = strstrip(line);
+
+ sta = LINE_UNPROCESSED ;
+ if (len<1) {
+ /* Empty line */
+ sta = LINE_EMPTY ;
+- } else if (line[0]=='#') {
++ } else if (line[0]=='#' || line[0]==';') {
+ /* Comment line */
+- sta = LINE_COMMENT ;
++ sta = LINE_COMMENT ;
+ } else if (line[0]=='[' && line[len-1]==']') {
+ /* Section name */
+ sscanf(line, "[%[^]]", section);
+- strcpy(section, strstrip(section));
+- strcpy(section, strlwc(section));
++ strstrip(section);
++ strlwc(section, section, len);
+ sta = LINE_SECTION ;
+ } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
+- || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2
+- || sscanf (line, "%[^=] = %[^;#]", key, value) == 2) {
+- /* Usual key=value, with or without comments */
+- strcpy(key, strstrip(key));
+- strcpy(key, strlwc(key));
+- strcpy(value, strstrip(value));
++ || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2) {
++ /* Usual key=value with quotes, with or without comments */
++ strstrip(key);
++ strlwc(key, key, len);
++ /* Don't strip spaces from values surrounded with quotes */
++ sta = LINE_VALUE ;
++ } else if (sscanf (line, "%[^=] = %[^;#]", key, value) == 2) {
++ /* Usual key=value without quotes, with or without comments */
++ strstrip(key);
++ strlwc(key, key, len);
++ strstrip(value);
+ /*
+ * sscanf cannot handle '' or "" as empty values
+ * this is done here
+@@ -501,14 +684,16 @@ static line_status iniparser_line(
+ * key=;
+ * key=#
+ */
+- strcpy(key, strstrip(key));
+- strcpy(key, strlwc(key));
++ strstrip(key);
++ strlwc(key, key, len);
+ value[0]=0 ;
+ sta = LINE_VALUE ;
+ } else {
+ /* Generate syntax error */
+ sta = LINE_ERROR ;
+ }
++
++ free(line);
+ return sta ;
+ }
+
+@@ -528,44 +713,33 @@ static line_status iniparser_line(
+ /*--------------------------------------------------------------------------*/
+ dictionary * iniparser_load(const char * ininame)
+ {
+- char *buf;
+ FILE * in ;
+
+- char *line;
+- char *section;
+- char *key;
+- char *tmp;
+- char *val;
++ char line [ASCIILINESZ+1] ;
++ char section [ASCIILINESZ+1] ;
++ char key [ASCIILINESZ+1] ;
++ char tmp [(ASCIILINESZ * 2) + 2] ;
++ char val [ASCIILINESZ+1] ;
+
+ int last=0 ;
+ int len ;
+ int lineno=0 ;
+ int errs=0;
+- int ret;
++ int mem_err=0;
+
+ dictionary * dict ;
+
+- if ((in=fopen(ininame, "r"))==NULL)
++ if ((in=fopen(ininame, "r"))==NULL) {
++ iniparser_error_callback("iniparser: cannot open %s\n", ininame);
+ return NULL ;
++ }
+
+ dict = dictionary_new(0) ;
+ if (!dict) {
+ fclose(in);
+- errno = ENOMEM;
+ return NULL ;
+ }
+
+- buf = malloc((ASCIILINESZ+1) * 5);
+- if (buf == NULL) {
+- errno = -ENOMEM;
+- return NULL;
+- }
+- line = buf;
+- section = line + ASCIILINESZ + 1;
+- key = section + ASCIILINESZ + 1;
+- tmp = key + ASCIILINESZ + 1;
+- val = tmp + ASCIILINESZ + 1;
+-
+ memset(line, 0, ASCIILINESZ);
+ memset(section, 0, ASCIILINESZ);
+ memset(key, 0, ASCIILINESZ);
+@@ -575,18 +749,16 @@ dictionary * iniparser_load(const char * ininame)
+ while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
+ lineno++ ;
+ len = (int)strlen(line)-1;
++ if (len<=0)
++ continue;
+ /* Safety check against buffer overflows */
+- if (last > 0 && line[len]!='\n') {
+-#if 0
+- warning(anon_scope,
+- "iniparser: input line too long in %s (%d)\n",
+- ininame,
+- lineno);
+-#endif
++ if (line[len]!='\n' && !feof(in)) {
++ iniparser_error_callback(
++ "iniparser: input line too long in %s (%d)\n",
++ ininame,
++ lineno);
+ dictionary_del(dict);
+ fclose(in);
+- free(buf);
+- errno = EINVAL;
+ return NULL ;
+ }
+ /* Get rid of \n and spaces at end of line */
+@@ -595,8 +767,11 @@ dictionary * iniparser_load(const char * ininame)
+ line[len]=0 ;
+ len-- ;
+ }
++ if (len < 0) { /* Line was entirely \n and/or spaces */
++ len = 0;
++ }
+ /* Detect multi-line */
+- if (len >= 0 && line[len]=='\\') {
++ if (line[len]=='\\') {
+ /* Multi-line value */
+ last=len ;
+ continue ;
+@@ -609,24 +784,20 @@ dictionary * iniparser_load(const char * ininame)
+ break ;
+
+ case LINE_SECTION:
+- errs = dictionary_set(dict, section, NULL);
++ mem_err = dictionary_set(dict, section, NULL);
+ break ;
+
+ case LINE_VALUE:
+ sprintf(tmp, "%s:%s", section, key);
+- errs = dictionary_set(dict, tmp, val) ;
++ mem_err = dictionary_set(dict, tmp, val);
+ break ;
+
+- case LINE_ERROR:
+-#if 0
+- printf("iniparser: syntax error in %s (%d):\n",
+- ininame,
+- lineno);
+- printf( "-> %s\n", line);
+-
+-#endif
+-
+- ret = EINVAL;
++ case LINE_ERROR:
++ iniparser_error_callback(
++ "iniparser: syntax error in %s (%d):\n-> %s\n",
++ ininame,
++ lineno,
++ line);
+ errs++ ;
+ break;
+
+@@ -635,18 +806,16 @@ dictionary * iniparser_load(const char * ininame)
+ }
+ memset(line, 0, ASCIILINESZ);
+ last=0;
+- if (errs<0) {
+- ret = ENOMEM;
++ if (mem_err<0) {
++ iniparser_error_callback("iniparser: memory allocation failure\n");
+ break ;
+ }
+ }
+- fclose(in);
+- free(buf);
+ if (errs) {
+ dictionary_del(dict);
+ dict = NULL ;
+- errno = ret;
+ }
++ fclose(in);
+ return dict ;
+ }
+
+@@ -665,5 +834,3 @@ void iniparser_freedict(dictionary * d)
+ {
+ dictionary_del(d);
+ }
+-
+-/* vim: set ts=4 et sw=4 tw=75 */
+diff --git a/lib/boilerplate/iniparser/iniparser.h b/lib/boilerplate/iniparser/iniparser.h
+index d454cef34..37ff7b71b 100644
+--- a/lib/boilerplate/iniparser/iniparser.h
++++ b/lib/boilerplate/iniparser/iniparser.h
+@@ -3,22 +3,15 @@
+ /**
+ @file iniparser.h
+ @author N. Devillard
+- @date Sep 2007
+- @version 3.0
+ @brief Parser for ini files.
+ */
+ /*--------------------------------------------------------------------------*/
+
+-/*
+- $Id: iniparser.h,v 1.24 2007-11-23 21:38:19 ndevilla Exp $
+- $Revision: 1.24 $
+-*/
+-
+ #ifndef _INIPARSER_H_
+ #define _INIPARSER_H_
+
+ /*---------------------------------------------------------------------------
+- Includes
++ Includes
+ ---------------------------------------------------------------------------*/
+
+ #include <stdio.h>
+@@ -34,12 +27,21 @@
+
+ #include "dictionary.h"
+
+-/*---------------------------------------------------------------------------
+- Macros
+- ---------------------------------------------------------------------------*/
+-/** For backwards compatibility only */
+-#define iniparser_getstr(d, k) iniparser_getstring(d, k, NULL)
+-#define iniparser_setstr iniparser_setstring
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/*-------------------------------------------------------------------------*/
++/**
++ @brief Configure a function to receive the error messages.
++ @param errback Function to call.
++
++ By default, the error will be printed on stderr. If a null pointer is passed
++ as errback the error callback will be switched back to default.
++ */
++/*--------------------------------------------------------------------------*/
++
++void iniparser_set_error_callback(int (*errback)(const char *, ...));
+
+ /*-------------------------------------------------------------------------*/
+ /**
+@@ -60,7 +62,7 @@
+ */
+ /*--------------------------------------------------------------------------*/
+
+-int iniparser_getnsec(dictionary * d);
++int iniparser_getnsec(const dictionary * d);
+
+
+ /*-------------------------------------------------------------------------*/
+@@ -78,7 +80,7 @@ int iniparser_getnsec(dictionary * d);
+ */
+ /*--------------------------------------------------------------------------*/
+
+-const char * iniparser_getsecname(dictionary * d, int n);
++const char * iniparser_getsecname(const dictionary * d, int n);
+
+
+ /*-------------------------------------------------------------------------*/
+@@ -93,7 +95,22 @@ const char * iniparser_getsecname(dictionary * d, int n);
+ */
+ /*--------------------------------------------------------------------------*/
+
+-void iniparser_dump_ini(dictionary * d, FILE * f);
++void iniparser_dump_ini(const dictionary * d, FILE * f);
++
++/*-------------------------------------------------------------------------*/
++/**
++ @brief Save a dictionary section to a loadable ini file
++ @param d Dictionary to dump
++ @param s Section name of dictionary to dump
++ @param f Opened file pointer to dump to
++ @return void
++
++ This function dumps a given section of a given dictionary into a loadable ini
++ file. It is Ok to specify @c stderr or @c stdout as output files.
++ */
++/*--------------------------------------------------------------------------*/
++
++void iniparser_dumpsection_ini(const dictionary * d, const char * s, FILE * f);
+
+ /*-------------------------------------------------------------------------*/
+ /**
+@@ -108,7 +125,36 @@ void iniparser_dump_ini(dictionary * d, FILE * f);
+ purposes mostly.
+ */
+ /*--------------------------------------------------------------------------*/
+-void iniparser_dump(dictionary * d, FILE * f);
++void iniparser_dump(const dictionary * d, FILE * f);
++
++/*-------------------------------------------------------------------------*/
++/**
++ @brief Get the number of keys in a section of a dictionary.
++ @param d Dictionary to examine
++ @param s Section name of dictionary to examine
++ @return Number of keys in section
++ */
++/*--------------------------------------------------------------------------*/
++int iniparser_getsecnkeys(const dictionary * d, const char * s);
++
++/*-------------------------------------------------------------------------*/
++/**
++ @brief Get the number of keys in a section of a dictionary.
++ @param d Dictionary to examine
++ @param s Section name of dictionary to examine
++ @param keys Already allocated array to store the keys in
++ @return The pointer passed as `keys` argument or NULL in case of error
++
++ This function queries a dictionary and finds all keys in a given section.
++ The keys argument should be an array of pointers which size has been
++ determined by calling `iniparser_getsecnkeys` function prior to this one.
++
++ Each pointer in the returned char pointer-to-pointer is pointing to
++ a string allocated in the dictionary; do not free or modify them.
++ */
++/*--------------------------------------------------------------------------*/
++const char ** iniparser_getseckeys(const dictionary * d, const char * s, const char ** keys);
++
+
+ /*-------------------------------------------------------------------------*/
+ /**
+@@ -125,7 +171,7 @@ void iniparser_dump(dictionary * d, FILE * f);
+ the dictionary, do not free or modify it.
+ */
+ /*--------------------------------------------------------------------------*/
+-const char * iniparser_getstring(dictionary * d, const char * key, const char * def);
++const char * iniparser_getstring(const dictionary * d, const char * key, const char * def);
+
+ /*-------------------------------------------------------------------------*/
+ /**
+@@ -154,7 +200,35 @@ const char * iniparser_getstring(dictionary * d, const char * key, const char *
+ Credits: Thanks to A. Becker for suggesting strtol()
+ */
+ /*--------------------------------------------------------------------------*/
+-int iniparser_getint(dictionary * d, const char * key, int notfound);
++int iniparser_getint(const dictionary * d, const char * key, int notfound);
++
++/*-------------------------------------------------------------------------*/
++/**
++ @brief Get the string associated to a key, convert to an long int
++ @param d Dictionary to search
++ @param key Key string to look for
++ @param notfound Value to return in case of error
++ @return integer
++
++ This function queries a dictionary for a key. A key as read from an
++ ini file is given as "section:key". If the key cannot be found,
++ the notfound value is returned.
++
++ Supported values for integers include the usual C notation
++ so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
++ are supported. Examples:
++
++ - "42" -> 42
++ - "042" -> 34 (octal -> decimal)
++ - "0x42" -> 66 (hexa -> decimal)
++
++ Warning: the conversion may overflow in various ways. Conversion is
++ totally outsourced to strtol(), see the associated man page for overflow
++ handling.
++ */
++/*--------------------------------------------------------------------------*/
++long int iniparser_getlongint(const dictionary * d, const char * key, long int notfound);
++
+
+ /*-------------------------------------------------------------------------*/
+ /**
+@@ -169,7 +243,7 @@ int iniparser_getint(dictionary * d, const char * key, int notfound);
+ the notfound value is returned.
+ */
+ /*--------------------------------------------------------------------------*/
+-double iniparser_getdouble(dictionary * d, const char * key, double notfound);
++double iniparser_getdouble(const dictionary * d, const char * key, double notfound);
+
+ /*-------------------------------------------------------------------------*/
+ /**
+@@ -203,7 +277,7 @@ double iniparser_getdouble(dictionary * d, const char * key, double notfound);
+ necessarily have to be 0 or 1.
+ */
+ /*--------------------------------------------------------------------------*/
+-int iniparser_getboolean(dictionary * d, const char * key, int notfound);
++int iniparser_getboolean(const dictionary * d, const char * key, int notfound);
+
+
+ /*-------------------------------------------------------------------------*/
+@@ -212,17 +286,16 @@ int iniparser_getboolean(dictionary * d, const char * key, int notfound);
+ @param ini Dictionary to modify.
+ @param entry Entry to modify (entry name)
+ @param val New value to associate to the entry.
+- @return int 0 if Ok, -1 otherwise.
++ @return int 0 if Ok, -1 otherwise.
+
+ If the given entry can be found in the dictionary, it is modified to
+- contain the provided value. If it cannot be found, -1 is returned.
++ contain the provided value. If it cannot be found, the entry is created.
+ It is Ok to set val to NULL.
+ */
+ /*--------------------------------------------------------------------------*/
+-int iniparser_setstring(dictionary * ini, const char * entry, const char * val);
+-
+ int iniparser_set(dictionary * ini, const char * entry, const char * val);
+
++
+ /*-------------------------------------------------------------------------*/
+ /**
+ @brief Delete an entry in a dictionary
+@@ -247,7 +320,7 @@ void iniparser_unset(dictionary * ini, const char * entry);
+ of querying for the presence of sections in a dictionary.
+ */
+ /*--------------------------------------------------------------------------*/
+-int iniparser_find_entry(dictionary * ini, const char * entry) ;
++int iniparser_find_entry(const dictionary * ini, const char * entry) ;
+
+ /*-------------------------------------------------------------------------*/
+ /**
+@@ -278,4 +351,8 @@ dictionary * iniparser_load(const char * ininame);
+ /*--------------------------------------------------------------------------*/
+ void iniparser_freedict(dictionary * d);
+
++#ifdef __cplusplus
++}
++#endif
++
+ #endif
+--
+GitLab
+