Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Update libucl
Vsevolod Stakhov committed 9 years ago
commit bd99521833258402a829f22a494345656f74f615
parent 6731b7b
9 files changed +449 -96
modified external/libucl/include/ucl++.h
@@ -24,6 +24,9 @@

#pragma once
#include <string>
+
#include <vector>
+
#include <map>
+
#include <set>
#include <memory>
#include <iostream>

@@ -100,6 +103,68 @@ private:
		return func;
	};

+
	static bool ucl_variable_getter(const unsigned char *data, size_t len,
+
			unsigned char ** /*replace*/, size_t * /*replace_len*/, bool *need_free, void* ud)
+
	{
+
        *need_free = false;
+

+
		auto vars = reinterpret_cast<std::set<std::string> *>(ud);
+
		if (vars && data && len != 0) {
+
			vars->emplace (data, data + len);
+
		}
+
		return false;
+
	}
+

+
	static bool ucl_variable_replacer (const unsigned char *data, size_t len,
+
			unsigned char **replace, size_t *replace_len, bool *need_free, void* ud)
+
	{
+
		*need_free = false;
+

+
		auto replacer = reinterpret_cast<variable_replacer *>(ud);
+
		if (!replacer) {
+
			return false;
+
        }
+

+
		std::string var_name (data, data + len);
+
		if (!replacer->is_variable (var_name)) {
+
			return false;
+
        }
+

+
		std::string var_value = replacer->replace (var_name);
+
		if (var_value.empty ()) {
+
			return false;
+
        }
+

+
		*replace = (unsigned char *)UCL_ALLOC (var_value.size ());
+
		memcpy (*replace, var_value.data (), var_value.size ());
+

+
		*replace_len = var_value.size ();
+
		*need_free = true;
+

+
		return true;
+
	}
+

+
	template <typename C, typename P>
+
	static Ucl parse_with_strategy_function (C config_func, P parse_func, std::string &err)
+
	{
+
		auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
+

+
		config_func (parser);
+

+
		if (!parse_func (parser)) {
+
			err.assign (ucl_parser_get_error (parser));
+
			ucl_parser_free (parser);
+

+
			return nullptr;
+
		}
+

+
		auto obj = ucl_parser_get_object (parser);
+
		ucl_parser_free (parser);
+

+
		// Obj will handle ownership
+
		return Ucl (obj);
+
	}
+

	std::unique_ptr<ucl_object_t, ucl_deleter> obj;

public:
@@ -117,9 +182,9 @@ public:

		const_iterator(const Ucl &obj) {
			it = std::shared_ptr<void>(ucl_object_iterate_new (obj.obj.get()),
-
					ucl_iter_deleter());
+
				ucl_iter_deleter());
			cur.reset (new Ucl(ucl_object_iterate_safe (it.get(), true)));
-
			if (!*cur) {
+
			if (cur->type() == UCL_NULL) {
				it.reset ();
				cur.reset ();
			}
@@ -153,7 +218,7 @@ public:
				cur.reset (new Ucl(ucl_object_iterate_safe (it.get(), true)));
			}

-
			if (!*cur) {
+
			if (cur && cur->type() == UCL_NULL) {
				it.reset ();
				cur.reset ();
			}
@@ -171,6 +236,17 @@ public:
		}
	};

+
	struct variable_replacer {
+
		virtual ~variable_replacer() {}
+

+
		virtual bool is_variable (const std::string &str) const
+
		{
+
			return !str.empty ();
+
		}
+

+
		virtual std::string replace (const std::string &var) const = 0;
+
	};
+

	// We grab ownership if get non-const ucl_object_t
	Ucl(ucl_object_t *other) {
		obj.reset (other);
@@ -211,20 +287,20 @@ public:
		obj.reset (ucl_object_fromstring_common (value.data (), value.size (),
				UCL_STRING_RAW));
	}
-
	Ucl(const char * value) {
+
	Ucl(const char *value) {
		obj.reset (ucl_object_fromstring_common (value, 0, UCL_STRING_RAW));
	}

	// Implicit constructor: anything with a to_json() function.
	template <class T, class = decltype(&T::to_ucl)>
-
	Ucl(const T & t) : Ucl(t.to_ucl()) {}
+
	Ucl(const T &t) : Ucl(t.to_ucl()) {}

	// Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
	template <class M, typename std::enable_if<
		std::is_constructible<std::string, typename M::key_type>::value
		&& std::is_constructible<Ucl, typename M::mapped_type>::value,
		int>::type = 0>
-
	Ucl(const M & m) {
+
	Ucl(const M &m) {
		obj.reset (ucl_object_typed_new (UCL_OBJECT));
		auto cobj = obj.get ();

@@ -238,7 +314,7 @@ public:
	template <class V, typename std::enable_if<
		std::is_constructible<Ucl, typename V::value_type>::value,
		int>::type = 0>
-
	Ucl(const V & v) {
+
	Ucl(const V &v) {
		obj.reset (ucl_object_typed_new (UCL_ARRAY));
		auto cobj = obj.get ();

@@ -356,46 +432,138 @@ public:
		return out;
	}

-
	static Ucl parse (const std::string & in, std::string & err)
+
	static Ucl parse (const std::string &in, std::string &err)
	{
-
		auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
+
		return parse (in, std::map<std::string, std::string>(), err);
+
	}

-
		if (!ucl_parser_add_chunk (parser, (const unsigned char *)in.data (),
-
				in.size ())) {
-
			err.assign (ucl_parser_get_error (parser));
-
			ucl_parser_free (parser);
+
	static Ucl parse (const std::string &in, const std::map<std::string, std::string> &vars, std::string &err)
+
	{
+
		auto config_func = [&vars] (ucl_parser *parser) {
+
			for (const auto & item : vars) {
+
				ucl_parser_register_variable (parser, item.first.c_str (), item.second.c_str ());
+
            }
+
		};
+

+
		auto parse_func = [&in] (ucl_parser *parser) {
+
			return ucl_parser_add_chunk (parser, (unsigned char *)in.data (), in.size ());
+
		};
+

+
		return parse_with_strategy_function (config_func, parse_func, err);
+
	}

+
	static Ucl parse (const std::string &in, const variable_replacer &replacer, std::string &err)
+
	{
+
		auto config_func = [&replacer] (ucl_parser *parser) {
+
			ucl_parser_set_variables_handler (parser, ucl_variable_replacer,
+
				&const_cast<variable_replacer &>(replacer));
+
		};
+

+
		auto parse_func = [&in] (ucl_parser *parser) {
+
			return ucl_parser_add_chunk (parser, (unsigned char *) in.data (), in.size ());
+
		};
+

+
		return parse_with_strategy_function (config_func, parse_func, err);
+
	}
+

+
	static Ucl parse (const char *in, std::string &err)
+
	{
+
		return parse (in, std::map<std::string, std::string>(), err);
+
	}
+

+
	static Ucl parse (const char *in, const std::map<std::string, std::string> &vars, std::string &err)
+
	{
+
		if (!in) {
+
			err = "null input";
			return nullptr;
		}
+
		return parse (std::string (in), vars, err);
+
	}

-
		auto obj = ucl_parser_get_object (parser);
+
	static Ucl parse (const char *in, const variable_replacer &replacer, std::string &err)
+
	{
+
		if (!in) {
+
			err = "null input";
+
			return nullptr;
+
		}
+
		return parse (std::string(in), replacer, err);
+
	}
+

+
	static Ucl parse_from_file (const std::string &filename, std::string &err)
+
	{
+
		return parse_from_file (filename, std::map<std::string, std::string>(), err);
+
	}
+

+
	static Ucl parse_from_file (const std::string &filename, const std::map<std::string, std::string> &vars, std::string &err)
+
	{
+
		auto config_func = [&vars] (ucl_parser *parser) {
+
			for (const auto & item : vars) {
+
				ucl_parser_register_variable (parser, item.first.c_str (), item.second.c_str ());
+
            }
+
		};
+

+
		auto parse_func = [&filename] (ucl_parser *parser) {
+
			return ucl_parser_add_file (parser, filename.c_str ());
+
		};
+

+
		return parse_with_strategy_function (config_func, parse_func, err);
+
	}
+

+
	static Ucl parse_from_file (const std::string &filename, const variable_replacer &replacer, std::string &err)
+
	{
+
		auto config_func = [&replacer] (ucl_parser *parser) {
+
			ucl_parser_set_variables_handler (parser, ucl_variable_replacer,
+
				&const_cast<variable_replacer &>(replacer));
+
		};
+

+
		auto parse_func = [&filename] (ucl_parser *parser) {
+
			return ucl_parser_add_file (parser, filename.c_str ());
+
		};
+

+
		return parse_with_strategy_function (config_func, parse_func, err);
+
	}
+

+
	static std::vector<std::string> find_variable (const std::string &in)
+
	{
+
		auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
+

+
		std::set<std::string> vars;
+
		ucl_parser_set_variables_handler (parser, ucl_variable_getter, &vars);
+
		ucl_parser_add_chunk (parser, (const unsigned char *)in.data (), in.size ());
		ucl_parser_free (parser);

-
		// Obj will handle ownership
-
		return Ucl (obj);
+
		std::vector<std::string> result;
+
		std::move (vars.begin (), vars.end (), std::back_inserter (result));
+
		return result;
	}

-
	static Ucl parse (const char * in, std::string & err)
+
	static std::vector<std::string> find_variable (const char *in)
	{
-
		if (in) {
-
			return parse (std::string(in), err);
-
		} else {
-
			err = "null input";
-
			return nullptr;
+
		if (!in) {
+
			return std::vector<std::string>();
		}
+
		return find_variable (std::string (in));
	}

-
	static Ucl parse (std::istream &ifs, std::string &err)
+
	static std::vector<std::string> find_variable_from_file (const std::string &filename)
	{
-
		return Ucl::parse (std::string(std::istreambuf_iterator<char>(ifs),
-
				std::istreambuf_iterator<char>()), err);
+
		auto parser = ucl_parser_new (UCL_PARSER_DEFAULT);
+

+
		std::set<std::string> vars;
+
		ucl_parser_set_variables_handler (parser, ucl_variable_getter, &vars);
+
		ucl_parser_add_file (parser, filename.c_str ());
+
		ucl_parser_free (parser);
+

+
		std::vector<std::string> result;
+
		std::move (vars.begin (), vars.end (), std::back_inserter (result));
+
		return std::move (result);
	}

-
    Ucl& operator= (Ucl rhs)
-
    {
-
        obj.swap (rhs.obj);
-
        return *this;
-
    }
+
	Ucl& operator= (Ucl rhs)
+
	{
+
		obj.swap (rhs.obj);
+
		return *this;
+
	}

	bool operator== (const Ucl &rhs) const
	{
modified external/libucl/include/ucl.h
@@ -154,7 +154,8 @@ typedef enum ucl_parser_flags {
	UCL_PARSER_NO_TIME = (1 << 2), /**< Do not parse time and treat time values as strings */
	UCL_PARSER_NO_IMPLICIT_ARRAYS = (1 << 3), /** Create explicit arrays instead of implicit ones */
	UCL_PARSER_SAVE_COMMENTS = (1 << 4), /** Save comments in the parser context */
-
	UCL_PARSER_DISABLE_MACRO = (1 << 5) /** Treat macros as comments */
+
	UCL_PARSER_DISABLE_MACRO = (1 << 5), /** Treat macros as comments */
+
	UCL_PARSER_NO_FILEVARS = (1 << 6) /** Do not set file vars */
} ucl_parser_flags_t;

/**
@@ -205,7 +206,8 @@ enum ucl_duplicate_strategy {
enum ucl_parse_type {
	UCL_PARSE_UCL = 0, /**< Default ucl format */
	UCL_PARSE_MSGPACK, /**< Message pack input format */
-
	UCL_PARSE_CSEXP /**< Canonical S-expressions */
+
	UCL_PARSE_CSEXP, /**< Canonical S-expressions */
+
	UCL_PARSE_AUTO /**< Try to detect parse type */
};

/**
@@ -227,7 +229,7 @@ typedef struct ucl_object_s {
	const char *key;						/**< Key of an object		*/
	struct ucl_object_s *next;				/**< Array handle			*/
	struct ucl_object_s *prev;				/**< Array handle			*/
-
	uint32_t keylen;						/**< Lenght of a key		*/
+
	uint32_t keylen;						/**< Length of a key		*/
	uint32_t len;							/**< Size of an object		*/
	uint32_t ref;							/**< Reference count		*/
	uint16_t flags;							/**< Object flags			*/
@@ -831,10 +833,29 @@ UCL_EXTERN ucl_object_iter_t ucl_object_iterate_reset (ucl_object_iter_t it,
 * Get the next object from the `obj`. This fucntion iterates over arrays, objects
 * and implicit arrays
 * @param iter safe iterator
+
 * @param expand_values expand explicit arrays and objects
 * @return the next object in sequence
 */
UCL_EXTERN const ucl_object_t* ucl_object_iterate_safe (ucl_object_iter_t iter,
		bool expand_values);
+
/**
+
 * Iteration type enumerator
+
 */
+
enum ucl_iterate_type {
+
	UCL_ITERATE_EXPLICIT = 1 << 0, /**< Iterate just explicit arrays and objects */
+
	UCL_ITERATE_IMPLICIT = 1 << 1,  /**< Iterate just implicit arrays */
+
	UCL_ITERATE_BOTH = (1 << 0) | (1 << 1),   /**< Iterate both explicit and implicit arrays*/
+
};
+

+
/**
+
 * Get the next object from the `obj`. This fucntion iterates over arrays, objects
+
 * and implicit arrays if needed
+
 * @param iter safe iterator
+
 * @param
+
 * @return the next object in sequence
+
 */
+
UCL_EXTERN const ucl_object_t* ucl_object_iterate_full (ucl_object_iter_t iter,
+
		enum ucl_iterate_type type);

/**
 * Free memory associated with the safe iterator
@@ -1035,6 +1056,20 @@ UCL_EXTERN bool ucl_parser_add_file_priority (struct ucl_parser *parser,
		const char *filename, unsigned priority);

/**
+
 * Load and add data from a file
+
 * @param parser parser structure
+
 * @param filename the name of file
+
 * @param priority the desired priority of a chunk (only 4 least significant bits
+
 * are considered for this parameter)
+
 * @param strat Merge strategy to use while parsing this file
+
 * @param parse_type Parser type to use while parsing this file
+
 * @return true if chunk has been added and false in case of error
+
 */
+
UCL_EXTERN bool ucl_parser_add_file_full (struct ucl_parser *parser, const char *filename,
+
		unsigned priority, enum ucl_duplicate_strategy strat,
+
		enum ucl_parse_type parse_type);
+

+
/**
 * Load and add data from a file descriptor
 * @param parser parser structure
 * @param filename the name of file
@@ -1057,6 +1092,21 @@ UCL_EXTERN bool ucl_parser_add_fd_priority (struct ucl_parser *parser,
		int fd, unsigned priority);

/**
+
 * Load and add data from a file descriptor
+
 * @param parser parser structure
+
 * @param filename the name of file
+
 * @param err if *err is NULL it is set to parser error
+
 * @param priority the desired priority of a chunk (only 4 least significant bits
+
 * are considered for this parameter)
+
 * @param strat Merge strategy to use while parsing this file
+
 * @param parse_type Parser type to use while parsing this file
+
 * @return true if chunk has been added and false in case of error
+
 */
+
UCL_EXTERN bool ucl_parser_add_fd_full (struct ucl_parser *parser, int fd,
+
		unsigned priority, enum ucl_duplicate_strategy strat,
+
		enum ucl_parse_type parse_type);
+

+
/**
 * Provide a UCL_ARRAY of paths to search for include files. The object is
 * copied so caller must unref the object.
 * @param parser parser structure
modified external/libucl/lua/lua_ucl.c
@@ -29,7 +29,6 @@
#include "ucl_internal.h"
#include "lua_ucl.h"
#include <strings.h>
-
#include <zconf.h>

/***
 * @module ucl
@@ -187,6 +186,8 @@ ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj)
			lua_rawseti (L, -2, i);
			i ++;
		}
+

+
		ucl_object_iterate_free (it);
	}
	else {
		/* Optimize allocation by preallocation of table */
@@ -482,7 +483,7 @@ static int
lua_ucl_parser_init (lua_State *L)
{
	struct ucl_parser *parser, **pparser;
-
	int flags = 0;
+
	int flags = UCL_PARSER_NO_FILEVARS;

	if (lua_gettop (L) >= 1) {
		flags = lua_tonumber (L, 1);
@@ -524,6 +525,27 @@ lua_ucl_push_opaque (lua_State *L, ucl_object_t *obj)
	lua_setmetatable (L, -2);
}

+
static inline enum ucl_parse_type
+
lua_ucl_str_to_parse_type (const char *str)
+
{
+
	enum ucl_parse_type type = UCL_PARSE_UCL;
+

+
	if (str != NULL) {
+
		if (strcasecmp (str, "msgpack") == 0) {
+
			type = UCL_PARSE_MSGPACK;
+
		}
+
		else if (strcasecmp (str, "sexp") == 0 ||
+
				strcasecmp (str, "csexp") == 0) {
+
			type = UCL_PARSE_CSEXP;
+
		}
+
		else if (strcasecmp (str, "auto") == 0) {
+
			type = UCL_PARSE_AUTO;
+
		}
+
	}
+

+
	return type;
+
}
+

/***
 * @method parser:parse_file(name)
 * Parse UCL object from file.
@@ -579,13 +601,19 @@ lua_ucl_parser_parse_string (lua_State *L)
	struct ucl_parser *parser;
	const char *string;
	size_t llen;
+
	enum ucl_parse_type type = UCL_PARSE_UCL;
	int ret = 2;

	parser = lua_ucl_parser_get (L, 1);
	string = luaL_checklstring (L, 2, &llen);

+
	if (lua_type (L, 3) == LUA_TSTRING) {
+
		type = lua_ucl_str_to_parse_type (lua_tostring (L, 3));
+
	}
+

	if (parser != NULL && string != NULL) {
-
		if (ucl_parser_add_chunk (parser, (const unsigned char *)string, llen)) {
+
		if (ucl_parser_add_chunk_full (parser, (const unsigned char *)string,
+
				llen, 0, UCL_DUPLICATE_APPEND, type)) {
			lua_pushboolean (L, true);
			ret = 1;
		}
@@ -761,6 +789,28 @@ lua_ucl_object_unwrap (lua_State *L)
	return 1;
}

+
static inline enum ucl_emitter
+
lua_ucl_str_to_emit_type (const char *strtype)
+
{
+
	enum ucl_emitter format = UCL_EMIT_JSON_COMPACT;
+

+
	if (strcasecmp (strtype, "json") == 0) {
+
		format = UCL_EMIT_JSON;
+
	}
+
	else if (strcasecmp (strtype, "json-compact") == 0) {
+
		format = UCL_EMIT_JSON_COMPACT;
+
	}
+
	else if (strcasecmp (strtype, "yaml") == 0) {
+
		format = UCL_EMIT_YAML;
+
	}
+
	else if (strcasecmp (strtype, "config") == 0 ||
+
			strcasecmp (strtype, "ucl") == 0) {
+
		format = UCL_EMIT_CONFIG;
+
	}
+

+
	return format;
+
}
+

/***
 * @method object:tostring(type)
 * Unwraps opaque ucl object to string (json by default). Optionally you can
@@ -787,19 +837,7 @@ lua_ucl_object_tostring (lua_State *L)
			if (lua_type (L, 2) == LUA_TSTRING) {
				const char *strtype = lua_tostring (L, 2);

-
				if (strcasecmp (strtype, "json") == 0) {
-
					format = UCL_EMIT_JSON;
-
				}
-
				else if (strcasecmp (strtype, "json-compact") == 0) {
-
					format = UCL_EMIT_JSON_COMPACT;
-
				}
-
				else if (strcasecmp (strtype, "yaml") == 0) {
-
					format = UCL_EMIT_YAML;
-
				}
-
				else if (strcasecmp (strtype, "config") == 0 ||
-
						strcasecmp (strtype, "ucl") == 0) {
-
					format = UCL_EMIT_CONFIG;
-
				}
+
				format = lua_ucl_str_to_emit_type (strtype);
			}
		}

@@ -1088,6 +1126,9 @@ lua_ucl_to_format (lua_State *L)
				strcasecmp (strtype, "ucl") == 0) {
				format = UCL_EMIT_CONFIG;
			}
+
			else if (strcasecmp (strtype, "msgpack") == 0) {
+
				format = UCL_EMIT_MSGPACK;
+
			}
		}
	}

modified external/libucl/src/mum.h
@@ -73,7 +73,7 @@ typedef unsigned __int64 uint64_t;
#define _MUM_FRESH_GCC
#endif

-
#if defined(__GNUC__) && !defined(__llvm__)
+
#if defined(__GNUC__) && !defined(__llvm__) && defined(_MUM_FRESH_GCC)
#define _MUM_ATTRIBUTE_UNUSED  __attribute__((unused))
#define _MUM_OPTIMIZE(opts) __attribute__((__optimize__ (opts)))
#define _MUM_TARGET(opts) __attribute__((__target__ (opts)))
modified external/libucl/src/ucl_emitter_utils.c
@@ -102,7 +102,7 @@ ucl_elt_string_write_json (const char *str, size_t size,
	func->ucl_emitter_append_character ('"', 1, func->ud);

	while (size) {
-
		if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE)) {
+
		if (ucl_test_character (*p, UCL_CHARACTER_JSON_UNSAFE|UCL_CHARACTER_DENIED)) {
			if (len > 0) {
				func->ucl_emitter_append_len (c, len, func->ud);
			}
@@ -128,6 +128,10 @@ ucl_elt_string_write_json (const char *str, size_t size,
			case '"':
				func->ucl_emitter_append_len ("\\\"", 2, func->ud);
				break;
+
			default:
+
				/* Emit unicode unknown character */
+
				func->ucl_emitter_append_len ("\\uFFFD", 5, func->ud);
+
				break;
			}
			len = 0;
			c = ++p;
@@ -138,9 +142,11 @@ ucl_elt_string_write_json (const char *str, size_t size,
		}
		size --;
	}
+

	if (len > 0) {
		func->ucl_emitter_append_len (c, len, func->ud);
	}
+

	func->ucl_emitter_append_character ('"', 1, func->ud);
}

modified external/libucl/src/ucl_internal.h
@@ -87,6 +87,9 @@
#ifdef HAVE_STRING_H
#include <string.h>
#endif
+
#ifdef HAVE_STRINGS_H
+
#include <strings.h>
+
#endif

#include "utlist.h"
#include "utstring.h"
@@ -127,19 +130,19 @@ enum ucl_parser_state {
};

enum ucl_character_type {
-
	UCL_CHARACTER_DENIED = 0,
-
	UCL_CHARACTER_KEY = 1,
-
	UCL_CHARACTER_KEY_START = 1 << 1,
-
	UCL_CHARACTER_WHITESPACE = 1 << 2,
-
	UCL_CHARACTER_WHITESPACE_UNSAFE = 1 << 3,
-
	UCL_CHARACTER_VALUE_END = 1 << 4,
-
	UCL_CHARACTER_VALUE_STR = 1 << 5,
-
	UCL_CHARACTER_VALUE_DIGIT = 1 << 6,
-
	UCL_CHARACTER_VALUE_DIGIT_START = 1 << 7,
-
	UCL_CHARACTER_ESCAPE = 1 << 8,
-
	UCL_CHARACTER_KEY_SEP = 1 << 9,
-
	UCL_CHARACTER_JSON_UNSAFE = 1 << 10,
-
	UCL_CHARACTER_UCL_UNSAFE = 1 << 11
+
	UCL_CHARACTER_DENIED = (1 << 0),
+
	UCL_CHARACTER_KEY = (1 << 1),
+
	UCL_CHARACTER_KEY_START = (1 << 2),
+
	UCL_CHARACTER_WHITESPACE = (1 << 3),
+
	UCL_CHARACTER_WHITESPACE_UNSAFE = (1 << 4),
+
	UCL_CHARACTER_VALUE_END = (1 << 5),
+
	UCL_CHARACTER_VALUE_STR = (1 << 6),
+
	UCL_CHARACTER_VALUE_DIGIT = (1 << 7),
+
	UCL_CHARACTER_VALUE_DIGIT_START = (1 << 8),
+
	UCL_CHARACTER_ESCAPE = (1 << 9),
+
	UCL_CHARACTER_KEY_SEP = (1 << 10),
+
	UCL_CHARACTER_JSON_UNSAFE = (1 << 11),
+
	UCL_CHARACTER_UCL_UNSAFE = (1 << 12)
};

struct ucl_macro {
@@ -568,4 +571,6 @@ bool ucl_parser_process_object_element (struct ucl_parser *parser,
 */
bool ucl_parse_msgpack (struct ucl_parser *parser);

+
bool ucl_parse_csexp (struct ucl_parser *parser);
+

#endif /* UCL_INTERNAL_H_ */
modified external/libucl/src/ucl_parser.c
@@ -342,6 +342,7 @@ ucl_check_variable_safe (struct ucl_parser *parser, const char *ptr, size_t rema
		/* Call generic handler */
		if (parser->var_handler (ptr, remain, &dst, &dstlen, &need_free,
				parser->var_data)) {
+
			*out_len += dstlen;
			*found = true;
			if (need_free) {
				free (dst);
@@ -458,11 +459,18 @@ ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr,
	}
	if (!found) {
		if (strict && parser->var_handler != NULL) {
-
			if (parser->var_handler (ptr, remain, &dst, &dstlen, &need_free,
+
			size_t var_len = 0;
+
			while (var_len < remain && p[var_len] != '}')
+
				var_len ++;
+

+
			if (parser->var_handler (p, var_len, &dst, &dstlen, &need_free,
							parser->var_data)) {
				memcpy (d, dst, dstlen);
-
				ret += dstlen;
-
				d += remain;
+
				ret += var_len;
+
				d += dstlen;
+
				if (need_free) {
+
					free (dst);
+
				}
				found = true;
			}
		}
@@ -2461,8 +2469,10 @@ ucl_parser_new (int flags)
		parser->comments = ucl_object_typed_new (UCL_OBJECT);
	}

-
	/* Initial assumption about filevars */
-
	ucl_parser_set_filevars (parser, NULL, false);
+
	if (!(flags & UCL_PARSER_NO_FILEVARS)) {
+
		/* Initial assumption about filevars */
+
		ucl_parser_set_filevars (parser, NULL, false);
+
	}

	return parser;
}
@@ -2609,6 +2619,19 @@ ucl_parser_add_chunk_full (struct ucl_parser *parser, const unsigned char *data,
			return false;
		}

+
		if (parse_type == UCL_PARSE_AUTO && len > 0) {
+
			/* We need to detect parse type by the first symbol */
+
			if ((*data & 0x80) == 0x80 && (*data >= 0xdc && *data <= 0xdf)) {
+
				parse_type = UCL_PARSE_MSGPACK;
+
			}
+
			else if (*data == '(') {
+
				parse_type = UCL_PARSE_CSEXP;
+
			}
+
			else {
+
				parse_type = UCL_PARSE_UCL;
+
			}
+
		}
+

		chunk->begin = data;
		chunk->remain = len;
		chunk->pos = chunk->begin;
@@ -2635,6 +2658,8 @@ ucl_parser_add_chunk_full (struct ucl_parser *parser, const unsigned char *data,
				return ucl_state_machine (parser);
			case UCL_PARSE_MSGPACK:
				return ucl_parse_msgpack (parser);
+
			case UCL_PARSE_CSEXP:
+
				return ucl_parse_csexp (parser);
			}
		}
		else {
modified external/libucl/src/ucl_schema.c
@@ -69,7 +69,7 @@ ucl_schema_create_error (struct ucl_schema_error *err,
 * Check whether we have a pattern specified
 */
static const ucl_object_t *
-
ucl_schema_test_pattern (const ucl_object_t *obj, const char *pattern)
+
ucl_schema_test_pattern (const ucl_object_t *obj, const char *pattern, bool recursive)
{
	const ucl_object_t *res = NULL;
#ifdef HAVE_REGEX_H
@@ -78,11 +78,16 @@ ucl_schema_test_pattern (const ucl_object_t *obj, const char *pattern)
	ucl_object_iter_t iter = NULL;

	if (regcomp (&reg, pattern, REG_EXTENDED | REG_NOSUB) == 0) {
-
		while ((elt = ucl_object_iterate (obj, &iter, true)) != NULL) {
-
			if (regexec (&reg, ucl_object_key (elt), 0, NULL, 0) == 0) {
-
				res = elt;
-
				break;
+
		if (recursive) {
+
			while ((elt = ucl_object_iterate (obj, &iter, true)) != NULL) {
+
				if (regexec (&reg, ucl_object_key (elt), 0, NULL, 0) == 0) {
+
					res = elt;
+
					break;
+
				}
			}
+
		} else {
+
			if (regexec (&reg, ucl_object_key (obj), 0, NULL, 0) == 0)
+
				res = obj;
		}
		regfree (&reg);
	}
@@ -205,12 +210,17 @@ ucl_schema_validate_object (const ucl_object_t *schema,
			}
		}
		else if (strcmp (ucl_object_key (elt), "patternProperties") == 0) {
+
			const ucl_object_t *vobj;
+
			ucl_object_iter_t viter;
			piter = NULL;
			while (ret && (prop = ucl_object_iterate (elt, &piter, true)) != NULL) {
-
				found = ucl_schema_test_pattern (obj, ucl_object_key (prop));
-
				if (found) {
-
					ret = ucl_schema_validate (prop, found, true, err, root,
-
							ext_ref);
+
				viter = NULL;
+
				while (ret && (vobj = ucl_object_iterate (obj, &viter, true)) != NULL) {
+
					found = ucl_schema_test_pattern (vobj, ucl_object_key (prop), false);
+
					if (found) {
+
						ret = ucl_schema_validate (prop, found, true, err, root,
+
								ext_ref);
+
					}
				}
			}
		}
@@ -234,7 +244,7 @@ ucl_schema_validate_object (const ucl_object_t *schema,
					piter = NULL;
					pat = ucl_object_lookup (schema, "patternProperties");
					while ((pelt = ucl_object_iterate (pat, &piter, true)) != NULL) {
-
						found = ucl_schema_test_pattern (obj, ucl_object_key (pelt));
+
						found = ucl_schema_test_pattern (obj, ucl_object_key (pelt), true);
						if (found != NULL) {
							break;
						}
modified external/libucl/src/ucl_util.c
@@ -26,11 +26,17 @@
#include "ucl_internal.h"
#include "ucl_chartable.h"
#include "kvec.h"
+
#include <limits.h>
#include <stdarg.h>
#include <stdio.h> /* for snprintf */

#ifndef _WIN32
#include <glob.h>
+
#include <sys/param.h>
+
#else
+
#ifndef NBBY
+
#define NBBY 8
+
#endif
#endif

#ifdef HAVE_LIBGEN_H
@@ -81,11 +87,6 @@ typedef kvec_t(ucl_object_t *) ucl_array_t;
#define MAP_FAILED      ((void *) -1)
#endif

-
#ifdef _WIN32
-
#include <limits.h>
-
#define NBBY CHAR_BIT
-
#endif
-

static void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
{
	void *map = NULL;
@@ -1795,8 +1796,9 @@ ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool n
}

bool
-
ucl_parser_add_file_priority (struct ucl_parser *parser, const char *filename,
-
		unsigned priority)
+
ucl_parser_add_file_full (struct ucl_parser *parser, const char *filename,
+
		unsigned priority, enum ucl_duplicate_strategy strat,
+
		enum ucl_parse_type parse_type)
{
	unsigned char *buf;
	size_t len;
@@ -1819,7 +1821,8 @@ ucl_parser_add_file_priority (struct ucl_parser *parser, const char *filename,
	}
	parser->cur_file = strdup (realbuf);
	ucl_parser_set_filevars (parser, realbuf, false);
-
	ret = ucl_parser_add_chunk_priority (parser, buf, len, priority);
+
	ret = ucl_parser_add_chunk_full (parser, buf, len, priority, strat,
+
			parse_type);

	if (len > 0) {
		ucl_munmap (buf, len);
@@ -1829,19 +1832,34 @@ ucl_parser_add_file_priority (struct ucl_parser *parser, const char *filename,
}

bool
+
ucl_parser_add_file_priority (struct ucl_parser *parser, const char *filename,
+
		unsigned priority)
+
{
+
	if (parser == NULL) {
+
		return false;
+
	}
+

+
	return ucl_parser_add_file_full(parser, filename, priority,
+
			UCL_DUPLICATE_APPEND, UCL_PARSE_UCL);
+
}
+

+
bool
ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
{
	if (parser == NULL) {
		return false;
	}

-
	return ucl_parser_add_file_priority(parser, filename,
-
			parser->default_priority);
+
	return ucl_parser_add_file_full(parser, filename,
+
			parser->default_priority, UCL_DUPLICATE_APPEND,
+
			UCL_PARSE_UCL);
}

+

bool
-
ucl_parser_add_fd_priority (struct ucl_parser *parser, int fd,
-
		unsigned priority)
+
ucl_parser_add_fd_full (struct ucl_parser *parser, int fd,
+
		unsigned priority, enum ucl_duplicate_strategy strat,
+
		enum ucl_parse_type parse_type)
{
	unsigned char *buf;
	size_t len;
@@ -1867,7 +1885,8 @@ ucl_parser_add_fd_priority (struct ucl_parser *parser, int fd,
	}
	parser->cur_file = NULL;
	len = st.st_size;
-
	ret = ucl_parser_add_chunk_priority (parser, buf, len, priority);
+
	ret = ucl_parser_add_chunk_full (parser, buf, len, priority, strat,
+
			parse_type);

	if (len > 0) {
		ucl_munmap (buf, len);
@@ -1877,6 +1896,18 @@ ucl_parser_add_fd_priority (struct ucl_parser *parser, int fd,
}

bool
+
ucl_parser_add_fd_priority (struct ucl_parser *parser, int fd,
+
		unsigned priority)
+
{
+
	if (parser == NULL) {
+
		return false;
+
	}
+

+
	return ucl_parser_add_fd_full(parser, fd, parser->default_priority,
+
			UCL_DUPLICATE_APPEND, UCL_PARSE_UCL);
+
}
+

+
bool
ucl_parser_add_fd (struct ucl_parser *parser, int fd)
{
	if (parser == NULL) {
@@ -2473,6 +2504,10 @@ ucl_object_iterate_reset (ucl_object_iter_t it, const ucl_object_t *obj)

	UCL_SAFE_ITER_CHECK (rit);

+
	if (rit->expl_it != NULL) {
+
		UCL_FREE (sizeof (*rit->expl_it), rit->expl_it);
+
	}
+

	rit->impl_it = obj;
	rit->expl_it = NULL;

@@ -2482,6 +2517,13 @@ ucl_object_iterate_reset (ucl_object_iter_t it, const ucl_object_t *obj)
const ucl_object_t*
ucl_object_iterate_safe (ucl_object_iter_t it, bool expand_values)
{
+
	return ucl_object_iterate_full (it, expand_values ? UCL_ITERATE_BOTH :
+
			UCL_ITERATE_IMPLICIT);
+
}
+

+
const ucl_object_t*
+
ucl_object_iterate_full (ucl_object_iter_t it, enum ucl_iterate_type type)
+
{
	struct ucl_object_safe_iter *rit = UCL_SAFE_ITER (it);
	const ucl_object_t *ret = NULL;

@@ -2494,21 +2536,23 @@ ucl_object_iterate_safe (ucl_object_iter_t it, bool expand_values)
	if (rit->impl_it->type == UCL_OBJECT || rit->impl_it->type == UCL_ARRAY) {
		ret = ucl_object_iterate (rit->impl_it, &rit->expl_it, true);

-
		if (ret == NULL) {
+
		if (ret == NULL && (type & UCL_ITERATE_IMPLICIT)) {
			/* Need to switch to another implicit object in chain */
			rit->impl_it = rit->impl_it->next;
			rit->expl_it = NULL;
-
			return ucl_object_iterate_safe (it, expand_values);
+

+
			return ucl_object_iterate_safe (it, type);
		}
	}
	else {
		/* Just iterate over the implicit array */
		ret = rit->impl_it;
		rit->impl_it = rit->impl_it->next;
-
		if (expand_values) {
+

+
		if (type & UCL_ITERATE_EXPLICIT) {
			/* We flatten objects if need to expand values */
			if (ret->type == UCL_OBJECT || ret->type == UCL_ARRAY) {
-
				return ucl_object_iterate_safe (it, expand_values);
+
				return ucl_object_iterate_safe (it, type);
			}
		}
	}
@@ -2523,6 +2567,10 @@ ucl_object_iterate_free (ucl_object_iter_t it)

	UCL_SAFE_ITER_CHECK (rit);

+
	if (rit->expl_it != NULL) {
+
		UCL_FREE (sizeof (*rit->expl_it), rit->expl_it);
+
	}
+

	UCL_FREE (sizeof (*rit), it);
}