1 #ifndef SIEVE_COMMANDS_H 2 #define SIEVE_COMMANDS_H 3 4 #include "lib.h" 5 6 #include "sieve-common.h" 7 #include "sieve-ast.h" 8 9 /* 10 * Argument definition 11 */ 12 13 enum sieve_argument_flag { 14 /* More than one of this (type of) tagged argument is allowed */ 15 SIEVE_ARGUMENT_FLAG_MULTIPLE = (1 << 0) 16 }; 17 18 struct sieve_argument_def { 19 const char *identifier; 20 enum sieve_argument_flag flags; 21 22 bool (*is_instance_of) 23 (struct sieve_validator *valdtr, struct sieve_command *cmd, 24 const struct sieve_extension *ext, const char *identifier, void **data); 25 26 bool (*validate) 27 (struct sieve_validator *valdtr, struct sieve_ast_argument **arg, 28 struct sieve_command *cmd); 29 bool (*validate_context) 30 (struct sieve_validator *valdtr, struct sieve_ast_argument *arg, 31 struct sieve_command *cmd); 32 bool (*validate_persistent) 33 (struct sieve_validator *valdtr, struct sieve_command *cmd, 34 const struct sieve_extension *ext); 35 36 bool (*generate) 37 (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, 38 struct sieve_command *cmd); 39 }; 40 41 /* 42 * Argument instance 43 */ 44 45 struct sieve_argument { 46 const struct sieve_argument_def *def; 47 const struct sieve_extension *ext; 48 int id_code; 49 50 /* Context data */ 51 void *data; 52 }; 53 54 #define sieve_argument_is(ast_arg, definition) \ 55 ( (ast_arg)->argument->def == &(definition) ) 56 #define sieve_argument_ext(ast_arg) \ 57 ( (ast_arg)->argument->ext ) 58 #define sieve_argument_identifier(ast_arg) \ 59 ( (ast_arg)->argument->def->identifier ) 60 61 /* Utility macros */ 62 63 #define sieve_argument_is_string_literal(arg) \ 64 ( (arg)->argument->def == &string_argument ) 65 66 /* Error handling */ 67 68 #define sieve_argument_validate_error(validator, arg_node, ...) \ 69 sieve_validator_error(validator, \ 70 ((arg_node) == NULL ? 0 : (arg_node)->source_line), \ 71 __VA_ARGS__) 72 #define sieve_argument_validate_warning(validator, arg_node, ...) \ 73 sieve_validator_warning(validator, \ 74 ((arg_node) == NULL ? 0 : (arg_node)->source_line), \ 75 __VA_ARGS__) 76 77 #define sieve_argument_generate_error(gentr, arg_node, ...) \ 78 sieve_generator_error(gentr, \ 79 ((arg_node) == NULL ? 0 : (arg_node)->source_line), \ 80 __VA_ARGS__) 81 #define sieve_argument_generate_warning(gentr, arg_node, ...) \ 82 sieve_generator_warning(gentr, \ 83 ((arg_node) == NULL ? 0 : (arg_node)->source_line), \ 84 __VA_ARGS__) 85 86 /* Argument API */ 87 88 struct sieve_argument *sieve_argument_create 89 (struct sieve_ast *ast, const struct sieve_argument_def *def, 90 const struct sieve_extension *ext, int id_code); 91 92 /* Literal arguments */ 93 94 extern const struct sieve_argument_def number_argument; 95 extern const struct sieve_argument_def string_argument; 96 extern const struct sieve_argument_def string_list_argument; 97 98 /* Catenated string argument */ 99 100 bool sieve_arg_catenated_string_generate 101 (const struct sieve_codegen_env *cgenv, struct sieve_ast_argument *arg, 102 struct sieve_command *context); 103 104 struct sieve_arg_catenated_string; 105 106 struct sieve_arg_catenated_string *sieve_arg_catenated_string_create 107 (struct sieve_ast_argument *orig_arg); 108 void sieve_arg_catenated_string_add_element 109 (struct sieve_arg_catenated_string *strdata, 110 struct sieve_ast_argument *element); 111 112 /* 113 * Command definition 114 */ 115 116 enum sieve_command_type { 117 SCT_NONE, 118 SCT_COMMAND, 119 SCT_TEST, 120 SCT_HYBRID 121 }; 122 123 struct sieve_command_def { 124 const char *identifier; 125 enum sieve_command_type type; 126 127 /* High-level command syntax */ 128 int positional_args; 129 int subtests; 130 bool block_allowed; 131 bool block_required; 132 133 bool (*registered) 134 (struct sieve_validator *valdtr, const struct sieve_extension *ext, 135 struct sieve_command_registration *cmd_reg); 136 bool (*pre_validate) 137 (struct sieve_validator *valdtr, struct sieve_command *cmd); 138 bool (*validate) 139 (struct sieve_validator *valdtr, struct sieve_command *cmd); 140 bool (*validate_const) 141 (struct sieve_validator *valdtr, struct sieve_command *cmd, 142 int *const_current, int const_next); 143 bool (*generate) 144 (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd); 145 bool (*control_generate) 146 (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd, 147 struct sieve_jumplist *jumps, bool jump_true); 148 }; 149 150 /* 151 * Command instance 152 */ 153 154 struct sieve_command { 155 const struct sieve_command_def *def; 156 const struct sieve_extension *ext; 157 158 /* The registration of this command in the validator (sieve-validator.h) */ 159 struct sieve_command_registration *reg; 160 161 /* The ast node of this command */ 162 struct sieve_ast_node *ast_node; 163 164 /* First positional argument, found during argument validation */ 165 struct sieve_ast_argument *first_positional; 166 167 /* The child ast node that unconditionally exits this command's block */ 168 struct sieve_command *block_exit_command; 169 170 /* Context data*/ 171 void *data; 172 }; 173 174 #define sieve_command_is(cmd, definition) \ 175 ( (cmd)->def == &(definition) ) 176 #define sieve_command_identifier(cmd) \ 177 ( (cmd)->def->identifier ) 178 179 #define sieve_commands_equal(cmd1, cmd2) \ 180 ( (cmd1) != NULL && (cmd2) != NULL && (cmd1)->def == (cmd2)->def ) 181 182 /* Context API */ 183 184 struct sieve_command *sieve_command_create 185 (struct sieve_ast_node *cmd_node, const struct sieve_extension *ext, 186 const struct sieve_command_def *cmd_def, 187 struct sieve_command_registration *cmd_reg); 188 189 const char *sieve_command_def_type_name 190 (const struct sieve_command_def *cmd_def); 191 const char *sieve_command_type_name 192 (const struct sieve_command *cmd); 193 194 struct sieve_command *sieve_command_prev 195 (struct sieve_command *cmd); 196 struct sieve_command *sieve_command_parent 197 (struct sieve_command *cmd); 198 199 struct sieve_ast_argument *sieve_command_add_dynamic_tag 200 (struct sieve_command *cmd, const struct sieve_extension *ext, 201 const struct sieve_argument_def *tag, int id_code); 202 struct sieve_ast_argument *sieve_command_find_argument 203 (struct sieve_command *cmd, const struct sieve_argument_def *argument); 204 205 void sieve_command_exit_block_unconditionally 206 (struct sieve_command *cmd); 207 bool sieve_command_block_exits_unconditionally 208 (struct sieve_command *cmd); 209 210 /* Error handling */ 211 212 #define sieve_command_validate_error(validator, context, ...) \ 213 sieve_validator_error(validator, \ 214 ((context) == NULL ? 0 : (context)->ast_node->source_line), \ 215 __VA_ARGS__) 216 #define sieve_command_validate_warning(validator, context, ...) \ 217 sieve_validator_warning(validator, \ 218 ((context) == NULL ? 0 : (context)->ast_node->source_line), \ 219 __VA_ARGS__) 220 221 #define sieve_command_generate_error(gentr, context, ...) \ 222 sieve_generator_error(gentr, \ 223 ((context) == NULL ? 0 : (context)->ast_node->source_line), \ 224 __VA_ARGS__) 225 #define sieve_command_generate_warning(gentr, context, ...) \ 226 sieve_generator_warning(gentr, \ 227 ((context) == NULL ? 0 : (context)->ast_node->source_line), \ 228 __VA_ARGS__) 229 230 /* Utility macros */ 231 232 #define sieve_command_pool(context) \ 233 sieve_ast_node_pool((context)->ast_node) 234 235 #define sieve_command_source_line(context) \ 236 (context)->ast_node->source_line 237 238 #define sieve_command_first_argument(context) \ 239 sieve_ast_argument_first((context)->ast_node) 240 241 #define sieve_command_is_toplevel(context) \ 242 ( sieve_ast_node_type(sieve_ast_node_parent((context)->ast_node)) == SAT_ROOT ) 243 #define sieve_command_is_first(context) \ 244 ( sieve_ast_node_prev((context)->ast_node) == NULL ) 245 246 /* 247 * Core commands 248 */ 249 250 extern const struct sieve_command_def cmd_require; 251 extern const struct sieve_command_def cmd_stop; 252 extern const struct sieve_command_def cmd_if; 253 extern const struct sieve_command_def cmd_elsif; 254 extern const struct sieve_command_def cmd_else; 255 extern const struct sieve_command_def cmd_redirect; 256 extern const struct sieve_command_def cmd_keep; 257 extern const struct sieve_command_def cmd_discard; 258 259 extern const struct sieve_command_def *sieve_core_commands[]; 260 extern const unsigned int sieve_core_commands_count; 261 262 /* 263 * Core tests 264 */ 265 266 extern const struct sieve_command_def tst_true; 267 extern const struct sieve_command_def tst_false; 268 extern const struct sieve_command_def tst_not; 269 extern const struct sieve_command_def tst_anyof; 270 extern const struct sieve_command_def tst_allof; 271 extern const struct sieve_command_def tst_address; 272 extern const struct sieve_command_def tst_header; 273 extern const struct sieve_command_def tst_exists; 274 extern const struct sieve_command_def tst_size; 275 276 extern const struct sieve_command_def *sieve_core_tests[]; 277 extern const unsigned int sieve_core_tests_count; 278 279 /* 280 * Command utility functions 281 */ 282 283 bool sieve_command_verify_headers_argument 284 (struct sieve_validator *valdtr, struct sieve_ast_argument *headers); 285 286 #endif 287