diff --git a/CONFIG/vita/.gitignore b/CONFIG/vita/.gitignore
deleted file mode 100644
index f3d6549d..00000000
--- a/CONFIG/vita/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build/
\ No newline at end of file
diff --git a/CONFIG/vita/CMakeLists.txt b/CONFIG/vita/CMakeLists.txt
index ff3f500f..cb76332a 100644
--- a/CONFIG/vita/CMakeLists.txt
+++ b/CONFIG/vita/CMakeLists.txt
@@ -12,6 +12,27 @@ FetchContent_Declare(
)
FetchContent_MakeAvailable(ScePaf_External)
+add_subdirectory(SceIniFileProcessor)
+
+add_library(iniparser_paf
+ iniparser_paf/src/dictionary.c
+ iniparser_paf/src/iniparser.c
+)
+
+target_link_libraries(iniparser_paf
+ ScePafStdc_stub
+ SceLibKernel_stub
+ SceLibc_stub
+)
+
+target_include_directories(iniparser_paf PUBLIC
+ iniparser_paf/src/
+)
+
+target_compile_options(iniparser_paf PRIVATE
+ -Wl,-q -Wall -fno-builtin -fshort-wchar -Wno-unused-function -Wno-sign-compare
+)
+
add_executable(isle-config
src/app.cpp
src/main.cpp
@@ -22,7 +43,7 @@ set_target_properties(isle-config PROPERTIES
)
target_compile_options(isle-config PRIVATE
- -fno-rtti -fno-exceptions -Wl,-q -Wall -fno-builtin -fshort-wchar -Wno-unused-function -Wno-sign-compare
+ -fno-rtti -fno-exceptions -Wl,-q -Wall -fno-builtin -fshort-wchar -Wno-unused-function -Wno-sign-compare -fno-use-cxa-atexit
)
target_link_options(isle-config PRIVATE
@@ -39,16 +60,23 @@ target_link_libraries(isle-config PRIVATE
ScePafWidget_stub
ScePafCommon_stub
ScePafStdc_stub
+ SceAppSettings_stub
+ SceFios2_stub
+
+ #Isle::iniparser
+ iniparser_paf
)
-block()
- vita_create_self(isle-config.self isle-config
- CONFIG exports.yml
- UNSAFE
- STRIPPED
- REL_OPTIMIZE
- )
-endblock()
+target_include_directories(isle-config PUBLIC
+ include
+)
+
+vita_create_self(isle-config.self isle-config
+ CONFIG exports.yml
+ UNSAFE
+ STRIPPED
+ REL_OPTIMIZE
+)
include(${scepaf_external_SOURCE_DIR}/rco.cmake)
make_rco(cxml/config_plugin.xml config_plugin.rco)
diff --git a/CONFIG/vita/cxml/config_plugin.xml b/CONFIG/vita/cxml/config_plugin.xml
index b0ea26d9..2f1df305 100644
--- a/CONFIG/vita/cxml/config_plugin.xml
+++ b/CONFIG/vita/cxml/config_plugin.xml
@@ -1,265 +1,16 @@
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+-->
-
+-->
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
diff --git a/CONFIG/vita/cxml/locale/en.xml b/CONFIG/vita/cxml/locale/en.xml
index 79bb95af..9e5337eb 100644
--- a/CONFIG/vita/cxml/locale/en.xml
+++ b/CONFIG/vita/cxml/locale/en.xml
@@ -1,38 +1,51 @@
-
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
+
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
+
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
+
+
-
-
-
-
\ No newline at end of file
+
+
+
+
+
diff --git a/CONFIG/vita/cxml/settings.xml b/CONFIG/vita/cxml/settings.xml
new file mode 100644
index 00000000..2271532e
--- /dev/null
+++ b/CONFIG/vita/cxml/settings.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CONFIG/vita/cxml/textures/shark.png b/CONFIG/vita/cxml/textures/shark.png
deleted file mode 100644
index 58b96386..00000000
Binary files a/CONFIG/vita/cxml/textures/shark.png and /dev/null differ
diff --git a/CONFIG/vita/cxml/textures/tex_settings_bg.gim b/CONFIG/vita/cxml/textures/tex_settings_bg.gim
deleted file mode 100644
index ee68e0ee..00000000
Binary files a/CONFIG/vita/cxml/textures/tex_settings_bg.gim and /dev/null differ
diff --git a/CONFIG/vita/include/fios2.h b/CONFIG/vita/include/fios2.h
new file mode 100644
index 00000000..11c8133e
--- /dev/null
+++ b/CONFIG/vita/include/fios2.h
@@ -0,0 +1,136 @@
+#include
+#include
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct SceFiosBuffer {
+ void *pPtr;
+ size_t length;
+} SceFiosBuffer;
+
+#define SCE_FIOS_THREAD_TYPES 3
+
+typedef struct SceFiosParams
+{
+ uint32_t initialized : 1;
+ uint32_t paramsSize : 15;
+ uint32_t pathMax : 16;
+ uint32_t profiling;
+ uint32_t ioThreadCount;
+ uint32_t threadsPerScheduler;
+ uint32_t extraFlag1 : 1;
+ uint32_t extraFlags : 31;
+ uint32_t maxChunk;
+ uint8_t maxDecompressorThreadCount;
+ uint8_t reserved1;
+ uint8_t reserved2;
+ uint8_t reserved3;
+ intptr_t reserved4;
+ intptr_t reserved5;
+ SceFiosBuffer opStorage;
+ SceFiosBuffer fhStorage;
+ SceFiosBuffer dhStorage;
+ SceFiosBuffer chunkStorage;
+ void* pVprintf;
+ void* pMemcpy;
+ void* pProfileCallback;
+ int threadPriority[SCE_FIOS_THREAD_TYPES];
+ int threadAffinity[SCE_FIOS_THREAD_TYPES];
+ int threadStackSize[SCE_FIOS_THREAD_TYPES];
+} SceFiosParams;
+
+#define SCE_KERNEL_HIGHEST_PRIORITY_USER (64)
+#define SCE_KERNEL_LOWEST_PRIORITY_USER (191)
+
+#define SCE_FIOS_IO_THREAD_DEFAULT_PRIORITY (SCE_KERNEL_HIGHEST_PRIORITY_USER+2)
+#define SCE_FIOS_DECOMPRESSOR_THREAD_DEFAULT_PRIORITY (SCE_KERNEL_LOWEST_PRIORITY_USER-2)
+#define SCE_FIOS_CALLBACK_THREAD_DEFAULT_PRIORITY (SCE_KERNEL_HIGHEST_PRIORITY_USER+2)
+
+#define SCE_FIOS_THREAD_DEFAULT_AFFINITY SCE_KERNEL_CPU_MASK_USER_2
+#define SCE_FIOS_IO_THREAD_DEFAULT_AFFINITY SCE_FIOS_THREAD_DEFAULT_AFFINITY
+#define SCE_FIOS_DECOMPRESSOR_THREAD_DEFAULT_AFFINITY SCE_KERNEL_THREAD_CPU_AFFINITY_MASK_DEFAULT
+#define SCE_FIOS_CALLBACK_THREAD_DEFAULT_AFFINITY SCE_FIOS_THREAD_DEFAULT_AFFINITY
+
+#define SCE_FIOS_IO_THREAD_DEFAULT_STACKSIZE (8*1024)
+#define SCE_FIOS_DECOMPRESSOR_THREAD_DEFAULT_STACKSIZE (16*1024)
+#define SCE_FIOS_CALLBACK_THREAD_DEFAULT_STACKSIZE (8*1024)
+
+#define SCE_FIOS_PARAMS_INITIALIZER { 0, sizeof(SceFiosParams), 0, 0, \
+ 2, 2, \
+ 0, 0, \
+ (256*1024), \
+ 2, 0, 0, 0, 0, 0, \
+ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \
+ NULL, NULL, NULL, \
+ { SCE_FIOS_IO_THREAD_DEFAULT_PRIORITY, SCE_FIOS_DECOMPRESSOR_THREAD_DEFAULT_PRIORITY, SCE_FIOS_CALLBACK_THREAD_DEFAULT_PRIORITY }, \
+ { SCE_FIOS_IO_THREAD_DEFAULT_AFFINITY, SCE_FIOS_DECOMPRESSOR_THREAD_DEFAULT_AFFINITY, SCE_FIOS_CALLBACK_THREAD_DEFAULT_AFFINITY}, \
+ { SCE_FIOS_IO_THREAD_DEFAULT_STACKSIZE, SCE_FIOS_DECOMPRESSOR_THREAD_DEFAULT_STACKSIZE, SCE_FIOS_CALLBACK_THREAD_DEFAULT_STACKSIZE}}
+
+#define SCE_FIOS_IO_THREAD 0
+#define SCE_FIOS_DECOMPRESSOR_THREAD 1
+#define SCE_FIOS_CALLBACK_THREAD 2
+
+#define SCE_FIOS_FH_SIZE 80
+#define SCE_FIOS_DH_SIZE 80
+#define SCE_FIOS_OP_SIZE 168
+#define SCE_FIOS_CHUNK_SIZE 64
+
+#define SCE_FIOS_ALIGN_UP(val,align) (((val) + ((align)-1)) & ~((align)-1))
+
+#define SCE_FIOS_STORAGE_SIZE(num, size) \
+ (((num) * (size)) + SCE_FIOS_ALIGN_UP(SCE_FIOS_ALIGN_UP((num), 8) / 8, 8))
+
+#define SCE_FIOS_DH_STORAGE_SIZE(numDHs, pathMax) \
+ SCE_FIOS_STORAGE_SIZE(numDHs, SCE_FIOS_DH_SIZE + pathMax)
+
+#define SCE_FIOS_FH_STORAGE_SIZE(numFHs,pathMax) \
+ SCE_FIOS_STORAGE_SIZE(numFHs, SCE_FIOS_FH_SIZE + pathMax)
+
+#define SCE_FIOS_OP_STORAGE_SIZE(numOps,pathMax) \
+ SCE_FIOS_STORAGE_SIZE(numOps, SCE_FIOS_OP_SIZE + pathMax)
+
+#define SCE_FIOS_CHUNK_STORAGE_SIZE(numChunks) \
+ SCE_FIOS_STORAGE_SIZE(numChunks, SCE_FIOS_CHUNK_SIZE)
+
+int sceFiosInitialize(SceFiosParams* params);
+
+
+typedef int64_t SceFiosTime;
+
+typedef int32_t SceFiosHandle;
+
+typedef SceFiosHandle SceFiosFH;
+
+typedef struct SceFiosOpenParams
+{
+ uint32_t openFlags:16;
+ uint32_t opFlags:16;
+ uint32_t reserved;
+ SceFiosBuffer buffer;
+} SceFiosOpenParams;
+
+typedef struct SceFiosOpAttr
+{
+ SceFiosTime deadline;
+ void* pCallback;
+ void * pCallbackContext;
+ int32_t priority : 8;
+ uint32_t opflags : 24;
+ uint32_t userTag;
+ void * userPtr;
+ void * pReserved;
+} SceFiosOpAttr;
+
+
+int sceFiosFHOpenWithModeSync(const SceFiosOpAttr *pAttr, SceFiosFH *pOutFH, const char *pPath, const SceFiosOpenParams *pOpenParams, int32_t nativeMode);
+
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/CONFIG/vita/include/pafinc.h b/CONFIG/vita/include/pafinc.h
new file mode 100644
index 00000000..5b4addf9
--- /dev/null
+++ b/CONFIG/vita/include/pafinc.h
@@ -0,0 +1,4 @@
+// clang-format off
+#include
+#include
+// clang-format on
\ No newline at end of file
diff --git a/CONFIG/vita/include/scetypes.h b/CONFIG/vita/include/scetypes.h
new file mode 100644
index 00000000..e69de29b
diff --git a/CONFIG/vita/iniparser_paf/src/dictionary.c b/CONFIG/vita/iniparser_paf/src/dictionary.c
new file mode 100644
index 00000000..38102dfa
--- /dev/null
+++ b/CONFIG/vita/iniparser_paf/src/dictionary.c
@@ -0,0 +1,381 @@
+/*-------------------------------------------------------------------------*/
+/**
+ @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.
+ informations retrieved from a configuration file (ini files).
+*/
+/*--------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+ Includes
+ ---------------------------------------------------------------------------*/
+#include "dictionary.h"
+
+#include "pafstd.h"
+
+/** Minimal allocated number of entries in a dictionary */
+#define DICTMINSZ 128
+
+/*---------------------------------------------------------------------------
+ Private functions
+ ---------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/**
+ @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 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
+ ---------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
+/**
+ @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.
+ The key is stored anyway in the struct so that collision can be avoided
+ by comparing the key itself in last resort.
+ */
+/*--------------------------------------------------------------------------*/
+unsigned dictionary_hash(const char * key)
+{
+ 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 object.
+
+ 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(size_t size)
+{
+ 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);
+ if (!d->size || !d->val || !d->hash) {
+ free((void *) d->size);
+ free((void *) d->val);
+ free((void *) d->hash);
+ free(d);
+ d = NULL;
+ }
+ }
+ return d ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @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)
+{
+ size_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.
+ @param def Default value to return if key not found.
+ @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
+ dictionary. The returned character pointer points to data internal to the
+ dictionary object, you should not try to free it or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+const char * dictionary_get(const dictionary * d, const char * key, const char * def)
+{
+ unsigned hash ;
+ size_t i ;
+
+ if(d == NULL || key == NULL)
+ return def ;
+
+ hash = dictionary_hash(key);
+ for (i=0 ; isize ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+ /* Compare hash */
+ if (hash==d->hash[i]) {
+ /* Compare string, to avoid hash collisions */
+ if (!strcmp(key, d->key[i])) {
+ return d->val[i] ;
+ }
+ }
+ }
+ return def ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Set a value in a dictionary.
+ @param d dictionary object to modify.
+ @param key Key to modify or add.
+ @param val Value to add.
+ @return int 0 if Ok, anything else otherwise
+
+ If the given key is found in the dictionary, the associated value is
+ replaced by the provided one. If the key cannot be found in the
+ dictionary, it is added to it.
+
+ It is Ok to provide a NULL value for val, but NULL values for the dictionary
+ or the key are considered as errors: the function will return immediately
+ in such a case.
+
+ Notice that if you dictionary_set a variable to NULL, a call to
+ dictionary_get will return a NULL value: the variable will be found, and
+ its value (NULL) is returned. In other words, setting the variable
+ content to NULL is equivalent to deleting the variable from the
+ dictionary. It is not possible (in this implementation) to have a key in
+ the dictionary without value.
+
+ This function returns non-zero in case of failure.
+ */
+/*--------------------------------------------------------------------------*/
+int dictionary_set(dictionary * d, const char * key, const char * val)
+{
+ size_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);
+ /* 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 */
+ if (dictionary_grow(d) != 0)
+ return -1;
+ }
+
+ /* 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 ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @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
+ key cannot be found.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_unset(dictionary * d, const char * key)
+{
+ unsigned hash ;
+ size_t i ;
+
+ if (key == NULL || d == NULL) {
+ return;
+ }
+
+ hash = dictionary_hash(key);
+ for (i=0 ; isize ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+ /* Compare hash */
+ 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 ;
+
+ free(d->key[i]);
+ d->key[i] = NULL ;
+ if (d->val[i]!=NULL) {
+ free(d->val[i]);
+ d->val[i] = NULL ;
+ }
+ d->hash[i] = 0 ;
+ d->n -- ;
+ return ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @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(const dictionary * d, FILE * out)
+{
+ size_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 ;
+}
diff --git a/CONFIG/vita/iniparser_paf/src/dictionary.h b/CONFIG/vita/iniparser_paf/src/dictionary.h
new file mode 100644
index 00000000..31f639c5
--- /dev/null
+++ b/CONFIG/vita/iniparser_paf/src/dictionary.h
@@ -0,0 +1,170 @@
+
+/*-------------------------------------------------------------------------*/
+/**
+ @file dictionary.h
+ @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.
+ informations retrieved from a configuration file (ini files).
+*/
+/*--------------------------------------------------------------------------*/
+
+#ifndef _DICTIONARY_H_
+#define _DICTIONARY_H_
+
+/*---------------------------------------------------------------------------
+ Includes
+ ---------------------------------------------------------------------------*/
+
+#include "pafstd.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*---------------------------------------------------------------------------
+ New types
+ ---------------------------------------------------------------------------*/
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Dictionary object
+
+ This object contains a list of string/string associations. Each
+ association is identified by a unique string key. Looking up values
+ in the dictionary is speeded up by the use of a (hopefully collision-free)
+ hash function.
+ */
+/*-------------------------------------------------------------------------*/
+typedef struct _dictionary_ {
+ unsigned n ; /** Number of entries in dictionary */
+ size_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
+ ---------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/**
+ @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.
+ The key is stored anyway in the struct so that collision can be avoided
+ by comparing the key itself in last resort.
+ */
+/*--------------------------------------------------------------------------*/
+unsigned dictionary_hash(const char * key);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Create a new dictionary object.
+ @param size Optional initial size of the dictionary.
+ @return 1 newly allocated dictionary object.
+
+ 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(size_t size);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @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 * vd);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @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.
+
+ 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
+ dictionary. The returned character pointer points to data internal to the
+ dictionary object, you should not try to free it or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+const char * dictionary_get(const dictionary * d, const char * key, const char * def);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Set a value in a dictionary.
+ @param d dictionary object to modify.
+ @param key Key to modify or add.
+ @param val Value to add.
+ @return int 0 if Ok, anything else otherwise
+
+ If the given key is found in the dictionary, the associated value is
+ replaced by the provided one. If the key cannot be found in the
+ dictionary, it is added to it.
+
+ It is Ok to provide a NULL value for val, but NULL values for the dictionary
+ or the key are considered as errors: the function will return immediately
+ in such a case.
+
+ Notice that if you dictionary_set a variable to NULL, a call to
+ dictionary_get will return a NULL value: the variable will be found, and
+ its value (NULL) is returned. In other words, setting the variable
+ content to NULL is equivalent to deleting the variable from the
+ dictionary. It is not possible (in this implementation) to have a key in
+ the dictionary without value.
+
+ This function returns non-zero in case of failure.
+ */
+/*--------------------------------------------------------------------------*/
+int dictionary_set(dictionary * vd, const char * key, const char * val);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @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
+ key cannot be found.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_unset(dictionary * d, const char * key);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @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(const dictionary * d, FILE * out);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/CONFIG/vita/iniparser_paf/src/iniparser.c b/CONFIG/vita/iniparser_paf/src/iniparser.c
new file mode 100644
index 00000000..222ebab9
--- /dev/null
+++ b/CONFIG/vita/iniparser_paf/src/iniparser.c
@@ -0,0 +1,958 @@
+
+/*-------------------------------------------------------------------------*/
+/**
+ @file iniparser.c
+ @author N. Devillard
+ @brief Parser for ini files.
+*/
+/*--------------------------------------------------------------------------*/
+/*---------------------------- Includes ------------------------------------*/
+#include
+#include "pafstd.h"
+#include
+#include
+#include "iniparser.h"
+
+/*---------------------------- Defines -------------------------------------*/
+#define ASCIILINESZ (1024)
+#define INI_INVALID_KEY ((char*)-1)
+
+/*---------------------------------------------------------------------------
+ Private to this module
+ ---------------------------------------------------------------------------*/
+/**
+ * This enum stores the status for each parsed line (internal use only).
+ */
+typedef enum _line_status_ {
+ LINE_UNPROCESSED,
+ LINE_ERROR,
+ LINE_EMPTY,
+ LINE_COMMENT,
+ LINE_SECTION,
+ LINE_VALUE
+} line_status ;
+
+/*-------------------------------------------------------------------------*/
+/**
+ @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 const char * strlwc(const char * in, char *out, unsigned len)
+{
+ unsigned i ;
+
+ if (in==NULL || out == NULL || len==0) return NULL ;
+ i=0 ;
+ while (in[i] != '\0' && i < len-1) {
+ out[i] = (char)tolower((int)in[i]);
+ i++ ;
+ }
+ 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((unsigned char)*s) && *s) s++;
+ while (last > s) {
+ if (!isspace((unsigned char)*(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 = 0;
+ va_list args;
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+ return ret;
+}
+
+static int (*iniparser_error_callback)(const char*, ...) = default_error_callback;
+
+/*-------------------------------------------------------------------------*/
+/**
+ @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 *, ...))
+{
+ if (errback) {
+ iniparser_error_callback = errback;
+ } else {
+ iniparser_error_callback = default_error_callback;
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get number of sections in a dictionary
+ @param d Dictionary to examine
+ @return int Number of sections found in dictionary
+
+ This function returns the number of sections found in a dictionary.
+ The test to recognize sections is done on the string stored in the
+ dictionary: a section name is given as "section" whereas a key is
+ stored as "section:key", thus the test looks for entries that do not
+ contain a colon.
+
+ This clearly fails in the case a section name contains a colon, but
+ this should simply be avoided.
+
+ This function returns -1 in case of error.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getnsec(const dictionary * d)
+{
+ size_t i ;
+ int nsec ;
+
+ if (d==NULL) return -1 ;
+ nsec=0 ;
+ for (i=0 ; isize ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+ if (strchr(d->key[i], ':')==NULL) {
+ nsec ++ ;
+ }
+ }
+ return nsec ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get name for section n in a dictionary.
+ @param d Dictionary to examine
+ @param n Section number (from 0 to nsec-1).
+ @return Pointer to char string
+
+ This function locates the n-th section in a dictionary and returns
+ its name as a pointer to a string statically allocated inside the
+ dictionary. Do not free or modify the returned string!
+
+ This function returns NULL in case of error.
+ */
+/*--------------------------------------------------------------------------*/
+const char * iniparser_getsecname(const dictionary * d, int n)
+{
+ size_t i ;
+ int foundsec ;
+
+ if (d==NULL || n<0) return NULL ;
+ foundsec=0 ;
+ for (i=0 ; isize ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+ if (strchr(d->key[i], ':')==NULL) {
+ foundsec++ ;
+ if (foundsec>n)
+ break ;
+ }
+ }
+ if (foundsec<=n) {
+ return NULL ;
+ }
+ return d->key[i] ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Dump a dictionary to an opened file pointer.
+ @param d Dictionary to dump.
+ @param f Opened file pointer to dump to.
+ @return void
+
+ This function prints out the contents of a dictionary, one element by
+ line, onto the provided file pointer. It is OK to specify @c stderr
+ or @c stdout as output files. This function is meant for debugging
+ purposes mostly.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_dump(const dictionary * d, FILE * f)
+{
+ size_t i ;
+
+ if (d==NULL || f==NULL) return ;
+ for (i=0 ; isize ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+ if (d->val[i]!=NULL) {
+ fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
+ } else {
+ fprintf(f, "[%s]=UNDEF\n", d->key[i]);
+ }
+ }
+ return ;
+}
+
+static void escape_value(char *escaped, char *value) {
+ char c;
+ int v = 0;
+ int e = 0;
+
+ if(!escaped || !value)
+ return;
+
+ while((c = value[v]) != '\0') {
+ if(c == '\\' || c == '"') {
+ escaped[e] = '\\';
+ e++;
+ }
+ escaped[e] = c;
+ v++;
+ e++;
+ }
+ escaped[e] = '\0';
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Save a dictionary to a loadable ini file
+ @param d Dictionary to dump
+ @param f Opened file pointer to dump to
+ @return void
+
+ This function dumps a given dictionary into a loadable ini file.
+ It is Ok to specify @c stderr or @c stdout as output files.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_dump_ini(const dictionary * d, FILE * f)
+{
+ size_t i ;
+ size_t nsec ;
+ const char * secname ;
+ char escaped[(ASCIILINESZ * 2) + 2] = "";
+
+ if (d==NULL || f==NULL) return ;
+
+ nsec = iniparser_getnsec(d);
+ if (nsec<1) {
+ /* No section in file: dump all keys as they are */
+ for (i=0 ; isize ; i++) {
+ if (d->key[i]==NULL)
+ continue ;
+ escape_value(escaped, d->val[i]);
+ fprintf(f, "%s = \"%s\"\n", d->key[i], escaped);
+ }
+ return ;
+ }
+ for (i=0 ; i sizeof(keym)) 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)) {
+ escape_value(escaped, d->val[j]);
+ fprintf(f, "%-30s = \"%s\"\n", d->key[j]+seclen+1, escaped);
+ }
+ }
+ 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];
+ size_t 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)
+{
+ size_t i, j, seclen ;
+ char keym[ASCIILINESZ+1];
+
+ if (d==NULL || keys==NULL) return NULL;
+ if (! iniparser_find_entry(d, s)) return NULL;
+
+ seclen = 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
+ @param d Dictionary to search
+ @param key Key string to look for
+ @param def Default value to return if key not found.
+ @return pointer to statically allocated character string
+
+ 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 pointer passed as 'def' is returned.
+ The returned char pointer is pointing to a string allocated in
+ the dictionary, do not free or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+const char * iniparser_getstring(const dictionary * d, const char * key, const char * def)
+{
+ const char * lc_key ;
+ const char * sval ;
+ char tmp_str[ASCIILINESZ+1];
+
+ if (d==NULL || key==NULL)
+ return 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 long int
+ @param d Dictionary to search
+ @param key Key string to look for
+ @param notfound Value to return in case of error
+ @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,
+ 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()
+ */
+/*--------------------------------------------------------------------------*/
+long int iniparser_getlongint(const dictionary * d, const char * key, long int notfound)
+{
+ const char * str ;
+
+ str = iniparser_getstring(d, key, INI_INVALID_KEY);
+ if (str==NULL || str==INI_INVALID_KEY) return notfound ;
+ return strtol(str, NULL, 0);
+}
+
+int64_t iniparser_getint64(const dictionary * d, const char * key, int64_t notfound)
+{
+ const char * str ;
+
+ str = iniparser_getstring(d, key, INI_INVALID_KEY);
+ if (str==NULL || str==INI_INVALID_KEY) return notfound ;
+ return strtoimax(str, NULL, 0);
+}
+
+uint64_t iniparser_getuint64(const dictionary * d, const char * key, uint64_t notfound)
+{
+ const char * str ;
+
+ str = iniparser_getstring(d, key, INI_INVALID_KEY);
+ if (str==NULL || str==INI_INVALID_KEY) return notfound ;
+ return strtoumax(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);
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key, convert to a double
+ @param d Dictionary to search
+ @param key Key string to look for
+ @param notfound Value to return in case of error
+ @return double
+
+ 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.
+ */
+/*--------------------------------------------------------------------------*/
+double iniparser_getdouble(const dictionary * d, const char * key, double notfound)
+{
+ const char * str ;
+
+ str = iniparser_getstring(d, key, INI_INVALID_KEY);
+ if (str==NULL || str==INI_INVALID_KEY) return notfound ;
+ return atof(str);
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key, convert to a boolean
+ @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.
+
+ A true boolean is found if one of the following is matched:
+
+ - A string starting with 'y'
+ - A string starting with 'Y'
+ - A string starting with 't'
+ - A string starting with 'T'
+ - A string starting with '1'
+
+ A false boolean is found if one of the following is matched:
+
+ - A string starting with 'n'
+ - A string starting with 'N'
+ - A string starting with 'f'
+ - A string starting with 'F'
+ - A string starting with '0'
+
+ The notfound value returned if no boolean is identified, does not
+ necessarily have to be 0 or 1.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getboolean(const dictionary * d, const char * key, int notfound)
+{
+ int ret ;
+ const char * c ;
+
+ c = iniparser_getstring(d, key, INI_INVALID_KEY);
+ if (c==NULL || c==INI_INVALID_KEY) return notfound ;
+ if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
+ ret = 1 ;
+ } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') {
+ ret = 0 ;
+ } else {
+ ret = notfound ;
+ }
+ return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Finds out if a given entry exists in a dictionary
+ @param ini Dictionary to search
+ @param entry Name of the entry to look for
+ @return integer 1 if entry exists, 0 otherwise
+
+ Finds out if a given entry exists in the dictionary. Since sections
+ are stored as keys with NULL associated values, this is the only way
+ of querying for the presence of sections in a dictionary.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_find_entry(const dictionary * ini, const char * entry)
+{
+ int found=0 ;
+ if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
+ found = 1 ;
+ }
+ return found ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Set an entry in a dictionary.
+ @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.
+
+ If the given entry can be found in the dictionary, it is modified to
+ 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)
+{
+ char tmp_key[ASCIILINESZ+1] = {0};
+ char tmp_val[ASCIILINESZ+1] = {0};
+ size_t len;
+
+ if(val) {
+ len = strlen(val);
+ len = len > ASCIILINESZ ? ASCIILINESZ : len;
+ memcpy(tmp_val, val, len) ;
+ val = tmp_val;
+ }
+ return dictionary_set(ini, strlwc(entry, tmp_key, sizeof(tmp_key)), val);
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Delete an entry in a dictionary
+ @param ini Dictionary to modify
+ @param entry Entry to delete (entry name)
+ @return void
+
+ If the given entry can be found, it is deleted from the dictionary.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_unset(dictionary * ini, const char * entry)
+{
+ char tmp_str[ASCIILINESZ+1];
+ dictionary_unset(ini, strlwc(entry, tmp_str, sizeof(tmp_str)));
+}
+
+static void parse_quoted_value(char *value, char quote) {
+ char c;
+ char *quoted;
+ int q = 0, v = 0;
+ int esc = 0;
+
+ if(!value)
+ return;
+
+ quoted = xstrdup(value);
+
+ if(!quoted) {
+ iniparser_error_callback("iniparser: memory allocation failure\n");
+ goto end_of_value;
+ }
+
+ while((c = quoted[q]) != '\0') {
+ if(!esc) {
+ if(c == '\\') {
+ esc = 1;
+ q++;
+ continue;
+ }
+
+ if(c == quote) {
+ goto end_of_value;
+ }
+ }
+ esc = 0;
+ value[v] = c;
+ v++;
+ q++;
+ }
+end_of_value:
+ value[v] = '\0';
+ free(quoted);
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @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
+ @param value Output space to store value
+ @return line_status value
+ */
+/*--------------------------------------------------------------------------*/
+static line_status iniparser_line(
+ const char * input_line,
+ char * section,
+ char * key,
+ char * value)
+{
+ line_status sta ;
+ char * line = NULL;
+ size_t len ;
+ int d_quote;
+
+ line = xstrdup(input_line);
+ len = strstrip(line);
+
+ sta = LINE_UNPROCESSED ;
+ if (len<1) {
+ /* Empty line */
+ sta = LINE_EMPTY ;
+ } else if (line[0]=='#' || line[0]==';') {
+ /* Comment line */
+ sta = LINE_COMMENT ;
+ } else if (line[0]=='[' && line[len-1]==']') {
+ /* Section name without opening square bracket */
+ sscanf(line, "[%[^\n]", section);
+ len = strlen(section);
+ /* Section name without closing square bracket */
+ if(section[len-1] == ']')
+ {
+ section[len-1] = '\0';
+ }
+ strstrip(section);
+ strlwc(section, section, len);
+ sta = LINE_SECTION ;
+ } else if ((d_quote = sscanf (line, "%[^=] = \"%[^\n]\"", key, value)) == 2
+ || sscanf (line, "%[^=] = '%[^\n]'", key, value) == 2) {
+ /* Usual key=value with quotes, with or without comments */
+ strstrip(key);
+ strlwc(key, key, len);
+ if(d_quote == 2)
+ parse_quoted_value(value, '"');
+ else
+ parse_quoted_value(value, '\'');
+ /* 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
+ */
+ if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) {
+ value[0]=0 ;
+ }
+ sta = LINE_VALUE ;
+ } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2
+ || sscanf(line, "%[^=] %[=]", key, value) == 2) {
+ /*
+ * Special cases:
+ * key=
+ * key=;
+ * key=#
+ */
+ strstrip(key);
+ strlwc(key, key, len);
+ value[0]=0 ;
+ sta = LINE_VALUE ;
+ } else {
+ /* Generate syntax error */
+ sta = LINE_ERROR ;
+ }
+
+ free(line);
+ return sta ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Parse an ini file and return an allocated dictionary object
+ @param in File to read.
+ @param ininame Name of the ini file to read (only used for nicer error messages)
+ @return Pointer to newly allocated dictionary
+
+ This is the parser for ini files. This function is called, providing
+ the file to be read. It returns a dictionary object that should not
+ be accessed directly, but through accessor functions instead.
+
+ The returned dictionary must be freed using iniparser_freedict().
+ */
+/*--------------------------------------------------------------------------*/
+dictionary * iniparser_load_file(FILE * in, const char * ininame)
+{
+ 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 mem_err=0;
+
+ dictionary * dict ;
+
+ dict = dictionary_new(0) ;
+ if (!dict) {
+ return NULL ;
+ }
+
+ memset(line, 0, ASCIILINESZ);
+ memset(section, 0, ASCIILINESZ);
+ memset(key, 0, ASCIILINESZ);
+ memset(val, 0, ASCIILINESZ);
+ last=0 ;
+
+ while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
+ lineno++ ;
+ len = (int)strlen(line)-1;
+ if (len<=0)
+ continue;
+ /* Safety check against buffer overflows */
+ if (line[len]!='\n' && !feof(in)) {
+ iniparser_error_callback(
+ "iniparser: input line too long in %s (%d)\n",
+ ininame,
+ lineno);
+ dictionary_del(dict);
+ return NULL ;
+ }
+ /* Get rid of \n and spaces at end of line */
+ while ((len>=0) &&
+ ((line[len]=='\n') || (isspace((unsigned char)line[len])))) {
+ line[len]=0 ;
+ len-- ;
+ }
+ if (len < 0) { /* Line was entirely \n and/or spaces */
+ len = 0;
+ }
+ /* Detect multi-line */
+ if (line[len]=='\\') {
+ /* Multi-line value */
+ last=len ;
+ continue ;
+ } else {
+ last=0 ;
+ }
+ switch (iniparser_line(line, section, key, val)) {
+ case LINE_EMPTY:
+ case LINE_COMMENT:
+ break ;
+
+ case LINE_SECTION:
+ mem_err = dictionary_set(dict, section, NULL);
+ break ;
+
+ case LINE_VALUE:
+ sprintf(tmp, "%s:%s", section, key);
+ mem_err = dictionary_set(dict, tmp, val);
+ break ;
+
+ case LINE_ERROR:
+ iniparser_error_callback(
+ "iniparser: syntax error in %s (%d):\n-> %s\n",
+ ininame,
+ lineno,
+ line);
+ errs++ ;
+ break;
+
+ default:
+ break ;
+ }
+ memset(line, 0, ASCIILINESZ);
+ last=0;
+ if (mem_err<0) {
+ iniparser_error_callback("iniparser: memory allocation failure\n");
+ break ;
+ }
+ }
+ if (errs) {
+ dictionary_del(dict);
+ dict = NULL ;
+ }
+ return dict ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Parse an ini file and return an allocated dictionary object
+ @param ininame Name of the ini file to read.
+ @return Pointer to newly allocated dictionary
+
+ This is the parser for ini files. This function is called, providing
+ the name of the file to be read. It returns a dictionary object that
+ should not be accessed directly, but through accessor functions
+ instead.
+
+ The returned dictionary must be freed using iniparser_freedict().
+ */
+/*--------------------------------------------------------------------------*/
+dictionary * iniparser_load(const char * ininame)
+{
+ FILE * in ;
+ dictionary * dict ;
+
+ if ((in=fopen(ininame, "r"))==NULL) {
+ iniparser_error_callback("iniparser: cannot open %s\n", ininame);
+ return NULL ;
+ }
+
+ dict = iniparser_load_file(in, ininame);
+ fclose(in);
+
+ return dict ;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Free all memory associated to an ini dictionary
+ @param d Dictionary to free
+ @return void
+
+ Free all memory associated to an ini dictionary.
+ It is mandatory to call this function before the dictionary object
+ gets out of the current context.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_freedict(dictionary * d)
+{
+ dictionary_del(d);
+}
diff --git a/CONFIG/vita/iniparser_paf/src/iniparser.h b/CONFIG/vita/iniparser_paf/src/iniparser.h
new file mode 100644
index 00000000..d8026a81
--- /dev/null
+++ b/CONFIG/vita/iniparser_paf/src/iniparser.h
@@ -0,0 +1,446 @@
+
+/*-------------------------------------------------------------------------*/
+/**
+ @file iniparser.h
+ @author N. Devillard
+ @brief Parser for ini files.
+*/
+/*--------------------------------------------------------------------------*/
+
+#ifndef _INIPARSER_H_
+#define _INIPARSER_H_
+
+/*---------------------------------------------------------------------------
+ Includes
+ ---------------------------------------------------------------------------*/
+
+#include "dictionary.h"
+#include
+
+#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 *, ...));
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get number of sections in a dictionary
+ @param d Dictionary to examine
+ @return int Number of sections found in dictionary
+
+ This function returns the number of sections found in a dictionary.
+ The test to recognize sections is done on the string stored in the
+ dictionary: a section name is given as "section" whereas a key is
+ stored as "section:key", thus the test looks for entries that do not
+ contain a colon.
+
+ This clearly fails in the case a section name contains a colon, but
+ this should simply be avoided.
+
+ This function returns -1 in case of error.
+ */
+/*--------------------------------------------------------------------------*/
+
+int iniparser_getnsec(const dictionary * d);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get name for section n in a dictionary.
+ @param d Dictionary to examine
+ @param n Section number (from 0 to nsec-1).
+ @return Pointer to char string
+
+ This function locates the n-th section in a dictionary and returns
+ its name as a pointer to a string statically allocated inside the
+ dictionary. Do not free or modify the returned string!
+
+ This function returns NULL in case of error.
+ */
+/*--------------------------------------------------------------------------*/
+
+const char * iniparser_getsecname(const dictionary * d, int n);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Save a dictionary to a loadable ini file
+ @param d Dictionary to dump
+ @param f Opened file pointer to dump to
+
+ This function dumps a given dictionary into a loadable ini file.
+ It is Ok to specify @c stderr or @c stdout as output files.
+
+ All values are quoted, these charecters are escaped:
+
+ - ' : the quote character (e.g. "String with \"Quotes\"")
+ - \ : the backslash character (e.g. "C:\\tmp")
+
+ */
+/*--------------------------------------------------------------------------*/
+
+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
+
+ 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);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Dump a dictionary to an opened file pointer.
+ @param d Dictionary to dump.
+ @param f Opened file pointer to dump to.
+
+ This function prints out the contents of a dictionary, one element by
+ line, onto the provided file pointer. It is OK to specify @c stderr
+ or @c stdout as output files. This function is meant for debugging
+ purposes mostly.
+ */
+/*--------------------------------------------------------------------------*/
+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);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key
+ @param d Dictionary to search
+ @param key Key string to look for
+ @param def Default value to return if key not found.
+ @return pointer to statically allocated character string
+
+ 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 pointer passed as 'def' is returned.
+ The returned char pointer is pointing to a string allocated in
+ the dictionary, do not free or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+const char * iniparser_getstring(const dictionary * d, const char * key, const char * def);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @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);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @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);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key, convert to an int64_t
+ @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 strtoimax(), see the associated man page for overflow
+ handling.
+
+ This function is usefull on 32bit architectures where `long int` is only
+ 32bit.
+ */
+/*--------------------------------------------------------------------------*/
+int64_t iniparser_getint64(const dictionary * d, const char * key, int64_t notfound);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key, convert to an uint64_t
+ @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 strtoumax(), see the associated man page for overflow
+ handling.
+
+ This function is usefull on 32bit architectures where `long int` is only
+ 32bit.
+ */
+/*--------------------------------------------------------------------------*/
+uint64_t iniparser_getuint64(const dictionary * d, const char * key, uint64_t notfound);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key, convert to a double
+ @param d Dictionary to search
+ @param key Key string to look for
+ @param notfound Value to return in case of error
+ @return double
+
+ 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.
+ */
+/*--------------------------------------------------------------------------*/
+double iniparser_getdouble(const dictionary * d, const char * key, double notfound);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Get the string associated to a key, convert to a boolean
+ @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.
+
+ A true boolean is found if one of the following is matched:
+
+ - A string starting with 'y'
+ - A string starting with 'Y'
+ - A string starting with 't'
+ - A string starting with 'T'
+ - A string starting with '1'
+
+ A false boolean is found if one of the following is matched:
+
+ - A string starting with 'n'
+ - A string starting with 'N'
+ - A string starting with 'f'
+ - A string starting with 'F'
+ - A string starting with '0'
+
+ The notfound value returned if no boolean is identified, does not
+ necessarily have to be 0 or 1.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getboolean(const dictionary * d, const char * key, int notfound);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Set an entry in a dictionary.
+ @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.
+
+ If the given entry can be found in the dictionary, it is modified to
+ 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);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Delete an entry in a dictionary
+ @param ini Dictionary to modify
+ @param entry Entry to delete (entry name)
+
+ If the given entry can be found, it is deleted from the dictionary.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_unset(dictionary * ini, const char * entry);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Finds out if a given entry exists in a dictionary
+ @param ini Dictionary to search
+ @param entry Name of the entry to look for
+ @return integer 1 if entry exists, 0 otherwise
+
+ Finds out if a given entry exists in the dictionary. Since sections
+ are stored as keys with NULL associated values, this is the only way
+ of querying for the presence of sections in a dictionary.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_find_entry(const dictionary * ini, const char * entry) ;
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Parse an ini file and return an allocated dictionary object
+ @param ininame Name of the ini file to read.
+ @return Pointer to newly allocated dictionary
+
+ This is the parser for ini files. This function is called, providing
+ the name of the file to be read. It returns a dictionary object that
+ should not be accessed directly, but through accessor functions
+ instead.
+
+ Iff the value is a quoted string it supports some escape sequences:
+
+ - \" or ' : the quote character
+ (e.g. 'String with "Quotes"' or "String with 'Quotes'")
+ - \ : the backslash character (e.g. "C:\tmp")
+
+ Escape sequences always start with a backslash. Additional escape sequences
+ might be added in the future. Backslash characters must be escaped. Any other
+ sequence then those outlined above is invalid and may lead to unpredictable
+ results.
+
+ The returned dictionary must be freed using iniparser_freedict().
+ */
+/*--------------------------------------------------------------------------*/
+dictionary * iniparser_load(const char * ininame);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Parse an ini file and return an allocated dictionary object
+ @param in File to read.
+ @param ininame Name of the ini file to read (only used for nicer error messages)
+ @return Pointer to newly allocated dictionary
+
+ This is the parser for ini files. This function is called, providing
+ the file to be read. It returns a dictionary object that should not
+ be accessed directly, but through accessor functions instead.
+
+ Iff the value is a quoted string it supports some escape sequences:
+
+ - \" or ' : the quote character
+ (e.g. 'String with "Quotes"' or "String with 'Quotes'")
+ - \ : the backslash character (e.g. "C:\tmp")
+
+ Escape sequences always start with a backslash. Additional escape sequences
+ might be added in the future. Backslash characters must be escaped. Any other
+ sequence then those outlined above is invalid and may lead to unpredictable
+ results.
+
+ The returned dictionary must be freed using iniparser_freedict().
+ */
+/*--------------------------------------------------------------------------*/
+dictionary * iniparser_load_file(FILE * in, const char * ininame);
+
+/*-------------------------------------------------------------------------*/
+/**
+ @brief Free all memory associated to an ini dictionary
+ @param d Dictionary to free
+
+ Free all memory associated to an ini dictionary.
+ It is mandatory to call this function before the dictionary object
+ gets out of the current context.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_freedict(dictionary * d);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/CONFIG/vita/iniparser_paf/src/pafstd.h b/CONFIG/vita/iniparser_paf/src/pafstd.h
new file mode 100644
index 00000000..469cd561
--- /dev/null
+++ b/CONFIG/vita/iniparser_paf/src/pafstd.h
@@ -0,0 +1,44 @@
+#ifndef __PAFSTD__
+#define __PAFSTD__
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define malloc sce_paf_malloc
+#define memcpy sce_paf_memcpy
+#define memset sce_paf_memset
+#define memmove sce_paf_memmove
+#define free sce_paf_free
+#define calloc sce_paf_calloc
+
+// _ctype_ isnt called that in scelibc, so just stub the functions that are needed
+
+inline int _is_space(char c) {
+ return (c == ' ' || c == '\f' || c == '\n' ||
+ c == '\r' || c == '\t' || c == '\v');
+}
+
+inline int _to_lower(int c) {
+ if (c >= 'A' && c <= 'Z') {
+ return c + ('a' - 'A');
+ }
+ return c;
+}
+
+inline int _is_digit(int c) {
+ return (c >= '0' && c <= '9');
+}
+
+#undef isspace
+#undef tolower
+#undef isdigit
+#define isspace _is_space
+#define tolower _to_lower
+#define isdigit _is_digit
+
+#endif
\ No newline at end of file
diff --git a/CONFIG/vita/src/app.cpp b/CONFIG/vita/src/app.cpp
index a636e3c0..8b31547a 100644
--- a/CONFIG/vita/src/app.cpp
+++ b/CONFIG/vita/src/app.cpp
@@ -1,55 +1,395 @@
-// clang-format off
-#include
-#include
-// clang-format on
+#include "pafinc.h"
+#include
#include
+#include
+#include
+#include
+#include
+
+#include "fios2.h"
+#include
+
+const char* g_iniPath = "ux0:data/isledecomp/isle/isle.ini";
paf::Framework* g_fw;
-paf::ui::Scene* g_rootPage;
-paf::Plugin* g_plugin;
+paf::Plugin* g_configPlugin;
+sce::AppSettings* g_appSettings;
+sce::AppSettings::Interface* g_appSetIf;
-void loadPluginCB(paf::Plugin* plugin)
-{
- g_plugin = plugin;
- plugin->SetLocale(Locale_EN);
- paf::Plugin::PageOpenParam pageOpenParam;
- pageOpenParam.option = paf::Plugin::PageOption_None;
- paf::ui::Scene* pScene = plugin->PageOpen("page_main", pageOpenParam);
- g_rootPage = pScene;
+struct Config {
+ paf::string m_base_path;
+ paf::string m_cd_path;
+ paf::string m_save_path;
+ int m_transition_type;
+ int m_texture_quality;
+ int m_model_quality;
+ int m_touch_scheme;
+ bool m_wide_view_angle;
+ bool m_music;
+ bool m_3d_sound;
+ bool m_haptic;
+ bool m_draw_cursor;
+ bool m_texture_load;
+ paf::string m_texture_path;
+ float m_max_lod;
+ int m_max_actors;
+ float m_frame_delta;
- const auto saveAndExitButton = static_cast(pScene->FindChild("save_exit_button"));
- const auto startAndExitButton = static_cast(pScene->FindChild("start_game_button"));
- const auto exitButton = static_cast(pScene->FindChild("exit_button"));
+ void Init() {
+ m_frame_delta = 10.0f;
+ m_transition_type = 3; // 3: Mosaic
+ m_wide_view_angle = true;
+ m_music = true;
+ m_3d_sound = true;
+ m_haptic = true;
+ m_touch_scheme = 2;
+ m_texture_load = true;
+ m_texture_path = "/textures/";
+ m_model_quality = 2;
+ m_texture_quality = 1;
+ m_max_lod = 3.5f;
+ m_max_actors = 20;
+ }
+
+ void LoadIni() {
+ dictionary* dict = iniparser_load(g_iniPath);
+ if (!dict) {
+ dict = dictionary_new(0);
+ }
+
+#define GET_INT(x, name) x = iniparser_getint(dict, name, x)
+#define GET_FLOAT(x, name) x = iniparser_getdouble(dict, name, x)
+#define GET_STRING(x, name) x = iniparser_getstring(dict, name, x.c_str()); sceClibPrintf("%s: %s\n", name, x.c_str())
+#define GET_BOOLEAN(x, name) x = iniparser_getboolean(dict, name, x)
+
+ GET_STRING(m_base_path, "isle:diskpath");
+ GET_STRING(m_cd_path, "isle:cdpath");
+ GET_STRING(m_save_path, "isle:savepath");
+
+ //m_display_bit_depth = iniparser_getint(dict, "isle:Display Bit Depth", -1);
+ //GET_BOOLEAN(m_flip_surfaces, "isle:Flip Surfaces");
+ //GET_BOOLEAN(m_full_screen, "isle:Full Screen");
+ //GET_BOOLEAN(m_exclusive_full_screen, "isle:Exclusive Full Screen");
+ GET_INT(m_transition_type, "isle:Transition Type");
+ GET_INT(m_touch_scheme, "isle:Touch Scheme");
+ //GET_BOOLEAN(m_3d_video_ram, "isle:Back Buffers in Video RAM");
+ GET_BOOLEAN(m_wide_view_angle, "isle:Wide View Angle");
+ GET_BOOLEAN(m_3d_sound, "isle:3DSound");
+ GET_BOOLEAN(m_draw_cursor, "isle:Draw Cursor");
+ GET_INT(m_model_quality, "isle:Island Quality");
+ GET_INT(m_texture_quality, "isle:Island Texture");
+ //GET_BOOLEAN(m_use_joystick, "isle:UseJoystick");
+ GET_BOOLEAN(m_haptic, "isle:Haptic");
+ GET_BOOLEAN(m_music, "isle:Music");
+ //GET_INT(m_joystick_index, "isle:JoystickIndex");
+ GET_FLOAT(m_max_lod, "isle:Max LOD");
+ GET_INT(m_max_actors, "isle:Max Allowed Extras");
+ GET_BOOLEAN(m_texture_load, "extensions:texture loader");
+ GET_STRING(m_texture_path, "texture loader:texture path");
+ //GET_INT(m_aspect_ratio, "isle:Aspect Ratio");
+ //GET_INT(m_x_res, "isle:Horizontal Resolution");
+ //GET_INT(m_y_res, "isle:Vertical Resolution");
+ GET_FLOAT(m_frame_delta, "isle:Frame Delta");
+#undef GET_INT
+#undef GET_FLOAT
+#undef GET_STRING
+#undef GET_BOOLEAN
+ iniparser_freedict(dict);
+ }
+
+ bool SaveIni() {
+ dictionary* dict = dictionary_new(0);
+
+ char buffer[128];
+#define SetIniBool(NAME, VALUE) iniparser_set(dict, NAME, VALUE ? "true" : "false")
+#define SetIniInt(NAME, VALUE) { \
+ sceClibPrintf(buffer, "%d", VALUE); \
+ iniparser_set(dict, NAME, buffer); \
+ }
+#define SetIniFloat(NAME, VALUE) { \
+ sceClibPrintf(buffer, "%f", VALUE); \
+ iniparser_set(dict, NAME, buffer); \
+ }
+#define SetString(NAME, VALUE) iniparser_set(dict, NAME, VALUE)
+
+ SetIniInt("isle:Display Bit Depth", 32);
+ SetIniBool("isle:Flip Surfaces", false);
+ SetIniBool("isle:Full Screen", true);
+ SetIniBool("isle:Exclusive Full Screen", true);
+ SetIniBool("isle:Wide View Angle", true); // option?
+
+ SetIniInt("isle:Transition Type", m_transition_type);
+ SetIniInt("isle:Touch Scheme", m_touch_scheme);
+
+ SetIniBool("isle:3DSound", m_3d_sound);
+ SetIniBool("isle:Music", m_music);
+ SetIniBool("isle:Haptic", m_haptic);
+
+ SetIniBool("isle:UseJoystick", true);
+ SetIniInt("isle:JoystickIndex", 0);
+ SetIniBool("isle:Draw Cursor", m_draw_cursor);
+
+ SetIniBool("extensions:texture loader", m_texture_load);
+ SetString("texture loader:texture path", m_texture_path.c_str());
+
+ SetIniBool("isle:Back Buffers in Video RAM", true);
+
+ SetIniInt("isle:Island Quality", m_model_quality);
+ SetIniInt("isle:Island Texture", m_texture_quality);
+
+ SetIniFloat("isle:Max LOD", m_max_lod);
+ SetIniInt("isle:Max Allowed Extras", m_max_actors);
+
+ SetIniInt("isle:Aspect Ratio", 0);
+ SetIniInt("isle:Horizontal Resolution", 640);
+ SetIniInt("isle:Vertical Resolution", 480);
+ SetIniFloat("isle:Frame Delta", 10.0f);
+
+#undef SetIniBool
+#undef SetIniInt
+#undef SetIniFloat
+#undef SetString
+
+ FILE* fd = fopen(g_iniPath, "w");
+ if(fd) {
+ iniparser_dump_ini(dict, fd);
+ }
+ iniparser_freedict(dict);
+
+ return true;
+ }
+
+ void ToSettings(sce::AppSettings* appSettings) {
+ appSettings->SetString("data_path", this->m_base_path.c_str());
+ appSettings->SetString("save_path", this->m_save_path.c_str());
+ }
+
+ void FromSettings(sce::AppSettings* appSettings) {
+
+ }
+};
+
+Config g_config;
+
+paf::Plugin* load_config_plugin(paf::Framework* paf_fw) {
+ paf::Plugin::InitParam pluginParam;
+ pluginParam.name = "config_plugin";
+ pluginParam.caller_name = "__main__";
+ pluginParam.resource_file = "app0:/config_plugin.rco";
+ pluginParam.init_func = NULL;
+ pluginParam.start_func = NULL;
+ pluginParam.stop_func = NULL;
+ pluginParam.exit_func = NULL;
+ paf::Plugin::LoadSync(pluginParam);
+ return paf_fw->FindPlugin("config_plugin");
}
-int paf_main(void)
+int load_app_settings_plugin() {
+ paf::Plugin::InitParam pluginParam;
+ sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_BXCE);
+ sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_INI_FILE_PROCESSOR);
+ sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_COMMON_GUI_DIALOG);
+
+ pluginParam.name = "app_settings_plugin";
+ pluginParam.resource_file = "vs0:vsh/common/app_settings_plugin.rco";
+ pluginParam.caller_name = "__main__";
+ pluginParam.set_param_func = sce::AppSettings::PluginSetParamCB;
+ pluginParam.init_func = sce::AppSettings::PluginInitCB;
+ pluginParam.start_func = sce::AppSettings::PluginStartCB;
+ pluginParam.stop_func = sce::AppSettings::PluginStopCB;
+ pluginParam.exit_func = sce::AppSettings::PluginExitCB;
+ pluginParam.module_file = "vs0:vsh/common/app_settings.suprx";
+ pluginParam.draw_priority = 0x96;
+ paf::Plugin::LoadSync(pluginParam);
+ return 0;
+}
+
+bool do_launch = false;
+
+void save_and_exit() {
+ g_config.FromSettings(g_appSettings);
+ g_config.SaveIni();
+ g_fw->RequestShutdown();
+}
+
+void save_and_launch() {
+ g_config.FromSettings(g_appSettings);
+ g_config.SaveIni();
+ g_fw->RequestShutdown();
+ do_launch = true;
+}
+
+void CBOnStartPageTransition(const char *elementId, int32_t type)
{
- paf::Framework::InitParam fwParam;
+
+}
+
+void CBOnPageActivate(const char *elementId, int32_t type)
+{
+
+}
+
+void CBOnPageDeactivate(const char *elementId, int32_t type)
+{
+
+}
+
+int32_t CBOnCheckVisible(const char *elementId, bool *pIsVisible)
+{
+ *pIsVisible = true;
+ return SCE_OK;
+}
+
+int32_t CBOnPreCreate(const char *elementId, sce::AppSettings::Element *element)
+{
+ return SCE_OK;
+}
+
+int32_t CBOnPostCreate(const char *elementId, paf::ui::Widget *widget)
+{
+ return SCE_OK;
+}
+
+int32_t CBOnPress(const char *elementId, const char *newValue)
+{
+ if(sce_paf_strcmp(elementId, "save_exit_button") == 0) {
+ save_and_exit();
+ return SCE_OK;
+ }
+
+ if(sce_paf_strcmp(elementId, "save_launch_button") == 0) {
+ save_and_launch();
+ return SCE_OK;
+ }
+
+ sceClibPrintf("OnPress %s %s\n", elementId, newValue);
+ return SCE_OK;
+}
+
+int32_t CBOnPress2(const char *elementId, const char *newValue)
+{
+ return SCE_OK;
+}
+
+void CBOnTerm(int32_t result)
+{
+ sceKernelExitProcess(0);
+}
+
+const wchar_t *CBOnGetString(const char *elementId)
+{
+ wchar_t* res = g_configPlugin->GetString(elementId);
+ if(res[0] != 0) {
+ return res;
+ }
+ return L"unknown string";
+}
+
+int32_t CBOnGetSurface(paf::graph::Surface **surf, const char *elementId)
+{
+ return SCE_OK;
+}
+
+void open_settings() {
+ g_config.Init();
+ g_config.LoadIni();
+ g_config.ToSettings(g_appSettings);
+
+ sce::AppSettings::InterfaceCallbacks ifCb;
+ ifCb.onStartPageTransitionCb = CBOnStartPageTransition;
+ ifCb.onPageActivateCb = CBOnPageActivate;
+ ifCb.onPageDeactivateCb = CBOnPageDeactivate;
+ ifCb.onCheckVisible = CBOnCheckVisible;
+ ifCb.onPreCreateCb = CBOnPreCreate;
+ ifCb.onPostCreateCb = CBOnPostCreate;
+ ifCb.onPressCb = CBOnPress;
+ ifCb.onPressCb2 = CBOnPress2;
+ ifCb.onTermCb = CBOnTerm;
+ ifCb.onGetStringCb = (sce::AppSettings::InterfaceCallbacks::GetStringCallback)CBOnGetString;
+ ifCb.onGetSurfaceCb = CBOnGetSurface;
+
+ paf::wstring msg_save_exit(g_configPlugin->GetString("msg_save_exit"));
+ paf::wstring msg_save_launch(g_configPlugin->GetString("msg_save_launch"));
+ paf::wstring msg_exit(g_configPlugin->GetString("msg_exit"));
+
+ paf::Plugin* appSetPlug = paf::Plugin::Find("app_settings_plugin");
+ g_appSetIf = (sce::AppSettings::Interface *)appSetPlug->GetInterface(1);
+ g_appSetIf->Show(&ifCb);
+ g_appSetIf->AddFooterButton("save_exit_button", &msg_save_exit, 1);
+ g_appSetIf->AddFooterButton("save_launch_button", &msg_save_launch, 2);
+ g_appSetIf->ShowFooter();
+}
+
+
+#define MAX_PATH_LENGTH 256
+
+static int64_t g_OpStorage[SCE_FIOS_OP_STORAGE_SIZE(64, MAX_PATH_LENGTH) / sizeof(int64_t) + 1];
+static int64_t g_ChunkStorage[SCE_FIOS_CHUNK_STORAGE_SIZE(1024) / sizeof(int64_t) + 1];
+static int64_t g_FHStorage[SCE_FIOS_FH_STORAGE_SIZE(1024, MAX_PATH_LENGTH) / sizeof(int64_t) + 1];
+static int64_t g_DHStorage[SCE_FIOS_DH_STORAGE_SIZE(32, MAX_PATH_LENGTH) / sizeof(int64_t) + 1];
+
+void init_fios2() {
+ sceSysmoduleLoadModule(SCE_SYSMODULE_FIOS2);
+ SceFiosParams params = SCE_FIOS_PARAMS_INITIALIZER;
+ params.opStorage.pPtr = g_OpStorage;
+ params.opStorage.length = sizeof(g_OpStorage);
+ params.chunkStorage.pPtr = g_ChunkStorage;
+ params.chunkStorage.length = sizeof(g_ChunkStorage);
+ params.fhStorage.pPtr = g_FHStorage;
+ params.fhStorage.length = sizeof(g_FHStorage);
+ params.dhStorage.pPtr = g_DHStorage;
+ params.dhStorage.length = sizeof(g_DHStorage);
+ params.pathMax = MAX_PATH_LENGTH;
+
+ params.threadAffinity[SCE_FIOS_IO_THREAD] = 0x10000;
+ params.threadAffinity[SCE_FIOS_CALLBACK_THREAD] = 0;
+ params.threadAffinity[SCE_FIOS_DECOMPRESSOR_THREAD] = 0;
+
+ params.threadPriority[SCE_FIOS_IO_THREAD] = 64;
+ params.threadPriority[SCE_FIOS_CALLBACK_THREAD] = 191;
+ params.threadPriority[SCE_FIOS_DECOMPRESSOR_THREAD] = 191;
+ int ret = sceFiosInitialize(¶ms);
+ if(ret < 0) {
+ sceClibPrintf("sceFiosInitialize: %08x\n", ret);
+ }
+}
+
+int paf_main(void) {
+ init_fios2();
+
+ paf::Framework::InitParam fwParam;
fwParam.mode = paf::Framework::Mode_Normal;
- paf::Framework* paf_fw = new paf::Framework(fwParam);
- if (paf_fw != NULL) {
- g_fw = paf_fw;
+ paf::Framework* paf_fw = new paf::Framework(fwParam);
+ g_fw = paf_fw;
- paf_fw->LoadCommonResourceSync();
+ paf_fw->LoadCommonResourceSync();
+ load_app_settings_plugin();
+ paf::Plugin* configPlugin = load_config_plugin(paf_fw);
+ g_configPlugin = configPlugin;
+ configPlugin->SetLocale(Locale_EN);
- paf::Plugin::InitParam pluginParam;
+ size_t fileSize = 0;
+ const char *mimeType = nullptr;
+ auto settingsXmlFile = configPlugin->GetResource()->GetFile("settings.xml", &fileSize, &mimeType);
- pluginParam.name = "config_plugin";
- pluginParam.caller_name = "__main__";
- pluginParam.resource_file = "app0:/config_plugin.rco";
- pluginParam.init_func = NULL;
- pluginParam.start_func = loadPluginCB;
- pluginParam.stop_func = NULL;
- pluginParam.exit_func = NULL;
+ sce::AppSettings::InitParam settingsParam;
+ settingsParam.xml_file = settingsXmlFile;
+ settingsParam.alloc_cb = sce_paf_malloc;
+ settingsParam.free_cb = sce_paf_free;
+ settingsParam.realloc_cb = sce_paf_realloc;
+ settingsParam.safemem_offset = 0;
+ settingsParam.safemem_size = 0x400;
- paf::Plugin::LoadSync(pluginParam);
- paf_fw->Run();
- }
+ sce::AppSettings::GetInstance(settingsParam, &g_appSettings);
+ g_appSettings->Initialize();
- sceClibPrintf("[SAMPLE] Failed to run PAF instance\n");
+ open_settings();
+ paf_fw->Run();
- exit(0);
- return 0;
+ if(do_launch) {
+ sceAppMgrLoadExec("app0:/eboot.bin", NULL, NULL);
+ }
+ return 0;
}
diff --git a/CONFIG/vita/src/main.cpp b/CONFIG/vita/src/main.cpp
index 10f1d1ac..0433fafa 100644
--- a/CONFIG/vita/src/main.cpp
+++ b/CONFIG/vita/src/main.cpp
@@ -1,7 +1,4 @@
-// clang-format off
-#include
-#include
-// clang-format on
+#include "pafinc.h"
#include
#include
#include
@@ -59,8 +56,8 @@ extern "C" int module_start(SceSize args, void* argp)
);
}
- paf_main();
-
+ res = paf_main();
+ sceKernelExitProcess(res);
return SCE_KERNEL_START_SUCCESS;
}