#ifndef SIEVE_COMMANDS_H #define SIEVE_COMMANDS_H #include "lib.h" #include "sieve-common.h" #include "sieve-ast.h" /* * Argument definition */ enum sieve_argument_flag { /* More than one of this (type of) tagged argument is allowed */ SIEVE_ARGUMENT_FLAG_MULTIPLE = (1 << 0) }; struct sieve_argument_def { const char *identifier; enum sieve_argument_flag flags; bool (*is_instance_of) (struct sieve_validator *valdtr, struct sieve_command *cmd, const struct sieve_extension *ext, const char *identifier, void **data); bool (*validate) (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, struct sieve_command *cmd); bool (*validate_context) (struct sieve_validator *valdtr, struct sieve_ast_argument *arg, struct sieve_command *cmd); bool (*validate_persistent) (struct sieve_validator *valdtr, struct sieve_command *cmd, const struct sieve_extension *ext); bool (*generate) (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, struct sieve_command *cmd); }; /* * Argument instance */ struct sieve_argument { const struct sieve_argument_def *def; const struct sieve_extension *ext; int id_code; /* Context data */ void *data; }; #define sieve_argument_is(ast_arg, definition) \ ( (ast_arg)->argument->def == &(definition) ) #define sieve_argument_ext(ast_arg) \ ( (ast_arg)->argument->ext ) #define sieve_argument_identifier(ast_arg) \ ( (ast_arg)->argument->def->identifier ) /* Utility macros */ #define sieve_argument_is_string_literal(arg) \ ( (arg)->argument->def == &string_argument ) /* Error handling */ #define sieve_argument_validate_error(validator, arg_node, ...) \ sieve_validator_error(validator, \ ((arg_node) == NULL ? 0 : (arg_node)->source_line), \ __VA_ARGS__) #define sieve_argument_validate_warning(validator, arg_node, ...) \ sieve_validator_warning(validator, \ ((arg_node) == NULL ? 0 : (arg_node)->source_line), \ __VA_ARGS__) #define sieve_argument_generate_error(gentr, arg_node, ...) \ sieve_generator_error(gentr, \ ((arg_node) == NULL ? 0 : (arg_node)->source_line), \ __VA_ARGS__) #define sieve_argument_generate_warning(gentr, arg_node, ...) \ sieve_generator_warning(gentr, \ ((arg_node) == NULL ? 0 : (arg_node)->source_line), \ __VA_ARGS__) /* Argument API */ struct sieve_argument *sieve_argument_create (struct sieve_ast *ast, const struct sieve_argument_def *def, const struct sieve_extension *ext, int id_code); /* Literal arguments */ extern const struct sieve_argument_def number_argument; extern const struct sieve_argument_def string_argument; extern const struct sieve_argument_def string_list_argument; /* Catenated string argument */ bool sieve_arg_catenated_string_generate (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, struct sieve_command *context); struct sieve_arg_catenated_string; struct sieve_arg_catenated_string *sieve_arg_catenated_string_create (struct sieve_ast_argument *orig_arg); void sieve_arg_catenated_string_add_element (struct sieve_arg_catenated_string *strdata, struct sieve_ast_argument *element); /* * Command definition */ enum sieve_command_type { SCT_NONE, SCT_COMMAND, SCT_TEST, SCT_HYBRID }; struct sieve_command_def { const char *identifier; enum sieve_command_type type; /* High-level command syntax */ int positional_args; int subtests; bool block_allowed; bool block_required; bool (*registered) (struct sieve_validator *valdtr, const struct sieve_extension *ext, struct sieve_command_registration *cmd_reg); bool (*pre_validate) (struct sieve_validator *valdtr, struct sieve_command *cmd); bool (*validate) (struct sieve_validator *valdtr, struct sieve_command *cmd); bool (*validate_const) (struct sieve_validator *valdtr, struct sieve_command *cmd, int *const_current, int const_next); bool (*generate) (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); bool (*control_generate) (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd, struct sieve_jumplist *jumps, bool jump_true); }; /* * Command instance */ struct sieve_command { const struct sieve_command_def *def; const struct sieve_extension *ext; /* The registration of this command in the validator (sieve-validator.h) */ struct sieve_command_registration *reg; /* The ast node of this command */ struct sieve_ast_node *ast_node; /* First positional argument, found during argument validation */ struct sieve_ast_argument *first_positional; /* The child ast node that unconditionally exits this command's block */ struct sieve_command *block_exit_command; /* Context data*/ void *data; }; #define sieve_command_is(cmd, definition) \ ( (cmd)->def == &(definition) ) #define sieve_command_identifier(cmd) \ ( (cmd)->def->identifier ) #define sieve_commands_equal(cmd1, cmd2) \ ( (cmd1) != NULL && (cmd2) != NULL && (cmd1)->def == (cmd2)->def ) /* Context API */ struct sieve_command *sieve_command_create (struct sieve_ast_node *cmd_node, const struct sieve_extension *ext, const struct sieve_command_def *cmd_def, struct sieve_command_registration *cmd_reg); const char *sieve_command_def_type_name (const struct sieve_command_def *cmd_def); const char *sieve_command_type_name (const struct sieve_command *cmd); struct sieve_command *sieve_command_prev (struct sieve_command *cmd); struct sieve_command *sieve_command_parent (struct sieve_command *cmd); struct sieve_ast_argument *sieve_command_add_dynamic_tag (struct sieve_command *cmd, const struct sieve_extension *ext, const struct sieve_argument_def *tag, int id_code); struct sieve_ast_argument *sieve_command_find_argument (struct sieve_command *cmd, const struct sieve_argument_def *argument); void sieve_command_exit_block_unconditionally (struct sieve_command *cmd); bool sieve_command_block_exits_unconditionally (struct sieve_command *cmd); /* Error handling */ #define sieve_command_validate_error(validator, context, ...) \ sieve_validator_error(validator, \ ((context) == NULL ? 0 : (context)->ast_node->source_line), \ __VA_ARGS__) #define sieve_command_validate_warning(validator, context, ...) \ sieve_validator_warning(validator, \ ((context) == NULL ? 0 : (context)->ast_node->source_line), \ __VA_ARGS__) #define sieve_command_generate_error(gentr, context, ...) \ sieve_generator_error(gentr, \ ((context) == NULL ? 0 : (context)->ast_node->source_line), \ __VA_ARGS__) #define sieve_command_generate_warning(gentr, context, ...) \ sieve_generator_warning(gentr, \ ((context) == NULL ? 0 : (context)->ast_node->source_line), \ __VA_ARGS__) /* Utility macros */ #define sieve_command_pool(context) \ sieve_ast_node_pool((context)->ast_node) #define sieve_command_source_line(context) \ (context)->ast_node->source_line #define sieve_command_first_argument(context) \ sieve_ast_argument_first((context)->ast_node) #define sieve_command_is_toplevel(context) \ ( sieve_ast_node_type(sieve_ast_node_parent((context)->ast_node)) == SAT_ROOT ) #define sieve_command_is_first(context) \ ( sieve_ast_node_prev((context)->ast_node) == NULL ) /* * Core commands */ extern const struct sieve_command_def cmd_require; extern const struct sieve_command_def cmd_stop; extern const struct sieve_command_def cmd_if; extern const struct sieve_command_def cmd_elsif; extern const struct sieve_command_def cmd_else; extern const struct sieve_command_def cmd_redirect; extern const struct sieve_command_def cmd_keep; extern const struct sieve_command_def cmd_discard; extern const struct sieve_command_def *sieve_core_commands[]; extern const unsigned int sieve_core_commands_count; /* * Core tests */ extern const struct sieve_command_def tst_true; extern const struct sieve_command_def tst_false; extern const struct sieve_command_def tst_not; extern const struct sieve_command_def tst_anyof; extern const struct sieve_command_def tst_allof; extern const struct sieve_command_def tst_address; extern const struct sieve_command_def tst_header; extern const struct sieve_command_def tst_exists; extern const struct sieve_command_def tst_size; extern const struct sieve_command_def *sieve_core_tests[]; extern const unsigned int sieve_core_tests_count; /* * Command utility functions */ bool sieve_command_verify_headers_argument (struct sieve_validator *valdtr, struct sieve_ast_argument *headers); #endif