1 #ifndef SIEVE_AST_H 2 #define SIEVE_AST_H 3 4 #include "lib.h" 5 #include "str.h" 6 7 #include "sieve-common.h" 8 #include "sieve-error.h" 9 10 /* 11 Abstract Syntax Tree (AST) structure: 12 13 sieve_ast (root) 14 [*command] 15 | 16 +-- command: 17 | .... 18 +-- command: 19 | [identifier *argument *test *command] 20 | +-- argument: | \--> as from root 21 | | .... | 22 | +-- argument: V (continued below) 23 | | [number | tag | *string] 24 | . 25 . 26 27 *test 28 +-- test: 29 | .... 30 +-- test: 31 | [identifier *argument *test] 32 | +-- argument: \--> as from the top 33 . | .... of this tree 34 +-- argument: 35 | [number | tag | *string] 36 . 37 38 Tests and commands are defined using the same structure: sieve_ast_node. 39 However, arguments and string-lists are described using sieve_ast_argument. 40 */ 41 42 /* IMPORTANT NOTICE: Do not decorate the AST with objects other than those 43 allocated on the ast's pool or static const objects. Otherwise it is possible 44 that pointers in the tree become dangling which is highly undesirable. 45 */ 46 47 /* 48 * Forward declarations 49 */ 50 51 struct sieve_ast_list; 52 struct sieve_ast_arg_list; 53 54 /* 55 * Types 56 */ 57 58 enum sieve_ast_argument_type { 59 SAAT_NONE, 60 SAAT_NUMBER, 61 SAAT_STRING, 62 SAAT_STRING_LIST, 63 SAAT_TAG, 64 }; 65 66 enum sieve_ast_type { 67 SAT_NONE, 68 SAT_ROOT, 69 SAT_COMMAND, 70 SAT_TEST, 71 }; 72 73 /* 74 * AST Nodes 75 */ 76 77 /* Argument node */ 78 79 struct sieve_ast_argument { 80 enum sieve_ast_argument_type type; 81 82 /* Back reference to the AST object */ 83 struct sieve_ast *ast; 84 85 /* List related */ 86 struct sieve_ast_arg_list *list; 87 struct sieve_ast_argument *next; 88 struct sieve_ast_argument *prev; 89 90 /* Parser-assigned data */ 91 92 union { 93 string_t *str; 94 struct sieve_ast_arg_list *strlist; 95 const char *tag; 96 sieve_number_t number; 97 } _value; 98 99 unsigned int source_line; 100 101 /* Assigned during validation */ 102 103 /* Argument associated with this ast element */ 104 struct sieve_argument *argument; 105 106 /* Parameters to this (tag) argument */ 107 struct sieve_ast_argument *parameters; 108 }; 109 110 struct sieve_ast_node { 111 enum sieve_ast_type type; 112 113 /* Back reference to the AST object */ 114 struct sieve_ast *ast; 115 116 /* Back reference to this node's parent */ 117 struct sieve_ast_node *parent; 118 119 /* Linked list references */ 120 struct sieve_ast_list *list; 121 struct sieve_ast_node *next; 122 struct sieve_ast_node *prev; 123 124 /* Commands (NULL if not allocated) */ 125 bool block; 126 struct sieve_ast_list *commands; 127 128 /* Tests (NULL if not allocated)*/ 129 bool test_list; 130 struct sieve_ast_list *tests; 131 132 /* Arguments (NULL if not allocated) */ 133 struct sieve_ast_arg_list *arguments; 134 135 /* Identifier of command or test */ 136 const char *identifier; 137 138 /* The location in the file where this command was started */ 139 unsigned int source_line; 140 141 /* Assigned during validation */ 142 143 /* Context */ 144 struct sieve_command *command; 145 }; 146 147 /* 148 * AST node lists 149 */ 150 151 struct sieve_ast_list { 152 struct sieve_ast_node *head; 153 struct sieve_ast_node *tail; 154 unsigned int len; 155 }; 156 157 struct sieve_ast_arg_list { 158 struct sieve_ast_argument *head; 159 struct sieve_ast_argument *tail; 160 unsigned int len; 161 }; 162 163 /* 164 * AST object 165 */ 166 167 struct sieve_ast; 168 169 struct sieve_ast *sieve_ast_create(struct sieve_script *script); 170 void sieve_ast_ref(struct sieve_ast *ast); 171 void sieve_ast_unref(struct sieve_ast **ast); 172 173 struct sieve_ast_node *sieve_ast_root(struct sieve_ast *ast); 174 pool_t sieve_ast_pool(struct sieve_ast *ast); 175 struct sieve_script *sieve_ast_script(struct sieve_ast *ast); 176 177 /* Extension support */ 178 179 struct sieve_ast_extension { 180 const struct sieve_extension_def *ext; 181 182 void (*free)(const struct sieve_extension *ext, struct sieve_ast *ast, 183 void *context); 184 }; 185 186 void sieve_ast_extension_link(struct sieve_ast *ast, 187 const struct sieve_extension *ext, 188 bool required); 189 const struct sieve_extension * const * 190 sieve_ast_extensions_get(struct sieve_ast *ast, unsigned int *count_r); 191 192 void sieve_ast_extension_register(struct sieve_ast *ast, 193 const struct sieve_extension *ext, 194 const struct sieve_ast_extension *ast_ext, 195 void *context); 196 void sieve_ast_extension_set_context(struct sieve_ast *ast, 197 const struct sieve_extension *ext, 198 void *context); 199 void *sieve_ast_extension_get_context(struct sieve_ast *ast, 200 const struct sieve_extension *ext); 201 202 bool sieve_ast_extension_is_required(struct sieve_ast *ast, 203 const struct sieve_extension *ext); 204 205 /* 206 * AST node manipulation 207 */ 208 209 /* Command nodes */ 210 211 struct sieve_ast_node * 212 sieve_ast_test_create(struct sieve_ast_node *parent, const char *identifier, 213 unsigned int source_line); 214 struct sieve_ast_node * 215 sieve_ast_command_create(struct sieve_ast_node *parent, const char *identifier, 216 unsigned int source_line); 217 218 struct sieve_ast_node * 219 sieve_ast_node_detach(struct sieve_ast_node *first); 220 221 const char *sieve_ast_type_name(enum sieve_ast_type ast_type); 222 223 /* Argument nodes */ 224 225 struct sieve_ast_argument * 226 sieve_ast_argument_create(struct sieve_ast *ast, unsigned int source_line); 227 228 struct sieve_ast_arg_list *sieve_ast_arg_list_create(pool_t pool); 229 bool sieve_ast_arg_list_add(struct sieve_ast_arg_list *list, 230 struct sieve_ast_argument *argument); 231 bool sieve_ast_arg_list_insert(struct sieve_ast_arg_list *list, 232 struct sieve_ast_argument *before, 233 struct sieve_ast_argument *argument); 234 void sieve_ast_arg_list_substitute(struct sieve_ast_arg_list *list, 235 struct sieve_ast_argument *argument, 236 struct sieve_ast_argument *replacement); 237 238 struct sieve_ast_argument * 239 sieve_ast_argument_string_create_raw(struct sieve_ast *ast, string_t *str, 240 unsigned int source_line); 241 struct sieve_ast_argument * 242 sieve_ast_argument_string_create(struct sieve_ast_node *node, 243 const string_t *str, unsigned int source_line); 244 struct sieve_ast_argument * 245 sieve_ast_argument_cstring_create(struct sieve_ast_node *node, const char *str, 246 unsigned int source_line); 247 248 struct sieve_ast_argument * 249 sieve_ast_argument_tag_create(struct sieve_ast_node *node, const char *tag, 250 unsigned int source_line); 251 252 struct sieve_ast_argument * 253 sieve_ast_argument_number_create(struct sieve_ast_node *node, 254 sieve_number_t number, 255 unsigned int source_line); 256 257 void sieve_ast_argument_string_set(struct sieve_ast_argument *argument, 258 string_t *newstr); 259 void sieve_ast_argument_string_setc(struct sieve_ast_argument *argument, 260 const char *newstr); 261 262 void sieve_ast_argument_number_set(struct sieve_ast_argument *argument, 263 sieve_number_t newnum); 264 void sieve_ast_argument_number_substitute(struct sieve_ast_argument *argument, 265 sieve_number_t number); 266 267 struct sieve_ast_argument * 268 sieve_ast_argument_tag_insert(struct sieve_ast_argument *before, 269 const char *tag, unsigned int source_line); 270 271 struct sieve_ast_argument * 272 sieve_ast_argument_stringlist_create(struct sieve_ast_node *node, 273 unsigned int source_line); 274 struct sieve_ast_argument * 275 sieve_ast_argument_stringlist_substitute(struct sieve_ast_node *node, 276 struct sieve_ast_argument *arg); 277 278 struct sieve_ast_argument * 279 sieve_ast_arguments_detach(struct sieve_ast_argument *first, 280 unsigned int count); 281 bool sieve_ast_argument_attach(struct sieve_ast_node *node, 282 struct sieve_ast_argument *argument); 283 284 const char *sieve_ast_argument_type_name(enum sieve_ast_argument_type arg_type); 285 #define sieve_ast_argument_name(argument) \ 286 sieve_ast_argument_type_name((argument)->type) 287 288 bool sieve_ast_stringlist_add(struct sieve_ast_argument *list, 289 const string_t *str, unsigned int source_line); 290 bool sieve_ast_stringlist_add_strc(struct sieve_ast_argument *list, 291 const char *str, unsigned int source_line); 292 293 /* 294 * Utility 295 */ 296 297 int sieve_ast_stringlist_map( 298 struct sieve_ast_argument **listitem, void *context, 299 int (*map_function)(void *context, struct sieve_ast_argument *arg)); 300 struct sieve_ast_argument * 301 sieve_ast_stringlist_join(struct sieve_ast_argument *list, 302 struct sieve_ast_argument *items); 303 304 /* 305 * AST access macros 306 */ 307 308 /* Generic list access macros */ 309 #define __AST_LIST_FIRST(list) \ 310 ((list) == NULL ? NULL : (list)->head) 311 #define __AST_LIST_LAST(list) \ 312 ((list) == NULL ? NULL : (list)->tail) 313 #define __AST_LIST_COUNT(list) \ 314 ((list) == NULL || (list)->head == NULL ? 0 : (list)->len) 315 #define __AST_LIST_NEXT(item) ((item)->next) 316 #define __AST_LIST_PREV(item) ((item)->prev) 317 318 #define __AST_NODE_LIST_FIRST(node, list) __AST_LIST_FIRST((node)->list) 319 #define __AST_NODE_LIST_LAST(node, list) __AST_LIST_LAST((node)->list) 320 #define __AST_NODE_LIST_COUNT(node, list) __AST_LIST_COUNT((node)->list) 321 322 /* AST macros */ 323 324 /* AST node macros */ 325 #define sieve_ast_node_pool(node) (sieve_ast_pool((node)->ast)) 326 #define sieve_ast_node_parent(node) ((node)->parent) 327 #define sieve_ast_node_prev(node) __AST_LIST_PREV(node) 328 #define sieve_ast_node_next(node) __AST_LIST_NEXT(node) 329 #define sieve_ast_node_type(node) ((node) == NULL ? SAT_NONE : (node)->type) 330 #define sieve_ast_node_line(node) ((node) == NULL ? 0 : (node)->source_line) 331 332 /* AST command node macros */ 333 #define sieve_ast_command_first(node) __AST_NODE_LIST_FIRST(node, commands) 334 #define sieve_ast_command_count(node) __AST_NODE_LIST_COUNT(node, commands) 335 #define sieve_ast_command_prev(command) __AST_LIST_PREV(command) 336 #define sieve_ast_command_next(command) __AST_LIST_NEXT(command) 337 338 /* Compare the identifier of the previous command */ 339 #define sieve_ast_prev_cmd_is(cmd, id) \ 340 ((cmd)->prev == NULL ? FALSE : \ 341 strncasecmp((cmd)->prev->identifier, id, sizeof(id)-1) == 0) 342 343 /* AST test macros */ 344 #define sieve_ast_test_count(node) __AST_NODE_LIST_COUNT(node, tests) 345 #define sieve_ast_test_first(node) __AST_NODE_LIST_FIRST(node, tests) 346 #define sieve_ast_test_next(test) __AST_LIST_NEXT(test) 347 348 /* AST argument macros */ 349 #define sieve_ast_argument_pool(node) (sieve_ast_pool((node)->ast)) 350 #define sieve_ast_argument_first(node) __AST_NODE_LIST_FIRST(node, arguments) 351 #define sieve_ast_argument_last(node) __AST_NODE_LIST_LAST(node, arguments) 352 #define sieve_ast_argument_count(node) __AST_NODE_LIST_COUNT(node, arguments) 353 #define sieve_ast_argument_prev(argument) __AST_LIST_PREV(argument) 354 #define sieve_ast_argument_next(argument) __AST_LIST_NEXT(argument) 355 #define sieve_ast_argument_type(argument) (argument)->type 356 #define sieve_ast_argument_line(argument) (argument)->source_line 357 358 #define sieve_ast_argument_str(argument) ((argument)->_value.str) 359 #define sieve_ast_argument_strc(argument) (str_c((argument)->_value.str)) 360 #define sieve_ast_argument_tag(argument) ((argument)->_value.tag) 361 #define sieve_ast_argument_number(argument) ((argument)->_value.number) 362 363 /* AST string list macros */ 364 // @UNSAFE: should check whether we are actually accessing a string list 365 #define sieve_ast_strlist_first(list) \ 366 __AST_NODE_LIST_FIRST(list, _value.strlist) 367 #define sieve_ast_strlist_last(list) \ 368 __AST_NODE_LIST_LAST(list, _value.strlist) 369 #define sieve_ast_strlist_count(list) \ 370 __AST_NODE_LIST_COUNT(list, _value.strlist) 371 #define sieve_ast_strlist_next(str) __AST_LIST_NEXT(str) 372 #define sieve_ast_strlist_prev(str) __AST_LIST_PREV(str) 373 #define sieve_ast_strlist_str(str) sieve_ast_argument_str(str) 374 #define sieve_ast_strlist_strc(str) sieve_ast_argument_strc(str) 375 376 /* 377 * Debug 378 */ 379 380 void sieve_ast_unparse(struct sieve_ast *ast); 381 382 #endif 383