package/xenomai: fix build with gcc 10
authorFabrice Fontaine <fontaine.fabrice@gmail.com>
Tue, 19 Jan 2021 17:31:19 +0000 (18:31 +0100)
committerPeter Korsgaard <peter@korsgaard.com>
Tue, 19 Jan 2021 19:22:46 +0000 (20:22 +0100)
Fixes:
 - http://autobuild.buildroot.org/results/551228bcc7152d5e835f3cced6329269b6bad651

Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com>
[Peter: move to 3.0.10 subdir so it is only used for that version]
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
package/xenomai/3.0.10/0001-lib-boilerplate-iniparser-Allow-building-with-GCC-10-2-2020101.patch [new file with mode: 0644]

diff --git a/package/xenomai/3.0.10/0001-lib-boilerplate-iniparser-Allow-building-with-GCC-10-2-2020101.patch b/package/xenomai/3.0.10/0001-lib-boilerplate-iniparser-Allow-building-with-GCC-10-2-2020101.patch
new file mode 100644 (file)
index 0000000..e4addea
--- /dev/null
@@ -0,0 +1,1721 @@
+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
+