From 4d14341a2ab04b5efd42d327e7931a3911366c36 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Sat, 24 Nov 2007 15:37:12 +0100
Subject: [PATCH] Grouped runtime parameters into a single runtime environment
 and started implementation of result composition/execution.

---
 src/lib-sieve/cmd-redirect.c                  |  18 +--
 src/lib-sieve/ext-envelope.c                  |  34 ++---
 src/lib-sieve/ext-fileinto.c                  |  19 +--
 src/lib-sieve/ext-reject.c                    |  22 ++-
 src/lib-sieve/plugins/imapflags/cmd-addflag.c |  13 +-
 .../plugins/imapflags/cmd-removeflag.c        |  13 +-
 src/lib-sieve/plugins/imapflags/cmd-setflag.c |  13 +-
 .../plugins/imapflags/ext-imapflags-common.c  |   5 +-
 .../plugins/imapflags/ext-imapflags-common.h  |   4 +-
 src/lib-sieve/plugins/imapflags/tst-hasflag.c |  44 +++---
 src/lib-sieve/plugins/vacation/ext-vacation.c |  42 +++---
 src/lib-sieve/sieve-address-parts.c           |  47 +++---
 src/lib-sieve/sieve-address-parts.h           |  13 +-
 src/lib-sieve/sieve-binary.c                  |   2 +-
 src/lib-sieve/sieve-code.c                    |  60 +++-----
 src/lib-sieve/sieve-code.h                    |  15 +-
 src/lib-sieve/sieve-commands.c                |  30 ++--
 src/lib-sieve/sieve-common.h                  |   1 +
 src/lib-sieve/sieve-comparators.c             |  20 ++-
 src/lib-sieve/sieve-comparators.h             |   6 +-
 src/lib-sieve/sieve-interpreter.c             | 140 +++++++++---------
 src/lib-sieve/sieve-interpreter.h             |  42 +++---
 src/lib-sieve/sieve-match-types.c             |  18 +--
 src/lib-sieve/sieve-match-types.h             |   6 +-
 src/lib-sieve/sieve-result.c                  |  31 +++-
 src/lib-sieve/sieve-result.h                  |   7 +-
 src/lib-sieve/sieve.c                         |  10 +-
 src/lib-sieve/tst-address.c                   |  36 +++--
 src/lib-sieve/tst-exists.c                    |  25 ++--
 src/lib-sieve/tst-header.c                    |  45 +++---
 src/lib-sieve/tst-size.c                      |  30 ++--
 31 files changed, 393 insertions(+), 418 deletions(-)

diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index 071a6480c..157f2d0ea 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -9,13 +9,11 @@
 /* Forward declarations */
 
 static bool cmd_redirect_opcode_dump
-	(const struct sieve_opcode *opcode, 
-		struct sieve_interpreter *interp ATTR_UNUSED, struct sieve_binary *sbin, 
-		sieve_size_t *address);
+	(const struct sieve_opcode *opcode,
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool cmd_redirect_opcode_execute
 	(const struct sieve_opcode *opcode, 
-		struct sieve_interpreter *interp ATTR_UNUSED, struct sieve_binary *sbin, 
-		sieve_size_t *address);
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 static bool cmd_redirect_validate
 	(struct sieve_validator *validator, struct sieve_command_context *cmd);
@@ -87,13 +85,12 @@ static bool cmd_redirect_generate
  
 static bool cmd_redirect_opcode_dump
 (const struct sieve_opcode *opcode ATTR_UNUSED,
-	struct sieve_interpreter *interp ATTR_UNUSED, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	printf("REDIRECT\n");
 
 	return 
-		sieve_opr_string_dump(sbin, address);
+		sieve_opr_string_dump(renv->sbin, address);
 }
 
 /*
@@ -102,14 +99,13 @@ static bool cmd_redirect_opcode_dump
 
 static bool cmd_redirect_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
-	struct sieve_interpreter *interp ATTR_UNUSED, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	string_t *redirect;
 
 	t_push();
 
-	if ( !sieve_opr_string_read(sbin, address, &redirect) ) {
+	if ( !sieve_opr_string_read(renv->sbin, address, &redirect) ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c
index ed5548adc..dad3a8616 100644
--- a/src/lib-sieve/ext-envelope.c
+++ b/src/lib-sieve/ext-envelope.c
@@ -29,11 +29,11 @@ static bool ext_envelope_load(int ext_id);
 static bool ext_envelope_validator_load(struct sieve_validator *validator);
 
 static bool ext_envelope_opcode_dump
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool ext_envelope_opcode_execute
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode,
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 static bool tst_envelope_registered
 	(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg);
@@ -163,22 +163,21 @@ static bool tst_envelope_generate
  
 static bool ext_envelope_opcode_dump
 (const struct sieve_opcode *opcode ATTR_UNUSED, 
-	struct sieve_interpreter *interp, struct sieve_binary *sbin, 
-	sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	printf("ENVELOPE\n");
 
 	/* Handle any optional arguments */
-	if ( !sieve_addrmatch_default_dump_optionals(interp, sbin, address) )
+	if ( !sieve_addrmatch_default_dump_optionals(renv, address) )
 		return FALSE;
 
 	return
-		sieve_opr_stringlist_dump(sbin, address) &&
-		sieve_opr_stringlist_dump(sbin, address);
+		sieve_opr_stringlist_dump(renv->sbin, address) &&
+		sieve_opr_stringlist_dump(renv->sbin, address);
 }
 
 static int ext_envelope_get_fields
-(struct sieve_message_data *msgdata, const char *field, 
+(const struct sieve_message_data *msgdata, const char *field, 
 	const char *const **value_r) 
 {
 	const char *value;
@@ -204,11 +203,8 @@ static int ext_envelope_get_fields
 
 static bool ext_envelope_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
-	struct sieve_interpreter *interp, struct sieve_binary *sbin, 
-	sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
-	struct sieve_message_data *msgdata = sieve_interpreter_get_msgdata(interp);
-
 	const struct sieve_comparator *cmp = &i_octet_comparator;
 	const struct sieve_match_type *mtch = &is_match_type;
 	const struct sieve_address_part *addrp = &all_address_part;
@@ -221,19 +217,19 @@ static bool ext_envelope_opcode_execute
 	printf("?? ENVELOPE\n");
 
 	if ( !sieve_addrmatch_default_get_optionals
-		(interp, sbin, address, &addrp, &mtch, &cmp) )
+		(renv, address, &addrp, &mtch, &cmp) )
 		return FALSE; 
 
 	t_push();
 		
 	/* Read header-list */
-	if ( (hdr_list=sieve_opr_stringlist_read(sbin, address)) == NULL ) {
+	if ( (hdr_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
 
 	/* Read key-list */
-	if ( (key_list=sieve_opr_stringlist_read(sbin, address)) == NULL ) {
+	if ( (key_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
@@ -247,7 +243,7 @@ static bool ext_envelope_opcode_execute
 	while ( !matched && sieve_coded_stringlist_next_item(hdr_list, &hdr_item) && hdr_item != NULL ) {
 		const char *const *fields;
 			
-		if ( ext_envelope_get_fields(msgdata, str_c(hdr_item), &fields) >= 0 ) {	
+		if ( ext_envelope_get_fields(renv->msgdata, str_c(hdr_item), &fields) >= 0 ) {	
 			
 			int i;
 			for ( i = 0; !matched && fields[i] != NULL; i++ ) {
@@ -261,7 +257,7 @@ static bool ext_envelope_opcode_execute
 
 	t_pop();
 	
-	sieve_interpreter_set_test_result(interp, matched);
+	sieve_interpreter_set_test_result(renv->interp, matched);
 	
 	return TRUE;
 }
diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c
index e6aee00b6..5cb29aa4a 100644
--- a/src/lib-sieve/ext-fileinto.c
+++ b/src/lib-sieve/ext-fileinto.c
@@ -23,11 +23,11 @@ static bool ext_fileinto_load(int ext_id);
 static bool ext_fileinto_validator_load(struct sieve_validator *validator);
 
 static bool ext_fileinto_opcode_dump
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool ext_fileinto_opcode_execute
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address); 
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address); 
 
 static bool cmd_fileinto_validate
 	(struct sieve_validator *validator, struct sieve_command_context *cmd);
@@ -128,13 +128,12 @@ static bool cmd_fileinto_generate
  
 static bool ext_fileinto_opcode_dump
 (const struct sieve_opcode *opcode ATTR_UNUSED,
-	struct sieve_interpreter *interp ATTR_UNUSED, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	printf("FILEINTO\n");
 
 	return 
-		sieve_opr_string_dump(sbin, address);
+		sieve_opr_string_dump(renv->sbin, address);
 }
 
 /*
@@ -143,15 +142,13 @@ static bool ext_fileinto_opcode_dump
 
 static bool ext_fileinto_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
-	struct sieve_interpreter *interp ATTR_UNUSED, 
-	struct sieve_binary *sbin, 
-	sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	string_t *folder;
 
 	t_push();
 
-	if ( !sieve_opr_string_read(sbin, address, &folder) ) {
+	if ( !sieve_opr_string_read(renv->sbin, address, &folder) ) {
 		t_pop();
 		return FALSE;
 	}
diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c
index 911b35376..509481b20 100644
--- a/src/lib-sieve/ext-reject.c
+++ b/src/lib-sieve/ext-reject.c
@@ -27,11 +27,11 @@ static bool cmd_reject_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx); 
 
 static bool ext_reject_opcode_dump
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool ext_reject_opcode_execute
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode,
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 /* Extension definitions */
 
@@ -128,14 +128,13 @@ static bool cmd_reject_generate
  */
  
 static bool ext_reject_opcode_dump
-	(const struct sieve_opcode *opcode ATTR_UNUSED,
-		struct sieve_interpreter *interp ATTR_UNUSED, struct sieve_binary *sbin, 
-		sieve_size_t *address)
+(const struct sieve_opcode *opcode ATTR_UNUSED,
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	printf("REJECT\n");
 	
 	return
-		sieve_opr_string_dump(sbin, address);
+		sieve_opr_string_dump(renv->sbin, address);
 }
 
 /*
@@ -143,15 +142,14 @@ static bool ext_reject_opcode_dump
  */
 
 static bool ext_reject_opcode_execute
-	(const struct sieve_opcode *opcode ATTR_UNUSED,
-		struct sieve_interpreter *interp ATTR_UNUSED, struct sieve_binary *sbin, 
-		sieve_size_t *address)
+(const struct sieve_opcode *opcode ATTR_UNUSED,
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	string_t *reason;
 
 	t_push();
 
-	if ( !sieve_opr_string_read(sbin, address, &reason) ) {
+	if ( !sieve_opr_string_read(renv->sbin, address, &reason) ) {
 		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 653c47afd..1a2c9b192 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-addflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-addflag.c
@@ -13,8 +13,8 @@ static bool cmd_addflag_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx);
 	
 static bool cmd_addflag_opcode_execute
-	(const struct sieve_opcode *opcode,	struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode,	
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 
 /* Addflag command 
@@ -66,8 +66,7 @@ static bool cmd_addflag_generate
 
 static bool cmd_addflag_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
-	struct sieve_interpreter *interp, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	string_t *flag_item;
 	struct sieve_coded_stringlist *flag_list;
@@ -77,7 +76,7 @@ static bool cmd_addflag_opcode_execute
 	t_push();
 		
 	/* Read header-list */
-	if ( (flag_list=sieve_opr_stringlist_read(sbin, address)) == NULL ) {
+	if ( (flag_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
@@ -85,12 +84,12 @@ static bool cmd_addflag_opcode_execute
 	/* Iterate through all requested headers to match */
 	while ( sieve_coded_stringlist_next_item(flag_list, &flag_item) && 
 		flag_item != NULL ) {
-		ext_imapflags_add_flags(interp, flag_item);
+		ext_imapflags_add_flags(renv->interp, flag_item);
 	}
 
 	t_pop();
 	
-	printf("  FLAGS: %s\n", ext_imapflags_get_flags_string(interp));
+	printf("  FLAGS: %s\n", ext_imapflags_get_flags_string(renv->interp));
 	
 	return TRUE;
 }
diff --git a/src/lib-sieve/plugins/imapflags/cmd-removeflag.c b/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
index 9ced9f801..8f7268dc0 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
@@ -14,8 +14,8 @@ static bool cmd_removeflag_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx);
 
 static bool cmd_removeflag_opcode_execute
-	(const struct sieve_opcode *opcode,	struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode,	
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 /* Removeflag command 
  *
@@ -68,8 +68,7 @@ static bool cmd_removeflag_generate
 
 static bool cmd_removeflag_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
-	struct sieve_interpreter *interp, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	string_t *flag_item;
 	struct sieve_coded_stringlist *flag_list;
@@ -79,7 +78,7 @@ static bool cmd_removeflag_opcode_execute
 	t_push();
 		
 	/* Read header-list */
-	if ( (flag_list=sieve_opr_stringlist_read(sbin, address)) == NULL ) {
+	if ( (flag_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
@@ -87,12 +86,12 @@ static bool cmd_removeflag_opcode_execute
 	/* Iterate through all requested headers to match */
 	while ( sieve_coded_stringlist_next_item(flag_list, &flag_item) && 
 		flag_item != NULL ) {
-		ext_imapflags_remove_flags(interp, flag_item);
+		ext_imapflags_remove_flags(renv->interp, flag_item);
 	}
 
 	t_pop();
 	
-	printf("  FLAGS: %s\n", ext_imapflags_get_flags_string(interp));
+	printf("  FLAGS: %s\n", ext_imapflags_get_flags_string(renv->interp));
 	
 	return TRUE;
 }
diff --git a/src/lib-sieve/plugins/imapflags/cmd-setflag.c b/src/lib-sieve/plugins/imapflags/cmd-setflag.c
index 1f7d583ce..85ea7560e 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-setflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-setflag.c
@@ -13,8 +13,8 @@ static bool cmd_setflag_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx);
 
 static bool cmd_setflag_opcode_execute
-	(const struct sieve_opcode *opcode,	struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode,
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 /* Setflag command 
  *
@@ -65,8 +65,7 @@ static bool cmd_setflag_generate
 
 static bool cmd_setflag_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
-	struct sieve_interpreter *interp, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	string_t *flag_item;
 	struct sieve_coded_stringlist *flag_list;
@@ -76,7 +75,7 @@ static bool cmd_setflag_opcode_execute
 	t_push();
 		
 	/* Read header-list */
-	if ( (flag_list=sieve_opr_stringlist_read(sbin, address)) == NULL ) {
+	if ( (flag_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
@@ -84,12 +83,12 @@ static bool cmd_setflag_opcode_execute
 	/* Iterate through all requested headers to match */
 	while ( sieve_coded_stringlist_next_item(flag_list, &flag_item) && 
 		flag_item != NULL ) {
-		ext_imapflags_set_flags(interp, flag_item);
+		ext_imapflags_set_flags(renv->interp, flag_item);
 	}
 
 	t_pop();
 	
-	printf("  FLAGS: %s\n", ext_imapflags_get_flags_string(interp));
+	printf("  FLAGS: %s\n", ext_imapflags_get_flags_string(renv->interp));
 	
 	return TRUE;
 }
diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c
index 2ac7e819e..5f88019bc 100644
--- a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c
+++ b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.c
@@ -81,13 +81,12 @@ bool ext_imapflags_command_validate
 
 bool ext_imapflags_command_opcode_dump
 (const struct sieve_opcode *opcode,
-	struct sieve_interpreter *interp ATTR_UNUSED, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	printf("%s\n", opcode->mnemonic);
 
 	return 
-		sieve_opr_stringlist_dump(sbin, address);
+		sieve_opr_stringlist_dump(renv->sbin, address);
 }
 
 /* Context access */
diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h
index b1fc5dd2b..087e3ec20 100644
--- a/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h
+++ b/src/lib-sieve/plugins/imapflags/ext-imapflags-common.h
@@ -21,8 +21,8 @@ bool ext_imapflags_command_validate
 	(struct sieve_validator *validator, struct sieve_command_context *cmd);
 
 bool ext_imapflags_command_opcode_dump
-(const struct sieve_opcode *opcode,	struct sieve_interpreter *interp, 
-	struct sieve_binary *sbin, sieve_size_t *address);
+(const struct sieve_opcode *opcode,	
+	const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 /* Flag registration */
 
diff --git a/src/lib-sieve/plugins/imapflags/tst-hasflag.c b/src/lib-sieve/plugins/imapflags/tst-hasflag.c
index 120a89c78..79a4f7985 100644
--- a/src/lib-sieve/plugins/imapflags/tst-hasflag.c
+++ b/src/lib-sieve/plugins/imapflags/tst-hasflag.c
@@ -20,11 +20,11 @@ static bool tst_hasflag_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx);
 
 static bool tst_hasflag_opcode_dump
-	(const struct sieve_opcode *opcode,	struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode,	
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool tst_hasflag_opcode_execute
-	(const struct sieve_opcode *opcode,	struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode,	
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 /* Hasflag test
  *
@@ -140,7 +140,9 @@ static bool tst_hasflag_validate
 	return TRUE;
 }
 
-/* Code generation */
+/*
+ * Code generation 
+ */
 
 static bool tst_hasflag_generate
 	(struct sieve_generator *generator,	struct sieve_command_context *ctx)
@@ -160,23 +162,22 @@ static bool tst_hasflag_generate
  */
  
 static bool tst_hasflag_opcode_dump
-	(const struct sieve_opcode *opcode ATTR_UNUSED,	
-		struct sieve_interpreter *interp, struct sieve_binary *sbin, 
-		sieve_size_t *address)
+(const struct sieve_opcode *opcode ATTR_UNUSED,	
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	unsigned int opt_code;
 
 	printf("HASFLAG\n");
 
 	/* Handle any optional arguments */
-	if ( sieve_operand_optional_present(sbin, address) ) {
-		while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) {
+	if ( sieve_operand_optional_present(renv->sbin, address) ) {
+		while ( (opt_code=sieve_operand_optional_read(renv->sbin, address)) ) {
 			switch ( opt_code ) {
 			case OPT_COMPARATOR:
-				sieve_opr_comparator_dump(interp, sbin, address);
+				sieve_opr_comparator_dump(renv, address);
 				break;
 			case OPT_MATCH_TYPE:
-				sieve_opr_match_type_dump(interp, sbin, address);
+				sieve_opr_match_type_dump(renv, address);
 				break;
 			default: 
 				return FALSE;
@@ -185,7 +186,7 @@ static bool tst_hasflag_opcode_dump
 	}
 
 	return
-		sieve_opr_stringlist_dump(sbin, address);
+		sieve_opr_stringlist_dump(renv->sbin, address);
 }
 
 /*
@@ -194,8 +195,7 @@ static bool tst_hasflag_opcode_dump
 
 static bool tst_hasflag_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
-	struct sieve_interpreter *interp ATTR_UNUSED, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	unsigned int opt_code;
 	const struct sieve_comparator *cmp = &i_ascii_casemap_comparator;
@@ -209,14 +209,14 @@ static bool tst_hasflag_opcode_execute
 	printf("?? HASFLAG\n");
 
 	/* Handle any optional arguments */
-	if ( sieve_operand_optional_present(sbin, address) ) {
-		while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) {
+	if ( sieve_operand_optional_present(renv->sbin, address) ) {
+		while ( (opt_code=sieve_operand_optional_read(renv->sbin, address)) ) {
 			switch ( opt_code ) {
 			case OPT_COMPARATOR:
-				cmp = sieve_opr_comparator_read(interp, sbin, address);
+				cmp = sieve_opr_comparator_read(renv, address);
 				break;
 			case OPT_MATCH_TYPE:
-				mtch = sieve_opr_match_type_read(interp, sbin, address);
+				mtch = sieve_opr_match_type_read(renv, address);
 				break;
 			default:
 				return FALSE;
@@ -227,7 +227,7 @@ static bool tst_hasflag_opcode_execute
 	t_push();
 		
 	/* Read key-list */
-	if ( (key_list=sieve_opr_stringlist_read(sbin, address)) == NULL ) {
+	if ( (key_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
@@ -235,7 +235,7 @@ static bool tst_hasflag_opcode_execute
 	matched = FALSE;
 	mctx = sieve_match_begin(mtch, cmp, key_list); 	
 
-	ext_imapflags_get_flags_init(&iter, interp);
+	ext_imapflags_get_flags_init(&iter, renv->interp);
 	
 	while ( (flag=ext_imapflags_iter_get_flag(&iter)) != NULL ) {
 		if ( sieve_match_value(mctx, flag) )
@@ -246,7 +246,7 @@ static bool tst_hasflag_opcode_execute
 	
 	t_pop();
 	
-	sieve_interpreter_set_test_result(interp, matched);
+	sieve_interpreter_set_test_result(renv->interp, matched);
 	
 	return TRUE;
 }
diff --git a/src/lib-sieve/plugins/vacation/ext-vacation.c b/src/lib-sieve/plugins/vacation/ext-vacation.c
index 50cf71429..3da21bc8f 100644
--- a/src/lib-sieve/plugins/vacation/ext-vacation.c
+++ b/src/lib-sieve/plugins/vacation/ext-vacation.c
@@ -26,11 +26,11 @@ static bool ext_vacation_load(int ext_id);
 static bool ext_vacation_validator_load(struct sieve_validator *validator);
 
 static bool ext_vacation_opcode_dump
-	(const struct sieve_opcode *opcode,	struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode,	
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool ext_vacation_opcode_execute
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 static bool cmd_vacation_registered
 	(struct sieve_validator *validator, struct sieve_command_registration *cmd_reg);
@@ -291,28 +291,27 @@ static bool cmd_vacation_generate
  
 static bool ext_vacation_opcode_dump
 (const struct sieve_opcode *opcode ATTR_UNUSED,
-	struct sieve_interpreter *interp ATTR_UNUSED, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {	
 	unsigned int opt_code;
 	
 	printf("VACATION\n");
 	
-	if ( sieve_operand_optional_present(sbin, address) ) {
-		while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) {
+	if ( sieve_operand_optional_present(renv->sbin, address) ) {
+		while ( (opt_code=sieve_operand_optional_read(renv->sbin, address)) ) {
 			switch ( opt_code ) {
 			case OPT_DAYS:
-				if ( !sieve_opr_number_dump(sbin, address) )
+				if ( !sieve_opr_number_dump(renv->sbin, address) )
 					return FALSE;
 				break;
 			case OPT_SUBJECT:
 			case OPT_FROM:
 			case OPT_HANDLE: 
-				if ( !sieve_opr_string_dump(sbin, address) )
+				if ( !sieve_opr_string_dump(renv->sbin, address) )
 					return FALSE;
 				break;
 			case OPT_ADDRESSES:
-				if ( !sieve_opr_stringlist_dump(sbin, address) )
+				if ( !sieve_opr_stringlist_dump(renv->sbin, address) )
 					return FALSE;
 				break;
 			case OPT_MIME:
@@ -324,7 +323,7 @@ static bool ext_vacation_opcode_dump
 		}
 	}
 	
-	return sieve_opr_string_dump(sbin, address);
+	return sieve_opr_string_dump(renv->sbin, address);
 }
 
 /* 
@@ -333,30 +332,29 @@ static bool ext_vacation_opcode_dump
  
 static bool ext_vacation_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
-	struct sieve_interpreter *interp ATTR_UNUSED, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {	
 	unsigned int opt_code;
 	sieve_size_t days = 0;
 	string_t *reason, *subject, *from, *handle;
 		
-	if ( sieve_operand_optional_present(sbin, address) ) {
-		while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) {
+	if ( sieve_operand_optional_present(renv->sbin, address) ) {
+		while ( (opt_code=sieve_operand_optional_read(renv->sbin, address)) ) {
 			switch ( opt_code ) {
 			case OPT_DAYS:
-				if ( !sieve_opr_number_read(sbin, address, &days) ) return FALSE;
+				if ( !sieve_opr_number_read(renv->sbin, address, &days) ) return FALSE;
 				break;
 			case OPT_SUBJECT:
-				if ( !sieve_opr_string_read(sbin, address, &subject) ) return FALSE;
+				if ( !sieve_opr_string_read(renv->sbin, address, &subject) ) return FALSE;
 				break;
 			case OPT_FROM:
-				if ( !sieve_opr_string_read(sbin, address, &from) ) return FALSE;
+				if ( !sieve_opr_string_read(renv->sbin, address, &from) ) return FALSE;
 				break;
 			case OPT_HANDLE: 
-				if ( !sieve_opr_string_read(sbin, address, &handle) ) return FALSE;
+				if ( !sieve_opr_string_read(renv->sbin, address, &handle) ) return FALSE;
 				break;
 			case OPT_ADDRESSES:
-				if ( sieve_opr_stringlist_read(sbin, address) == NULL ) return FALSE;
+				if ( sieve_opr_stringlist_read(renv->sbin, address) == NULL ) return FALSE;
 				break;
 			case OPT_MIME:
 				break;
@@ -366,7 +364,7 @@ static bool ext_vacation_opcode_execute
 		}
 	}
 	
-	if ( !sieve_opr_string_read(sbin, address, &reason) ) 
+	if ( !sieve_opr_string_read(renv->sbin, address, &reason) ) 
 		return FALSE;
 	
 	printf(">> VACATION \"%s\"\n", str_c(reason));
diff --git a/src/lib-sieve/sieve-address-parts.c b/src/lib-sieve/sieve-address-parts.c
index 6858a271a..6274a99d7 100644
--- a/src/lib-sieve/sieve-address-parts.c
+++ b/src/lib-sieve/sieve-address-parts.c
@@ -288,16 +288,15 @@ static void opr_address_part_emit_ext
 }
 
 const struct sieve_address_part *sieve_opr_address_part_read
-  (struct sieve_interpreter *interpreter, 
-		struct sieve_binary *sbin, sieve_size_t *address)
+(const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	unsigned int addrp_code;
-	const struct sieve_operand *operand = sieve_operand_read(sbin, address);
+	const struct sieve_operand *operand = sieve_operand_read(renv->sbin, address);
 	
 	if ( operand == NULL || operand->class != &address_part_class ) 
 		return NULL;
 	
-	if ( sieve_binary_read_byte(sbin, address, &addrp_code) ) {
+	if ( sieve_binary_read_byte(renv->sbin, address, &addrp_code) ) {
 		if ( addrp_code < SIEVE_ADDRESS_PART_CUSTOM ) {
 			if ( addrp_code < sieve_core_address_parts_count )
 				return sieve_core_address_parts[addrp_code];
@@ -307,18 +306,18 @@ const struct sieve_address_part *sieve_opr_address_part_read
 			int ext_id = -1;
 			const struct sieve_address_part_extension *ap_ext;
 
-			if ( sieve_binary_extension_get_by_index(sbin,
+			if ( sieve_binary_extension_get_by_index(renv->sbin,
 				addrp_code - SIEVE_ADDRESS_PART_CUSTOM, &ext_id) == NULL )
 				return NULL; 
 
-			ap_ext = sieve_address_part_extension_get(interpreter, ext_id); 
+			ap_ext = sieve_address_part_extension_get(renv->interp, ext_id); 
  
 			if ( ap_ext != NULL ) {  	
 				unsigned int code;
 				if ( ap_ext->address_part != NULL )
 					return ap_ext->address_part;
 		  	
-				if ( sieve_binary_read_byte(sbin, address, &code) &&
+				if ( sieve_binary_read_byte(renv->sbin, address, &code) &&
 					ap_ext->get_part != NULL )
 				return ap_ext->get_part(code);
 			} else {
@@ -331,12 +330,11 @@ const struct sieve_address_part *sieve_opr_address_part_read
 }
 
 bool sieve_opr_address_part_dump
-	(struct sieve_interpreter *interpreter,
-		struct sieve_binary *sbin, sieve_size_t *address)
+(const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	sieve_size_t pc = *address;
 	const struct sieve_address_part *addrp = 
-		sieve_opr_address_part_read(interpreter, sbin, address);
+		sieve_opr_address_part_read(renv, address);
 	
 	if ( addrp == NULL )
 		return FALSE;
@@ -409,24 +407,23 @@ bool sieve_address_match
  */
  
 bool sieve_addrmatch_default_dump_optionals
-(struct sieve_interpreter *interp, 
-	struct sieve_binary *sbin, sieve_size_t *address) 
+(const struct sieve_runtime_env *renv, sieve_size_t *address) 
 {
 	unsigned int opt_code;
 	
-	if ( sieve_operand_optional_present(sbin, address) ) {
-		while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) {
+	if ( sieve_operand_optional_present(renv->sbin, address) ) {
+		while ( (opt_code=sieve_operand_optional_read(renv->sbin, address)) ) {
 			switch ( opt_code ) {
 			case SIEVE_AM_OPT_COMPARATOR:
-				if ( !sieve_opr_comparator_dump(interp, sbin, address) )
+				if ( !sieve_opr_comparator_dump(renv, address) )
 					return FALSE;
 				break;
 			case SIEVE_AM_OPT_MATCH_TYPE:
-				if ( !sieve_opr_match_type_dump(interp, sbin, address) )
+				if ( !sieve_opr_match_type_dump(renv, address) )
 					return FALSE;
 				break;
 			case SIEVE_AM_OPT_ADDRESS_PART:
-				if ( !sieve_opr_address_part_dump(interp, sbin, address) )
+				if ( !sieve_opr_address_part_dump(renv, address) )
 					return FALSE;
 				break;
 			default:
@@ -439,25 +436,25 @@ bool sieve_addrmatch_default_dump_optionals
 }
 
 bool sieve_addrmatch_default_get_optionals
-(struct sieve_interpreter *interp, struct sieve_binary *sbin, 
-	sieve_size_t *address, const struct sieve_address_part **addrp, 
-	const struct sieve_match_type **mtch, const struct sieve_comparator **cmp) 
+(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) 
 {
 	unsigned int opt_code;
 	
-	if ( sieve_operand_optional_present(sbin, address) ) {
-		while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) {
+	if ( sieve_operand_optional_present(renv->sbin, address) ) {
+		while ( (opt_code=sieve_operand_optional_read(renv->sbin, address)) ) {
 			switch ( opt_code ) {
 			case SIEVE_AM_OPT_COMPARATOR:
-				if ( (*cmp = sieve_opr_comparator_read(interp, 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(interp, 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(interp, 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 728023138..253bc51e4 100644
--- a/src/lib-sieve/sieve-address-parts.h
+++ b/src/lib-sieve/sieve-address-parts.h
@@ -61,11 +61,9 @@ 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_interpreter *interpreter, 
-  	struct sieve_binary *sbin, sieve_size_t *address);
+ 	(const struct sieve_runtime_env *renv, sieve_size_t *address);
 bool sieve_opr_address_part_dump
-	(struct sieve_interpreter *interpreter,
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 /* Match utility */
 
@@ -81,11 +79,10 @@ enum sieve_addrmatch_opt_operand {
 };
 
 bool sieve_addrmatch_default_dump_optionals
-(struct sieve_interpreter *interp, 
-	struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address);
 bool sieve_addrmatch_default_get_optionals
-	(struct sieve_interpreter *interp, struct sieve_binary *sbin, 
-		sieve_size_t *address, const struct sieve_address_part **addp, 
+	(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);
 
 #endif /* __SIEVE_ADDRESS_PARTS_H */
diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c
index febbc4891..1ba09a628 100644
--- a/src/lib-sieve/sieve-binary.c
+++ b/src/lib-sieve/sieve-binary.c
@@ -53,8 +53,8 @@ void sieve_binary_unref(struct sieve_binary **binary)
 {
 	if ( binary != NULL && *binary != NULL ) {
 		pool_unref(&((*binary)->pool));
-		*binary = NULL;
 	}
+	*binary = NULL;
 }
 
 inline sieve_size_t sieve_binary_get_code_size(struct sieve_binary *binary)
diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c
index e398b7978..378d700b3 100644
--- a/src/lib-sieve/sieve-code.c
+++ b/src/lib-sieve/sieve-code.c
@@ -606,18 +606,18 @@ const struct sieve_opcode *sieve_operation_read
 /* Declaration of opcodes defined in this file */
 
 static bool opc_jmp_dump
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 static bool opc_jmp_execute
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool opc_jmptrue_execute
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool opc_jmpfalse_execute
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 const struct sieve_opcode sieve_jmp_opcode = { 
 	"JMP",
@@ -679,15 +679,14 @@ const unsigned int sieve_opcode_count =
 
 /* Code dump for core commands */
 
-static bool opc_jmp_dump(
-	const struct sieve_opcode *opcode,
-	struct sieve_interpreter *interp ATTR_UNUSED, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+static bool opc_jmp_dump
+(const struct sieve_opcode *opcode,
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	unsigned int pc = *address;
 	int offset;
 	
-	if ( sieve_binary_read_offset(sbin, address, &offset) ) 
+	if ( sieve_binary_read_offset(renv->sbin, address, &offset) ) 
 		printf("%s %d [%08x]\n", opcode->mnemonic, offset, pc + offset);
 	else
 		return FALSE;
@@ -697,37 +696,24 @@ static bool opc_jmp_dump(
 			
 /* Code dump for trivial opcodes */
 
-bool sieve_opcode_trivial_dump
-(const struct sieve_opcode *opcode,
-	struct sieve_interpreter *interp ATTR_UNUSED, 
-	struct sieve_binary *sbin ATTR_UNUSED,sieve_size_t *address ATTR_UNUSED)
-{	
-	printf("%s\n", opcode->mnemonic);
-	
-	return TRUE;
-}
-
 bool sieve_opcode_string_dump
 (const struct sieve_opcode *opcode,
-	struct sieve_interpreter *interp ATTR_UNUSED, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	printf("%s\n", opcode->mnemonic);
 
 	return 
-		sieve_opr_string_dump(sbin, address);
+		sieve_opr_string_dump(renv->sbin, address);
 }
 
-
 /* Code execution for core commands */
 
 static bool opc_jmp_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED, 
-	struct sieve_interpreter *interp, struct sieve_binary *sbin ATTR_UNUSED, 
-	sieve_size_t *address ATTR_UNUSED) 
+	const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED) 
 {
 	printf("JMP\n");
-	if ( !sieve_interpreter_program_jump(interp, TRUE) )
+	if ( !sieve_interpreter_program_jump(renv->interp, TRUE) )
 		return FALSE;
 	
 	return TRUE;
@@ -735,11 +721,10 @@ static bool opc_jmp_execute
 		
 static bool opc_jmptrue_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED, 
-	struct sieve_interpreter *interp,	struct sieve_binary *sbin ATTR_UNUSED, 
-	sieve_size_t *address ATTR_UNUSED)
+	const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED)
 {	
-	if ( !sieve_interpreter_program_jump(interp,
-		sieve_interpreter_get_test_result(interp)) )
+	if ( !sieve_interpreter_program_jump(renv->interp,
+		sieve_interpreter_get_test_result(renv->interp)) )
 		return FALSE;
 		
 	printf("JMPTRUE\n");
@@ -749,11 +734,10 @@ static bool opc_jmptrue_execute
 
 static bool opc_jmpfalse_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED, 
-	struct sieve_interpreter *interp, struct sieve_binary *sbin ATTR_UNUSED, 
-	sieve_size_t *address ATTR_UNUSED)
+	const struct sieve_runtime_env *renv, sieve_size_t *address ATTR_UNUSED)
 {	
-	if ( !sieve_interpreter_program_jump(interp,
-		!sieve_interpreter_get_test_result(interp)) )
+	if ( !sieve_interpreter_program_jump(renv->interp,
+		!sieve_interpreter_get_test_result(renv->interp)) )
 		return FALSE;
 		
 	printf("JMPFALSE\n");
diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h
index 72d68e03e..95793020b 100644
--- a/src/lib-sieve/sieve-code.h
+++ b/src/lib-sieve/sieve-code.h
@@ -130,11 +130,11 @@ struct sieve_opcode {
 	unsigned int ext_code;
 	
 	bool (*dump)
-		(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-			struct sieve_binary *sbin, sieve_size_t *address);
+		(const struct sieve_opcode *opcode, 
+			const struct sieve_runtime_env *renv, sieve_size_t *address);
 	bool (*execute)
-		(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-			struct sieve_binary *sbin, sieve_size_t *address);
+		(const struct sieve_opcode *opcode, 
+			const struct sieve_runtime_env *renv, sieve_size_t *address);
 };
 
 extern const struct sieve_opcode *sieve_opcodes[];
@@ -151,12 +151,9 @@ inline sieve_size_t sieve_operation_emit_code_ext
 const struct sieve_opcode *sieve_operation_read
 	(struct sieve_binary *sbin, sieve_size_t *address);
 
-bool sieve_opcode_trivial_dump
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
 bool sieve_opcode_string_dump
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode,
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 /* Core operands */
 
diff --git a/src/lib-sieve/sieve-commands.c b/src/lib-sieve/sieve-commands.c
index dfec19e8c..3ac1ae015 100644
--- a/src/lib-sieve/sieve-commands.c
+++ b/src/lib-sieve/sieve-commands.c
@@ -271,21 +271,21 @@ inline bool sieve_command_block_exits_unconditionally
 /* Opcodes */
 
 static bool opc_stop_execute
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool opc_keep_execute
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool opc_discard_execute
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 const struct sieve_opcode cmd_stop_opcode = { 
 	"STOP",
 	SIEVE_OPCODE_STOP,
 	NULL,
 	0,
-	sieve_opcode_trivial_dump, 
+	NULL, 
 	opc_stop_execute 
 };
 
@@ -294,7 +294,7 @@ const struct sieve_opcode cmd_keep_opcode = {
 	SIEVE_OPCODE_KEEP,
 	NULL,
 	0,
-	sieve_opcode_trivial_dump, 
+	NULL, 
 	opc_keep_execute 
 };
 
@@ -303,26 +303,26 @@ const struct sieve_opcode cmd_discard_opcode = {
 	SIEVE_OPCODE_DISCARD,
 	NULL,
 	0,
-	sieve_opcode_trivial_dump, 
+	NULL, 
 	opc_discard_execute 
 };
 
 static bool opc_stop_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED, 
-	struct sieve_interpreter *interp, struct sieve_binary *sbin ATTR_UNUSED, 
+	const struct sieve_runtime_env *renv,  
 	sieve_size_t *address ATTR_UNUSED)
 {	
 	printf(">> STOP\n");
 	
-	sieve_interpreter_stop(interp);
+	sieve_interpreter_stop(renv->interp);
 
 	return TRUE;
 }
 
 static bool opc_keep_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
-	struct sieve_interpreter *interp ATTR_UNUSED, 	
-	struct sieve_binary *sbin ATTR_UNUSED, sieve_size_t *address ATTR_UNUSED)
+	const struct sieve_runtime_env *renv ATTR_UNUSED, 
+	sieve_size_t *address ATTR_UNUSED)
 {	
 	printf(">> KEEP\n");
 	
@@ -331,8 +331,8 @@ static bool opc_keep_execute
 
 static bool opc_discard_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
-	struct sieve_interpreter *interp ATTR_UNUSED, 
-	struct sieve_binary *sbin ATTR_UNUSED, sieve_size_t *address ATTR_UNUSED)
+	const struct sieve_runtime_env *renv ATTR_UNUSED, 
+	sieve_size_t *address ATTR_UNUSED)
 {	
 	printf(">> DISCARD\n");
 	
diff --git a/src/lib-sieve/sieve-common.h b/src/lib-sieve/sieve-common.h
index 03a6dad95..d428eb785 100644
--- a/src/lib-sieve/sieve-common.h
+++ b/src/lib-sieve/sieve-common.h
@@ -46,6 +46,7 @@ struct sieve_jumplist;
 struct sieve_generator;
 
 /* sieve-interpreter.h */
+struct sieve_runtime_env;
 struct sieve_interpreter;
 
 /* sieve-extension.h */
diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c
index 5a043a703..7cb799515 100644
--- a/src/lib-sieve/sieve-comparators.c
+++ b/src/lib-sieve/sieve-comparators.c
@@ -326,37 +326,36 @@ static void opr_comparator_emit_ext
 }
 
 const struct sieve_comparator *sieve_opr_comparator_read
-  (struct sieve_interpreter *interpreter, 
-  	struct sieve_binary *sbin, sieve_size_t *address)
+  (const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	unsigned int cmp_code;
-	const struct sieve_operand *operand = sieve_operand_read(sbin, address);
+	const struct sieve_operand *operand = sieve_operand_read(renv->sbin, address);
 	
 	if ( operand == NULL || operand->class != &comparator_class ) 
 		return NULL;
 	
-	if ( sieve_binary_read_byte(sbin, address, &cmp_code) ) {
+	if ( sieve_binary_read_byte(renv->sbin, address, &cmp_code) ) {
 		if ( cmp_code < SIEVE_COMPARATOR_CUSTOM ) {
 			if ( cmp_code < sieve_core_comparators_count )
 				return sieve_core_comparators[cmp_code];
 			else
 				return NULL;
 		} else {
-		  int ext_id = -1;
+			int ext_id = -1;
 			const struct sieve_comparator_extension *cmp_ext;
 
-			if ( sieve_binary_extension_get_by_index(sbin,
+			if ( sieve_binary_extension_get_by_index(renv->sbin,
 				cmp_code - SIEVE_COMPARATOR_CUSTOM, &ext_id) == NULL )
 				return NULL; 
 
-			cmp_ext = sieve_comparator_extension_get(interpreter, ext_id); 
+			cmp_ext = sieve_comparator_extension_get(renv->interp, ext_id); 
  
 			if ( cmp_ext != NULL ) {  	
 				unsigned int code;
 				if ( cmp_ext->comparator != NULL )
 					return cmp_ext->comparator;
 		  	
-				if ( sieve_binary_read_byte(sbin, address, &code) &&
+				if ( sieve_binary_read_byte(renv->sbin, address, &code) &&
 					cmp_ext->get_comparator != NULL )
 					return cmp_ext->get_comparator(code);
 			} else {
@@ -369,12 +368,11 @@ const struct sieve_comparator *sieve_opr_comparator_read
 }
 
 bool sieve_opr_comparator_dump
-	(struct sieve_interpreter *interpreter,
-		struct sieve_binary *sbin, sieve_size_t *address)
+	(const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	sieve_size_t pc = *address;
 	const struct sieve_comparator *cmp = 
-		sieve_opr_comparator_read(interpreter, sbin, address);
+		sieve_opr_comparator_read(renv, address);
 	
 	if ( cmp == NULL )
 		return FALSE;
diff --git a/src/lib-sieve/sieve-comparators.h b/src/lib-sieve/sieve-comparators.h
index 10b7c8290..51a4bfedc 100644
--- a/src/lib-sieve/sieve-comparators.h
+++ b/src/lib-sieve/sieve-comparators.h
@@ -71,11 +71,9 @@ const struct sieve_comparator *sieve_comparator_find
 		int *ext_id);
 
 const struct sieve_comparator *sieve_opr_comparator_read
-  (struct sieve_interpreter *interpreter, 
-  	struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address);
 bool sieve_opr_comparator_dump
-	(struct sieve_interpreter *interpreter,
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 void sieve_comparator_extension_set
 	(struct sieve_interpreter *interpreter, int ext_id,
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index 977f20263..9033e6ba9 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -18,23 +18,21 @@
 
 struct sieve_interpreter {
 	pool_t pool;
-	
-	struct sieve_binary *binary;
-		
+			
 	/* Object registries */
 	ARRAY_DEFINE(ext_contexts, void *); 
 		
 	/* Execution status */
-	sieve_size_t pc; 
-	bool test_result;
-	bool stopped;
 	
-	/* Execution environment */
-	struct sieve_result *result; 
-	struct sieve_message_data *msgdata;	
+	sieve_size_t pc;  /* Program counter */
+	bool stopped;     /* Explicit successful stop requested */
+	bool test_result; /* Result of previous test command */
+	
+	/* Runtime environment environment */
+	struct sieve_runtime_env runenv; 
 };
 
-struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *binary) 
+struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *sbin) 
 {
 	unsigned int i;
 	int idx;
@@ -44,10 +42,11 @@ struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *binary)
 	pool = pool_alloconly_create("sieve_interpreter", 4096);	
 	interp = p_new(pool, struct sieve_interpreter, 1);
 	interp->pool = pool;
+	interp->runenv.interp = interp;
 	
-	interp->binary = binary;
-	sieve_binary_ref(binary);
-	sieve_binary_commit(binary);
+	interp->runenv.sbin = sbin;
+	sieve_binary_ref(sbin);
+	sieve_binary_commit(sbin);
 	
 	interp->pc = 0;
 
@@ -62,9 +61,9 @@ struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *binary)
 	}
 
 	/* Load other extensions listed in the binary */
-	for ( idx = 0; idx < sieve_binary_extensions_count(binary); idx++ ) {
+	for ( idx = 0; idx < sieve_binary_extensions_count(sbin); idx++ ) {
 		const struct sieve_extension *ext = 
-			sieve_binary_extension_get_by_index(binary, idx, NULL);
+			sieve_binary_extension_get_by_index(sbin, idx, NULL);
 		
 		if ( ext->interpreter_load != NULL )
 			ext->interpreter_load(interp);
@@ -73,10 +72,10 @@ struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *binary)
 	return interp;
 }
 
-void sieve_interpreter_free(struct sieve_interpreter *interpreter) 
+void sieve_interpreter_free(struct sieve_interpreter *interp) 
 {
-	sieve_binary_unref(&interpreter->binary);
-	pool_unref(&(interpreter->pool));
+	sieve_binary_unref(&interp->runenv.sbin);
+	pool_unref(&(interp->pool));
 }
 
 inline pool_t sieve_interpreter_pool(struct sieve_interpreter *interp)
@@ -106,44 +105,41 @@ inline const void *sieve_interpreter_extension_get_context
 	return *ctx;
 }
 
-
-/* Accessing runtinme environment */
-
-inline struct sieve_message_data *
-	sieve_interpreter_get_msgdata(struct sieve_interpreter *interpreter) 
-{
-	return interpreter->msgdata;
-}
-
 /* Program counter */
 
-inline void sieve_interpreter_reset(struct sieve_interpreter *interpreter) 
+inline void sieve_interpreter_reset(struct sieve_interpreter *interp) 
 {
-	interpreter->pc = 0;
+	interp->pc = 0;
+	interp->stopped = FALSE;
+	interp->test_result = FALSE;
+	interp->runenv.msgdata = NULL;
+	interp->runenv.result = NULL;
 }
 
-inline void sieve_interpreter_stop(struct sieve_interpreter *interpreter)
+inline void sieve_interpreter_stop(struct sieve_interpreter *interp)
 {
-    interpreter->stopped = TRUE;
+	interp->stopped = TRUE;
 }
 
-inline sieve_size_t sieve_interpreter_program_counter(struct sieve_interpreter *interpreter)
+inline sieve_size_t sieve_interpreter_program_counter(struct sieve_interpreter *interp)
 {
-	return interpreter->pc;
+	return interp->pc;
 }
 
 inline bool sieve_interpreter_program_jump
-	(struct sieve_interpreter *interpreter, bool jump)
+	(struct sieve_interpreter *interp, bool jump)
 {
-	sieve_size_t pc = sieve_interpreter_program_counter(interpreter);
+	sieve_size_t pc = interp->pc;
 	int offset;
 	
-	if ( !sieve_interpreter_read_offset_operand(interpreter, &offset) )
+	if ( !sieve_interpreter_read_offset_operand(interp, &offset) )
 		return FALSE;
 
-	if ( pc + offset <= sieve_binary_get_code_size(interpreter->binary) && pc + offset > 0 ) {
+	if ( pc + offset <= sieve_binary_get_code_size(interp->runenv.sbin) && 
+		pc + offset > 0 ) 
+	{	
 		if ( jump )
-			interpreter->pc = pc + offset;
+			interp->pc = pc + offset;
 		
 		return TRUE;
 	}
@@ -151,27 +147,24 @@ inline bool sieve_interpreter_program_jump
 	return FALSE;
 }
 
-inline void sieve_interpreter_set_test_result(struct sieve_interpreter *interpreter, bool result)
-{
-	interpreter->test_result = result;
-}
-
-inline bool sieve_interpreter_get_test_result(struct sieve_interpreter *interpreter)
+inline void sieve_interpreter_set_test_result
+	(struct sieve_interpreter *interp, bool result)
 {
-	return interpreter->test_result;
+	interp->test_result = result;
 }
 
-inline struct sieve_binary *sieve_interpreter_get_binary(struct sieve_interpreter *interp)
+inline bool sieve_interpreter_get_test_result
+	(struct sieve_interpreter *interp)
 {
-	return interp->binary;
+	return interp->test_result;
 }
 
 /* Opcodes and operands */
 
 bool sieve_interpreter_read_offset_operand
-	(struct sieve_interpreter *interpreter, int *offset) 
+	(struct sieve_interpreter *interp, int *offset) 
 {
-	return sieve_binary_read_offset(interpreter->binary, &(interpreter->pc), offset);
+	return sieve_binary_read_offset(interp->runenv.sbin, &(interp->pc), offset);
 }
  
 /* Code Dump */
@@ -180,13 +173,13 @@ static bool sieve_interpreter_dump_operation
 	(struct sieve_interpreter *interp) 
 {
 	const struct sieve_opcode *opcode = 
-		sieve_operation_read(interp->binary, &(interp->pc));
+		sieve_operation_read(interp->runenv.sbin, &(interp->pc));
 
 	if ( opcode != NULL ) {
 		printf("%08x: ", interp->pc-1);
 	
 		if ( opcode->dump != NULL )
-			return opcode->dump(opcode, interp, interp->binary, &(interp->pc));
+			return opcode->dump(opcode, &(interp->runenv), &(interp->pc));
 		else if ( opcode->mnemonic != NULL )
 			printf("%s\n", opcode->mnemonic);
 		else
@@ -198,21 +191,23 @@ static bool sieve_interpreter_dump_operation
 	return FALSE;
 }
 
-void sieve_interpreter_dump_code(struct sieve_interpreter *interpreter) 
+void sieve_interpreter_dump_code(struct sieve_interpreter *interp) 
 {
-	sieve_interpreter_reset(interpreter);
+	sieve_interpreter_reset(interp);
 	
-	interpreter->result = NULL;
-	interpreter->msgdata = NULL;
+	interp->runenv.result = NULL;
+	interp->runenv.msgdata = NULL;
 	
-	while ( interpreter->pc < sieve_binary_get_code_size(interpreter->binary) ) {
-		if ( !sieve_interpreter_dump_operation(interpreter) ) {
+	while ( interp->pc < 
+		sieve_binary_get_code_size(interp->runenv.sbin) ) {
+		if ( !sieve_interpreter_dump_operation(interp) ) {
 			printf("Binary is corrupt.\n");
 			return;
 		}
 	}
 	
-	printf("%08x: [End of code]\n", sieve_binary_get_code_size(interpreter->binary));	
+	printf("%08x: [End of code]\n", 
+		sieve_binary_get_code_size(interp->runenv.sbin));	
 }
 
 /* Code execute */
@@ -220,11 +215,12 @@ void sieve_interpreter_dump_code(struct sieve_interpreter *interpreter)
 bool sieve_interpreter_execute_operation
 	(struct sieve_interpreter *interp) 
 {
-	const struct sieve_opcode *opcode = sieve_operation_read(interp->binary, &(interp->pc));
+	const struct sieve_opcode *opcode = 
+		sieve_operation_read(interp->runenv.sbin, &(interp->pc));
 
 	if ( opcode != NULL ) {
 		if ( opcode->execute != NULL )
-			return opcode->execute(opcode, interp, interp->binary, &(interp->pc));
+			return opcode->execute(opcode, &(interp->runenv), &(interp->pc));
 		else
 			return FALSE;
 			
@@ -234,29 +230,33 @@ bool sieve_interpreter_execute_operation
 	return FALSE;
 }		
 
-struct sieve_result *sieve_interpreter_run
-	(struct sieve_interpreter *interp, struct sieve_message_data *msgdata) 
+bool sieve_interpreter_run
+(struct sieve_interpreter *interp, struct sieve_message_data *msgdata,
+	struct sieve_result *result) 
 {
-	struct sieve_result *result;
 	sieve_interpreter_reset(interp);
 	
-	result = sieve_result_create();
-	interp->result = result;
-	interp->msgdata = msgdata;
+	interp->runenv.msgdata = msgdata;
+	interp->runenv.result = result;		
+	sieve_result_ref(result);
 	
 	while ( !interp->stopped && 
-		interp->pc < sieve_binary_get_code_size(interp->binary) ) {
+		interp->pc < sieve_binary_get_code_size(interp->runenv.sbin) ) {
 		printf("%08x: ", interp->pc);
 		
 		if ( !sieve_interpreter_execute_operation(interp) ) {
 			printf("Execution aborted.\n");
-			return NULL;
+			sieve_result_unref(&result);
+			return FALSE;
 		}
 	}
 	
-	interp->result = NULL;
+	interp->runenv.result = NULL;
+	interp->runenv.msgdata = NULL;
 	
-	return result;
+	sieve_result_unref(&result);
+
+	return TRUE;
 }
 
 
diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h
index 24a0bbcd8..0f0f5fee6 100644
--- a/src/lib-sieve/sieve-interpreter.h
+++ b/src/lib-sieve/sieve-interpreter.h
@@ -13,43 +13,42 @@
 
 struct sieve_interpreter;
 
-struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *binary);
-void sieve_interpreter_free(struct sieve_interpreter *interpreter);
+struct sieve_runtime_env {
+	struct sieve_interpreter *interp;
+	struct sieve_binary *sbin;
+	const struct sieve_message_data *msgdata;
+	struct sieve_result *result;
+};
+
+struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *sbin);
+void sieve_interpreter_free(struct sieve_interpreter *interp);
 inline pool_t sieve_interpreter_pool(struct sieve_interpreter *interp);
 
 inline void sieve_interpreter_reset
-	(struct sieve_interpreter *interpreter);
+	(struct sieve_interpreter *interp);
 inline void sieve_interpreter_stop
-	(struct sieve_interpreter *interpreter);
+	(struct sieve_interpreter *interp);
 inline sieve_size_t sieve_interpreter_program_counter
-	(struct sieve_interpreter *interpreter);
+	(struct sieve_interpreter *interp);
 inline bool sieve_interpreter_program_jump
-	(struct sieve_interpreter *interpreter, bool jump);
+	(struct sieve_interpreter *interp, bool jump);
 	
 inline void sieve_interpreter_set_test_result
-	(struct sieve_interpreter *interpreter, bool result);
+	(struct sieve_interpreter *interp, bool result);
 inline bool sieve_interpreter_get_test_result
-	(struct sieve_interpreter *interpreter);
-	
-inline struct sieve_binary *sieve_interpreter_get_binary
 	(struct sieve_interpreter *interp);
-
+	
 /* Extension support */
 
 inline void sieve_interpreter_extension_set_context
-	(struct sieve_interpreter *interpreter, int ext_id, void *context);
+	(struct sieve_interpreter *interp, int ext_id, void *context);
 inline const void *sieve_interpreter_extension_get_context
-	(struct sieve_interpreter *interpreter, int ext_id);
+	(struct sieve_interpreter *interp, int ext_id);
 	
 /* Opcodes and operands */
 
 bool sieve_interpreter_read_offset_operand
-	(struct sieve_interpreter *interpreter, int *offset);
-
-/* Accessing runtime information */
-
-inline struct sieve_message_data *
-	sieve_interpreter_get_msgdata(struct sieve_interpreter *interpreter);
+	(struct sieve_interpreter *interp, int *offset);
 
 /* Code dump (debugging purposes) */
 
@@ -58,8 +57,9 @@ void sieve_interpreter_dump_code(struct sieve_interpreter *interp);
 /* Code execute */
 
 bool sieve_interpreter_execute_operation(struct sieve_interpreter *interp); 
-struct sieve_result *sieve_interpreter_run
-	(struct sieve_interpreter *interp, struct sieve_message_data *message);
 
+bool sieve_interpreter_run
+(struct sieve_interpreter *interp, struct sieve_message_data *msgdata,
+	struct sieve_result *result);
 
 #endif /* __SIEVE_INTERPRETER_H */
diff --git a/src/lib-sieve/sieve-match-types.c b/src/lib-sieve/sieve-match-types.c
index e8c7a532c..3b7865d22 100644
--- a/src/lib-sieve/sieve-match-types.c
+++ b/src/lib-sieve/sieve-match-types.c
@@ -338,16 +338,15 @@ static void opr_match_type_emit_ext
 }
 
 const struct sieve_match_type *sieve_opr_match_type_read
-  (struct sieve_interpreter *interpreter, 
-		struct sieve_binary *sbin, sieve_size_t *address)
+  (const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	unsigned int mtch_code;
-	const struct sieve_operand *operand = sieve_operand_read(sbin, address);
+	const struct sieve_operand *operand = sieve_operand_read(renv->sbin, address);
 	
 	if ( operand == NULL || operand->class != &match_type_class ) 
 		return NULL;
 	
-	if ( sieve_binary_read_byte(sbin, address, &mtch_code) ) {
+	if ( sieve_binary_read_byte(renv->sbin, address, &mtch_code) ) {
 		if ( mtch_code < SIEVE_MATCH_TYPE_CUSTOM ) {
 			if ( mtch_code < sieve_core_match_types_count )
 				return sieve_core_match_types[mtch_code];
@@ -357,18 +356,18 @@ const struct sieve_match_type *sieve_opr_match_type_read
 			int ext_id = -1;
 			const struct sieve_match_type_extension *mtch_ext;
 
-			if ( sieve_binary_extension_get_by_index(sbin,
+			if ( sieve_binary_extension_get_by_index(renv->sbin,
 				mtch_code - SIEVE_MATCH_TYPE_CUSTOM, &ext_id) == NULL )
 				return NULL; 
 
-			mtch_ext = sieve_match_type_extension_get(interpreter, ext_id); 
+			mtch_ext = sieve_match_type_extension_get(renv->interp, ext_id); 
  
 			if ( mtch_ext != NULL ) {  	
 				unsigned int code;
 				if ( mtch_ext->match_type != NULL )
 					return mtch_ext->match_type;
 		  	
-				if ( sieve_binary_read_byte(sbin, address, &code) &&
+				if ( sieve_binary_read_byte(renv->sbin, address, &code) &&
 					mtch_ext->get_match != NULL )
 					return mtch_ext->get_match(code);
 			} else {
@@ -381,12 +380,11 @@ const struct sieve_match_type *sieve_opr_match_type_read
 }
 
 bool sieve_opr_match_type_dump
-	(struct sieve_interpreter *interpreter,
-		struct sieve_binary *sbin, sieve_size_t *address)
+(const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	sieve_size_t pc = *address;
 	const struct sieve_match_type *mtch = 
-		sieve_opr_match_type_read(interpreter, sbin, address);
+		sieve_opr_match_type_read(renv, 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 721b7129d..d3eee1a81 100644
--- a/src/lib-sieve/sieve-match-types.h
+++ b/src/lib-sieve/sieve-match-types.h
@@ -102,11 +102,9 @@ 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_interpreter *interpreter, 
-  	struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address);
 bool sieve_opr_match_type_dump
-	(struct sieve_interpreter *interpreter,
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_runtime_env *renv, sieve_size_t *address);
 		
 /* Match Utility */
 
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index fc463b9f6..15e34c851 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -36,11 +36,20 @@ struct sieve_result *sieve_result_create(void)
 	return result;
 }
 
-void sieve_result_free(struct sieve_result *result) 
+void sieve_result_ref(struct sieve_result *result) 
 {
-	pool_unref(&(result->pool));
+	pool_ref(result->pool);
 }
 
+void sieve_result_unref(struct sieve_result **result) 
+{
+	if ( result != NULL && *result != NULL ) {
+		pool_unref(&((*result)->pool));
+	}
+	*result = NULL;
+}
+
+
 void sieve_result_add_action
 	(struct sieve_result *result, struct sieve_action *action, void *context)		
 {
@@ -65,12 +74,28 @@ void sieve_result_add_action
 	}	
 }	
 
+bool sieve_result_dump(struct sieve_result *result)
+{
+	struct sieve_result_action *rac = result->first_action;
+	
+	while ( rac != NULL ) {
+		if ( rac->action->dump != NULL ) {
+			
+		} else {
+			printf("ACTION: %s (no further information)\n", rac->action->name); 
+		}
+		rac = rac->next;	
+	}
+	
+	return TRUE;
+}
+
 bool sieve_result_execute(struct sieve_result *result)
 {
 	struct sieve_result_action *raction = result->first_action;
 	
 	while ( raction != NULL ) {
-		if ( raction->action->perform != NULL ) {
+		if ( raction->action->execute != NULL ) {
 			
 		} else {
 			i_warning("Action %s performs absolutely nothing.", raction->action->name);	
diff --git a/src/lib-sieve/sieve-result.h b/src/lib-sieve/sieve-result.h
index 781439ca5..197a43108 100644
--- a/src/lib-sieve/sieve-result.h
+++ b/src/lib-sieve/sieve-result.h
@@ -8,18 +8,21 @@ struct sieve_result;
 struct sieve_action {
 	const char *name;
 
-	int (*perform)
+	int (*execute)
 		(struct sieve_interpreter *interpreter, struct sieve_result *result, void *context);	
 	int (*dump)
 		(struct sieve_interpreter *interpreter, struct sieve_result *result, void *context);	
 };
 
 struct sieve_result *sieve_result_create(void);
-void sieve_result_free(struct sieve_result *result);
+void sieve_result_ref(struct sieve_result *result); 
+void sieve_result_unref(struct sieve_result **result); 
 
 void sieve_result_add_action
 	(struct sieve_result *result, struct sieve_action *action, void *context);		
 
+bool sieve_result_dump(struct sieve_result *result);
+
 bool sieve_result_execute(struct sieve_result *result);
 
 #endif
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index 1416ee269..9c0d4eb76 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -4,8 +4,12 @@
 #include "buffer.h"
 
 #include "sieve-extensions.h"
-#include "sieve-parser.h"
+
 #include "sieve-ast.h"
+#include "sieve-binary.h"
+#include "sieve-result.h"
+
+#include "sieve-parser.h"
 #include "sieve-validator.h"
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
@@ -142,16 +146,18 @@ void sieve_dump(struct sieve_binary *binary)
 bool sieve_execute
 	(struct sieve_binary *binary, struct sieve_message_data *msgdata) 
 {
+	struct sieve_result *sres = sieve_result_create();
 	struct sieve_interpreter *interpreter = sieve_interpreter_create(binary);			
 	bool result = TRUE;
 							
 	printf("Code Execute:\n\n");
-	if ( sieve_interpreter_run(interpreter, msgdata) == NULL ) {
+	if ( !sieve_interpreter_run(interpreter, msgdata, sres) ) {
 		result = FALSE;
 	}
 				
 	sieve_interpreter_free(interpreter);
 	
+	sieve_result_unref(&sres);
 	return result;
 }
 	
diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c
index ee7c5ba68..8c36d3df6 100644
--- a/src/lib-sieve/tst-address.c
+++ b/src/lib-sieve/tst-address.c
@@ -39,11 +39,11 @@ const struct sieve_command tst_address = {
 /* Opcode */
 
 static bool tst_address_opcode_dump
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool tst_address_opcode_execute
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 const struct sieve_opcode tst_address_opcode = { 
 	"ADDRESS",
@@ -110,28 +110,26 @@ static bool tst_address_generate
 /* Code dump */
 
 static bool tst_address_opcode_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED,	struct sieve_interpreter *interp, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+(const struct sieve_opcode *opcode ATTR_UNUSED,	
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	printf("ADDRESS\n");
 
 	//* Handle any optional arguments */
-	if ( !sieve_addrmatch_default_dump_optionals(interp, sbin, address) )
+	if ( !sieve_addrmatch_default_dump_optionals(renv, address) )
 		return FALSE;
 
 	return
-		sieve_opr_stringlist_dump(sbin, address) &&
-		sieve_opr_stringlist_dump(sbin, address);
+		sieve_opr_stringlist_dump(renv->sbin, address) &&
+		sieve_opr_stringlist_dump(renv->sbin, address);
 }
 
 /* Code execution */
 
 static bool tst_address_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED, struct sieve_interpreter *interp, 
-	struct sieve_binary *sbin, sieve_size_t *address)
-{
-	struct sieve_message_data *msgdata = sieve_interpreter_get_msgdata(interp);
-	
+(const struct sieve_opcode *opcode ATTR_UNUSED, 
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
+{	
 	const struct sieve_comparator *cmp = &i_octet_comparator;
 	const struct sieve_match_type *mtch = &is_match_type;
 	const struct sieve_address_part *addrp = &all_address_part;
@@ -144,19 +142,19 @@ static bool tst_address_opcode_execute
 	printf("?? ADDRESS\n");
 
 	if ( !sieve_addrmatch_default_get_optionals
-		(interp, sbin, address, &addrp, &mtch, &cmp) )
+		(renv, address, &addrp, &mtch, &cmp) )
 		return FALSE; 
 
 	t_push();
 		
 	/* Read header-list */
-	if ( (hdr_list=sieve_opr_stringlist_read(sbin, address)) == NULL ) {
+	if ( (hdr_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
 	
 	/* Read key-list */
-	if ( (key_list=sieve_opr_stringlist_read(sbin, address)) == NULL ) {
+	if ( (key_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
@@ -170,7 +168,7 @@ static bool tst_address_opcode_execute
 	while ( !matched && sieve_coded_stringlist_next_item(hdr_list, &hdr_item) && hdr_item != NULL ) {
 		const char *const *headers;
 			
-		if ( mail_get_headers_utf8(msgdata->mail, str_c(hdr_item), &headers) >= 0 ) {	
+		if ( mail_get_headers_utf8(renv->msgdata->mail, str_c(hdr_item), &headers) >= 0 ) {	
 			
 			int i;
 			for ( i = 0; !matched && headers[i] != NULL; i++ ) {
@@ -184,7 +182,7 @@ static bool tst_address_opcode_execute
 
 	t_pop();
 	
-	sieve_interpreter_set_test_result(interp, matched);
+	sieve_interpreter_set_test_result(renv->interp, matched);
 	
 	return TRUE;
 }
diff --git a/src/lib-sieve/tst-exists.c b/src/lib-sieve/tst-exists.c
index 796bee239..29986c79c 100644
--- a/src/lib-sieve/tst-exists.c
+++ b/src/lib-sieve/tst-exists.c
@@ -31,11 +31,11 @@ const struct sieve_command tst_exists = {
 /* Opcodes */
 
 static bool tst_exists_opcode_dump
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool tst_exists_opcode_execute
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 const struct sieve_opcode tst_exists_opcode = { 
 	"EXISTS",
@@ -81,22 +81,20 @@ static bool tst_exists_generate
 
 static bool tst_exists_opcode_dump
 (const struct sieve_opcode *opcode ATTR_UNUSED, 
-	struct sieve_interpreter *interp ATTR_UNUSED, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
     printf("EXISTS\n");
 
 	return
-    	sieve_opr_stringlist_dump(sbin, address);
+    	sieve_opr_stringlist_dump(renv->sbin, address);
 }
 
 /* Code execution */
 
 static bool tst_exists_opcode_execute
-(const struct sieve_opcode *opcode ATTR_UNUSED, struct sieve_interpreter *interp, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+(const struct sieve_opcode *opcode ATTR_UNUSED, 
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
-	struct sieve_message_data *msgdata = sieve_interpreter_get_msgdata(interp);
 	struct sieve_coded_stringlist *hdr_list;
 	string_t *hdr_item;
 	bool matched;
@@ -106,7 +104,7 @@ static bool tst_exists_opcode_execute
 	t_push();
 		
 	/* Read header-list */
-	if ( (hdr_list=sieve_opr_stringlist_read(sbin, address)) == NULL ) {
+	if ( (hdr_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
@@ -118,7 +116,8 @@ static bool tst_exists_opcode_execute
 		hdr_item != NULL ) {
 		const char *const *headers;
 			
-		if ( mail_get_headers_utf8(msgdata->mail, str_c(hdr_item), &headers) >= 0 && 
+		if ( mail_get_headers_utf8
+			(renv->msgdata->mail, str_c(hdr_item), &headers) >= 0 && 
 			headers[0] != NULL ) {	
 			matched = TRUE;				 
 		}
@@ -126,7 +125,7 @@ static bool tst_exists_opcode_execute
 	
 	t_pop();
 	
-	sieve_interpreter_set_test_result(interp, matched);
+	sieve_interpreter_set_test_result(renv->interp, matched);
 	
 	return TRUE;
 }
diff --git a/src/lib-sieve/tst-header.c b/src/lib-sieve/tst-header.c
index 4eb4fd320..eddfb9bf7 100644
--- a/src/lib-sieve/tst-header.c
+++ b/src/lib-sieve/tst-header.c
@@ -36,11 +36,11 @@ const struct sieve_command tst_header = {
 /* Opcode */
 
 static bool tst_header_opcode_dump
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *runenv, sieve_size_t *address);
 static bool tst_header_opcode_execute
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *runenv, sieve_size_t *address);
 
 const struct sieve_opcode tst_header_opcode = { 
 	"HEADER",
@@ -114,23 +114,22 @@ static bool tst_header_generate
 /* Code dump */
 
 static bool tst_header_opcode_dump
-(const struct sieve_opcode *opcode ATTR_UNUSED, 
-	struct sieve_interpreter *interp, struct sieve_binary *sbin, 
-	sieve_size_t *address)
+(const struct sieve_opcode *opcode ATTR_UNUSED,
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	unsigned int opt_code;
 
 	printf("HEADER\n");
 
 	/* Handle any optional arguments */
-	if ( sieve_operand_optional_present(sbin, address) ) {
-		while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) {
+	if ( sieve_operand_optional_present(renv->sbin, address) ) {
+		while ( (opt_code=sieve_operand_optional_read(renv->sbin, address)) ) {
 			switch ( opt_code ) {
 			case OPT_COMPARATOR:
-				sieve_opr_comparator_dump(interp, sbin, address);
+				sieve_opr_comparator_dump(renv, address);
 				break;
 			case OPT_MATCH_TYPE:
-				sieve_opr_match_type_dump(interp, sbin, address);
+				sieve_opr_match_type_dump(renv, address);
 				break;
 			default: 
 				return FALSE;
@@ -139,18 +138,16 @@ static bool tst_header_opcode_dump
 	}
 
 	return
-		sieve_opr_stringlist_dump(sbin, address) &&
-		sieve_opr_stringlist_dump(sbin, address);
+		sieve_opr_stringlist_dump(renv->sbin, address) &&
+		sieve_opr_stringlist_dump(renv->sbin, address);
 }
 
 /* Code execution */
 
 static bool tst_header_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED, 
-	struct sieve_interpreter *interp, struct sieve_binary *sbin, 
-	sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
-	struct sieve_message_data *msgdata = sieve_interpreter_get_msgdata(interp);
 	unsigned int opt_code;
 	const struct sieve_comparator *cmp = &i_octet_comparator;
 	const struct sieve_match_type *mtch = &is_match_type;
@@ -163,14 +160,14 @@ static bool tst_header_opcode_execute
 	printf("?? HEADER\n");
 
 	/* Handle any optional arguments */
-	if ( sieve_operand_optional_present(sbin, address) ) {
-		while ( (opt_code=sieve_operand_optional_read(sbin, address)) ) {
+	if ( sieve_operand_optional_present(renv->sbin, address) ) {
+		while ( (opt_code=sieve_operand_optional_read(renv->sbin, address)) ) {
 			switch ( opt_code ) {
 			case OPT_COMPARATOR:
-				cmp = sieve_opr_comparator_read(interp, sbin, address);
+				cmp = sieve_opr_comparator_read(renv, address);
 				break;
 			case OPT_MATCH_TYPE:
-				mtch = sieve_opr_match_type_read(interp, sbin, address);
+				mtch = sieve_opr_match_type_read(renv, address);
 				break;
 			default:
 				return FALSE;
@@ -181,13 +178,13 @@ static bool tst_header_opcode_execute
 	t_push();
 		
 	/* Read header-list */
-	if ( (hdr_list=sieve_opr_stringlist_read(sbin, address)) == NULL ) {
+	if ( (hdr_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
 	
 	/* Read key-list */
-	if ( (key_list=sieve_opr_stringlist_read(sbin, address)) == NULL ) {
+	if ( (key_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
 		t_pop();
 		return FALSE;
 	}
@@ -200,7 +197,7 @@ static bool tst_header_opcode_execute
 	while ( !matched && sieve_coded_stringlist_next_item(hdr_list, &hdr_item) && hdr_item != NULL ) {
 		const char *const *headers;
 			
-		if ( mail_get_headers_utf8(msgdata->mail, str_c(hdr_item), &headers) >= 0 ) {	
+		if ( mail_get_headers_utf8(renv->msgdata->mail, str_c(hdr_item), &headers) >= 0 ) {	
 			
 			int i;
 			for ( i = 0; !matched && headers[i] != NULL; i++ ) {
@@ -214,7 +211,7 @@ static bool tst_header_opcode_execute
 	
 	t_pop();
 	
-	sieve_interpreter_set_test_result(interp, matched);
+	sieve_interpreter_set_test_result(renv->interp, matched);
 	
 	return TRUE;
 }
diff --git a/src/lib-sieve/tst-size.c b/src/lib-sieve/tst-size.c
index 22032ffbf..cd09f8aac 100644
--- a/src/lib-sieve/tst-size.c
+++ b/src/lib-sieve/tst-size.c
@@ -36,11 +36,11 @@ const struct sieve_command tst_size = {
 /* Opcodes */
 
 static bool tst_size_opcode_dump
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 static bool tst_size_opcode_execute
-	(const struct sieve_opcode *opcode, struct sieve_interpreter *interp, 
-		struct sieve_binary *sbin, sieve_size_t *address);
+	(const struct sieve_opcode *opcode, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address);
 
 const struct sieve_opcode tst_size_over_opcode = { 
 	"SIZE-OVER",
@@ -182,23 +182,22 @@ bool tst_size_generate
 
 static bool tst_size_opcode_dump
 (const struct sieve_opcode *opcode,
-	struct sieve_interpreter *interp ATTR_UNUSED, 
-	struct sieve_binary *sbin, sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
     printf("%s\n", opcode->mnemonic);
     
 	return 
-		sieve_opr_number_dump(sbin, address);
+		sieve_opr_number_dump(renv->sbin, address);
 }
 
 /* Code execution */
 
-static bool tst_size_get(struct sieve_interpreter *interp, sieve_size_t *size) 
+static bool tst_size_get
+(const struct sieve_runtime_env *renv, sieve_size_t *size) 
 {
-	struct sieve_message_data *msgdata = sieve_interpreter_get_msgdata(interp);
 	uoff_t psize;
 
-	if ( mail_get_physical_size(msgdata->mail, &psize) < 0 )
+	if ( mail_get_physical_size(renv->msgdata->mail, &psize) < 0 )
 		return FALSE;
 
 	*size = psize;
@@ -208,23 +207,22 @@ static bool tst_size_get(struct sieve_interpreter *interp, sieve_size_t *size)
 
 static bool tst_size_opcode_execute
 (const struct sieve_opcode *opcode,
-	struct sieve_interpreter *interp, struct sieve_binary *sbin, 
-	sieve_size_t *address)
+	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
 	sieve_size_t mail_size, limit;
 	
 	printf("%s\n", opcode->mnemonic);
 	
-	if ( !sieve_opr_number_read(sbin, address, &limit) ) 
+	if ( !sieve_opr_number_read(renv->sbin, address, &limit) ) 
 		return FALSE;	
 	
-	if ( !tst_size_get(interp, &mail_size) )
+	if ( !tst_size_get(renv, &mail_size) )
 		return FALSE;
 	
 	if ( opcode == &tst_size_over_opcode )
-		sieve_interpreter_set_test_result(interp, (mail_size > limit));
+		sieve_interpreter_set_test_result(renv->interp, (mail_size > limit));
 	else
-		sieve_interpreter_set_test_result(interp, (mail_size < limit));
+		sieve_interpreter_set_test_result(renv->interp, (mail_size < limit));
 
 	return TRUE;
 }
-- 
GitLab