]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Minor] Sync from libucl
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 21 Mar 2018 13:08:45 +0000 (13:08 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 21 Mar 2018 13:09:52 +0000 (13:09 +0000)
contrib/libucl/ucl_parser.c
contrib/libucl/ucl_util.c

index 088813918e79fee67cb34ea6265144aa92df9f0f..e82b5da513f20ffc288f2dacb94f061e9a8ad939 100644 (file)
@@ -44,16 +44,17 @@ struct ucl_parser_saved_state {
  * @param len
  * @return new position in chunk
  */
-#define ucl_chunk_skipc(chunk, p)    do{                                       \
-    if (*(p) == '\n') {                                                                                \
-        (chunk)->line ++;                                                                      \
-        (chunk)->column = 0;                                                           \
-    }                                                                                                          \
-    else (chunk)->column ++;                                                           \
-    (p++);                                                                                                     \
-    (chunk)->pos ++;                                                                           \
-    (chunk)->remain --;                                                                                \
-    } while (0)
+#define ucl_chunk_skipc(chunk, p)    \
+do {                                 \
+       if (*(p) == '\n') {          \
+               (chunk)->line ++;    \
+               (chunk)->column = 0; \
+       }                            \
+       else (chunk)->column ++;     \
+       (p++);                       \
+       (chunk)->pos ++;             \
+       (chunk)->remain --;          \
+} while (0)
 
 static inline void
 ucl_set_err (struct ucl_parser *parser, int code, const char *str, UT_string **err)
@@ -1706,6 +1707,7 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
                                }
                        }
                        /* Fallback to ordinary strings */
+                       /* FALLTHRU */
                default:
 parse_string:
                        if (obj == NULL) {
@@ -2506,6 +2508,16 @@ ucl_parser_set_default_priority (struct ucl_parser *parser, unsigned prio)
        return true;
 }
 
+int
+ucl_parser_get_default_priority (struct ucl_parser *parser)
+{
+       if (parser == NULL) {
+               return -1;
+       }
+
+       return parser->default_priority;
+}
+
 void
 ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
                ucl_macro_handler handler, void* ud)
@@ -2723,6 +2735,39 @@ ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data,
                        parser->default_priority, UCL_DUPLICATE_APPEND, UCL_PARSE_UCL);
 }
 
+bool
+ucl_parser_insert_chunk (struct ucl_parser *parser, const unsigned char *data,
+                size_t len)
+{
+       if (parser == NULL || parser->top_obj == NULL) {
+               return false;
+       }
+
+       bool res;
+       struct ucl_chunk *chunk;
+
+       int state = parser->state;
+       parser->state = UCL_STATE_INIT;
+
+       /* Prevent inserted chunks from unintentionally closing the current object */
+       if (parser->stack != NULL && parser->stack->next != NULL) parser->stack->level = parser->stack->next->level;
+
+       res = ucl_parser_add_chunk_full (parser, data, len, parser->chunks->priority,
+                                       parser->chunks->strategy, parser->chunks->parse_type);
+
+       /* Remove chunk from the stack */
+       chunk = parser->chunks;
+       if (chunk != NULL) {
+               parser->chunks = chunk->next;
+               UCL_FREE (sizeof (struct ucl_chunk), chunk);
+               parser->recursion --;
+       }
+
+       parser->state = state;
+
+       return res;
+}
+
 bool
 ucl_parser_add_string_priority (struct ucl_parser *parser, const char *data,
                size_t len, unsigned priority)
@@ -2772,3 +2817,54 @@ ucl_set_include_path (struct ucl_parser *parser, ucl_object_t *paths)
 
        return true;
 }
+
+unsigned char ucl_parser_chunk_peek (struct ucl_parser *parser)
+{
+       if (parser == NULL || parser->chunks == NULL || parser->chunks->pos == NULL || parser->chunks->end == NULL ||
+               parser->chunks->pos == parser->chunks->end) {
+               return 0;
+       }
+
+       return( *parser->chunks->pos );
+}
+
+bool ucl_parser_chunk_skip (struct ucl_parser *parser)
+{
+       if (parser == NULL || parser->chunks == NULL || parser->chunks->pos == NULL || parser->chunks->end == NULL ||
+               parser->chunks->pos == parser->chunks->end) {
+               return false;
+       }
+
+       const unsigned char *p = parser->chunks->pos;
+       ucl_chunk_skipc( parser->chunks, p );
+       if( parser->chunks->pos != NULL ) return true;
+       return false;
+}
+
+ucl_object_t* ucl_parser_get_current_stack_object (struct ucl_parser *parser, unsigned int depth)
+{
+       ucl_object_t *obj;
+
+       if (parser == NULL || parser->stack == NULL) {
+               return NULL;
+       }
+
+       struct ucl_stack *stack = parser->stack;
+       if(stack == NULL || stack->obj == NULL || ucl_object_type (stack->obj) != UCL_OBJECT)
+       {
+               return NULL;
+       }
+
+       for( unsigned int i = 0; i < depth; ++i )
+       {
+               stack = stack->next;
+               if(stack == NULL || stack->obj == NULL || ucl_object_type (stack->obj) != UCL_OBJECT)
+               {
+                       return NULL;
+               }
+       }
+
+       obj = ucl_object_ref (stack->obj);
+       return obj;
+}
+
index 8f5231e2fdfb9eeae806d84e302068977e263af8..fba3df920d93df83dc1ebe02df8b89f29e355491 100644 (file)
 #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
-#include <libgen.h> /* For dirname */
+#ifndef _WIN32
+#  include <libgen.h> /* For dirname */
+#endif
 #endif
 
 typedef kvec_t(ucl_object_t *) ucl_array_t;
@@ -59,8 +67,10 @@ typedef kvec_t(ucl_object_t *) ucl_array_t;
 #include <fetch.h>
 #endif
 
-#ifdef _WIN32
+#if defined(_MSC_VER)
 #include <windows.h>
+#include <io.h>
+#include <direct.h>
 
 #ifndef PROT_READ
 #define PROT_READ       1
@@ -81,10 +91,9 @@ 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
+#define getcwd _getcwd
+#define open _open
+#define close _close
 
 static void *ucl_mmap(char *addr, size_t length, int prot, int access, int fd, off_t offset)
 {
@@ -132,16 +141,46 @@ static int ucl_munmap(void *map,size_t length)
        return(0);
 }
 
-static char* ucl_realpath(const char *path, char *resolved_path) {
-    char *p;
-    char tmp[MAX_PATH + 1];
-    strncpy(tmp, path, sizeof(tmp)-1);
-    p = tmp;
-    while(*p) {
-        if (*p == '/') *p = '\\';
-        p++;
-    }
-    return _fullpath(resolved_path, tmp, MAX_PATH);
+static char* ucl_realpath(const char *path, char *resolved_path)
+{
+       char *p;
+       char tmp[MAX_PATH + 1];
+       strncpy(tmp, path, sizeof(tmp)-1);
+       p = tmp;
+       while(*p) {
+               if (*p == '/') *p = '\\';
+               p++;
+       }
+       return _fullpath(resolved_path, tmp, MAX_PATH);
+}
+
+
+char *dirname(char *path)
+{
+       static char path_buffer[_MAX_PATH];
+       char drive[_MAX_DRIVE];
+       char dir[_MAX_DIR];
+       char fname[_MAX_FNAME];
+       char ext[_MAX_EXT];
+
+       _splitpath (path, drive, dir, fname, ext);
+       _makepath(path_buffer, drive, dir, NULL, NULL);
+
+       return path_buffer;
+}
+
+char *basename(char *path)
+{
+       static char path_buffer[_MAX_PATH];
+       char drive[_MAX_DRIVE];
+       char dir[_MAX_DIR];
+       char fname[_MAX_FNAME];
+       char ext[_MAX_EXT];
+
+       _splitpath(path, drive, dir, fname, ext);
+       _makepath(path_buffer, NULL, NULL, fname, ext);
+
+       return path_buffer;
 }
 #else
 #define ucl_mmap mmap
@@ -1052,53 +1091,89 @@ ucl_include_file_single (const unsigned char *data, size_t len,
                old_obj = __DECONST (ucl_object_t *, ucl_hash_search (container,
                                params->prefix, strlen (params->prefix)));
 
-               if (strcasecmp (params->target, "array") == 0 && old_obj == NULL) {
-                       /* Create an array with key: prefix */
-                       old_obj = ucl_object_new_full (UCL_ARRAY, params->priority);
-                       old_obj->key = params->prefix;
-                       old_obj->keylen = strlen (params->prefix);
-                       ucl_copy_key_trash(old_obj);
-                       old_obj->prev = old_obj;
-                       old_obj->next = NULL;
+               if (strcasecmp (params->target, "array") == 0) {
+                       if (old_obj == NULL) {
+                               /* Create an array with key: prefix */
+                               old_obj = ucl_object_new_full (UCL_ARRAY, params->priority);
+                               old_obj->key = params->prefix;
+                               old_obj->keylen = strlen (params->prefix);
+                               ucl_copy_key_trash (old_obj);
+                               old_obj->prev = old_obj;
+                               old_obj->next = NULL;
 
-                       container = ucl_hash_insert_object (container, old_obj,
-                                       parser->flags & UCL_PARSER_KEY_LOWERCASE);
-                       parser->stack->obj->len ++;
+                               container = ucl_hash_insert_object (container, old_obj,
+                                               parser->flags & UCL_PARSER_KEY_LOWERCASE);
+                               parser->stack->obj->len++;
 
-                       nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority);
-                       nest_obj->prev = nest_obj;
-                       nest_obj->next = NULL;
+                               nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority);
+                               nest_obj->prev = nest_obj;
+                               nest_obj->next = NULL;
 
-                       ucl_array_append (old_obj, nest_obj);
-               }
-               else if (old_obj == NULL) {
-                       /* Create an object with key: prefix */
-                       nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority);
+                               ucl_array_append (old_obj, nest_obj);
+                       }
+                       else {
+                               if (ucl_object_type (old_obj) == UCL_ARRAY) {
+                                       /* Append to the existing array */
+                                       nest_obj = ucl_object_new_full (UCL_OBJECT,
+                                                       params->priority);
+                                       if (nest_obj == NULL) {
+                                               ucl_create_err (&parser->err,
+                                                               "cannot allocate memory for an object");
+                                               if (buf) {
+                                                       ucl_munmap (buf, buflen);
+                                               }
 
-                       if (nest_obj == NULL) {
-                               ucl_create_err (&parser->err, "cannot allocate memory for an object");
-                               if (buf) {
-                                       ucl_munmap (buf, buflen);
+                                               return false;
+                                       }
+                                       nest_obj->prev = nest_obj;
+                                       nest_obj->next = NULL;
+
+                                       ucl_array_append (old_obj, nest_obj);
                                }
+                               else {
+                                       /* Convert the object to an array */
+                                       new_obj = ucl_object_typed_new (UCL_ARRAY);
+                                       if (new_obj == NULL) {
+                                               ucl_create_err (&parser->err,
+                                                               "cannot allocate memory for an object");
+                                               if (buf) {
+                                                       ucl_munmap (buf, buflen);
+                                               }
 
-                               return false;
-                       }
+                                               return false;
+                                       }
+                                       new_obj->key = old_obj->key;
+                                       new_obj->keylen = old_obj->keylen;
+                                       new_obj->flags |= UCL_OBJECT_MULTIVALUE;
+                                       new_obj->prev = new_obj;
+                                       new_obj->next = NULL;
+
+                                       nest_obj = ucl_object_new_full (UCL_OBJECT,
+                                                       params->priority);
+                                       if (nest_obj == NULL) {
+                                               ucl_create_err (&parser->err,
+                                                               "cannot allocate memory for an object");
+                                               if (buf) {
+                                                       ucl_munmap (buf, buflen);
+                                               }
 
-                       nest_obj->key = params->prefix;
-                       nest_obj->keylen = strlen (params->prefix);
-                       ucl_copy_key_trash(nest_obj);
-                       nest_obj->prev = nest_obj;
-                       nest_obj->next = NULL;
+                                               return false;
+                                       }
+                                       nest_obj->prev = nest_obj;
+                                       nest_obj->next = NULL;
 
-                       container = ucl_hash_insert_object (container, nest_obj,
-                                       parser->flags & UCL_PARSER_KEY_LOWERCASE);
-                       parser->stack->obj->len ++;
+                                       ucl_array_append (new_obj, old_obj);
+                                       ucl_array_append (new_obj, nest_obj);
+                                       ucl_hash_replace (container, old_obj, new_obj);
+                               }
+                       }
                }
-               else if (strcasecmp (params->target, "array") == 0 ||
-                               ucl_object_type(old_obj) == UCL_ARRAY) {
-                       if (ucl_object_type(old_obj) == UCL_ARRAY) {
-                               /* Append to the existing array */
+               else {
+                       /* Case of object */
+                       if (old_obj == NULL) {
+                               /* Create an object with key: prefix */
                                nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority);
+
                                if (nest_obj == NULL) {
                                        ucl_create_err (&parser->err, "cannot allocate memory for an object");
                                        if (buf) {
@@ -1107,64 +1182,39 @@ ucl_include_file_single (const unsigned char *data, size_t len,
 
                                        return false;
                                }
+
+                               nest_obj->key = params->prefix;
+                               nest_obj->keylen = strlen (params->prefix);
+                               ucl_copy_key_trash(nest_obj);
                                nest_obj->prev = nest_obj;
                                nest_obj->next = NULL;
 
-                               ucl_array_append (old_obj, nest_obj);
+                               container = ucl_hash_insert_object (container, nest_obj,
+                                               parser->flags & UCL_PARSER_KEY_LOWERCASE);
+                               parser->stack->obj->len ++;
                        }
                        else {
-                               /* Convert the object to an array */
-                               new_obj = ucl_object_typed_new (UCL_ARRAY);
-                               if (new_obj == NULL) {
-                                       ucl_create_err (&parser->err, "cannot allocate memory for an object");
-                                       if (buf) {
-                                               ucl_munmap (buf, buflen);
-                                       }
-
-                                       return false;
+                               if (ucl_object_type (old_obj) == UCL_OBJECT) {
+                                       /* Append to existing Object*/
+                                       nest_obj = old_obj;
                                }
-                               new_obj->key = old_obj->key;
-                               new_obj->keylen = old_obj->keylen;
-                               new_obj->flags |= UCL_OBJECT_MULTIVALUE;
-                               new_obj->prev = new_obj;
-                               new_obj->next = NULL;
-
-                               nest_obj = ucl_object_new_full (UCL_OBJECT, params->priority);
-                               if (nest_obj == NULL) {
-                                       ucl_create_err (&parser->err, "cannot allocate memory for an object");
+                               else {
+                                       /* The key is not an object */
+                                       ucl_create_err (&parser->err,
+                                                       "Conflicting type for key: %s, asked %s, has %s",
+                                                       params->prefix, params->target,
+                                                       ucl_object_type_to_string (ucl_object_type (old_obj)));
                                        if (buf) {
                                                ucl_munmap (buf, buflen);
                                        }
 
                                        return false;
                                }
-                               nest_obj->prev = nest_obj;
-                               nest_obj->next = NULL;
-
-                               ucl_array_append (new_obj, old_obj);
-                               ucl_array_append (new_obj, nest_obj);
-                               ucl_hash_replace (container, old_obj, new_obj);
                        }
                }
-               else {
-                       if (ucl_object_type (old_obj) == UCL_OBJECT) {
-                               /* Append to existing Object*/
-                               nest_obj = old_obj;
-                       }
-                       else {
-                               /* The key is not an object */
-                               ucl_create_err (&parser->err,
-                                               "Conflicting type for key: %s",
-                                               params->prefix);
-                               if (buf) {
-                                       ucl_munmap (buf, buflen);
-                               }
 
-                               return false;
-                       }
-               }
 
-                /* Put all of the content of the include inside that object */
+               /* Put all of the content of the include inside that object */
                parser->stack->obj->value.ov = container;
 
                st = UCL_ALLOC (sizeof (struct ucl_stack));
@@ -1808,8 +1858,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;
@@ -1832,7 +1883,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);
@@ -1841,6 +1893,18 @@ ucl_parser_add_file_priority (struct ucl_parser *parser, const char *filename,
        return ret;
 }
 
+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)
 {
@@ -1848,13 +1912,16 @@ ucl_parser_add_file (struct ucl_parser *parser, const char *filename)
                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;
@@ -1866,6 +1933,9 @@ ucl_parser_add_fd_priority (struct ucl_parser *parser, int fd,
                        fd, strerror (errno));
                return false;
        }
+       if (st.st_size == 0) {
+               return true;
+       }
        if ((buf = ucl_mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
                ucl_create_err (&parser->err, "cannot mmap fd %d: %s",
                        fd, strerror (errno));
@@ -1877,7 +1947,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);
@@ -1886,6 +1957,18 @@ ucl_parser_add_fd_priority (struct ucl_parser *parser, int fd,
        return ret;
 }
 
+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)
 {
@@ -3025,6 +3108,22 @@ ucl_array_pop_first (ucl_object_t *top)
        return ret;
 }
 
+unsigned int
+ucl_array_size (const ucl_object_t *top)
+{
+       if (top == NULL || top->type != UCL_ARRAY) {
+               return 0;
+       }
+
+       UCL_ARRAY_GET (vec, top);
+
+       if (vec != NULL) {
+               return kv_size(*vec);
+       }
+
+       return 0;
+}
+
 const ucl_object_t *
 ucl_array_find_index (const ucl_object_t *top, unsigned int index)
 {
@@ -3132,7 +3231,7 @@ ucl_object_toint_safe (const ucl_object_t *obj, int64_t *target)
                break;
        case UCL_FLOAT:
        case UCL_TIME:
-               *target = obj->value.dv; /* Loosing of decimal points */
+               *target = obj->value.dv; /* Losing of decimal points */
                break;
        default:
                return false;