diff --git a/src/lib-sieve/plugins/include/cmd-include.c b/src/lib-sieve/plugins/include/cmd-include.c index 40ae8c8ed1a53e1c5b9462cd261b08f5f078a659..c3cb1569c97f27564d144fb624a013c2025d78ca 100644 --- a/src/lib-sieve/plugins/include/cmd-include.c +++ b/src/lib-sieve/plugins/include/cmd-include.c @@ -68,8 +68,8 @@ const struct sieve_opcode include_opcode = { struct cmd_include_context_data { enum { LOCATION_PERSONAL, LOCATION_GLOBAL } location; bool location_assigned; - struct sieve_script *script; - struct sieve_ast *ast; + const char *script_name; + const char *script_path; }; /* Tags */ @@ -158,12 +158,11 @@ static bool cmd_include_pre_validate static bool cmd_include_validate(struct sieve_validator *validator, struct sieve_command_context *cmd) { + pool_t pool = sieve_command_pool(cmd); struct sieve_ast_argument *arg = cmd->first_positional; struct cmd_include_context_data *ctx_data = (struct cmd_include_context_data *) cmd->data; - const char *script_name, *script_path; - struct sieve_ast *ast; - + if ( !sieve_validate_positional_argument (validator, cmd, arg, "value", 1, SAAT_STRING) ) { return FALSE; @@ -171,27 +170,20 @@ static bool cmd_include_validate(struct sieve_validator *validator, /* Get script path */ - script_name = sieve_ast_argument_strc(arg); + ctx_data->script_name = sieve_ast_argument_strc(arg); /* FIXME: Hardcoded */ #define HARDCODED_DIR "src/lib-sieve/plugins/include/" if ( ctx_data->location == LOCATION_PERSONAL ) - script_path = t_strconcat - (HARDCODED_DIR, script_name, ".sieve", NULL); + ctx_data->script_path = p_strconcat + (pool, HARDCODED_DIR, ctx_data->script_name, ".sieve", NULL); else if ( ctx_data->location == LOCATION_GLOBAL ) - script_path = t_strconcat - (HARDCODED_DIR, script_name, ".sieve", NULL); + ctx_data->script_path = p_strconcat + (pool, HARDCODED_DIR, ctx_data->script_name, ".sieve", NULL); else return FALSE; - - /* Validate */ - if ( !ext_include_validate_include - (validator, cmd, script_path, script_name, &ast) ) { - return FALSE; - } - - ctx_data->ast = ast; - sieve_validator_argument_activate(validator, arg); + + arg = sieve_ast_arguments_detach(arg, 1); return TRUE; } @@ -201,8 +193,17 @@ static bool cmd_include_validate(struct sieve_validator *validator, */ static bool cmd_include_generate - (struct sieve_generator *generator, struct sieve_command_context *ctx) + (struct sieve_generator *generator, struct sieve_command_context *cmd) { + struct cmd_include_context_data *ctx_data = + (struct cmd_include_context_data *) cmd->data; + + /* Generate */ + if ( !ext_include_generate_include + (generator, cmd, ctx_data->script_path, ctx_data->script_name) ) { + return FALSE; + } + 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 ed10681ad8bdf8fa4aa72041a9fde496cfb6b490..059c5051c85cef86e34bcf718b7700d18616181d 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.c +++ b/src/lib-sieve/plugins/include/ext-include-common.c @@ -3,42 +3,41 @@ #include "sieve-script.h" #include "sieve-ast.h" #include "sieve-commands.h" -#include "sieve-parser.h" -#include "sieve-validator.h" +#include "sieve-generator.h" #include "ext-include-common.h" -/* Validator context management */ +/* Generator context management */ static struct ext_include_main_context *ext_include_create_main_context -(struct sieve_validator *validator) +(struct sieve_generator *gentr) { - pool_t pool = sieve_validator_pool(validator); + pool_t pool = sieve_generator_pool(gentr); struct ext_include_main_context *ctx = p_new(pool, struct ext_include_main_context, 1); - ctx->validator = validator; + ctx->generator = gentr; ctx->included_scripts = hash_create (pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp); return ctx; } -static struct ext_include_validator_context * - ext_include_create_validator_context -(struct sieve_validator *validator, - struct ext_include_validator_context *parent, struct sieve_script *script) +static struct ext_include_generator_context * + ext_include_create_generator_context +(struct sieve_generator *gentr, struct ext_include_generator_context *parent, + struct sieve_script *script) { - struct ext_include_validator_context *ctx; + struct ext_include_generator_context *ctx; - pool_t pool = sieve_validator_pool(validator); - ctx = p_new(pool, struct ext_include_validator_context, 1); + pool_t pool = sieve_generator_pool(gentr); + ctx = p_new(pool, struct ext_include_generator_context, 1); ctx->parent = parent; ctx->script = script; if ( parent == NULL ) { ctx->nesting_level = 0; - ctx->main = ext_include_create_main_context(validator); + ctx->main = ext_include_create_main_context(gentr); } else { ctx->nesting_level = parent->nesting_level + 1; ctx->main = parent->main; @@ -47,40 +46,38 @@ static struct ext_include_validator_context * return ctx; } -inline struct ext_include_validator_context * - ext_include_get_validator_context -(struct sieve_validator *validator) +inline struct ext_include_generator_context *ext_include_get_generator_context +(struct sieve_generator *gentr) { - return (struct ext_include_validator_context *) - sieve_validator_extension_get_context(validator, ext_include_my_id); + return (struct ext_include_generator_context *) + sieve_generator_extension_get_context(gentr, ext_include_my_id); } -void ext_include_register_validator_context -(struct sieve_validator *validator, struct sieve_script *script) +void ext_include_register_generator_context(struct sieve_generator *gentr) { - struct ext_include_validator_context *ctx = - ext_include_get_validator_context(validator); + struct ext_include_generator_context *ctx = + ext_include_get_generator_context(gentr); + struct sieve_script *script = sieve_generator_script(gentr); if ( ctx == NULL ) { - ctx = ext_include_create_validator_context(validator, NULL, script); + ctx = ext_include_create_generator_context(gentr, NULL, script); - sieve_validator_extension_set_context - (validator, ext_include_my_id, (void *) ctx); + sieve_generator_extension_set_context + (gentr, ext_include_my_id, (void *) ctx); } } -bool ext_include_validate_include -(struct sieve_validator *validator, struct sieve_command_context *cmd, - const char *script_path, const char *script_name, struct sieve_ast **ast_r) +bool ext_include_generate_include +(struct sieve_generator *gentr, struct sieve_command_context *cmd, + const char *script_path, const char *script_name) { bool result = TRUE; struct sieve_script *script; - struct sieve_validator *subvalid; - struct ext_include_validator_context *parent = - ext_include_get_validator_context(validator); - struct ext_include_validator_context *ctx; - struct sieve_error_handler *ehandler = - sieve_validator_get_error_handler(validator); + struct sieve_ast *ast; + struct ext_include_generator_context *parent = + ext_include_get_generator_context(gentr); + struct ext_include_generator_context *ctx; + struct sieve_error_handler *ehandler = sieve_generator_error_handler(gentr); /* Do not include more scripts when errors have occured already. */ if ( sieve_get_errors(ehandler) > 0 ) @@ -91,15 +88,12 @@ bool ext_include_validate_include == NULL ) return FALSE; - *ast_r = NULL; - /* Check for circular include */ ctx = parent; while ( ctx != NULL ) { if ( sieve_script_equals(ctx->script, script) ) { - sieve_command_validate_error - (validator, cmd, "circular include"); + sieve_command_generate_error(gentr, cmd, "circular include"); sieve_script_unref(&script); return FALSE; @@ -107,34 +101,24 @@ bool ext_include_validate_include ctx = ctx->parent; } - - /* Parse script */ - - if ( (*ast_r = sieve_parse(script, ehandler)) == NULL ) { - sieve_command_validate_error - (validator, cmd, "parse failed for included script '%s'", script_name); - sieve_script_unref(&script); - return FALSE; + + /* Parse */ + if ( (ast = sieve_parse(script, ehandler)) == NULL ) { + sieve_command_generate_error(gentr, cmd, + "failed to parse included script '%s'", script_name); + return NULL; } - - /* AST now holds a reference, so we can drop it already */ - sieve_script_unref(&script); - - /* Validate script */ - subvalid = sieve_validator_create(*ast_r, ehandler); - ctx = ext_include_create_validator_context(subvalid, parent, script); - sieve_validator_extension_set_context(subvalid, ext_include_my_id, ctx); - - if ( !sieve_validator_run(subvalid) || sieve_get_errors(ehandler) > 0 ) { - sieve_command_validate_error - (validator, cmd, "validation failed for included script '%s'", - script_name); - sieve_ast_unref(ast_r); - result = FALSE; - } + /* Validate */ + if ( !sieve_validate(ast, ehandler) ) { + sieve_command_generate_error(gentr, cmd, + "failed to validate included script '%s'", script_name); - sieve_validator_free(&subvalid); + sieve_ast_unref(&ast); + return NULL; + } + + sieve_ast_unref(&ast); 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 b4f1d51c2e6d147974fbd2f8fa2f3c4fcb3e5ef4..958e25fd42b8b1d63fa7905e5cb5ff370fd7761d 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.h +++ b/src/lib-sieve/plugins/include/ext-include-common.h @@ -12,24 +12,24 @@ extern int ext_include_my_id; extern const struct sieve_extension include_extension; struct ext_include_main_context { - struct sieve_validator *validator; + struct sieve_generator *generator; struct hash_table *included_scripts; }; -struct ext_include_validator_context { +struct ext_include_generator_context { unsigned int nesting_level; struct sieve_script *script; struct ext_include_main_context *main; - struct ext_include_validator_context *parent; + struct ext_include_generator_context *parent; }; -inline struct ext_include_validator_context *ext_include_get_validator_context - (struct sieve_validator *validator); -void ext_include_register_validator_context - (struct sieve_validator *validator, struct sieve_script *script); +inline struct ext_include_generator_context *ext_include_get_generator_context + (struct sieve_generator *gentr); +void ext_include_register_generator_context + (struct sieve_generator *gentr); -bool ext_include_validate_include - (struct sieve_validator *validator, struct sieve_command_context *cmd, - const char *script_path, const char *script_name, struct sieve_ast **ast_r); +bool ext_include_generate_include + (struct sieve_generator *gentr, struct sieve_command_context *cmd, + const char *script_path, const char *script_name); #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 6e3b02efb1f8533a48b2320355c1db6d246529b7..ea1156cdf715ba5edeb6a3c42f8c406d336b574e 100644 --- a/src/lib-sieve/plugins/include/ext-include.c +++ b/src/lib-sieve/plugins/include/ext-include.c @@ -24,6 +24,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); /* Commands */ @@ -46,7 +47,8 @@ const struct sieve_extension include_extension = { "include", ext_include_load, ext_include_validator_load, - NULL, NULL, NULL, + ext_include_generator_load, + NULL, NULL, SIEVE_EXT_DEFINE_OPCODES(ext_include_opcodes), NULL }; @@ -65,9 +67,15 @@ static bool ext_include_validator_load(struct sieve_validator *validator) /* Register new commands */ sieve_validator_register_command(validator, &cmd_include); sieve_validator_register_command(validator, &cmd_return); - - ext_include_register_validator_context(validator, - sieve_validator_get_script(validator)); + + return TRUE; +} + +/* Load extension into generator */ + +static bool ext_include_generator_load(struct sieve_generator *gentr) +{ + ext_include_register_generator_context(gentr); return TRUE; } diff --git a/src/lib-sieve/plugins/include/included1.sieve b/src/lib-sieve/plugins/include/included1.sieve index 41e84c2dd55cd8cad0014048576bca7a2e9f35c4..a544e2742d7b0a2a311b9a6f10410079ecf94384 100644 --- a/src/lib-sieve/plugins/include/included1.sieve +++ b/src/lib-sieve/plugins/include/included1.sieve @@ -1,3 +1,3 @@ require "fileinto"; -fileinto "INBOX.frop"; +fileinto "INBOX.frop" diff --git a/src/lib-sieve/sieve-ast.c b/src/lib-sieve/sieve-ast.c index 1a59e6ec555255e465be5698f7166a8de26e5748..500a0717f1f6a0e0ce17663831a4a493021c04d3 100644 --- a/src/lib-sieve/sieve-ast.c +++ b/src/lib-sieve/sieve-ast.c @@ -88,6 +88,20 @@ const char *sieve_ast_type_name(enum sieve_ast_type ast_type) { } } +/* AST-based error reporting */ + +void sieve_ast_error +(struct sieve_error_handler *ehandler, sieve_error_vfunc_t vfunc, + struct sieve_ast_node *node, const char *fmt, va_list args) +{ + struct sieve_script *script = node->ast->script; + + T_FRAME(vfunc(ehandler, + t_strdup_printf("%s:%d", sieve_script_name(script), + sieve_ast_node_line(node)), fmt, args)); +} + + /* Very simplistic linked list implementation */ #define __LIST_CREATE(pool, type) { \ diff --git a/src/lib-sieve/sieve-ast.h b/src/lib-sieve/sieve-ast.h index 83a5259ed797e07f9ea6088ace65ca9537d81266..4268bb8fed504cabdcab84dcaab4051984561933 100644 --- a/src/lib-sieve/sieve-ast.h +++ b/src/lib-sieve/sieve-ast.h @@ -163,6 +163,11 @@ inline pool_t sieve_ast_pool(struct sieve_ast *ast); inline struct sieve_script *sieve_ast_script(struct sieve_ast *ast); const char *sieve_ast_type_name(enum sieve_ast_type ast_type); + +/* error reporting */ +void sieve_ast_error +(struct sieve_error_handler *ehandler, sieve_error_vfunc_t vfunc, + struct sieve_ast_node *node, const char *fmt, va_list args); /* sieve_ast_argument */ struct sieve_ast_argument *sieve_ast_argument_string_create diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c index 4c3d0b6ec4304682d1333a8a0f8d3745559d13d2..e20441e26353cd0ed1934983542a350197aec15b 100644 --- a/src/lib-sieve/sieve-binary.c +++ b/src/lib-sieve/sieve-binary.c @@ -41,6 +41,8 @@ struct sieve_binary_extension { struct sieve_binary { pool_t pool; + struct sieve_script *script; + /* When the binary is loaded into memory or when it is being constructed by * the generator, extensions will be associated to the binary. The extensions * array is a sequential lit of all used extensions. The extension_index @@ -73,7 +75,7 @@ struct sieve_binary { size_t code_size; }; -static struct sieve_binary *sieve_binary_create(void) +static struct sieve_binary *sieve_binary_create(struct sieve_script *script) { pool_t pool; struct sieve_binary *sbin; @@ -81,6 +83,7 @@ static struct sieve_binary *sieve_binary_create(void) pool = pool_alloconly_create("sieve_binary", 4096); sbin = p_new(pool, struct sieve_binary, 1); sbin->pool = pool; + sbin->script = script; p_array_init(&sbin->extensions, pool, 5); p_array_init(&sbin->extension_index, pool, sieve_extensions_get_count()); @@ -90,9 +93,9 @@ static struct sieve_binary *sieve_binary_create(void) return sbin; } -struct sieve_binary *sieve_binary_create_new(void) +struct sieve_binary *sieve_binary_create_new(struct sieve_script *script) { - struct sieve_binary *sbin = sieve_binary_create(); + struct sieve_binary *sbin = sieve_binary_create(script); sbin->code_buffer = buffer_create_dynamic(sbin->pool, 256); sbin->data = sbin->code_buffer; @@ -123,6 +126,11 @@ inline pool_t sieve_binary_pool(struct sieve_binary *sbin) return sbin->pool; } +inline struct sieve_script *sieve_binary_script(struct sieve_binary *sbin) +{ + return sbin->script; +} + static inline void sieve_binary_set_active_block (struct sieve_binary *sbin, buffer_t *buffer) { @@ -431,7 +439,8 @@ static bool _sieve_binary_load(struct sieve_binary *sbin) return TRUE; } -struct sieve_binary *sieve_binary_load(const char *path) +struct sieve_binary *sieve_binary_load + (const char *path, struct sieve_script *script) { int fd; struct stat st; @@ -455,7 +464,7 @@ struct sieve_binary *sieve_binary_load(const char *path) } /* Create binary object */ - sbin = sieve_binary_create(); + sbin = sieve_binary_create(script); sbin->path = p_strdup(sbin->pool, path); /* Allocate memory buffer @@ -493,7 +502,8 @@ struct sieve_binary *sieve_binary_load(const char *path) sbin = NULL; } - sieve_binary_activate(sbin); + if ( sbin != NULL ) + sieve_binary_activate(sbin); return sbin; } diff --git a/src/lib-sieve/sieve-binary.h b/src/lib-sieve/sieve-binary.h index be7bd9257ce201435e1215e0e6f829493eb6048e..fd3bc54d6250a088c609c546efb019896e408cd5 100644 --- a/src/lib-sieve/sieve-binary.h +++ b/src/lib-sieve/sieve-binary.h @@ -8,17 +8,19 @@ struct sieve_binary; -struct sieve_binary *sieve_binary_create_new(void); +struct sieve_binary *sieve_binary_create_new(struct sieve_script *script); void sieve_binary_ref(struct sieve_binary *sbin); void sieve_binary_unref(struct sieve_binary **sbin); inline pool_t sieve_binary_pool(struct sieve_binary *sbin); +inline struct sieve_script *sieve_binary_script(struct sieve_binary *sbin); void sieve_binary_activate(struct sieve_binary *sbin); bool sieve_binary_save (struct sieve_binary *sbin, const char *path); -struct sieve_binary *sieve_binary_load(const char *path); +struct sieve_binary *sieve_binary_load + (const char *path, struct sieve_script *script); /* * Extension support diff --git a/src/lib-sieve/sieve-commands.h b/src/lib-sieve/sieve-commands.h index 1bfd5bfce5402b64ee7a0a167ae3fbcc6fe1aca7..8736904dc2238cd27b684ad20eca559f998efcab 100644 --- a/src/lib-sieve/sieve-commands.h +++ b/src/lib-sieve/sieve-commands.h @@ -90,6 +90,11 @@ const char *sieve_command_type_name(const struct sieve_command *command); #define sieve_command_validate_critical(validator, context, ...) \ sieve_validator_critical(validator, (context)->ast_node, __VA_ARGS__) +#define sieve_command_generate_error(gentr, context, ...) \ + sieve_generator_error(gentr, (context)->ast_node, __VA_ARGS__) +#define sieve_command_generate_critical(gentr, context, ...) \ + sieve_generator_critical(gentr, (context)->ast_node, __VA_ARGS__) + #define sieve_command_pool(context) \ sieve_ast_node_pool((context)->ast_node) diff --git a/src/lib-sieve/sieve-error.h b/src/lib-sieve/sieve-error.h index 37ab8d23ef538e801e8bb5d404aa214245e75d42..00d395f84b10fbf5872f7ff4cbb8fae3ee6dfdc8 100644 --- a/src/lib-sieve/sieve-error.h +++ b/src/lib-sieve/sieve-error.h @@ -8,6 +8,10 @@ struct sieve_error_handler; +typedef void (*sieve_error_vfunc_t) + (struct sieve_error_handler *ehandler, const char *location, + const char *fmt, va_list args); + /* For these functions it is the responsibility of the caller to * manage the datastack. */ diff --git a/src/lib-sieve/sieve-generator.c b/src/lib-sieve/sieve-generator.c index b09ca2b738a01284f4b3cb090f0f1275a9931777..7d38eef0886383bec83a6c2e724a99cb0dccf852 100644 --- a/src/lib-sieve/sieve-generator.c +++ b/src/lib-sieve/sieve-generator.c @@ -41,27 +41,47 @@ void sieve_jumplist_resolve(struct sieve_jumplist *jlist) struct sieve_generator { pool_t pool; + struct sieve_error_handler *ehandler; + struct sieve_ast *ast; + struct sieve_script *script; struct sieve_binary *binary; + + ARRAY_DEFINE(ext_contexts, void *); }; -struct sieve_generator *sieve_generator_create(struct sieve_ast *ast) +struct sieve_generator *sieve_generator_create + (struct sieve_ast *ast, struct sieve_error_handler *ehandler) { pool_t pool; - struct sieve_generator *generator; + struct sieve_generator *gentr; pool = pool_alloconly_create("sieve_generator", 4096); - generator = p_new(pool, struct sieve_generator, 1); - generator->pool = pool; + gentr = p_new(pool, struct sieve_generator, 1); + gentr->pool = pool; + gentr->ehandler = ehandler; - generator->ast = ast; + gentr->ast = ast; + gentr->script = sieve_ast_script(ast); sieve_ast_ref(ast); - generator->binary = sieve_binary_create_new(); - sieve_binary_ref(generator->binary); + /* Setup storage for extension contexts */ + array_create(&gentr->ext_contexts, pool, sizeof(void *), + sieve_extensions_get_count()); + + gentr->binary = sieve_binary_create_new(sieve_ast_script(ast)); + sieve_binary_ref(gentr->binary); - return generator; + /* Pre-load core language features implemented as 'extensions' (none) */ + /*for ( i = 0; i < sieve_preloaded_extensions_count; i++ ) { + const struct sieve_extension *ext = sieve_preloaded_extensions[i]; + + if ( ext->generator_load != NULL ) + (void)ext->generator_load(gentr); + }*/ + + return gentr; } void sieve_generator_free(struct sieve_generator *generator) @@ -71,10 +91,82 @@ void sieve_generator_free(struct sieve_generator *generator) pool_unref(&(generator->pool)); } -inline void sieve_generator_link_extension - (struct sieve_generator *generator, int ext_id) +inline struct sieve_script *sieve_generator_get_script + (struct sieve_generator *gentr) +{ + return gentr->script; +} + +/* Error handling */ + +void sieve_generator_warning +(struct sieve_generator *gentr, struct sieve_ast_node *node, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sieve_ast_error(gentr->ehandler, sieve_vwarning, node, fmt, args); + va_end(args); +} + +void sieve_generator_error +(struct sieve_generator *gentr, struct sieve_ast_node *node, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sieve_ast_error(gentr->ehandler, sieve_verror, node, fmt, args); + va_end(args); +} + +void sieve_generator_critical +(struct sieve_generator *gentr, struct sieve_ast_node *node, + const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + sieve_ast_error(gentr->ehandler, sieve_vcritical, node, fmt, args); + va_end(args); +} + +/* Extension support */ + +bool sieve_generator_link_extension + (struct sieve_generator *gentr, int ext_id) +{ + const struct sieve_extension *ext = sieve_extension_get_by_id(ext_id); + + (void)sieve_binary_extension_link(gentr->binary, ext_id); + + if ( ext == NULL ) + return FALSE; + + if ( ext->generator_load != NULL ) + return ext->generator_load(gentr); + + return TRUE; +} + +inline void sieve_generator_extension_set_context + (struct sieve_generator *gentr, int ext_id, void *context) { - (void)sieve_binary_extension_link(generator->binary, ext_id); + array_idx_set(&gentr->ext_contexts, (unsigned int) ext_id, &context); +} + +inline const void *sieve_generator_extension_get_context + (struct sieve_generator *gentr, int ext_id) +{ + void * const *ctx; + + if ( ext_id < 0 || ext_id >= (int) array_count(&gentr->ext_contexts) ) + return NULL; + + ctx = array_idx(&gentr->ext_contexts, (unsigned int) ext_id); + + return *ctx; } /* Binary access */ @@ -201,17 +293,18 @@ static bool sieve_generate_command bool sieve_generate_block (struct sieve_generator *generator, struct sieve_ast_node *block) { + bool result = TRUE; struct sieve_ast_node *command; T_FRAME( command = sieve_ast_command_first(block); - while ( command != NULL ) { - sieve_generate_command(generator, command); + while ( result && command != NULL ) { + result = sieve_generate_command(generator, command); command = sieve_ast_command_next(command); } ); - return TRUE; + return result; } struct sieve_binary *sieve_generator_run(struct sieve_generator *generator) { @@ -223,4 +316,24 @@ struct sieve_binary *sieve_generator_run(struct sieve_generator *generator) { return NULL; } +/* Accessors */ + +inline struct sieve_error_handler *sieve_generator_error_handler + (struct sieve_generator *gentr) +{ + return gentr->ehandler; +} + +inline pool_t sieve_generator_pool(struct sieve_generator *gentr) +{ + return gentr->pool; +} + +inline struct sieve_script *sieve_generator_script + (struct sieve_generator *gentr) +{ + return gentr->script; +} + + diff --git a/src/lib-sieve/sieve-generator.h b/src/lib-sieve/sieve-generator.h index e2d021913c8b449853960eb0b8f413c32e0cb53e..64b1fe6d3c546ec19d9bc33c77a1bcd3a5bad7cb 100644 --- a/src/lib-sieve/sieve-generator.h +++ b/src/lib-sieve/sieve-generator.h @@ -6,11 +6,33 @@ struct sieve_generator; -struct sieve_generator *sieve_generator_create(struct sieve_ast *ast); +struct sieve_generator *sieve_generator_create + (struct sieve_ast *ast, struct sieve_error_handler *ehandler); void sieve_generator_free(struct sieve_generator *generator); -inline void sieve_generator_link_extension - (struct sieve_generator *generator, int ext_id); +inline struct sieve_script *sieve_generator_get_script + (struct sieve_generator *gentr); + +/* Error handling */ + +void sieve_generator_warning +(struct sieve_generator *gentr, struct sieve_ast_node *node, + const char *fmt, ...) ATTR_FORMAT(3, 4);; +void sieve_generator_error +(struct sieve_generator *gentr, struct sieve_ast_node *node, + const char *fmt, ...) ATTR_FORMAT(3, 4); +void sieve_generator_critical +(struct sieve_generator *gentr, struct sieve_ast_node *node, + const char *fmt, ...) ATTR_FORMAT(3, 4); + +/* Extension support */ + +bool sieve_generator_link_extension + (struct sieve_generator *gentr, int ext_id); +inline void sieve_generator_extension_set_context + (struct sieve_generator *gentr, int ext_id, void *context); +inline const void *sieve_generator_extension_get_context + (struct sieve_generator *gentr, int ext_id); /* Jump list */ @@ -19,16 +41,22 @@ struct sieve_jumplist { ARRAY_DEFINE(jumps, sieve_size_t); }; -void sieve_jumplist_init(struct sieve_jumplist *jlist, struct sieve_binary *sbin); -void sieve_jumplist_add(struct sieve_jumplist *jlist, sieve_size_t jump); +void sieve_jumplist_init + (struct sieve_jumplist *jlist, struct sieve_binary *sbin); +void sieve_jumplist_add + (struct sieve_jumplist *jlist, sieve_size_t jump); void sieve_jumplist_resolve(struct sieve_jumplist *jlist); /* Code emission API */ -inline sieve_size_t sieve_generator_emit_data(struct sieve_generator *generator, void *data, sieve_size_t size); -inline sieve_size_t sieve_generator_emit_byte(struct sieve_generator *generator, unsigned char byte); +inline sieve_size_t sieve_generator_emit_data + (struct sieve_generator *generator, void *data, sieve_size_t size); +inline sieve_size_t sieve_generator_emit_byte + (struct sieve_generator *generator, unsigned char byte); inline void sieve_generator_update_data - (struct sieve_generator *generator, sieve_size_t address, void *data, sieve_size_t size); -inline sieve_size_t sieve_generator_get_current_address(struct sieve_generator *generator); + (struct sieve_generator *generator, sieve_size_t address, void *data, + sieve_size_t size); +inline sieve_size_t sieve_generator_get_current_address + (struct sieve_generator *generator); inline struct sieve_binary *sieve_generator_get_binary (struct sieve_generator *gentr); @@ -39,10 +67,13 @@ inline sieve_size_t sieve_generator_emit_opcode_ext /* Offset emission */ -inline sieve_size_t sieve_generator_emit_offset(struct sieve_generator *generator, int offset); -inline void sieve_generator_resolve_offset(struct sieve_generator *generator, sieve_size_t address); +inline sieve_size_t sieve_generator_emit_offset + (struct sieve_generator *generator, int offset); +inline void sieve_generator_resolve_offset + (struct sieve_generator *generator, sieve_size_t address); /* Literal emission */ + inline sieve_size_t sieve_generator_emit_byte (struct sieve_generator *generator, unsigned char btval); inline sieve_size_t sieve_generator_emit_integer @@ -52,8 +83,6 @@ inline sieve_size_t sieve_generator_emit_string /* API */ -inline void sieve_generator_register_extension - (struct sieve_generator *gnr, const struct sieve_extension *ext); bool sieve_generate_arguments(struct sieve_generator *generator, struct sieve_command_context *cmd, struct sieve_ast_argument **arg); @@ -64,5 +93,13 @@ bool sieve_generate_test struct sieve_jumplist *jlist, bool jump_true); struct sieve_binary *sieve_generator_run(struct sieve_generator *genarator); +/* Accessors */ + +inline struct sieve_error_handler *sieve_generator_error_handler + (struct sieve_generator *gentr); +inline pool_t sieve_generator_pool(struct sieve_generator *gentr); +inline struct sieve_script *sieve_generator_script + (struct sieve_generator *gentr); + #endif /* __SIEVE_GENERATOR_H */ diff --git a/src/lib-sieve/sieve-script.c b/src/lib-sieve/sieve-script.c index 03ad7c9d8185f5bc941af99659a2f22cead663af..11e4639dd9162a8c7eb4695c5d75b4f0c76f02b8 100644 --- a/src/lib-sieve/sieve-script.c +++ b/src/lib-sieve/sieve-script.c @@ -35,23 +35,22 @@ struct sieve_script *sieve_script_create pool_t pool; struct stat st; struct sieve_script *script; - const char *dirpath; + const char *filename, *dirpath; T_FRAME( + /* Extract filename from path */ + filename = strrchr(path, '/'); + if ( filename == NULL ) { + dirpath = ""; + filename = path; + } else { + dirpath = t_strdup_until(path, filename); + filename++; + } + if ( name == NULL || *name == '\0' ) { - const char *filename; const char *ext; - /* Extract filename from path */ - filename = strrchr(path, '/'); - if ( filename == NULL ) { - dirpath = ""; - filename = path; - } else { - dirpath = t_strdup_until(path, filename); - filename++; - } - /* Extract the script name */ ext = strrchr(filename, '.'); if ( ext == NULL || ext == filename || strncmp(ext,".sieve",6) != 0 ) @@ -64,7 +63,7 @@ struct sieve_script *sieve_script_create if ( stat(path, &st) < 0 ) { if ( errno == ENOENT ) - sieve_error(ehandler, name, "sieve script does not exist"); + sieve_error(ehandler, path, "sieve script does not exist"); else sieve_critical(ehandler, path, "failed to stat sieve script: %m"); script = NULL; diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c index 6ca58191e98bee0bd159371ad5381e91b78a322e..77d0fbd74bcdfcdd79c49ba1e3a27823b1aa9a8f 100644 --- a/src/lib-sieve/sieve-validator.c +++ b/src/lib-sieve/sieve-validator.c @@ -40,12 +40,9 @@ void sieve_validator_warning const char *fmt, ...) { va_list args; - va_start(args, fmt); - - T_FRAME(sieve_vwarning(validator->ehandler, - t_strdup_printf("%s:%d", sieve_script_name(validator->script), - sieve_ast_node_line(node)), fmt, args)); + va_start(args, fmt); + sieve_ast_error(validator->ehandler, sieve_vwarning, node, fmt, args); va_end(args); } @@ -54,12 +51,9 @@ void sieve_validator_error const char *fmt, ...) { va_list args; - va_start(args, fmt); - - T_FRAME(sieve_verror(validator->ehandler, - t_strdup_printf("%s:%d", sieve_script_name(validator->script), - sieve_ast_node_line(node)), fmt, args)); + va_start(args, fmt); + sieve_ast_error(validator->ehandler, sieve_verror, node, fmt, args); va_end(args); } @@ -68,12 +62,9 @@ void sieve_validator_critical const char *fmt, ...) { va_list args; - va_start(args, fmt); - - T_FRAME(sieve_vcritical(validator->ehandler, - t_strdup_printf("%s:%d", sieve_script_name(validator->script), - sieve_ast_node_line(node)), fmt, args)); + va_start(args, fmt); + sieve_ast_error(validator->ehandler, sieve_vcritical, node, fmt, args); va_end(args); } @@ -100,6 +91,12 @@ struct sieve_validator *sieve_validator_create array_create(&validator->ext_contexts, pool, sizeof(void *), sieve_extensions_get_count()); + /* Setup command registry */ + validator->commands = hash_create + (pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp); + sieve_validator_register_core_commands(validator); + sieve_validator_register_core_tests(validator); + /* Pre-load core language features implemented as 'extensions' */ for ( i = 0; i < sieve_preloaded_extensions_count; i++ ) { const struct sieve_extension *ext = sieve_preloaded_extensions[i]; @@ -107,13 +104,7 @@ struct sieve_validator *sieve_validator_create if ( ext->validator_load != NULL ) (void)ext->validator_load(validator); } - - /* Setup command registry */ - validator->commands = hash_create - (pool, pool, 0, str_hash, (hash_cmp_callback_t *)strcmp); - sieve_validator_register_core_commands(validator); - sieve_validator_register_core_tests(validator); - + return validator; } @@ -132,19 +123,19 @@ inline pool_t sieve_validator_pool(struct sieve_validator *validator) return validator->pool; } -inline struct sieve_error_handler *sieve_validator_get_error_handler +inline struct sieve_error_handler *sieve_validator_error_handler (struct sieve_validator *validator) { return validator->ehandler; } -inline struct sieve_ast *sieve_validator_get_ast +inline struct sieve_ast *sieve_validator_ast (struct sieve_validator *validator) { return validator->ast; } -inline struct sieve_script *sieve_validator_get_script +inline struct sieve_script *sieve_validator_script (struct sieve_validator *validator) { return validator->script; diff --git a/src/lib-sieve/sieve-validator.h b/src/lib-sieve/sieve-validator.h index dbeb709898f2bdc9c6467eaaf49b615b6befbe9d..4072ff5c1a798ef7190135a141b45b004a0a1d33 100644 --- a/src/lib-sieve/sieve-validator.h +++ b/src/lib-sieve/sieve-validator.h @@ -14,11 +14,11 @@ struct sieve_validator *sieve_validator_create void sieve_validator_free(struct sieve_validator **validator); inline pool_t sieve_validator_pool(struct sieve_validator *validator); -inline struct sieve_error_handler *sieve_validator_get_error_handler +inline struct sieve_error_handler *sieve_validator_error_handler (struct sieve_validator *validator); -inline struct sieve_ast *sieve_validator_get_ast +inline struct sieve_ast *sieve_validator_ast (struct sieve_validator *validator); -inline struct sieve_script *sieve_validator_get_script +inline struct sieve_script *sieve_validator_script (struct sieve_validator *validator); bool sieve_validator_run(struct sieve_validator *validator); diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c index f2bc2c76db24fee953ccd0e12e9b10c921a2188c..55c9caea4c13383df24aed69b11ff33064c80dbf 100644 --- a/src/lib-sieve/sieve.c +++ b/src/lib-sieve/sieve.c @@ -57,7 +57,7 @@ struct sieve_ast *sieve_parse return ast; } -static bool sieve_validate(struct sieve_ast *ast, struct sieve_error_handler *ehandler) +bool sieve_validate(struct sieve_ast *ast, struct sieve_error_handler *ehandler) { bool result = TRUE; struct sieve_validator *validator = sieve_validator_create(ast, ehandler); @@ -70,9 +70,10 @@ static bool sieve_validate(struct sieve_ast *ast, struct sieve_error_handler *eh return result; } -static struct sieve_binary *sieve_generate(struct sieve_ast *ast) +static struct sieve_binary *sieve_generate + (struct sieve_ast *ast, struct sieve_error_handler *ehandler) { - struct sieve_generator *generator = sieve_generator_create(ast); + struct sieve_generator *generator = sieve_generator_create(ast, ehandler); struct sieve_binary *result; result = sieve_generator_run(generator); @@ -103,7 +104,7 @@ static struct sieve_binary *sieve_compile_script } /* Generate */ - if ( (sbin=sieve_generate(ast)) == NULL ) { + if ( (sbin=sieve_generate(ast, ehandler)) == NULL ) { sieve_error(ehandler, sieve_script_name(script), "code generation failed"); sieve_ast_unref(&ast); @@ -146,7 +147,7 @@ struct sieve_binary *sieve_open T_FRAME( binpath = sieve_script_binpath(script); - sbin = sieve_binary_load(binpath); + sbin = sieve_binary_load(binpath, script); if ( sbin == NULL ) { sbin = sieve_compile_script(script, ehandler); diff --git a/src/sieve-bin/sieved.c b/src/sieve-bin/sieved.c index fc0527345470c613b183a0bd2546234d8e66490c..566e8d7536159dc9502ce4c4a90d29201f9439a3 100644 --- a/src/sieve-bin/sieved.c +++ b/src/sieve-bin/sieved.c @@ -45,7 +45,7 @@ int main(int argc, char **argv) { bin_init(); - sbin = sieve_binary_load(binfile); + sbin = sieve_binary_load(binfile, NULL); if ( sbin != NULL ) { bin_dump_sieve_binary_to(sbin, outfile == NULL ? "-" : outfile);