From a22ea751b62b7be2f879a77c71588d1b5aa2f643 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Tue, 18 Aug 2015 13:17:16 +0100 Subject: [PATCH] Update libucl and use UCL_RANDOM_FUNCTION. --- config.h.in | 16 +++++----- contrib/libucl/ucl.h | 43 +++++++++++++++++++++----- contrib/libucl/ucl_hash.c | 15 +++++++-- contrib/libucl/ucl_internal.h | 17 ++++++++++- contrib/libucl/ucl_parser.c | 57 ++++++++++++++++++++++++++++++++--- contrib/libucl/ucl_util.c | 50 ++++++++++++++++++++++++++++++ 6 files changed, 177 insertions(+), 21 deletions(-) diff --git a/config.h.in b/config.h.in index 41be3c587..695b43856 100644 --- a/config.h.in +++ b/config.h.in @@ -66,32 +66,32 @@ #ifdef HAVE_ENDIAN_H #include - #else + #else #ifdef HAVE_SYS_ENDIAN_H #include #else #ifdef HAVE_MACHINE_ENDIAN_H #include #else - #define LITTLE_ENDIAN 1234 - #define BIG_ENDIAN 4321 + #define LITTLE_ENDIAN 1234 + #define BIG_ENDIAN 4321 #if defined(i386) || defined(__i386) || defined(__amd64) || \ defined(BIT_ZERO_ON_RIGHT) || defined(__x86__) #define BYTE_ORDER LITTLE_ENDIAN #endif - + #if defined(__sparc) || defined(__sparc__) || defined(__powerpc__) #define BYTE_ORDER BIG_ENDIAN #endif - + #endif /* HAVE_MACHINE_ENDIAN_H */ #endif /* HAVE_SYS_ENDIAN_H */ #endif /* HAVE_ENDIAN_H */ - + #if !defined(BYTE_ORDER) # error "Undefined or unknown BYTE_ORDER" #endif - + #ifdef _MSC_VER # define RSPAMD_PACKED(name) \ __pragma(pack(push, 1)) struct name __pragma(pack(pop)) @@ -509,5 +509,7 @@ typedef off_t goffset; # define NBYTES(nbits) (((nbits) + BITSPERBYTE - 1) / BITSPERBYTE) #endif +extern uint64_t ottery_rand_uint64(void); +#define UCL_RANDOM_FUNCTION ottery_rand_uint64() #endif diff --git a/contrib/libucl/ucl.h b/contrib/libucl/ucl.h index 4d417eebe..2e0183671 100644 --- a/contrib/libucl/ucl.h +++ b/contrib/libucl/ucl.h @@ -176,12 +176,13 @@ typedef enum ucl_string_flags { * Basic flags for an object */ typedef enum ucl_object_flags { - UCL_OBJECT_ALLOCATED_KEY = 0x1, /**< An object has key allocated internally */ - UCL_OBJECT_ALLOCATED_VALUE = 0x2, /**< An object has a string value allocated internally */ - UCL_OBJECT_NEED_KEY_ESCAPE = 0x4, /**< The key of an object need to be escaped on output */ - UCL_OBJECT_EPHEMERAL = 0x8, /**< Temporary object that does not need to be freed really */ - UCL_OBJECT_MULTILINE = 0x10, /**< String should be displayed as multiline string */ - UCL_OBJECT_MULTIVALUE = 0x20 /**< Object is a key with multiple values */ + UCL_OBJECT_ALLOCATED_KEY = (1 << 0), /**< An object has key allocated internally */ + UCL_OBJECT_ALLOCATED_VALUE = (1 << 1), /**< An object has a string value allocated internally */ + UCL_OBJECT_NEED_KEY_ESCAPE = (1 << 2), /**< The key of an object need to be escaped on output */ + UCL_OBJECT_EPHEMERAL = (1 << 3), /**< Temporary object that does not need to be freed really */ + UCL_OBJECT_MULTILINE = (1 << 4), /**< String should be displayed as multiline string */ + UCL_OBJECT_MULTIVALUE = (1 << 5), /**< Object is a key with multiple values */ + UCL_OBJECT_INHERITED = (1 << 6) /**< Object has been inherited from another */ } ucl_object_flags_t; /** @@ -805,6 +806,21 @@ typedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len, const ucl_object_t *arguments, void* ud); +/** + * Context dependent macro handler for a parser + * @param data the content of macro + * @param len the length of content + * @param arguments arguments object + * @param context previously parsed context + * @param ud opaque user data + * @param err error pointer + * @return true if macro has been parsed + */ +typedef bool (*ucl_context_macro_handler) (const unsigned char *data, size_t len, + const ucl_object_t *arguments, + const ucl_object_t *context, + void* ud); + /* Opaque parser */ struct ucl_parser; @@ -831,9 +847,22 @@ UCL_EXTERN bool ucl_parser_set_default_priority (struct ucl_parser *parser, * @param handler handler (it is called immediately after macro is parsed) * @param ud opaque user data for a handler */ -UCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, +UCL_EXTERN void ucl_parser_register_macro (struct ucl_parser *parser, + const char *macro, ucl_macro_handler handler, void* ud); +/** + * Register new context dependent handler for a macro + * @param parser parser object + * @param macro macro name (without leading dot) + * @param handler handler (it is called immediately after macro is parsed) + * @param ud opaque user data for a handler + */ +UCL_EXTERN void ucl_parser_register_context_macro (struct ucl_parser *parser, + const char *macro, + ucl_context_macro_handler handler, + void* ud); + /** * Handler to detect unregistered variables * @param data variable data diff --git a/contrib/libucl/ucl_hash.c b/contrib/libucl/ucl_hash.c index 183eac84f..7de8196fa 100644 --- a/contrib/libucl/ucl_hash.c +++ b/contrib/libucl/ucl_hash.c @@ -46,8 +46,12 @@ ucl_hash_seed (void) static uint64_t seed; if (seed == 0) { +#ifdef UCL_RANDOM_FUNCTION + seed = UCL_RANDOM_FUNCTION; +#else /* Not very random but can be useful for our purposes */ seed = time (NULL); +#endif } return seed; @@ -88,7 +92,14 @@ static const unsigned char lc_map[256] = { 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; -#if (defined(WORD_BIT) && WORD_BIT == 64) || (defined(__WORDSIZE) && __WORDSIZE == 64) +#if (defined(WORD_BIT) && WORD_BIT == 64) || \ + (defined(__WORDSIZE) && __WORDSIZE == 64) || \ + defined(__x86_64__) || \ + defined(__amd64__) +#define UCL64_BIT_HASH 1 +#endif + +#ifdef UCL64_BIT_HASH static inline uint32_t ucl_hash_func (const ucl_object_t *o) { @@ -115,7 +126,7 @@ ucl_hash_equal (const ucl_object_t *k1, const ucl_object_t *k2) KHASH_INIT (ucl_hash_node, const ucl_object_t *, struct ucl_hash_elt, 1, ucl_hash_func, ucl_hash_equal) -#if (defined(WORD_BIT) && WORD_BIT == 64) || (defined(__WORDSIZE) && __WORDSIZE == 64) +#ifdef UCL64_BIT_HASH static inline uint32_t ucl_hash_caseless_func (const ucl_object_t *o) { diff --git a/contrib/libucl/ucl_internal.h b/contrib/libucl/ucl_internal.h index fe926dbaa..885e8c57f 100644 --- a/contrib/libucl/ucl_internal.h +++ b/contrib/libucl/ucl_internal.h @@ -145,8 +145,12 @@ enum ucl_character_type { struct ucl_macro { char *name; - ucl_macro_handler handler; + union { + ucl_macro_handler handler; + ucl_context_macro_handler context_handler; + } h; void* ud; + bool is_context; UT_hash_handle hh; }; @@ -274,6 +278,17 @@ bool ucl_priority_handler (const unsigned char *data, size_t len, */ bool ucl_load_handler (const unsigned char *data, size_t len, const ucl_object_t *args, void* ud); +/** + * Handle inherit macro + * @param data include data + * @param len length of data + * @param args UCL object representing arguments to the macro + * @param ctx the current context object + * @param ud user data + * @return + */ +bool ucl_inherit_handler (const unsigned char *data, size_t len, + const ucl_object_t *args, const ucl_object_t *ctx, void* ud); size_t ucl_strlcpy (char *dst, const char *src, size_t siz); size_t ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz); diff --git a/contrib/libucl/ucl_parser.c b/contrib/libucl/ucl_parser.c index 8f177938c..03935d9d0 100644 --- a/contrib/libucl/ucl_parser.c +++ b/contrib/libucl/ucl_parser.c @@ -1226,6 +1226,12 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, */ unsigned priold = ucl_object_get_priority (tobj), prinew = ucl_object_get_priority (nobj); + + /* Special case for inherited objects */ + if (tobj->flags & UCL_OBJECT_INHERITED) { + prinew = priold + 1; + } + if (priold == prinew) { ucl_parser_append_elt (parser, container, tobj, nobj); } @@ -2066,12 +2072,29 @@ ucl_state_machine (struct ucl_parser *parser) macro_start, macro_len); parser->state = parser->prev_state; if (macro_escaped == NULL) { - ret = macro->handler (macro_start, macro_len, macro_args, - macro->ud); + if (macro->is_context) { + ret = macro->h.context_handler (macro_start, macro_len, + macro_args, + parser->top_obj, + macro->ud); + } + else { + ret = macro->h.handler (macro_start, macro_len, macro_args, + macro->ud); + } } else { - ret = macro->handler (macro_escaped, macro_len, macro_args, + if (macro->is_context) { + ret = macro->h.context_handler (macro_escaped, macro_len, + macro_args, + parser->top_obj, + macro->ud); + } + else { + ret = macro->h.handler (macro_escaped, macro_len, macro_args, macro->ud); + } + UCL_FREE (macro_len + 1, macro_escaped); } @@ -2116,6 +2139,7 @@ ucl_parser_new (int flags) ucl_parser_register_macro (new, "includes", ucl_includes_handler, new); ucl_parser_register_macro (new, "priority", ucl_priority_handler, new); ucl_parser_register_macro (new, "load", ucl_load_handler, new); + ucl_parser_register_context_macro (new, "inherit", ucl_inherit_handler, new); new->flags = flags; new->includepaths = NULL; @@ -2147,14 +2171,39 @@ ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, if (macro == NULL || handler == NULL) { return; } + + new = UCL_ALLOC (sizeof (struct ucl_macro)); + if (new == NULL) { + return; + } + + memset (new, 0, sizeof (struct ucl_macro)); + new->h.handler = handler; + new->name = strdup (macro); + new->ud = ud; + HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new); +} + +void +ucl_parser_register_context_macro (struct ucl_parser *parser, const char *macro, + ucl_context_macro_handler handler, void* ud) +{ + struct ucl_macro *new; + + if (macro == NULL || handler == NULL) { + return; + } + new = UCL_ALLOC (sizeof (struct ucl_macro)); if (new == NULL) { return; } + memset (new, 0, sizeof (struct ucl_macro)); - new->handler = handler; + new->h.context_handler = handler; new->name = strdup (macro); new->ud = ud; + new->is_context = true; HASH_ADD_KEYPTR (hh, parser->macroes, new->name, strlen (new->name), new); } diff --git a/contrib/libucl/ucl_util.c b/contrib/libucl/ucl_util.c index bdac1d214..7833e1f1c 100644 --- a/contrib/libucl/ucl_util.c +++ b/contrib/libucl/ucl_util.c @@ -1578,6 +1578,56 @@ ucl_load_handler (const unsigned char *data, size_t len, return false; } +bool +ucl_inherit_handler (const unsigned char *data, size_t len, + const ucl_object_t *args, const ucl_object_t *ctx, void* ud) +{ + const ucl_object_t *parent, *cur; + ucl_object_t *target, *copy; + ucl_object_iter_t it = NULL; + bool replace = false; + struct ucl_parser *parser = ud; + + parent = ucl_object_find_keyl (ctx, data, len); + + /* Some sanity checks */ + if (parent == NULL || ucl_object_type (parent) != UCL_OBJECT) { + ucl_create_err (&parser->err, "Unable to find inherited object %*.s", + (int)len, data); + return false; + } + + if (parser->stack == NULL || parser->stack->obj == NULL || + ucl_object_type (parser->stack->obj) != UCL_OBJECT) { + ucl_create_err (&parser->err, "Invalid inherit context"); + return false; + } + + target = parser->stack->obj; + + if (args && (cur = ucl_object_find_key (args, "replace")) != NULL) { + replace = ucl_object_toboolean (cur); + } + + while ((cur = ucl_iterate_object (parent, &it, true))) { + /* We do not replace existing keys */ + if (!replace && ucl_object_find_keyl (target, cur->key, cur->keylen)) { + continue; + } + + copy = ucl_object_copy (cur); + + if (!replace) { + copy->flags |= UCL_OBJECT_INHERITED; + } + + ucl_object_insert_key (target, copy, copy->key, + copy->keylen, false); + } + + return true; +} + bool ucl_parser_set_filevars (struct ucl_parser *parser, const char *filename, bool need_expand) { -- 2.39.5