From 47ce4d8c34b231cfe18a02b2cdba4d4b9bd304c7 Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Fri, 10 Apr 2009 19:16:07 +0200 Subject: [PATCH] Include: added skeleton :once modifier. --- src/lib-sieve/plugins/include/cmd-include.c | 54 ++++++++++++++++--- .../plugins/include/ext-include-common.c | 16 ++++-- .../plugins/include/ext-include-common.h | 2 +- src/lib-sieve/sieve-binary-dumper.c | 2 +- .../extensions/include/included/once-1.sieve | 9 ++++ .../extensions/include/included/once-2.sieve | 12 +++++ tests/extensions/include/once.svtest | 20 +++++++ 7 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 tests/extensions/include/included/once-1.sieve create mode 100644 tests/extensions/include/included/once-2.sieve create mode 100644 tests/extensions/include/once.svtest diff --git a/src/lib-sieve/plugins/include/cmd-include.c b/src/lib-sieve/plugins/include/cmd-include.c index 730acf0b7..5dbb27ceb 100644 --- a/src/lib-sieve/plugins/include/cmd-include.c +++ b/src/lib-sieve/plugins/include/cmd-include.c @@ -76,6 +76,9 @@ const struct sieve_operation include_operation = { struct cmd_include_context_data { enum ext_include_script_location location; bool location_assigned; + + bool include_once; + struct sieve_script *script; }; @@ -101,6 +104,17 @@ static const struct sieve_argument include_global_tag = { NULL, NULL }; +static bool cmd_include_validate_once_tag + (struct sieve_validator *validator, struct sieve_ast_argument **arg, + struct sieve_command_context *cmd); + +static const struct sieve_argument include_once_tag = { + "once", + NULL, NULL, + cmd_include_validate_once_tag, + NULL, NULL +}; + /* * Tag validation */ @@ -134,6 +148,21 @@ static bool cmd_include_validate_location_tag return TRUE; } +static bool cmd_include_validate_once_tag +(struct sieve_validator *validator ATTR_UNUSED, struct sieve_ast_argument **arg, + struct sieve_command_context *cmd) +{ + struct cmd_include_context_data *ctx_data = + (struct cmd_include_context_data *) cmd->data; + + ctx_data->include_once = TRUE; + + /* Delete this tag (for now) */ + *arg = sieve_ast_arguments_detach(*arg, 1); + + return TRUE; +} + /* * Command registration */ @@ -145,6 +174,8 @@ static bool cmd_include_registered (validator, cmd_reg, &include_personal_tag, 0); sieve_validator_register_tag (validator, cmd_reg, &include_global_tag, 0); + sieve_validator_register_tag + (validator, cmd_reg, &include_once_tag, 0); return TRUE; } @@ -240,6 +271,7 @@ static bool cmd_include_generate struct cmd_include_context_data *ctx_data = (struct cmd_include_context_data *) cmd->data; const struct ext_include_script_info *included; + unsigned int flags = ctx_data->include_once; /* Compile (if necessary) and include the script into the binary. * This yields the id of the binary block containing the compiled byte code. @@ -250,6 +282,7 @@ static bool cmd_include_generate (void)sieve_operation_emit_code(cgenv->sbin, &include_operation); (void)sieve_binary_emit_unsigned(cgenv->sbin, included->id); + (void)sieve_binary_emit_byte(cgenv->sbin, flags); return TRUE; } @@ -264,7 +297,7 @@ static bool opc_include_dump { const struct ext_include_script_info *included; struct ext_include_binary_context *binctx; - unsigned int include_id; + unsigned int include_id, flags; sieve_code_dumpf(denv, "INCLUDE:"); @@ -272,15 +305,19 @@ static bool opc_include_dump if ( !sieve_binary_read_unsigned(denv->sbin, address, &include_id) ) return FALSE; + if ( !sieve_binary_read_byte(denv->sbin, address, &flags) ) + return FALSE; + binctx = ext_include_binary_get_context(denv->sbin); included = ext_include_binary_script_get_included(binctx, include_id); if ( included == NULL ) return FALSE; sieve_code_descend(denv); - sieve_code_dumpf(denv, "script: %s [ID: %d, BLOCK: %d]", - sieve_script_filename(included->script), include_id, included->block_id); - + sieve_code_dumpf(denv, "script: %s %s[ID: %d, BLOCK: %d]", + sieve_script_filename(included->script), (flags & 0x01 ? "(once) " : ""), + include_id, included->block_id); + return TRUE; } @@ -292,14 +329,19 @@ static int opc_include_execute (const struct sieve_operation *op ATTR_UNUSED, const struct sieve_runtime_env *renv, sieve_size_t *address) { - unsigned int include_id; + unsigned int include_id, flags; if ( !sieve_binary_read_unsigned(renv->sbin, address, &include_id) ) { sieve_runtime_trace_error(renv, "invalid include-id operand"); return SIEVE_EXEC_BIN_CORRUPT; } + + if ( !sieve_binary_read_unsigned(renv->sbin, address, &flags) ) { + sieve_runtime_trace_error(renv, "invalid flags operand"); + return SIEVE_EXEC_BIN_CORRUPT; + } - return ext_include_execute_include(renv, include_id); + return ext_include_execute_include(renv, include_id, flags & 0x01); } diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c index 8486a4146..f6786253d 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.c +++ b/src/lib-sieve/plugins/include/ext-include-common.c @@ -453,7 +453,7 @@ bool ext_include_generate_include */ bool ext_include_execute_include - (const struct sieve_runtime_env *renv, unsigned int include_id) +(const struct sieve_runtime_env *renv, unsigned int include_id, bool once) { int result = TRUE; struct ext_include_interpreter_context *ctx; @@ -472,8 +472,8 @@ bool ext_include_execute_include ctx = ext_include_get_interpreter_context(renv->interp); block_id = included->block_id; - sieve_runtime_trace(renv, "INCLUDE command (id: %d, script: %s, block: %d)", - include_id, sieve_script_name(included->script), block_id); + sieve_runtime_trace(renv, "INCLUDE command (script: %s, id: %d block: %d) START::", + sieve_script_name(included->script), include_id, block_id); if ( ctx->parent == NULL ) { struct ext_include_interpreter_context *curctx = NULL; @@ -514,11 +514,15 @@ bool ext_include_execute_include */ if ( result > 0 && interrupted && !curctx->returned ) { while ( result > 0 ) { + if ( ( (interrupted && curctx->returned) || (!interrupted) ) && curctx->parent != NULL ) { /* Sub-interpreter ended or executed return */ + sieve_runtime_trace(renv, "INCLUDE command (block: %d) END ::", + curctx->block_id); + /* Ascend interpreter stack */ curctx = curctx->parent; sieve_interpreter_free(&subinterp); @@ -534,6 +538,7 @@ bool ext_include_execute_include /* Continue parent */ curctx->inc_block_id = 0; curctx->returned = FALSE; + result = ( sieve_interpreter_continue(subinterp, &interrupted) == 1 ); } else { if ( curctx->inc_block_id >= SBIN_SYSBLOCK_LAST ) { @@ -577,8 +582,9 @@ bool ext_include_execute_include } } } - } - + } else + sieve_runtime_trace(renv, "INCLUDE command (block: %d) END ::", curctx->block_id); + /* Free any sub-interpreters that might still be active */ while ( curctx != NULL && curctx->parent != NULL ) { struct ext_include_interpreter_context *nextctx = curctx->parent; diff --git a/src/lib-sieve/plugins/include/ext-include-common.h b/src/lib-sieve/plugins/include/ext-include-common.h index 128fdd09c..5d2e8d84f 100644 --- a/src/lib-sieve/plugins/include/ext-include-common.h +++ b/src/lib-sieve/plugins/include/ext-include-common.h @@ -101,7 +101,7 @@ bool ext_include_generate_include void ext_include_interpreter_context_init(struct sieve_interpreter *interp); bool ext_include_execute_include - (const struct sieve_runtime_env *renv, unsigned int block_id); + (const struct sieve_runtime_env *renv, unsigned int block_id, bool once); void ext_include_execute_return(const struct sieve_runtime_env *renv); struct sieve_variable_storage *ext_include_interpreter_get_global_variables diff --git a/src/lib-sieve/sieve-binary-dumper.c b/src/lib-sieve/sieve-binary-dumper.c index 7dd31a023..89a041a97 100644 --- a/src/lib-sieve/sieve-binary-dumper.c +++ b/src/lib-sieve/sieve-binary-dumper.c @@ -132,7 +132,7 @@ bool sieve_binary_dumper_run /* Dump main program */ - sieve_binary_dump_sectionf(denv, "Main program"); + sieve_binary_dump_sectionf(denv, "Main program (block: %d)", SBIN_SYSBLOCK_MAIN_PROGRAM); if ( !sieve_binary_block_set_active(sbin, SBIN_SYSBLOCK_MAIN_PROGRAM, NULL) ) { return FALSE; diff --git a/tests/extensions/include/included/once-1.sieve b/tests/extensions/include/included/once-1.sieve new file mode 100644 index 000000000..288d1412c --- /dev/null +++ b/tests/extensions/include/included/once-1.sieve @@ -0,0 +1,9 @@ +require "include"; +require "variables"; + +global "result"; + +set "result" "${result} ONE"; + +return; + diff --git a/tests/extensions/include/included/once-2.sieve b/tests/extensions/include/included/once-2.sieve new file mode 100644 index 000000000..226df6de3 --- /dev/null +++ b/tests/extensions/include/included/once-2.sieve @@ -0,0 +1,12 @@ +require "include"; +require "variables"; + +global "result"; + +set "result" "${result} TWO"; + +keep; + +include "once-1.sieve"; + +return; diff --git a/tests/extensions/include/once.svtest b/tests/extensions/include/once.svtest new file mode 100644 index 000000000..1a08c8da4 --- /dev/null +++ b/tests/extensions/include/once.svtest @@ -0,0 +1,20 @@ +require "vnd.dovecot.testsuite"; +require "include"; +require "variables"; + +global "result"; + +set "result" ""; + +test "Included Once" { + include "once-1"; + include "once-2"; + + if string "${result}" " ONE TWO ONE" { + test_fail "duplicate included :once script"; + } + + if not string "${result}" " ONE TWO" { + test_fail "unexpected result value: ${result}"; + } +} -- GitLab