From patchwork Tue Jan 19 17:31:19 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Fabrice Fontaine X-Patchwork-Id: 1428759 Return-Path: X-Original-To: incoming-buildroot@patchwork.ozlabs.org Delivered-To: patchwork-incoming-buildroot@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=busybox.net (client-ip=140.211.166.137; helo=fraxinus.osuosl.org; envelope-from=buildroot-bounces@busybox.net; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=e6jFHXDc; dkim-atps=neutral Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4DKwhf1vrXz9sW8 for ; Wed, 20 Jan 2021 04:32:33 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id B90E98531B; Tue, 19 Jan 2021 17:32:30 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id t1566ukWA9Hl; Tue, 19 Jan 2021 17:32:26 +0000 (UTC) Received: from ash.osuosl.org (ash.osuosl.org [140.211.166.34]) by fraxinus.osuosl.org (Postfix) with ESMTP id 0D74885168; Tue, 19 Jan 2021 17:32:26 +0000 (UTC) X-Original-To: buildroot@lists.busybox.net Delivered-To: buildroot@osuosl.org Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by ash.osuosl.org (Postfix) with ESMTP id 1643A1BF9C2 for ; Tue, 19 Jan 2021 17:32:25 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 03203868C0 for ; Tue, 19 Jan 2021 17:32:25 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 2p2IbSH+J9VP for ; Tue, 19 Jan 2021 17:32:21 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mail-wm1-f49.google.com (mail-wm1-f49.google.com [209.85.128.49]) by whitealder.osuosl.org (Postfix) with ESMTPS id 8BC1286138 for ; Tue, 19 Jan 2021 17:32:20 +0000 (UTC) Received: by mail-wm1-f49.google.com with SMTP id e15so511277wme.0 for ; Tue, 19 Jan 2021 09:32:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=xQBYOwSRyNicN+DCXjg18gVV0cRbtsY5ALVDI1SbxFY=; b=e6jFHXDcY2mjkRbK/vAFKDkJE+Rg8CX3XmYnktm0poYJAlDiZ1HhdCppbFqTaEhAea PkvyZcqvmnSCS7V07h10OqIEeG7CLKoQ+D1X8hzYvi5n2KnC7ojT1Q+4JEmQ5Pa8R7cx pE5T+pVvQO0PSYIadQMcGODG/oM3hdthE7KCeeQCoY3GkjpOhY0+DLw7hiQpDFd8IZnQ 5n6S3cwzb82oD7sEySRH/HOxNSIYT8Ghr9XlOUnyEoJV6KjqHFbKvRbTQifVDEgn7pE4 WMA7cL8ovq29WggY7F4IiUQ4RlFlZdz4cI1JOdS3eG0eMnQCBPe3SAq1/Y/S0E75dQqn EAKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=xQBYOwSRyNicN+DCXjg18gVV0cRbtsY5ALVDI1SbxFY=; b=fz64waFIJb4cwLzHc78bPOFg330SCr23s5dS+HcmcXa+pzmtBpRmeeIszxGQYi5JvA eO32ue/MWvZQR497jZ44peRqGtFO/fVN9j79HhlSy1ByiZKuxCdp+zV5FCP1RQRc2EcG o6adhEzjHpFyPUSCDX+CRILdvcx25nfRKV7LU67r2ojrBZ48Fzh29cEhk0Z4Goxy/b7P qs5XzetEOH4Pfu8ZW024T6G7XX/nyDktBfTbVCDC68uztm9dO0fQeEpIGMvTRzOIC8B2 MxyTcSAmQEkxNlFmgJoue7FGxrVvvTsjIHo2gdA2QAedLhvXQZSh7M6dR5Of9fza4KJi vSoQ== X-Gm-Message-State: AOAM5309fXcKSXr5aPxyHtweEs3bwfcWrqVl2XbxvfRqG3qbJqw/B2u3 R4wjVTwYxzBeJ8BPu3LGJAB+Awq2wCAGGQ== X-Google-Smtp-Source: ABdhPJyHimg0d8xiRrrKcaeN6CLFruMhw7HyndmW+TsYlhCiQbxIy1n6J9vvA/g7/JZCExd0qS0R8g== X-Received: by 2002:a1c:4e17:: with SMTP id g23mr666348wmh.130.1611077537297; Tue, 19 Jan 2021 09:32:17 -0800 (PST) Received: from kali.home (2a01cb0881b76d00c2afd0dfa851d2b9.ipv6.abo.wanadoo.fr. [2a01:cb08:81b7:6d00:c2af:d0df:a851:d2b9]) by smtp.gmail.com with ESMTPSA id x11sm5309465wmi.4.2021.01.19.09.32.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Jan 2021 09:32:16 -0800 (PST) From: Fabrice Fontaine To: buildroot@buildroot.org Date: Tue, 19 Jan 2021 18:31:19 +0100 Message-Id: <20210119173119.436246-1-fontaine.fabrice@gmail.com> X-Mailer: git-send-email 2.29.2 MIME-Version: 1.0 Subject: [Buildroot] [PATCH 1/1] package/xenomai: fix build with gcc 10 X-BeenThere: buildroot@busybox.net X-Mailman-Version: 2.1.29 Precedence: list List-Id: Discussion and development of buildroot List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Matt Weber , Romain Naour , Alistair Francis , Fabrice Fontaine , Thomas De Schampheleire Errors-To: buildroot-bounces@busybox.net Sender: "buildroot" Fixes: - http://autobuild.buildroot.org/results/551228bcc7152d5e835f3cced6329269b6bad651 Signed-off-by: Fabrice Fontaine --- ...Allow-building-with-GCC-10-2-2020101.patch | 1721 +++++++++++++++++ 1 file changed, 1721 insertions(+) create mode 100644 package/xenomai/0001-lib-boilerplate-iniparser-Allow-building-with-GCC-10-2-2020101.patch diff --git a/package/xenomai/0001-lib-boilerplate-iniparser-Allow-building-with-GCC-10-2-2020101.patch b/package/xenomai/0001-lib-boilerplate-iniparser-Allow-building-with-GCC-10-2-2020101.patch new file mode 100644 index 0000000000..e4addea856 --- /dev/null +++ b/package/xenomai/0001-lib-boilerplate-iniparser-Allow-building-with-GCC-10-2-2020101.patch @@ -0,0 +1,1721 @@ +From 8acdbd718b7828b5d8903a6254b2fa198b866491 Mon Sep 17 00:00:00 2001 +From: Florian Bezdeka +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 +Signed-off-by: Jan Kiszka + +[Retrieved from: +https://gitlab.denx.de/Xenomai/xenomai/-/commit/8acdbd718b7828b5d8903a6254b2fa198b866491] +Signed-off-by: Fabrice Fontaine +--- + 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 + + /** 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>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>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 (sizesize = 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 (sizesize = 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 ; isize ; 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 ; isize ; 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 ; isize ; i++) { ++ hash = dictionary_hash(key); ++ for (i=0 ; isize ; 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 ; isize ; 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 ; isize ; 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 ; isize ; 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 ; isize ; i++) { ++ hash = dictionary_hash(key); ++ for (i=0 ; isize ; 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 ; isize ; i++) { ++ ssize_t i ; ++ ++ if (d==NULL || out==NULL) return ; ++ if (d->n<1) { ++ fprintf(out, "empty dictionary\n"); ++ return ; ++ } ++ for (i=0 ; isize ; 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 ; in != 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 +@@ -32,14 +23,18 @@ + #include + #include + ++#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 +-#include ++#include + #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 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 ; isize ; 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 ; jsize ; 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 ; jsize ; 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 ; jsize ; 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 +@@ -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 +