From 3be89fef58d5cf1b2eda0ff128c2791567032bf4 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Sun, 31 Aug 2008 19:09:46 +0200
Subject: [PATCH] Revised implementation of the require command.

---
 src/lib-sieve/cmd-require.c       | 45 +++----------------------------
 src/lib-sieve/sieve-ast.c         | 26 +++++++++++++++---
 src/lib-sieve/sieve-ast.h         |  5 ++++
 src/lib-sieve/sieve-generator.c   | 45 +++++++++++++++++++------------
 src/lib-sieve/sieve-generator.h   |  5 +---
 src/lib-sieve/sieve-interpreter.c | 12 ++++-----
 src/lib-sieve/sieve-validator.c   |  2 ++
 7 files changed, 67 insertions(+), 73 deletions(-)

diff --git a/src/lib-sieve/cmd-require.c b/src/lib-sieve/cmd-require.c
index 5c6fc151e..f6d25a3a7 100644
--- a/src/lib-sieve/cmd-require.c
+++ b/src/lib-sieve/cmd-require.c
@@ -18,8 +18,6 @@
 
 static bool cmd_require_validate
 	(struct sieve_validator *validator, struct sieve_command_context *cmd);
-static bool cmd_require_generate
-	(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx);
 
 const struct sieve_command cmd_require = { 
 	"require", 
@@ -27,10 +25,9 @@ const struct sieve_command cmd_require = {
 	1, 0, FALSE, FALSE,
 	NULL, NULL, 
 	cmd_require_validate, 
-	cmd_require_generate, 
-	NULL 
+	NULL, NULL
 };
-
+ 
 /* 
  * Validation 
  */
@@ -63,8 +60,7 @@ static bool cmd_require_validate
 			(validator, cmd, sieve_ast_argument_str(arg));	
 
 		if ( ext == NULL ) result = FALSE;
-		arg->context = (void *) ext;
-
+		
 	} else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) {
 		/* String list */
 		struct sieve_ast_argument *stritem = sieve_ast_strlist_first(arg);
@@ -74,7 +70,6 @@ static bool cmd_require_validate
 				(validator, cmd, sieve_ast_strlist_str(stritem));
 
 			if ( ext == NULL ) result = FALSE;
-			stritem->context = (void *) ext;
 	
 			stritem = sieve_ast_strlist_next(stritem);
 		}
@@ -89,37 +84,3 @@ static bool cmd_require_validate
 	 
 	return result;
 }
-
-/* 
- * Code generation 
- */
-
-static bool cmd_require_generate
-(const struct sieve_codegen_env *cgenv, struct sieve_command_context *ctx) 
-{
-	struct sieve_ast_argument *arg = ctx->first_positional;
-	
-	if ( sieve_ast_argument_type(arg) == SAAT_STRING ) {
-		/* Single string */
-		const struct sieve_extension *ext = 
-			(const struct sieve_extension *) arg->context;
-		
-		sieve_generator_link_extension(cgenv->gentr, ext);
-	} else if ( sieve_ast_argument_type(arg) == SAAT_STRING_LIST ) {
-		/* String list */
-		struct sieve_ast_argument *stritem = sieve_ast_strlist_first(arg);
-		
-		while ( stritem != NULL ) {
-			const struct sieve_extension *ext = 
-				(const struct sieve_extension *) stritem->context;
-		
-			sieve_generator_link_extension(cgenv->gentr, ext);
-			
-			stritem = sieve_ast_strlist_next(stritem);
-		}
-	} else {
-		i_unreached();
-	}
-	
-	return TRUE;
-}
diff --git a/src/lib-sieve/sieve-ast.c b/src/lib-sieve/sieve-ast.c
index c34c1d1ae..082c57db2 100644
--- a/src/lib-sieve/sieve-ast.c
+++ b/src/lib-sieve/sieve-ast.c
@@ -45,6 +45,7 @@ struct sieve_ast {
 		
 	struct sieve_ast_node *root;
 	
+	ARRAY_DEFINE(linked_extensions, const struct sieve_extension *);
 	ARRAY_DEFINE(extensions, struct sieve_ast_extension_reg);
 };
 
@@ -64,6 +65,7 @@ struct sieve_ast *sieve_ast_create(struct sieve_script *script)
 	ast->root = sieve_ast_node_create(ast, NULL, SAT_ROOT, 0);
 	ast->root->identifier = "ROOT";
 	
+	p_array_init(&ast->linked_extensions, pool, sieve_extensions_get_count());
 	p_array_init(&ast->extensions, pool, sieve_extensions_get_count());
 	
 	return ast;
@@ -120,19 +122,35 @@ struct sieve_script *sieve_ast_script(struct sieve_ast *ast)
  * Extension support 
  */
 
+void sieve_ast_extension_link
+(struct sieve_ast *ast, const struct sieve_extension *ext)
+{
+	int ext_id = *ext->id;
+
+	if ( ext_id < 0 ) return;
+
+	array_append(&ast->linked_extensions, &ext, 1);	
+}
+
+const struct sieve_extension * const *sieve_ast_extensions_get
+(struct sieve_ast *ast, unsigned int *count_r)
+{
+	return array_get(&ast->linked_extensions, count_r);
+}
+
 void sieve_ast_extension_register
 (struct sieve_ast *ast, const struct sieve_ast_extension *ast_ext, 
 	void *context)
 {
-	struct sieve_ast_extension_reg reg;
 	int ext_id = *ast_ext->ext->id;
+	struct sieve_ast_extension_reg reg;
 
 	if ( ext_id < 0 ) return;
 
+	/* Initialize registration */
 	reg.ast_ext = ast_ext;
-	reg.context = context;
-	
-	array_idx_set(&ast->extensions, (unsigned int) ext_id, &reg);	
+	reg.context = context;	
+	array_idx_set(&ast->extensions, (unsigned int) ext_id, &reg);
 }
 
 void *sieve_ast_extension_get_context
diff --git a/src/lib-sieve/sieve-ast.h b/src/lib-sieve/sieve-ast.h
index c92262568..564bd5f8b 100644
--- a/src/lib-sieve/sieve-ast.h
+++ b/src/lib-sieve/sieve-ast.h
@@ -189,6 +189,11 @@ struct sieve_ast_extension {
 	void (*free)(struct sieve_ast *ast, void *context);
 };
 
+void sieve_ast_extension_link
+	(struct sieve_ast *ast, const struct sieve_extension *ext);
+const struct sieve_extension * const *sieve_ast_extensions_get
+	(struct sieve_ast *ast, unsigned int *count_r);
+
 void sieve_ast_extension_register
 	(struct sieve_ast *ast, const struct sieve_ast_extension *ast_ext, 
 		void *context);
diff --git a/src/lib-sieve/sieve-generator.c b/src/lib-sieve/sieve-generator.c
index afac539c9..71443ade5 100644
--- a/src/lib-sieve/sieve-generator.c
+++ b/src/lib-sieve/sieve-generator.c
@@ -177,17 +177,6 @@ void sieve_generator_critical
  * Extension support 
  */
 
-bool sieve_generator_link_extension
-(struct sieve_generator *gentr, const struct sieve_extension *ext) 
-{
-	(void)sieve_binary_extension_link(gentr->genenv.sbin, ext);
-	
-	if ( ext->generator_load != NULL )
-		return ext->generator_load(&gentr->genenv);
-	
-	return TRUE;
-}
-
 void sieve_generator_extension_set_context
 (struct sieve_generator *gentr, const struct sieve_extension *ext, void *context)
 {
@@ -369,24 +358,46 @@ bool sieve_generate_block
 }
 
 bool sieve_generator_run
-(struct sieve_generator *generator, struct sieve_binary **sbin) 
+(struct sieve_generator *gentr, struct sieve_binary **sbin) 
 {
 	bool topmost = ( *sbin == NULL );
 	bool result = TRUE;
+	const struct sieve_extension *const *extensions;
+	unsigned int i, ext_count;
+	
+	/* Initialize */
 	
 	if ( topmost )
-		*sbin = sieve_binary_create_new(sieve_ast_script(generator->genenv.ast));
+		*sbin = sieve_binary_create_new(sieve_ast_script(gentr->genenv.ast));
 	
 	sieve_binary_ref(*sbin);
 		
-	generator->genenv.sbin = *sbin;
+	gentr->genenv.sbin = *sbin;
+		
+	/* Load extensions linked to the AST */
+	extensions = sieve_ast_extensions_get(gentr->genenv.ast, &ext_count);
+	for ( i = 0; i < ext_count; i++ ) {
+		const struct sieve_extension *ext = extensions[i];
+
+		/* Link to binary */
+		(void)sieve_binary_extension_link(*sbin, ext);
+	
+		/* Load */
+		if ( ext->generator_load != NULL && !ext->generator_load(&gentr->genenv) )
+			return FALSE;
+	}
+
+	/* Generate code */
 	
-	if ( !sieve_generate_block(&generator->genenv, sieve_ast_root(generator->genenv.ast))) 
+	if ( !sieve_generate_block
+		(&gentr->genenv, sieve_ast_root(gentr->genenv.ast))) 
 		result = FALSE;
 	else if ( topmost ) 
 		sieve_binary_activate(*sbin);
-	
-	generator->genenv.sbin = NULL;
+
+	/* Cleanup */
+		
+	gentr->genenv.sbin = NULL;
 	sieve_binary_unref(sbin);
 
 	if ( topmost && !result ) {
diff --git a/src/lib-sieve/sieve-generator.h b/src/lib-sieve/sieve-generator.h
index 9b1f4ea8b..5ab6f651a 100644
--- a/src/lib-sieve/sieve-generator.h
+++ b/src/lib-sieve/sieve-generator.h
@@ -54,9 +54,6 @@ void sieve_generator_critical
  * Extension support 
  */
 
-bool sieve_generator_link_extension
-	(struct sieve_generator *gentr, const struct sieve_extension *ext);
-
 void sieve_generator_extension_set_context
 	(struct sieve_generator *gentr, const struct sieve_extension *ext, 
 		void *context);
@@ -103,7 +100,7 @@ bool sieve_generate_test
 	(const struct sieve_codegen_env *cgenv, struct sieve_ast_node *tst_node, 
 		struct sieve_jumplist *jlist, bool jump_true);
 bool sieve_generator_run
-	(struct sieve_generator *generator, struct sieve_binary **sbin);
+	(struct sieve_generator *gentr, struct sieve_binary **sbin);
 
 #endif /* __SIEVE_GENERATOR_H */
 
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index a730ff6fb..eb8e35073 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -474,12 +474,12 @@ int sieve_interpreter_start
 		sieve_message_context_ref(msgctx);
 	}
 
-    /* Signal registered extensions that the interpreter is being run */
-    extrs = array_get(&interp->extensions, &ext_count);
-    for ( i = 0; i < ext_count; i++ ) {
-        if ( extrs[i].int_ext != NULL && extrs[i].int_ext->run != NULL )
-            extrs[i].int_ext->run(&interp->runenv, extrs[i].context);
-    }
+	/* Signal registered extensions that the interpreter is being run */
+	extrs = array_get(&interp->extensions, &ext_count);
+	for ( i = 0; i < ext_count; i++ ) {
+		if ( extrs[i].int_ext != NULL && extrs[i].int_ext->run != NULL )
+			extrs[i].int_ext->run(&interp->runenv, extrs[i].context);
+	}
 
 	return sieve_interpreter_continue(interp, interrupted); 
 }
diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c
index f6497aa7f..c134acf7a 100644
--- a/src/lib-sieve/sieve-validator.c
+++ b/src/lib-sieve/sieve-validator.c
@@ -503,6 +503,8 @@ const struct sieve_extension *sieve_validator_extension_load
 			"unsupported sieve capability '%s'", name);
 		return NULL;
 	}
+	
+	sieve_ast_extension_link(validator->ast, ext);
 
 	if ( ext->validator_load != NULL && !ext->validator_load(validator) ) {
 		sieve_command_validate_error(validator, cmd, 
-- 
GitLab