diff --git a/.hgignore b/.hgignore index 33fd8cd09b3f81449f634b819c20bfbc8e6a6f69..ab593f7d6bd763f1d650ad916ea2289b505c4795 100644 --- a/.hgignore +++ b/.hgignore @@ -47,4 +47,4 @@ Makefile.in **/Makefile **/Makefile.in -src/libsieve/sievec +src/lib-sieve/sievec diff --git a/src/lib-sieve/Makefile.am b/src/lib-sieve/Makefile.am index 723b566c2007808dbbe3831719fd985ac2f40073..243d17ea20201f34d1c76b51bf84773cf3af92c4 100644 --- a/src/lib-sieve/Makefile.am +++ b/src/lib-sieve/Makefile.am @@ -31,6 +31,7 @@ exts = \ sievec_SOURCES = \ sieve-lexer.c \ sieve-ast.c \ + sieve-binary.c \ sieve-parser.c \ sieve-validator.c \ sieve-generator.c \ diff --git a/src/lib-sieve/cmd-require.c b/src/lib-sieve/cmd-require.c index 0091eec3681427d4fb81e9c23a4db236e7b27bbc..0179afc21a51eba72fc1a28049e782cfb9a94282 100644 --- a/src/lib-sieve/cmd-require.c +++ b/src/lib-sieve/cmd-require.c @@ -5,6 +5,11 @@ #include "sieve-extensions.h" #include "sieve-validator.h" +struct cmd_require_context_data { + struct sieve_ast_argument *arg; + struct sieve_extension *extension; +}; + bool cmd_require_validate(struct sieve_validator *validator, struct sieve_command_context *cmd) { struct sieve_ast_argument *arg; @@ -28,18 +33,20 @@ bool cmd_require_validate(struct sieve_validator *validator, struct sieve_comman return FALSE; } - cmd->data = arg; - + cmd->data = (void *) arg; + /* Check argument and load specified extension(s) */ if ( sieve_ast_argument_type(arg) == SAAT_STRING ) /* Single string */ - sieve_validator_load_extension(validator, cmd, sieve_ast_argument_strc(arg)); + arg->context = (void *) sieve_validator_load_extension + (validator, cmd, sieve_ast_argument_strc(arg)); 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 ) { - sieve_validator_load_extension(validator, cmd, sieve_ast_strlist_strc(stritem)); + stritem->context = (void *) sieve_validator_load_extension + (validator, cmd, sieve_ast_strlist_strc(stritem)); stritem = sieve_ast_strlist_next(stritem); } @@ -59,11 +66,24 @@ bool cmd_require_generate { struct sieve_ast_argument *arg = (struct sieve_ast_argument *) ctx->data; - sieve_generator_emit_core_opcode(generator, SIEVE_OPCODE_LOAD); - - /* Emit */ - if ( !sieve_generator_emit_stringlist_argument(generator, arg) ) - return FALSE; + if ( sieve_ast_argument_type(arg) == SAAT_STRING ) { + struct sieve_extension *ext = (struct sieve_extension *) arg->context; + + sieve_generator_register_extension(generator, ext); + } 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 ) { + struct sieve_extension *ext = (struct sieve_extension *) arg->context; + + sieve_generator_register_extension(generator, ext); + + stritem = sieve_ast_strlist_next(stritem); + } + } else { + i_unreached(); + } return TRUE; } diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c index 88bf792e4c5ffc62ecb054f7805b50f55d43458b..fe17a5c8a561521833da450ec823b19ba2e6ffc8 100644 --- a/src/lib-sieve/ext-envelope.c +++ b/src/lib-sieve/ext-envelope.c @@ -3,12 +3,17 @@ #include "sieve-validator.h" /* Forward declarations */ + +static bool ext_envelope_validator_load(struct sieve_validator *validator); static bool tst_envelope_registered (struct sieve_validator *validator, struct sieve_command_registration *cmd_reg); static bool tst_envelope_validate (struct sieve_validator *validator, struct sieve_command_context *tst); -/* Test definitions */ +/* Extension definitions */ + +const struct sieve_extension envelope_extension = + { "envelope", ext_envelope_validator_load, NULL, NULL, NULL }; static const struct sieve_command envelope_test = { "envelope", SCT_TEST, tst_envelope_registered, tst_envelope_validate, NULL, NULL }; @@ -55,7 +60,7 @@ static bool tst_envelope_validate(struct sieve_validator *validator, struct siev } /* Load extension into validator */ -bool ext_envelope_validator_load(struct sieve_validator *validator) +static bool ext_envelope_validator_load(struct sieve_validator *validator) { /* Register new test */ sieve_validator_register_command(validator, &envelope_test); diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c index 85a9d042b812a79fa7d8a4a2047efa60b2d5da99..34113465006ffb400286e8a2927379150da3a92f 100644 --- a/src/lib-sieve/ext-fileinto.c +++ b/src/lib-sieve/ext-fileinto.c @@ -3,9 +3,12 @@ #include "sieve-validator.h" /* Forward declarations */ +static bool ext_fileinto_validator_load(struct sieve_validator *validator); static bool cmd_fileinto_validate(struct sieve_validator *validator, struct sieve_command_context *cmd); -/* Command definitions */ +/* Extension definitions */ +const struct sieve_extension fileinto_extension = + { "fileinto", ext_fileinto_validator_load, NULL, NULL, NULL }; static const struct sieve_command fileinto_command = { "fileinto", SCT_COMMAND, NULL, cmd_fileinto_validate, NULL, NULL }; @@ -26,7 +29,7 @@ static bool cmd_fileinto_validate(struct sieve_validator *validator, struct siev } /* Load extension into validator */ -bool ext_fileinto_validator_load(struct sieve_validator *validator) +static bool ext_fileinto_validator_load(struct sieve_validator *validator) { /* Register new command */ sieve_validator_register_command(validator, &fileinto_command); diff --git a/src/lib-sieve/ext-reject.c b/src/lib-sieve/ext-reject.c index 65c92b13840e030755b57887a29b6b853ef4d4ad..3ae44d0a75fd1578558376b92847cf82ac75c43c 100644 --- a/src/lib-sieve/ext-reject.c +++ b/src/lib-sieve/ext-reject.c @@ -9,14 +9,17 @@ static bool cmd_reject_validate(struct sieve_validator *validator, struct sieve_command_context *cmd); static bool cmd_reject_generate(struct sieve_generator *generator, struct sieve_command_context *ctx); -static bool opc_reject_dump(struct sieve_interpreter *interpreter); + +static bool ext_reject_validator_load(struct sieve_validator *validator); +static bool ext_reject_generator_load(struct sieve_generator *generator); +static bool ext_reject_opcode_dump(struct sieve_interpreter *interpreter); /* Extension definitions */ +struct sieve_extension reject_extension = + { "reject", ext_reject_validator_load, ext_reject_generator_load, ext_reject_opcode_dump, NULL }; static const struct sieve_command reject_command = { "reject", SCT_COMMAND, NULL, cmd_reject_validate, cmd_reject_generate, NULL }; -static const struct sieve_opcode reject_opcode = - { opc_reject_dump, NULL }; /* * Validation @@ -42,7 +45,7 @@ static bool cmd_reject_validate(struct sieve_validator *validator, struct sieve_ } /* Load extension into validator */ -bool ext_reject_validator_load(struct sieve_validator *validator) +static bool ext_reject_validator_load(struct sieve_validator *validator) { /* Register new command */ sieve_validator_register_command(validator, &reject_command); @@ -59,7 +62,7 @@ static bool cmd_reject_generate { struct sieve_ast_argument *arg = (struct sieve_ast_argument *) ctx->data; - sieve_generator_emit_opcode(generator, &reject_opcode); + sieve_generator_emit_opcode(generator, &reject_extension); /* Emit reason string */ if ( !sieve_generator_emit_string_argument(generator, arg) ) @@ -69,11 +72,8 @@ static bool cmd_reject_generate } /* Load extension into generator */ -bool ext_reject_generator_load(struct sieve_generator *generator) +static bool ext_reject_generator_load(struct sieve_generator *generator __attr_unused__) { - /* Register new command */ - sieve_generator_register_opcode(generator, &reject_opcode); - return TRUE; } @@ -82,7 +82,7 @@ bool ext_reject_generator_load(struct sieve_generator *generator) * Code dump */ -static bool opc_reject_dump(struct sieve_interpreter *interpreter) +static bool ext_reject_opcode_dump(struct sieve_interpreter *interpreter) { printf("REJECT\n"); sieve_interpreter_dump_operand(interpreter); diff --git a/src/lib-sieve/scripts/tests/reject.sieve b/src/lib-sieve/scripts/tests/reject.sieve new file mode 100644 index 0000000000000000000000000000000000000000..c8d1d311898ecfa81f6ef6f7bcb522fad2e74302 --- /dev/null +++ b/src/lib-sieve/scripts/tests/reject.sieve @@ -0,0 +1,7 @@ +require "reject"; + +if anyof(exists "frop", size :over 45, size :under 10, address "from" "frop@student.utwente.nl") { + keep; +} else { + reject "I dont want your email."; +} diff --git a/src/lib-sieve/sieve-ast.h b/src/lib-sieve/sieve-ast.h index 195c29217df3c0cdb14ba4596791ba22e7c6b388..bcbeae6a6bb8975a75bb64649bc864b22ce265b6 100644 --- a/src/lib-sieve/sieve-ast.h +++ b/src/lib-sieve/sieve-ast.h @@ -72,6 +72,9 @@ struct sieve_ast_argument { } _value; unsigned int source_line; + + /* Arbitrary data associated with this ast element */ + void *context; }; struct sieve_ast_list { diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c new file mode 100644 index 0000000000000000000000000000000000000000..99ae39472ea660303cd1587f3b5ead7715afc86d --- /dev/null +++ b/src/lib-sieve/sieve-binary.c @@ -0,0 +1,91 @@ +#include "lib.h" +#include "mempool.h" +#include "buffer.h" +#include "array.h" + +#include "sieve-binary.h" + +struct sieve_binary { + pool_t pool; + array_t ARRAY_DEFINE(extensions, struct sieve_extension *); + buffer_t *code; +}; + +struct sieve_binary *sieve_binary_create_new() +{ + pool_t pool; + struct sieve_binary *binary; + + pool = pool_alloconly_create("sieve_binary", 4096); + binary = p_new(pool, struct sieve_binary, 1); + binary->pool = pool; + + binary->code = buffer_create_dynamic(pool, 256); + + ARRAY_CREATE(&binary->extensions, pool, struct sieve_extension *, 4); + + return binary; +} + +void sieve_binary_ref(struct sieve_binary *binary) +{ + pool_ref(binary->pool); +} + +void sieve_binary_unref(struct sieve_binary **binary) +{ + if ( binary != NULL && *binary != NULL ) { + pool_unref((*binary)->pool); + *binary = NULL; + } +} + +/* Extension handling */ + +unsigned int sieve_binary_link_extension(struct sieve_binary *binary, const struct sieve_extension *extension) +{ + array_append(&binary->extensions, &extension, 1); + + return array_count(&binary->extensions) - 1; +} + +const struct sieve_extension *sieve_binary_get_extension(struct sieve_binary *binary, unsigned int index) +{ + const struct sieve_extension * const *ext = array_idx(&binary->extensions, index); + + return *ext; +} + + +/* Emission functions */ + +inline sieve_size_t sieve_binary_emit_data(struct sieve_binary *binary, void *data, sieve_size_t size) +{ + sieve_size_t address = buffer_get_used_size(binary->code); + + buffer_append(binary->code, data, size); + + return address; +} + +inline sieve_size_t sieve_binary_emit_byte(struct sieve_binary *binary, unsigned char byte) +{ + return sieve_binary_emit_data(binary, &byte, 1); +} + +inline void sieve_binary_update_data + (struct sieve_binary *binary, sieve_size_t address, void *data, sieve_size_t size) +{ + buffer_write(binary->code, address, data, size); +} + +inline sieve_size_t sieve_binary_get_code_size(struct sieve_binary *binary) +{ + return buffer_get_used_size(binary->code); +} + +inline const char *sieve_binary_get_code(struct sieve_binary *binary, sieve_size_t *code_size) +{ + return buffer_get_data(binary->code, code_size); +} + diff --git a/src/lib-sieve/sieve-binary.h b/src/lib-sieve/sieve-binary.h new file mode 100644 index 0000000000000000000000000000000000000000..78da1afec9d9f6017941d81334ea8f6077133d30 --- /dev/null +++ b/src/lib-sieve/sieve-binary.h @@ -0,0 +1,30 @@ +#ifndef __SIEVE_BINARY_H__ +#define __SIEVE_BINARY_H__ + +#include "sieve-extensions.h" +#include "sieve-code.h" + +struct sieve_binary; + +struct sieve_binary *sieve_binary_create_new(); +void sieve_binary_ref(struct sieve_binary *binary); +void sieve_binary_unref(struct sieve_binary **binary); + +/* Extension handling */ + +unsigned int sieve_binary_link_extension(struct sieve_binary *binary, const struct sieve_extension *extension); +const struct sieve_extension *sieve_binary_get_extension(struct sieve_binary *binary, unsigned int index); + +/* Emission functions */ + +inline sieve_size_t sieve_binary_emit_data(struct sieve_binary *binary, void *data, sieve_size_t size); +inline sieve_size_t sieve_binary_emit_byte(struct sieve_binary *binary, unsigned char byte); +inline void sieve_binary_update_data + (struct sieve_binary *binary, sieve_size_t address, void *data, sieve_size_t size); +inline sieve_size_t sieve_binary_get_code_size(struct sieve_binary *binary); + +/* Retrieval functions */ + +inline const char *sieve_binary_get_code(struct sieve_binary *binary, sieve_size_t *code_size); + +#endif diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h index 02c4734ce8075fbf4806a7c85c3c521f0570a823..08f4d3ac55583016007f73aa3e78b3afbbb439f4 100644 --- a/src/lib-sieve/sieve-code.h +++ b/src/lib-sieve/sieve-code.h @@ -1,16 +1,15 @@ #ifndef __SIEVE_CODE_H__ #define __SIEVE_CODE_H__ +#include <lib.h> +#include <buffer.h> +#include <array.h> + #include "sieve-common.h" #include "sieve-extensions.h" typedef size_t sieve_size_t; -struct sieve_opcode { - bool (*dump)(struct sieve_interpreter *interpreter); - bool (*execute)(struct sieve_interpreter *interpreter); -}; - enum sieve_core_operation { SIEVE_OPCODE_LOAD = 0x01, SIEVE_OPCODE_JMP = 0x02, @@ -32,6 +31,9 @@ enum sieve_core_operand { SIEVE_OPERAND_STRING_LIST = 0x03 }; +#define SIEVE_OPCODE_CORE_MASK 0x1F +#define SIEVE_OPCODE_EXT_OFFSET (SIEVE_OPCODE_CORE_MASK + 1) + #define SIEVE_CORE_OPERAND_MASK 0x0F #define SIEVE_CORE_OPERAND_BITS 4 diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c index d46f0a302867f8a0f0d58fae11a5710aa7658208..4112b028cfa57b269731a22c5016fb61ce9c0f72 100644 --- a/src/lib-sieve/sieve-extensions.c +++ b/src/lib-sieve/sieve-extensions.c @@ -3,10 +3,12 @@ #include "sieve-extensions.h" -const struct sieve_extension sieve_core_extensions[] = { - { "fileinto", ext_fileinto_validator_load, NULL }, - { "reject", ext_reject_validator_load, ext_reject_generator_load }, - { "envelope", ext_envelope_validator_load, NULL } +extern const struct sieve_extension fileinto_extension; +extern const struct sieve_extension reject_extension; +extern const struct sieve_extension envelope_extension; + +const struct sieve_extension *sieve_core_extensions[] = { + &fileinto_extension, &reject_extension, &envelope_extension }; const unsigned int sieve_core_extensions_count = @@ -17,8 +19,8 @@ const struct sieve_extension *sieve_extension_acquire(const char *extension) { /* First try to acquire one of the compiled-in extensions */ for ( i = 0; i < sieve_core_extensions_count; i++ ) { - if ( strcasecmp(extension, sieve_core_extensions[i].name) == 0 ) - return &sieve_core_extensions[i]; + if ( strcasecmp(extension, sieve_core_extensions[i]->name) == 0 ) + return sieve_core_extensions[i]; } /* Try to load a plugin */ diff --git a/src/lib-sieve/sieve-extensions.h b/src/lib-sieve/sieve-extensions.h index 15a841b3b4bc8f530fb4c67f07c12906bd29e578..ca9338b10dee08eeb029e82abec9cce3c4bca0d1 100644 --- a/src/lib-sieve/sieve-extensions.h +++ b/src/lib-sieve/sieve-extensions.h @@ -9,16 +9,11 @@ struct sieve_extension { bool (*validator_load)(struct sieve_validator *validator); bool (*generator_load)(struct sieve_generator *generator); + + bool (*opcode_dump)(struct sieve_interpreter *interpreter); + bool (*opcode_execute)(struct sieve_interpreter *interpreter); }; const struct sieve_extension *sieve_extension_acquire(const char *extension); -bool ext_fileinto_validator_load(struct sieve_validator *validator); - -bool ext_reject_validator_load(struct sieve_validator *validator); -bool ext_reject_generator_load(struct sieve_generator *generator); - -bool ext_envelope_validator_load(struct sieve_validator *validator); - - #endif /* __SIEVE_EXTENSIONS_H__ */ diff --git a/src/lib-sieve/sieve-generator.c b/src/lib-sieve/sieve-generator.c index 921e90990b5baa58e4fd71c631a6f6e912e041ef..fcb2fb6e0b3dc0a9bf900d9712c3b199358a89ed 100644 --- a/src/lib-sieve/sieve-generator.c +++ b/src/lib-sieve/sieve-generator.c @@ -2,18 +2,16 @@ #include "lib.h" #include "mempool.h" -#include "buffer.h" -#include "array.h" #include "hash.h" #include "sieve-common.h" #include "sieve-extensions.h" #include "sieve-commands-private.h" #include "sieve-code.h" +#include "sieve-binary.h" #include "sieve-generator.h" - /* Jump list */ void sieve_jumplist_init(struct sieve_jumplist *jlist) { @@ -38,11 +36,11 @@ void sieve_jumplist_resolve(struct sieve_jumplist *jlist, struct sieve_generator array_free(&jlist->jumps); } -/* Opcode */ +/* Extensions */ -struct sieve_opcode_registration { - const struct sieve_opcode *opcode; - unsigned int code; +struct sieve_extension_registration { + const struct sieve_extension *extension; + unsigned int opcode; }; /* Generator */ @@ -52,11 +50,13 @@ struct sieve_generator { struct sieve_ast *ast; - buffer_t *code_buffer; - struct hash_table *opcodes; + struct sieve_binary *binary; + + struct hash_table *extension_index; }; -struct sieve_generator *sieve_generator_create(struct sieve_ast *ast) { +struct sieve_generator *sieve_generator_create(struct sieve_ast *ast) +{ pool_t pool; struct sieve_generator *generator; @@ -66,10 +66,11 @@ struct sieve_generator *sieve_generator_create(struct sieve_ast *ast) { generator->ast = ast; sieve_ast_ref(ast); + + generator->binary = sieve_binary_create_new(); + sieve_binary_ref(generator->binary); - generator->code_buffer = buffer_create_dynamic(pool, 256); - - generator->opcodes = hash_create + generator->extension_index = hash_create (pool, pool, 0, NULL, NULL); return generator; @@ -77,74 +78,46 @@ struct sieve_generator *sieve_generator_create(struct sieve_ast *ast) { void sieve_generator_free(struct sieve_generator *generator) { - hash_destroy(generator->opcodes); + hash_destroy(generator->extension_index); sieve_ast_unref(&generator->ast); + sieve_binary_unref(&generator->binary); pool_unref(generator->pool); } /* Registration functions */ -void sieve_generator_register_opcode - (struct sieve_generator *generator, const struct sieve_opcode *opcode) +void sieve_generator_register_extension + (struct sieve_generator *generator, const struct sieve_extension *extension) { - struct sieve_opcode_registration *reg; + struct sieve_extension_registration *reg; - reg = p_new(generator->pool, struct sieve_opcode_registration, 1); - reg->opcode = opcode; - reg->code = hash_size(generator->opcodes); + reg = p_new(generator->pool, struct sieve_extension_registration, 1); + reg->extension = extension; + reg->opcode = sieve_binary_link_extension(generator->binary, extension); - hash_insert(generator->opcodes, (void *) opcode, (void *) reg); + hash_insert(generator->extension_index, (void *) extension, (void *) reg); } -unsigned int sieve_generator_find_opcode - (struct sieve_generator *generator, const struct sieve_opcode *opcode) +unsigned int sieve_generator_find_extension + (struct sieve_generator *generator, const struct sieve_extension *extension) { - struct sieve_opcode_registration *reg = - (struct sieve_opcode_registration *) hash_lookup(generator->opcodes, opcode); + struct sieve_extension_registration *reg = + (struct sieve_extension_registration *) hash_lookup(generator->extension_index, extension); - return reg->code; + return reg->opcode; } /* Emission functions */ -inline sieve_size_t sieve_generator_emit_data(struct sieve_generator *generator, void *data, sieve_size_t size) -{ - buffer_append(generator->code_buffer, data, size); - - return buffer_get_used_size(generator->code_buffer); -} - -inline sieve_size_t sieve_generator_emit_byte(struct sieve_generator *generator, unsigned char byte) -{ - sieve_size_t address = buffer_get_used_size(generator->code_buffer); - - buffer_append(generator->code_buffer, &byte, 1); - - return address; -} - -inline void sieve_generator_update_data - (struct sieve_generator *generator, sieve_size_t address, void *data, sieve_size_t size) -{ - buffer_write(generator->code_buffer, address, data, size); -} - -inline sieve_size_t sieve_generator_get_current_address(struct sieve_generator *generator) -{ - return buffer_get_used_size(generator->code_buffer); -} - -/* - */ sieve_size_t sieve_generator_emit_offset(struct sieve_generator *generator, int offset) { int i; - sieve_size_t address = buffer_get_used_size(generator->code_buffer); + sieve_size_t address = sieve_binary_get_code_size(generator->binary); for ( i = 3; i >= 0; i-- ) { char c = (char) (offset >> (i * 8)); - (void) sieve_generator_emit_data(generator, &c, 1); + (void) sieve_binary_emit_data(generator->binary, &c, 1); } return address; @@ -154,11 +127,11 @@ void sieve_generator_resolve_offset (struct sieve_generator *generator, sieve_size_t address) { int i; - int offset = sieve_generator_get_current_address(generator) - address; + int offset = sieve_binary_get_code_size(generator->binary) - address; for ( i = 3; i >= 0; i-- ) { char c = (char) (offset >> (i * 8)); - (void) sieve_generator_update_data(generator, address + 3 - i, &c, 1); + (void) sieve_binary_update_data(generator->binary, address + 3 - i, &c, 1); } } @@ -167,7 +140,6 @@ void sieve_generator_resolve_offset sieve_size_t sieve_generator_emit_integer(struct sieve_generator *generator, sieve_size_t integer) { int i; - sieve_size_t address = buffer_get_used_size(generator->code_buffer); char buffer[sizeof(sieve_size_t) + 1]; int bufpos = sizeof(buffer) - 1; @@ -187,14 +159,12 @@ sieve_size_t sieve_generator_emit_integer(struct sieve_generator *generator, sie } } - (void) sieve_generator_emit_data(generator, buffer + bufpos, sizeof(buffer) - bufpos); - - return address; + return sieve_binary_emit_data(generator->binary, buffer + bufpos, sizeof(buffer) - bufpos); } sieve_size_t sieve_generator_emit_number(struct sieve_generator *generator, sieve_size_t number) { - sieve_size_t address = sieve_generator_emit_byte(generator, SIEVE_OPERAND_NUMBER); + sieve_size_t address = sieve_binary_emit_byte(generator->binary, SIEVE_OPERAND_NUMBER); (void) sieve_generator_emit_integer(generator, number); @@ -203,17 +173,15 @@ sieve_size_t sieve_generator_emit_number(struct sieve_generator *generator, siev static sieve_size_t sieve_generator_emit_string_item(struct sieve_generator *generator, const string_t *str) { - sieve_size_t address = buffer_get_used_size(generator->code_buffer); - - (void) sieve_generator_emit_integer(generator, str_len(str)); - (void) sieve_generator_emit_data(generator, (void *) str_data(str), str_len(str)); + sieve_size_t address = sieve_generator_emit_integer(generator, str_len(str)); + (void) sieve_binary_emit_data(generator->binary, (void *) str_data(str), str_len(str)); return address; } sieve_size_t sieve_generator_emit_string(struct sieve_generator *generator, const string_t *str) { - sieve_size_t address = sieve_generator_emit_byte(generator, SIEVE_OPERAND_STRING); + sieve_size_t address = sieve_binary_emit_byte(generator->binary, SIEVE_OPERAND_STRING); (void) sieve_generator_emit_string_item(generator, str); @@ -248,12 +216,13 @@ bool sieve_generator_emit_string_argument sieve_size_t sieve_generator_emit_string_list (struct sieve_generator *generator, const struct sieve_ast_argument *strlist) { + sieve_size_t address; const struct sieve_ast_argument *stritem; unsigned int listlen = sieve_ast_strlist_count(strlist); sieve_size_t end_offset = 0; /* Emit byte identifying the type of operand */ - sieve_size_t address = sieve_generator_emit_byte(generator, SIEVE_OPERAND_STRING_LIST); + address = sieve_binary_emit_byte(generator->binary, SIEVE_OPERAND_STRING_LIST); /* Give the interpreter an easy way to skip over this string list */ end_offset = sieve_generator_emit_offset(generator, 0); @@ -277,17 +246,17 @@ sieve_size_t sieve_generator_emit_string_list sieve_size_t sieve_generator_emit_core_opcode(struct sieve_generator *generator, int opcode) { - unsigned char op = opcode & 0x3F; + unsigned char op = opcode & SIEVE_OPCODE_CORE_MASK; - return sieve_generator_emit_data(generator, (void *) &op, 1); + return sieve_binary_emit_byte(generator->binary, op); } sieve_size_t sieve_generator_emit_opcode - (struct sieve_generator *generator, const struct sieve_opcode *opcode) + (struct sieve_generator *generator, const struct sieve_extension *extension) { - unsigned char op = (1 << 6) + sieve_generator_find_opcode(generator, opcode); + unsigned char op = SIEVE_OPCODE_EXT_OFFSET + sieve_generator_find_extension(generator, extension); - return sieve_generator_emit_data(generator, (void *) &op, 1); + return sieve_binary_emit_byte(generator->binary, op); } /* Generator functions */ @@ -351,14 +320,12 @@ bool sieve_generate_block(struct sieve_generator *generator, struct sieve_ast_no return TRUE; } -bool sieve_generate(struct sieve_generator *generator, buffer_t **code) { +struct sieve_binary *sieve_generate(struct sieve_generator *generator) { if ( sieve_generate_block(generator, sieve_ast_root(generator->ast)) ) { - if ( code != NULL ) - *code = generator->code_buffer; - return TRUE; + return generator->binary; } - return FALSE; + return NULL; } diff --git a/src/lib-sieve/sieve-generator.h b/src/lib-sieve/sieve-generator.h index 808dc76480a73ad5506648252c8471bafffac029..a8ded0b25f5cafb971e691d6a65f29e5fd3bf168 100644 --- a/src/lib-sieve/sieve-generator.h +++ b/src/lib-sieve/sieve-generator.h @@ -9,10 +9,10 @@ struct sieve_generator; struct sieve_generator *sieve_generator_create(struct sieve_ast *ast); void sieve_generator_free(struct sieve_generator *generator); -void sieve_generator_register_opcode - (struct sieve_generator *generator, const struct sieve_opcode *opcode); -unsigned int sieve_generator_find_opcode - (struct sieve_generator *generator, const struct sieve_opcode *opcode); +void sieve_generator_register_extension + (struct sieve_generator *generator, const struct sieve_extension *extension); +unsigned int sieve_generator_find_extension + (struct sieve_generator *generator, const struct sieve_extension *extension); /* Jump list */ @@ -32,7 +32,7 @@ inline void sieve_generator_update_data inline sieve_size_t sieve_generator_get_current_address(struct sieve_generator *generator); sieve_size_t sieve_generator_emit_core_opcode(struct sieve_generator *generator, int opcode); -sieve_size_t sieve_generator_emit_opcode(struct sieve_generator *generator, const struct sieve_opcode *opcode); +sieve_size_t sieve_generator_emit_opcode(struct sieve_generator *generator, const struct sieve_extension *extension); sieve_size_t sieve_generator_emit_offset(struct sieve_generator *generator, int offset); void sieve_generator_resolve_offset(struct sieve_generator *generator, sieve_size_t address); @@ -55,7 +55,7 @@ bool sieve_generator_emit_stringlist_argument bool sieve_generate_block(struct sieve_generator *generator, struct sieve_ast_node *block); bool sieve_generate_test(struct sieve_generator *generator, struct sieve_ast_node *tst_node, struct sieve_jumplist *jlist, bool jump_true); -bool sieve_generate(struct sieve_generator *genarator, buffer_t **code); +struct sieve_binary *sieve_generate(struct sieve_generator *genarator); #endif diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c index 1961e8852c9ca45a0cf317d7b38dd2ad836d9e3c..f072237805367499c32485a5cdc3d0827a94ecbd 100644 --- a/src/lib-sieve/sieve-interpreter.c +++ b/src/lib-sieve/sieve-interpreter.c @@ -7,6 +7,8 @@ #include "sieve-commands-private.h" #include "sieve-generator.h" +#include "sieve-binary.h" + #include "sieve-interpreter.h" struct sieve_coded_stringlist { @@ -24,15 +26,17 @@ struct sieve_coded_stringlist { struct sieve_interpreter { pool_t pool; + + struct sieve_binary *binary; + + /* Direct pointer to code inside binary (which is considered immutable) */ const char *code; sieve_size_t code_size; - sieve_size_t pc; - - array_t ARRAY_DEFINE(opcode_extensions, struct sieve_operation_extension *); + sieve_size_t pc; }; -struct sieve_interpreter *sieve_interpreter_create(buffer_t *code) +struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *binary) { pool_t pool; struct sieve_interpreter *interpreter; @@ -41,18 +45,19 @@ struct sieve_interpreter *sieve_interpreter_create(buffer_t *code) interpreter = p_new(pool, struct sieve_interpreter, 1); interpreter->pool = pool; - interpreter->code = buffer_get_data(code, &interpreter->code_size); + interpreter->binary = binary; + interpreter->code = sieve_binary_get_code(binary, &interpreter->code_size); + sieve_binary_ref(binary); interpreter->pc = 0; - ARRAY_CREATE(&interpreter->opcode_extensions, pool, struct sieve_operation_extension *, 4); - return interpreter; } void sieve_interpreter_free(struct sieve_interpreter *interpreter) { pool_unref(interpreter->pool); + sieve_binary_unref(&interpreter->binary); } void sieve_interpreter_reset(struct sieve_interpreter *interpreter) @@ -165,16 +170,23 @@ bool sieve_coded_stringlist_read_item(struct sieve_coded_stringlist *strlist, st static void sieve_interpreter_dump_operation (struct sieve_interpreter *interpreter) { - int opcode; + unsigned int opcode; if ( CODE_BYTES_LEFT(interpreter) > 0 ) { - opcode = CODE_AT_PC(interpreter); + opcode = DATA_AT_PC(interpreter); CODE_JUMP(interpreter, 1); - if ( opcode <= 0x3F ) { + if ( opcode < SIEVE_OPCODE_EXT_OFFSET ) { sieve_core_code_dump(interpreter, interpreter->pc-1, opcode); } else { - printf("DUMPING EXTENSIONS NOT IMPLEMENTED\n"); + const struct sieve_extension *ext = + sieve_binary_get_extension(interpreter->binary, opcode - SIEVE_OPCODE_EXT_OFFSET); + + printf("%08x: ", interpreter->pc-1); + if ( ext->opcode_dump != NULL ) + (void) ext->opcode_dump(interpreter); + else + printf("OPCODE: %d, Extension %s provides no opcode_dump implementation.\n", opcode, ext->name); } } } @@ -269,5 +281,7 @@ void sieve_interpreter_dump_code(struct sieve_interpreter *interpreter) while ( interpreter->pc < interpreter->code_size ) { sieve_interpreter_dump_operation(interpreter); } + + printf("%08x: [End of code]\n", interpreter->code_size); } diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h index 8b9d27ae569c3402b4695163598b0c244669fa83..28cdcba9794fe4880417edfd6cfe2e0dc20f69da 100644 --- a/src/lib-sieve/sieve-interpreter.h +++ b/src/lib-sieve/sieve-interpreter.h @@ -3,13 +3,14 @@ #include "lib.h" #include "buffer.h" -#include "sieve-interpreter.h" + +#include "sieve-binary.h" struct sieve_coded_stringlist; struct sieve_interpreter; -struct sieve_interpreter *sieve_interpreter_create(buffer_t *code); +struct sieve_interpreter *sieve_interpreter_create(struct sieve_binary *binary); void sieve_interpreter_free(struct sieve_interpreter *interpreter); int sieve_interpreter_read_offset(struct sieve_interpreter *interpreter); @@ -23,6 +24,8 @@ bool sieve_interpreter_read_stringlist bool sieve_coded_stringlist_read_item (struct sieve_coded_stringlist *strlist, string_t **str); +/* Code dump (debugging purposes) */ + void sieve_interpreter_dump_number(struct sieve_interpreter *interpreter); void sieve_interpreter_dump_string(struct sieve_interpreter *interpreter); void sieve_interpreter_dump_string_list(struct sieve_interpreter *interpreter); diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c index e449ba8dc0a2bee721bc4f25df242210903a1d2d..d3d06d0c37659c8b52658fa4a793b0cee4616e32 100644 --- a/src/lib-sieve/sieve-validator.c +++ b/src/lib-sieve/sieve-validator.c @@ -201,7 +201,7 @@ static const struct sieve_tag *sieve_validator_find_tag /* Extension support */ -bool sieve_validator_load_extension +const struct sieve_extension *sieve_validator_load_extension (struct sieve_validator *validator, struct sieve_command_context *cmd, const char *extension) { const struct sieve_extension *ext = sieve_extension_acquire(extension); @@ -209,17 +209,17 @@ bool sieve_validator_load_extension if ( ext == NULL ) { sieve_command_validate_error(validator, cmd, "unsupported sieve capability '%s'", extension); - return FALSE; + return NULL; } if ( ext->validator_load != NULL && !ext->validator_load(validator) ) { sieve_command_validate_error(validator, cmd, "failed to load sieve capability '%s'", extension); - return FALSE; + return NULL; } i_info("loaded extension '%s'", extension); - return TRUE; + return ext; } /* Comparator validation */ diff --git a/src/lib-sieve/sieve-validator.h b/src/lib-sieve/sieve-validator.h index 97c0f61e2eb2439c06a91fbdea458ab95a6d90e5..f00ee5c1e018c33becc6ee93c719ddccdee34132 100644 --- a/src/lib-sieve/sieve-validator.h +++ b/src/lib-sieve/sieve-validator.h @@ -46,7 +46,9 @@ bool sieve_validate_command_subtests (struct sieve_validator *validator, struct sieve_command_context *cmd, const unsigned int count); bool sieve_validate_command_block(struct sieve_validator *validator, struct sieve_command_context *cmd, bool block_allowed, bool block_required); -bool sieve_validator_load_extension + +/* Extensions */ +const struct sieve_extension *sieve_validator_load_extension (struct sieve_validator *validator, struct sieve_command_context *cmd, const char *extension); #endif /* __SIEVE_VALIDATOR_H__ */ diff --git a/src/lib-sieve/sievec.c b/src/lib-sieve/sievec.c index 0df9d23eaba43e553f855a4b4ae11ef4085b3f68..cafc4240c34f6cbd26f186ad5a0a8ead0b8b94b4 100644 --- a/src/lib-sieve/sievec.c +++ b/src/lib-sieve/sievec.c @@ -31,9 +31,8 @@ int main(int argc, char **argv) { struct sieve_validator *validator; struct sieve_generator *generator; struct sieve_interpreter *interpreter; - buffer_t *code = NULL; + struct sieve_binary *binary; - if ( argc < 2 ) { printf( "Usage: sievec <filename>\n"); exit(1); @@ -73,13 +72,14 @@ int main(int argc, char **argv) { printf("Generating script...\n"); generator = sieve_generator_create(ast); - if ( !sieve_generate(generator, &code) || sieve_get_errors(ehandler) > 0 ) { + binary = sieve_generate(generator); + if ( sieve_get_errors(ehandler) > 0 || (binary == NULL) ) { printf("Script generation failed.\n"); } else { printf("Script generation successful.\n"); printf("Code Dump:\n\n"); - interpreter = sieve_interpreter_create(code); + interpreter = sieve_interpreter_create(binary); sieve_interpreter_dump_code(interpreter);