From c289acca3c53d204aa5de9345392e151b8620b68 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Sat, 19 Jul 2008 19:43:29 +0200
Subject: [PATCH] Revised extension support for match-types.

---
 TODO                                          |   2 +-
 src/lib-sieve/cmp-i-octet.c                   |   2 -
 src/lib-sieve/mcht-contains.c                 |   2 +-
 src/lib-sieve/mcht-is.c                       |   2 +-
 src/lib-sieve/mcht-matches.c                  |   2 +-
 src/lib-sieve/plugins/regex/Makefile.am       |   1 +
 .../plugins/regex/ext-regex-common.c          |  22 ++
 .../plugins/regex/ext-regex-common.h          |   6 +-
 src/lib-sieve/plugins/regex/ext-regex.c       |  28 +--
 src/lib-sieve/plugins/regex/mcht-regex.c      |   2 +-
 .../relational/ext-relational-common.c        |  29 +++
 .../relational/ext-relational-common.h        |   2 +-
 .../plugins/relational/ext-relational.c       |  31 +--
 src/lib-sieve/plugins/relational/mcht-count.c |   4 +-
 src/lib-sieve/plugins/relational/mcht-value.c |   4 +-
 src/lib-sieve/sieve-comparators.c             |   9 +-
 src/lib-sieve/sieve-comparators.h             |   2 -
 src/lib-sieve/sieve-match-types.c             | 223 ++++++++----------
 src/lib-sieve/sieve-match-types.h             |  52 ++--
 19 files changed, 205 insertions(+), 220 deletions(-)
 create mode 100644 src/lib-sieve/plugins/regex/ext-regex-common.c

diff --git a/TODO b/TODO
index 374ba1bee..876415514 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,5 @@
 Next (in order of descending priority/precedence):
-* Revise extension support for match-types, address-parts and side-effects. 
+* Revise extension support for address-parts and side-effects. 
   Current implementation emits redundant bytes and associated code is not very 
   neat.
 * Improve handling of old/corrupt binaries.
diff --git a/src/lib-sieve/cmp-i-octet.c b/src/lib-sieve/cmp-i-octet.c
index bf1dae1ad..2a7eb3617 100644
--- a/src/lib-sieve/cmp-i-octet.c
+++ b/src/lib-sieve/cmp-i-octet.c
@@ -23,8 +23,6 @@ static int cmp_i_octet_compare
 static bool cmp_i_octet_char_match
 	(const struct sieve_comparator *cmp, const char **val1, const char *val1_end, 
 		const char **val2, const char *val2_end);
-static bool cmp_i_octet_char_skip
-	(const struct sieve_comparator *cmp, const char **val, const char *val_end);
 
 /*
  * Comparator object
diff --git a/src/lib-sieve/mcht-contains.c b/src/lib-sieve/mcht-contains.c
index ec0baf63c..9464a544a 100644
--- a/src/lib-sieve/mcht-contains.c
+++ b/src/lib-sieve/mcht-contains.c
@@ -23,7 +23,7 @@ static bool mcht_contains_match
 
 const struct sieve_match_type contains_match_type = {
 	"contains", TRUE,
-	NULL,
+	&match_type_operand,
 	SIEVE_MATCH_TYPE_CONTAINS,
 	NULL,
 	sieve_match_substring_validate_context,
diff --git a/src/lib-sieve/mcht-is.c b/src/lib-sieve/mcht-is.c
index 1468e3982..2abefa237 100644
--- a/src/lib-sieve/mcht-is.c
+++ b/src/lib-sieve/mcht-is.c
@@ -24,7 +24,7 @@ static bool mcht_is_match
 
 const struct sieve_match_type is_match_type = {
 	"is", TRUE,
-	NULL,
+	&match_type_operand,
 	SIEVE_MATCH_TYPE_IS,
 	NULL, NULL, NULL,
 	mcht_is_match,
diff --git a/src/lib-sieve/mcht-matches.c b/src/lib-sieve/mcht-matches.c
index 185aaf141..50b5ace0b 100644
--- a/src/lib-sieve/mcht-matches.c
+++ b/src/lib-sieve/mcht-matches.c
@@ -24,7 +24,7 @@ static bool mcht_matches_match
 
 const struct sieve_match_type matches_match_type = {
 	"matches", TRUE,
-	NULL,
+	&match_type_operand,
 	SIEVE_MATCH_TYPE_MATCHES,
 	NULL,
 	sieve_match_substring_validate_context, 
diff --git a/src/lib-sieve/plugins/regex/Makefile.am b/src/lib-sieve/plugins/regex/Makefile.am
index 1e02e47ae..f59cc5063 100644
--- a/src/lib-sieve/plugins/regex/Makefile.am
+++ b/src/lib-sieve/plugins/regex/Makefile.am
@@ -9,6 +9,7 @@ AM_CPPFLAGS = \
 
 libsieve_ext_regex_la_SOURCES = \
 	mcht-regex.c \
+	ext-regex-common.c \
 	ext-regex.c
 
 noinst_HEADERS = \
diff --git a/src/lib-sieve/plugins/regex/ext-regex-common.c b/src/lib-sieve/plugins/regex/ext-regex-common.c
new file mode 100644
index 000000000..f0ce1fbc4
--- /dev/null
+++ b/src/lib-sieve/plugins/regex/ext-regex-common.c
@@ -0,0 +1,22 @@
+#include "sieve-common.h"
+#include "sieve-match-types.h"
+
+#include "ext-regex-common.h"
+
+/* 
+ * Regex match type operand
+ */
+
+static const struct sieve_match_type_operand_interface match_type_operand_intf =
+{
+    SIEVE_EXT_DEFINE_MATCH_TYPE(regex_match_type)
+};
+
+const struct sieve_operand regex_match_type_operand = {
+    "regex match",
+    &regex_extension,
+    0,
+    &sieve_match_type_operand_class,
+    &match_type_operand_intf
+};
+
diff --git a/src/lib-sieve/plugins/regex/ext-regex-common.h b/src/lib-sieve/plugins/regex/ext-regex-common.h
index 3c50ad1cf..e2399e9a3 100644
--- a/src/lib-sieve/plugins/regex/ext-regex-common.h
+++ b/src/lib-sieve/plugins/regex/ext-regex-common.h
@@ -1,7 +1,11 @@
 #ifndef __EXT_REGEX_COMMON_H
 #define __EXT_REGEX_COMMON_H
 
-extern const struct sieve_match_type_extension regex_match_extension;
+const struct sieve_extension regex_extension;
+
+const struct sieve_operand regex_match_type_operand;
+
+extern const struct sieve_match_type regex_match_type;
 
 #endif
 
diff --git a/src/lib-sieve/plugins/regex/ext-regex.c b/src/lib-sieve/plugins/regex/ext-regex.c
index e3fb99bce..b5d28acb0 100644
--- a/src/lib-sieve/plugins/regex/ext-regex.c
+++ b/src/lib-sieve/plugins/regex/ext-regex.c
@@ -41,7 +41,6 @@
 
 static bool ext_regex_load(int ext_id);
 static bool ext_regex_validator_load(struct sieve_validator *validator);
-static bool ext_regex_binary_load(struct sieve_binary *sbin);
 
 /* Extension definitions */
 
@@ -51,9 +50,7 @@ const struct sieve_extension regex_extension = {
 	"regex", 
 	ext_regex_load,
 	ext_regex_validator_load,
-	NULL, NULL, NULL,
-	ext_regex_binary_load,
-	NULL,  
+	NULL, NULL, NULL, NULL, NULL,  
 	SIEVE_EXT_DEFINE_NO_OPERATIONS, 
 	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
@@ -65,17 +62,6 @@ static bool ext_regex_load(int ext_id)
 	return TRUE;
 }
 
-/* 
- * Extension access structures 
- */
-
-extern const struct sieve_match_type regex_match_type;
-
-const struct sieve_match_type_extension regex_match_extension = { 
-	&regex_extension,
-	SIEVE_EXT_DEFINE_MATCH_TYPE(regex_match_type)
-};
-
 /* 
  * Load extension into validator 
  */
@@ -88,16 +74,4 @@ static bool ext_regex_validator_load(struct sieve_validator *validator)
 	return TRUE;
 }
 
-/* 
- * Load extension into binary 
- */
-
-static bool ext_regex_binary_load(struct sieve_binary *sbin)
-{
-	sieve_match_type_extension_set
-		(sbin, ext_my_id, &regex_match_extension);
-
-	return TRUE;
-}
-
 
diff --git a/src/lib-sieve/plugins/regex/mcht-regex.c b/src/lib-sieve/plugins/regex/mcht-regex.c
index 1c631e174..9d2e4934d 100644
--- a/src/lib-sieve/plugins/regex/mcht-regex.c
+++ b/src/lib-sieve/plugins/regex/mcht-regex.c
@@ -41,7 +41,7 @@ bool mcht_regex_validate_context
 
 const struct sieve_match_type regex_match_type = {
 	"regex", TRUE,
-	&regex_match_extension,
+	&regex_match_type_operand,
 	0,
 	NULL,
 	mcht_regex_validate_context,
diff --git a/src/lib-sieve/plugins/relational/ext-relational-common.c b/src/lib-sieve/plugins/relational/ext-relational-common.c
index 549c90318..8cbdbceed 100644
--- a/src/lib-sieve/plugins/relational/ext-relational-common.c
+++ b/src/lib-sieve/plugins/relational/ext-relational-common.c
@@ -23,6 +23,12 @@
 
 #include "ext-relational-common.h"
 
+/*
+ * Forward declarations
+ */
+
+const struct sieve_match_type *rel_match_types[];
+
 /* 
  * Validation 
  */
@@ -123,4 +129,27 @@ bool mcht_relational_validate
 	return TRUE;
 }
 
+/*
+ * Relational match-type operand
+ */
+
+const const struct sieve_match_type *rel_match_types[] = {
+    &rel_match_value_gt, &rel_match_value_ge, &rel_match_value_lt,
+    &rel_match_value_le, &rel_match_value_eq, &rel_match_value_ne,
+    &rel_match_count_gt, &rel_match_count_ge, &rel_match_count_lt,
+    &rel_match_count_le, &rel_match_count_eq, &rel_match_count_ne
+};
+
+static const struct sieve_match_type_operand_interface match_type_operand_intf =
+{
+    SIEVE_EXT_DEFINE_MATCH_TYPES(rel_match_types)
+};
+
+const struct sieve_operand rel_match_type_operand = {
+    "relational match",
+    &relational_extension,
+    0,
+    &sieve_match_type_operand_class,
+    &match_type_operand_intf
+};
 
diff --git a/src/lib-sieve/plugins/relational/ext-relational-common.h b/src/lib-sieve/plugins/relational/ext-relational-common.h
index aa759cf6d..238914075 100644
--- a/src/lib-sieve/plugins/relational/ext-relational-common.h
+++ b/src/lib-sieve/plugins/relational/ext-relational-common.h
@@ -65,6 +65,6 @@ extern const struct sieve_match_type rel_match_value_le;
 extern const struct sieve_match_type rel_match_value_eq;
 extern const struct sieve_match_type rel_match_value_ne;
 
-extern const struct sieve_match_type *rel_match_types[];
+extern const struct sieve_operand rel_match_type_operand;
 
 #endif
diff --git a/src/lib-sieve/plugins/relational/ext-relational.c b/src/lib-sieve/plugins/relational/ext-relational.c
index 220c5e578..8f93092c4 100644
--- a/src/lib-sieve/plugins/relational/ext-relational.c
+++ b/src/lib-sieve/plugins/relational/ext-relational.c
@@ -31,28 +31,18 @@
 
 static bool ext_relational_load(int ext_id);
 static bool ext_relational_validator_load(struct sieve_validator *validator);
-static bool ext_relational_binary_load(struct sieve_binary *sbin);
 
 /* Extension definitions */
 
 int ext_relational_my_id;
 
-const struct sieve_match_type *rel_match_types[] = {
-    &rel_match_value_gt, &rel_match_value_ge, &rel_match_value_lt,
-    &rel_match_value_le, &rel_match_value_eq, &rel_match_value_ne,
-    &rel_match_count_gt, &rel_match_count_ge, &rel_match_count_lt,
-    &rel_match_count_le, &rel_match_count_eq, &rel_match_count_ne
-};
-
 const struct sieve_extension relational_extension = { 
 	"relational", 
 	ext_relational_load,
 	ext_relational_validator_load,
-	NULL, NULL, NULL,
-	ext_relational_binary_load,  
-	NULL,
+	NULL, NULL, NULL, NULL, NULL,
 	SIEVE_EXT_DEFINE_NO_OPERATIONS, 
-	SIEVE_EXT_DEFINE_NO_OPERANDS
+	SIEVE_EXT_DEFINE_OPERAND(rel_match_type_operand)
 };
 
 static bool ext_relational_load(int ext_id)
@@ -62,11 +52,6 @@ static bool ext_relational_load(int ext_id)
 	return TRUE;
 }
 
-const struct sieve_match_type_extension relational_match_extension = { 
-	&relational_extension,
-	SIEVE_EXT_DEFINE_MATCH_TYPES(rel_match_types) 
-};
-
 /* 
  * Load extension into validator 
  */
@@ -81,16 +66,4 @@ static bool ext_relational_validator_load(struct sieve_validator *validator)
 	return TRUE;
 }
 
-/* 
- * Load extension into binary 
- */
-
-static bool ext_relational_binary_load(struct sieve_binary *sbin)
-{
-	sieve_match_type_extension_set
-		(sbin, ext_relational_my_id, &relational_match_extension);
-
-	return TRUE;
-}
-
 
diff --git a/src/lib-sieve/plugins/relational/mcht-count.c b/src/lib-sieve/plugins/relational/mcht-count.c
index 771cbf547..9206d1a96 100644
--- a/src/lib-sieve/plugins/relational/mcht-count.c
+++ b/src/lib-sieve/plugins/relational/mcht-count.c
@@ -34,7 +34,7 @@ static bool mcht_count_match_deinit(struct sieve_match_context *mctx);
 
 const struct sieve_match_type count_match_type = {
 	"count", FALSE,
-	&relational_match_extension,
+	&rel_match_type_operand,
 	RELATIONAL_COUNT,
 	mcht_relational_validate,
 	NULL, NULL, NULL, NULL
@@ -43,7 +43,7 @@ const struct sieve_match_type count_match_type = {
 #define COUNT_MATCH_TYPE(name, rel_match)                   \
 const struct sieve_match_type rel_match_count_ ## name = {  \
 	"count-" #name, FALSE,                                  \
-	&relational_match_extension,                            \
+	&rel_match_type_operand,                                \
 	REL_MATCH_INDEX(RELATIONAL_COUNT, rel_match),           \
 	NULL, NULL,                                             \
 	mcht_count_match_init,                                  \
diff --git a/src/lib-sieve/plugins/relational/mcht-value.c b/src/lib-sieve/plugins/relational/mcht-value.c
index 1838d337c..1fe190650 100644
--- a/src/lib-sieve/plugins/relational/mcht-value.c
+++ b/src/lib-sieve/plugins/relational/mcht-value.c
@@ -21,7 +21,7 @@
 
 const struct sieve_match_type value_match_type = {
 	"value", TRUE,
-	&relational_match_extension,
+	&rel_match_type_operand,
 	RELATIONAL_VALUE,
 	mcht_relational_validate,
 	NULL, NULL, NULL, NULL
@@ -30,7 +30,7 @@ const struct sieve_match_type value_match_type = {
 #define VALUE_MATCH_TYPE(name, rel_match)                   \
 const struct sieve_match_type rel_match_value_ ## name = {  \
 	"value-" #name, TRUE,                                   \
-	&relational_match_extension,                            \
+	&rel_match_type_operand,                                \
 	REL_MATCH_INDEX(RELATIONAL_VALUE, rel_match),           \
 	NULL, NULL, NULL,                                       \
 	mcht_value_match,                                       \
diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c
index d0f780021..fcdc9417b 100644
--- a/src/lib-sieve/sieve-comparators.c
+++ b/src/lib-sieve/sieve-comparators.c
@@ -31,6 +31,13 @@ const struct sieve_comparator *sieve_core_comparators[] = {
 const unsigned int sieve_core_comparators_count =
 	N_ELEMENTS(sieve_core_comparators);
 
+/*
+ * Forward declarations
+ */
+ 
+static void sieve_opr_comparator_emit
+	(struct sieve_binary *sbin, const struct sieve_comparator *cmp, int ext_id);
+
 /* 
  * Comparator 'extension' 
  */
@@ -288,7 +295,7 @@ const struct sieve_operand comparator_operand = {
 	&comparator_operand_intf
 };
 
-void sieve_opr_comparator_emit
+static void sieve_opr_comparator_emit
 	(struct sieve_binary *sbin, const struct sieve_comparator *cmp, int ext_id)
 { 
 	(void) sieve_operand_emit_code(sbin, cmp->operand, ext_id);	
diff --git a/src/lib-sieve/sieve-comparators.h b/src/lib-sieve/sieve-comparators.h
index c6de0d1b6..37ea426e0 100644
--- a/src/lib-sieve/sieve-comparators.h
+++ b/src/lib-sieve/sieve-comparators.h
@@ -101,8 +101,6 @@ static inline bool sieve_operand_is_comparator
 		operand->class == &sieve_comparator_operand_class );
 }
 
-void sieve_opr_comparator_emit
-	(struct sieve_binary *sbin, const struct sieve_comparator *cmp, int ext_id);
 const struct sieve_comparator *sieve_opr_comparator_read
   (const struct sieve_runtime_env *renv, sieve_size_t *address);
 bool sieve_opr_comparator_dump
diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c
index 118118e5c..588bd98f4 100644
--- a/src/lib-sieve/sieve-match-types.c
+++ b/src/lib-sieve/sieve-match-types.c
@@ -31,14 +31,11 @@ const struct sieve_match_type *sieve_core_match_types[] = {
 const unsigned int sieve_core_match_types_count = 
 	N_ELEMENTS(sieve_core_match_types);
 
-static struct sieve_extension_obj_registry mtch_default_reg =
-	SIEVE_EXT_DEFINE_MATCH_TYPES(sieve_core_match_types);
-
 /* 
  * Forward declarations 
  */
   
-static void opr_match_type_emit
+static void sieve_opr_match_type_emit
 	(struct sieve_binary *sbin, const struct sieve_match_type *mtch, int ext_id);
 
 /* 
@@ -49,15 +46,12 @@ static int ext_my_id = -1;
 
 static bool mtch_extension_load(int ext_id);
 static bool mtch_validator_load(struct sieve_validator *validator);
-static bool mtch_binary_load(struct sieve_binary *sbin);
 
 const struct sieve_extension match_type_extension = {
 	"@match-types",
 	mtch_extension_load,
 	mtch_validator_load,
-	NULL, NULL, NULL,
-	mtch_binary_load,
-	NULL,
+	NULL, NULL, NULL, NULL, NULL,
 	SIEVE_EXT_DEFINE_NO_OPERATIONS,
 	SIEVE_EXT_DEFINE_NO_OPERANDS
 };
@@ -155,40 +149,6 @@ bool mtch_validator_load(struct sieve_validator *validator)
 	return TRUE;
 }
 
-void sieve_match_types_link_tags
-	(struct sieve_validator *validator, 
-		struct sieve_command_registration *cmd_reg, int id_code) 
-{	
-	sieve_validator_register_tag
-		(validator, cmd_reg, &match_type_tag, id_code); 	
-}
-
-/*
- * Binary context
- */
-
-static inline const struct sieve_match_type_extension *sieve_match_type_extension_get
-	(struct sieve_binary *sbin, int ext_id)
-{	
-	return (const struct sieve_match_type_extension *)
-		sieve_binary_registry_get_object(sbin, ext_my_id, ext_id);
-}
-
-void sieve_match_type_extension_set
-	(struct sieve_binary *sbin, int ext_id,
-		const struct sieve_match_type_extension *ext)
-{
-	sieve_binary_registry_set_object
-		(sbin, ext_my_id, ext_id, (const void *) ext);
-}
-
-static bool mtch_binary_load(struct sieve_binary *sbin)
-{
-	sieve_binary_registry_init(sbin, ext_my_id);
-	
-	return TRUE;
-}
-
 /* 
  * Interpreter context
  */
@@ -244,7 +204,8 @@ bool sieve_match_values_set_enabled
 	return previous;
 }
 
-struct sieve_match_values *sieve_match_values_start(struct sieve_interpreter *interp)
+struct sieve_match_values *sieve_match_values_start
+(struct sieve_interpreter *interp)
 {
 	struct mtch_interpreter_context *ctx = get_interpreter_context(interp);
 	
@@ -334,26 +295,35 @@ void sieve_match_values_get
 	*value_r = NULL;	
 }
 
-
-/*
- * Match-type operand
+/* 
+ * Match-type tagged argument 
  */
  
-struct sieve_operand_class match_type_class = 
-	{ "match-type" };
+/* Forward declarations */
 
-struct sieve_operand match_type_operand = { 
-	"match-type", 
+static bool tag_match_type_is_instance_of
+	(struct sieve_validator *validator, struct sieve_command_context *cmd, 
+		struct sieve_ast_argument *arg);
+static bool tag_match_type_validate
+	(struct sieve_validator *validator, struct sieve_ast_argument **arg, 
+		struct sieve_command_context *cmd);
+static bool tag_match_type_generate
+	(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, 
+		struct sieve_command_context *cmd);
+
+/* Argument object */
+ 
+const struct sieve_argument match_type_tag = { 
+	"MATCH-TYPE",
+	tag_match_type_is_instance_of,
+	NULL, 
+	tag_match_type_validate, 
 	NULL,
-	SIEVE_OPERAND_MATCH_TYPE,
-	&match_type_class,
-	NULL
+	tag_match_type_generate 
 };
 
-/* 
- * Match-type tag 
- */
-  
+/* Argument implementation */
+
 static bool tag_match_type_is_instance_of
 (struct sieve_validator *validator, struct sieve_command_context *cmd, 
 	struct sieve_ast_argument *arg)
@@ -402,6 +372,19 @@ static bool tag_match_type_validate
 	return TRUE;
 }
 
+static bool tag_match_type_generate
+(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, 
+	struct sieve_command_context *cmd ATTR_UNUSED)
+{
+	struct sieve_match_type_context *mtctx =
+		(struct sieve_match_type_context *) arg->context;
+	
+	(void) sieve_opr_match_type_emit
+		(cgenv->sbin, mtctx->match_type, mtctx->ext_id);
+			
+	return TRUE;
+}
+
 bool sieve_match_type_validate_argument
 (struct sieve_validator *validator, struct sieve_ast_argument *arg,
 	struct sieve_ast_argument *key_arg )
@@ -440,41 +423,60 @@ bool sieve_match_type_validate
 	return TRUE;	
 }
 
-/* 
- * Code generation 
+void sieve_match_types_link_tags
+	(struct sieve_validator *validator, 
+		struct sieve_command_registration *cmd_reg, int id_code) 
+{	
+	sieve_validator_register_tag
+		(validator, cmd_reg, &match_type_tag, id_code); 	
+}
+
+/*
+ * Match-type operand
  */
+ 
+struct sieve_operand_class sieve_match_type_operand_class = 
+	{ "match-type" };
+	
+static const struct sieve_match_type_operand_interface 
+	match_type_operand_intf = {
+	SIEVE_EXT_DEFINE_MATCH_TYPES(sieve_core_match_types)
+};
 
-static void opr_match_type_emit
+const struct sieve_operand match_type_operand = { 
+	"match-type", 
+	NULL,
+	SIEVE_OPERAND_MATCH_TYPE,
+	&sieve_match_type_operand_class,
+	&match_type_operand_intf
+};
+
+static void sieve_opr_match_type_emit
 	(struct sieve_binary *sbin, const struct sieve_match_type *mtch, int ext_id)
 { 
-	(void) sieve_operand_emit_code(sbin, &match_type_operand, -1);	
-	
-	(void) sieve_extension_emit_obj
-		(sbin, &mtch_default_reg, mtch, match_types, ext_id);
+	(void) sieve_operand_emit_code(sbin, mtch->operand, ext_id);	
+	(void) sieve_binary_emit_byte(sbin, mtch->code);
 }
 
-static const struct sieve_extension_obj_registry *
-	sieve_match_type_registry_get
-(struct sieve_binary *sbin, unsigned int ext_index)
+static const struct sieve_match_type *_sieve_opr_match_type_read_data
+  (struct sieve_binary *sbin, const struct sieve_operand *operand,
+  	sieve_size_t *address)
 {
-	int ext_id = -1; 
-	const struct sieve_match_type_extension *ext;
+	const struct sieve_match_type_operand_interface *intf;	
+	unsigned int obj_code; 
+
+	if ( !sieve_operand_is_match_type(operand) )
+		return NULL;
 	
-	if ( sieve_binary_extension_get_by_index(sbin, ext_index, &ext_id) == NULL )
+	intf = operand->interface;
+	if ( intf == NULL ) 
 		return NULL;
-
-	if ( (ext=sieve_match_type_extension_get(sbin, ext_id)) == NULL ) 
+			
+	if ( !sieve_binary_read_byte(sbin, address, &obj_code) ) 
 		return NULL;
-		
-	return &(ext->match_types);
-}
 
-static inline const struct sieve_match_type *sieve_match_type_read
-  (struct sieve_binary *sbin, sieve_size_t *address)
-{
-	return sieve_extension_read_obj
-		(struct sieve_match_type, sbin, address, &mtch_default_reg, 
-			sieve_match_type_registry_get);
+	return sieve_extension_get_object
+		(struct sieve_match_type, intf->match_types, obj_code);
 }
 
 const struct sieve_match_type *sieve_opr_match_type_read
@@ -482,23 +484,19 @@ const struct sieve_match_type *sieve_opr_match_type_read
 {
 	const struct sieve_operand *operand = sieve_operand_read(renv->sbin, address);
 	
-	if ( operand == NULL || operand->class != &match_type_class ) 
-		return NULL;
-
-	return sieve_match_type_read(renv->sbin, address);
+	return _sieve_opr_match_type_read_data(renv->sbin, operand, address);
 }
 
 bool sieve_opr_match_type_dump
-(const struct sieve_dumptime_env *denv, sieve_size_t *address)
+	(const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
-	const struct sieve_operand *operand = sieve_operand_read(denv->sbin, address);
+	const struct sieve_operand *operand;
 	const struct sieve_match_type *mtch;
 	
-	if ( operand == NULL || operand->class != &match_type_class ) 
-		return NULL;
-
-	sieve_code_mark(denv); 
-	mtch = sieve_match_type_read(denv->sbin, address);
+	sieve_code_mark(denv);
+	
+	operand = sieve_operand_read(denv->sbin, address); 
+	mtch = _sieve_opr_match_type_read_data(denv->sbin, operand, address);
 	
 	if ( mtch == NULL )
 		return FALSE;
@@ -508,25 +506,6 @@ bool sieve_opr_match_type_dump
 	return TRUE;
 }
 
-static bool tag_match_type_generate
-(const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, 
-	struct sieve_command_context *cmd ATTR_UNUSED)
-{
-	struct sieve_match_type_context *mtctx =
-		(struct sieve_match_type_context *) arg->context;
-	
-	if ( mtctx->match_type->extension == NULL ) {
-		if ( mtctx->match_type->code < SIEVE_MATCH_TYPE_CUSTOM )
-			opr_match_type_emit(cgenv->sbin, mtctx->match_type, -1);
-		else
-			return FALSE;
-	} else {
-		opr_match_type_emit(cgenv->sbin, mtctx->match_type, mtctx->ext_id);
-	} 
-			
-	return TRUE;
-}
-
 /* Match Utility */
 
 struct sieve_match_context *sieve_match_begin
@@ -610,32 +589,18 @@ bool sieve_match_substring_validate_context
 				sieve_comparator_tag_get(carg);
 			
 			if ( (cmp->flags & SIEVE_COMPARATOR_FLAG_SUBSTRING_MATCH) == 0 ) {
-                sieve_command_validate_error(validator, ctx->command_ctx,
-                    "the specified %s comparator does not support "
+				sieve_command_validate_error(validator, ctx->command_ctx,
+					"the specified %s comparator does not support "
 					"sub-string matching as required by the :%s match type",
 					cmp->identifier, ctx->match_type->identifier );
 
 				return FALSE;
 			}
-            return TRUE;
+			return TRUE;
 		}
 
 		carg = sieve_ast_argument_next(carg);
 	}
 
 	return TRUE;
-}
-
-/* 
- * Core match-type modifiers
- */
-
-const struct sieve_argument match_type_tag = { 
-	"MATCH-TYPE",
-	tag_match_type_is_instance_of,
-	NULL, 
-	tag_match_type_validate, 
-	NULL,
-	tag_match_type_generate 
-};
- 
+} 
diff --git a/src/lib-sieve/sieve-match-types.h b/src/lib-sieve/sieve-match-types.h
index f4d358c4f..fcf73d41e 100644
--- a/src/lib-sieve/sieve-match-types.h
+++ b/src/lib-sieve/sieve-match-types.h
@@ -3,7 +3,12 @@
 
 #include "sieve-common.h"
 #include "sieve-extensions.h"
+#include "sieve-code.h"
 
+/*
+ * Core match types 
+ */
+ 
 enum sieve_match_type_code {
 	SIEVE_MATCH_TYPE_IS,
 	SIEVE_MATCH_TYPE_CONTAINS,
@@ -11,6 +16,14 @@ enum sieve_match_type_code {
 	SIEVE_MATCH_TYPE_CUSTOM
 };
 
+extern const struct sieve_match_type is_match_type;
+extern const struct sieve_match_type contains_match_type;
+extern const struct sieve_match_type matches_match_type;
+
+/*
+ * Matching context
+ */
+
 struct sieve_match_context {
 	struct sieve_interpreter *interp;
 	const struct sieve_match_type *match_type;
@@ -21,7 +34,6 @@ struct sieve_match_context {
 };
 
 struct sieve_match_type;
-struct sieve_match_type_extension;
 struct sieve_match_type_context;
 
 struct sieve_match_type {
@@ -32,7 +44,7 @@ struct sieve_match_type {
 	 */
 	bool is_iterative;
 	
-	const struct sieve_match_type_extension *extension;
+	const struct sieve_operand *operand;
 	unsigned int code;
 	
 	bool (*validate)
@@ -49,15 +61,6 @@ struct sieve_match_type {
 	bool (*match_deinit)(struct sieve_match_context *mctx);
 };
 
-struct sieve_match_type_extension {
-	const struct sieve_extension *extension;
-
-	struct sieve_extension_obj_registry match_types;
-};
-
-#define SIEVE_EXT_DEFINE_MATCH_TYPE(OP) SIEVE_EXT_DEFINE_OBJECT(OP)
-#define SIEVE_EXT_DEFINE_MATCH_TYPES(OPS) SIEVE_EXT_DEFINE_OBJECTS(OPS)
-
 struct sieve_match_type_context {
 	struct sieve_command_context *command_ctx;
 	const struct sieve_match_type *match_type;
@@ -106,18 +109,29 @@ void sieve_match_type_register
 const struct sieve_match_type *sieve_match_type_find
 	(struct sieve_validator *validator, const char *identifier,
 		int *ext_id);
-void sieve_match_type_extension_set
-	(struct sieve_binary *sbin, int ext_id,
-		const struct sieve_match_type_extension *ext);
 
 extern const struct sieve_argument match_type_tag;
 
-extern const struct sieve_match_type is_match_type;
-extern const struct sieve_match_type contains_match_type;
-extern const struct sieve_match_type matches_match_type;
+/*
+ * Match type operand
+ */
+ 
+const struct sieve_operand match_type_operand;
+struct sieve_operand_class sieve_match_type_operand_class;
+
+struct sieve_match_type_operand_interface {
+	struct sieve_extension_obj_registry match_types;
+};
+
+#define SIEVE_EXT_DEFINE_MATCH_TYPE(OP) SIEVE_EXT_DEFINE_OBJECT(OP)
+#define SIEVE_EXT_DEFINE_MATCH_TYPES(OPS) SIEVE_EXT_DEFINE_OBJECTS(OPS)
 
-extern const struct sieve_match_type *sieve_core_match_types[];
-extern const unsigned int sieve_core_match_types_count;
+static inline bool sieve_operand_is_match_type
+(const struct sieve_operand *operand)
+{
+	return ( operand != NULL && 
+		operand->class == &sieve_match_type_operand_class );
+}
 
 const struct sieve_match_type *sieve_opr_match_type_read
 	(const struct sieve_runtime_env *renv, sieve_size_t *address);
-- 
GitLab