]> source.dussan.org Git - rspamd.git/commitdiff
Fix rcl issues (ported from libucl).
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 17 Oct 2013 13:56:02 +0000 (14:56 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 17 Oct 2013 13:56:02 +0000 (14:56 +0100)
src/rcl/rcl_emitter.c
src/rcl/rcl_parser.c

index 9702ffefd6080cf05e84948189331170b8b2984f..bf394ee1d586e555ee555d3794650666f219cd18 100644 (file)
  */
 
 
-static void rspamd_cl_elt_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs, gboolean compact);
-static void rspamd_cl_obj_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs, gboolean compact);
-static void rspamd_cl_elt_write_rcl (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs, gboolean is_top);
+static void rspamd_cl_elt_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs,
+               gboolean start_tabs, gboolean compact);
+static void rspamd_cl_obj_write_json (rspamd_cl_object_t *obj, GString *buf, guint tabs,
+               gboolean start_tabs, gboolean compact);
+static void rspamd_cl_elt_write_rcl (rspamd_cl_object_t *obj, GString *buf, guint tabs,
+               gboolean start_tabs, gboolean is_top, gboolean expand_array);
 
 /**
  * Add tabulation to the output buffer
@@ -306,25 +309,22 @@ rspamd_cl_elt_obj_write_rcl (rspamd_cl_object_t *obj, GString *buf, guint tabs,
                g_string_append_len (buf, "{\n", 2);
        }
 
-       while (obj) {
-               HASH_ITER (hh, obj, cur, tmp) {
-                       rspamd_cl_add_tabs (buf, tabs + 1, is_top);
-                       g_string_append (buf, cur->key);
-                       if (cur->type != RSPAMD_CL_OBJECT && cur->type != RSPAMD_CL_ARRAY) {
-                               g_string_append_len (buf, " = ", 3);
-                       }
-                       else {
-                               g_string_append_c (buf, ' ');
-                       }
-                       rspamd_cl_elt_write_rcl (cur, buf, is_top ? tabs : tabs + 1, FALSE, FALSE);
-                       if (cur->type != RSPAMD_CL_OBJECT && cur->type != RSPAMD_CL_ARRAY) {
-                               g_string_append_len (buf, ";\n", 2);
-                       }
-                       else {
-                               g_string_append_c (buf, '\n');
-                       }
+       HASH_ITER (hh, obj, cur, tmp) {
+               rspamd_cl_add_tabs (buf, tabs + 1, is_top);
+               g_string_append (buf, cur->key);
+               if (cur->type != RSPAMD_CL_OBJECT && cur->type != RSPAMD_CL_ARRAY) {
+                       g_string_append_len (buf, " = ", 3);
+               }
+               else {
+                       g_string_append_c (buf, ' ');
+               }
+               rspamd_cl_elt_write_rcl (cur, buf, is_top ? tabs : tabs + 1, FALSE, FALSE, TRUE);
+               if (cur->type != RSPAMD_CL_OBJECT && cur->type != RSPAMD_CL_ARRAY) {
+                       g_string_append_len (buf, ";\n", 2);
+               }
+               else {
+                       g_string_append_c (buf, '\n');
                }
-               obj = obj->next;
        }
        rspamd_cl_add_tabs (buf, tabs, is_top);
        if (!is_top) {
@@ -348,7 +348,7 @@ rspamd_cl_elt_array_write_rcl (rspamd_cl_object_t *obj, GString *buf, guint tabs
 
        g_string_append_len (buf, "[\n", 2);
        while (cur) {
-               rspamd_cl_elt_write_rcl (cur, buf, tabs + 1, TRUE, FALSE);
+               rspamd_cl_elt_write_rcl (cur, buf, tabs + 1, TRUE, FALSE, FALSE);
                g_string_append_len (buf, ",\n", 2);
                cur = cur->next;
        }
@@ -362,47 +362,53 @@ rspamd_cl_elt_array_write_rcl (rspamd_cl_object_t *obj, GString *buf, guint tabs
  * @param buf buffer
  */
 static void
-rspamd_cl_elt_write_rcl (rspamd_cl_object_t *obj, GString *buf, guint tabs, gboolean start_tabs, gboolean is_top)
+rspamd_cl_elt_write_rcl (rspamd_cl_object_t *obj, GString *buf, guint tabs,
+               gboolean start_tabs, gboolean is_top, gboolean expand_array)
 {
-       switch (obj->type) {
-       case RSPAMD_CL_INT:
-               if (start_tabs) {
-                       rspamd_cl_add_tabs (buf, tabs, FALSE);
-               }
-               g_string_append_printf (buf, "%ld", (long int)rspamd_cl_obj_toint (obj));
-               break;
-       case RSPAMD_CL_FLOAT:
-               if (start_tabs) {
-                       rspamd_cl_add_tabs (buf, tabs, FALSE);
-               }
-               g_string_append_printf (buf, "%.4lf", rspamd_cl_obj_todouble (obj));
-               break;
-       case RSPAMD_CL_TIME:
-               if (start_tabs) {
-                       rspamd_cl_add_tabs (buf, tabs, FALSE);
-               }
-               g_string_append_printf (buf, "%.4lf", rspamd_cl_obj_todouble (obj));
-               break;
-       case RSPAMD_CL_BOOLEAN:
-               if (start_tabs) {
-                       rspamd_cl_add_tabs (buf, tabs, FALSE);
-               }
-               g_string_append_printf (buf, "%s", rspamd_cl_obj_toboolean (obj) ? "true" : "false");
-               break;
-       case RSPAMD_CL_STRING:
-               if (start_tabs) {
-                       rspamd_cl_add_tabs (buf, tabs, FALSE);
+       if (expand_array && obj->next) {
+               rspamd_cl_elt_array_write_rcl (obj, buf, tabs, start_tabs, is_top);
+       }
+       else {
+               switch (obj->type) {
+               case RSPAMD_CL_INT:
+                       if (start_tabs) {
+                               rspamd_cl_add_tabs (buf, tabs, FALSE);
+                       }
+                       g_string_append_printf (buf, "%ld", (long int)rspamd_cl_obj_toint (obj));
+                       break;
+               case RSPAMD_CL_FLOAT:
+                       if (start_tabs) {
+                               rspamd_cl_add_tabs (buf, tabs, FALSE);
+                       }
+                       g_string_append_printf (buf, "%.4lf", rspamd_cl_obj_todouble (obj));
+                       break;
+               case RSPAMD_CL_TIME:
+                       if (start_tabs) {
+                               rspamd_cl_add_tabs (buf, tabs, FALSE);
+                       }
+                       g_string_append_printf (buf, "%.4lf", rspamd_cl_obj_todouble (obj));
+                       break;
+               case RSPAMD_CL_BOOLEAN:
+                       if (start_tabs) {
+                               rspamd_cl_add_tabs (buf, tabs, FALSE);
+                       }
+                       g_string_append_printf (buf, "%s", rspamd_cl_obj_toboolean (obj) ? "true" : "false");
+                       break;
+               case RSPAMD_CL_STRING:
+                       if (start_tabs) {
+                               rspamd_cl_add_tabs (buf, tabs, FALSE);
+                       }
+                       rspamd_cl_elt_string_write_json (rspamd_cl_obj_tostring (obj), buf);
+                       break;
+               case RSPAMD_CL_OBJECT:
+                       rspamd_cl_elt_obj_write_rcl (obj->value.ov, buf, tabs, start_tabs, is_top);
+                       break;
+               case RSPAMD_CL_ARRAY:
+                       rspamd_cl_elt_array_write_rcl (obj->value.ov, buf, tabs, start_tabs, is_top);
+                       break;
+               case RSPAMD_CL_USERDATA:
+                       break;
                }
-               rspamd_cl_elt_string_write_json (rspamd_cl_obj_tostring (obj), buf);
-               break;
-       case RSPAMD_CL_OBJECT:
-               rspamd_cl_elt_obj_write_rcl (obj->value.ov, buf, tabs, start_tabs, is_top);
-               break;
-       case RSPAMD_CL_ARRAY:
-               rspamd_cl_elt_array_write_rcl (obj->value.ov, buf, tabs, start_tabs, is_top);
-               break;
-       case RSPAMD_CL_USERDATA:
-               break;
        }
 }
 
@@ -420,7 +426,7 @@ rspamd_cl_object_emit_rcl (rspamd_cl_object_t *obj)
        /* Allocate large enough buffer */
        buf = g_string_sized_new (BUFSIZ);
 
-       rspamd_cl_elt_write_rcl (obj, buf, 0, FALSE, TRUE);
+       rspamd_cl_elt_write_rcl (obj, buf, 0, FALSE, TRUE, TRUE);
 
        res = buf->str;
        g_string_free (buf, FALSE);
index 7989ece153516f157407501c2402ef86dbaa4589..b601df310de4cc0f3e002bc599613c7bb03fb092 100644 (file)
  * The implementation of rcl parser
  */
 
+struct rspamd_cl_parser_saved_state {
+       guint line;
+       guint column;
+       gsize remain;
+       const guchar *pos;
+};
+
 /**
  * Move up to len characters
  * @param parser
@@ -54,6 +61,34 @@ rspamd_cl_chunk_skipc (struct rspamd_cl_chunk *chunk, guchar c)
        chunk->remain --;
 }
 
+/**
+ * Save parser state
+ * @param chunk
+ * @param s
+ */
+static inline void
+rspamd_cl_chunk_save_state (struct rspamd_cl_chunk *chunk, struct rspamd_cl_parser_saved_state *s)
+{
+       s->column = chunk->column;
+       s->pos = chunk->pos;
+       s->line = chunk->line;
+       s->remain = chunk->remain;
+}
+
+/**
+ * Restore parser state
+ * @param chunk
+ * @param s
+ */
+static inline void
+rspamd_cl_chunk_restore_state (struct rspamd_cl_chunk *chunk, struct rspamd_cl_parser_saved_state *s)
+{
+       chunk->column = s->column;
+       chunk->pos = s->pos;
+       chunk->line = s->line;
+       chunk->remain = s->remain;
+}
+
 static inline gboolean
 rcl_test_character (guchar c, gint type_flags)
 {
@@ -227,6 +262,9 @@ rspamd_cl_lex_number (struct rspamd_cl_parser *parser,
        gboolean got_dot = FALSE, got_exp = FALSE, need_double = FALSE, is_date = FALSE;
        gdouble dv;
        gint64 lv;
+       struct rspamd_cl_parser_saved_state s;
+
+       rspamd_cl_chunk_save_state (chunk, &s);
 
        if (*p == '-') {
                rspamd_cl_chunk_skipc (chunk, *p);
@@ -240,11 +278,13 @@ rspamd_cl_lex_number (struct rspamd_cl_parser *parser,
                else {
                        if (p == c) {
                                /* Empty digits sequence, not a number */
+                               rspamd_cl_chunk_restore_state (chunk, &s);
                                return FALSE;
                        }
                        else if (*p == '.') {
                                if (got_dot) {
                                        /* Double dots, not a number */
+                                       rspamd_cl_chunk_restore_state (chunk, &s);
                                        return FALSE;
                                }
                                else {
@@ -257,6 +297,7 @@ rspamd_cl_lex_number (struct rspamd_cl_parser *parser,
                        else if (*p == 'e' || *p == 'E') {
                                if (got_exp) {
                                        /* Double exp, not a number */
+                                       rspamd_cl_chunk_restore_state (chunk, &s);
                                        return FALSE;
                                }
                                else {
@@ -265,10 +306,12 @@ rspamd_cl_lex_number (struct rspamd_cl_parser *parser,
                                        rspamd_cl_chunk_skipc (chunk, *p);
                                        p ++;
                                        if (p >= chunk->end) {
+                                               rspamd_cl_chunk_restore_state (chunk, &s);
                                                return FALSE;
                                        }
                                        if (!g_ascii_isdigit (*p) && *p != '+' && *p != '-') {
                                                /* Wrong exponent sign */
+                                               rspamd_cl_chunk_restore_state (chunk, &s);
                                                return FALSE;
                                        }
                                        else {
@@ -295,6 +338,7 @@ rspamd_cl_lex_number (struct rspamd_cl_parser *parser,
                rspamd_cl_set_err (chunk, RSPAMD_CL_ESYNTAX, "numeric value is out of range", err);
                parser->prev_state = parser->state;
                parser->state = RSPAMD_RCL_STATE_ERROR;
+               rspamd_cl_chunk_restore_state (chunk, &s);
                return FALSE;
        }
 
@@ -950,7 +994,7 @@ static gboolean
 rspamd_cl_parse_after_value (struct rspamd_cl_parser *parser, struct rspamd_cl_chunk *chunk, GError **err)
 {
        const guchar *p;
-       gboolean got_sep = FALSE, got_comma = FALSE, got_semicolon = FALSE;
+       gboolean got_sep = FALSE;
        struct rspamd_cl_stack *st;
 
        p = chunk->pos;
@@ -973,22 +1017,12 @@ rspamd_cl_parse_after_value (struct rspamd_cl_parser *parser, struct rspamd_cl_c
                else if (*p == ',') {
                        /* Got a separator */
                        got_sep = TRUE;
-                       if (got_comma || got_semicolon) {
-                               rspamd_cl_set_err (chunk, RSPAMD_CL_ESYNTAX, "unexpected comma detected", err);
-                               return FALSE;
-                       }
-                       got_comma = TRUE;
                        rspamd_cl_chunk_skipc (chunk, *p);
                        p ++;
                }
                else if (*p == ';') {
                        /* Got a separator */
                        got_sep = TRUE;
-                       if (got_comma || got_semicolon) {
-                               rspamd_cl_set_err (chunk, RSPAMD_CL_ESYNTAX, "unexpected semicolon detected", err);
-                               return FALSE;
-                       }
-                       got_semicolon = TRUE;
                        rspamd_cl_chunk_skipc (chunk, *p);
                        p ++;
                }