From 5f9a9f9967c98a35c9ce446c54cafdd08ae62e8f Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Mon, 24 Mar 2008 20:39:05 +0100
Subject: [PATCH] Include: added AST context and now export context detectects
 export of imported variables.

---
 src/lib-sieve/plugins/include/cmd-export.c    | 85 ++++++++-----------
 src/lib-sieve/plugins/include/cmd-import.c    | 73 ++++++----------
 .../plugins/include/ext-include-common.c      | 70 ++++++++++++++-
 .../plugins/include/ext-include-common.h      |  5 ++
 src/lib-sieve/plugins/include/ext-include.c   |  6 +-
 .../include/include-variables-error2.sieve    |  6 ++
 .../plugins/variables/ext-variables-common.c  | 31 ++++---
 .../plugins/variables/ext-variables-common.h  |  2 +-
 .../plugins/variables/sieve-ext-variables.h   |  4 +-
 src/lib-sieve/sieve-ast.c                     | 25 ++++++
 src/lib-sieve/sieve-ast.h                     |  6 ++
 11 files changed, 194 insertions(+), 119 deletions(-)
 create mode 100644 src/lib-sieve/plugins/include/include-variables-error2.sieve

diff --git a/src/lib-sieve/plugins/include/cmd-export.c b/src/lib-sieve/plugins/include/cmd-export.c
index 713db8165..049717abf 100644
--- a/src/lib-sieve/plugins/include/cmd-export.c
+++ b/src/lib-sieve/plugins/include/cmd-export.c
@@ -14,13 +14,6 @@
 
 static bool cmd_export_validate
   (struct sieve_validator *validator, struct sieve_command_context *cmd);
-static bool cmd_export_generate
-	(struct sieve_generator *generator, 
-		struct sieve_command_context *ctx ATTR_UNUSED);
-
-static bool opc_export_execute
-	(const struct sieve_operation *op, 
-		const struct sieve_runtime_env *renv, sieve_size_t *address);
 		
 /* Export command 
  * 
@@ -31,20 +24,9 @@ const struct sieve_command cmd_export = {
 	"export", 
 	SCT_COMMAND, 
 	1, 0, FALSE, FALSE,
-	NULL, NULL,
+	NULL, NULL, 
 	cmd_export_validate, 
-	cmd_export_generate, 
-	NULL
-};
-
-/* Export operation */
-
-const struct sieve_operation export_operation = { 
-	"export",
-	&include_extension,
-	EXT_INCLUDE_OPERATION_EXPORT,
-	NULL, 
-	opc_export_execute 
+	NULL, NULL
 };
 
 /*
@@ -77,38 +59,41 @@ static bool cmd_export_validate
 		return FALSE;
 	}
 	
-	if ( !sieve_validate_positional_argument
-		(validator, cmd, arg, "value", 1, SAAT_STRING_LIST) ) {
+	/* Register imported variable */
+	if ( sieve_ast_argument_type(arg) == SAAT_STRING ) {
+		/* Single string */
+		const char *variable = sieve_ast_argument_strc(arg);
+		
+		if ( !ext_include_export_variable(arg->ast, variable) ) {
+			sieve_command_validate_error(validator, cmd, 
+				"cannot export imported variable '%s'", variable);
+			return FALSE;
+		}
+
+	} 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 char *variable = sieve_ast_argument_strc(stritem);
+			
+			if ( !ext_include_export_variable(arg->ast, variable) ) {
+				sieve_command_validate_error(validator, cmd, 
+					"cannot export imported variable '%s'", variable);
+				return FALSE;
+			}
+	
+			stritem = sieve_ast_strlist_next(stritem);
+		}
+	} else {
+		/* Something else */
+		sieve_command_validate_error(validator, cmd, 
+			"the export command accepts a single string or string list argument, "
+			"but %s was found", 
+			sieve_ast_argument_name(arg));
 		return FALSE;
 	}
 	
-	//return sieve_validator_argument_activate(validator, cmd, arg, FALSE);
-	return TRUE;
-}
-
-/*
- * Generation
- */
-
-static bool cmd_export_generate
-(struct sieve_generator *gentr, struct sieve_command_context *ctx ATTR_UNUSED) 
-{
-	sieve_generator_emit_operation_ext	
-		(gentr, &export_operation, ext_include_my_id);
-
-	return TRUE;
-}
-
-/*
- * Interpretation
- */
-
-static bool opc_export_execute
-(const struct sieve_operation *op ATTR_UNUSED,
-	const struct sieve_runtime_env *renv, 
-	sieve_size_t *address ATTR_UNUSED)
-{	
+	(void)sieve_ast_arguments_detach(arg, 1);
 	return TRUE;
 }
-
-
diff --git a/src/lib-sieve/plugins/include/cmd-import.c b/src/lib-sieve/plugins/include/cmd-import.c
index 997cea655..ad0102dd9 100644
--- a/src/lib-sieve/plugins/include/cmd-import.c
+++ b/src/lib-sieve/plugins/include/cmd-import.c
@@ -14,13 +14,6 @@
 
 static bool cmd_import_validate
   (struct sieve_validator *validator, struct sieve_command_context *cmd); 
-static bool cmd_import_generate
-	(struct sieve_generator *generator, 
-		struct sieve_command_context *ctx ATTR_UNUSED);
-		
-static bool opc_import_execute
-	(const struct sieve_operation *op, 
-		const struct sieve_runtime_env *renv, sieve_size_t *address);
 		
 /* Import command 
  * 
@@ -33,18 +26,7 @@ const struct sieve_command cmd_import = {
 	1, 0, FALSE, FALSE,
 	NULL, NULL,
 	cmd_import_validate, 
-	cmd_import_generate, 
-	NULL
-};
-
-/* Import operation */
-
-const struct sieve_operation import_operation = { 
-	"import",
-	&include_extension,
-	EXT_INCLUDE_OPERATION_IMPORT,
-	NULL, 
-	opc_import_execute 
+	NULL, NULL
 };
 
 /*
@@ -75,39 +57,34 @@ static bool cmd_import_validate
 			"import command requires that variables extension is active");
 		return FALSE;
 	}
+		
+	/* Register imported variable */
+	if ( sieve_ast_argument_type(arg) == SAAT_STRING ) {
+		/* Single string */
+		const char *variable = sieve_ast_argument_strc(arg);
+		
+		ext_include_import_variable(arg->ast, variable);
+
+	} 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 char *variable = sieve_ast_argument_strc(stritem);
+			ext_include_import_variable(arg->ast, variable);
 	
-	if ( !sieve_validate_positional_argument
-		(validator, cmd, arg, "value", 1, SAAT_STRING_LIST) ) {
+			stritem = sieve_ast_strlist_next(stritem);
+		}
+	} else {
+		/* Something else */
+		sieve_command_validate_error(validator, cmd, 
+			"the import command accepts a single string or string list argument, "
+			"but %s was found", 
+			sieve_ast_argument_name(arg));
 		return FALSE;
 	}
 	
-	//return sieve_validator_argument_activate(validator, cmd, arg, FALSE);
-	return TRUE;
-}
-
-/*
- * Generation
- */
-
-static bool cmd_import_generate
-(struct sieve_generator *gentr, struct sieve_command_context *ctx ATTR_UNUSED) 
-{
-	sieve_generator_emit_operation_ext	
-		(gentr, &import_operation, ext_include_my_id);
-
-	return TRUE;
-}
-
-/*
- * Interpretation
- */
-
-static bool opc_import_execute
-(const struct sieve_operation *op ATTR_UNUSED,
-	const struct sieve_runtime_env *renv, 
-	sieve_size_t *address ATTR_UNUSED)
-{	
+	(void)sieve_ast_arguments_detach(arg, 1);
 	return TRUE;
 }
 
-
diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c
index 67aedc331..4aacb8405 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.c
+++ b/src/lib-sieve/plugins/include/ext-include-common.c
@@ -6,12 +6,20 @@
 #include "sieve-commands.h"
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
+#include "sieve-ext-variables.h"
 
 #include "ext-include-common.h"
 
 /*
  * Forward declarations
  */
+ 
+/* AST context */
+
+struct ext_include_ast_context {
+	struct sieve_variable_scope *import_vars;
+	struct sieve_variable_scope *export_vars;
+};
 
 /* Generator context */
 
@@ -59,10 +67,14 @@ const char *ext_include_get_script_path
 (enum ext_include_script_location location, const char *script_name)
 {
 	/* FIXME: Hardcoded */	
-	if ( location == EXT_INCLUDE_LOCATION_PERSONAL )
+	switch ( location ) {
+	case EXT_INCLUDE_LOCATION_PERSONAL:
 		return t_strconcat(HARDCODED_PERSONAL_DIR, script_name, ".sieve", NULL);
-	else if ( location == EXT_INCLUDE_LOCATION_GLOBAL )
+	case EXT_INCLUDE_LOCATION_GLOBAL:
 		return t_strconcat(HARDCODED_GLOBAL_DIR, script_name, ".sieve", NULL);
+	default:
+		break;
+	}
 	
 	return NULL;
 }
@@ -84,6 +96,60 @@ static struct ext_include_main_context *ext_include_create_main_context
 	return ctx;
 }
 
+/* 
+ * AST context management
+ */
+
+static struct ext_include_ast_context *ext_include_create_ast_context
+(struct sieve_ast *ast)
+{	
+	struct ext_include_ast_context *ctx;
+
+	pool_t pool = sieve_ast_pool(ast);
+	ctx = p_new(pool, struct ext_include_ast_context, 1);
+	ctx->import_vars = sieve_variable_scope_create(pool);
+	ctx->export_vars = sieve_variable_scope_create(pool);
+	
+	return ctx;
+}
+
+static inline struct ext_include_ast_context *
+	ext_include_get_ast_context(struct sieve_ast *ast)
+{
+	struct ext_include_ast_context *ctx = (struct ext_include_ast_context *)
+		sieve_ast_extension_get_context(ast, ext_include_my_id);
+		
+	if ( ctx == NULL ) {
+		ctx = ext_include_create_ast_context(ast);
+		sieve_ast_extension_set_context(ast, ext_include_my_id, ctx);
+	}
+	
+	return ctx;
+}
+
+/* 
+ * Variable import-export
+ */
+ 
+void ext_include_import_variable(struct sieve_ast *ast, const char *variable)
+{
+	struct ext_include_ast_context *ctx = ext_include_get_ast_context(ast);
+	
+	(void)sieve_variable_scope_declare(ctx->import_vars, variable);
+}
+
+bool ext_include_export_variable(struct sieve_ast *ast, const char *variable)
+{
+	struct ext_include_ast_context *ctx = ext_include_get_ast_context(ast);
+	
+	if ( sieve_variable_scope_get_variable(ctx->import_vars, variable, FALSE) 
+		!= NULL )
+		return FALSE;
+		
+	(void)sieve_variable_scope_declare(ctx->export_vars, variable);
+	return TRUE;	
+}
+
 /* 
  * Generator context management 
  */
diff --git a/src/lib-sieve/plugins/include/ext-include-common.h b/src/lib-sieve/plugins/include/ext-include-common.h
index 3440e209a..cb389e53e 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.h
+++ b/src/lib-sieve/plugins/include/ext-include-common.h
@@ -73,4 +73,9 @@ bool ext_include_execute_include
 	(const struct sieve_runtime_env *renv, unsigned int block_id);
 void ext_include_execute_return(const struct sieve_runtime_env *renv);
 
+/* Variables import-export */
+
+void ext_include_import_variable(struct sieve_ast *ast, const char *variable);
+bool ext_include_export_variable(struct sieve_ast *ast, const char *variable);
+
 #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 999aaa3e8..2d12ebb6e 100644
--- a/src/lib-sieve/plugins/include/ext-include.c
+++ b/src/lib-sieve/plugins/include/ext-include.c
@@ -41,14 +41,10 @@ static bool ext_include_interpreter_load(struct sieve_interpreter *interp);
 
 extern const struct sieve_operation include_operation;
 extern const struct sieve_operation return_operation;
-extern const struct sieve_operation import_operation;
-extern const struct sieve_operation export_operation;
 
 static const struct sieve_operation *ext_include_operations[] = { 
 	&include_operation, 
-	&return_operation, 
-	&import_operation, 
-	&export_operation 
+	&return_operation
 };
 
 /* Extension definitions */
diff --git a/src/lib-sieve/plugins/include/include-variables-error2.sieve b/src/lib-sieve/plugins/include/include-variables-error2.sieve
new file mode 100644
index 000000000..f06a7df1a
--- /dev/null
+++ b/src/lib-sieve/plugins/include/include-variables-error2.sieve
@@ -0,0 +1,6 @@
+require "include";
+require "variables";
+import "frop";
+import ["friep", "frml"];
+export ["friep"];
+
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.c b/src/lib-sieve/plugins/variables/ext-variables-common.c
index 26691a0dd..8c3a72355 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.c
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.c
@@ -79,19 +79,26 @@ struct sieve_variable_scope *sieve_variable_scope_create(pool_t pool)
 	return scope;
 }
 
-struct sieve_variable *sieve_variable_scope_get_variable
+struct sieve_variable *sieve_variable_scope_declare
 (struct sieve_variable_scope *scope, const char *identifier)
+{
+	struct sieve_variable *var = p_new(scope->pool, struct sieve_variable, 1);
+	var->identifier = identifier;
+	var->index = scope->next_index++;
+		
+	hash_insert(scope->variables, (void *) identifier, (void *) var);
+	
+	return var;
+}
+
+struct sieve_variable *sieve_variable_scope_get_variable
+(struct sieve_variable_scope *scope, const char *identifier, bool declare)
 {
 	struct sieve_variable *var = 
 		(struct sieve_variable *) hash_lookup(scope->variables, identifier);
 	
-	if ( var == NULL ) {
-		var = p_new(scope->pool, struct sieve_variable, 1);
-		var->identifier = identifier;
-		var->index = scope->next_index++;
-		
-		hash_insert(scope->variables, (void *) identifier, (void *) var);
-	} 
+	if ( var == NULL && declare )
+		var = sieve_variable_scope_declare(scope, identifier);
 	
 	return var;
 }
@@ -196,12 +203,12 @@ ext_variables_validator_context_get(struct sieve_validator *validator)
 }
 
 struct sieve_variable *ext_variables_validator_get_variable
-(struct sieve_validator *validator, const char *variable)
+(struct sieve_validator *validator, const char *variable, bool declare)
 {
 	struct ext_variables_validator_context *ctx = 
 		ext_variables_validator_context_get(validator);
 		
-	return sieve_variable_scope_get_variable(ctx->main_scope, variable);
+	return sieve_variable_scope_get_variable(ctx->main_scope, variable, declare);
 }
 
 bool sieve_ext_variables_is_active(struct sieve_validator *valdtr)
@@ -279,7 +286,7 @@ static struct sieve_ast_argument *ext_variables_variable_argument_create
 	struct sieve_ast_argument *arg;
 	
 	ctx = ext_variables_validator_context_get(validator);
-	var = sieve_variable_scope_get_variable(ctx->main_scope, variable);
+	var = sieve_variable_scope_get_variable(ctx->main_scope, variable, TRUE);
 
 	if ( var == NULL ) 
 		return NULL;
@@ -323,7 +330,7 @@ bool ext_variables_variable_assignment_activate
 		if ( cur_element->num_variable == -1 ) {
 			ctx = ext_variables_validator_context_get(validator);
 			var = sieve_variable_scope_get_variable
-				(ctx->main_scope, str_c(cur_element->identifier));
+				(ctx->main_scope, str_c(cur_element->identifier), TRUE);
 
 			arg->argument = &variable_argument;
 			arg->context = (void *) var;
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.h b/src/lib-sieve/plugins/variables/ext-variables-common.h
index 83eb4c99f..b016f4acf 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.h
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.h
@@ -72,7 +72,7 @@ bool ext_variables_variable_assignment_activate
 	struct sieve_command_context *cmd);
 
 struct sieve_variable *ext_variables_validator_get_variable
-(struct sieve_validator *validator, const char *variable);
+(struct sieve_validator *validator, const char *variable, bool declare);
 
 struct sieve_variable_storage *ext_variables_interpreter_get_storage
 	(struct sieve_interpreter *interp);
diff --git a/src/lib-sieve/plugins/variables/sieve-ext-variables.h b/src/lib-sieve/plugins/variables/sieve-ext-variables.h
index 120df3753..d2f025d5a 100644
--- a/src/lib-sieve/plugins/variables/sieve-ext-variables.h
+++ b/src/lib-sieve/plugins/variables/sieve-ext-variables.h
@@ -22,8 +22,10 @@ struct sieve_variable {
 struct sieve_variable_scope;
 
 struct sieve_variable_scope *sieve_variable_scope_create(pool_t pool);
-struct sieve_variable *sieve_variable_scope_get_variable
+struct sieve_variable *sieve_variable_scope_declare
 	(struct sieve_variable_scope *scope, const char *identifier);
+struct sieve_variable *sieve_variable_scope_get_variable
+	(struct sieve_variable_scope *scope, const char *identifier, bool create);
 	
 /* 
  * Variable storage
diff --git a/src/lib-sieve/sieve-ast.c b/src/lib-sieve/sieve-ast.c
index 5ab6edde1..21fbc7906 100644
--- a/src/lib-sieve/sieve-ast.c
+++ b/src/lib-sieve/sieve-ast.c
@@ -6,6 +6,7 @@
 #include "array.h"
 
 #include "sieve-script.h"
+#include "sieve-extensions.h"
 
 #include "sieve-ast.h"
 
@@ -32,6 +33,8 @@ struct sieve_ast {
 		
 	struct sieve_ast_node *root;
 	
+	ARRAY_DEFINE(ext_contexts, void *);
+
 	ARRAY_DEFINE(node_links, struct sieve_ast_node_link);
 };
 
@@ -52,6 +55,7 @@ struct sieve_ast *sieve_ast_create(struct sieve_script *script)
 	ast->root->identifier = "ROOT";
 	
 	p_array_init(&ast->node_links, pool, 4);
+	p_array_init(&ast->ext_contexts, pool, sieve_extensions_get_count());
 	
 	return ast;
 }
@@ -123,6 +127,27 @@ const char *sieve_ast_type_name(enum sieve_ast_type ast_type) {
 	}
 }
 
+/* Extension support */
+
+inline void sieve_ast_extension_set_context
+	(struct sieve_ast *ast, int ext_id, void *context)
+{
+	array_idx_set(&ast->ext_contexts, (unsigned int) ext_id, &context);	
+}
+
+inline const void *sieve_ast_extension_get_context
+	(struct sieve_ast *ast, int ext_id) 
+{
+	void * const *ctx;
+
+	if  ( ext_id < 0 || ext_id >= (int) array_count(&ast->ext_contexts) )
+		return NULL;
+	
+	ctx = array_idx(&ast->ext_contexts, (unsigned int) ext_id);		
+
+	return *ctx;
+}
+
 /* AST-based error reporting */
 
 void sieve_ast_error
diff --git a/src/lib-sieve/sieve-ast.h b/src/lib-sieve/sieve-ast.h
index cfd638b2f..cb962e802 100644
--- a/src/lib-sieve/sieve-ast.h
+++ b/src/lib-sieve/sieve-ast.h
@@ -167,6 +167,12 @@ inline struct sieve_script *sieve_ast_script(struct sieve_ast *ast);
 
 const char *sieve_ast_type_name(enum sieve_ast_type ast_type);
 
+/* extension support */
+inline void sieve_ast_extension_set_context
+	(struct sieve_ast *ast, int ext_id, void *context);
+inline const void *sieve_ast_extension_get_context
+	(struct sieve_ast *ast, int ext_id);
+
 /* error reporting */
 void sieve_ast_error
 (struct sieve_error_handler *ehandler, sieve_error_vfunc_t vfunc, 
-- 
GitLab