From c061f3896cccb46fa3b4e471810eda49a11a288b Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Thu, 13 Dec 2007 22:59:24 +0100
Subject: [PATCH] First successful (single level) execution of four consecutive
 includes.

---
 src/lib-sieve/plugins/include/cmd-include.c   |  9 +-
 .../plugins/include/ext-include-common.c      | 94 +++++++++++++++++++
 .../plugins/include/ext-include-common.h      |  7 ++
 src/lib-sieve/plugins/include/ext-include.c   | 16 +++-
 src/lib-sieve/sieve-interpreter.c             | 28 ++++--
 src/lib-sieve/sieve-interpreter.h             | 14 ++-
 src/lib-sieve/sieve.c                         |  4 +-
 7 files changed, 158 insertions(+), 14 deletions(-)

diff --git a/src/lib-sieve/plugins/include/cmd-include.c b/src/lib-sieve/plugins/include/cmd-include.c
index b5e6186b4..c128e79d3 100644
--- a/src/lib-sieve/plugins/include/cmd-include.c
+++ b/src/lib-sieve/plugins/include/cmd-include.c
@@ -240,8 +240,13 @@ static bool opc_include_dump
 static bool opc_include_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
-{	
-	return TRUE;
+{
+	int block;
+	
+	if ( !sieve_binary_read_offset(renv->sbin, address, &block) )
+		return FALSE;
+	
+	return ext_include_execute_include(renv, (unsigned int) block);
 }
 
 
diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c
index be669d741..4f188b462 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.c
+++ b/src/lib-sieve/plugins/include/ext-include-common.c
@@ -5,6 +5,7 @@
 #include "sieve-binary.h"
 #include "sieve-commands.h"
 #include "sieve-generator.h"
+#include "sieve-interpreter.h"
 
 #include "ext-include-common.h"
 
@@ -28,6 +29,16 @@ struct ext_include_binary_context {
 	struct hash_table *included_scripts;
 };
 
+/* Interpreter context */
+
+struct ext_include_interpreter_context {
+	struct sieve_interpreter *interp;
+	unsigned int nesting_level;
+	struct sieve_script *script;
+	unsigned int block_id;
+	struct ext_include_interpreter_context *parent;
+};
+
 /* Main context management */
 
 static struct ext_include_main_context *ext_include_create_main_context
@@ -187,6 +198,62 @@ static bool ext_include_script_is_included
 	return TRUE;
 }
 
+/* Interpreter context management */
+
+static struct ext_include_interpreter_context *
+	ext_include_create_interpreter_context
+(struct sieve_interpreter *interp, 
+	struct ext_include_interpreter_context *parent, 
+	struct sieve_script *script, unsigned int block_id)
+{	
+	struct ext_include_interpreter_context *ctx;
+
+	pool_t pool = sieve_interpreter_pool(interp);
+	ctx = p_new(pool, struct ext_include_interpreter_context, 1);
+	ctx->parent = parent;
+	ctx->script = script;
+	ctx->block_id = block_id;
+	if ( parent == NULL ) 
+		ctx->nesting_level = 0;
+	else
+		ctx->nesting_level = parent->nesting_level + 1;
+	
+	return ctx;
+}
+
+static inline struct ext_include_interpreter_context *
+	ext_include_get_interpreter_context
+(struct sieve_interpreter *interp)
+{
+	return (struct ext_include_interpreter_context *)
+		sieve_interpreter_extension_get_context(interp, ext_include_my_id);
+}
+
+static inline void ext_include_initialize_interpreter_context
+(struct sieve_interpreter *interp, 
+	struct ext_include_interpreter_context *parent, 
+	struct sieve_script *script, unsigned int block_id)
+{
+	sieve_interpreter_extension_set_context(interp, ext_include_my_id,
+		ext_include_create_interpreter_context(interp, parent, script, block_id));
+}
+
+void ext_include_register_interpreter_context
+(struct sieve_interpreter *interp)
+{
+	struct ext_include_interpreter_context *ctx = 
+		ext_include_get_interpreter_context(interp);
+	struct sieve_script *script = sieve_interpreter_script(interp);
+	
+	if ( ctx == NULL ) {
+		ctx = ext_include_create_interpreter_context
+			(interp, NULL, script, SBIN_SYSBLOCK_MAIN_PROGRAM);
+		
+		sieve_interpreter_extension_set_context
+			(interp, ext_include_my_id, (void *) ctx);		
+	}
+}
+
 /* Including a script during generation */
 
 bool ext_include_generate_include
@@ -296,3 +363,30 @@ bool ext_include_generate_include
 	return result;
 }
 
+/* Executing an included script during interpretation */
+
+bool ext_include_execute_include
+	(const struct sieve_runtime_env *renv, unsigned int block_id)
+{
+	int result = TRUE;
+	struct ext_include_interpreter_context *ctx =
+		ext_include_get_interpreter_context(renv->interp);
+	struct sieve_error_handler *ehandler = 
+		sieve_interpreter_get_error_handler(renv->interp);
+	struct sieve_interpreter *subinterp;
+	unsigned int this_block_id;
+	bool interrupted;
+	
+	this_block_id = sieve_binary_block_set_active(renv->sbin, block_id); 	
+	subinterp = sieve_interpreter_create(renv->sbin, ehandler);			
+	ext_include_initialize_interpreter_context(subinterp, ctx, NULL, block_id);
+	
+	result = ( sieve_interpreter_start
+		(subinterp, renv->msgdata, renv->scriptenv, renv->result, &interrupted)
+		== 1 );
+				
+	(void) sieve_binary_block_set_active(renv->sbin, this_block_id); 	
+	sieve_interpreter_free(&subinterp);
+	
+	return result;
+}
diff --git a/src/lib-sieve/plugins/include/ext-include-common.h b/src/lib-sieve/plugins/include/ext-include-common.h
index 2401a229a..54e228f93 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.h
+++ b/src/lib-sieve/plugins/include/ext-include-common.h
@@ -30,4 +30,11 @@ bool ext_include_generate_include
 
 void ext_include_binary_free(struct sieve_binary *sbin);
 
+/* Interpreter */
+
+void ext_include_register_interpreter_context
+	(struct sieve_interpreter *interp);
+bool ext_include_execute_include
+	(const struct sieve_runtime_env *renv, unsigned int block_id);
+
 #endif /* __EXT_INCLUDE_COMMON_H */
diff --git a/src/lib-sieve/plugins/include/ext-include.c b/src/lib-sieve/plugins/include/ext-include.c
index d1d426be2..29373bd8f 100644
--- a/src/lib-sieve/plugins/include/ext-include.c
+++ b/src/lib-sieve/plugins/include/ext-include.c
@@ -35,6 +35,7 @@ static bool ext_include_load(int ext_id);
 static bool ext_include_validator_load(struct sieve_validator *validator);
 static bool ext_include_generator_load(struct sieve_generator *gentr);
 static bool ext_include_binary_load(struct sieve_binary *sbin);
+static bool ext_include_interpreter_load(struct sieve_interpreter *interp);
 
 /* Commands */
 
@@ -58,7 +59,8 @@ const struct sieve_extension include_extension = {
 	ext_include_load,
 	ext_include_validator_load, 
 	ext_include_generator_load,
-	ext_include_binary_load, NULL, 
+	ext_include_binary_load, 
+	ext_include_interpreter_load, 
 	SIEVE_EXT_DEFINE_OPCODES(ext_include_opcodes),
 	NULL
 };
@@ -96,6 +98,8 @@ static bool ext_include_generator_load(struct sieve_generator *gentr)
 	return TRUE;
 }
 
+/* Load extension into binary */
+
 static bool ext_include_binary_load(struct sieve_binary *sbin)
 {
 	sieve_binary_extension_set(sbin, ext_include_my_id, &include_binary_ext);
@@ -103,3 +107,13 @@ static bool ext_include_binary_load(struct sieve_binary *sbin)
 	return TRUE;
 }
 
+/* Load extension into interpreter */
+
+static bool ext_include_interpreter_load(struct sieve_interpreter *interp)
+{
+	ext_include_register_interpreter_context(interp);
+	
+	return TRUE;
+}
+
+
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index 5aba90f7a..926ec1fce 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -54,6 +54,7 @@ struct sieve_interpreter *sieve_interpreter_create
 	interp->runenv.interp = interp;
 	
 	interp->runenv.sbin = sbin;
+	interp->runenv.script = sieve_binary_script(sbin);
 	sieve_binary_ref(sbin);
 	
 	interp->pc = 0;
@@ -80,10 +81,13 @@ struct sieve_interpreter *sieve_interpreter_create
 	return interp;
 }
 
-void sieve_interpreter_free(struct sieve_interpreter *interp) 
+void sieve_interpreter_free(struct sieve_interpreter **interp) 
 {
-	sieve_binary_unref(&interp->runenv.sbin);
-	pool_unref(&(interp->pool));
+	sieve_binary_unref(&(*interp)->runenv.sbin);
+	
+	pool_unref(&((*interp)->pool));
+	
+	*interp = NULL;
 }
 
 inline pool_t sieve_interpreter_pool(struct sieve_interpreter *interp)
@@ -91,6 +95,18 @@ inline pool_t sieve_interpreter_pool(struct sieve_interpreter *interp)
 	return interp->pool;
 }
 
+inline struct sieve_script *sieve_interpreter_script
+	(struct sieve_interpreter *interp)
+{
+	return interp->runenv.script;
+}
+
+inline struct sieve_error_handler *sieve_interpreter_get_error_handler
+	(struct sieve_interpreter *interp)
+{
+	return interp->ehandler;
+}
+
 /* Error handling */
 
 /* This is not particularly user friendly, so we might want to consider storing
@@ -304,11 +320,11 @@ int sieve_interpreter_continue
 
 int sieve_interpreter_start
 (struct sieve_interpreter *interp, const struct sieve_message_data *msgdata,
-	const struct sieve_script_env *senv, struct sieve_result **result,
+	const struct sieve_script_env *senv, struct sieve_result *result,
 	bool *interrupted) 
 {
 	interp->runenv.msgdata = msgdata;
-	interp->runenv.result = *result;		
+	interp->runenv.result = result;		
 	interp->runenv.scriptenv = senv;
 	
 	return sieve_interpreter_continue(interp, interrupted); 
@@ -328,7 +344,7 @@ int sieve_interpreter_run
 		sieve_result_ref(*result);
 	}
 	
-	ret = sieve_interpreter_start(interp, msgdata, senv, result, NULL);
+	ret = sieve_interpreter_start(interp, msgdata, senv, *result, NULL);
 
 	if ( ret >= 0 && is_topmost ) {
 		ret = sieve_result_execute(*result, msgdata, senv);
diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h
index 972d315d4..4c7c4c29c 100644
--- a/src/lib-sieve/sieve-interpreter.h
+++ b/src/lib-sieve/sieve-interpreter.h
@@ -15,7 +15,9 @@ struct sieve_interpreter;
 
 struct sieve_runtime_env {
 	struct sieve_interpreter *interp;
+	struct sieve_script *script;
 	struct sieve_binary *sbin;
+	
 	const struct sieve_message_data *msgdata;
 	const struct sieve_script_env *scriptenv;
 	struct sieve_result *result;
@@ -23,8 +25,14 @@ struct sieve_runtime_env {
 
 struct sieve_interpreter *sieve_interpreter_create
 	(struct sieve_binary *sbin, struct sieve_error_handler *ehandler);
-void sieve_interpreter_free(struct sieve_interpreter *interp);
-inline pool_t sieve_interpreter_pool(struct sieve_interpreter *interp);
+void sieve_interpreter_free(struct sieve_interpreter **interp);
+
+inline pool_t sieve_interpreter_pool
+	(struct sieve_interpreter *interp);
+inline struct sieve_script *sieve_interpreter_script
+	(struct sieve_interpreter *interp);
+inline struct sieve_error_handler *sieve_interpreter_get_error_handler
+	(struct sieve_interpreter *interp);
 
 inline void sieve_interpreter_reset
 	(struct sieve_interpreter *interp);
@@ -73,7 +81,7 @@ int sieve_interpreter_continue
 	(struct sieve_interpreter *interp, bool *interrupted);
 int sieve_interpreter_start
 	(struct sieve_interpreter *interp, const struct sieve_message_data *msgdata,
-		const struct sieve_script_env *senv, struct sieve_result **result,
+		const struct sieve_script_env *senv, struct sieve_result *result,
 		bool *interrupted);
 int sieve_interpreter_run
 	(struct sieve_interpreter *interp, const struct sieve_message_data *msgdata,
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index 2dd1732b5..185aeab23 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -184,7 +184,7 @@ int sieve_test
 	if ( ret > 0 ) 
 		ret = sieve_result_print(sres);
 	
-	sieve_interpreter_free(interp);
+	sieve_interpreter_free(&interp);
 	sieve_result_unref(&sres);
 	return ret;
 }
@@ -201,7 +201,7 @@ int sieve_execute
 							
 	ret = sieve_interpreter_run(interp, msgdata, senv, &sres);
 				
-	sieve_interpreter_free(interp);
+	sieve_interpreter_free(&interp);
 	sieve_result_unref(&sres);
 	return ret;
 }
-- 
GitLab