diff options
Diffstat (limited to 'pigeonhole/src/testsuite/testsuite-variables.c')
-rw-r--r-- | pigeonhole/src/testsuite/testsuite-variables.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/pigeonhole/src/testsuite/testsuite-variables.c b/pigeonhole/src/testsuite/testsuite-variables.c new file mode 100644 index 0000000..f644393 --- /dev/null +++ b/pigeonhole/src/testsuite/testsuite-variables.c @@ -0,0 +1,183 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" + +#include "sieve-common.h" +#include "sieve-ast.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-commands.h" +#include "sieve-validator.h" +#include "sieve-generator.h" +#include "sieve-interpreter.h" +#include "sieve-dump.h" + +#include "sieve-ext-variables.h" + +#include "testsuite-common.h" +#include "testsuite-variables.h" + +/* + * + */ + +static const struct sieve_extension *testsuite_ext_variables = NULL; + +/* + * + */ + +bool testsuite_varnamespace_validate + (struct sieve_validator *valdtr, const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment); +bool testsuite_varnamespace_generate + (const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg, struct sieve_command *cmd, void *var_data); +bool testsuite_varnamespace_dump_variable + (const struct sieve_dumptime_env *denv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, sieve_size_t *address); +int testsuite_varnamespace_read_variable + (const struct sieve_runtime_env *renv, + const struct sieve_variables_namespace *nspc, + const struct sieve_operand *oprnd, sieve_size_t *address, string_t **str_r); + +static const struct sieve_variables_namespace_def testsuite_namespace = { + SIEVE_OBJECT("tst", &testsuite_namespace_operand, 0), + testsuite_varnamespace_validate, + testsuite_varnamespace_generate, + testsuite_varnamespace_dump_variable, + testsuite_varnamespace_read_variable +}; + +bool testsuite_varnamespace_validate +(struct sieve_validator *valdtr, + const struct sieve_variables_namespace *nspc ATTR_UNUSED, + struct sieve_ast_argument *arg, struct sieve_command *cmd ATTR_UNUSED, + ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, + bool assignment) +{ + struct sieve_ast *ast = arg->ast; + const struct sieve_variable_name *name_element; + const char *variable; + + /* Check variable name */ + + if ( array_count(var_name) != 2 ) { + sieve_argument_validate_error(valdtr, arg, + "testsuite: invalid variable name within testsuite namespace: " + "encountered sub-namespace"); + return FALSE; + } + + name_element = array_idx(var_name, 1); + if ( name_element->num_variable >= 0 ) { + sieve_argument_validate_error(valdtr, arg, + "testsuite: invalid variable name within testsuite namespace 'tst.%d': " + "encountered numeric variable name", name_element->num_variable); + return FALSE; + } + + variable = str_c(name_element->identifier); + + if ( assignment ) { + sieve_argument_validate_error(valdtr, arg, + "testsuite: cannot assign to testsuite variable 'tst.%s'", variable); + return FALSE; + } + + *var_data = (void *) p_strdup(sieve_ast_pool(ast), variable); + + return TRUE; +} + +bool testsuite_varnamespace_generate +(const struct sieve_codegen_env *cgenv, + const struct sieve_variables_namespace *nspc, + struct sieve_ast_argument *arg ATTR_UNUSED, + struct sieve_command *cmd ATTR_UNUSED, void *var_data) +{ + const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc); + const char *variable = (const char *) var_data; + + if ( this_ext == NULL ) + return FALSE; + + sieve_variables_opr_namespace_variable_emit + (cgenv->sblock, testsuite_ext_variables, this_ext, &testsuite_namespace); + sieve_binary_emit_cstring(cgenv->sblock, variable); + + return TRUE; +} + +bool testsuite_varnamespace_dump_variable +(const struct sieve_dumptime_env *denv, + const struct sieve_variables_namespace *nspc ATTR_UNUSED, + const struct sieve_operand *oprnd, sieve_size_t *address) +{ + string_t *var_name; + + if ( !sieve_binary_read_string(denv->sblock, address, &var_name) ) + return FALSE; + + if ( oprnd->field_name != NULL ) + sieve_code_dumpf(denv, "%s: VAR ${tst.%s}", + oprnd->field_name, str_c(var_name)); + else + sieve_code_dumpf(denv, "VAR ${tst.%s}", + str_c(var_name)); + + return TRUE; +} + +int testsuite_varnamespace_read_variable +(const struct sieve_runtime_env *renv, + const struct sieve_variables_namespace *nspc ATTR_UNUSED, + const struct sieve_operand *oprnd, sieve_size_t *address, + string_t **str_r) +{ + string_t *var_name; + + if ( !sieve_binary_read_string(renv->sblock, address, &var_name) ) { + sieve_runtime_trace_operand_error(renv, oprnd, + "testsuite variable operand corrupt: invalid name"); + return SIEVE_EXEC_BIN_CORRUPT; + } + + if ( str_r != NULL ) { + if ( strcmp(str_c(var_name), "path") == 0 ) + *str_r = t_str_new_const(testsuite_test_path, strlen(testsuite_test_path)); + else + *str_r = NULL; + } + return SIEVE_EXEC_OK; +} + + +/* + * Namespace registration + */ + +static const struct sieve_extension_objects testsuite_namespaces = + SIEVE_VARIABLES_DEFINE_NAMESPACE(testsuite_namespace); + +const struct sieve_operand_def testsuite_namespace_operand = { + .name = "testsuite-namespace", + .ext_def = &testsuite_extension, + .code = TESTSUITE_OPERAND_NAMESPACE, + .class = &sieve_variables_namespace_operand_class, + .interface = &testsuite_namespaces +}; + +void testsuite_variables_init +(const struct sieve_extension *this_ext, struct sieve_validator *valdtr) +{ + testsuite_ext_variables = sieve_ext_variables_get_extension(this_ext->svinst); + + sieve_variables_namespace_register + (testsuite_ext_variables, valdtr, this_ext, &testsuite_namespace); +} |