From fa295e4bb815818abb4cd090bf5899407e03269d Mon Sep 17 00:00:00 2001 From: Stephan Bosch <stephan@rename-it.nl> Date: Thu, 13 Dec 2007 01:20:59 +0100 Subject: [PATCH] Changed binary object's extension linkage for extending the binary itself. --- src/lib-sieve/sieve-binary.c | 153 ++++++++++++++++++------------- src/lib-sieve/sieve-binary.h | 7 ++ src/lib-sieve/sieve-extensions.c | 20 +++- src/lib-sieve/sieve-extensions.h | 1 + 4 files changed, 116 insertions(+), 65 deletions(-) diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c index 9afe052de..241b8de92 100644 --- a/src/lib-sieve/sieve-binary.c +++ b/src/lib-sieve/sieve-binary.c @@ -32,10 +32,12 @@ static inline sieve_size_t sieve_binary_emit_dynamic_data static inline sieve_size_t sieve_binary_emit_cstring (struct sieve_binary *binary, const char *str); -struct sieve_binary_extension { - const struct sieve_extension *extension; +struct sieve_binary_extension_reg { + const struct sieve_extension *extension; /* Null for pre-loaded extensions */ + const struct sieve_binary_extension *binext; int ext_id; int index; + void *context; }; struct sieve_binary { @@ -46,19 +48,18 @@ struct sieve_binary { /* 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 - * array is a mapping extension_id -> binary_extension. This is used to obtain - * the code associated with an extension for this particular binary. + * array is a sequential list of all used extensions. The extension_index + * array is a mapping ext_id -> binary_extension. This is used to obtain the + * index code associated with an extension for this particular binary. + * + * Both arrays refer to the same extension registration objects. Upon loading + * a binary, the 'require'd extensions will sometimes need to associate + * context data to the binary object in memory. This is stored in these + * registration objects as well. */ - ARRAY_DEFINE(extensions, struct sieve_binary_extension *); - ARRAY_DEFINE(extension_index, struct sieve_binary_extension *); - - /* Upon loading a binary, the 'require'd extensions will sometimes need to - * associate context data to the binary object in memory. This is stored in - * the following array: - */ - ARRAY_DEFINE(ext_contexts, void *); - + ARRAY_DEFINE(extensions, struct sieve_binary_extension_reg *); + ARRAY_DEFINE(extension_index, struct sieve_binary_extension_reg *); + /* Attributes of a loaded binary */ const char *path; @@ -82,6 +83,7 @@ static struct sieve_binary *sieve_binary_create(struct sieve_script *script) { pool_t pool; struct sieve_binary *sbin; + const int *ext_id; pool = pool_alloconly_create("sieve_binary", 4096); sbin = p_new(pool, struct sieve_binary, 1); @@ -92,10 +94,15 @@ static struct sieve_binary *sieve_binary_create(struct sieve_script *script) p_array_init(&sbin->extensions, pool, 5); p_array_init(&sbin->extension_index, pool, sieve_extensions_get_count()); - p_array_init(&sbin->ext_contexts, pool, 5); - p_array_init(&sbin->blocks, pool, 3); - + + /* Pre-link core language features implemented as 'extensions' */ + ext_id = sieve_extensions_get_preloaded_ext_ids(); + while ( *ext_id > -1 ) { + sieve_binary_extension_link(sbin, *ext_id); + ext_id++; + } + return sbin; } @@ -300,7 +307,7 @@ static bool _sieve_binary_save sieve_binary_emit_integer(sbin, ext_count); for ( i = 0; i < ext_count; i++ ) { - struct sieve_binary_extension * const *ext + struct sieve_binary_extension_reg * const *ext = array_idx(&sbin->extensions, i); sieve_binary_emit_cstring(sbin, (*ext)->extension->name); @@ -575,66 +582,89 @@ void sieve_binary_activate(struct sieve_binary *sbin) unsigned int i; sieve_binary_block_set_active(sbin, SBIN_SYSBLOCK_MAIN_PROGRAM); - - /* 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]; - if ( ext->binary_load != NULL ) - (void)ext->binary_load(sbin); - } - /* Load other extensions into binary */ for ( i = 0; i < array_count(&sbin->extensions); i++ ) { - struct sieve_binary_extension * const *aext = + struct sieve_binary_extension_reg * const *ereg = array_idx(&sbin->extensions, i); - const struct sieve_extension *ext = (*aext)->extension; + const struct sieve_extension *ext = (*ereg)->extension; - if ( ext->binary_load != NULL ) + if ( ext != NULL && ext->binary_load != NULL ) ext->binary_load(sbin); } } -/* Extension contexts */ +/* Extension handling */ + +static inline struct sieve_binary_extension_reg *sieve_binary_extension_get_reg +(struct sieve_binary *sbin, int ext_id) +{ + if ( ext_id >= 0 && ext_id < (int) array_count(&sbin->extension_index) ) { + struct sieve_binary_extension_reg * const *ereg = + array_idx(&sbin->extension_index, (unsigned int) ext_id); + + return *ereg; + } + + return NULL; +} + +static inline struct sieve_binary_extension_reg * + sieve_binary_extension_create_reg +(struct sieve_binary *sbin, const struct sieve_extension *ext, int ext_id) +{ + int index = array_count(&sbin->extensions); + struct sieve_binary_extension_reg *ereg; + + ereg = p_new(sbin->pool, struct sieve_binary_extension_reg, 1); + ereg->index = index; + ereg->ext_id = ext_id; + ereg->extension = ext; + + array_idx_set(&sbin->extensions, (unsigned int) index, &ereg); + array_idx_set(&sbin->extension_index, (unsigned int) ext_id, &ereg); + + return ereg; +} inline void sieve_binary_extension_set_context (struct sieve_binary *sbin, int ext_id, void *context) { - array_idx_set(&sbin->ext_contexts, (unsigned int) ext_id, &context); + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_get_reg(sbin, ext_id); + + if ( ereg == NULL ) { + /* Only pre-loaded extensions should cause this */ + ereg = sieve_binary_extension_create_reg(sbin, + sieve_extension_get_by_id(ext_id), ext_id); + } + + ereg->context = context; } inline const void *sieve_binary_extension_get_context (struct sieve_binary *sbin, int ext_id) { - void * const *ctx; + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_get_reg(sbin, ext_id); - if ( ext_id < 0 || ext_id >= (int) array_count(&sbin->ext_contexts) ) - return NULL; - - ctx = array_idx(&sbin->ext_contexts, (unsigned int) ext_id); - - return *ctx; + if ( ereg != NULL ) { + return ereg->context; + } + + return NULL; } -/* Extension handling */ - int sieve_binary_extension_link (struct sieve_binary *sbin, int ext_id) { - int index = array_count(&sbin->extensions); - const struct sieve_extension *ext = sieve_extension_get_by_id(ext_id); - struct sieve_binary_extension *bext; - - if ( ext != NULL && sieve_binary_extension_get_index(sbin, ext_id) == -1 ) { - bext = p_new(sbin->pool, struct sieve_binary_extension, 1); - bext->index = index; - bext->ext_id = ext_id; - bext->extension = ext; + const struct sieve_extension *ext = sieve_extension_get_by_id(ext_id); - array_idx_set(&sbin->extensions, (unsigned int) index, &bext); - array_idx_set(&sbin->extension_index, (unsigned int) ext_id, &bext); - - return index; + if ( ext != NULL && sieve_binary_extension_get_index(sbin, ext_id) == -1 ) { + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_create_reg(sbin, ext, ext_id); + + return ereg->index; } return -1; @@ -643,7 +673,7 @@ int sieve_binary_extension_link const struct sieve_extension *sieve_binary_extension_get_by_index (struct sieve_binary *sbin, int index, int *ext_id) { - struct sieve_binary_extension * const *ext; + struct sieve_binary_extension_reg * const *ext; if ( index < (int) array_count(&sbin->extensions) ) { ext = array_idx(&sbin->extensions, (unsigned int) index); @@ -661,15 +691,12 @@ const struct sieve_extension *sieve_binary_extension_get_by_index int sieve_binary_extension_get_index (struct sieve_binary *sbin, int ext_id) { - struct sieve_binary_extension * const *ext; - - if ( ext_id > 0 && ext_id < (int) array_count(&sbin->extension_index) ) { - ext = array_idx(&sbin->extension_index, (unsigned int) ext_id); - - if ( *ext != NULL ) - return (*ext)->index; - } + struct sieve_binary_extension_reg *ereg = + sieve_binary_extension_get_reg(sbin, ext_id); + if ( ereg != NULL ) + return ereg->index; + return -1; } @@ -959,7 +986,7 @@ void sieve_binary_registry_set_object void sieve_binary_registry_init(struct sieve_binary *sbin, int ext_id) { pool_t pool = sieve_binary_pool(sbin); - + struct sieve_binary_registry *reg = p_new(pool, struct sieve_binary_registry, 1); diff --git a/src/lib-sieve/sieve-binary.h b/src/lib-sieve/sieve-binary.h index 426b3fd42..82e7b6ca7 100644 --- a/src/lib-sieve/sieve-binary.h +++ b/src/lib-sieve/sieve-binary.h @@ -39,6 +39,13 @@ unsigned int sieve_binary_block_create(struct sieve_binary *sbin); * Extension support */ +struct sieve_binary_extension { + struct sieve_extension *extension; + + bool (*save)(struct sieve_binary *sbin); + void (*free)(struct sieve_binary *sbin); +}; + inline void sieve_binary_extension_set_context (struct sieve_binary *sbin, int ext_id, void *context); inline const void *sieve_binary_extension_get_context diff --git a/src/lib-sieve/sieve-extensions.c b/src/lib-sieve/sieve-extensions.c index e71dc4ebc..d52aa66fb 100644 --- a/src/lib-sieve/sieve-extensions.c +++ b/src/lib-sieve/sieve-extensions.c @@ -25,6 +25,8 @@ const struct sieve_extension *sieve_preloaded_extensions[] = { const unsigned int sieve_preloaded_extensions_count = N_ELEMENTS(sieve_preloaded_extensions); +ARRAY_DEFINE(sieve_preloaded_ext_ids, int); + /* Dummy extensions */ static const struct sieve_extension comparator_i_octet_extension = { @@ -84,13 +86,17 @@ const unsigned int sieve_core_extensions_count = bool sieve_extensions_init(const char *sieve_plugins ATTR_UNUSED) { unsigned int i; + int ext_id; sieve_extensions_init_registry(); + i_array_init(&sieve_preloaded_ext_ids, sieve_core_extensions_count); + /* Pre-load core extensions */ for ( i = 0; i < sieve_core_extensions_count; i++ ) { - int ext_id = - sieve_extension_register(sieve_core_extensions[i]); + ext_id = sieve_extension_register(sieve_core_extensions[i]); + + array_append(&sieve_preloaded_ext_ids, &ext_id, 1); if ( sieve_core_extensions[i]->load != NULL && !sieve_core_extensions[i]->load(ext_id) ) { @@ -100,14 +106,24 @@ bool sieve_extensions_init(const char *sieve_plugins ATTR_UNUSED) } } + ext_id = -1; + array_append(&sieve_preloaded_ext_ids, &ext_id, 1); + /* More extensions can be added through plugins */ /* FIXME */ return TRUE; } +const int *sieve_extensions_get_preloaded_ext_ids(void) +{ + return array_idx(&sieve_preloaded_ext_ids, 0); +} + void sieve_extensions_deinit(void) { + array_free(&sieve_preloaded_ext_ids); + sieve_extensions_deinit_registry(); } diff --git a/src/lib-sieve/sieve-extensions.h b/src/lib-sieve/sieve-extensions.h index c9da9ae53..e41bd11c0 100644 --- a/src/lib-sieve/sieve-extensions.h +++ b/src/lib-sieve/sieve-extensions.h @@ -47,6 +47,7 @@ const struct sieve_extension *sieve_extension_acquire(const char *extension); /* Extensions state */ bool sieve_extensions_init(const char *sieve_plugins ATTR_UNUSED); +const int *sieve_extensions_get_preloaded_ext_ids(void); void sieve_extensions_deinit(void); /* Extension registry */ -- GitLab