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