/*
 * Copyright (c) 2002-2017  Martin Hedenfalk <martin@bzero.se>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/** A configuration file parser library.
 * @file confuse.h
 *
 */

#ifndef CONFUSE_H_
#define CONFUSE_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>

#if defined(_WIN32) && !defined(__GNUC__)
# ifdef HAVE__FILENO
#  define fileno _fileno
# endif
# include <io.h>
# ifdef HAVE__ISATTY
#  define isatty _isatty
# endif
# ifdef BUILDING_STATIC
#  define DLLIMPORT
# else /* ! BUILDING_STATIC */
#  ifdef BUILDING_DLL
#   define DLLIMPORT __declspec (dllexport)
#  else /* ! BUILDING_DLL */
#   define DLLIMPORT __declspec (dllimport)
#  endif /* BUILDING_DLL */
# endif /* BUILDING_STATIC */
#else /* ! _WIN32 || __GNUC__ */
# define DLLIMPORT
#endif /* _WIN32 */

#ifndef __BORLANDC__
# define __export
#endif

/** Fundamental option types */
enum cfg_type_t {
	CFGT_NONE,
	CFGT_INT,    /**< integer */
	CFGT_FLOAT,  /**< floating point number */
	CFGT_STR,    /**< string */
	CFGT_BOOL,   /**< boolean value */
	CFGT_SEC,    /**< section */
	CFGT_FUNC,   /**< function */
	CFGT_PTR,    /**< pointer to user-defined value */
	CFGT_COMMENT,/**< comment/annotation */
	CFGT_RAWSEC, /**< section whose body is captured verbatim as a string */
	CFGT_INT64,  /**< 64-bit signed integer */
	CFGT_UINT32, /**< 32-bit unsigned integer */
	CFGT_UINT64, /**< 64-bit unsigned integer */
	CFGT_INT8,   /**< 8-bit signed integer */
	CFGT_INT16,  /**< 16-bit signed integer */
	CFGT_INT32,  /**< 32-bit signed integer */
	CFGT_UINT8,  /**< 8-bit unsigned integer */
	CFGT_UINT16  /**< 16-bit unsigned integer */
};
typedef enum cfg_type_t cfg_type_t;	/**< A fundamental option type, one of the CFGT_* values */

/** Flags. */
#define CFGF_NONE           (0)        /**< no flags */
#define CFGF_MULTI          (1 <<  0) /**< option may be specified multiple times (only applies to sections) */
#define CFGF_LIST           (1 <<  1) /**< option is a list */
#define CFGF_NOCASE         (1 <<  2) /**< configuration file is case insensitive */
#define CFGF_TITLE          (1 <<  3) /**< option has a title (only applies to sections) */
#define CFGF_NODEFAULT      (1 <<  4) /**< option has no default value */
#define CFGF_NO_TITLE_DUPES (1 <<  5) /**< multiple section titles must be unique
					  (duplicates raises an error, only applies to sections) */

#define CFGF_RESET          (1 <<  6) /**< used internally to clear an option's values before (re)setting */
#define CFGF_DEFINIT        (1 <<  7) /**< used internally, the option's default value has been initialized */
#define CFGF_IGNORE_UNKNOWN (1 <<  8) /**< ignore unknown options in configuration files */
#define CFGF_DEPRECATED     (1 <<  9) /**< option is deprecated and should be ignored. */
#define CFGF_DROP           (1 << 10) /**< option should be dropped after parsing */
#define CFGF_COMMENTS       (1 << 11) /**< Enable option annotation/comments support */
#define CFGF_MODIFIED       (1 << 12) /**< option has been changed from its default value */
#define CFGF_KEYSTRVAL      (1 << 13) /**< section has free-form key=value string options created when parsing file */
#define CFGF_USE_INCLUDE_FUNCTION (1 << 14) /**< add an include() function to the section's options */
#define CFGF_JSON_LISTS (1 << 15) /**< accept and print JSON-style [ ] as an alternative to { } for lists */

/* Return codes from cfg_parse(), cfg_parse_boolean(), and cfg_set*() functions. */
#define CFG_SUCCESS     0  /**< Success, all OK (POSIX '0') */
#define CFG_FAIL       -1  /**< Generic failure */
#define CFG_FILE_ERROR -1  /**< Error opening the configuration file */
#define CFG_PARSE_ERROR 1  /**< Error parsing the configuration */

typedef union cfg_value_t cfg_value_t;		/**< A fundamental option value */
typedef union cfg_simple_t cfg_simple_t;	/**< Pointer to a user variable, for CFG_SIMPLE_* options */
typedef struct cfg_opt_t cfg_opt_t;		/**< Describes a single configuration option */
typedef struct cfg_t cfg_t;			/**< A configuration context (the file or a section) */
typedef struct cfg_defvalue_t cfg_defvalue_t;	/**< Holds an option's default value */
typedef int cfg_flag_t;				/**< Option flags, a bitwise OR of CFGF_* values */
typedef struct cfg_searchpath_t cfg_searchpath_t; /**< An entry in the include search path */

/** Function prototype used by CFGT_FUNC options.
 *
 * This is a callback function, registered with the CFG_FUNC
 * initializer. Each time libConfuse finds a function, the registered
 * callback function is called (parameters are passed as strings, any
 * conversion to other types should be made in the callback
 * function). libConfuse does not support any storage of the data
 * found; these are passed as parameters to the callback, and it's the
 * responsibility of the callback function to do whatever it should do
 * with the data.
 *
 * @param cfg The configuration file context.
 * @param opt The option.
 * @param argc Number of arguments passed. The callback function is
 * responsible for checking that the correct number of arguments are
 * passed.
 * @param argv Arguments as an array of character strings.
 *
 * @return On success, 0 should be returned. All other values
 * indicates an error, and the parsing is aborted. The callback
 * function should notify the error itself, for example by calling
 * cfg_error().
 *
 * @see CFG_FUNC
 */
typedef int (*cfg_func_t)(cfg_t *cfg, cfg_opt_t *opt, int argc, const char **argv);

/** Function prototype used by the cfg_print_ functions.
 *
 * This callback function is used to print option values. For options
 * with a value parsing callback, this is often required, especially
 * if a string is mapped to an integer by the callback. This print
 * callback must then map the integer back to the appropriate string.
 *
 * Except for functions, the print callback function should only print
 * the value of the option, not the name and the equal sign (that is
 * handled by the cfg_opt_print function). For function options
 * however, the name and the parenthesis must be printed by this
 * function. The value to print can be accessed with the cfg_opt_get
 * functions.
 *
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get. Zero based.
 * @param fp File stream to print to, use stdout to print to the screen.
 *
 * @see cfg_print, cfg_set_print_func
 */
typedef void (*cfg_print_func_t)(cfg_opt_t *opt, unsigned int index, FILE *fp);

/** Value parsing callback prototype
 *
 * This is a callback function (different from the one registered with the
 * CFG_FUNC initializer) used to parse a value. This can be used to override
 * the internal parsing of a value.
 *
 * Suppose you want an integer option that only can have certain values, for
 * example 1, 2 and 3, and these should be written in the configuration file as
 * "yes", "no" and "maybe". The callback function would be called with the
 * found value ("yes", "no" or "maybe") as a string, and the result should be
 * stored in the result parameter.
 *
 * @param cfg The configuration file context.
 * @param opt The option.
 * @param value The value found in the configuration file.
 * @param result Pointer to storage for the result, cast to a void pointer.
 *
 * @return On success, 0 should be returned. All other values indicates an
 * error, and the parsing is aborted. The callback function should notify the
 * error itself, for example by calling cfg_error().
 */
typedef int (*cfg_callback_t)(cfg_t *cfg, cfg_opt_t *opt, const char *value, void *result);

/** Validating callback prototype
 *
 * This callback function is called after an option has been parsed and set.
 * The function is called for both fundamental values (strings, integers etc)
 * as well as lists and sections. This can for example be used to validate that
 * all required options in a section has been set to sane values.
 *
 * @return On success, 0 should be returned. All other values indicates an
 * error, and the parsing is aborted. The callback function should notify the
 * error itself, for example by calling cfg_error().
 *
 * @see cfg_set_validate_func
 */
typedef int (*cfg_validate_callback_t)(cfg_t *cfg, cfg_opt_t *opt);

/** Validating callback2 prototype
 *
 * This callback function is called before an option is set using the
 * cfg_set*() APIs.  The function is called only for strings, integers,
 * and floats.  Compared to the regular callback function this takes a
 * value pointer argument which must be cast before use, but can also
 * be used to correct a value before it is set, e.g. when a too large
 * value is set this can be used to set the MAX.
 *
 * @return On success, 0 should be returned. All other values indicates an
 * error, and the cfg_set*() function will return without setting the value.
 *
 * @see cfg_set_validate_func2()
 */
typedef int (*cfg_validate_callback2_t)(cfg_t *cfg, cfg_opt_t *opt, void *value);

/** User-defined memory release function for CFG_PTR values
 *
 * This callback is used to free memory allocated in a value parsing callback
 * function. Especially useful for CFG_PTR options, since libConfuse will not
 * itself release such values. If the values are simply allocated with a
 * malloc(3), one can use the standard free(3) function here.
 *
 */
typedef void (*cfg_free_func_t)(void *value);

/** Boolean values. */
typedef enum { cfg_false, cfg_true } cfg_bool_t;

/** Error reporting function. */
typedef void (*cfg_errfunc_t)(cfg_t *cfg, const char *fmt, va_list ap);

/** Print filter function.
 *
 * @param cfg The configuration file context that opt belongs to.
 * @param opt The configuration option that is about to be printed, or not.
 * @return Zero if opt should be printed, non-zero if it should be filtered
 * out.
 *
 * @see cfg_set_print_filter_func()
 */
typedef int (*cfg_print_filter_func_t)(cfg_t *cfg, cfg_opt_t *opt);

/** Data structure holding information about a "section". Sections can
 * be nested. A section has a list of options (strings, numbers,
 * booleans or other sections) grouped together.
 */
struct cfg_t {
	cfg_flag_t flags;	/**< Any flags passed to cfg_init() */
	char *name;		/**< The name of this section, the root
				 * section returned from cfg_init() is
				 * always named "root" */
	char *comment;	        /**< Optional annotation/comment */
	cfg_opt_t *opts;        /**< Array of options */
	char *title;	        /**< Optional title for this section, only
				 * set if CFGF_TITLE flag is set */
	char *filename;		/**< Name of the file being parsed */
	int line;		/**< Line number in the config file */
	cfg_errfunc_t errfunc;	/**< This function (if set with
				 * cfg_set_error_function) is called for
				 * any error message. */
	cfg_searchpath_t *path;	/**< Linked list of directories to search */
	cfg_print_filter_func_t pff; /**< Printing filter function */
	char *raw;		/**< Verbatim body, set for CFGT_RAWSEC sections */
};

/** Data structure holding the value of a fundamental option value.
 */
union cfg_value_t {
	long int number;	/**< integer value */
	int8_t   i8;		/**< 8-bit signed integer value */
	int16_t  i16;		/**< 16-bit signed integer value */
	int32_t  i32;		/**< 32-bit signed integer value */
	int64_t  i64;		/**< 64-bit signed integer value */
	uint8_t  u8;		/**< 8-bit unsigned integer value */
	uint16_t u16;		/**< 16-bit unsigned integer value */
	uint32_t u32;		/**< 32-bit unsigned integer value */
	uint64_t u64;		/**< 64-bit unsigned integer value */
	double fpnumber;	/**< floating point value */
	cfg_bool_t boolean;	/**< boolean value */
	char *string;		/**< string value */
	cfg_t *section;		/**< section value */
	void *ptr;		/**< user-defined value */
};

/** Data structure holding the pointer to a user provided variable
 *  defined with CFG_SIMPLE_*
 */
union cfg_simple_t {
	long int *number;	/**< pointer to a long int, for CFG_SIMPLE_INT */
	int8_t   *i8;		/**< pointer to an int8_t, for CFG_SIMPLE_INT8 */
	int16_t  *i16;		/**< pointer to an int16_t, for CFG_SIMPLE_INT16 */
	int32_t  *i32;		/**< pointer to an int32_t, for CFG_SIMPLE_INT32 */
	int64_t  *i64;		/**< pointer to an int64_t, for CFG_SIMPLE_INT64 */
	uint8_t  *u8;		/**< pointer to a uint8_t, for CFG_SIMPLE_UINT8 */
	uint16_t *u16;		/**< pointer to a uint16_t, for CFG_SIMPLE_UINT16 */
	uint32_t *u32;		/**< pointer to a uint32_t, for CFG_SIMPLE_UINT32 */
	uint64_t *u64;		/**< pointer to a uint64_t, for CFG_SIMPLE_UINT64 */
	double *fpnumber;	/**< pointer to a double, for CFG_SIMPLE_FLOAT */
	cfg_bool_t *boolean;	/**< pointer to a cfg_bool_t, for CFG_SIMPLE_BOOL */
	char **string;		/**< pointer to a char *, for CFG_SIMPLE_STR */
	void **ptr;		/**< pointer to a user value, for CFG_SIMPLE_PTR */
};

/** Data structure holding the default value given by the
 *  initialization macros.
 */
struct cfg_defvalue_t {
	long int number; 	/**< default integer value */
	double fpnumber;	/**< default floating point value */
	cfg_bool_t boolean;	/**< default boolean value */
	const char *string;	/**< default string value */
	char *parsed;		/**< default value that is parsed by
				 * libConfuse, used for lists and
				 * functions */
};

/** Data structure holding information about an option. The value(s)
 * are stored as an array of fundamental values (strings, numbers,
 * etc).
 */
struct cfg_opt_t {
	const char *name;	/**< The name of the option */
	char *comment;	        /**< Optional comment/annotation */
	cfg_type_t type;	/**< Type of option */
	unsigned int nvalues;	/**< Number of values parsed */
	cfg_value_t **values;	/**< Array of found values */
	cfg_flag_t flags;	/**< Flags */
	cfg_opt_t *subopts;	/**< Suboptions (only applies to sections) */
	cfg_defvalue_t def;	/**< Default value */
	cfg_func_t func;	/**< Function callback for CFGT_FUNC options */
	cfg_simple_t simple_value;	/**< Pointer to user-specified variable to
					 * store simple values (created with the
					 * CFG_SIMPLE_* initializers) */
	cfg_callback_t parsecb;	/**< Value parsing callback function */
	cfg_validate_callback_t  validcb;  /**< Value validating parsing callback function */
	cfg_validate_callback2_t validcb2; /**< Value validating set callback function */
	cfg_print_func_t pf;	/**< print callback function */
	cfg_free_func_t freecb;	/**< user-defined memory release function */
};

extern const char __export confuse_copyright[]; /**< libConfuse copyright string */
extern const char __export confuse_version[];   /**< libConfuse version string */
extern const char __export confuse_author[];    /**< libConfuse author string */

#define __CFG_STR(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, \
	.type = CFGT_STR, \
	.flags = _flags, \
	.def = { .string = _def, }, \
	.simple_value = { .string = _svalue, }, \
	.parsecb = _cb, \
}
#define __CFG_STR_LIST(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, \
	.type = CFGT_STR, \
	.flags = _flags | CFGF_LIST, \
	.def = { .parsed = _def, }, \
	.simple_value = { .string = _svalue, }, \
	.parsecb = _cb, \
}

/** Initialize a string option
 */
#define CFG_STR(name, def, flags) \
  __CFG_STR(name, def, flags, NULL, NULL)

/** Initialize a raw section option.
 */
#define CFG_RAWSEC(_name, _flags) { \
	.name = _name, \
	.type = CFGT_RAWSEC, \
	.flags = _flags, \
	.subopts = NULL, \
}

/** Initialize a string list option
 */
#define CFG_STR_LIST(name, def, flags) \
  __CFG_STR_LIST(name, def, flags, NULL, NULL)

/** Initialize a string option with a value parsing callback
 */
#define CFG_STR_CB(name, def, flags, cb) \
  __CFG_STR(name, def, flags, NULL, cb)

/** Initialize a string list option with a value parsing callback
 */
#define CFG_STR_LIST_CB(name, def, flags, cb) \
  __CFG_STR_LIST(name, def, flags, NULL, cb)

/** Initialize a "simple" string option.
 *
 * "Simple" options (in lack of a better expression) does not support
 * lists of values or multiple sections. LibConfuse will store the
 * value of a simple option in the user-defined location specified by
 * the value parameter in the initializer. Simple options are not
 * stored in the cfg_t context, only a pointer. Sections can not be
 * initialized as a "simple" option.
 *
 * As of version 2.2, libConfuse can now return the values of simple
 * options with the cfg_get functions. This allows using the new
 * cfg_print function with simple options.
 *
 * libConfuse doesn't support handling default values for "simple"
 * options. They are assumed to be set by the calling application
 * before cfg_parse is called.
 *
 * @param name name of the option
 * @param svalue pointer to a character pointer (a char **). This value
 * must be initialized either to NULL or to a malloc()'ed string. You
 * can't use
 * <pre>
 * char *user = "joe";
 * ...
 * cfg_opt_t opts[] = {
 *     CFG_SIMPLE_STR("user", &user),
 * ...
 * </pre>
 * since libConfuse will try to free the static string "joe" (which is
 * an error) when a "user" option is found. Rather, use the following
 * code snippet:
 * <pre>
 * char *user = strdup("joe");
 * ...
 * cfg_opt_t opts[] = {
 *      CFG_SIMPLE_STR("user", &user),
 * ...
 * </pre>
 * Alternatively, the default value can be set after the opts struct
 * is defined, as in:
 * <pre>
 * char *user = NULL;
 * ...
 * cfg_opt_t opts[] = {
 *      CFG_SIMPLE_STR("user", &user),
 * ...
 * user = strdup("joe");
 * cfg = cfg_init(opts, 0);
 * cfg_parse(cfg, filename);
 * </pre>
 *
 */
#define CFG_SIMPLE_STR(name, svalue) \
  __CFG_STR(name, NULL, CFGF_NONE, svalue, NULL)


#define __CFG_INT(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, \
	.type = CFGT_INT, \
	.flags = _flags, \
	.def = { .number = _def, }, \
	.simple_value = { .number = _svalue, }, \
	.parsecb = _cb, \
}
#define __CFG_INT_LIST(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, \
	.type = CFGT_INT, \
	.flags = _flags | CFGF_LIST, \
	.def = { .parsed = _def, }, \
	.simple_value = { .number = _svalue, }, \
	.parsecb = _cb, \
}

/** Initialize an integer option.
 *
 * The value is a C `long int`, so it is platform width -- 32-bit on ILP32
 * platforms -- and always signed.  For a defined width or an unsigned
 * value use CFG_INT8() ... CFG_INT64() or CFG_UINT8() ... CFG_UINT64()
 */
#define CFG_INT(name, def, flags) \
  __CFG_INT(name, def, flags, NULL, NULL)

/** Initialize an integer list option
 */
#define CFG_INT_LIST(name, def, flags) \
  __CFG_INT_LIST(name, def, flags, NULL, NULL)

/** Initialize an integer option with a value parsing callback
 */
#define CFG_INT_CB(name, def, flags, cb) \
  __CFG_INT(name, def, flags, NULL, cb)

/** Initialize an integer list option with a value parsing callback
 */
#define CFG_INT_LIST_CB(name, def, flags, cb) \
  __CFG_INT_LIST(name, def, flags, NULL, cb)

/** Initialize a "simple" integer option (see documentation for
 * CFG_SIMPLE_STR for more information).
 * Note that confuse uses long integers, so make sure that any pointer
 * you provide for svalue points to a long int rather than a normal int.
 * Otherwise, you will have strange problems on 64-bit architectures.
 */
#define CFG_SIMPLE_INT(name, svalue) \
  __CFG_INT(name, 0, CFGF_NONE, svalue, NULL)


/*
 * Fixed-width and unsigned integer types.  Unlike CFG_INT, which is a
 * platform `long int` (32-bit on ILP32), these have a defined width on
 * every platform, and out-of-range values are rejected on parse.  A
 * compile-time default set with CFG_INT64() et al. is still limited to
 * `long int` range on ILP32; use the config file or cfg_setint64() for
 * larger defaults.
 */
#define __CFG_INT64(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, \
	.type = CFGT_INT64, \
	.flags = _flags, \
	.def = { .number = _def, }, \
	.simple_value = { .i64 = _svalue, }, \
	.parsecb = _cb, \
}
#define __CFG_INT64_LIST(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, \
	.type = CFGT_INT64, \
	.flags = _flags | CFGF_LIST, \
	.def = { .parsed = _def, }, \
	.simple_value = { .i64 = _svalue, }, \
	.parsecb = _cb, \
}
#define __CFG_UINT32(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, \
	.type = CFGT_UINT32, \
	.flags = _flags, \
	.def = { .number = _def, }, \
	.simple_value = { .u32 = _svalue, }, \
	.parsecb = _cb, \
}
#define __CFG_UINT32_LIST(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, \
	.type = CFGT_UINT32, \
	.flags = _flags | CFGF_LIST, \
	.def = { .parsed = _def, }, \
	.simple_value = { .u32 = _svalue, }, \
	.parsecb = _cb, \
}
#define __CFG_UINT64(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, \
	.type = CFGT_UINT64, \
	.flags = _flags, \
	.def = { .number = _def, }, \
	.simple_value = { .u64 = _svalue, }, \
	.parsecb = _cb, \
}
#define __CFG_UINT64_LIST(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, \
	.type = CFGT_UINT64, \
	.flags = _flags | CFGF_LIST, \
	.def = { .parsed = _def, }, \
	.simple_value = { .u64 = _svalue, }, \
	.parsecb = _cb, \
}

/** Initialize a 64-bit signed integer option */
#define CFG_INT64(name, def, flags)             __CFG_INT64(name, def, flags, NULL, NULL)
/** Initialize a 64-bit signed integer list option */
#define CFG_INT64_LIST(name, def, flags)        __CFG_INT64_LIST(name, def, flags, NULL, NULL)
/** Initialize a 64-bit signed integer option with a parsing callback */
#define CFG_INT64_CB(name, def, flags, cb)      __CFG_INT64(name, def, flags, NULL, cb)
/** Initialize a 64-bit signed integer list option with a parsing callback */
#define CFG_INT64_LIST_CB(name, def, flags, cb) __CFG_INT64_LIST(name, def, flags, NULL, cb)
/** Initialize a "simple" 64-bit signed integer option, svalue is an int64_t * */
#define CFG_SIMPLE_INT64(name, svalue)          __CFG_INT64(name, 0, CFGF_NONE, svalue, NULL)

/** Initialize a 32-bit unsigned integer option */
#define CFG_UINT32(name, def, flags)             __CFG_UINT32(name, def, flags, NULL, NULL)
/** Initialize a 32-bit unsigned integer list option */
#define CFG_UINT32_LIST(name, def, flags)        __CFG_UINT32_LIST(name, def, flags, NULL, NULL)
/** Initialize a 32-bit unsigned integer option with a parsing callback */
#define CFG_UINT32_CB(name, def, flags, cb)      __CFG_UINT32(name, def, flags, NULL, cb)
/** Initialize a 32-bit unsigned integer list option with a parsing callback */
#define CFG_UINT32_LIST_CB(name, def, flags, cb) __CFG_UINT32_LIST(name, def, flags, NULL, cb)
/** Initialize a "simple" 32-bit unsigned integer option, svalue is a uint32_t * */
#define CFG_SIMPLE_UINT32(name, svalue)          __CFG_UINT32(name, 0, CFGF_NONE, svalue, NULL)

/** Initialize a 64-bit unsigned integer option */
#define CFG_UINT64(name, def, flags)             __CFG_UINT64(name, def, flags, NULL, NULL)
/** Initialize a 64-bit unsigned integer list option */
#define CFG_UINT64_LIST(name, def, flags)        __CFG_UINT64_LIST(name, def, flags, NULL, NULL)
/** Initialize a 64-bit unsigned integer option with a parsing callback */
#define CFG_UINT64_CB(name, def, flags, cb)      __CFG_UINT64(name, def, flags, NULL, cb)
/** Initialize a 64-bit unsigned integer list option with a parsing callback */
#define CFG_UINT64_LIST_CB(name, def, flags, cb) __CFG_UINT64_LIST(name, def, flags, NULL, cb)
/** Initialize a "simple" 64-bit unsigned integer option, svalue is a uint64_t * */
#define CFG_SIMPLE_UINT64(name, svalue)          __CFG_UINT64(name, 0, CFGF_NONE, svalue, NULL)

#define __CFG_INT8(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, .type = CFGT_INT8, .flags = _flags, \
	.def = { .number = _def, }, .simple_value = { .i8 = _svalue, }, .parsecb = _cb, \
}
#define __CFG_INT8_LIST(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, .type = CFGT_INT8, .flags = _flags | CFGF_LIST, \
	.def = { .parsed = _def, }, .simple_value = { .i8 = _svalue, }, .parsecb = _cb, \
}
#define __CFG_INT16(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, .type = CFGT_INT16, .flags = _flags, \
	.def = { .number = _def, }, .simple_value = { .i16 = _svalue, }, .parsecb = _cb, \
}
#define __CFG_INT16_LIST(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, .type = CFGT_INT16, .flags = _flags | CFGF_LIST, \
	.def = { .parsed = _def, }, .simple_value = { .i16 = _svalue, }, .parsecb = _cb, \
}
#define __CFG_INT32(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, .type = CFGT_INT32, .flags = _flags, \
	.def = { .number = _def, }, .simple_value = { .i32 = _svalue, }, .parsecb = _cb, \
}
#define __CFG_INT32_LIST(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, .type = CFGT_INT32, .flags = _flags | CFGF_LIST, \
	.def = { .parsed = _def, }, .simple_value = { .i32 = _svalue, }, .parsecb = _cb, \
}
#define __CFG_UINT8(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, .type = CFGT_UINT8, .flags = _flags, \
	.def = { .number = _def, }, .simple_value = { .u8 = _svalue, }, .parsecb = _cb, \
}
#define __CFG_UINT8_LIST(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, .type = CFGT_UINT8, .flags = _flags | CFGF_LIST, \
	.def = { .parsed = _def, }, .simple_value = { .u8 = _svalue, }, .parsecb = _cb, \
}
#define __CFG_UINT16(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, .type = CFGT_UINT16, .flags = _flags, \
	.def = { .number = _def, }, .simple_value = { .u16 = _svalue, }, .parsecb = _cb, \
}
#define __CFG_UINT16_LIST(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, .type = CFGT_UINT16, .flags = _flags | CFGF_LIST, \
	.def = { .parsed = _def, }, .simple_value = { .u16 = _svalue, }, .parsecb = _cb, \
}

/** Initialize an 8-bit signed integer option */
#define CFG_INT8(name, def, flags)              __CFG_INT8(name, def, flags, NULL, NULL)
/** Initialize an 8-bit signed integer list option */
#define CFG_INT8_LIST(name, def, flags)         __CFG_INT8_LIST(name, def, flags, NULL, NULL)
/** Initialize an 8-bit signed integer option with a parsing callback */
#define CFG_INT8_CB(name, def, flags, cb)       __CFG_INT8(name, def, flags, NULL, cb)
/** Initialize an 8-bit signed integer list option with a parsing callback */
#define CFG_INT8_LIST_CB(name, def, flags, cb)  __CFG_INT8_LIST(name, def, flags, NULL, cb)
/** Initialize a "simple" 8-bit signed integer option, svalue is an int8_t * */
#define CFG_SIMPLE_INT8(name, svalue)           __CFG_INT8(name, 0, CFGF_NONE, svalue, NULL)

/** Initialize a 16-bit signed integer option */
#define CFG_INT16(name, def, flags)             __CFG_INT16(name, def, flags, NULL, NULL)
/** Initialize a 16-bit signed integer list option */
#define CFG_INT16_LIST(name, def, flags)        __CFG_INT16_LIST(name, def, flags, NULL, NULL)
/** Initialize a 16-bit signed integer option with a parsing callback */
#define CFG_INT16_CB(name, def, flags, cb)      __CFG_INT16(name, def, flags, NULL, cb)
/** Initialize a 16-bit signed integer list option with a parsing callback */
#define CFG_INT16_LIST_CB(name, def, flags, cb) __CFG_INT16_LIST(name, def, flags, NULL, cb)
/** Initialize a "simple" 16-bit signed integer option, svalue is an int16_t * */
#define CFG_SIMPLE_INT16(name, svalue)          __CFG_INT16(name, 0, CFGF_NONE, svalue, NULL)

/** Initialize a 32-bit signed integer option */
#define CFG_INT32(name, def, flags)             __CFG_INT32(name, def, flags, NULL, NULL)
/** Initialize a 32-bit signed integer list option */
#define CFG_INT32_LIST(name, def, flags)        __CFG_INT32_LIST(name, def, flags, NULL, NULL)
/** Initialize a 32-bit signed integer option with a parsing callback */
#define CFG_INT32_CB(name, def, flags, cb)      __CFG_INT32(name, def, flags, NULL, cb)
/** Initialize a 32-bit signed integer list option with a parsing callback */
#define CFG_INT32_LIST_CB(name, def, flags, cb) __CFG_INT32_LIST(name, def, flags, NULL, cb)
/** Initialize a "simple" 32-bit signed integer option, svalue is an int32_t * */
#define CFG_SIMPLE_INT32(name, svalue)          __CFG_INT32(name, 0, CFGF_NONE, svalue, NULL)

/** Initialize an 8-bit unsigned integer option */
#define CFG_UINT8(name, def, flags)              __CFG_UINT8(name, def, flags, NULL, NULL)
/** Initialize an 8-bit unsigned integer list option */
#define CFG_UINT8_LIST(name, def, flags)         __CFG_UINT8_LIST(name, def, flags, NULL, NULL)
/** Initialize an 8-bit unsigned integer option with a parsing callback */
#define CFG_UINT8_CB(name, def, flags, cb)       __CFG_UINT8(name, def, flags, NULL, cb)
/** Initialize an 8-bit unsigned integer list option with a parsing callback */
#define CFG_UINT8_LIST_CB(name, def, flags, cb)  __CFG_UINT8_LIST(name, def, flags, NULL, cb)
/** Initialize a "simple" 8-bit unsigned integer option, svalue is a uint8_t * */
#define CFG_SIMPLE_UINT8(name, svalue)           __CFG_UINT8(name, 0, CFGF_NONE, svalue, NULL)

/** Initialize a 16-bit unsigned integer option */
#define CFG_UINT16(name, def, flags)             __CFG_UINT16(name, def, flags, NULL, NULL)
/** Initialize a 16-bit unsigned integer list option */
#define CFG_UINT16_LIST(name, def, flags)        __CFG_UINT16_LIST(name, def, flags, NULL, NULL)
/** Initialize a 16-bit unsigned integer option with a parsing callback */
#define CFG_UINT16_CB(name, def, flags, cb)      __CFG_UINT16(name, def, flags, NULL, cb)
/** Initialize a 16-bit unsigned integer list option with a parsing callback */
#define CFG_UINT16_LIST_CB(name, def, flags, cb) __CFG_UINT16_LIST(name, def, flags, NULL, cb)
/** Initialize a "simple" 16-bit unsigned integer option, svalue is a uint16_t * */
#define CFG_SIMPLE_UINT16(name, svalue)          __CFG_UINT16(name, 0, CFGF_NONE, svalue, NULL)



#define __CFG_FLOAT(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, \
	.type = CFGT_FLOAT, \
	.flags = _flags, \
	.def = { .fpnumber = _def, }, \
	.simple_value = { .fpnumber = _svalue, }, \
	.parsecb = _cb, \
}
#define __CFG_FLOAT_LIST(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, \
	.type = CFGT_FLOAT, \
	.flags = _flags | CFGF_LIST, \
	.def = { .parsed = _def, }, \
	.simple_value = { .fpnumber = _svalue, }, \
	.parsecb = _cb, \
}

/** Initialize a floating point option
 */
#define CFG_FLOAT(name, def, flags) \
  __CFG_FLOAT(name, def, flags, NULL, NULL)

/** Initialize a floating point list option
 */
#define CFG_FLOAT_LIST(name, def, flags) \
  __CFG_FLOAT_LIST(name, def, flags, NULL, NULL)

/** Initialize a floating point option with a value parsing callback
 */
#define CFG_FLOAT_CB(name, def, flags, cb) \
  __CFG_FLOAT(name, def, flags, NULL, cb)

/** Initialize a floating point list option with a value parsing callback
 */
#define CFG_FLOAT_LIST_CB(name, def, flags, cb) \
  __CFG_FLOAT_LIST(name, def, flags, NULL, cb)

/** Initialize a "simple" floating point option (see documentation for
 * CFG_SIMPLE_STR for more information).
 */
#define CFG_SIMPLE_FLOAT(name, svalue) \
  __CFG_FLOAT(name, 0, CFGF_NONE, svalue, NULL)



#define __CFG_BOOL(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, \
	.type = CFGT_BOOL, \
	.flags = _flags, \
	.def = { .boolean = _def, }, \
	.simple_value = { .boolean = _svalue, }, \
	.parsecb = _cb, \
}
#define __CFG_BOOL_LIST(_name, _def, _flags, _svalue, _cb) { \
	.name = _name, \
	.type = CFGT_BOOL, \
	.flags = _flags | CFGF_LIST, \
	.def = { .parsed = _def, }, \
	.simple_value = { .boolean = _svalue, }, \
	.parsecb = _cb, \
}

/** Initialize a boolean option
 */
#define CFG_BOOL(name, def, flags) \
  __CFG_BOOL(name, def, flags, NULL, NULL)

/** Initialize a boolean list option
 */
#define CFG_BOOL_LIST(name, def, flags) \
  __CFG_BOOL_LIST(name, def, flags, NULL, NULL)

/** Initialize a boolean option with a value parsing callback
 */
#define CFG_BOOL_CB(name, def, flags, cb) \
  __CFG_BOOL(name, def, flags, NULL, cb)

/** Initialize a boolean list option with a value parsing callback
 */
#define CFG_BOOL_LIST_CB(name, def, flags, cb) \
  __CFG_BOOL_LIST(name, def, flags, NULL, cb)

/** Initialize a "simple" boolean option (see documentation for
 * CFG_SIMPLE_STR for more information).
 */
#define CFG_SIMPLE_BOOL(name, svalue) \
  __CFG_BOOL(name, cfg_false, CFGF_NONE, svalue, NULL)



/** Initialize a section
 *
 * @param _name  The name of the option
 * @param _opts  Array of options that are valid within this section
 *
 * @param _flags Flags, specify CFGF_MULTI if it should be possible to
 * have multiples of the same section, and CFGF_TITLE if the
 * section(s) must have a title (which can be used in the
 * cfg_gettsec() function)
 *
 */
#define CFG_SEC(_name, _opts, _flags) { \
	.name = _name, \
	.type = CFGT_SEC, \
	.flags = _flags, \
	.subopts = _opts, \
}



/** Initialize a function
 * @param _name The name of the option
 * @param _func The callback function.
 *
 * @see cfg_func_t
 */
#define CFG_FUNC(_name, _func) { \
	.name = _name, \
	.type = CFGT_FUNC, \
	.func = _func, \
}


#define __CFG_PTR(_name, _def, _flags, _svalue, _parsecb, _freecb) { \
	.name = _name, \
	.type = CFGT_PTR, \
	.flags = _flags, \
	.def = { .parsed = _def, }, \
	.simple_value = { .ptr = _svalue, }, \
	.parsecb = _parsecb, \
	.freecb = _freecb, \
}
#define __CFG_PTR_LIST(name, def, flags, svalue, parsecb, freecb) { \
	.name = _name, \
	.type = CFGT_PTR, \
	.flags = _flags | CFGF_LIST, \
	.def = { .parsed = _def, }, \
	.simple_value = { .ptr = _svalue, }, \
	.parsecb = _parsecb, \
	.freecb = _freecb, \
}

/** Initialize a user-defined option
 *
 * CFG_PTR options can only be used together with a value parsing callback.
 *
 * @param name The name of the option
 * @param def Default value
 * @param flags Flags
 * @param parsecb Value parsing callback
 * @param freecb Memory release function
 *
 * @see cfg_callback_t, cfg_free_func_t
 */
#define CFG_PTR_CB(name, def, flags, parsecb, freecb) \
  __CFG_PTR(name, def, flags, NULL, parsecb, freecb)

/** Initialize a list of user-defined options
 */
#define CFG_PTR_LIST_CB(name, def, flags, parsecb, freecb) \
  __CFG_PTR(name, def, flags | CFGF_LIST, NULL, parsecb, freecb)

/*#define CFG_SIMPLE_PTR(name, svalue, cb) \
  __CFG_PTR(name, 0, 0, svalue, cb)*/


/** Terminate list of options. This must be the last initializer in
 * the option list.
 */
#define CFG_END() \
  { .type = CFGT_NONE, }



/** Create and initialize a cfg_t structure. This should be the first function
 * called when setting up the parsing of a configuration file. The options
 * passed in the first parameter is initialized using the CFG_* initializers.
 * The last option in the option array must be CFG_END(), unless you like
 * segmentation faults.
 *
 * The options must no longer be defined in the same scope as where the cfg_xxx
 * functions are used (since version 2.3).
 *
 * CFGF_IGNORE_UNKNOWN can be specified to use the "__unknown" option
 * whenever an unknown option is parsed. Be sure to define an "__unknown"
 * option in each scope that unknown parameters are allowed.
 *
 * Call setlocale() before calling this function to localize handling of
 * types, LC_CTYPE, and messages, LC_MESSAGES, since version 2.9:
 * <pre>
 *     setlocale(LC_MESSAGES, "");
 *     setlocale(LC_CTYPE, "");
 * </pre>
 * @param opts An array of options
 * @param flags One or more flags (bitwise or'ed together). Currently only
 * CFGF_NOCASE and CFGF_IGNORE_UNKNOWN are available. Use 0 if no flags are
 * needed.
 *
 * @return A configuration context structure. This pointer is passed
 * to almost all other functions as the first parameter.
 */
DLLIMPORT cfg_t *__export cfg_init(cfg_opt_t *opts, cfg_flag_t flags);

/** Add a searchpath directory to the configuration context, the
 * const char* argument will be duplicated and then freed as part
 * of the usual context takedown.
 *
 * All directories added to the context in this manner will be searched
 * for the file specified in cfg_parse(), and for those included.
 * All directories added with this function will be "tilde expanded".
 * Note that the current directory is not added to the searchpath
 * by default.
 *
 * @param cfg The configuration file context as returned from cfg_init().
 * @param dir Directory to be added to the search path.
 *
 * @return On success, CFG_SUCCESS, on failure (which can only be
 * caused by a failed malloc()), CFG_PARSE_ERROR.
 */
DLLIMPORT int __export cfg_add_searchpath(cfg_t *cfg, const char *dir);

/** Search the linked-list of cfg_searchpath_t for the specified
 * file.  If not NULL, the return value is freshly allocated and
 * and should be freed by the caller.
 *
 * @param path The linked list of cfg_searchpath_t structs, each
 * containing a directory to be searched
 * @param file The file for which to search
 *
 * @return If the file is found on the searchpath then the full
 * path to the file is returned. If not found, NULL is returned.
 */
DLLIMPORT char *__export cfg_searchpath(cfg_searchpath_t *path, const char *file);

/** Parse a configuration file. Tilde expansion is performed on the
 * filename before it is opened. After a configuration file has been
 * initialized (with cfg_init()) and parsed (with cfg_parse()), the
 * values can be read with the cfg_getXXX functions.
 *
 * @param cfg The configuration file context as returned from cfg_init().
 * @param filename The name of the file to parse.
 *
 * @return On success, CFG_SUCCESS is returned. If the file couldn't
 * be opened for reading, CFG_FILE_ERROR is returned. On all other
 * errors, CFG_PARSE_ERROR is returned and cfg_error() was called with
 * a descriptive error message.
 */
DLLIMPORT int __export cfg_parse(cfg_t *cfg, const char *filename);

/** Same as cfg_parse() above, but takes an already opened file as
 * argument. Reading begins at the current position. After parsing,
 * the position is not reset. The caller is responsible for closing
 * the file.
 *
 * Diagnostics use cfg->filename for their `file:line` prefix.  Set it,
 * to a heap-allocated string, before calling to name the source;
 * ownership transfers to the library, which frees it.  When left unset
 * it defaults to "FILE".
 *
 * @param cfg The configuration file context as returned from cfg_init().
 * @param fp An open file stream.
 *
 * @see cfg_parse()
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_parse_fp(cfg_t *cfg, FILE *fp);

/** Same as cfg_parse() above, but takes a character buffer as
 * argument.
 *
 * Diagnostics use cfg->filename for their `file:line` prefix.  Set it,
 * to a heap-allocated string, before calling to make errors from an
 * in-memory buffer point at the real source file; ownership transfers
 * to the library, which frees it.  When left unset it defaults to
 * "[buf]".  This mirrors cfg_parse_fp().
 *
 * @param cfg The configuration file context as returned from cfg_init().
 * @param buf A zero-terminated string with configuration directives.
 *
 * @see cfg_parse()
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_parse_buf(cfg_t *cfg, const char *buf);

/** Free the memory allocated for the values of a given option. Only
 * the values are freed, not the option itself (it is freed by cfg_free()).
 *
 * @see cfg_free()
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_free_value(cfg_opt_t *opt);

/** Free a cfg_t context. All memory allocated by the cfg_t context
 * structure are freed, and can't be used in any further cfg_* calls.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_free(cfg_t *cfg);

/** Install a user-defined error reporting function.
 * @return The old error reporting function is returned.
 */
DLLIMPORT cfg_errfunc_t __export cfg_set_error_function(cfg_t *cfg, cfg_errfunc_t errfunc);

/** Show a parser error. Any user-defined error reporting function is called.
 * @see cfg_set_error_function
 */
#ifdef __GNUC__
__attribute__((__format__(__printf__, 2, 3)))
#endif
DLLIMPORT void __export cfg_error(cfg_t *cfg, const char *fmt, ...);

/** Returns the option comment
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @see cfg_getcomment
 */
DLLIMPORT char * __export cfg_opt_getcomment(cfg_opt_t *opt);

/** Returns the option comment
 *
 * This function can be used to extract option annotations from a config
 * file.  Only comments preceding the option are read by cfg_parse().
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @see cfg_setcomment
 * @return The comment for this option, or NULL if unset
 */
DLLIMPORT char * __export cfg_getcomment(cfg_t *cfg, const char *name);

/** Returns the value of an integer option, given a cfg_opt_t pointer.
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get. Zero based.
 * @see cfg_getnint
 */
DLLIMPORT signed long __export cfg_opt_getnint(cfg_opt_t *opt, unsigned int index);

/** Indexed version of cfg_getint(), used for lists.
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param index Index of the value to get. Zero based.
 * @see cfg_getint
 */
DLLIMPORT long int __export cfg_getnint(cfg_t *cfg, const char *name, unsigned int index);

/** Returns the value of an integer option. This is the same as
 * calling cfg_getnint with index 0.
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @return The requested value is returned. If the option was not set
 * in the configuration file, the default value given in the
 * corresponding cfg_opt_t structure is returned. It is an error to
 * try to get an option that isn't declared.
 */
DLLIMPORT long int __export cfg_getint(cfg_t *cfg, const char *name);

/** Returns the value of a CFGT_INT64 (64-bit signed) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get, zero based.
 * @return The value at @p index, or 0 if unset or on error.
 * @see cfg_getnint64
 */
DLLIMPORT int64_t __export cfg_opt_getnint64(cfg_opt_t *opt, unsigned int index);
/** Indexed version of cfg_getint64(), used for lists.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param index Index of the value to get, zero based.
 * @see cfg_getint64
 */
DLLIMPORT int64_t __export cfg_getnint64(cfg_t *cfg, const char *name, unsigned int index);
/** Returns the value of a CFGT_INT64 (64-bit signed) option, same as cfg_getnint64() with index 0.
 * @param cfg  The configuration file context.
 * @param name The name of the option.
 * @return The value, or the default from the cfg_opt_t if the option was not set.
 */
DLLIMPORT int64_t __export cfg_getint64(cfg_t *cfg, const char *name);

/** Returns the value of a CFGT_UINT32 (32-bit unsigned) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get, zero based.
 * @return The value at @p index, or 0 if unset or on error.
 * @see cfg_getnuint32
 */
DLLIMPORT uint32_t __export cfg_opt_getnuint32(cfg_opt_t *opt, unsigned int index);
/** Indexed version of cfg_getuint32(), used for lists.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param index Index of the value to get, zero based.
 * @see cfg_getuint32
 */
DLLIMPORT uint32_t __export cfg_getnuint32(cfg_t *cfg, const char *name, unsigned int index);
/** Returns the value of a CFGT_UINT32 (32-bit unsigned) option, same as cfg_getnuint32() with index 0.
 * @param cfg  The configuration file context.
 * @param name The name of the option.
 * @return The value, or the default from the cfg_opt_t if the option was not set.
 */
DLLIMPORT uint32_t __export cfg_getuint32(cfg_t *cfg, const char *name);

/** Returns the value of a CFGT_UINT64 (64-bit unsigned) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get, zero based.
 * @return The value at @p index, or 0 if unset or on error.
 * @see cfg_getnuint64
 */
DLLIMPORT uint64_t __export cfg_opt_getnuint64(cfg_opt_t *opt, unsigned int index);
/** Indexed version of cfg_getuint64(), used for lists.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param index Index of the value to get, zero based.
 * @see cfg_getuint64
 */
DLLIMPORT uint64_t __export cfg_getnuint64(cfg_t *cfg, const char *name, unsigned int index);
/** Returns the value of a CFGT_UINT64 (64-bit unsigned) option, same as cfg_getnuint64() with index 0.
 * @param cfg  The configuration file context.
 * @param name The name of the option.
 * @return The value, or the default from the cfg_opt_t if the option was not set.
 */
DLLIMPORT uint64_t __export cfg_getuint64(cfg_t *cfg, const char *name);

/** Returns the value of a CFGT_INT8 (8-bit signed) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get, zero based.
 * @return The value at @p index, or 0 if unset or on error.
 * @see cfg_getnint8
 */
DLLIMPORT int8_t __export cfg_opt_getnint8(cfg_opt_t *opt, unsigned int index);
/** Indexed version of cfg_getint8(), used for lists.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param index Index of the value to get, zero based.
 * @see cfg_getint8
 */
DLLIMPORT int8_t __export cfg_getnint8(cfg_t *cfg, const char *name, unsigned int index);
/** Returns the value of a CFGT_INT8 (8-bit signed) option, same as cfg_getnint8() with index 0.
 * @param cfg  The configuration file context.
 * @param name The name of the option.
 * @return The value, or the default from the cfg_opt_t if the option was not set.
 */
DLLIMPORT int8_t __export cfg_getint8(cfg_t *cfg, const char *name);

/** Returns the value of a CFGT_INT16 (16-bit signed) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get, zero based.
 * @return The value at @p index, or 0 if unset or on error.
 * @see cfg_getnint16
 */
DLLIMPORT int16_t __export cfg_opt_getnint16(cfg_opt_t *opt, unsigned int index);
/** Indexed version of cfg_getint16(), used for lists.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param index Index of the value to get, zero based.
 * @see cfg_getint16
 */
DLLIMPORT int16_t __export cfg_getnint16(cfg_t *cfg, const char *name, unsigned int index);
/** Returns the value of a CFGT_INT16 (16-bit signed) option, same as cfg_getnint16() with index 0.
 * @param cfg  The configuration file context.
 * @param name The name of the option.
 * @return The value, or the default from the cfg_opt_t if the option was not set.
 */
DLLIMPORT int16_t __export cfg_getint16(cfg_t *cfg, const char *name);

/** Returns the value of a CFGT_INT32 (32-bit signed) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get, zero based.
 * @return The value at @p index, or 0 if unset or on error.
 * @see cfg_getnint32
 */
DLLIMPORT int32_t __export cfg_opt_getnint32(cfg_opt_t *opt, unsigned int index);
/** Indexed version of cfg_getint32(), used for lists.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param index Index of the value to get, zero based.
 * @see cfg_getint32
 */
DLLIMPORT int32_t __export cfg_getnint32(cfg_t *cfg, const char *name, unsigned int index);
/** Returns the value of a CFGT_INT32 (32-bit signed) option, same as cfg_getnint32() with index 0.
 * @param cfg  The configuration file context.
 * @param name The name of the option.
 * @return The value, or the default from the cfg_opt_t if the option was not set.
 */
DLLIMPORT int32_t __export cfg_getint32(cfg_t *cfg, const char *name);

/** Returns the value of a CFGT_UINT8 (8-bit unsigned) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get, zero based.
 * @return The value at @p index, or 0 if unset or on error.
 * @see cfg_getnuint8
 */
DLLIMPORT uint8_t __export cfg_opt_getnuint8(cfg_opt_t *opt, unsigned int index);
/** Indexed version of cfg_getuint8(), used for lists.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param index Index of the value to get, zero based.
 * @see cfg_getuint8
 */
DLLIMPORT uint8_t __export cfg_getnuint8(cfg_t *cfg, const char *name, unsigned int index);
/** Returns the value of a CFGT_UINT8 (8-bit unsigned) option, same as cfg_getnuint8() with index 0.
 * @param cfg  The configuration file context.
 * @param name The name of the option.
 * @return The value, or the default from the cfg_opt_t if the option was not set.
 */
DLLIMPORT uint8_t __export cfg_getuint8(cfg_t *cfg, const char *name);

/** Returns the value of a CFGT_UINT16 (16-bit unsigned) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get, zero based.
 * @return The value at @p index, or 0 if unset or on error.
 * @see cfg_getnuint16
 */
DLLIMPORT uint16_t __export cfg_opt_getnuint16(cfg_opt_t *opt, unsigned int index);
/** Indexed version of cfg_getuint16(), used for lists.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param index Index of the value to get, zero based.
 * @see cfg_getuint16
 */
DLLIMPORT uint16_t __export cfg_getnuint16(cfg_t *cfg, const char *name, unsigned int index);
/** Returns the value of a CFGT_UINT16 (16-bit unsigned) option, same as cfg_getnuint16() with index 0.
 * @param cfg  The configuration file context.
 * @param name The name of the option.
 * @return The value, or the default from the cfg_opt_t if the option was not set.
 */
DLLIMPORT uint16_t __export cfg_getuint16(cfg_t *cfg, const char *name);

/** Returns the value of a floating point option, given a cfg_opt_t pointer.
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get. Zero based.
 * @see cfg_getnfloat
 */
DLLIMPORT double __export cfg_opt_getnfloat(cfg_opt_t *opt, unsigned int index);

/** Indexed version of cfg_getfloat(), used for lists.
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param index Index of the value to get. Zero based.
 * @see cfg_getfloat
 */
DLLIMPORT double __export cfg_getnfloat(cfg_t *cfg, const char *name, unsigned int index);

/** Returns the value of a floating point option.
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @return The requested value is returned. If the option was not set
 * in the configuration file, the default value given in the
 * corresponding cfg_opt_t structure is returned. It is an error to
 * try to get an option that isn't declared.
 */
DLLIMPORT double __export cfg_getfloat(cfg_t *cfg, const char *name);

/** Returns the value of a string option, given a cfg_opt_t pointer.
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get. Zero based.
 * @see cfg_getnstr
 */
DLLIMPORT char *__export cfg_opt_getnstr(cfg_opt_t *opt, unsigned int index);

/** Indexed version of cfg_getstr(), used for lists.
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param index Index of the value to get. Zero based.
 * @see cfg_getstr
 */
DLLIMPORT char *__export cfg_getnstr(cfg_t *cfg, const char *name, unsigned int index);

/** Returns the value of a string option.
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @return The requested value is returned. If the option was not set
 * in the configuration file, the default value given in the
 * corresponding cfg_opt_t structure is returned. It is an error to
 * try to get an option that isn't declared.
 */
DLLIMPORT char *__export cfg_getstr(cfg_t *cfg, const char *name);

/** Returns the value of a boolean option, given a cfg_opt_t pointer.
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get. Zero based.
 * @see cfg_getnbool
 */
DLLIMPORT cfg_bool_t __export cfg_opt_getnbool(cfg_opt_t *opt, unsigned int index);

/** Indexed version of cfg_getbool(), used for lists.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param index Index of the value to get. Zero based.
 * @see cfg_getbool
 */
DLLIMPORT cfg_bool_t __export cfg_getnbool(cfg_t *cfg, const char *name, unsigned int index);

/** Returns the value of a boolean option.
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @return The requested value is returned. If the option was not set
 * in the configuration file, the default value given in the
 * corresponding cfg_opt_t structure is returned. It is an error to
 * try to get an option that isn't declared.
 */
DLLIMPORT cfg_bool_t __export cfg_getbool(cfg_t *cfg, const char *name);


/** Returns the value of a user-defined (CFGT_PTR) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get, zero based.
 * @return The stored pointer at @p index, or NULL if unset or on error.
 * @see cfg_getnptr
 */
DLLIMPORT void *__export cfg_opt_getnptr(cfg_opt_t *opt, unsigned int index);
/** Indexed version of cfg_getptr(), used for lists of user-defined values.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param index Index of the value to get, zero based.
 * @see cfg_getptr
 */
DLLIMPORT void *__export cfg_getnptr(cfg_t *cfg, const char *name, unsigned int index);

/** Returns the value of a user-defined option (void pointer).
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @return The requested value is returned. If the option was not set
 * in the configuration file, the default value given in the
 * corresponding cfg_opt_t structure is returned. It is an error to
 * try to get an option that isn't declared.
 */
DLLIMPORT void *__export cfg_getptr(cfg_t *cfg, const char *name);


/** Returns the value of a section option, given a cfg_opt_t pointer.
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the value to get. Zero based.
 * @see cfg_getnsec
 */
DLLIMPORT cfg_t *__export cfg_opt_getnsec(cfg_opt_t *opt, unsigned int index);

/** Indexed version of cfg_getsec(), used for sections with the
 * CFGF_MULTI flag set.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param index Index of the section to get. Zero based.
 * @see cfg_getsec
 */
DLLIMPORT cfg_t *__export cfg_getnsec(cfg_t *cfg, const char *name, unsigned int index);

/** Returns the value of a section option, given a cfg_opt_t pointer
 * and the title.
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param title The title of this section. The CFGF_TITLE flag must
 * have been set for this option.
 * @see cfg_gettsec
 */
DLLIMPORT cfg_t *__export cfg_opt_gettsec(cfg_opt_t *opt, const char *title);

/** Return a section given the title, used for section with the
 * CFGF_TITLE flag set.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param title The title of this section. The CFGF_TITLE flag must
 * have been set for this option.
 * @see cfg_getsec
 */
DLLIMPORT cfg_t *__export cfg_gettsec(cfg_t *cfg, const char *name, const char *title);

/** Returns the value of a section option. The returned value is
 * another cfg_t structure that can be used in following calls to
 * cfg_getint, cfg_getstr or other get-functions.
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @return The requested section is returned. If no section is found
 * with that name, 0 is returned. There can only be default values for
 * section without the CFGF_MULTI flag set. It is an error to try to
 * get a section that isn't declared.
 */
DLLIMPORT cfg_t *__export cfg_getsec(cfg_t *cfg, const char *name);

/** Return the number of values this option has. If no default value
 * is given for the option and no value was found in the config file,
 * 0 will be returned (ie, the option value is not set at all).
 * @param opt The option structure (eg, as returned from cfg_getopt())
 */
DLLIMPORT unsigned int __export cfg_opt_size(cfg_opt_t *opt);

/** Return the number of values this option has. If no default value
 * is given for the option and no value was found in the config file,
 * 0 will be returned (ie, the option value is not set at all).
 *
 * Note that there is no way to *not* specify a default value for integers,
 * floats and booleans. Ie, they always have default values (since 0 or NULL is
 * a valid integer/float/boolean value). Only strings and lists may have no
 * default value.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 */
DLLIMPORT unsigned int __export cfg_size(cfg_t *cfg, const char *name);

/** Return the title of a section.
 *
 * @param cfg The configuration file context.
 * @return Returns the title, or 0 if there is no title. This string
 * should not be modified.
 */
DLLIMPORT const char *__export cfg_title(cfg_t *cfg);

/** Return the verbatim body of a raw section (CFGT_RAWSEC).
 *
 * @param cfg The raw section context.
 * @return Returns the captured body, or 0 if none. Do not modify.
 */
DLLIMPORT const char *__export cfg_getraw(cfg_t *cfg);

/** Return the name of a section.
 *
 * @param cfg The configuration file context.
 * @return Returns the title, or 0 if there is no title. This string
 * should not be modified.
 */
DLLIMPORT const char *__export cfg_name(cfg_t *cfg);

/** Return the name of an option.
 *
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @return Returns the title, or 0 if there is no title. This string
 * should not be modified.
 */
DLLIMPORT const char *__export cfg_opt_name(cfg_opt_t *opt);

/** Return the string value of a key=value pair
 *
 * @param opt The option structure (eg, as returned from cfg_getnopt())
 * @see cfg_opt_name
 * @return The string value for the option, or NULL if it's not a
 * string.  This string must not be modified!
 */
DLLIMPORT const char *cfg_opt_getstr(cfg_opt_t *opt);

/** Predefined include-function. This function can be used in the
 * options passed to cfg_init() to specify a function for including
 * other configuration files in the parsing. For example:
 * CFG_FUNC("include", &cfg_include)
 */
DLLIMPORT int __export cfg_include(cfg_t *cfg, cfg_opt_t *opt, int argc, const char **argv);

/** Does tilde expansion (~ -> $HOME) on the filename.
 * @return The expanded filename is returned. If a ~user was not
 * found, the original filename is returned. In any case, a
 * dynamically allocated string is returned, which should be free()'d
 * by the caller.
 */
DLLIMPORT char *__export cfg_tilde_expand(const char *filename);

/** Parse a boolean option string. Accepted "true" values are "true",
 * "on" and "yes", and accepted "false" values are "false", "off" and
 * "no".
 *
 * @return Returns 1 or 0 (true/false) if the string was parsed
 * correctly, or -1 if an error occurred.
 */
DLLIMPORT int __export cfg_parse_boolean(const char *s);

/** Return the nth option in a file or section
 *
 * @param cfg The configuration file or section context
 * @param index Option index
 * @see cfg_num
 */
DLLIMPORT cfg_opt_t *cfg_getnopt(cfg_t *cfg, unsigned int index);

/** Return an option given it's name.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 *
 * @return Returns a pointer to the option. If the option isn't declared,
 * libConfuse will print an error message and return 0.
 */
DLLIMPORT cfg_opt_t *__export cfg_getopt(cfg_t *cfg, const char *name);

/** Set an option (create an instance of an option).
 *
 * @param cfg The configuration file context.
 * @param opt The option definition.
 * @param value The initial value for the option.
 *
 * @return Returns a pointer to the value object.
 */
DLLIMPORT cfg_value_t *cfg_setopt(cfg_t *cfg, cfg_opt_t *opt, const char *value);

/** Annotate an option
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param comment The annotation
 * @see cfg_setcomment
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_setcomment(cfg_opt_t *opt, char *comment);

/** Annotate an option given its name
 *
 * All options can be annotated as long as the CFGF_COMMENTS flag is
 * given to cfg_init().
 *
 * When calling cfg_print(), annotations are saved as a C style one-liner
 * comment before each option.
 *
 * When calling cfg_parse(), only one-liner comments preceding an option
 * are read and used to annotate the option.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param comment The annotation
 *
 * @return POSIX OK(0), or non-zero on failure.  This function will fail
 * if memory for the new comment cannot be allocated.
 */
DLLIMPORT int __export cfg_setcomment(cfg_t *cfg, const char *name, char *comment);

/** Set a value of an integer option.
 *
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param value The value to set.
 * @param index The index in the option value array that should be
 * modified. It is an error to set values with indices larger than 0
 * for options without the CFGF_LIST flag set.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_setnint(cfg_opt_t *opt, long int value, unsigned int index);

/** Set the value of an integer option given its name.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param value The value to set. If the option is a list (the CFGF_LIST flag
 * is set), only the first value (with index 0) is set.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setint(cfg_t *cfg, const char *name, long int value);

/** Set a value of an integer option given its name and index.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param value The value to set.
 * @param index The index in the option value array that should be
 * modified. It is an error to set values with indices larger than 0
 * for options without the CFGF_LIST flag set.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setnint(cfg_t *cfg, const char *name, long int value, unsigned int index);

/** Set the value of a CFGT_INT64 (64-bit signed) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_setnint64(cfg_opt_t *opt, int64_t value, unsigned int index);
/** Set the value of a CFGT_INT64 (64-bit signed) option.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setint64(cfg_t *cfg, const char *name, int64_t value);
/** Set a value of a CFGT_INT64 (64-bit signed) option at a given list index.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setnint64(cfg_t *cfg, const char *name, int64_t value, unsigned int index);

/** Set the value of a CFGT_UINT32 (32-bit unsigned) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_setnuint32(cfg_opt_t *opt, uint32_t value, unsigned int index);
/** Set the value of a CFGT_UINT32 (32-bit unsigned) option.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setuint32(cfg_t *cfg, const char *name, uint32_t value);
/** Set a value of a CFGT_UINT32 (32-bit unsigned) option at a given list index.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setnuint32(cfg_t *cfg, const char *name, uint32_t value, unsigned int index);

/** Set the value of a CFGT_UINT64 (64-bit unsigned) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_setnuint64(cfg_opt_t *opt, uint64_t value, unsigned int index);
/** Set the value of a CFGT_UINT64 (64-bit unsigned) option.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setuint64(cfg_t *cfg, const char *name, uint64_t value);
/** Set a value of a CFGT_UINT64 (64-bit unsigned) option at a given list index.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setnuint64(cfg_t *cfg, const char *name, uint64_t value, unsigned int index);

/** Set the value of a CFGT_INT8 (8-bit signed) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_setnint8(cfg_opt_t *opt, int8_t value, unsigned int index);
/** Set the value of a CFGT_INT8 (8-bit signed) option.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setint8(cfg_t *cfg, const char *name, int8_t value);
/** Set a value of a CFGT_INT8 (8-bit signed) option at a given list index.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setnint8(cfg_t *cfg, const char *name, int8_t value, unsigned int index);

/** Set the value of a CFGT_INT16 (16-bit signed) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_setnint16(cfg_opt_t *opt, int16_t value, unsigned int index);
/** Set the value of a CFGT_INT16 (16-bit signed) option.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setint16(cfg_t *cfg, const char *name, int16_t value);
/** Set a value of a CFGT_INT16 (16-bit signed) option at a given list index.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setnint16(cfg_t *cfg, const char *name, int16_t value, unsigned int index);

/** Set the value of a CFGT_INT32 (32-bit signed) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_setnint32(cfg_opt_t *opt, int32_t value, unsigned int index);
/** Set the value of a CFGT_INT32 (32-bit signed) option.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setint32(cfg_t *cfg, const char *name, int32_t value);
/** Set a value of a CFGT_INT32 (32-bit signed) option at a given list index.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setnint32(cfg_t *cfg, const char *name, int32_t value, unsigned int index);

/** Set the value of a CFGT_UINT8 (8-bit unsigned) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_setnuint8(cfg_opt_t *opt, uint8_t value, unsigned int index);
/** Set the value of a CFGT_UINT8 (8-bit unsigned) option.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setuint8(cfg_t *cfg, const char *name, uint8_t value);
/** Set a value of a CFGT_UINT8 (8-bit unsigned) option at a given list index.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setnuint8(cfg_t *cfg, const char *name, uint8_t value, unsigned int index);

/** Set the value of a CFGT_UINT16 (16-bit unsigned) option, given a cfg_opt_t pointer.
 * @param opt   The option structure (eg, as returned from cfg_getopt())
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_setnuint16(cfg_opt_t *opt, uint16_t value, unsigned int index);
/** Set the value of a CFGT_UINT16 (16-bit unsigned) option.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setuint16(cfg_t *cfg, const char *name, uint16_t value);
/** Set a value of a CFGT_UINT16 (16-bit unsigned) option at a given list index.
 * @param cfg   The configuration file context.
 * @param name  The name of the option.
 * @param value The value to set.
 * @param index Index in the value array to modify; must be 0 unless CFGF_LIST is set.
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setnuint16(cfg_t *cfg, const char *name, uint16_t value, unsigned int index);

/** Set a value of a floating point option.
 *
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param value The value to set.
 * @param index The index in the option value array that should be
 * modified. It is an error to set values with indices larger than 0
 * for options without the CFGF_LIST flag set.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_setnfloat(cfg_opt_t *opt, double value, unsigned int index);

/** Set the value of a floating point option given its name.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param value The value to set. If the option is a list (the CFGF_LIST flag
 * is set), only the first value (with index 0) is set.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setfloat(cfg_t *cfg, const char *name, double value);

/** Set a value of a floating point option given its name and index.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param value The value to set.
 * @param index The index in the option value array that should be
 * modified. It is an error to set values with indices larger than 0
 * for options without the CFGF_LIST flag set.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setnfloat(cfg_t *cfg, const char *name, double value, unsigned int index);

/** Set a value of a boolean option.
 *
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param value The value to set.
 * @param index The index in the option value array that should be
 * modified. It is an error to set values with indices larger than 0
 * for options without the CFGF_LIST flag set.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_setnbool(cfg_opt_t *opt, cfg_bool_t value, unsigned int index);

/** Set the value of a boolean option given its name.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param value The value to set. If the option is a list (the CFGF_LIST flag
 * is set), only the first value (with index 0) is set.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setbool(cfg_t *cfg, const char *name, cfg_bool_t value);

/** Set a value of a boolean option given its name and index.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param value The value to set.
 * @param index The index in the option value array that should be
 * modified. It is an error to set values with indices larger than 0
 * for options without the CFGF_LIST flag set.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setnbool(cfg_t *cfg, const char *name, cfg_bool_t value, unsigned int index);

/** Set a value of a string option.
 *
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param value The value to set. Memory for the string is allocated
 * and the value is copied. Any previous string value is freed.
 * @param index The index in the option value array that should be
 * modified. It is an error to set values with indices larger than 0
 * for options without the CFGF_LIST flag set.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_setnstr(cfg_opt_t *opt, const char *value, unsigned int index);

/** Set the value of a string option given its name.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param value The value to set. Memory for the string is allocated and the
 * value is copied. Any previous string value is freed. If the option is a list
 * (the CFGF_LIST flag is set), only the first value (with index 0) is set.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setstr(cfg_t *cfg, const char *name, const char *value);

/** Set a value of a boolean option given its name and index.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param value The value to set. Memory for the string is allocated
 * and the value is copied. Any privious string value is freed.
 * @param index The index in the option value array that should be
 * modified. It is an error to set values with indices larger than 0
 * for options without the CFGF_LIST flag set.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setnstr(cfg_t *cfg, const char *name, const char *value, unsigned int index);

/** Set values for a list option. All existing values are replaced
 * with the new ones.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param nvalues Number of values to set.
 * @param ... The values to set, the type must match the type of the
 * option and the number of values must be equal to the nvalues
 * parameter.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_setlist(cfg_t *cfg, const char *name, unsigned int nvalues, ...);

/** Count the number of options in a cfg_opt_t array.
 * @param opts A cfg_opt_t array, terminated by CFG_END().
 * @return The number of options in @p opts, excluding the terminating CFG_END().
 */
DLLIMPORT int __export cfg_numopts(cfg_opt_t *opts);

/** Return number of options in a file or section
 *
 * @param cfg The configuration file or section context
 *
 * When a file has been parsed this function returns the number of
 * options/settings the file, or a sub-section, has.
 *
 * @return Number of options in a config file or section.
 */
DLLIMPORT unsigned int __export cfg_num(cfg_t *cfg);

/** Add values for a list option. The new values are appended to any
 * current values in the list.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param nvalues Number of values to add.
 * @param ... The values to add, the type must match the type of the
 * option and the number of values must be equal to the nvalues
 * parameter.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_addlist(cfg_t *cfg, const char *name, unsigned int nvalues, ...);

/** Set an option (create an instance of an option).
 *
 * @param cfg The configuration file context.
 * @param opt The option definition.
 * @param nvalues The number of values to set for the option.
 * @param values The value(s) for the option.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int cfg_opt_setmulti(cfg_t *cfg, cfg_opt_t *opt, unsigned int nvalues, char **values);

/** Set an option (create an instance of an option).
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param nvalues The number of values to set for the option.
 * @param values The value(s) for the option.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int cfg_setmulti(cfg_t *cfg, const char *name, unsigned int nvalues, char **values);

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

/** Removes and frees a config section, given a cfg_opt_t pointer.
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param index Index of the section to remove. Zero based.
 * @see cfg_rmnsec
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_rmnsec(cfg_opt_t *opt, unsigned int index);

/** Indexed version of cfg_rmsec(), used for CFGF_MULTI sections.
 * @param cfg The configuration file context.
 * @param name The name of the section.
 * @param index Index of the section to remove. Zero based.
 * @see cfg_rmsec
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_rmnsec(cfg_t *cfg, const char *name, unsigned int index);

/** Removes and frees a config section. This is the same as
 * calling cfg_rmnsec with index 0.
 * @param cfg The configuration file context.
 * @param name The name of the section.
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_rmsec(cfg_t *cfg, const char *name);

/** Removes and frees a config section, given a cfg_opt_t pointer
 * and the title.
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param title The title of this section. The CFGF_TITLE flag must
 * have been set for this option.
 * @see cfg_rmtsec
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_rmtsec(cfg_opt_t *opt, const char *title);

/** Removes and frees a section given the title, used for section with the
 * CFGF_TITLE flag set.
 *
 * @param cfg The configuration file context.
 * @param name The name of the section.
 * @param title The title of this section. The CFGF_TITLE flag must
 * have been set for this option.
 * @see cfg_rmsec
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_rmtsec(cfg_t *cfg, const char *name, const char *title);

/** Default value print function.
 *
 * Print only the value of a given option. Does not handle sections or
 * functions. Use cfg_opt_print to print the whole assignment ("option
 * = value"), or cfg_print to print the whole config file.
 *
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param index The index in the option value array that should be printed
 * @param fp File stream to print to.
 *
 * @see cfg_print, cfg_opt_print
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_nprint_var(cfg_opt_t *opt, unsigned int index, FILE *fp);

/** Print an option and its value to a file.
 * Same as cfg_opt_print, but with the indentation level specified.
 * @see cfg_opt_print
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_print_indent(cfg_opt_t *opt, FILE *fp, int indent);

/** Print an option and its value to a file.
 *
 * If a print callback function is specified for the option, it is
 * used instead of cfg_opt_nprint_var.
 *
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param fp File stream to print to.
 *
 * @see cfg_print_func_t
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_opt_print(cfg_opt_t *opt, FILE *fp);

/** Print the options and values to a file.
 * Same as cfg_print, but with the indentation level specified.
 * @see cfg_print
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_print_indent(cfg_t *cfg, FILE *fp, int indent);

/** Print the options and values to a file.
 *
 * Note that options in any included file are expanded and printed
 * directly to the file. Option values given with environment
 * variables in the parsed input are also printed expanded. This means
 * that if you parse a configuration file you can't expect that the
 * output from this function is identical to the initial file.
 *
 * @param cfg The configuration file context.
 * @param fp File stream to print to, use stdout to print to the screen.
 *
 * @see cfg_print_func_t, cfg_set_print_func
 *
 * @return POSIX OK(0), or non-zero on failure.
 */
DLLIMPORT int __export cfg_print(cfg_t *cfg, FILE *fp);

/** Set a print callback function for an option.
 *
 * @param opt The option structure (eg, as returned from cfg_getopt())
 * @param pf The print function callback.
 *
 * @see cfg_print_func_t
 */
DLLIMPORT cfg_print_func_t __export cfg_opt_set_print_func(cfg_opt_t *opt, cfg_print_func_t pf);

/** Set a print callback function for an option given its name.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param pf The print callback function.
 *
 * @see cfg_print_func_t
 */
DLLIMPORT cfg_print_func_t __export cfg_set_print_func(cfg_t *cfg, const char *name, cfg_print_func_t pf);

/** Install a user-defined print filter function. This callback is
 * called for each option when printing cfg, or something above cfg
 * if cfg is a section in some parent cfg. When cfg (or something
 * above cfg) is printed, this filter is also inherited to child
 * sections unless the child section has its own print filter.
 *
 * @param cfg The configuration file context.
 * @param pff The print filter callback function.
 *
 * @return The old print filter function is returned.
 *
 * @see cfg_print_filter_func_t
 */
DLLIMPORT cfg_print_filter_func_t __export cfg_set_print_filter_func(cfg_t *cfg, cfg_print_filter_func_t pff);

/** Register a validating callback function for an option.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param vf The validating callback function.
 *
 * @see cfg_validate_callback_t
 */
DLLIMPORT cfg_validate_callback_t __export cfg_set_validate_func(cfg_t *cfg, const char *name, cfg_validate_callback_t vf);

/** Register a validating callback function for an option.
 *
 * This callback is called for all cfg_set*() functions, although not
 * cfg_opt_set*(), and can be used to check and modify a value/string
 * *before* it is actually set.  The regular callbacks are run after
 * the fact and are only called when parsing a buffer or file.
 *
 * @param cfg The configuration file context.
 * @param name The name of the option.
 * @param vf The validating callback function.
 *
 * @see cfg_validate_callback2_t
 */
DLLIMPORT cfg_validate_callback2_t __export cfg_set_validate_func2(cfg_t *cfg, const char *name, cfg_validate_callback2_t vf);

#ifdef __cplusplus
}
#endif
#endif /* CONFUSE_H_ */

/** @example simple.c */
/** @example reread.c */
/** @example parsebuf.c */
/** @example addsec.c */
/** @example nested.c */
/** @example env.c */
/** @example deprecated.c */
/** @example cli.c */
/** @example ftpconf.c */

/**
 * Local Variables:
 *  indent-tabs-mode: t
 *  c-file-style: "linux"
 * End:
 */
