dovecot-2.2-pigeonhole: lib-sieve: Implemented running code loop...
pigeonhole at rename-it.nl
pigeonhole at rename-it.nl
Sun Nov 29 10:53:29 UTC 2015
details: http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/7c516d25ad50
changeset: 2139:7c516d25ad50
user: Stephan Bosch <stephan at rename-it.nl>
date: Sun Nov 29 11:50:44 2015 +0100
description:
lib-sieve: Implemented running code loops in the interpreter.
diffstat:
src/lib-sieve/sieve-interpreter.c | 192 +++++++++++++++++++++++++++++++++++++-
src/lib-sieve/sieve-interpreter.h | 32 ++++++
2 files changed, 221 insertions(+), 3 deletions(-)
diffs (270 lines):
diff -r be0971931cfe -r 7c516d25ad50 src/lib-sieve/sieve-interpreter.c
--- a/src/lib-sieve/sieve-interpreter.c Sun Nov 29 11:49:47 2015 +0100
+++ b/src/lib-sieve/sieve-interpreter.c Sun Nov 29 11:50:44 2015 +0100
@@ -38,6 +38,18 @@
};
/*
+ * Code loop
+ */
+
+struct sieve_interpreter_loop {
+ unsigned int level;
+ sieve_size_t begin, end;
+ const struct sieve_extension_def *ext_def;
+ pool_t pool;
+ void *context;
+};
+
+/*
* Interpreter
*/
@@ -55,6 +67,10 @@
bool interrupted; /* Interpreter interrupt requested */
bool test_result; /* Result of previous test command */
+ /* Loop stack */
+ ARRAY(struct sieve_interpreter_loop) loop_stack;
+ sieve_size_t loop_limit;
+
/* Runtime environment */
struct sieve_runtime_env runenv;
struct sieve_runtime_trace trace;
@@ -225,14 +241,21 @@
struct sieve_interpreter *interp = *_interp;
struct sieve_runtime_env *renv = &interp->runenv;
const struct sieve_interpreter_extension_reg *eregs;
- unsigned int ext_count, i;
+ struct sieve_interpreter_loop *loops;
+ unsigned int count, i;
+
+ if ( array_is_created(&interp->loop_stack) ) {
+ loops = array_get_modifiable(&interp->loop_stack, &count);
+ for ( i = 0; i < count; i++ )
+ pool_unref(&loops[i].pool);
+ }
interp->trace.indent = 0;
sieve_runtime_trace_end(renv);
/* Signal registered extensions that the interpreter is being destroyed */
- eregs = array_get(&interp->extensions, &ext_count);
- for ( i = 0; i < ext_count; i++ ) {
+ eregs = array_get(&interp->extensions, &count);
+ for ( i = 0; i < count; i++ ) {
if ( eregs[i].intext != NULL && eregs[i].intext->free != NULL )
eregs[i].intext->free(eregs[i].ext, interp, eregs[i].context);
}
@@ -456,6 +479,169 @@
}
/*
+ * Loop handling
+ */
+
+struct sieve_interpreter_loop *sieve_interpreter_loop_start
+(struct sieve_interpreter *interp, sieve_size_t loop_end,
+ const struct sieve_extension_def *ext_def)
+{
+ const struct sieve_runtime_env *renv = &interp->runenv;
+ struct sieve_interpreter_loop *loop;
+
+ i_assert( loop_end > interp->runenv.pc );
+
+ if ( loop_end > sieve_binary_block_get_size(renv->sblock) ) {
+ sieve_runtime_trace_error(renv,
+ "loop end offset out of range");
+ return NULL;
+ }
+
+ if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
+ unsigned int line =
+ sieve_runtime_get_source_location(renv, loop_end);
+
+ if ( sieve_runtime_trace_hasflag(renv, SIEVE_TRFLG_ADDRESSES) ) {
+ sieve_runtime_trace(renv, 0, "loop ends at line %d [%08llx]",
+ line, (long long unsigned int) loop_end);
+ } else {
+ sieve_runtime_trace(renv, 0, "loop ends at line %d", line);
+ }
+ }
+
+ if ( !array_is_created(&interp->loop_stack) )
+ p_array_init(&interp->loop_stack, interp->pool, 8);
+
+ loop = array_append_space(&interp->loop_stack);
+ loop->level = array_count(&interp->loop_stack)-1;
+ loop->ext_def = ext_def;
+ loop->begin = interp->runenv.pc;
+ loop->end = loop_end;
+ loop->pool = pool_alloconly_create("sieve_interpreter", 128);
+
+ return loop;
+}
+
+struct sieve_interpreter_loop *sieve_interpreter_loop_get
+(struct sieve_interpreter *interp, sieve_size_t loop_end,
+ const struct sieve_extension_def *ext_def)
+{
+ struct sieve_interpreter_loop *loops;
+ unsigned int count, i;
+
+ if ( !array_is_created(&interp->loop_stack) )
+ return NULL;
+
+ loops = array_get_modifiable(&interp->loop_stack, &count);
+ for ( i = count; i > 0; i-- ) {
+ /* We're really making sure our loop matches */
+ if ( loops[i-1].end == loop_end &&
+ loops[i-1].ext_def == ext_def )
+ return &loops[i-1];
+ }
+ return NULL;
+}
+
+void sieve_interpreter_loop_next(struct sieve_interpreter *interp,
+ struct sieve_interpreter_loop *loop,
+ sieve_size_t loop_begin)
+{
+ const struct sieve_runtime_env *renv = &interp->runenv;
+ struct sieve_interpreter_loop *loops;
+ unsigned int count;
+
+ if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
+ unsigned int line =
+ sieve_runtime_get_source_location(renv, loop_begin);
+
+ if ( sieve_runtime_trace_hasflag(renv, SIEVE_TRFLG_ADDRESSES) ) {
+ sieve_runtime_trace(renv, 0, "looping back to line %d [%08llx]",
+ line, (long long unsigned int) loop_begin);
+ } else {
+ sieve_runtime_trace(renv, 0, "looping back to line %d", line);
+ }
+ }
+
+ i_assert( loop->begin == loop_begin );
+
+ i_assert( array_is_created(&interp->loop_stack) );
+ loops = array_get_modifiable(&interp->loop_stack, &count);
+ i_assert( &loops[count-1] == loop );
+
+ interp->runenv.pc = loop_begin;
+}
+
+void sieve_interpreter_loop_break(struct sieve_interpreter *interp,
+ struct sieve_interpreter_loop *loop)
+{
+ const struct sieve_runtime_env *renv = &interp->runenv;
+ struct sieve_interpreter_loop *loops;
+ sieve_size_t loop_end = loop->end;
+ unsigned int count, i;
+
+ i_assert( array_is_created(&interp->loop_stack) );
+ loops = array_get_modifiable(&interp->loop_stack, &count);
+ for ( i = count; i > 0 && &loops[i-1] != loop; i-- )
+ pool_unref(&loops[i-1].pool);
+ i_assert( i > 0 && &loops[i-1] == loop );
+
+ array_delete(&interp->loop_stack, i-1, count - (i-1));
+
+ if ( sieve_runtime_trace_active(renv, SIEVE_TRLVL_COMMANDS) ) {
+ unsigned int jmp_line =
+ sieve_runtime_get_source_location(renv, loop_end);
+
+ if ( sieve_runtime_trace_hasflag(renv, SIEVE_TRFLG_ADDRESSES) ) {
+ sieve_runtime_trace(renv, 0, "ending loop at line %d [%08llx]",
+ jmp_line, (long long unsigned int) loop_end);
+ } else {
+ sieve_runtime_trace(renv, 0, "ending loop at line %d", jmp_line);
+ }
+ }
+
+ interp->runenv.pc = loop->end;
+}
+
+struct sieve_interpreter_loop *sieve_interpreter_loop_get_surrounding
+(struct sieve_interpreter *interp,
+ struct sieve_interpreter_loop *loop,
+ const struct sieve_extension_def *ext_def)
+{
+ struct sieve_interpreter_loop *loops;
+ unsigned int count, i;
+
+ if ( !array_is_created(&interp->loop_stack) )
+ return NULL;
+
+ loops = array_get_modifiable(&interp->loop_stack, &count);
+ i_assert(loop == NULL || loop->level < count);
+
+ for ( i = (loop == NULL ? count : loop->level); i > 0; i-- ) {
+ if ( ext_def == NULL || loops[i-1].ext_def == ext_def )
+ return &loops[i-1];
+ }
+ return NULL;
+}
+
+pool_t sieve_interpreter_loop_get_pool
+(struct sieve_interpreter_loop *loop)
+{
+ return loop->pool;
+}
+
+void *sieve_interpreter_loop_get_context
+(struct sieve_interpreter_loop *loop)
+{
+ return loop->context;
+}
+
+void sieve_interpreter_loop_set_context
+(struct sieve_interpreter_loop *loop, void *context)
+{
+ loop->context = context;
+}
+
+/*
* Program flow
*/
diff -r be0971931cfe -r 7c516d25ad50 src/lib-sieve/sieve-interpreter.h
--- a/src/lib-sieve/sieve-interpreter.h Sun Nov 29 11:49:47 2015 +0100
+++ b/src/lib-sieve/sieve-interpreter.h Sun Nov 29 11:50:44 2015 +0100
@@ -46,6 +46,38 @@
(struct sieve_interpreter *interp, struct sieve_result *result);
/*
+ * Loop handling
+ */
+
+struct sieve_interpreter_loop;
+
+struct sieve_interpreter_loop *sieve_interpreter_loop_start
+ (struct sieve_interpreter *interp, sieve_size_t loop_end,
+ const struct sieve_extension_def *ext_def);
+struct sieve_interpreter_loop *sieve_interpreter_loop_get
+ (struct sieve_interpreter *interp, sieve_size_t loop_end,
+ const struct sieve_extension_def *ext_def);
+void sieve_interpreter_loop_next
+ (struct sieve_interpreter *interp,
+ struct sieve_interpreter_loop *loop,
+ sieve_size_t loop_begin);
+void sieve_interpreter_loop_break
+ (struct sieve_interpreter *interp,
+ struct sieve_interpreter_loop *loop);
+
+struct sieve_interpreter_loop *sieve_interpreter_loop_get_surrounding
+(struct sieve_interpreter *interp,
+ struct sieve_interpreter_loop *loop,
+ const struct sieve_extension_def *ext_def) ATTR_NULL(2, 3);
+
+pool_t sieve_interpreter_loop_get_pool
+ (struct sieve_interpreter_loop *loop) ATTR_PURE;
+void *sieve_interpreter_loop_get_context
+ (struct sieve_interpreter_loop *loop) ATTR_PURE;
+void sieve_interpreter_loop_set_context
+ (struct sieve_interpreter_loop *loop, void *context);
+
+/*
* Program flow
*/
More information about the dovecot-cvs
mailing list