diff --git a/src/lib-sieve/plugins/include/cmd-include.c b/src/lib-sieve/plugins/include/cmd-include.c index c609e3a25e97a25f1f97bdf62551576836e5a033..d6331a599f39f18b7af18dc23799ce4292bad932 100644 --- a/src/lib-sieve/plugins/include/cmd-include.c +++ b/src/lib-sieve/plugins/include/cmd-include.c @@ -148,20 +148,6 @@ static bool cmd_include_registered * Command validation */ -static void cmd_include_ast_destroy -(struct sieve_ast *ast ATTR_UNUSED, struct sieve_ast_node *node) -{ - struct sieve_command_context *cmd = node->context; - struct cmd_include_context_data *ctx_data = - (struct cmd_include_context_data *) cmd->data; - - sieve_script_unref(&ctx_data->script); -} - -static const struct sieve_ast_node_object cmd_include_ast_object = { - cmd_include_ast_destroy -}; - static bool cmd_include_pre_validate (struct sieve_validator *validator ATTR_UNUSED, struct sieve_command_context *cmd) @@ -209,10 +195,9 @@ static bool cmd_include_validate(struct sieve_validator *validator, sieve_validator_error_handler(validator), NULL); if ( script == NULL ) return FALSE; - - sieve_ast_link_object(cmd->ast_node, &cmd_include_ast_object); + + ext_include_ast_link_included_script(cmd->ast_node->ast, script); ctx_data->script = script; - sieve_script_ref(script); arg = sieve_ast_arguments_detach(arg, 1); diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c index 45d67e8a0b9389ce87c7d5d22e7644672f3cc6e1..a987d9ae40876b432d456eac6f0b7728ce9ca45f 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.c +++ b/src/lib-sieve/plugins/include/ext-include-common.c @@ -19,7 +19,7 @@ /* * Forward declarations */ - + /* Generator context */ struct ext_include_generator_context { @@ -82,6 +82,70 @@ const char *ext_include_get_script_directory return sieve_dir; } +/* + * AST context management + */ + +static void ext_include_ast_free +(struct sieve_ast *ast ATTR_UNUSED, void *context) +{ + struct ext_include_ast_context *actx = + (struct ext_include_ast_context *) context; + struct sieve_script **scripts; + unsigned int count, i; + + scripts = array_get_modifiable(&actx->included_scripts, &count); + for ( i = 0; i < count; i++ ) { + sieve_script_unref(&scripts[i]); + } +} + +static const struct sieve_ast_extension include_ast_extension = { + &include_extension, + ext_include_ast_free +}; + +struct ext_include_ast_context *ext_include_create_ast_context +(struct sieve_ast *ast, struct sieve_ast *parent) +{ + struct ext_include_ast_context *actx; + + pool_t pool = sieve_ast_pool(ast); + actx = p_new(pool, struct ext_include_ast_context, 1); + actx->import_vars = sieve_variable_scope_create(pool, &include_extension); + p_array_init(&actx->included_scripts, pool, 32); + + if ( parent != NULL ) { + struct ext_include_ast_context *parent_ctx = + (struct ext_include_ast_context *) + sieve_ast_extension_get_context(parent, &include_extension); + actx->global_vars = ( parent_ctx == NULL ? NULL : parent_ctx->global_vars ); + } + + sieve_ast_extension_register(ast, &include_ast_extension, (void *) actx); + + return actx; +} + +struct ext_include_ast_context *ext_include_get_ast_context +(struct sieve_ast *ast) +{ + struct ext_include_ast_context *actx = (struct ext_include_ast_context *) + sieve_ast_extension_get_context(ast, &include_extension); + + if ( actx != NULL ) return actx; + + return ext_include_create_ast_context(ast, NULL); +} + +void ext_include_ast_link_included_script +(struct sieve_ast *ast, struct sieve_script *script) +{ + struct ext_include_ast_context *actx = ext_include_get_ast_context(ast); + + array_append(&actx->included_scripts, &script, 1); +} + /* * 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 a793d2fc254ea98056b690b6eb1b85e5dba89769..28daa04eb3e0fcfe858552e9a608e748bea45fe9 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.h +++ b/src/lib-sieve/plugins/include/ext-include-common.h @@ -43,7 +43,30 @@ enum ext_include_script_location { const char *ext_include_get_script_directory (enum ext_include_script_location location, const char *script_name); -/* Generator */ +/* + * AST Context + */ + +/* AST context */ + +struct ext_include_ast_context { + struct sieve_variable_scope *import_vars; + struct sieve_variable_scope *global_vars; + + ARRAY_DEFINE(included_scripts, struct sieve_script *); +}; + +struct ext_include_ast_context *ext_include_create_ast_context + (struct sieve_ast *ast, struct sieve_ast *parent); +struct ext_include_ast_context *ext_include_get_ast_context + (struct sieve_ast *ast); + +void ext_include_ast_link_included_script + (struct sieve_ast *ast, struct sieve_script *script); + +/* + * Generator context + */ void ext_include_register_generator_context (struct sieve_generator *gentr); @@ -53,7 +76,9 @@ bool ext_include_generate_include enum ext_include_script_location location, struct sieve_script *script, unsigned *blk_id_r); -/* Interpreter */ +/* + * Interpreter context + */ void ext_include_interpreter_context_init(struct sieve_interpreter *interp); diff --git a/src/lib-sieve/plugins/include/ext-include-variables.c b/src/lib-sieve/plugins/include/ext-include-variables.c index da749379737d53c7df2f62c7cbc109f964d068b6..0d8d91c73b46c3ae50bba9db9256736b7402a147 100644 --- a/src/lib-sieve/plugins/include/ext-include-variables.c +++ b/src/lib-sieve/plugins/include/ext-include-variables.c @@ -10,54 +10,6 @@ #include "ext-include-common.h" #include "ext-include-variables.h" -/* - * Forward declarations - */ - - -/* - * AST context - */ - -struct ext_include_ast_context { - struct sieve_variable_scope *import_vars; - struct sieve_variable_scope *global_vars; -}; - -struct ext_include_ast_context *ext_include_create_ast_context -(struct sieve_ast *ast, struct sieve_ast *parent) -{ - 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, &include_extension); - - if ( parent != NULL ) { - struct ext_include_ast_context *parent_ctx = - (struct ext_include_ast_context *) - sieve_ast_extension_get_context(parent, &include_extension); - ctx->global_vars = ( parent_ctx == NULL ? NULL : parent_ctx->global_vars ); - } - - sieve_ast_extension_set_context(ast, &include_extension, ctx); - - 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, &include_extension); - - if ( ctx == NULL ) { - ctx = ext_include_create_ast_context(ast, NULL); - } - - return ctx; -} - /* * Variable import-export */ diff --git a/src/lib-sieve/plugins/include/ext-include-variables.h b/src/lib-sieve/plugins/include/ext-include-variables.h index e5aea5d86f4384108f786101bc1c993743b007e9..22f5d48539f95495c9bb67edc086f76ed10a67a8 100644 --- a/src/lib-sieve/plugins/include/ext-include-variables.h +++ b/src/lib-sieve/plugins/include/ext-include-variables.h @@ -6,13 +6,6 @@ #include "ext-include-common.h" -/* - * AST Context - */ - -struct ext_include_ast_context *ext_include_create_ast_context - (struct sieve_ast *ast, struct sieve_ast *parent); - /* * Variable import-export */ diff --git a/src/lib-sieve/sieve-ast.c b/src/lib-sieve/sieve-ast.c index e1fb2850be8cda9e4148be5ca10b9d40f2c1aded..6f3a48f8363396f1a151c6bb7fc0d28dd00ed288 100644 --- a/src/lib-sieve/sieve-ast.c +++ b/src/lib-sieve/sieve-ast.c @@ -16,11 +16,11 @@ static struct sieve_ast_node *sieve_ast_node_create (struct sieve_ast *ast, struct sieve_ast_node *parent, enum sieve_ast_type type, unsigned int source_line); -/* Links to other objects (notified if AST is destroyed) */ +/* Extensions to the AST */ -struct sieve_ast_node_link { - struct sieve_ast_node *node; - const struct sieve_ast_node_object *object; +struct sieve_ast_extension_reg { + const struct sieve_ast_extension *ast_ext; + void *context; }; /* The AST object */ @@ -33,9 +33,7 @@ struct sieve_ast { struct sieve_ast_node *root; - ARRAY_DEFINE(ext_contexts, void *); - - ARRAY_DEFINE(node_links, struct sieve_ast_node_link); + ARRAY_DEFINE(extensions, struct sieve_ast_extension_reg); }; struct sieve_ast *sieve_ast_create(struct sieve_script *script) @@ -54,22 +52,11 @@ 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->node_links, pool, 4); - p_array_init(&ast->ext_contexts, pool, sieve_extensions_get_count()); + p_array_init(&ast->extensions, pool, sieve_extensions_get_count()); return ast; } -void sieve_ast_link_object -(struct sieve_ast_node *node, const struct sieve_ast_node_object *obj) -{ - struct sieve_ast_node_link link; - - link.node = node; - link.object = obj; - array_append(&node->ast->node_links, &link, 1); -} - void sieve_ast_ref(struct sieve_ast *ast) { ast->refcount++; @@ -77,8 +64,8 @@ void sieve_ast_ref(struct sieve_ast *ast) void sieve_ast_unref(struct sieve_ast **ast) { - unsigned int i, lcount; - const struct sieve_ast_node_link *node_links; + unsigned int i, ext_count; + const struct sieve_ast_extension_reg *extrs; i_assert((*ast)->refcount > 0); @@ -88,12 +75,14 @@ void sieve_ast_unref(struct sieve_ast **ast) /* Release script reference */ sieve_script_unref(&(*ast)->script); - /* Signal linked objects that the AST is being destroyed */ - node_links = array_get(&(*ast)->node_links, &lcount); - for ( i = 0; i < lcount; i++ ) { - node_links[i].object->ast_destroy(*ast, node_links[i].node); + /* Signal registered extensions that the AST is being destroyed */ + extrs = array_get(&(*ast)->extensions, &ext_count); + for ( i = 0; i < ext_count; i++ ) { + if ( extrs[i].ast_ext != NULL && + extrs[i].ast_ext->free != NULL ) + extrs[i].ast_ext->free(*ast, extrs[i].context); } - + /* Destroy AST */ pool_unref(&(*ast)->pool); @@ -129,24 +118,32 @@ const char *sieve_ast_type_name(enum sieve_ast_type ast_type) { /* Extension support */ -void sieve_ast_extension_set_context -(struct sieve_ast *ast, const struct sieve_extension *ext, void *context) +void sieve_ast_extension_register +(struct sieve_ast *ast, const struct sieve_ast_extension *ast_ext, void *context) { - array_idx_set(&ast->ext_contexts, (unsigned int) *ext->id, &context); + struct sieve_ast_extension_reg reg; + int ext_id = *ast_ext->ext->id; + + if ( ext_id < 0 ) return; + + reg.ast_ext = ast_ext; + reg.context = context; + + array_idx_set(&ast->extensions, (unsigned int) ext_id, ®); } -const void *sieve_ast_extension_get_context +void *sieve_ast_extension_get_context (struct sieve_ast *ast, const struct sieve_extension *ext) { int ext_id = *ext->id; - void * const *ctx; + const struct sieve_ast_extension_reg *reg; - if ( ext_id < 0 || ext_id >= (int) array_count(&ast->ext_contexts) ) + if ( ext_id < 0 || ext_id >= (int) array_count(&ast->extensions) ) return NULL; - ctx = array_idx(&ast->ext_contexts, (unsigned int) ext_id); + reg = array_idx(&ast->extensions, (unsigned int) ext_id); - return *ctx; + return reg->context; } /* AST-based error reporting */ diff --git a/src/lib-sieve/sieve-ast.h b/src/lib-sieve/sieve-ast.h index 55e1b1112dc6c93f27421961932b70fdf21f7dc9..36c5d3cca8ff4b351ac969ae05189725deddff8d 100644 --- a/src/lib-sieve/sieve-ast.h +++ b/src/lib-sieve/sieve-ast.h @@ -148,8 +148,10 @@ struct sieve_ast_node { struct sieve_command_context *context; }; -struct sieve_ast_node_object { - void (*ast_destroy)(struct sieve_ast *ast, struct sieve_ast_node *node); +struct sieve_ast_extension { + const struct sieve_extension *ext; + + void (*free)(struct sieve_ast *ast, void *context); }; struct sieve_ast; @@ -159,9 +161,6 @@ struct sieve_ast *sieve_ast_create(struct sieve_script *script); void sieve_ast_ref(struct sieve_ast *ast); void sieve_ast_unref(struct sieve_ast **ast); -void sieve_ast_link_object - (struct sieve_ast_node *node, const struct sieve_ast_node_object *obj); - struct sieve_ast_node *sieve_ast_root(struct sieve_ast *ast); pool_t sieve_ast_pool(struct sieve_ast *ast); struct sieve_script *sieve_ast_script(struct sieve_ast *ast); @@ -169,9 +168,10 @@ struct sieve_script *sieve_ast_script(struct sieve_ast *ast); const char *sieve_ast_type_name(enum sieve_ast_type ast_type); /* extension support */ -void sieve_ast_extension_set_context - (struct sieve_ast *ast, const struct sieve_extension *ext, void *context); -const void *sieve_ast_extension_get_context +void sieve_ast_extension_register + (struct sieve_ast *ast, const struct sieve_ast_extension *ast_ext, + void *context); +void *sieve_ast_extension_get_context (struct sieve_ast *ast, const struct sieve_extension *ext); /* error reporting */