]> source.dussan.org Git - rspamd.git/commitdiff
Update libucl and use UCL_RANDOM_FUNCTION.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 18 Aug 2015 12:17:16 +0000 (13:17 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Tue, 18 Aug 2015 12:17:16 +0000 (13:17 +0100)
config.h.in
contrib/libucl/ucl.h
contrib/libucl/ucl_hash.c
contrib/libucl/ucl_internal.h
contrib/libucl/ucl_parser.c
contrib/libucl/ucl_util.c

index 41be3c5872bd8b877d1607cb3d371b5aabd51a26..695b4385603a28988e380e8cee97504b6c582595 100644 (file)
 
  #ifdef HAVE_ENDIAN_H
  #include <endian.h>
- #else 
+ #else
  #ifdef HAVE_SYS_ENDIAN_H
  #include <sys/endian.h>
  #else
  #ifdef HAVE_MACHINE_ENDIAN_H
  #include <machine/endian.h>
  #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
index 4d417eebefc791cee4e16a8c55f5f1a341b0d091..2e0183671a03e59b550373a1c01c100078b5e070 100644 (file)
@@ -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
index 183eac84f4a050d477d574a26a57cd638af422bb..7de8196fa01497760528cbc765deb98a4f554db2 100644 (file)
@@ -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)
 {
index fe926dbaa4332b09fab13637c16d4415ec611708..885e8c57ff3e915e8609d0bbf17df88533a7e41b 100644 (file)
@@ -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);
index 8f177938c7978340b319a9be9eb1c5306d7be9c6..03935d9d0ae6595e03fd0dbb584fdf0506715830 100644 (file)
@@ -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);
 }
 
index bdac1d214903e2c0c5b107614c0e49217497a03b..7833e1f1cfe3e26c246b6f3c55dd19fc2d02408e 100644 (file)
@@ -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)
 {