diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index e374e8bafaacb2b812bb4fc0bdd1e28d22a31c0b..f39882db9011f431218e546a6d32828b8c2d26eb 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -156,7 +156,7 @@ static bool cmd_redirect_operation_execute
 
 	t_push();
 
-	if ( !sieve_opr_string_read(renv->sbin, address, &redirect) ) {
+	if ( !sieve_opr_string_read(renv, address, &redirect) ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c
index 00bc1457a7adc4374560d5cf23759053923427ff..67a187791c60ab40b4ed62c5d2a1e9e0c440fb49 100644
--- a/src/lib-sieve/ext-envelope.c
+++ b/src/lib-sieve/ext-envelope.c
@@ -219,19 +219,19 @@ static bool ext_envelope_operation_execute
 	printf("?? ENVELOPE\n");
 
 	if ( !sieve_addrmatch_default_get_optionals
-		(renv->sbin, address, &addrp, &mtch, &cmp) )
+		(renv, address, &addrp, &mtch, &cmp) )
 		return FALSE; 
 
 	t_push();
 		
 	/* Read header-list */
-	if ( (hdr_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (hdr_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
 
 	/* Read key-list */
-	if ( (key_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c
index 8dcc093fb129e41ef98e9abfd52e4b4c456c1c4a..056e1bed0c47449a50d7a15740796fd9b31fcb96 100644
--- a/src/lib-sieve/ext-fileinto.c
+++ b/src/lib-sieve/ext-fileinto.c
@@ -158,7 +158,7 @@ static bool ext_fileinto_operation_execute
 
 	t_push();
 	
-	if ( !sieve_opr_string_read(renv->sbin, address, &folder) ) {
+	if ( !sieve_opr_string_read(renv, address, &folder) ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c
index 41a38aef13fcf3e855fb0986db9c23831ca594e0..53a9aa66dcd7fbbc94ccc97cfb53e21bb726d31c 100644
--- a/src/lib-sieve/ext-reject.c
+++ b/src/lib-sieve/ext-reject.c
@@ -201,7 +201,7 @@ static bool ext_reject_operation_execute
 		return FALSE;
 	}
 
-	if ( !sieve_opr_string_read(renv->sbin, address, &reason) ) {
+	if ( !sieve_opr_string_read(renv, address, &reason) ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/plugins/body/tst-body.c b/src/lib-sieve/plugins/body/tst-body.c
index f40d249a32447a132af438612667a49e41c49071..b825004765b2b3aac6f77ec9dbf2cdb2b38dd5a5 100644
--- a/src/lib-sieve/plugins/body/tst-body.c
+++ b/src/lib-sieve/plugins/body/tst-body.c
@@ -319,10 +319,10 @@ static bool ext_body_operation_execute
 			case 0: 
 				break;
 			case OPT_COMPARATOR:
-				cmp = sieve_opr_comparator_read(renv->sbin, address);
+				cmp = sieve_opr_comparator_read(renv, address);
 				break;
 			case OPT_MATCH_TYPE:
-				mtch = sieve_opr_match_type_read(renv->sbin, address);
+				mtch = sieve_opr_match_type_read(renv, address);
 				break;
 			case OPT_BODY_TRANSFORM:
 				if ( !sieve_binary_read_byte(renv->sbin, address, &transform) ||
@@ -330,7 +330,7 @@ static bool ext_body_operation_execute
 					return FALSE;
 				
 				if ( transform == TST_BODY_TRANSFORM_CONTENT ) {				
-					if ( (ctype_list=sieve_opr_stringlist_read(renv->sbin, address)) 
+					if ( (ctype_list=sieve_opr_stringlist_read(renv, address)) 
 						== NULL )
 						return FALSE;
 				}
@@ -345,7 +345,7 @@ static bool ext_body_operation_execute
 	t_push();
 		
 	/* Read key-list */
-	if ( (key_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/plugins/imapflags/cmd-addflag.c b/src/lib-sieve/plugins/imapflags/cmd-addflag.c
index 7acf3700f1f556c404a4961244d877c82b6c3a41..2e871c2eece39868eee0d441f07a9e64d5a5249f 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-addflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-addflag.c
@@ -77,7 +77,7 @@ static bool cmd_addflag_operation_execute
 	t_push();
 		
 	/* Read header-list */
-	if ( (flag_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (flag_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/plugins/imapflags/cmd-removeflag.c b/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
index f1739153bf021525859b030f93888e2b25f997d4..08b59eb741a8ea06d1181d675a1b2f7570951724 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
@@ -78,7 +78,7 @@ static bool cmd_removeflag_operation_execute
 	t_push();
 		
 	/* Read header-list */
-	if ( (flag_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (flag_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/plugins/imapflags/cmd-setflag.c b/src/lib-sieve/plugins/imapflags/cmd-setflag.c
index 3b0adba792fe9378cb48dd5d7b0da0b63d251356..231d3ce7f3fbb9e3fdd581c34428b3ea498446da 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-setflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-setflag.c
@@ -76,7 +76,7 @@ static bool cmd_setflag_operation_execute
 	t_push();
 		
 	/* Read header-list */
-	if ( (flag_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (flag_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/plugins/imapflags/tag-flags.c b/src/lib-sieve/plugins/imapflags/tag-flags.c
index 989902bee02f0b7ebacff14ae1bc23a3f8a5ca42..ff716cc6e5003232a6d6d7576106fc737f5d7eb8 100644
--- a/src/lib-sieve/plugins/imapflags/tag-flags.c
+++ b/src/lib-sieve/plugins/imapflags/tag-flags.c
@@ -152,7 +152,7 @@ static bool seff_flags_read_context
 	t_push();
 	
 	/* Read key-list */
-	if ( (flag_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (flag_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/plugins/imapflags/tst-hasflag.c b/src/lib-sieve/plugins/imapflags/tst-hasflag.c
index 19eda59053991d77ad521f8309b9e8a5e5abfec1..abee7453893df5e2e6af94a65d808a87cc5cfbe2 100644
--- a/src/lib-sieve/plugins/imapflags/tst-hasflag.c
+++ b/src/lib-sieve/plugins/imapflags/tst-hasflag.c
@@ -226,10 +226,10 @@ static bool tst_hasflag_operation_execute
 			case 0:
 				break;
 			case OPT_COMPARATOR:
-				cmp = sieve_opr_comparator_read(renv->sbin, address);
+				cmp = sieve_opr_comparator_read(renv, address);
 				break;
 			case OPT_MATCH_TYPE:
-				mtch = sieve_opr_match_type_read(renv->sbin, address);
+				mtch = sieve_opr_match_type_read(renv, address);
 				break;
 			default:
 				return FALSE;
@@ -240,7 +240,7 @@ static bool tst_hasflag_operation_execute
 	t_push();
 		
 	/* Read key-list */
-	if ( (key_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/plugins/vacation/ext-vacation.c b/src/lib-sieve/plugins/vacation/ext-vacation.c
index 47f70b81740daccdfe0bc2df3bef5454706f7ade..0bf1f355d930415c8b626374cf3dc542c592cb27 100644
--- a/src/lib-sieve/plugins/vacation/ext-vacation.c
+++ b/src/lib-sieve/plugins/vacation/ext-vacation.c
@@ -393,23 +393,23 @@ static bool ext_vacation_operation_execute
 			case 0:
 				break;
 			case OPT_DAYS:
-				if ( !sieve_opr_number_read(renv->sbin, address, &days) ) 
+				if ( !sieve_opr_number_read(renv, address, &days) ) 
 					return FALSE;
 				break;
 			case OPT_SUBJECT:
-				if ( !sieve_opr_string_read(renv->sbin, address, &subject) ) 
+				if ( !sieve_opr_string_read(renv, address, &subject) ) 
 					return FALSE;
 				break;
 			case OPT_FROM:
-				if ( !sieve_opr_string_read(renv->sbin, address, &from) ) 
+				if ( !sieve_opr_string_read(renv, address, &from) ) 
 					return FALSE;
 				break;
 			case OPT_HANDLE: 
-				if ( !sieve_opr_string_read(renv->sbin, address, &handle) ) 	
+				if ( !sieve_opr_string_read(renv, address, &handle) ) 	
 					return FALSE;
 				break;
 			case OPT_ADDRESSES:
-				if ( (addresses=sieve_opr_stringlist_read(renv->sbin, address)) 
+				if ( (addresses=sieve_opr_stringlist_read(renv, address)) 
 					== NULL ) 
 					return FALSE;
 				break;
@@ -422,7 +422,7 @@ static bool ext_vacation_operation_execute
 		}
 	}
 	
-	if ( !sieve_opr_string_read(renv->sbin, address, &reason) ) 
+	if ( !sieve_opr_string_read(renv, address, &reason) ) 
 		return FALSE;
 	
 	printf(">> VACATION \"%s\"\n", str_c(reason));
diff --git a/src/lib-sieve/plugins/variables/cmd-set.c b/src/lib-sieve/plugins/variables/cmd-set.c
index 4a2dae08637e81f377342899bacc8be814a69c3f..d5e0a4719f3487a817ee0507370425f9af442d62 100644
--- a/src/lib-sieve/plugins/variables/cmd-set.c
+++ b/src/lib-sieve/plugins/variables/cmd-set.c
@@ -211,6 +211,11 @@ static bool cmd_set_operation_execute
 (const struct sieve_operation *op ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {	
+	struct sieve_variable_storage *storage = 
+		ext_variables_interpreter_get_storage(renv->interp);
+
+	
+	
 	return TRUE;
 }
 
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.c b/src/lib-sieve/plugins/variables/ext-variables-common.c
index ef8aa49e2658d152e675b46b64c08ab06a4761b1..59826b6b91349600fbe89db22a309db9053bda6d 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.c
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.c
@@ -70,6 +70,57 @@ struct sieve_variable *sieve_variable_scope_get_variable
 	return var;
 }
 
+/* Variable storage */
+
+struct sieve_variable_storage {
+	pool_t pool;
+	ARRAY_DEFINE(var_values, string_t *); 
+};
+
+struct sieve_variable_storage *sieve_variable_storage_create(pool_t pool)
+{
+	struct sieve_variable_storage *storage;
+	
+	storage = p_new(pool, struct sieve_variable_storage, 1);
+	storage->pool = pool;
+		
+	p_array_init(&storage->var_values, pool, 4);
+
+	return storage;
+}
+
+void sieve_variable_get
+(struct sieve_variable_storage *storage, unsigned int index, string_t **value)
+{
+	*value = NULL;
+	
+	if  ( index < array_count(&storage->var_values) ) {
+		string_t * const *varent;
+			
+		varent = array_idx(&storage->var_values, index);
+		
+		*value = *varent;
+	};
+} 
+
+void sieve_variable_assign
+(struct sieve_variable_storage *storage, unsigned int index, 
+	const string_t *value)
+{
+	string_t *varval;
+	
+	sieve_variable_get(storage, index, &varval);
+	
+	if ( varval == NULL ) {
+		varval = str_new(storage->pool, str_len(value));
+		array_idx_set(&storage->var_values, index, &varval);	
+	} else {
+		str_truncate(varval, 0);
+	}
+	
+	str_append_str(varval, value);
+}
+
 /* Validator context */
 
 struct ext_variables_validator_context {
@@ -127,6 +178,51 @@ struct sieve_variable *ext_variables_validator_get_variable
 	return sieve_variable_scope_get_variable(ctx->main_scope, variable);
 }
 
+/* Interpreter context */
+
+struct ext_variables_interpreter_context {
+	struct sieve_variable_storage *local_storage;
+};
+
+static struct ext_variables_interpreter_context *
+ext_variables_interpreter_context_create(struct sieve_interpreter *interp)
+{		
+	pool_t pool = sieve_interpreter_pool(interp);
+	struct ext_variables_interpreter_context *ctx;
+	
+	ctx = p_new(pool, struct ext_variables_interpreter_context, 1);
+	ctx->local_storage = sieve_variable_storage_create(pool);
+
+	sieve_interpreter_extension_set_context
+		(interp, ext_variables_my_id, (void *) ctx);
+
+	return ctx;
+}
+
+void ext_variables_interpreter_initialize(struct sieve_interpreter *interp)
+{
+	struct ext_variables_interpreter_context *ctx;
+	
+	/* Create our context */
+	ctx = ext_variables_interpreter_context_create(interp);
+}
+
+static inline struct ext_variables_interpreter_context *
+ext_variables_interpreter_context_get(struct sieve_interpreter *interp)
+{
+	return (struct ext_variables_interpreter_context *)
+		sieve_interpreter_extension_get_context(interp, ext_variables_my_id);
+}
+
+struct sieve_variable_storage *ext_variables_interpreter_get_storage
+	(struct sieve_interpreter *interp)
+{
+	struct ext_variables_interpreter_context *ctx = 
+		ext_variables_interpreter_context_get(interp);
+		
+	return ctx->local_storage;
+}
+
 /* Variable arguments */
 
 static bool arg_variable_generate
@@ -156,7 +252,7 @@ static bool arg_variable_generate
 {
 	struct sieve_variable *var = (struct sieve_variable *) arg->context;
 	
-	ext_variables_variable_emit(sieve_generator_get_binary(generator), var);
+	ext_variables_opr_variable_emit(sieve_generator_get_binary(generator), var);
 
 	return TRUE;
 }
@@ -164,7 +260,7 @@ static bool arg_variable_generate
 /* Variable operands */
 
 static bool opr_variable_read
-	(struct sieve_binary *sbin, sieve_size_t *address, string_t **str);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address, string_t **str);
 static bool opr_variable_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
 
@@ -180,7 +276,7 @@ const struct sieve_operand variable_operand = {
 	&variable_interface
 };	
 
-void ext_variables_variable_emit
+void ext_variables_opr_variable_emit
 	(struct sieve_binary *sbin, struct sieve_variable *var) 
 {
 	(void) sieve_operand_emit_code(sbin, &variable_operand, ext_variables_my_id);
@@ -190,10 +286,10 @@ void ext_variables_variable_emit
 static bool opr_variable_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address) 
 {
-	sieve_size_t number = 0;
+	sieve_size_t index = 0;
 	
-	if (sieve_binary_read_integer(denv->sbin, address, &number) ) {
-		sieve_code_dumpf(denv, "VARIABLE: %ld [?]", (long) number);
+	if (sieve_binary_read_integer(denv->sbin, address, &index) ) {
+		sieve_code_dumpf(denv, "VARIABLE: %ld [?]", (long) index);
 
 		return TRUE;
 	}
@@ -202,11 +298,11 @@ static bool opr_variable_dump
 }
 
 static bool opr_variable_read
-  (struct sieve_binary *sbin, sieve_size_t *address, string_t **str)
+  (const struct sieve_runtime_env *renv, sieve_size_t *address, string_t **str)
 { 
-	sieve_size_t number = 0;
+	sieve_size_t index = 0;
 	
-	if (sieve_binary_read_integer(sbin, address, &number) ) {
+	if (sieve_binary_read_integer(renv->sbin, address, &index) ) {
 		*str = t_str_new(10);
 		str_append(*str, "VARIABLE");
 
@@ -216,6 +312,20 @@ static bool opr_variable_read
 	return FALSE;
 }
 
+bool ext_variables_opr_variable_assign
+	(struct sieve_binary *sbin, sieve_size_t *address, string_t *str)
+{
+	sieve_size_t index = 0;
+	
+	if (sieve_binary_read_integer(sbin, address, &index) ) {
+		/* FIXME: Assign */
+	
+		return TRUE;
+	}
+	
+	return FALSE;
+}
+
 /* Set modifier registration */
 
 const struct ext_variables_set_modifier *ext_variables_set_modifier_find
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.h b/src/lib-sieve/plugins/variables/ext-variables-common.h
index 5768717d0d9c74a9dfa025de119d252a84b16981..5dcadf54bbc020154e13e8354f03614374eaa3a3 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.h
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.h
@@ -17,6 +17,7 @@ enum ext_variables_opcode {
 /* Extension */
 
 void ext_variables_validator_initialize(struct sieve_validator *validator);
+void ext_variables_interpreter_initialize(struct sieve_interpreter *interp);
 
 /* Set modifiers */
 
@@ -41,8 +42,10 @@ const struct ext_variables_set_modifier *ext_variables_set_modifier_find
 	
 /* Variables */
 
-void ext_variables_variable_emit
+void ext_variables_opr_variable_emit
 	(struct sieve_binary *sbin, struct sieve_variable *var);
+bool ext_variables_opr_variable_assign
+	(struct sieve_binary *sbin, sieve_size_t *address, string_t *str);
 
 void ext_variables_variable_argument_activate
 	(struct sieve_validator *validator, struct sieve_ast_argument *arg);
@@ -50,4 +53,8 @@ void ext_variables_variable_argument_activate
 struct sieve_variable *ext_variables_validator_get_variable
 (struct sieve_validator *validator, const char *variable);
 
+struct sieve_variable_storage *ext_variables_interpreter_get_storage
+	(struct sieve_interpreter *interp);
+
+
 #endif /* __EXT_VARIABLES_COMMON_H */
diff --git a/src/lib-sieve/plugins/variables/ext-variables.c b/src/lib-sieve/plugins/variables/ext-variables.c
index b3b2c0494622ab2bc030a27c8d8bbd2192df9ee2..4f2f41f1acf4767d8f7759c64ccd1c2b28fd6670 100644
--- a/src/lib-sieve/plugins/variables/ext-variables.c
+++ b/src/lib-sieve/plugins/variables/ext-variables.c
@@ -9,6 +9,7 @@
  */
 
 #include "lib.h"
+#include "str.h"
 #include "unichar.h"
 
 #include "sieve-extensions.h"
@@ -23,6 +24,7 @@
 
 static bool ext_variables_load(int ext_id);
 static bool ext_variables_validator_load(struct sieve_validator *validator);
+static bool ext_variables_interpreter_load(struct sieve_interpreter *interp);
 
 /* Commands */
 
@@ -50,7 +52,8 @@ struct sieve_extension variables_extension = {
 	"variables", 
 	ext_variables_load,
 	ext_variables_validator_load, 
-	NULL, NULL, NULL, 
+	NULL, NULL,
+	ext_variables_interpreter_load, 
 	SIEVE_EXT_DEFINE_OPERATIONS(ext_variables_operations), 
 	SIEVE_EXT_DEFINE_OPERAND(variable_operand)
 };
@@ -160,7 +163,7 @@ static bool arg_variable_string_validate
 /* Load extension into validator */
 
 static bool ext_variables_validator_load
-	(struct sieve_validator *validator ATTR_UNUSED)
+	(struct sieve_validator *validator)
 {
 	/*sieve_validator_argument_override(validator, SAT_VAR_STRING, 
 		&variable_string_argument);*/ 
@@ -172,3 +175,13 @@ static bool ext_variables_validator_load
 
 	return TRUE;
 }
+
+/* Load extension into interpreter */
+
+static bool ext_variables_interpreter_load
+	(struct sieve_interpreter *interp)
+{
+	ext_variables_interpreter_initialize(interp);
+
+	return TRUE;
+}
diff --git a/src/lib-sieve/plugins/variables/sieve-ext-variables.h b/src/lib-sieve/plugins/variables/sieve-ext-variables.h
index 42f8c9c63746c320c6f5c52c2583837790421686..db9903c1aca40cbfcb9fb7ab8164f1735b2ae4bf 100644
--- a/src/lib-sieve/plugins/variables/sieve-ext-variables.h
+++ b/src/lib-sieve/plugins/variables/sieve-ext-variables.h
@@ -13,6 +13,15 @@ struct sieve_variable_scope;
 struct sieve_variable_scope *sieve_variable_scope_create(pool_t pool);
 struct sieve_variable *sieve_variable_scope_get_variable
 	(struct sieve_variable_scope *scope, const char *identifier);
+	
+struct sieve_variable_storage;
 
+struct sieve_variable_storage *sieve_variable_storage_create(pool_t pool);
+void sieve_variable_get
+	(struct sieve_variable_storage *storage, unsigned int index, 
+		string_t **value);
+void sieve_variable_assign
+	(struct sieve_variable_storage *storage, unsigned int index, 
+		const string_t *value);
 
 #endif /* __SIEVE_EXT_VARIABLES_H */
diff --git a/src/lib-sieve/plugins/variables/tst-string.c b/src/lib-sieve/plugins/variables/tst-string.c
index 44f800eb072c8402a0706878fdcbe74b17d406f5..ece3095a31a9666233c0bc17c890b8f6ebd45976 100644
--- a/src/lib-sieve/plugins/variables/tst-string.c
+++ b/src/lib-sieve/plugins/variables/tst-string.c
@@ -180,10 +180,10 @@ static bool tst_string_operation_execute
 			case 0: 
 				break;
 			case OPT_COMPARATOR:
-				cmp = sieve_opr_comparator_read(renv->sbin, address);
+				cmp = sieve_opr_comparator_read(renv, address);
 				break;
 			case OPT_MATCH_TYPE:
-				mtch = sieve_opr_match_type_read(renv->sbin, address);
+				mtch = sieve_opr_match_type_read(renv, address);
 				break;
 			default:
 				return FALSE;
@@ -194,13 +194,13 @@ static bool tst_string_operation_execute
 	t_push();
 		
 	/* Read string-list */
-	if ( (source=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (source=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
 	
 	/* Read key-list */
-	if ( (key_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c
index 036eacea68f17b5fc83e4a8fd4dacf92f7952638..088265038c4177b3b3ae013bd147512f091f1035 100644
--- a/src/lib-sieve/sieve-actions.c
+++ b/src/lib-sieve/sieve-actions.c
@@ -123,26 +123,36 @@ static const struct sieve_extension_obj_registry *
 	return &(ext->side_effects);
 }
 
-const struct sieve_side_effect *sieve_opr_side_effect_read
+static inline const struct sieve_side_effect *sieve_side_effect_read
 (struct sieve_binary *sbin, sieve_size_t *address)
 {
-	const struct sieve_operand *operand = sieve_operand_read(sbin, address);
+	return sieve_extension_read_obj
+		(struct sieve_side_effect, sbin, address, &seff_default_reg, 
+			sieve_side_effect_registry_get);
+}
+
+const struct sieve_side_effect *sieve_opr_side_effect_read
+(const struct sieve_runtime_env *renv, sieve_size_t *address)
+{
+	const struct sieve_operand *operand = sieve_operand_read(renv->sbin, address);
 
 	if ( operand == NULL || operand->class != &side_effect_class ) 
 		return NULL;
 		
-	return sieve_extension_read_obj
-		(struct sieve_side_effect, sbin, address, &seff_default_reg, 
-			sieve_side_effect_registry_get);
+	return sieve_side_effect_read(renv->sbin, address);
 }
 
 bool sieve_opr_side_effect_dump
 (const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
+	const struct sieve_operand *operand = sieve_operand_read(denv->sbin, address);
 	const struct sieve_side_effect *seffect;
 
+	if ( operand == NULL || operand->class != &side_effect_class ) 
+		return NULL;
+
 	sieve_code_mark(denv);
-	seffect = sieve_opr_side_effect_read(denv->sbin, address);
+	seffect = sieve_side_effect_read(denv->sbin, address);
 
 	if ( seffect == NULL ) 
 		return FALSE;
diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h
index 7806872f3f522ca76d6ba3189b8f9b2b393f5425..c9122231161d3736ff26f0aac412e6966b8e68eb 100644
--- a/src/lib-sieve/sieve-actions.h
+++ b/src/lib-sieve/sieve-actions.h
@@ -114,7 +114,7 @@ void sieve_opr_side_effect_emit
 bool sieve_opr_side_effect_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
 const struct sieve_side_effect *sieve_opr_side_effect_read
-	(struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 /* Actions common to multiple commands */
 
diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c
index 42806dfc6b6541e0b5c26ad7b177774ddc5c2faf..fc6f4d3f09ea3a6862d6d69074cadc050f14714c 100644
--- a/src/lib-sieve/sieve-address-parts.c
+++ b/src/lib-sieve/sieve-address-parts.c
@@ -279,26 +279,36 @@ static const struct sieve_extension_obj_registry *
 	return &(ext->address_parts);
 }
 
-const struct sieve_address_part *sieve_opr_address_part_read
+static inline const struct sieve_address_part *sieve_address_part_read
 (struct sieve_binary *sbin, sieve_size_t *address)
 {
-	const struct sieve_operand *operand = sieve_operand_read(sbin, address);
+	return sieve_extension_read_obj
+		(struct sieve_address_part, sbin, address, &addrp_default_reg, 
+			sieve_address_part_registry_get);
+}
+
+const struct sieve_address_part *sieve_opr_address_part_read
+(const struct sieve_runtime_env *renv, sieve_size_t *address)
+{
+	const struct sieve_operand *operand = sieve_operand_read(renv->sbin, address);
 	
 	if ( operand == NULL || operand->class != &address_part_class ) 
 		return NULL;
 
-	return sieve_extension_read_obj
-		(struct sieve_address_part, sbin, address, &addrp_default_reg, 
-			sieve_address_part_registry_get);
+	return sieve_address_part_read(renv->sbin, address);
 }
 
 bool sieve_opr_address_part_dump
 (const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
+	const struct sieve_operand *operand = sieve_operand_read(denv->sbin, address);
 	const struct sieve_address_part *addrp; 
+	
+	if ( operand == NULL || operand->class != &address_part_class ) 
+		return NULL;
 		
 	sieve_code_mark(denv);
-	addrp = sieve_opr_address_part_read(denv->sbin, address);
+	addrp = sieve_address_part_read(denv->sbin, address);
 	
 	if ( addrp == NULL )
 		return FALSE;
@@ -404,31 +414,31 @@ bool sieve_addrmatch_default_dump_optionals
 }
 
 bool sieve_addrmatch_default_get_optionals
-(struct sieve_binary *sbin, sieve_size_t *address, 
+(const struct sieve_runtime_env *renv, sieve_size_t *address, 
 	const struct sieve_address_part **addrp, const struct sieve_match_type **mtch, 
 	const struct sieve_comparator **cmp) 
 {
 	int opt_code = 1;
 	
 	
-	if ( sieve_operand_optional_present(sbin, address) ) {
+	if ( sieve_operand_optional_present(renv->sbin, address) ) {
 		while ( opt_code != 0 ) {
-			if ( !sieve_operand_optional_read(sbin, address, &opt_code) )
+			if ( !sieve_operand_optional_read(renv->sbin, address, &opt_code) )
 				return FALSE;
 				  
 			switch ( opt_code ) {
 			case 0:
 				break;
 			case SIEVE_AM_OPT_COMPARATOR:
-				if ( (*cmp = sieve_opr_comparator_read(sbin, address)) == NULL )
+				if ( (*cmp = sieve_opr_comparator_read(renv, address)) == NULL )
 					return FALSE;
 				break;
 			case SIEVE_AM_OPT_MATCH_TYPE:
-				if ( (*mtch = sieve_opr_match_type_read(sbin, address)) == NULL )
+				if ( (*mtch = sieve_opr_match_type_read(renv, address)) == NULL )
 					return FALSE;
 				break;
 			case SIEVE_AM_OPT_ADDRESS_PART:
-				if ( (*addrp = sieve_opr_address_part_read(sbin, address)) == NULL )
+				if ( (*addrp = sieve_opr_address_part_read(renv, address)) == NULL )
 					return FALSE;
 				break;
 			default:
diff --git a/src/lib-sieve/sieve-address-parts.h b/src/lib-sieve/sieve-address-parts.h
index ff0365107d159b2e0e0b6cdbab397c690fcc304f..10ea5595d27866a97dd3459c130677ddeaa3b1c0 100644
--- a/src/lib-sieve/sieve-address-parts.h
+++ b/src/lib-sieve/sieve-address-parts.h
@@ -64,7 +64,7 @@ extern const struct sieve_address_part *sieve_core_address_parts[];
 extern const unsigned int sieve_core_address_parts_count;
 
 const struct sieve_address_part *sieve_opr_address_part_read
- 	(struct sieve_binary *sbin, sieve_size_t *address);
+ 	(const struct sieve_runtime_env *renv, sieve_size_t *address);
 bool sieve_opr_address_part_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
 
@@ -84,7 +84,7 @@ enum sieve_addrmatch_opt_operand {
 bool sieve_addrmatch_default_dump_optionals
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
 bool sieve_addrmatch_default_get_optionals
-	(struct sieve_binary *sbin, sieve_size_t *address, 
+	(const struct sieve_runtime_env *renv, sieve_size_t *address, 
 		const struct sieve_address_part **addp, 
 		const struct sieve_match_type **mtch, const struct sieve_comparator **cmp);
 
diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c
index 1dfa9dc674d12cc7cf30ba9cabfbd6de17143334..dd9c7edec8e3aca29c721a4abb9d85b2a73dd05a 100644
--- a/src/lib-sieve/sieve-code.c
+++ b/src/lib-sieve/sieve-code.c
@@ -19,7 +19,7 @@
  */
 
 struct sieve_coded_stringlist {
-	struct sieve_binary *binary;
+	const struct sieve_runtime_env *runenv;
 	sieve_size_t start_address;
 	sieve_size_t end_address;
 	sieve_size_t current_offset;
@@ -28,16 +28,16 @@ struct sieve_coded_stringlist {
 };
 
 static struct sieve_coded_stringlist *sieve_coded_stringlist_create
-	(struct sieve_binary *sbin, 
+(const struct sieve_runtime_env *renv, 
 	 sieve_size_t start_address, sieve_size_t length, sieve_size_t end)
 {
 	struct sieve_coded_stringlist *strlist;
 	
-	if ( end > sieve_binary_get_code_size(sbin) ) 
+	if ( end > sieve_binary_get_code_size(renv->sbin) ) 
   		return NULL;
     
 	strlist = p_new(pool_datastack_create(), struct sieve_coded_stringlist, 1);
-	strlist->binary = sbin;
+	strlist->runenv = renv;
 	strlist->start_address = start_address;
 	strlist->current_offset = start_address;
 	strlist->end_address = end;
@@ -48,7 +48,7 @@ static struct sieve_coded_stringlist *sieve_coded_stringlist_create
 }
 
 bool sieve_coded_stringlist_next_item
-	(struct sieve_coded_stringlist *strlist, string_t **str) 
+(struct sieve_coded_stringlist *strlist, string_t **str) 
 {
 	sieve_size_t address;
 	*str = NULL;
@@ -58,7 +58,7 @@ bool sieve_coded_stringlist_next_item
 	else {
 		address = strlist->current_offset;
   	
-		if ( sieve_opr_string_read(strlist->binary, &address, str) ) {
+		if ( sieve_opr_string_read(strlist->runenv, &address, str) ) {
 			strlist->index++;
 			strlist->current_offset = address;
 			return TRUE;
@@ -118,6 +118,35 @@ bool sieve_coded_stringlist_read_all
 	return result;
 }
 
+static bool sieve_coded_stringlist_dump
+(const struct sieve_dumptime_env *denv, sieve_size_t *address, 
+	sieve_size_t length, sieve_size_t end)
+{
+	unsigned int i;
+	
+	if ( end > sieve_binary_get_code_size(denv->sbin) ) 
+  		return FALSE;
+    
+	sieve_code_dumpf(denv, "STRLIST [%d] (END %08x)", length, end);
+	sieve_code_descend(denv);
+	
+	for ( i = 0; i < length; i++ ) {
+		if ( !sieve_opr_string_dump(denv, address) ) 
+			return FALSE;
+
+		if ( *address > end ) 
+			return FALSE;
+	}
+
+	if ( *address != end ) return FALSE;
+	
+	sieve_code_ascend(denv);
+		
+	return TRUE;
+}
+	
+
+
 /*
  * Core operands
  */
@@ -215,7 +244,8 @@ bool sieve_operand_optional_read
 static bool opr_number_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
 static bool opr_number_read
-	(struct sieve_binary *sbin, sieve_size_t *address, sieve_size_t *number);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address, 
+		sieve_size_t *number);
 
 const struct sieve_opr_number_interface number_interface = { 
 	opr_number_dump, 
@@ -234,10 +264,10 @@ const struct sieve_operand number_operand = {
 
 /* String */
 
-static bool opr_string_read
-	(struct sieve_binary *sbin, sieve_size_t *address, string_t **str);
 static bool opr_string_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
+static bool opr_string_read
+	(const struct sieve_runtime_env *renv, sieve_size_t *address, string_t **str);
 
 const struct sieve_opr_string_interface string_interface ={ 
 	opr_string_dump,
@@ -259,7 +289,7 @@ const struct sieve_operand string_operand = {
 static bool opr_stringlist_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
 static struct sieve_coded_stringlist *opr_stringlist_read
-	(struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 const struct sieve_opr_stringlist_interface stringlist_interface = { 
 	opr_stringlist_dump, 
@@ -310,9 +340,10 @@ bool sieve_opr_number_dump
 }
 
 bool sieve_opr_number_read
-  (struct sieve_binary *sbin, sieve_size_t *address, sieve_size_t *number)
+(const struct sieve_runtime_env *renv, sieve_size_t *address, 
+	sieve_size_t *number)
 {
-	const struct sieve_operand *operand = sieve_operand_read(sbin, address);
+	const struct sieve_operand *operand = sieve_operand_read(renv->sbin, address);
 	const struct sieve_opr_number_interface *intf;
 	
 	if ( operand == NULL || operand->class != &number_class ) 
@@ -323,7 +354,7 @@ bool sieve_opr_number_read
 	if ( intf->read == NULL )
 		return FALSE;
 
-	return intf->read(sbin, address, number);  
+	return intf->read(renv, address, number);  
 }
 
 static bool opr_number_dump
@@ -341,9 +372,10 @@ static bool opr_number_dump
 }
 
 static bool opr_number_read
-  (struct sieve_binary *sbin, sieve_size_t *address, sieve_size_t *number)
+(const struct sieve_runtime_env *renv, sieve_size_t *address, 
+	sieve_size_t *number)
 { 
-	return sieve_binary_read_integer(sbin, address, number);
+	return sieve_binary_read_integer(renv->sbin, address, number);
 }
 
 /* String */
@@ -375,9 +407,9 @@ bool sieve_opr_string_dump
 }
 
 bool sieve_opr_string_read
-  (struct sieve_binary *sbin, sieve_size_t *address, string_t **str)
+(const struct sieve_runtime_env *renv, sieve_size_t *address, string_t **str)
 {
-	const struct sieve_operand *operand = sieve_operand_read(sbin, address);
+	const struct sieve_operand *operand = sieve_operand_read(renv->sbin, address);
 	const struct sieve_opr_string_interface *intf;
 	
 	if ( operand == NULL || operand->class != &string_class ) 
@@ -388,7 +420,7 @@ bool sieve_opr_string_read
 	if ( intf->read == NULL )
 		return FALSE;
 
-	return intf->read(sbin, address, str);  
+	return intf->read(renv, address, str);  
 }
 
 static void _dump_string
@@ -417,9 +449,9 @@ bool opr_string_dump
 }
 
 static bool opr_string_read
-  (struct sieve_binary *sbin, sieve_size_t *address, string_t **str)
+  (const struct sieve_runtime_env *renv, sieve_size_t *address, string_t **str)
 { 	
-	return sieve_binary_read_string(sbin, address, str);
+	return sieve_binary_read_string(renv->sbin, address, str);
 }
 
 /* String list */
@@ -487,10 +519,10 @@ bool sieve_opr_stringlist_dump
 }
 
 struct sieve_coded_stringlist *sieve_opr_stringlist_read
-  (struct sieve_binary *sbin, sieve_size_t *address)
+  (const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	sieve_size_t start = *address;
-	const struct sieve_operand *operand = sieve_operand_read(sbin, address);
+	const struct sieve_operand *operand = sieve_operand_read(renv->sbin, address);
 	
 	if ( operand == NULL )
 		return NULL;
@@ -502,18 +534,17 @@ struct sieve_coded_stringlist *sieve_opr_stringlist_read
 		if ( intf->read == NULL ) 
 			return NULL;
 
-		return intf->read(sbin, address);  
+		return intf->read(renv, address);  
 	} else if ( operand->class == &string_class ) {
 		/* Special case, accept single string as string list as well. */
 		const struct sieve_opr_string_interface *intf = 
 			(const struct sieve_opr_string_interface *) operand->interface;
 		
-  	if ( intf->read == NULL || !intf->read(sbin, address, NULL) ) {
-  		printf("FAILED TO SKIP\n");
+  	if ( intf->read == NULL || !intf->read(renv, address, NULL) ) {
   		return NULL;
   	}
   
-		return sieve_coded_stringlist_create(sbin, start, 1, *address); 
+		return sieve_coded_stringlist_create(renv, start, 1, *address); 
 	}	
 	
 	return NULL;
@@ -522,53 +553,40 @@ struct sieve_coded_stringlist *sieve_opr_stringlist_read
 static bool opr_stringlist_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address) 
 {
-	bool result = TRUE;
-	struct sieve_coded_stringlist *strlist;
-	
-	if ( (strlist=opr_stringlist_read(denv->sbin, address)) != NULL ) {
-		string_t *stritem;
-		
-		sieve_code_dumpf(denv, "STRLIST [%d] (END %08x)", 
-			sieve_coded_stringlist_get_length(strlist), 
-			sieve_coded_stringlist_get_end_address(strlist));
-	  	
-		sieve_code_mark_specific(denv,
-			sieve_coded_stringlist_get_current_offset(strlist));
-		sieve_code_descend(denv);
-		while ( (result=sieve_coded_stringlist_next_item(strlist, &stritem)) && 
-			stritem != NULL ) {	
-			_dump_string(denv, stritem);
-			sieve_code_mark_specific(denv,
-				sieve_coded_stringlist_get_current_offset(strlist));  
-		}
-		sieve_code_ascend(denv);
-		
-		return result;
-	}
-	
-	return FALSE;
+	sieve_size_t pc = *address;
+	sieve_size_t end; 
+	sieve_size_t length = 0; 
+ 	int end_offset;
+
+	if ( !sieve_binary_read_offset(denv->sbin, address, &end_offset) )
+		return FALSE;
+
+	end = pc + end_offset;
+
+	if ( !sieve_binary_read_integer(denv->sbin, address, &length) ) 
+		return FALSE;	
+  	
+	return sieve_coded_stringlist_dump(denv, address, length, end); 
 }
 
 static struct sieve_coded_stringlist *opr_stringlist_read
-  (struct sieve_binary *sbin, sieve_size_t *address )
+  (const struct sieve_runtime_env *renv, sieve_size_t *address )
 {
 	struct sieve_coded_stringlist *strlist;
-
 	sieve_size_t pc = *address;
 	sieve_size_t end; 
-	sieve_size_t length = 0; 
- 
+	sieve_size_t length = 0;  
 	int end_offset;
 	
-	if ( !sieve_binary_read_offset(sbin, address, &end_offset) )
+	if ( !sieve_binary_read_offset(renv->sbin, address, &end_offset) )
 		return NULL;
 
 	end = pc + end_offset;
 
-	if ( !sieve_binary_read_integer(sbin, address, &length) ) 
+	if ( !sieve_binary_read_integer(renv->sbin, address, &length) ) 
   	return NULL;	
   	
-	strlist = sieve_coded_stringlist_create(sbin, *address, length, end); 
+	strlist = sieve_coded_stringlist_create(renv, *address, length, end); 
 
 	/* Skip over the string list for now */
 	*address = end;
diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h
index 82eabe4f726788149f8438141826640a84364b70..dbb4902c96498c53463df3c6087c701eee4cebc7 100644
--- a/src/lib-sieve/sieve-code.h
+++ b/src/lib-sieve/sieve-code.h
@@ -47,21 +47,23 @@ struct sieve_opr_number_interface {
 	bool (*dump)	
 		(const struct sieve_dumptime_env *denv, sieve_size_t *address);
 	bool (*read)
-	  (struct sieve_binary *sbin, sieve_size_t *address, sieve_size_t *number);
+	  (const struct sieve_runtime_env *renv, sieve_size_t *address, 
+	  	sieve_size_t *number);
 };
 
 struct sieve_opr_string_interface {
 	bool (*dump)
 		(const struct sieve_dumptime_env *denv, sieve_size_t *address);
 	bool (*read)
-		(struct sieve_binary *sbin, sieve_size_t *address, string_t **str);
+		(const struct sieve_runtime_env *renv, sieve_size_t *address, 
+			string_t **str);
 };
 
 struct sieve_opr_stringlist_interface {
 	bool (*dump)
 		(const struct sieve_dumptime_env *denv, sieve_size_t *address);
 	struct sieve_coded_stringlist *(*read)
-		(struct sieve_binary *sbin, sieve_size_t *address);
+		(const struct sieve_runtime_env *renv, sieve_size_t *address);
 };
 
 enum sieve_core_operand {
@@ -102,13 +104,14 @@ void sieve_opr_number_emit(struct sieve_binary *sbin, sieve_size_t number);
 bool sieve_opr_number_dump	
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address); 
 bool sieve_opr_number_read
-	(struct sieve_binary *sbin, sieve_size_t *address, sieve_size_t *number);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address, 
+		sieve_size_t *number);
 
 void sieve_opr_string_emit(struct sieve_binary *sbin, string_t *str);
 bool sieve_opr_string_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address); 
 bool sieve_opr_string_read
-	(struct sieve_binary *sbin, sieve_size_t *address, string_t **str);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address, string_t **str);
 
 void sieve_opr_stringlist_emit_start
 	(struct sieve_binary *sbin, unsigned int listlen, void **context);
@@ -119,7 +122,7 @@ void sieve_opr_stringlist_emit_end
 bool sieve_opr_stringlist_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
 struct sieve_coded_stringlist *sieve_opr_stringlist_read
-	(struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 
 /* Operation: identifies what's to be done */
diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c
index 6ab9de1914a9a47d9256f1a1c75992c435a57c5f..dfbc23519322c6244e8a9aeed59279729e7086ee 100644
--- a/src/lib-sieve/sieve-comparators.c
+++ b/src/lib-sieve/sieve-comparators.c
@@ -332,26 +332,36 @@ static const struct sieve_extension_obj_registry *
 	return &(ext->comparators);
 }
 
-const struct sieve_comparator *sieve_opr_comparator_read
+static inline const struct sieve_comparator *sieve_comparator_read
   (struct sieve_binary *sbin, sieve_size_t *address)
 {
-	const struct sieve_operand *operand = sieve_operand_read(sbin, address);
+	return sieve_extension_read_obj
+		(struct sieve_comparator, sbin, address, &cmp_default_reg, 
+			sieve_comparator_registry_get);
+}
+
+const struct sieve_comparator *sieve_opr_comparator_read
+  (const struct sieve_runtime_env *renv, sieve_size_t *address)
+{
+	const struct sieve_operand *operand = sieve_operand_read(renv->sbin, address);
 	
 	if ( operand == NULL || operand->class != &comparator_class ) 
 		return NULL;
 	
-	return sieve_extension_read_obj
-		(struct sieve_comparator, sbin, address, &cmp_default_reg, 
-			sieve_comparator_registry_get);
+	return sieve_comparator_read(renv->sbin, address);
 }
 
 bool sieve_opr_comparator_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
+	const struct sieve_operand *operand = sieve_operand_read(denv->sbin, address);
 	const struct sieve_comparator *cmp;
+	
+	if ( operand == NULL || operand->class != &comparator_class ) 
+		return NULL;
 
 	sieve_code_mark(denv);
-	cmp = sieve_opr_comparator_read(denv->sbin, address);
+	cmp = sieve_comparator_read(denv->sbin, address);
 	
 	if ( cmp == NULL )
 		return FALSE;
diff --git a/src/lib-sieve/sieve-comparators.h b/src/lib-sieve/sieve-comparators.h
index b082870033fa8bd76da8f3cea6af1e1664dcf8b4..2fb8e1f64195afc9d2aea1d91b087ff8832dce26 100644
--- a/src/lib-sieve/sieve-comparators.h
+++ b/src/lib-sieve/sieve-comparators.h
@@ -77,7 +77,7 @@ const struct sieve_comparator *sieve_comparator_find
 		int *ext_id);
 
 const struct sieve_comparator *sieve_opr_comparator_read
-	(struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address);
 bool sieve_opr_comparator_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
 
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index 63522d84dd0adda901b2a2f99ae03b69c4e68180..b07e23fbcb998f301691ea15733166ab793395e6 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -331,7 +331,7 @@ bool sieve_interpreter_handle_optional_operands
 					*list = sieve_side_effects_list_create(renv->result);
 					
 				const struct sieve_side_effect *seffect = 
-					sieve_opr_side_effect_read(renv->sbin, address);
+					sieve_opr_side_effect_read(renv, address);
 
 				if ( seffect == NULL ) return FALSE;
 			
diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c
index e312de4cd1c6a716c994cb83c997645b0dc50dc9..c3cf10e48504bf0b4cc5f17ae1e56b3d727137f1 100644
--- a/src/lib-sieve/sieve-match-types.c
+++ b/src/lib-sieve/sieve-match-types.c
@@ -323,26 +323,36 @@ static const struct sieve_extension_obj_registry *
 	return &(ext->match_types);
 }
 
-const struct sieve_match_type *sieve_opr_match_type_read
+static inline const struct sieve_match_type *sieve_match_type_read
   (struct sieve_binary *sbin, sieve_size_t *address)
 {
-	const struct sieve_operand *operand = sieve_operand_read(sbin, address);
+	return sieve_extension_read_obj
+		(struct sieve_match_type, sbin, address, &mtch_default_reg, 
+			sieve_match_type_registry_get);
+}
+
+const struct sieve_match_type *sieve_opr_match_type_read
+  (const struct sieve_runtime_env *renv, sieve_size_t *address)
+{
+	const struct sieve_operand *operand = sieve_operand_read(renv->sbin, address);
 	
 	if ( operand == NULL || operand->class != &match_type_class ) 
 		return NULL;
 
-	return sieve_extension_read_obj
-		(struct sieve_match_type, sbin, address, &mtch_default_reg, 
-			sieve_match_type_registry_get);
+	return sieve_match_type_read(renv->sbin, address);
 }
 
 bool sieve_opr_match_type_dump
 (const struct sieve_dumptime_env *denv, sieve_size_t *address)
 {
+	const struct sieve_operand *operand = sieve_operand_read(denv->sbin, address);
 	const struct sieve_match_type *mtch;
+	
+	if ( operand == NULL || operand->class != &match_type_class ) 
+		return NULL;
 
 	sieve_code_mark(denv); 
-	mtch = sieve_opr_match_type_read(denv->sbin, address);
+	mtch = sieve_match_type_read(denv->sbin, address);
 	
 	if ( mtch == NULL )
 		return FALSE;
diff --git a/src/lib-sieve/sieve-match-types.h b/src/lib-sieve/sieve-match-types.h
index fc275f1188f969517e51466d2f5fe99ea18e534f..bf0265d871cf31f3f81e74997513991342af565f 100644
--- a/src/lib-sieve/sieve-match-types.h
+++ b/src/lib-sieve/sieve-match-types.h
@@ -99,7 +99,7 @@ extern const struct sieve_match_type *sieve_core_match_types[];
 extern const unsigned int sieve_core_match_types_count;
 
 const struct sieve_match_type *sieve_opr_match_type_read
-	(struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address);
 bool sieve_opr_match_type_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address);
 		
diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c
index 9040e10a3691ebc75c8e55bf4034746d9e69e55a..fadb704776933c935c79ef9bacbd8f05b43f5440 100644
--- a/src/lib-sieve/tst-address.c
+++ b/src/lib-sieve/tst-address.c
@@ -146,19 +146,19 @@ static bool tst_address_operation_execute
 	printf("?? ADDRESS\n");
 
 	if ( !sieve_addrmatch_default_get_optionals
-		(renv->sbin, address, &addrp, &mtch, &cmp) )
+		(renv, address, &addrp, &mtch, &cmp) )
 		return FALSE; 
 
 	t_push();
 		
 	/* Read header-list */
-	if ( (hdr_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (hdr_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
 	
 	/* Read key-list */
-	if ( (key_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/tst-exists.c b/src/lib-sieve/tst-exists.c
index 149f9c94e656ac82e44d14e648c52a9917908471..a2cc385549f2084d36bf91662ff5a5735a1927dd 100644
--- a/src/lib-sieve/tst-exists.c
+++ b/src/lib-sieve/tst-exists.c
@@ -108,7 +108,7 @@ static bool tst_exists_operation_execute
 	t_push();
 		
 	/* Read header-list */
-	if ( (hdr_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (hdr_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/tst-header.c b/src/lib-sieve/tst-header.c
index d74f40527e9cf84356ddfe8ad75b1e84550699fe..020cc914f7379d8a610b1e2bfaebd72da1dcad80 100644
--- a/src/lib-sieve/tst-header.c
+++ b/src/lib-sieve/tst-header.c
@@ -178,10 +178,10 @@ static bool tst_header_operation_execute
 			case 0: 
 				break;
 			case OPT_COMPARATOR:
-				cmp = sieve_opr_comparator_read(renv->sbin, address);
+				cmp = sieve_opr_comparator_read(renv, address);
 				break;
 			case OPT_MATCH_TYPE:
-				mtch = sieve_opr_match_type_read(renv->sbin, address);
+				mtch = sieve_opr_match_type_read(renv, address);
 				break;
 			default:
 				return FALSE;
@@ -192,13 +192,13 @@ static bool tst_header_operation_execute
 	t_push();
 		
 	/* Read header-list */
-	if ( (hdr_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (hdr_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
 	
 	/* Read key-list */
-	if ( (key_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+	if ( (key_list=sieve_opr_stringlist_read(renv, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/tst-size.c b/src/lib-sieve/tst-size.c
index 4f4656ead05115ba37f4ddd90eff73f67769d219..8efb6a852c9e2838d7d18aa09d7c6aaa84822b4e 100644
--- a/src/lib-sieve/tst-size.c
+++ b/src/lib-sieve/tst-size.c
@@ -215,7 +215,7 @@ static bool tst_size_operation_execute
 	
 	printf("%s\n", op->mnemonic);
 	
-	if ( !sieve_opr_number_read(renv->sbin, address, &limit) ) 
+	if ( !sieve_opr_number_read(renv, address, &limit) ) 
 		return FALSE;	
 	
 	if ( !tst_size_get(renv, &mail_size) )