summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2016-12-02 17:11:01 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2016-12-02 17:11:01 +0200
commit15f6dbf66eed6bed5c084d97077e7cc5f8e192a7 (patch)
tree1debcb9960f990af390cf3930c539736d0179960
parented04bc837e353e61e4c43f6bdbd9a67859c61f61 (diff)
downloadmailutils-15f6dbf66eed6bed5c084d97077e7cc5f8e192a7.tar.gz
mailutils-15f6dbf66eed6bed5c084d97077e7cc5f8e192a7.tar.bz2
sieve: change string allocation and argument passing convention
Strings are allocated in a per-machine string space. String and argument lists form contiguous arrays of structures. Regular ex- pressions are compiled when they are needed. Compiled expressions are cached for eventual reuse.
-rw-r--r--examples/numaddr.c2
-rw-r--r--include/mailutils/sieve.h78
-rw-r--r--libmu_sieve/Makefile.am1
-rw-r--r--libmu_sieve/actions.c17
-rw-r--r--libmu_sieve/comparator.c297
-rw-r--r--libmu_sieve/extensions/editheader.c62
-rw-r--r--libmu_sieve/extensions/list.c2
-rw-r--r--libmu_sieve/extensions/vacation.c22
-rw-r--r--libmu_sieve/mem.c41
-rw-r--r--libmu_sieve/prog.c366
-rw-r--r--libmu_sieve/relational.c5
-rw-r--r--libmu_sieve/require.c24
-rw-r--r--libmu_sieve/runtime.c46
-rw-r--r--libmu_sieve/sieve-priv.h51
-rw-r--r--libmu_sieve/sieve.y257
-rw-r--r--libmu_sieve/string.c61
-rw-r--r--libmu_sieve/tests.c84
-rw-r--r--libmu_sieve/util.c379
-rw-r--r--sieve/tests/delheader.at2
-rw-r--r--sieve/tests/enc-char.at35
20 files changed, 908 insertions, 924 deletions
diff --git a/examples/numaddr.c b/examples/numaddr.c
index 7981e0bc2..584d2b9f7 100644
--- a/examples/numaddr.c
+++ b/examples/numaddr.c
@@ -95,7 +95,7 @@ numaddr_test (mu_sieve_machine_t mach)
vc.count = 0;
/* Count the addresses */
- rc = mu_sieve_vlist_do (h, _count_items, &vc);
+ rc = mu_sieve_vlist_do (mach, h, _count_items, &vc);
/* Here rc >= 1 iff the counted number of addresses is greater or equal
to vc.limit. If `:under' tag was given we reverse the return value */
diff --git a/include/mailutils/sieve.h b/include/mailutils/sieve.h
index 20ad24eec..7227abad8 100644
--- a/include/mailutils/sieve.h
+++ b/include/mailutils/sieve.h
@@ -33,6 +33,13 @@ extern "C" {
typedef struct mu_sieve_machine *mu_sieve_machine_t;
+typedef struct mu_sieve_string
+{
+ char *orig;
+ char *exp;
+ void *rx;
+} mu_sieve_string_t;
+
typedef int (*mu_sieve_handler_t) (mu_sieve_machine_t mach);
typedef void (*mu_sieve_action_log_t) (mu_sieve_machine_t mach,
const char *action,
@@ -40,13 +47,12 @@ typedef void (*mu_sieve_action_log_t) (mu_sieve_machine_t mach,
typedef int (*mu_sieve_relcmp_t) (int, int);
typedef int (*mu_sieve_relcmpn_t) (size_t, size_t);
-typedef int (*mu_sieve_comparator_t) (const char *, const char *);
+typedef int (*mu_sieve_comparator_t) (mu_sieve_machine_t mach,
+ mu_sieve_string_t *, const char *);
typedef int (*mu_sieve_retrieve_t) (void *item, void *data, int idx,
char **pval);
typedef void (*mu_sieve_destructor_t) (void *data);
-typedef int (*mu_sieve_tag_checker_t) (mu_sieve_machine_t mach,
- const char *name,
- mu_list_t tags, mu_list_t args);
+typedef int (*mu_sieve_tag_checker_t) (mu_sieve_machine_t mach);
typedef enum
{
@@ -55,24 +61,29 @@ typedef enum
SVT_STRING,
SVT_STRING_LIST,
SVT_TAG,
- SVT_IDENT,
- SVT_POINTER
+ SVT_IDENT
}
mu_sieve_data_type;
-typedef struct mu_sieve_runtime_tag mu_sieve_runtime_tag_t;
+struct mu_sieve_slice
+{
+ size_t first;
+ size_t count;
+};
+
+typedef struct mu_sieve_slice *mu_sieve_slice_t;
union mu_sieve_value_storage
{
char *string;
size_t number;
- mu_list_t list;
- void *ptr;
+ struct mu_sieve_slice list;
};
typedef struct
{
mu_sieve_data_type type;
+ char *tag;
union mu_sieve_value_storage v;
} mu_sieve_value_t;
@@ -88,12 +99,6 @@ typedef struct
mu_sieve_tag_checker_t checker;
} mu_sieve_tag_group_t;
-struct mu_sieve_runtime_tag
-{
- char *tag;
- mu_sieve_value_t *arg;
-};
-
typedef struct
{
const char *name;
@@ -135,11 +140,9 @@ void *mu_sieve_realloc (mu_sieve_machine_t mach, void *ptr, size_t size);
void mu_sieve_reclaim_default (void *p);
void mu_sieve_reclaim_list (void *p);
void mu_sieve_reclaim_value (void *p);
-void mu_sieve_reclaim_tag (void *p);
-mu_sieve_value_t *mu_sieve_value_create (mu_sieve_machine_t mach,
- mu_sieve_data_type type, void *data);
-void mu_sieve_slist_destroy (mu_list_t *plist);
+size_t mu_sieve_value_create (mu_sieve_machine_t mach,
+ mu_sieve_data_type type, void *data);
/* Symbol space functions */
mu_sieve_register_t *mu_sieve_test_lookup (mu_sieve_machine_t mach,
@@ -185,30 +188,41 @@ int mu_sieve_str_to_relcmp (const char *str, mu_sieve_relcmp_t *test,
mu_sieve_relcmpn_t *stest);
mu_sieve_relcmp_t mu_sieve_get_relcmp (mu_sieve_machine_t mach);
-void mu_sieve_require (mu_sieve_machine_t mach, mu_list_t slist);
+void mu_sieve_require (mu_sieve_machine_t mach, mu_sieve_slice_t list);
+void mu_sieve_value_get (mu_sieve_machine_t mach, mu_sieve_value_t *val,
+ mu_sieve_data_type type, void *ret);
+
int mu_sieve_get_tag (mu_sieve_machine_t mach, char *name,
mu_sieve_data_type type, void *ret);
-int mu_sieve_get_tag_untyped (mu_sieve_machine_t mach,
- char *name, mu_sieve_value_t **ret);
+mu_sieve_value_t *mu_sieve_get_tag_untyped (mu_sieve_machine_t mach,
+ char const *name);
+mu_sieve_value_t *mu_sieve_get_tag_n (mu_sieve_machine_t mach, size_t n);
int mu_sieve_load_ext (mu_sieve_machine_t mach, const char *name);
-int mu_sieve_match_part_checker (mu_sieve_machine_t mach,
- const char *name, mu_list_t tags,
- mu_list_t args);
-int mu_sieve_match_part_checker (mu_sieve_machine_t mach,
- const char *name, mu_list_t tags,
- mu_list_t args);
+int mu_sieve_match_part_checker (mu_sieve_machine_t mach);
+
/* Operations on value lists */
mu_sieve_value_t *mu_sieve_get_arg_optional (mu_sieve_machine_t mach,
size_t index);
mu_sieve_value_t *mu_sieve_get_arg_untyped (mu_sieve_machine_t mach,
size_t index);
-int mu_sieve_get_arg (mu_sieve_machine_t mach, size_t index,
- mu_sieve_data_type type, void *ret);
-int mu_sieve_vlist_do (mu_sieve_value_t *val, mu_list_action_t ac,
+void mu_sieve_get_arg (mu_sieve_machine_t mach, size_t index,
+ mu_sieve_data_type type, void *ret);
+
+char *mu_sieve_string (mu_sieve_machine_t mach,
+ mu_sieve_slice_t slice,
+ size_t i);
+struct mu_sieve_string *mu_sieve_string_raw (mu_sieve_machine_t mach,
+ mu_sieve_slice_t slice,
+ size_t i);
+
+
+int mu_sieve_vlist_do (mu_sieve_machine_t mach,
+ mu_sieve_value_t *val, mu_list_action_t ac,
void *data);
-int mu_sieve_vlist_compare (mu_sieve_value_t *a, mu_sieve_value_t *b,
+int mu_sieve_vlist_compare (mu_sieve_machine_t mach,
+ mu_sieve_value_t *a, mu_sieve_value_t *b,
mu_sieve_comparator_t comp,
mu_sieve_relcmp_t test, mu_sieve_retrieve_t ac,
void *data, size_t *count);
diff --git a/libmu_sieve/Makefile.am b/libmu_sieve/Makefile.am
index 0b06ffe3e..b9f3a0ada 100644
--- a/libmu_sieve/Makefile.am
+++ b/libmu_sieve/Makefile.am
@@ -42,6 +42,7 @@ libmu_sieve_la_SOURCES = \
sieve-gram.h\
sieve-lex.c\
strexp.c\
+ string.c\
tests.c\
util.c
libmu_sieve_la_LIBADD = ${MU_LIB_MAILUTILS} @LTDL_LIB@
diff --git a/libmu_sieve/actions.c b/libmu_sieve/actions.c
index 077b8cd06..f3ef7f472 100644
--- a/libmu_sieve/actions.c
+++ b/libmu_sieve/actions.c
@@ -511,24 +511,22 @@ mu_sieve_data_type fileinto_args[] = {
};
static int
-perms_tag_checker (mu_sieve_machine_t mach,
- const char *name, mu_list_t tags, mu_list_t args)
+perms_tag_checker (mu_sieve_machine_t mach)
{
- mu_iterator_t itr;
+ size_t i;
int err = 0;
- if (!tags || mu_list_get_iterator (tags, &itr))
+ if (mach->tagcount == 0)
return 0;
- for (mu_iterator_first (itr); !err && !mu_iterator_is_done (itr);
- mu_iterator_next (itr))
+ for (i = 0; i < mach->tagcount; i++)
{
int flag;
const char *p;
- mu_sieve_runtime_tag_t *t;
- mu_iterator_current (itr, (void **)&t);
+ mu_sieve_value_t *t = mu_sieve_get_tag_n (mach, i);
+
if (strcmp (t->tag, "permissions") == 0)
{
- if (mu_parse_stream_perm_string (&flag, t->arg->v.string, &p))
+ if (mu_parse_stream_perm_string (&flag, t->v.string, &p))
{
mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
_("invalid permissions (near %s)"), p);
@@ -537,7 +535,6 @@ perms_tag_checker (mu_sieve_machine_t mach,
}
}
}
- mu_iterator_destroy (&itr);
return err;
}
diff --git a/libmu_sieve/comparator.c b/libmu_sieve/comparator.c
index a2ac34b0f..a0d5836d3 100644
--- a/libmu_sieve/comparator.c
+++ b/libmu_sieve/comparator.c
@@ -38,13 +38,13 @@ typedef struct {
int
mu_sieve_register_comparator (mu_sieve_machine_t mach,
- const char *name,
- int required,
- mu_sieve_comparator_t is,
- mu_sieve_comparator_t contains,
- mu_sieve_comparator_t matches,
- mu_sieve_comparator_t regex,
- mu_sieve_comparator_t eq)
+ const char *name,
+ int required,
+ mu_sieve_comparator_t is,
+ mu_sieve_comparator_t contains,
+ mu_sieve_comparator_t matches,
+ mu_sieve_comparator_t regex,
+ mu_sieve_comparator_t eq)
{
sieve_comparator_record_t *rp;
@@ -113,56 +113,28 @@ mu_sieve_comparator_lookup (mu_sieve_machine_t mach, const char *name,
return NULL;
}
-static int
-_find_comparator (void *item, void *data)
-{
- mu_sieve_runtime_tag_t *tag = item;
-
- if (strcmp (tag->tag, TAG_COMPFUN) == 0)
- {
- *(mu_sieve_comparator_t*)data = tag->arg->v.ptr;
- return 1;
- }
- return 0;
-}
+static int i_ascii_casemap_is (mu_sieve_machine_t mach,
+ mu_sieve_string_t *pattern, const char *text);
mu_sieve_comparator_t
mu_sieve_get_comparator (mu_sieve_machine_t mach)
{
- mu_sieve_comparator_t comp = NULL;
-
- mu_list_foreach (mach->tag_list, _find_comparator, &comp);
- return comp ? comp : mu_sieve_comparator_lookup (mach,
- "i;ascii-casemap",
- MU_SIEVE_MATCH_IS);
+ if (!mach->comparator)
+ return i_ascii_casemap_is;
+ return mach->comparator;
}
/* Compile time support */
-
-struct regex_data
-{
- mu_sieve_machine_t mach;
- int flags;
- mu_list_t list;
-};
-
-#ifndef FNM_CASEFOLD
-static int
-_pattern_upcase (void *item, void *data)
-{
- mu_strupper (item);
- return 0;
-}
-#endif
-
-static int
-_regex_compile (void *item, void *data)
+static void
+compile_pattern (mu_sieve_machine_t mach, mu_sieve_string_t *pattern, int flags)
{
- struct regex_data *rd = data;
int rc;
- regex_t *preg = mu_sieve_malloc (rd->mach, sizeof (*preg));
-
- rc = regcomp (preg, (char*)item, rd->flags);
+ regex_t *preg;
+
+ if (pattern->rx)
+ return;
+ preg = mu_sieve_malloc (mach, sizeof (*preg));
+ rc = regcomp (preg, pattern->orig, REG_EXTENDED | flags);
if (rc)
{
size_t size = regerror (rc, preg, NULL, 0);
@@ -170,64 +142,39 @@ _regex_compile (void *item, void *data)
if (errbuf)
{
regerror (rc, preg, errbuf, size);
- mu_diag_at_locus (MU_LOG_ERROR, &rd->mach->locus,
- _("regex error: %s"), errbuf);
+ mu_sieve_error (mach, _("regex error: %s"), errbuf);
free (errbuf);
}
else
- mu_diag_at_locus (MU_LOG_ERROR, &rd->mach->locus, _("regex error"));
- mu_i_sv_error (rd->mach);
- return rc;
+ mu_sieve_error (mach, _("regex error"));
+ mu_sieve_abort (mach);
}
-
- mu_list_append (rd->list, preg);
-
- return 0;
-}
-
-static int
-_free_regex (void *item, void *unused)
-{
- regfree ((regex_t*)item);
- return 0;
-}
-
-static void
-_free_reglist (void *data)
-{
- mu_list_t list = data;
- mu_list_foreach (list, _free_regex, NULL);
- mu_list_destroy (&list);
+ pattern->rx = preg;
}
static int
-comp_false (const char *pattern, const char *text)
+comp_false (mu_sieve_machine_t mach, mu_sieve_string_t *pattern,
+ const char *text)
{
return 0;
}
int
-mu_sieve_match_part_checker (mu_sieve_machine_t mach,
- const char *name, mu_list_t tags, mu_list_t args)
+mu_sieve_match_part_checker (mu_sieve_machine_t mach)
{
- mu_iterator_t itr;
- mu_sieve_runtime_tag_t *match = NULL;
- mu_sieve_runtime_tag_t *comp = NULL;
- mu_sieve_runtime_tag_t *tmp;
+ size_t i;
+ mu_sieve_value_t *match = NULL;
mu_sieve_comparator_t compfun = NULL;
- char *compname = "false";
+ char *compname = NULL;
int matchtype;
- int err = 0;
-
- if (!tags || mu_list_get_iterator (tags, &itr))
+
+ if (mach->tagcount == 0)
return 0;
- for (mu_iterator_first (itr); !err && !mu_iterator_is_done (itr);
- mu_iterator_next (itr))
+ for (i = 0; i < mach->tagcount; i++)
{
- mu_sieve_runtime_tag_t *t;
- mu_iterator_current (itr, (void **)&t);
+ mu_sieve_value_t *t = mu_sieve_get_tag_n (mach, i);
if (strcmp (t->tag, "is") == 0
|| strcmp (t->tag, "contains") == 0
@@ -240,22 +187,21 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach,
{
mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
_("match type specified twice in call to `%s'"),
- name);
+ mach->identifier);
mu_i_sv_error (mach);
- err = 1;
+ return 1;
}
else
match = t;
}
- else if (strcmp (t->tag, "comparator") == 0)
- comp = t;
+ else if (strcmp (t->tag, "comparator") == 0)
+ {
+ if (t->type != SVT_STRING)
+ abort ();
+ compname = mu_sieve_string (mach, &t->v.list, 0);
+ }
}
- mu_iterator_destroy (&itr);
-
- if (err)
- return 1;
-
if (!match || strcmp (match->tag, "is") == 0)
matchtype = MU_SIEVE_MATCH_IS;
else if (strcmp (match->tag, "contains") == 0)
@@ -264,42 +210,43 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach,
matchtype = MU_SIEVE_MATCH_MATCHES;
else if (strcmp (match->tag, "regex") == 0)
matchtype = MU_SIEVE_MATCH_REGEX;
- else
+ else if (match->type == SVT_STRING)
{
- char *str = match->arg->v.string;
+ char *str = mu_sieve_string (mach, &match->v.list, 0);
if (strcmp (match->tag, "count") == 0)
{
mu_sieve_value_t *val;
char *str;
size_t count;
- if (comp && strcmp (comp->arg->v.string, "i;ascii-numeric"))
+ if (compname && strcmp (compname, "i;ascii-numeric"))
{
mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
/* TRANSLATORS: Do not translate ':count'.
It is the name of a Sieve tag */
_("comparator %s is incompatible with "
":count in call to `%s'"),
- comp->arg->v.string,
- name);
+ compname,
+ mach->identifier);
mu_i_sv_error (mach);
return 1;
}
matchtype = MU_SIEVE_MATCH_LAST; /* to not leave it undefined */
+ compname = "false";
compfun = comp_false;
- if (mu_list_get (args, 1, (void**) &val))
- return 1; /* shouldn't happen */
- /* NOTE: Type of v is always SVT_STRING_LIST */
- mu_list_count (val->v.list, &count);
- if (count > 1)
+ val = mu_sieve_get_arg_untyped (mach, 1);
+ /* NOTE: Type of val is always SVT_STRING_LIST */
+ if (val->type != SVT_STRING_LIST)
+ abort ();
+ if (val->v.list.count > 1)
{
mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
_("second argument must be a list of one element"));
mu_i_sv_error (mach);
return 1;
}
- mu_list_get (val->v.list, 0, (void **) &str);
+ str = mu_sieve_string_raw (mach, &val->v.list, 0)->orig;
count = strtoul (str, &str, 10);
if (*str)
{
@@ -316,72 +263,32 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach,
{
mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
_("invalid relational match `%s' in call to `%s'"),
- str, name);
+ str, mach->identifier);
mu_i_sv_error (mach);
return 1;
}
}
-
+ else
+ abort ();//FIXME
+
if (!compfun)
{
- compname = comp ? comp->arg->v.string : "i;ascii-casemap";
+ if (!compname)
+ compname = "i;ascii-casemap";
compfun = mu_sieve_comparator_lookup (mach, compname, matchtype);
if (!compfun)
{
mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
_("comparator `%s' is incompatible with match type `%s' in call to `%s'"),
- compname, match ? match->tag : "is", name);
+ compname, match ? match->tag : "is",
+ mach->identifier);
mu_i_sv_error (mach);
return 1;
}
}
- tmp = mu_sieve_malloc (mach, sizeof (*tmp));
- tmp->tag = TAG_COMPFUN;
- tmp->arg = mu_sieve_value_create (mach, SVT_POINTER, compfun);
- mu_list_append (tags, tmp);
+ mach->comparator = compfun;
- if (matchtype == MU_SIEVE_MATCH_REGEX)
- {
- /* To speed up things, compile all patterns at once.
- Notice that it is supposed that patterns are in arg 2 */
- mu_sieve_value_t *val, *newval;
- struct regex_data rd;
- int rc;
-
- if (mu_list_get (args, 1, (void**)&val))
- return 0;
-
- rd.mach = mach;
- rd.flags = REG_EXTENDED;
- if (strcmp (compname, "i;ascii-casemap") == 0)
- rd.flags |= REG_ICASE;
-
- mu_list_create (&rd.list);
-
- rc = mu_sieve_vlist_do (val, _regex_compile, &rd);
-
- mu_sieve_machine_add_destructor (rd.mach, _free_reglist, rd.list);
-
- if (rc)
- return rc;
- newval = mu_sieve_value_create (rd.mach, SVT_STRING_LIST, rd.list);
- mu_list_replace (args, val, newval);
- }
-#ifndef FNM_CASEFOLD
- else if (matchtype == MU_SIEVE_MATCH_MATCHES
- && strcmp (compname, "i;ascii-casemap") == 0)
- {
- int rc;
- mu_sieve_value_t *val;
-
- if (mu_list_get (args, 1, (void**)&val))
- return 0;
- rc = mu_sieve_vlist_do (val, _pattern_upcase, NULL);
- if (rc)
- return rc;
- }
-#endif
return 0;
}
@@ -390,85 +297,88 @@ mu_sieve_match_part_checker (mu_sieve_machine_t mach,
/* :comparator i;octet */
static int
-i_octet_is (const char *pattern, const char *text)
+i_octet_is (mu_sieve_machine_t mach, mu_sieve_string_t *pattern,
+ const char *text)
{
- return strcmp (pattern, text) == 0;
+ return strcmp (pattern->orig, text) == 0;
}
static int
-i_octet_contains (const char *pattern, const char *text)
+i_octet_contains (mu_sieve_machine_t mach, mu_sieve_string_t *pattern,
+ const char *text)
{
- return strstr (text, pattern) != NULL;
+ return strstr (text, pattern->orig) != NULL;
}
static int
-i_octet_matches (const char *pattern, const char *text)
+i_octet_matches (mu_sieve_machine_t mach, mu_sieve_string_t *pattern,
+ const char *text)
{
- return fnmatch (pattern, text, 0) == 0;
+ return fnmatch (pattern->orig, text, 0) == 0;
}
static int
-i_octet_regex (const char *pattern, const char *text)
+i_octet_regex (mu_sieve_machine_t mach, mu_sieve_string_t *pattern,
+ const char *text)
{
- return regexec ((regex_t *) pattern, text, 0, NULL, 0) == 0;
+ compile_pattern (mach, pattern, 0);
+ return regexec ((regex_t *)pattern->rx, text, 0, NULL, 0) == 0;
}
static int
-i_octet_eq (const char *pattern, const char *text)
+i_octet_eq (mu_sieve_machine_t mach,
+ mu_sieve_string_t *pattern, const char *text)
{
- return strcmp (text, pattern);
+ return strcmp (text, pattern->orig);
}
/* :comparator i;ascii-casemap */
static int
-i_ascii_casemap_is (const char *pattern, const char *text)
+i_ascii_casemap_is (mu_sieve_machine_t mach,
+ mu_sieve_string_t *pattern, const char *text)
{
- return mu_c_strcasecmp (pattern, text) == 0;
+ return mu_c_strcasecmp (pattern->orig, text) == 0;
}
static int
-i_ascii_casemap_contains (const char *pattern, const char *text)
+i_ascii_casemap_contains (mu_sieve_machine_t mach,
+ mu_sieve_string_t *pattern, const char *text)
{
- return mu_c_strcasestr (text, pattern) != NULL;
+ return mu_c_strcasestr (text, pattern->orig) != NULL;
}
static int
-i_ascii_casemap_matches (const char *pattern, const char *text)
+i_ascii_casemap_matches (mu_sieve_machine_t mach,
+ mu_sieve_string_t *pattern, const char *text)
{
-#ifdef FNM_CASEFOLD
- return fnmatch (pattern, text, FNM_CASEFOLD) == 0;
-#else
- int rc;
- char *p = strdup (text);
- if (!p)
- return 0;
- _pattern_upcase (p, NULL);
- rc = fnmatch (pattern, p, 0) == 0;
- free (p);
- return rc;
-#endif
+ return fnmatch (pattern->orig, text, FNM_CASEFOLD) == 0;
}
static int
-i_ascii_casemap_regex (const char *pattern, const char *text)
+i_ascii_casemap_regex (mu_sieve_machine_t mach,
+ mu_sieve_string_t *pattern, const char *text)
{
- return regexec ((regex_t *) pattern, text, 0, NULL, 0) == 0;
+ compile_pattern (mach, pattern, REG_ICASE);
+ return regexec ((regex_t *) pattern->rx, text, 0, NULL, 0) == 0;
}
static int
-i_ascii_casemap_eq (const char *pattern, const char *text)
+i_ascii_casemap_eq (mu_sieve_machine_t mach,
+ mu_sieve_string_t *pattern, const char *text)
{
- return mu_c_strcasecmp (text, pattern);
+ return mu_c_strcasecmp (text, pattern->orig);
}
/* :comparator i;ascii-numeric */
static int
-i_ascii_numeric_is (const char *pattern, const char *text)
+i_ascii_numeric_is (mu_sieve_machine_t mach,
+ mu_sieve_string_t *pattern, const char *text)
{
- if (mu_isdigit (*pattern))
+ if (mu_isdigit (*pattern->orig))
{
if (mu_isdigit (*text))
- return strtol (pattern, NULL, 10) == strtol (text, NULL, 10);
+ //FIXME: Error checking
+ return strtol (pattern->orig, NULL, 10) == strtol (text, NULL, 10);
else
return 0;
}
@@ -479,13 +389,14 @@ i_ascii_numeric_is (const char *pattern, const char *text)
}
static int
-i_ascii_numeric_eq (const char *pattern, const char *text)
+i_ascii_numeric_eq (mu_sieve_machine_t mach,
+ mu_sieve_string_t *pattern, const char *text)
{
- if (mu_isdigit (*pattern))
+ if (mu_isdigit (*pattern->orig))
{
if (mu_isdigit (*text))
{
- size_t a = strtoul (pattern, NULL, 10);
+ size_t a = strtoul (pattern->orig, NULL, 10);
size_t b = strtoul (text, NULL, 10);
if (b > a)
return 1;
diff --git a/libmu_sieve/extensions/editheader.c b/libmu_sieve/extensions/editheader.c
index 52c745eb4..3ef017f0d 100644
--- a/libmu_sieve/extensions/editheader.c
+++ b/libmu_sieve/extensions/editheader.c
@@ -81,7 +81,6 @@ sieve_deleteheader (mu_sieve_machine_t mach)
{
mu_sieve_value_t *val;
const char *field_name;
- const char *field_pattern;
mu_message_t msg;
mu_header_t hdr;
int rc;
@@ -91,41 +90,9 @@ sieve_deleteheader (mu_sieve_machine_t mach)
mu_sieve_get_arg (mach, 0, SVT_STRING, &field_name);
val = mu_sieve_get_arg_optional (mach, 1);
- if (!val)
- {
- field_pattern = NULL;
- mu_sieve_log_action (mach, "DELETEHEADER", "%s", field_name);
- }
- else
- {
- switch (val->type)
- {
- case SVT_STRING_LIST:
- if (mu_list_get (val->v.list, 0, (void**)&field_pattern))
- {
- mu_sieve_error (mach, "%lu: %s",
- (unsigned long) mu_sieve_get_message_num (mach),
- _("cannot get list item"));
- mu_sieve_abort (mach);
- }
- mu_sieve_log_action (mach, "DELETEHEADER", "%s: (regexp)",
- field_name);
- break;
-
- case SVT_STRING:
- field_pattern = val->v.string;
- mu_sieve_log_action (mach, "DELETEHEADER", "%s: %s", field_name,
- field_pattern);
- break;
-
- default:
- mu_sieve_error (mach, "%lu: %s: %d",
- (unsigned long) mu_sieve_get_message_num (mach),
- _("unexpected value type"), val->type);
- mu_sieve_abort (mach);
-
- }
- }
+
+ mu_sieve_log_action (mach, "DELETEHEADER", "%s%s", field_name,
+ val ? " (values)" : "" );
if (mu_sieve_is_dry_run (mach))
return 0;
@@ -141,7 +108,14 @@ sieve_deleteheader (mu_sieve_machine_t mach)
mu_sieve_abort (mach);
}
- mu_header_get_iterator (hdr, &itr);
+ rc = mu_header_get_iterator (hdr, &itr);
+ if (rc)
+ {
+ mu_sieve_error (mach, "mu_header_get_iterator: %s",
+ mu_strerror (rc));
+ mu_sieve_abort (mach);
+ }
+
if (mu_sieve_get_tag (mach, "last", SVT_VOID, NULL))
{
int backwards = 1;
@@ -162,10 +136,18 @@ sieve_deleteheader (mu_sieve_machine_t mach)
if (idx && ++i < idx)
continue;
- if (field_pattern)
+ if (val)
{
- if (comp (field_pattern, fv))
- mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
+ for (i = 0; i < val->v.list.count; i++)
+ {
+ mu_sieve_string_t *s = mu_sieve_string_raw (mach,
+ &val->v.list, i);
+ if (comp (mach, s, fv))
+ {
+ mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
+ break;
+ }
+ }
}
else
mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
diff --git a/libmu_sieve/extensions/list.c b/libmu_sieve/extensions/list.c
index 71696c6ec..3a64e0a69 100644
--- a/libmu_sieve/extensions/list.c
+++ b/libmu_sieve/extensions/list.c
@@ -159,7 +159,7 @@ list_test (mu_sieve_machine_t mach)
h = mu_sieve_get_arg_untyped (mach, 0);
v = mu_sieve_get_arg_untyped (mach, 1);
mu_message_get_header (mu_sieve_get_message (mach), &clos.header);
- result = mu_sieve_vlist_compare (h, v, comp,
+ result = mu_sieve_vlist_compare (mach, h, v, comp,
mu_sieve_get_relcmp (mach),
list_retrieve_header,
&clos, NULL) > 0;
diff --git a/libmu_sieve/extensions/vacation.c b/libmu_sieve/extensions/vacation.c
index 989a87a8e..fa19c8785 100644
--- a/libmu_sieve/extensions/vacation.c
+++ b/libmu_sieve/extensions/vacation.c
@@ -161,8 +161,8 @@ _compare (void *item, void *data)
of the originating mail. Return non-zero if so and store a pointer
to the matching address in *MY_ADDRESS. */
static int
-match_addresses (mu_header_t hdr, char *email, mu_sieve_value_t *addresses,
- char const **my_address)
+match_addresses (mu_sieve_machine_t mach, mu_header_t hdr, char *email,
+ mu_sieve_value_t *addresses, char const **my_address)
{
int match = 0;
const char *str;
@@ -176,7 +176,7 @@ match_addresses (mu_header_t hdr, char *email, mu_sieve_value_t *addresses,
if (_compare (email, &ad))
match = 1;
else if (addresses)
- match += mu_sieve_vlist_do (addresses, _compare, &ad);
+ match += mu_sieve_vlist_do (mach, addresses, _compare, &ad);
mu_address_destroy (&ad.addr);
}
}
@@ -188,7 +188,7 @@ match_addresses (mu_header_t hdr, char *email, mu_sieve_value_t *addresses,
if (_compare (email, &ad))
match = 1;
else if (addresses)
- match += mu_sieve_vlist_do (addresses, _compare, &ad);
+ match += mu_sieve_vlist_do (mach, addresses, _compare, &ad);
mu_address_destroy (&ad.addr);
}
}
@@ -249,8 +249,8 @@ noreply_address_p (mu_sieve_machine_t mach, char *email)
for (i = 0; rc == 0 && noreply_sender[i]; i++)
rc = regex_comparator (noreply_sender[i], &rd);
- if (!rc && mu_sieve_get_tag_untyped (mach, "noreply", &arg))
- rc = mu_sieve_vlist_do (arg, regex_comparator, &rd);
+ if (!rc && (arg = mu_sieve_get_tag_untyped (mach, "noreply")) != NULL)
+ rc = mu_sieve_vlist_do (mach, arg, regex_comparator, &rd);
return rc;
}
@@ -716,12 +716,13 @@ vacation_reply (mu_sieve_machine_t mach, mu_message_t msg,
{
mu_header_set_value (newhdr, MU_HEADER_TO, to, 0);
- if (mu_sieve_get_tag_untyped (mach, "header", &val))
+ val = mu_sieve_get_tag_untyped (mach, "header");
+ if (val)
{
struct header_closure hc;
hc.mach = mach;
hc.hdr = newhdr;
- mu_sieve_vlist_do (val, add_header, &hc);
+ mu_sieve_vlist_do (mach, val, add_header, &hc);
}
vacation_subject (mach, msg, newhdr);
@@ -807,9 +808,8 @@ sieve_action_vacation (mu_sieve_machine_t mach)
return_address = my_address;
else
{
- mu_sieve_value_t *val = NULL;
- mu_sieve_get_tag_untyped (mach, "aliases", &val);
- if (match_addresses (hdr, my_address, val, &return_address) == 0)
+ mu_sieve_value_t *val = mu_sieve_get_tag_untyped (mach, "aliases");
+ if (match_addresses (mach, hdr, my_address, val, &return_address) == 0)
{
free (my_address);
return 0;
diff --git a/libmu_sieve/mem.c b/libmu_sieve/mem.c
index f03b06dd5..25dc26c5b 100644
--- a/libmu_sieve/mem.c
+++ b/libmu_sieve/mem.c
@@ -196,11 +196,42 @@ mu_sieve_reclaim_value (void *p)
/* For now, the same as _default. Will change in the future */
free (p);
}
-
+
+/* Based on gnulib's x2nrealloc */
void
-mu_sieve_reclaim_tag (void *p)
+mu_i_sv_2nrealloc (mu_sieve_machine_t mach, void **pptr, size_t *pnmemb,
+ size_t size)
{
- mu_sieve_runtime_tag_t *tag = p;
- mu_sieve_reclaim_value (tag->arg);
-}
+ void *ptr = *pptr;
+ size_t nmemb = *pnmemb;
+
+ if (!ptr)
+ {
+ if (!nmemb)
+ {
+ /* Initial allocation size */
+ nmemb = 16;
+ }
+ }
+ else
+ {
+ /* Set NMEMB = floor (1.5 * NMEMB) + 1 so that progress is made even
+ if NMEMB == 0.
+ Check for overflow, so that NMEMB * SIZE stays in size_t range.
+ The check may be slightly conservative, but an exact check isn't
+ worth the trouble. */
+ if ((size_t) -1 / 3 * 2 / size <= nmemb)
+ {
+ mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ _("requested too much memory %zu * %zu"),
+ nmemb, size);
+ mu_sieve_abort (mach);
+ }
+ nmemb += nmemb / 2 + 1;
+ }
+ ptr = mu_sieve_realloc (mach, ptr, nmemb * size);
+
+ *pptr = ptr;
+ *pnmemb = nmemb;
+}
diff --git a/libmu_sieve/prog.c b/libmu_sieve/prog.c
index 8c6bc6d8e..17b65870f 100644
--- a/libmu_sieve/prog.c
+++ b/libmu_sieve/prog.c
@@ -24,25 +24,15 @@
#include <assert.h>
#include <sieve-priv.h>
-int
+void
mu_i_sv_code (struct mu_sieve_machine *mach, sieve_op_t op)
{
if (mach->pc >= mach->progsize)
{
- size_t newsize = mach->progsize + SIEVE_CODE_INCR;
- sieve_op_t *newprog =
- mu_sieve_realloc (mach, mach->prog, newsize * sizeof mach->prog[0]);
- if (!newprog)
- {
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus, _("not enough memory"));
- mu_i_sv_error (mach);
- return 1;
- }
- mach->prog = newprog;
- mach->progsize = newsize;
+ mu_i_sv_2nrealloc (mach, (void**) &mach->prog, &mach->progsize,
+ sizeof mach->prog[0]);
}
mach->prog[mach->pc++] = op;
- return 0;
}
static int
@@ -105,249 +95,247 @@ _compare_ptr (void *item, void *data)
struct check_arg
{
struct mu_sieve_machine *mach;
- const char *name;
- mu_list_t args;
- mu_list_t tags;
+ struct mu_sieve_node *node;
};
static int
_run_checker (void *item, void *data)
{
struct check_arg *arg = data;
- return (*(mu_sieve_tag_checker_t)item) (arg->mach, arg->name,
- arg->tags, arg->args);
+ mu_sieve_machine_t mach = arg->mach;
+ struct mu_sieve_node *node = arg->node;
+ mu_sieve_tag_checker_t checker = item;
+ int rc;
+
+ mach->comparator = node->v.command.comparator;
+ mach->argstart = node->v.command.argstart;
+ mach->argcount = node->v.command.argcount;
+ mach->tagcount = node->v.command.tagcount;
+ mach->identifier = node->v.command.reg->name;
+
+ rc = checker (arg->mach);
+
+ /* checker is allowed to alter these values */
+ node->v.command.comparator = mach->comparator;
+ node->v.command.argcount = mach->argcount;
+ node->v.command.tagcount = mach->tagcount;
+
+ mach->argstart = 0;
+ mach->argcount = 0;
+ mach->tagcount = 0;
+ mach->identifier = NULL;
+
+ return rc;
}
-static int
-sv_code_command (struct mu_sieve_machine *mach,
- mu_sieve_register_t *reg, mu_list_t arglist)
+void
+mu_i_sv_lint_command (struct mu_sieve_machine *mach,
+ struct mu_sieve_node *node)
{
- mu_iterator_t itr;
- mu_list_t arg_list = NULL;
- mu_list_t tag_list = NULL;
+ size_t i;
+ mu_sieve_register_t *reg = node->v.command.reg;
+
+ mu_sieve_value_t *start = mach->valspace + node->v.command.argstart;
+
mu_list_t chk_list = NULL;
mu_sieve_data_type *exp_arg;
int opt_args = 0;
int rc, err = 0;
static mu_sieve_data_type empty[] = { SVT_VOID };
- if (mu_i_sv_code (mach, (sieve_op_t) reg->handler))
- return 1;
-
exp_arg = reg->req_args ? reg->req_args : empty;
- if (arglist)
+ /* Pass 1: consolidation */
+ for (i = 0; i < node->v.command.argcount; i++)
{
- rc = mu_list_get_iterator (arglist, &itr);
-
- if (rc)
- {
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("cannot create iterator: %s"),
- mu_strerror (rc));
- mu_i_sv_error (mach);
- return 1;
- }
-
- for (mu_iterator_first (itr);
- !mu_iterator_is_done (itr); mu_iterator_next (itr))
- {
- mu_sieve_value_t *val;
- mu_sieve_runtime_tag_t tagrec, *tagptr;
+ mu_sieve_value_t *val = start + i;
- mu_iterator_current (itr, (void **)&val);
+ if (val->type == SVT_TAG)
+ {
+ mu_sieve_tag_checker_t cf;
+ mu_sieve_tag_def_t *tag = find_tag (reg->tags, val->v.string, &cf);
+
+ if (!tag)
+ {
+ mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ _("invalid tag name `%s' for `%s'"),
+ val->v.string, reg->name);
+ mu_i_sv_error (mach);
+ err = 1;
+ break;
+ }
+
+ node->v.command.tagcount++;
- if (val->type == SVT_TAG)
+ if (tag->argtype == SVT_VOID)
+ {
+ val->type = SVT_VOID;
+ val->tag = val->v.string;
+ val->v.string = NULL;
+ }
+ else
{
- mu_sieve_tag_checker_t cf;
- mu_sieve_tag_def_t *tag = find_tag (reg->tags, val->v.string,
- &cf);
- if (!tag)
+ if (i + 1 == node->v.command.argcount)
{
mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("invalid tag name `%s' for `%s'"),
- val->v.string, reg->name);
+ _("required argument for tag %s is missing"),
+ tag->name);
mu_i_sv_error (mach);
err = 1;
break;
}
+
+ val[1].tag = val->v.string;
+ *val = val[1];
+ memmove (val + 1, val + 2,
+ (node->v.command.argcount - i - 2) * sizeof (val[0]));
+ mach->valcount--;
+ node->v.command.argcount--;
- if (!tag_list && (rc = mu_list_create (&tag_list)))
+ if (val->type != tag->argtype)
{
mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("cannot create tag list: %s"),
- mu_strerror (rc));
+ _("type mismatch in argument to "
+ "tag `%s'"),
+ tag->name);
+ mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ _("expected %s but passed %s"),
+ mu_sieve_type_str (tag->argtype),
+ mu_sieve_type_str (val->type));
mu_i_sv_error (mach);
err = 1;
break;
}
-
- tagrec.tag = tag->name;
- if (tag->argtype != SVT_VOID)
- {
- mu_iterator_next (itr);
- if (mu_iterator_is_done (itr))
- {
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("required argument for tag %s is missing"),
- tag->name);
- mu_i_sv_error (mach);
- err = 1;
- break;
- }
- mu_iterator_current (itr, (void **)&tagrec.arg);
- if (tagrec.arg->type != tag->argtype)
- {
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("type mismatch in argument to "
- "tag `%s'"),
- tag->name);
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("expected %s but passed %s"),
- mu_sieve_type_str (tag->argtype),
- mu_sieve_type_str (tagrec.arg->type));
- mu_i_sv_error (mach);
- err = 1;
- break;
- }
- }
- else
- tagrec.arg = NULL;
-
- tagptr = mu_sieve_malloc (mach, sizeof (*tagptr));
- *tagptr = tagrec;
- mu_list_append (tag_list, tagptr);
+ }
- if (cf)
+ if (cf)
+ {
+ if (!chk_list && (rc = mu_list_create (&chk_list)))
{
- if (!chk_list && (rc = mu_list_create (&chk_list)))
- {
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("cannot create check list: %s"),
- mu_strerror (rc));
- mu_i_sv_error (mach);
- err = 1;
- break;
- }
- if (mu_list_foreach (chk_list, _compare_ptr, cf) == 0)
- mu_list_append (chk_list, cf);
+ mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ _("cannot create check list: %s"),
+ mu_strerror (rc));
+ mu_i_sv_error (mach);
+ err = 1;
+ break;
}
+ //FIXME
+ if (mu_list_foreach (chk_list, _compare_ptr, cf) == 0)
+ mu_list_append (chk_list, cf);
}
- else
+ }
+ else
+ {
+ if (*exp_arg == SVT_VOID)
{
- if (*exp_arg == SVT_VOID)
+ if (reg->opt_args)
{
- if (reg->opt_args)
- {
- exp_arg = reg->opt_args;
- opt_args = 1;
- }
- else
- {
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("too many arguments in call to `%s'"),
- reg->name);
- mu_i_sv_error (mach);
- err = 1;
- break;
- }
+ exp_arg = reg->opt_args;
+ opt_args = 1;
}
-
- if (*exp_arg != val->type)
+ else
{
- if (*exp_arg == SVT_STRING_LIST && val->type == SVT_STRING)
- {
- mu_list_t list;
-
- mu_list_create (&list);
- mu_list_append (list, val->v.string);
- mu_sieve_free (mach, val);
- val = mu_sieve_value_create (mach, SVT_STRING_LIST, list);
- }
- else
- {
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("type mismatch in argument %lu to `%s'"),
- (unsigned long) (exp_arg - reg->req_args + 1),
- reg->name);
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("expected %s but passed %s"),
- mu_sieve_type_str (*exp_arg),
- mu_sieve_type_str (val->type));
- mu_i_sv_error (mach);
- err = 1;
- break;
- }
+ mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ _("too many arguments in call to `%s'"),
+ reg->name);
+ mu_i_sv_error (mach);
+ err = 1;
+ break;
}
-
- if (!arg_list && (rc = mu_list_create (&arg_list)))
+ }
+
+ if (*exp_arg != val->type)
+ {
+ if (*exp_arg == SVT_STRING_LIST && val->type == SVT_STRING)
+ /* compatible types */;
+ else
{
mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("cannot create arg list: %s"),
- mu_strerror (rc));
+ _("type mismatch in argument %lu to `%s'"),
+ (unsigned long) (exp_arg - reg->req_args + 1),
+ reg->name);
+ mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ _("expected %s but passed %s"),
+ mu_sieve_type_str (*exp_arg),
+ mu_sieve_type_str (val->type));
mu_i_sv_error (mach);
err = 1;
break;
}
-
- mu_list_append (arg_list, val);
- exp_arg++;
- }
+ }
+ exp_arg++;
}
- mu_iterator_destroy (&itr);
}
- if (!err)
+ if (!err && !opt_args && *exp_arg != SVT_VOID)
{
- if (!opt_args && *exp_arg != SVT_VOID)
- {
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("too few arguments in call to `%s'"),
- reg->name);
- mu_i_sv_error (mach);
- err = 1;
- }
+ mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
+ _("too few arguments in call to `%s'"),
+ reg->name);
+ mu_i_sv_error (mach);
+ err = 1;
+ }
+
+ if (err)
+ {
+ mu_list_destroy (&chk_list);
+ return;
+ }
- if (chk_list)
+ if (node->v.command.tagcount)
+ {
+ /* Move tags to the end of the list */
+ for (i = 1; i < node->v.command.argcount; i++)
{
- struct check_arg chk_arg;
-
- chk_arg.mach = mach;
- chk_arg.name = reg->name;
- chk_arg.tags = tag_list;
- chk_arg.args = arg_list;
- err = mu_list_foreach (chk_list, _run_checker, &chk_arg);
+ int j;//FIXME
+ mu_sieve_value_t tmp = start[i];
+ for (j = i - 1; j >= 0; j--)
+ {
+ if (!tmp.tag && start[j].tag)
+ start[j + 1] = start[j];
+ else
+ break;
+ }
+ start[j + 1] = tmp;
}
}
-
- if (!err)
- err = mu_i_sv_code (mach, (sieve_op_t) arg_list)
- || mu_i_sv_code (mach, (sieve_op_t) tag_list)
- || mu_i_sv_code (mach, (sieve_op_t) (char*) reg->name);
- if (err)
+ node->v.command.argcount -= node->v.command.tagcount;
+
+ if (chk_list)
{
- mu_list_destroy (&arg_list);
- mu_list_destroy (&tag_list);
- mu_list_destroy (&chk_list);
+ struct check_arg chk_arg;
+
+ chk_arg.mach = mach;
+ chk_arg.node = node;
+ err = mu_list_foreach (chk_list, _run_checker, &chk_arg);
}
+}
- return err;
+static void
+sv_code_command (struct mu_sieve_machine *mach,
+ struct mu_sieve_node *node)
+{
+ mu_i_sv_code (mach, (sieve_op_t) node->v.command.reg->handler);
+ mu_i_sv_code (mach, (sieve_op_t) node->v.command.argstart);
+ mu_i_sv_code (mach, (sieve_op_t) node->v.command.argcount);
+ mu_i_sv_code (mach, (sieve_op_t) node->v.command.tagcount);
+ mu_i_sv_code (mach, (sieve_op_t) (char*) node->v.command.reg->name);
+ mu_i_sv_code (mach, (sieve_op_t) node->v.command.comparator);
}
-int
+void
mu_i_sv_code_action (struct mu_sieve_machine *mach,
- mu_sieve_register_t *reg, mu_list_t arglist)
+ struct mu_sieve_node *node)
{
- return mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_action)
- || sv_code_command (mach, reg, arglist);
+ mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_action);
+ sv_code_command (mach, node);
}
-int
-mu_i_sv_code_test (struct mu_sieve_machine *mach,
- mu_sieve_register_t *reg, mu_list_t arglist)
+void
+mu_i_sv_code_test (struct mu_sieve_machine *mach, struct mu_sieve_node *node)
{
- return mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_test)
- || sv_code_command (mach, reg, arglist);
+ mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_test);
+ sv_code_command (mach, node);
}
diff --git a/libmu_sieve/relational.c b/libmu_sieve/relational.c
index 7d18ea87e..81006b413 100644
--- a/libmu_sieve/relational.c
+++ b/libmu_sieve/relational.c
@@ -38,7 +38,8 @@ DCL(ge,>=)
DCL(lt,<)
DCL(le,<=)
-static struct reltest_tab {
+static struct reltest_tab
+{
char *name;
mu_sieve_relcmp_t test;
mu_sieve_relcmpn_t stest;
@@ -66,7 +67,7 @@ _relcmp_lookup (const char *str)
int
mu_sieve_str_to_relcmp (const char *str,
- mu_sieve_relcmp_t *test, mu_sieve_relcmpn_t *stest)
+ mu_sieve_relcmp_t *test, mu_sieve_relcmpn_t *stest)
{
struct reltest_tab *t = _relcmp_lookup (str);
if (t)
diff --git a/libmu_sieve/require.c b/libmu_sieve/require.c
index 2f76d050b..a04d6546d 100644
--- a/libmu_sieve/require.c
+++ b/libmu_sieve/require.c
@@ -27,30 +27,17 @@
#include <sieve-priv.h>
void
-mu_sieve_require (mu_sieve_machine_t mach, mu_list_t slist)
+mu_sieve_require (mu_sieve_machine_t mach, mu_sieve_slice_t list)
{
- int status;
- mu_iterator_t itr;
+ size_t i;
- status = mu_list_get_iterator (slist, &itr);
- if (status)
+ for (i = 0; i < list->count; i++)
{
- mu_diag_at_locus (MU_LOG_ERROR, &mach->locus,
- _("cannot create iterator: %s"),
- mu_strerror (status));
- mu_i_sv_error (mach);
- return;
- }
-
- for (mu_iterator_first (itr);
- !mu_iterator_is_done (itr); mu_iterator_next (itr))
- {
- char *name;
+ struct mu_sieve_string *str = mu_sieve_string_raw (mach, list, i);
+ char *name = str->orig;
int (*reqfn) (mu_sieve_machine_t mach, const char *name) = NULL;
const char *text = NULL;
- mu_iterator_current (itr, (void **)&name);
-
if (strncmp (name, "comparator-", 11) == 0)
{
name += 11;
@@ -87,6 +74,5 @@ mu_sieve_require (mu_sieve_machine_t mach, mu_list_t slist)
mu_i_sv_error (mach);
}
}
- mu_iterator_destroy (&itr);
}
diff --git a/libmu_sieve/runtime.c b/libmu_sieve/runtime.c
index 1c0e38b2e..fea9bf80e 100644
--- a/libmu_sieve/runtime.c
+++ b/libmu_sieve/runtime.c
@@ -24,8 +24,8 @@
#include <assert.h>
#include <sieve-priv.h>
-#define SIEVE_ARG(m,n,t) ((m)->prog[(m)->pc+(n)].t)
-#define SIEVE_ADJUST(m,n) (m)->pc+=(n)
+#define SIEVE_RT_ARG(m,n,t) ((m)->prog[(m)->pc+(n)].t)
+#define SIEVE_RT_ADJUST(m,n) (m)->pc+=(n)
#define INSTR_DISASS(m) ((m)->state == mu_sieve_state_disass)
#define INSTR_DEBUG(m) \
@@ -34,49 +34,53 @@
void
_mu_i_sv_instr_source (mu_sieve_machine_t mach)
{
- mach->locus.mu_file = (char*) SIEVE_ARG (mach, 0, string);
+ mach->locus.mu_file = (char*) SIEVE_RT_ARG (mach, 0, string);
mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_LOCUS,
&mach->locus);
if (INSTR_DEBUG (mach))
mu_i_sv_debug (mach, mach->pc - 1, "SOURCE %s", mach->locus.mu_file);
- SIEVE_ADJUST (mach, 1);
+ SIEVE_RT_ADJUST (mach, 1);
}
void
_mu_i_sv_instr_line (mu_sieve_machine_t mach)
{
- mach->locus.mu_line = SIEVE_ARG (mach, 0, line);
+ mach->locus.mu_line = SIEVE_RT_ARG (mach, 0, line);
mu_stream_ioctl (mach->errstream, MU_IOCTL_LOGSTREAM,
MU_IOCTL_LOGSTREAM_SET_LOCUS,
&mach->locus);
if (INSTR_DEBUG (mach))
mu_i_sv_debug (mach, mach->pc - 1, "LINE %u",
mach->locus.mu_line);
- SIEVE_ADJUST (mach, 1);
+ SIEVE_RT_ADJUST (mach, 1);
}
static int
instr_run (mu_sieve_machine_t mach, char const *what)
{
int rc = 0;
- mu_sieve_handler_t han = SIEVE_ARG (mach, 0, handler);
- mach->arg_list = SIEVE_ARG (mach, 1, list);
- mach->tag_list = SIEVE_ARG (mach, 2, list);
- mach->identifier = SIEVE_ARG (mach, 3, string);
-
- SIEVE_ADJUST (mach, 4);
+ mu_sieve_handler_t han = SIEVE_RT_ARG (mach, 0, handler);
+ mach->argstart = SIEVE_RT_ARG (mach, 1, pc);
+ mach->argcount = SIEVE_RT_ARG (mach, 2, pc);
+ mach->tagcount = SIEVE_RT_ARG (mach, 3, pc);
+ mach->identifier = SIEVE_RT_ARG (mach, 4, string);
+ mach->comparator = SIEVE_RT_ARG (mach, 5, comp);
+
+ SIEVE_RT_ADJUST (mach, 6);
if (INSTR_DEBUG (mach))
- mu_i_sv_debug_command (mach, mach->pc - 1, what);
+ mu_i_sv_debug_command (mach, mach->pc - 7, what);
else
mu_i_sv_trace (mach, what);
if (!INSTR_DISASS (mach))
rc = han (mach);
- mach->arg_list = NULL;
- mach->tag_list = NULL;
+ mach->argstart = 0;
+ mach->argcount = 0;
+ mach->tagcount = 0;
mach->identifier = NULL;
+ mach->comparator = NULL;
return rc;
}
@@ -138,9 +142,9 @@ _mu_i_sv_instr_not (mu_sieve_machine_t mach)
void
_mu_i_sv_instr_branch (mu_sieve_machine_t mach)
{
- long num = SIEVE_ARG (mach, 0, number);
+ long num = SIEVE_RT_ARG (mach, 0, number);
- SIEVE_ADJUST (mach, 1);
+ SIEVE_RT_ADJUST (mach, 1);
if (INSTR_DEBUG (mach))
mu_i_sv_debug (mach, mach->pc - 2, "BRANCH %lu",
(unsigned long)(mach->pc + num));
@@ -153,8 +157,8 @@ _mu_i_sv_instr_branch (mu_sieve_machine_t mach)
void
_mu_i_sv_instr_brz (mu_sieve_machine_t mach)
{
- long num = SIEVE_ARG (mach, 0, number);
- SIEVE_ADJUST (mach, 1);
+ long num = SIEVE_RT_ARG (mach, 0, number);
+ SIEVE_RT_ADJUST (mach, 1);
if (INSTR_DEBUG (mach))
mu_i_sv_debug (mach, mach->pc - 2, "BRZ %lu",
@@ -169,8 +173,8 @@ _mu_i_sv_instr_brz (mu_sieve_machine_t mach)
void
_mu_i_sv_instr_brnz (mu_sieve_machine_t mach)
{
- long num = SIEVE_ARG (mach, 0, number);
- SIEVE_ADJUST (mach, 1);
+ long num = SIEVE_RT_ARG (mach, 0, number);
+ SIEVE_RT_ADJUST (mach, 1);
if (INSTR_DEBUG (mach))
mu_i_sv_debug (mach, mach->pc - 2, "BRNZ %lu",
diff --git a/libmu_sieve/sieve-priv.h b/libmu_sieve/sieve-priv.h
index d7b389b07..7ae2fdf5a 100644
--- a/libmu_sieve/sieve-priv.h
+++ b/libmu_sieve/sieve-priv.h
@@ -19,8 +19,7 @@
#include <mailutils/sieve.h>
#include <setjmp.h>
#include <string.h>
-
-#define SIEVE_CODE_INCR 128
+#include <regex.h>
typedef void (*sieve_instr_t) (mu_sieve_machine_t mach);
@@ -29,6 +28,7 @@ typedef union
sieve_instr_t instr;
mu_sieve_handler_t handler;
mu_sieve_value_t *val;
+ mu_sieve_comparator_t comp;
mu_list_t list;
long number;
size_t pc;
@@ -37,7 +37,7 @@ typedef union
char *string;
unsigned unum;
} sieve_op_t;
-
+
struct mu_locus_range
{
struct mu_locus beg;
@@ -73,6 +73,14 @@ struct mu_sieve_machine
mu_list_t action_list; /* Actions */
mu_list_t comp_list; /* Comparators */
mu_list_t source_list; /* Source names (for diagnostics) */
+
+ mu_sieve_string_t *stringspace;
+ size_t stringcount;
+ size_t stringmax;
+
+ mu_sieve_value_t *valspace;
+ size_t valcount;
+ size_t valmax;
size_t progsize; /* Number of allocated program cells */
sieve_op_t *prog; /* Compiled program */
@@ -85,8 +93,10 @@ struct mu_sieve_machine
/* Call environment */
const char *identifier; /* Name of action or test being executed */
- mu_list_t arg_list; /* Positional arguments */
- mu_list_t tag_list; /* Tagged arguments */
+ size_t argstart; /* Index of the first argument in valspace */
+ size_t argcount; /* Number of positional arguments */
+ size_t tagcount; /* Number of tagged arguments */
+ mu_sieve_comparator_t comparator; /* Comparator (for tests) */
int dry_run; /* Dry-run mode */
jmp_buf errbuf; /* Target location for non-local exits */
@@ -146,7 +156,10 @@ struct mu_sieve_node
struct
{
mu_sieve_register_t *reg;
- mu_list_t arg;
+ size_t argstart;
+ size_t argcount;
+ size_t tagcount;
+ mu_sieve_comparator_t comparator; /* Comparator (for tests) */
} command;
} v;
};
@@ -161,18 +174,16 @@ void mu_i_sv_lex_finish (struct mu_sieve_machine *mach);
extern mu_sieve_machine_t mu_sieve_machine;
-#define TAG_COMPFUN "__compfun__"
-
-int mu_i_sv_code (struct mu_sieve_machine *mach, sieve_op_t op);
+void mu_i_sv_code (struct mu_sieve_machine *mach, sieve_op_t op);
void mu_i_sv_compile_error (struct mu_sieve_machine *mach,
const char *fmt, ...) MU_PRINTFLIKE(2,3);
int mu_i_sv_locus (struct mu_sieve_machine *mach, struct mu_locus_range *lr);
-int mu_i_sv_code_action (struct mu_sieve_machine *mach,
- mu_sieve_register_t *reg, mu_list_t arglist);
-int mu_i_sv_code_test (struct mu_sieve_machine *mach,
- mu_sieve_register_t *reg, mu_list_t arglist);
+void mu_i_sv_code_action (struct mu_sieve_machine *mach,
+ struct mu_sieve_node *node);
+void mu_i_sv_code_test (struct mu_sieve_machine *mach,
+ struct mu_sieve_node *node);
/* Opcodes */
void _mu_i_sv_instr_action (mu_sieve_machine_t mach);
@@ -203,8 +214,7 @@ void mu_i_sv_debug_command (mu_sieve_machine_t mach, size_t pc,
char const *what);
void mu_i_sv_trace (mu_sieve_machine_t mach, const char *what);
-void mu_i_sv_argf (mu_stream_t str, mu_list_t list);
-void mu_i_sv_valf (mu_stream_t str, mu_sieve_value_t *val);
+void mu_i_sv_valf (mu_sieve_machine_t mach, mu_stream_t str, mu_sieve_value_t *val);
typedef int (*mu_i_sv_interp_t) (char const *, size_t, char **, void *);
@@ -216,4 +226,15 @@ int mu_i_sv_expand_encoded_char (char const *input, size_t len, char **exp, void
int mu_sieve_require_encoded_character (mu_sieve_machine_t mach,
const char *name);
+void mu_i_sv_2nrealloc (mu_sieve_machine_t mach,
+ void **pptr, size_t *pnmemb, size_t size);
+
+
+mu_sieve_value_t *mu_i_sv_mach_arg (mu_sieve_machine_t mach, size_t n);
+mu_sieve_value_t *mu_i_sv_mach_tagn (mu_sieve_machine_t mach, size_t n);
+void mu_i_sv_lint_command (struct mu_sieve_machine *mach,
+ struct mu_sieve_node *node);
+
+
+size_t mu_i_sv_string_create (mu_sieve_machine_t mach, char *str);
diff --git a/libmu_sieve/sieve.y b/libmu_sieve/sieve.y
index b60d44fd4..a76b3de91 100644
--- a/libmu_sieve/sieve.y
+++ b/libmu_sieve/sieve.y
@@ -79,12 +79,13 @@ static void cond_join (struct mu_sieve_node *node);
%union {
char *string;
size_t number;
- mu_sieve_value_t *value;
- mu_list_t list;
+ size_t idx;
+ struct mu_sieve_slice slice;
struct
{
char *ident;
- mu_list_t args;
+ size_t first;
+ size_t count;
} command;
struct node_list
{
@@ -98,8 +99,8 @@ static void cond_join (struct mu_sieve_node *node);
%token <string> STRING MULTILINE
%token REQUIRE IF ELSIF ELSE ANYOF ALLOF NOT FALSE TRUE
-%type <value> arg
-%type <list> slist stringlist stringorlist arglist maybe_arglist
+%type <idx> arg
+%type <slice> arglist maybe_arglist slist stringlist stringorlist
%type <command> command
%type <node> action test statement block cond
%type <node> else_part
@@ -138,10 +139,10 @@ list : statement
statement : REQUIRE stringorlist ';'
{
- mu_sieve_require (mu_sieve_machine, $2);
- /* All the items in $2 are registered in memory_pool,
- so we don't free them */
- mu_list_destroy (&$2);
+ mu_sieve_require (mu_sieve_machine, &$2);
+ /* Reclaim string slots. The string data referred to by
+ $2 are registered in memory_pool, so we don't free them */
+ mu_sieve_machine->stringcount -= $2.count;
$$ = NULL;
}
| action ';'
@@ -265,7 +266,11 @@ test : command
$$ = node_alloc (mu_sieve_node_test, &@1);
$$->v.command.reg = reg;
- $$->v.command.arg = $1.args;
+ $$->v.command.argstart = $1.first;
+ $$->v.command.argcount = $1.count;
+ $$->v.command.tagcount = 0;
+ $$->v.command.comparator = NULL;
+ mu_i_sv_lint_command (mu_sieve_machine, $$);
}
| TRUE
{
@@ -280,7 +285,8 @@ test : command
command : IDENT maybe_arglist
{
$$.ident = $1;
- $$.args = $2;
+ $$.first = $2.first;
+ $$.count = $2.count;
}
;
@@ -308,25 +314,29 @@ action : command
$$ = node_alloc(mu_sieve_node_action, &@1);
$$->v.command.reg = reg;
- $$->v.command.arg = $1.args;
+ $$->v.command.argstart = $1.first;
+ $$->v.command.argcount = $1.count;
+ $$->v.command.tagcount = 0;
+ mu_i_sv_lint_command (mu_sieve_machine, $$);
}
;
maybe_arglist: /* empty */
{
- $$ = NULL;
+ $$.first = 0;
+ $$.count = 0;
}
| arglist
;
arglist : arg
{
- mu_list_create (&$$);
- mu_list_append ($$, $1);
+ $$.first = $1;
+ $$.count = 1;
}
| arglist arg
{
- mu_list_append ($1, $2);
+ $1.count++;
$$ = $1;
}
;
@@ -334,7 +344,7 @@ arglist : arg
arg : stringlist
{
$$ = mu_sieve_value_create (mu_sieve_machine,
- SVT_STRING_LIST, $1);
+ SVT_STRING_LIST, &$1);
}
| STRING
{
@@ -356,8 +366,8 @@ arg : stringlist
stringorlist : STRING
{
- mu_list_create (&$$);
- mu_list_append ($$, $1);
+ $$.first = mu_i_sv_string_create (mu_sieve_machine, $1);
+ $$.count = 1;
}
| stringlist
;
@@ -370,12 +380,13 @@ stringlist : '[' slist ']'
slist : STRING
{
- mu_list_create (&$$);
- mu_list_append ($$, $1);
+ $$.first = mu_i_sv_string_create (mu_sieve_machine, $1);
+ $$.count = 1;
}
| slist ',' STRING
{
- mu_list_append ($1, $3);
+ mu_i_sv_string_create (mu_sieve_machine, $3);
+ $1.count++;
$$ = $1;
}
;
@@ -396,7 +407,7 @@ yyerror (const char *s)
static void
cond_join (struct mu_sieve_node *node)
{
- while (node)
+ while (node && node->type == mu_sieve_node_cond)
{
struct mu_sieve_node *next = node->next;
node->prev = node->next = NULL;
@@ -422,16 +433,18 @@ static void node_optimize (struct mu_sieve_node *node);
static void node_free (struct mu_sieve_node *node);
static void node_replace (struct mu_sieve_node *node,
struct mu_sieve_node *repl);
-static int node_code (struct mu_sieve_machine *mach,
- struct mu_sieve_node *node);
+static void node_code (struct mu_sieve_machine *mach,
+ struct mu_sieve_node *node);
static void node_dump (mu_stream_t str, struct mu_sieve_node *node,
- unsigned level);
+ unsigned level, struct mu_sieve_machine *mach);
static void tree_free (struct mu_sieve_node **tree);
static void tree_optimize (struct mu_sieve_node *tree);
-static int tree_code (struct mu_sieve_machine *mach,
- struct mu_sieve_node *tree);
-static void tree_dump (mu_stream_t str, struct mu_sieve_node *tree, unsigned level);
+static void tree_code (struct mu_sieve_machine *mach,
+ struct mu_sieve_node *tree);
+static void tree_dump (mu_stream_t str,
+ struct mu_sieve_node *tree, unsigned level,
+ struct mu_sieve_machine *mach);
static void
indent (mu_stream_t str, unsigned level)
@@ -444,7 +457,8 @@ indent (mu_stream_t str, unsigned level)
/* mu_sieve_node_noop */
static void
-dump_node_noop (mu_stream_t str, struct mu_sieve_node *node, unsigned level)
+dump_node_noop (mu_stream_t str, struct mu_sieve_node *node, unsigned level,
+ struct mu_sieve_machine *mach)
{
indent (str, level);
mu_stream_printf (str, "NOOP\n");
@@ -452,7 +466,8 @@ dump_node_noop (mu_stream_t str, struct mu_sieve_node *node, unsigned level)
/* mu_sieve_node_false */
static void
-dump_node_false (mu_stream_t str, struct mu_sieve_node *node, unsigned level)
+dump_node_false (mu_stream_t str, struct mu_sieve_node *node, unsigned level,
+ struct mu_sieve_machine *mach)
{
indent (str, level);
mu_stream_printf (str, "FALSE\n");
@@ -460,7 +475,8 @@ dump_node_false (mu_stream_t str, struct mu_sieve_node *node, unsigned level)
/* mu_sieve_node_true */
static void
-dump_node_true (mu_stream_t str, struct mu_sieve_node *node, unsigned level)
+dump_node_true (mu_stream_t str, struct mu_sieve_node *node, unsigned level,
+ struct mu_sieve_machine *mach)
{
indent (str, level);
mu_stream_printf (str, "TRUE\n");
@@ -470,43 +486,32 @@ dump_node_true (mu_stream_t str, struct mu_sieve_node *node, unsigned level)
static void
free_node_command (struct mu_sieve_node *node)
{
- mu_list_destroy (&node->v.command.arg);
+ /* nothing */
}
-static int
+static void
code_node_test (struct mu_sieve_machine *mach, struct mu_sieve_node *node)
{
- return mu_i_sv_code_test (mach, node->v.command.reg, node->v.command.arg);
+ mu_i_sv_code_test (mach, node);
}
-static int
+static void
code_node_action (struct mu_sieve_machine *mach, struct mu_sieve_node *node)
{
- return mu_i_sv_code_action (mach, node->v.command.reg, node->v.command.arg);
-}
-
-struct string_dumper_data
-{
- int init;
- mu_stream_t stream;
-};
-
-static int
-string_dumper (void *item, void *data)
-{
- struct string_dumper_data *dp = data;
- if (dp->init == 0)
- dp->init = 1;
- else
- mu_stream_printf (dp->stream, ", ");
- mu_stream_printf (dp->stream, "\"%s\"", (char*)item);
- return 0;
+ mu_i_sv_code_action (mach, node);
}
void
-mu_i_sv_valf (mu_stream_t str, mu_sieve_value_t *val)
+mu_i_sv_valf (mu_sieve_machine_t mach, mu_stream_t str, mu_sieve_value_t *val)
{
mu_stream_printf (str, " ");
+ if (val->tag)
+ {
+ mu_stream_printf (str, ":%s", val->tag);
+ if (val->type == SVT_VOID)
+ return;
+ mu_stream_printf (str, " ");
+ }
switch (val->type)
{
case SVT_VOID:
@@ -518,16 +523,22 @@ mu_i_sv_valf (mu_stream_t str, mu_sieve_value_t *val)
break;
case SVT_STRING:
- mu_stream_printf (str, "\"%s\"", val->v.string);
+ mu_stream_printf (str, "\"%s\"",
+ mu_sieve_string_raw (mach, &val->v.list, 0)->orig);
break;
case SVT_STRING_LIST:
{
- struct string_dumper_data d;
- d.init = 0;
- d.stream = str;
+ size_t i;
+
mu_stream_printf (str, "[");
- mu_list_foreach (val->v.list, string_dumper, &d);
+ for (i = 0; i < val->v.list.count; i++)
+ {
+ if (i)
+ mu_stream_printf (str, ", ");
+ mu_stream_printf (str, "\"%s\"",
+ mu_sieve_string_raw (mach, &val->v.list, i)->orig);
+ }
mu_stream_printf (str, "]");
}
break;
@@ -540,36 +551,21 @@ mu_i_sv_valf (mu_stream_t str, mu_sieve_value_t *val)
mu_stream_printf (str, "%s", val->v.string);
break;
- case SVT_POINTER:
- mu_stream_printf (str, "%p", val->v.ptr);
- break;
-
default:
abort ();
}
}
-static int
-dump_val (void *item, void *data)
-{
- mu_sieve_value_t *val = item;
- mu_stream_t str = data;
- mu_i_sv_valf (str, val);
- return 0;
-}
-
-void
-mu_i_sv_argf (mu_stream_t str, mu_list_t list)
-{
- mu_list_foreach (list, dump_val, str);
-}
-
static void
-dump_node_command (mu_stream_t str, struct mu_sieve_node *node, unsigned level)
+dump_node_command (mu_stream_t str, struct mu_sieve_node *node, unsigned level,
+ struct mu_sieve_machine *mach)
{
+ size_t i;
+
indent (str, level);
mu_stream_printf (str, "COMMAND %s", node->v.command.reg->name);
- mu_list_foreach (node->v.command.arg, dump_val, str);
+ for (i = 0; i < node->v.command.argcount + node->v.command.tagcount; i++)
+ mu_i_sv_valf (mach, str, &mach->valspace[node->v.command.argstart + i]);
mu_stream_printf (str, "\n");
}
@@ -604,7 +600,7 @@ optimize_node_cond (struct mu_sieve_node *node)
}
}
-static int
+static void
code_node_cond (struct mu_sieve_machine *mach, struct mu_sieve_node *node)
{
size_t br1;
@@ -630,11 +626,11 @@ code_node_cond (struct mu_sieve_machine *mach, struct mu_sieve_node *node)
}
else
mach->prog[br1].pc = mach->pc - br1 - 1;
- return 0;
}
static void
-dump_node_cond (mu_stream_t str, struct mu_sieve_node *node, unsigned level)
+dump_node_cond (mu_stream_t str, struct mu_sieve_node *node, unsigned level,
+ struct mu_sieve_machine *mach)
{
indent (str, level);
mu_stream_printf (str, "COND\n");
@@ -643,15 +639,15 @@ dump_node_cond (mu_stream_t str, struct mu_sieve_node *node, unsigned level)
indent (str, level);
mu_stream_printf (str, "EXPR:\n");
- tree_dump (str, node->v.cond.expr, level + 1);
+ tree_dump (str, node->v.cond.expr, level + 1, mach);
indent (str, level);
mu_stream_printf (str, "IFTRUE:\n");
- tree_dump (str, node->v.cond.iftrue, level + 1);
+ tree_dump (str, node->v.cond.iftrue, level + 1, mach);
indent (str, level);
mu_stream_printf (str, "IFFALSE:\n");
- tree_dump (str, node->v.cond.iffalse, level + 1);
+ tree_dump (str, node->v.cond.iffalse, level + 1, mach);
}
/* mu_sieve_node_anyof & mu_sieve_node_allof */
@@ -703,7 +699,7 @@ optimize_x_of (struct mu_sieve_node *node, enum mu_sieve_node_type solve)
node->type = solve == mu_sieve_node_false ? mu_sieve_node_true : mu_sieve_node_false;
}
-static int
+static void
code_node_x_of (struct mu_sieve_machine *mach, struct mu_sieve_node *node,
sieve_op_t op)
{
@@ -731,12 +727,11 @@ code_node_x_of (struct mu_sieve_machine *mach, struct mu_sieve_node *node,
mach->prog[pc].pc = end - pc - 1;
pc = prev;
}
-
- return 0;
}
static void
-dump_node_x_of (mu_stream_t str, struct mu_sieve_node *node, unsigned level)
+dump_node_x_of (mu_stream_t str, struct mu_sieve_node *node, unsigned level,
+ mu_sieve_machine_t mach)
{
indent (str, level);
mu_stream_printf (str, "%s:\n",
@@ -746,7 +741,7 @@ dump_node_x_of (mu_stream_t str, struct mu_sieve_node *node, unsigned level)
node = node->v.node;
while (node)
{
- node_dump (str, node, level + 1);
+ node_dump (str, node, level + 1, mach);
node = node->next;
if (node)
{
@@ -764,10 +759,10 @@ optimize_node_anyof (struct mu_sieve_node *node)
optimize_x_of (node, mu_sieve_node_true);
}
-static int
+static void
code_node_anyof (struct mu_sieve_machine *mach, struct mu_sieve_node *node)
{
- return code_node_x_of (mach, node, (sieve_op_t) _mu_i_sv_instr_brnz);
+ code_node_x_of (mach, node, (sieve_op_t) _mu_i_sv_instr_brnz);
}
/* mu_sieve_node_allof */
@@ -777,10 +772,10 @@ optimize_node_allof (struct mu_sieve_node *node)
return optimize_x_of (node, mu_sieve_node_false);
}
-static int
+static void
code_node_allof (struct mu_sieve_machine *mach, struct mu_sieve_node *node)
{
- return code_node_x_of (mach, node, (sieve_op_t) _mu_i_sv_instr_brz);
+ code_node_x_of (mach, node, (sieve_op_t) _mu_i_sv_instr_brz);
}
/* mu_sieve_node_not */
@@ -811,27 +806,29 @@ optimize_node_not (struct mu_sieve_node *node)
}
}
-static int
+static void
code_node_not (struct mu_sieve_machine *mach, struct mu_sieve_node *node)
{
node_code (mach, node->v.node);
- return mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_not);
+ mu_i_sv_code (mach, (sieve_op_t) _mu_i_sv_instr_not);
}
static void
-dump_node_not (mu_stream_t str, struct mu_sieve_node *node, unsigned level)
+dump_node_not (mu_stream_t str, struct mu_sieve_node *node, unsigned level,
+ struct mu_sieve_machine *mach)
{
indent (str, level);
mu_stream_printf (str, "NOT\n");
- node_dump (str, node->v.node, level + 1);
+ node_dump (str, node->v.node, level + 1, mach);
}
struct node_descr
{
- int (*code_fn) (struct mu_sieve_machine *mach, struct mu_sieve_node *node);
+ void (*code_fn) (struct mu_sieve_machine *mach, struct mu_sieve_node *node);
void (*optimize_fn) (struct mu_sieve_node *node);
void (*free_fn) (struct mu_sieve_node *node);
- void (*dump_fn) (mu_stream_t str, struct mu_sieve_node *node, unsigned level);
+ void (*dump_fn) (mu_stream_t str, struct mu_sieve_node *node, unsigned level,
+ mu_sieve_machine_t);
};
@@ -913,28 +910,27 @@ node_replace (struct mu_sieve_node *node, struct mu_sieve_node *repl)
node_descr[node->type].free_fn (&copy);
}
-static int
+static void
node_code (struct mu_sieve_machine *mach, struct mu_sieve_node *node)
{
if ((int)node->type >= MU_ARRAY_SIZE (node_descr))
abort ();
- if (!node_descr[node->type].code_fn)
- return 0;
-
- if (mu_i_sv_locus (mach, &node->locus))
- return 1;
-
- return node_descr[node->type].code_fn (mach, node);
+ if (node_descr[node->type].code_fn)
+ {
+ mu_i_sv_locus (mach, &node->locus);
+ node_descr[node->type].code_fn (mach, node);
+ }
}
static void
-node_dump (mu_stream_t str, struct mu_sieve_node *node, unsigned level)
+node_dump (mu_stream_t str, struct mu_sieve_node *node, unsigned level,
+ struct mu_sieve_machine *mach)
{
if ((int)node->type >= MU_ARRAY_SIZE (node_descr)
|| !node_descr[node->type].dump_fn)
abort ();
- node_descr[node->type].dump_fn (str, node, level);
+ node_descr[node->type].dump_fn (str, node, level, mach);
}
@@ -960,24 +956,23 @@ tree_optimize (struct mu_sieve_node *tree)
}
}
-static int
+static void
tree_code (struct mu_sieve_machine *mach, struct mu_sieve_node *tree)
{
while (tree)
{
- if (node_code (mach, tree))
- return 1;
+ node_code (mach, tree);
tree = tree->next;
}
- return 0;
}
static void
-tree_dump (mu_stream_t str, struct mu_sieve_node *tree, unsigned level)
+tree_dump (mu_stream_t str, struct mu_sieve_node *tree, unsigned level,
+ struct mu_sieve_machine *mach)
{
while (tree)
{
- node_dump (str, tree, level);
+ node_dump (str, tree, level, mach);
tree = tree->next;
}
}
@@ -1251,7 +1246,21 @@ void
mu_sieve_machine_destroy (mu_sieve_machine_t *pmach)
{
mu_sieve_machine_t mach = *pmach;
-
+ size_t i;
+
+ for (i = 0; i < mach->stringcount; i++)
+ {
+ if (mach->stringspace[i].rx)
+ {
+ regex_t *rx = mach->stringspace[i].rx;
+ regfree (rx);
+ }
+ /* FIXME: Is it needed?
+ if (mach->stringspace[i].exp)
+ free (mach->stringspace[i].exp);
+ */
+ }
+
mu_stream_destroy (&mach->errstream);
mu_stream_destroy (&mach->dbgstream);
mu_mailer_destroy (&mach->mailer);
@@ -1320,13 +1329,13 @@ sieve_parse (void)
if (mu_debug_level_p (mu_sieve_debug_handle, MU_DEBUG_TRACE1))
{
mu_error (_("Unoptimized parse tree"));
- tree_dump (mu_strerr, sieve_tree, 0);
+ tree_dump (mu_strerr, sieve_tree, 0, mu_sieve_machine);
}
tree_optimize (sieve_tree);
if (mu_debug_level_p (mu_sieve_debug_handle, MU_DEBUG_TRACE2))
{
mu_error (_("Optimized parse tree"));
- tree_dump (mu_strerr, sieve_tree, 0);
+ tree_dump (mu_strerr, sieve_tree, 0, mu_sieve_machine);
}
mu_i_sv_code (mu_sieve_machine, (sieve_op_t) 0);
@@ -1335,9 +1344,7 @@ sieve_parse (void)
mu_sieve_machine->locus.mu_line = 0;
mu_sieve_machine->locus.mu_col = 0;
- rc = tree_code (mu_sieve_machine, sieve_tree);
- if (rc)
- mu_i_sv_error (mu_sieve_machine);
+ tree_code (mu_sieve_machine, sieve_tree);
mu_i_sv_code (mu_sieve_machine, (sieve_op_t) 0);
}
diff --git a/libmu_sieve/string.c b/libmu_sieve/string.c
new file mode 100644
index 000000000..254f3ad92
--- /dev/null
+++ b/libmu_sieve/string.c
@@ -0,0 +1,61 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2002, 2005-2008, 2010-2012, 2014-2016 Free
+ Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <sieve-priv.h>
+
+size_t
+mu_i_sv_string_create (mu_sieve_machine_t mach, char *str)
+{
+ size_t n;
+ mu_sieve_string_t *s;
+
+ if (mach->stringcount == mach->stringmax)
+ {
+ mu_i_sv_2nrealloc (mach, (void**) &mach->stringspace,
+ &mach->stringmax,
+ sizeof mach->stringspace[0]);
+ }
+
+ n = mach->stringcount++;
+ s = &mach->stringspace[n];
+ memset (s, 0, sizeof *s);
+ s->orig = str;
+
+ return n;
+}
+
+struct mu_sieve_string *
+mu_sieve_string_raw (mu_sieve_machine_t mach, mu_sieve_slice_t slice,
+ size_t i)
+{
+ if (i >= slice->count)
+ abort ();
+ return mach->stringspace + slice->first + i;
+}
+
+char *
+mu_sieve_string (mu_sieve_machine_t mach, mu_sieve_slice_t slice,
+ size_t i)
+{
+ return mu_sieve_string_raw (mach, slice, i)->orig;
+}
diff --git a/libmu_sieve/tests.c b/libmu_sieve/tests.c
index 0713373e3..10c482516 100644
--- a/libmu_sieve/tests.c
+++ b/libmu_sieve/tests.c
@@ -27,32 +27,24 @@
typedef int (*address_aget_t) (mu_address_t addr, size_t no, char **buf);
-static int
-_get_address_part (void *item, void *data)
-{
- mu_sieve_runtime_tag_t *t = item;
- address_aget_t ret = NULL;
-
- if (strcmp (t->tag, "all") == 0)
- ret = mu_address_aget_email;
- else if (strcmp (t->tag, "domain") == 0)
- ret = mu_address_aget_domain;
- else if (strcmp (t->tag, "localpart") == 0)
- ret = mu_address_aget_local_part;
- if (ret)
- {
- *(address_aget_t*)data = ret;
- return 1; /* break the loop */
- }
- return 0; /* continue */
-}
-
address_aget_t
-sieve_get_address_part (mu_list_t tags)
+sieve_get_address_part (mu_sieve_machine_t mach)
{
- address_aget_t ret = mu_address_aget_email;
- mu_list_foreach (tags, _get_address_part, &ret);
- return ret;
+ size_t i;
+
+ for (i = 0; i < mach->tagcount; i++)
+ {
+ mu_sieve_value_t *t = mu_sieve_get_tag_n (mach, i);
+ if (strcmp (t->tag, "all") == 0)
+ return mu_address_aget_email;
+ else if (strcmp (t->tag, "domain") == 0)
+ return mu_address_aget_domain;
+ else if (strcmp (t->tag, "localpart") == 0)
+ return mu_address_aget_local_part;
+ }
+ /* RFC 3028, 2.7.4. Comparisons Against Addresses:
+ If an optional address-part is omitted, the default is ":all". */
+ return mu_address_aget_email;
}
/* Structure shared between address and envelope tests */
@@ -72,11 +64,11 @@ do_count (mu_sieve_machine_t mach, size_t count, int retval)
{
size_t limit;
char *str;
- mu_list_t list;
+ struct mu_sieve_slice slice;
mu_sieve_relcmpn_t stest;
- mu_sieve_get_arg (mach, 1, SVT_STRING_LIST, &list);
- mu_list_get (list, 0, (void **) &str);
+ mu_sieve_get_arg (mach, 1, SVT_STRING_LIST, &slice);
+ str = mu_sieve_string (mach, &slice, 0);
limit = strtoul (str, &str, 10);
mu_sieve_str_to_relcmp (relcmp, NULL, &stest);
@@ -117,16 +109,16 @@ sieve_test_address (mu_sieve_machine_t mach)
mu_sieve_relcmp_t test = mu_sieve_get_relcmp (mach);
struct address_closure clos;
int rc;
- size_t count;
+ size_t count = 0;
h = mu_sieve_get_arg_untyped (mach, 0);
v = mu_sieve_get_arg_untyped (mach, 1);
mu_message_get_header (mu_sieve_get_message (mach), &header);
clos.data = header;
- clos.aget = sieve_get_address_part (mach->tag_list);
+ clos.aget = sieve_get_address_part (mach);
clos.addr = NULL;
- rc = mu_sieve_vlist_compare (h, v, comp, test, retrieve_address, &clos,
+ rc = mu_sieve_vlist_compare (mach, h, v, comp, test, retrieve_address, &clos,
&count);
mu_address_destroy (&clos.addr);
@@ -169,7 +161,7 @@ sieve_test_header (mu_sieve_machine_t mach)
mu_sieve_value_t *h, *v;
mu_sieve_comparator_t comp = mu_sieve_get_comparator (mach);
mu_sieve_relcmp_t test = mu_sieve_get_relcmp (mach);
- size_t count, mcount = 0;
+ size_t count = 0, mcount = 0;
struct header_closure clos;
h = mu_sieve_get_arg_untyped (mach, 0);
@@ -192,7 +184,7 @@ sieve_test_header (mu_sieve_machine_t mach)
if (mu_message_get_part (mach->msg, i, &message) == 0)
{
mu_message_get_header (message, &clos.header);
- if (mu_sieve_vlist_compare (h, v, comp, test,
+ if (mu_sieve_vlist_compare (mach, h, v, comp, test,
retrieve_header, &clos, &mcount))
return 1;
}
@@ -200,7 +192,7 @@ sieve_test_header (mu_sieve_machine_t mach)
}
}
mu_message_get_header (mach->msg, &clos.header);
- if (mu_sieve_vlist_compare (h, v, comp, test, retrieve_header, &clos,
+ if (mu_sieve_vlist_compare (mach, h, v, comp, test, retrieve_header, &clos,
&count))
return 1;
@@ -242,16 +234,16 @@ sieve_test_envelope (mu_sieve_machine_t mach)
mu_sieve_relcmp_t test = mu_sieve_get_relcmp (mach);
struct address_closure clos;
int rc;
- size_t count;
+ size_t count = 0;
h = mu_sieve_get_arg_untyped (mach, 0);
v = mu_sieve_get_arg_untyped (mach, 1);
mu_message_get_envelope (mu_sieve_get_message (mach),
(mu_envelope_t*)&clos.data);
- clos.aget = sieve_get_address_part (mach->tag_list);
+ clos.aget = sieve_get_address_part (mach);
clos.addr = NULL;
- rc = mu_sieve_vlist_compare (h, v, comp, test, retrieve_envelope, &clos,
+ rc = mu_sieve_vlist_compare (mach, h, v, comp, test, retrieve_envelope, &clos,
&count);
mu_address_destroy (&clos.addr);
return do_count (mach, count, rc);
@@ -261,19 +253,23 @@ int
sieve_test_size (mu_sieve_machine_t mach)
{
int rc = 1;
- mu_sieve_runtime_tag_t *tag = NULL;
size_t size;
size_t arg;
mu_sieve_get_arg (mach, 0, SVT_NUMBER, &arg);
mu_message_size (mu_sieve_get_message (mach), &size);
- mu_list_get (mach->tag_list, 0, (void **)&tag);
- if (!tag)
+ if (mach->tagcount)
+ {
+ mu_sieve_value_t *tag = mu_sieve_get_tag_n (mach, 0);
+ if (strcmp (tag->tag, "over") == 0)
+ rc = size > arg;
+ else if (strcmp (tag->tag, "under") == 0)
+ rc = size < arg;
+ else
+ abort ();
+ }
+ else
rc = size == arg;
- else if (strcmp (tag->tag, "over") == 0)
- rc = size > arg;
- else if (strcmp (tag->tag, "under") == 0)
- rc = size < arg;
return rc;
}
@@ -295,7 +291,7 @@ sieve_test_exists (mu_sieve_machine_t mach)
mu_message_get_header (mu_sieve_get_message (mach), &header);
val = mu_sieve_get_arg_untyped (mach, 0);
- return mu_sieve_vlist_do (val, _test_exists, header) == 0;
+ return mu_sieve_vlist_do (mach, val, _test_exists, header) == 0;
}
static mu_sieve_tag_def_t address_part_tags[] = {
diff --git a/libmu_sieve/util.c b/libmu_sieve/util.c
index 3df7a2d89..9e46bda95 100644
--- a/libmu_sieve/util.c
+++ b/libmu_sieve/util.c
@@ -26,29 +26,22 @@
#include <sieve-priv.h>
-static int
-_destroy_item (void *item, void *data)
-{
- free (item);
- return 0;
-}
-/* FIXME: Not needed? */
-void
-mu_sieve_slist_destroy (mu_list_t *plist)
-{
- if (!plist)
- return;
- mu_list_foreach (*plist, _destroy_item, NULL);
- mu_list_destroy (plist);
-}
-
-mu_sieve_value_t *
+size_t
mu_sieve_value_create (mu_sieve_machine_t mach, mu_sieve_data_type type,
void *data)
{
- mu_sieve_value_t *val = mu_sieve_alloc_memory (mach, sizeof (*val),
- mu_sieve_reclaim_value);
-
+ size_t idx;
+ mu_sieve_value_t *val;
+
+ if (mach->valcount == mach->valmax)
+ {
+ mu_i_sv_2nrealloc (mach, (void**) &mach->valspace, &mach->valmax,
+ sizeof mach->valspace[0]);
+ }
+ idx = mach->valcount++;
+ val = &mach->valspace[idx];
+ memset (val, 0, sizeof *val);
+
val->type = type;
switch (type)
{
@@ -57,11 +50,12 @@ mu_sieve_value_create (mu_sieve_machine_t mach, mu_sieve_data_type type,
break;
case SVT_STRING:
- val->v.string = data;
+ val->v.list.first = mu_i_sv_string_create (mach, (char *)data);
+ val->v.list.count = 1;
break;
case SVT_STRING_LIST:
- val->v.list = data;
+ val->v.list = *(mu_sieve_slice_t)data;
break;
case SVT_TAG:
@@ -69,66 +63,140 @@ mu_sieve_value_create (mu_sieve_machine_t mach, mu_sieve_data_type type,
val->v.string = data;
break;
- case SVT_POINTER:
- val->v.ptr = data;
- break;
-
default:
mu_error ("%s", _("invalid data type"));
abort ();
}
- return val;
+ return idx;
}
mu_sieve_value_t *
mu_sieve_get_arg_untyped (mu_sieve_machine_t mach, size_t index)
{
- mu_sieve_value_t *val = NULL;
- int rc = mu_list_get (mach->arg_list, index, (void **)&val);
- if (rc)
+ if (index >= mach->argcount)
{
- mu_sieve_error (mach, _("can't get argument %zu: %s"),
- index, mu_strerror (rc));
- mu_sieve_abort (mach);
+ mu_sieve_error (mach, _("INTERNAL ERROR: %s,%zu,%zu,%zu argument index %zu out of range"),
+ mach->identifier,
+ mach->argstart,
+ mach->argcount,
+ mach->tagcount,
+ index);
+ abort ();
+ //FIXME mu_sieve_abort (mach);
}
- return val;
+
+ return mach->valspace + mach->argstart + index;
}
mu_sieve_value_t *
mu_sieve_get_arg_optional (mu_sieve_machine_t mach, size_t index)
{
- mu_sieve_value_t *val = NULL;
- int rc = mu_list_get (mach->arg_list, index, (void **)&val);
- if (rc == MU_ERR_NOENT)
+ if (index >= mach->argcount)
return NULL;
- else if (rc)
+ return mach->valspace + mach->argstart + index;
+}
+
+void
+mu_sieve_value_get (mu_sieve_machine_t mach, mu_sieve_value_t *val,
+ mu_sieve_data_type type, void *ret)
+{
+ if (val->type != type)
{
- mu_sieve_error (mach, _("can't get argument %zu: %s"),
- index, mu_strerror (rc));
+ if (val->tag)
+ mu_sieve_error (mach,
+ _("tag :%s has type %s, instead of expected %s"),
+ val->tag,
+ mu_sieve_type_str (val->type),
+ mu_sieve_type_str (type));
+ else
+ {
+ size_t idx = val - mu_sieve_get_arg_untyped (mach, 0);
+ if (idx < mach->argcount)
+ mu_sieve_error (mach,
+ _("argument %zu has type %s, instead of expected %s"),
+ idx,
+ mu_sieve_type_str (val->type),
+ mu_sieve_type_str (type));
+ else
+ abort ();
+ }
mu_sieve_abort (mach);
}
- return val;
-}
-int
+ switch (type)
+ {
+ case SVT_VOID:
+ *(void**) ret = NULL;
+ break;
+
+ case SVT_NUMBER:
+ *(size_t*) ret = val->v.number;
+ break;
+
+ case SVT_STRING:
+ *(char**) ret = mu_sieve_string (mach, &val->v.list, 0);
+ break;
+
+ case SVT_STRING_LIST:
+ *(struct mu_sieve_slice *) ret = val->v.list;
+ break;
+
+ case SVT_TAG:
+ case SVT_IDENT:
+ *(char**) ret = val->v.string;
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+void
mu_sieve_get_arg (mu_sieve_machine_t mach, size_t index,
mu_sieve_data_type type, void *ret)
{
- mu_sieve_value_t *val = mu_sieve_get_arg_untyped (mach, index);
- if (val->type != type)
+ mu_sieve_value_get (mach, mu_sieve_get_arg_untyped (mach, index),
+ type, ret);
+}
+
+mu_sieve_value_t *
+mu_sieve_get_tag_untyped (mu_sieve_machine_t mach, char const *name)
+{
+ size_t i;
+ mu_sieve_value_t *tag = mach->valspace + mach->argstart + mach->argcount;
+
+ for (i = 0; i < mach->tagcount; i++)
{
- mu_sieve_error (mach,
- _("bad type for argument %zu: %s, instead of expected %s"),
- index,
- mu_sieve_type_str (val->type),
- mu_sieve_type_str (type));
- mu_sieve_abort (mach);
+ if (strcmp (tag[i].tag, name) == 0)
+ return &tag[i];
}
+ return NULL;
+}
- *(union mu_sieve_value_storage *)ret = val->v;
- return 0;
+mu_sieve_value_t *
+mu_sieve_get_tag_n (mu_sieve_machine_t mach, size_t n)
+{
+ if (n >= mach->tagcount)
+ abort ();
+ return &mach->valspace[mach->argstart + mach->argcount + n];
}
+int
+mu_sieve_get_tag (mu_sieve_machine_t mach,
+ char *name, mu_sieve_data_type type,
+ void *ret)
+{
+ mu_sieve_value_t *val = mu_sieve_get_tag_untyped (mach, name);
+
+ if (val)
+ {
+ if (ret)
+ mu_sieve_value_get (mach, val, type, ret);
+ }
+
+ return val != NULL;
+}
+
void
mu_sieve_error (mu_sieve_machine_t mach, const char *fmt, ...)
{
@@ -172,31 +240,11 @@ mu_sieve_type_str (mu_sieve_data_type type)
case SVT_IDENT:
return "ident";
- case SVT_POINTER:
- return "pointer";
}
return "unknown";
}
-static int
-tag_printer (void *item, void *data)
-{
- mu_sieve_runtime_tag_t *val = item;
- mu_stream_t str = data;
-
- mu_stream_printf (str, " :%s", val->tag);
- if (val->arg)
- mu_i_sv_valf (str, val->arg);
- return 0;
-}
-
-void
-mu_i_sv_tagf (mu_stream_t str, mu_list_t taglist)
-{
- mu_list_foreach (taglist, tag_printer, str);
-}
-
void
mu_i_sv_debug (mu_sieve_machine_t mach, size_t pc, const char *fmt, ...)
{
@@ -228,6 +276,8 @@ mu_i_sv_debug_command (mu_sieve_machine_t mach,
size_t pc,
char const *what)
{
+ size_t i;
+
if (mach->state_flags & MU_SV_SAVED_DBG_STATE)
{
unsigned severity = MU_LOG_DEBUG;
@@ -243,15 +293,20 @@ mu_i_sv_debug_command (mu_sieve_machine_t mach,
}
}
mu_stream_printf (mach->dbgstream, "%4zu: %s: %s",
- pc, what, mach->identifier);
- mu_i_sv_tagf (mach->dbgstream, mach->tag_list);
- mu_i_sv_argf (mach->dbgstream, mach->arg_list);
+ pc, what, mach->identifier);
+ for (i = 0; i < mach->argcount; i++)
+ mu_i_sv_valf (mach, mach->dbgstream, &mach->valspace[mach->argstart + i]);
+ for (i = 0; i < mach->tagcount; i++)
+ mu_i_sv_valf (mach, mach->dbgstream, mu_sieve_get_tag_n (mach, i));
+
mu_stream_write (mach->dbgstream, "\n", 1, NULL);
}
void
mu_i_sv_trace (mu_sieve_machine_t mach, const char *what)
{
+ size_t i;
+
if (!mu_debug_level_p (mu_sieve_debug_handle, MU_DEBUG_TRACE4))
return;
@@ -264,8 +319,10 @@ mu_i_sv_trace (mu_sieve_machine_t mach, const char *what)
mach->locus.mu_line);
mu_stream_printf (mach->errstream, "%zu: %s %s", mach->msgno, what,
mach->identifier);
- mu_i_sv_tagf (mach->errstream, mach->tag_list);
- mu_i_sv_argf (mach->errstream, mach->arg_list);
+ for (i = 0; i < mach->argcount; i++)
+ mu_i_sv_valf (mach, mach->errstream, mu_sieve_get_arg_untyped (mach, i));
+ for (i = 0; i < mach->tagcount; i++)
+ mu_i_sv_valf (mach, mach->errstream, mu_sieve_get_tag_n (mach, i));
mu_stream_printf (mach->errstream, "\n");
}
@@ -284,146 +341,74 @@ mu_sieve_log_action (mu_sieve_machine_t mach, const char *action,
mach->logger (mach, action, fmt, ap);
va_end (ap);
}
-
-static int
-tag_finder (void *item, void *data)
-{
- mu_sieve_runtime_tag_t *val = item;
- mu_sieve_runtime_tag_t *target = data;
-
- if (strcmp (val->tag, target->tag) == 0)
- {
- target->arg = val->arg;
- return 1;
- }
- return 0;
-}
-
-int
-mu_sieve_get_tag_untyped (mu_sieve_machine_t mach,
- char *name, mu_sieve_value_t **ret)
-{
- mu_sieve_runtime_tag_t t;
-
- t.tag = name;
- if (mach->tag_list && mu_list_foreach (mach->tag_list, tag_finder, &t))
- {
- if (ret)
- *ret = t.arg;
- return 1;
- }
- return 0;
-}
-
-int
-mu_sieve_get_tag (mu_sieve_machine_t mach,
- char *name, mu_sieve_data_type type,
- void *ret)
-{
- mu_sieve_value_t *val;
- int found = mu_sieve_get_tag_untyped (mach, name, &val);
-
- if (found)
- {
- if (ret)
- {
- if (val->type != type)
- {
- mu_sieve_error (mach,
- _("bad type for tag %s: %s, instead of expected %s"),
- name,
- mu_sieve_type_str (val->type),
- mu_sieve_type_str (type));
- mu_sieve_abort (mach);
- }
- *(union mu_sieve_value_storage *)ret = val->v;
- }
- }
-
- return found;
-}
-
+
int
-mu_sieve_vlist_do (mu_sieve_value_t *val, mu_list_action_t ac, void *data)
+mu_sieve_vlist_do (mu_sieve_machine_t mach, mu_sieve_value_t *val,
+ mu_list_action_t ac, void *data)
{
+ size_t i;
switch (val->type)
{
case SVT_STRING_LIST:
- return mu_list_foreach (val->v.list, ac, data);
case SVT_STRING:
- return ac (val->v.string, data);
+ for (i = 0; i < val->v.list.count; i++)
+ {
+ int rc = ac (mu_sieve_string (mach, &val->v.list, i), data);
+ if (rc)
+ return rc;
+ }
+ return 0;
default:
mu_error ("mu_sieve_vlist_do: unexpected list type %d", val->type);
return EINVAL;
}
}
-struct comp_data
-{
- mu_sieve_value_t *val;
- mu_sieve_comparator_t comp;
- mu_sieve_relcmp_t test;
- mu_sieve_retrieve_t retr;
- void *data;
- size_t count;
-};
-
-struct comp_data2
-{
- char *sample;
- mu_sieve_comparator_t comp;
- mu_sieve_relcmp_t test;
-};
-
-int
-_comp_action2 (void *item, void *data)
-{
- struct comp_data2 *cp = data;
- return cp->test (cp->comp (item, cp->sample), 0);
-}
-
int
-_comp_action (void *item, void *data)
-{
- struct comp_data *cp = data;
- struct comp_data2 d;
- int rc = 0;
- int i;
-
- d.comp = cp->comp;
- d.test = cp->test;
- for (i = 0; rc == 0 && cp->retr (item, cp->data, i, &d.sample) == 0; i++)
- if (d.sample)
- {
- cp->count++;
- rc = mu_sieve_vlist_do (cp->val, _comp_action2, &d);
- free (d.sample);
- }
- return rc;
-}
-
-int
-mu_sieve_vlist_compare (mu_sieve_value_t *a, mu_sieve_value_t *b,
+mu_sieve_vlist_compare (mu_sieve_machine_t mach,
+ mu_sieve_value_t *a, mu_sieve_value_t *b,
mu_sieve_comparator_t comp, mu_sieve_relcmp_t test,
mu_sieve_retrieve_t retr,
void *data, size_t *count)
{
- struct comp_data d;
- int rc;
+ int rc = 0;
+ size_t i;
+
+ switch (a->type)
+ {
+ case SVT_STRING_LIST:
+ case SVT_STRING:
+ for (i = 0; i < a->v.list.count; i++)
+ {
+ char *item = mu_sieve_string (mach, &a->v.list, i);
+ char *sample;
+ size_t j, k;
- d.comp = comp;
- d.test = test;
- d.retr = retr;
- d.data = data;
- d.val = b;
- d.count = 0;
- rc = mu_sieve_vlist_do (a, _comp_action, &d);
- if (count)
- *count = d.count;
+ for (j = 0; rc == 0 && retr (item, data, j, &sample) == 0; j++)
+ {
+ if (count)
+ (*count)++;
+ for (k = 0; k < b->v.list.count; k++)
+ {
+ mu_sieve_string_t *s = mu_sieve_string_raw (mach, &b->v.list, k);
+ rc = test (comp (mach, s, sample), 0);
+ if (rc)
+ {
+ free (sample);
+ return rc;
+ }
+ }
+ free (sample);
+ }
+ }
+ break;
+
+ default:
+ abort ();
+ }
return rc;
}
-
void
mu_sieve_stream_save (mu_sieve_machine_t mach)
{
diff --git a/sieve/tests/delheader.at b/sieve/tests/delheader.at
index d068ce446..659d77ee9 100644
--- a/sieve/tests/delheader.at
+++ b/sieve/tests/delheader.at
@@ -125,7 +125,7 @@ Subject: Ping
Test message, please discard.
],
-[DELETEHEADER on msg uid 1: X-Agent: (regexp)
+[DELETEHEADER on msg uid 1: X-Agent (values)
])
m4_popdef([MUT_SIEVE_EXT_NAME])
diff --git a/sieve/tests/enc-char.at b/sieve/tests/enc-char.at
index 9d82525a6..d76c0c35a 100644
--- a/sieve/tests/enc-char.at
+++ b/sieve/tests/enc-char.at
@@ -19,7 +19,6 @@ AT_KEYWORDS([encoded-character enc-char])
AT_CHECK([
AT_DATA([prog],[[require ["reject", "encoded-character"];
-
reject "$${hex:40}";
reject "${hex: 40 }";
reject "${HEX: 40}";
@@ -38,25 +37,25 @@ reject "Nested ${hex: 73 65 71 ${hex: 75 65 6E}}ce";
reject "Invalid ${hex: 73 RE}";
]])
-sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -D prog | grep ACTION
+sieve MUT_SIEVE_CMDLINE MUT_SIEVE_OPTIONS -D prog | sed -n 's/.*ACTION: //p'
],
[0],
-[ 9: ACTION: reject "$@"
- 16: ACTION: reject "@"
- 23: ACTION: reject "@"
- 30: ACTION: reject "${hex:40"
- 37: ACTION: reject "${hex:400}"
- 44: ACTION: reject "${hex:40}"
- 51: ACTION: reject "@"
- 58: ACTION: reject "${ unicode:40}"
- 65: ACTION: reject "@"
- 72: ACTION: reject "@"
- 79: ACTION: reject "@"
- 86: ACTION: reject "${Unicode:Cool}"
- 93: ACTION: reject "Now is the time"
- 100: ACTION: reject "Unbalanced ${hex: 73 65 71 uence"
- 107: ACTION: reject "Nested ${hex: 73 65 71 uen}ce"
- 114: ACTION: reject "Invalid ${hex: 73 RE}"
+[reject "$@"
+reject "@"
+reject "@"
+reject "${hex:40"
+reject "${hex:400}"
+reject "${hex:40}"
+reject "@"
+reject "${ unicode:40}"
+reject "@"
+reject "@"
+reject "@"
+reject "${Unicode:Cool}"
+reject "Now is the time"
+reject "Unbalanced ${hex: 73 65 71 uence"
+reject "Nested ${hex: 73 65 71 uen}ce"
+reject "Invalid ${hex: 73 RE}"
])
AT_CLEANUP

Return to:

Send suggestions and report system problems to the System administrator.