diff options
Diffstat (limited to 'pigeonhole/src/lib-sieve/sieve-ast.h')
-rw-r--r-- | pigeonhole/src/lib-sieve/sieve-ast.h | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-sieve/sieve-ast.h b/pigeonhole/src/lib-sieve/sieve-ast.h new file mode 100644 index 0000000..00f8a6b --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-ast.h @@ -0,0 +1,382 @@ +#ifndef SIEVE_AST_H +#define SIEVE_AST_H + +#include "lib.h" +#include "str.h" + +#include "sieve-common.h" +#include "sieve-error.h" + +/* + Abstract Syntax Tree (AST) structure: + + sieve_ast (root) + [*command] + | + +-- command: + | .... + +-- command: + | [identifier *argument *test *command] + | +-- argument: | \--> as from root + | | .... | + | +-- argument: V (continued below) + | | [number | tag | *string] + | . + . + + *test + +-- test: + | .... + +-- test: + | [identifier *argument *test] + | +-- argument: \--> as from the top + . | .... of this tree + +-- argument: + | [number | tag | *string] + . + + Tests and commands are defined using the same structure: sieve_ast_node. + However, arguments and string-lists are described using sieve_ast_argument. +*/ + +/* IMPORTANT NOTICE: Do not decorate the AST with objects other than those + allocated on the ast's pool or static const objects. Otherwise it is possible + that pointers in the tree become dangling which is highly undesirable. + */ + +/* + * Forward declarations + */ + +struct sieve_ast_list; +struct sieve_ast_arg_list; + +/* + * Types + */ + +enum sieve_ast_argument_type { + SAAT_NONE, + SAAT_NUMBER, + SAAT_STRING, + SAAT_STRING_LIST, + SAAT_TAG, +}; + +enum sieve_ast_type { + SAT_NONE, + SAT_ROOT, + SAT_COMMAND, + SAT_TEST, +}; + +/* + * AST Nodes + */ + +/* Argument node */ + +struct sieve_ast_argument { + enum sieve_ast_argument_type type; + + /* Back reference to the AST object */ + struct sieve_ast *ast; + + /* List related */ + struct sieve_ast_arg_list *list; + struct sieve_ast_argument *next; + struct sieve_ast_argument *prev; + + /* Parser-assigned data */ + + union { + string_t *str; + struct sieve_ast_arg_list *strlist; + const char *tag; + sieve_number_t number; + } _value; + + unsigned int source_line; + + /* Assigned during validation */ + + /* Argument associated with this ast element */ + struct sieve_argument *argument; + + /* Parameters to this (tag) argument */ + struct sieve_ast_argument *parameters; +}; + +struct sieve_ast_node { + enum sieve_ast_type type; + + /* Back reference to the AST object */ + struct sieve_ast *ast; + + /* Back reference to this node's parent */ + struct sieve_ast_node *parent; + + /* Linked list references */ + struct sieve_ast_list *list; + struct sieve_ast_node *next; + struct sieve_ast_node *prev; + + /* Commands (NULL if not allocated) */ + bool block; + struct sieve_ast_list *commands; + + /* Tests (NULL if not allocated)*/ + bool test_list; + struct sieve_ast_list *tests; + + /* Arguments (NULL if not allocated) */ + struct sieve_ast_arg_list *arguments; + + /* Identifier of command or test */ + const char *identifier; + + /* The location in the file where this command was started */ + unsigned int source_line; + + /* Assigned during validation */ + + /* Context */ + struct sieve_command *command; +}; + +/* + * AST node lists + */ + +struct sieve_ast_list { + struct sieve_ast_node *head; + struct sieve_ast_node *tail; + unsigned int len; +}; + +struct sieve_ast_arg_list { + struct sieve_ast_argument *head; + struct sieve_ast_argument *tail; + unsigned int len; +}; + +/* + * AST object + */ + +struct sieve_ast; + +struct sieve_ast *sieve_ast_create(struct sieve_script *script); +void sieve_ast_ref(struct sieve_ast *ast); +void sieve_ast_unref(struct sieve_ast **ast); + +struct sieve_ast_node *sieve_ast_root(struct sieve_ast *ast); +pool_t sieve_ast_pool(struct sieve_ast *ast); +struct sieve_script *sieve_ast_script(struct sieve_ast *ast); + +/* Extension support */ + +struct sieve_ast_extension { + const struct sieve_extension_def *ext; + + void (*free)(const struct sieve_extension *ext, struct sieve_ast *ast, + void *context); +}; + +void sieve_ast_extension_link(struct sieve_ast *ast, + const struct sieve_extension *ext, + bool required); +const struct sieve_extension * const * +sieve_ast_extensions_get(struct sieve_ast *ast, unsigned int *count_r); + +void sieve_ast_extension_register(struct sieve_ast *ast, + const struct sieve_extension *ext, + const struct sieve_ast_extension *ast_ext, + void *context); +void sieve_ast_extension_set_context(struct sieve_ast *ast, + const struct sieve_extension *ext, + void *context); +void *sieve_ast_extension_get_context(struct sieve_ast *ast, + const struct sieve_extension *ext); + +bool sieve_ast_extension_is_required(struct sieve_ast *ast, + const struct sieve_extension *ext); + +/* + * AST node manipulation + */ + +/* Command nodes */ + +struct sieve_ast_node * +sieve_ast_test_create(struct sieve_ast_node *parent, const char *identifier, + unsigned int source_line); +struct sieve_ast_node * +sieve_ast_command_create(struct sieve_ast_node *parent, const char *identifier, + unsigned int source_line); + +struct sieve_ast_node * +sieve_ast_node_detach(struct sieve_ast_node *first); + +const char *sieve_ast_type_name(enum sieve_ast_type ast_type); + +/* Argument nodes */ + +struct sieve_ast_argument * +sieve_ast_argument_create(struct sieve_ast *ast, unsigned int source_line); + +struct sieve_ast_arg_list *sieve_ast_arg_list_create(pool_t pool); +bool sieve_ast_arg_list_add(struct sieve_ast_arg_list *list, + struct sieve_ast_argument *argument); +bool sieve_ast_arg_list_insert(struct sieve_ast_arg_list *list, + struct sieve_ast_argument *before, + struct sieve_ast_argument *argument); +void sieve_ast_arg_list_substitute(struct sieve_ast_arg_list *list, + struct sieve_ast_argument *argument, + struct sieve_ast_argument *replacement); + +struct sieve_ast_argument * +sieve_ast_argument_string_create_raw(struct sieve_ast *ast, string_t *str, + unsigned int source_line); +struct sieve_ast_argument * +sieve_ast_argument_string_create(struct sieve_ast_node *node, + const string_t *str, unsigned int source_line); +struct sieve_ast_argument * +sieve_ast_argument_cstring_create(struct sieve_ast_node *node, const char *str, + unsigned int source_line); + +struct sieve_ast_argument * +sieve_ast_argument_tag_create(struct sieve_ast_node *node, const char *tag, + unsigned int source_line); + +struct sieve_ast_argument * +sieve_ast_argument_number_create(struct sieve_ast_node *node, + sieve_number_t number, + unsigned int source_line); + +void sieve_ast_argument_string_set(struct sieve_ast_argument *argument, + string_t *newstr); +void sieve_ast_argument_string_setc(struct sieve_ast_argument *argument, + const char *newstr); + +void sieve_ast_argument_number_set(struct sieve_ast_argument *argument, + sieve_number_t newnum); +void sieve_ast_argument_number_substitute(struct sieve_ast_argument *argument, + sieve_number_t number); + +struct sieve_ast_argument * +sieve_ast_argument_tag_insert(struct sieve_ast_argument *before, + const char *tag, unsigned int source_line); + +struct sieve_ast_argument * +sieve_ast_argument_stringlist_create(struct sieve_ast_node *node, + unsigned int source_line); +struct sieve_ast_argument * +sieve_ast_argument_stringlist_substitute(struct sieve_ast_node *node, + struct sieve_ast_argument *arg); + +struct sieve_ast_argument * +sieve_ast_arguments_detach(struct sieve_ast_argument *first, + unsigned int count); +bool sieve_ast_argument_attach(struct sieve_ast_node *node, + struct sieve_ast_argument *argument); + +const char *sieve_ast_argument_type_name(enum sieve_ast_argument_type arg_type); +#define sieve_ast_argument_name(argument) \ + sieve_ast_argument_type_name((argument)->type) + +bool sieve_ast_stringlist_add(struct sieve_ast_argument *list, + const string_t *str, unsigned int source_line); +bool sieve_ast_stringlist_add_strc(struct sieve_ast_argument *list, + const char *str, unsigned int source_line); + +/* + * Utility + */ + +int sieve_ast_stringlist_map( + struct sieve_ast_argument **listitem, void *context, + int (*map_function)(void *context, struct sieve_ast_argument *arg)); +struct sieve_ast_argument * +sieve_ast_stringlist_join(struct sieve_ast_argument *list, + struct sieve_ast_argument *items); + +/* + * AST access macros + */ + +/* Generic list access macros */ +#define __AST_LIST_FIRST(list) \ + ((list) == NULL ? NULL : (list)->head) +#define __AST_LIST_LAST(list) \ + ((list) == NULL ? NULL : (list)->tail) +#define __AST_LIST_COUNT(list) \ + ((list) == NULL || (list)->head == NULL ? 0 : (list)->len) +#define __AST_LIST_NEXT(item) ((item)->next) +#define __AST_LIST_PREV(item) ((item)->prev) + +#define __AST_NODE_LIST_FIRST(node, list) __AST_LIST_FIRST((node)->list) +#define __AST_NODE_LIST_LAST(node, list) __AST_LIST_LAST((node)->list) +#define __AST_NODE_LIST_COUNT(node, list) __AST_LIST_COUNT((node)->list) + +/* AST macros */ + +/* AST node macros */ +#define sieve_ast_node_pool(node) (sieve_ast_pool((node)->ast)) +#define sieve_ast_node_parent(node) ((node)->parent) +#define sieve_ast_node_prev(node) __AST_LIST_PREV(node) +#define sieve_ast_node_next(node) __AST_LIST_NEXT(node) +#define sieve_ast_node_type(node) ((node) == NULL ? SAT_NONE : (node)->type) +#define sieve_ast_node_line(node) ((node) == NULL ? 0 : (node)->source_line) + +/* AST command node macros */ +#define sieve_ast_command_first(node) __AST_NODE_LIST_FIRST(node, commands) +#define sieve_ast_command_count(node) __AST_NODE_LIST_COUNT(node, commands) +#define sieve_ast_command_prev(command) __AST_LIST_PREV(command) +#define sieve_ast_command_next(command) __AST_LIST_NEXT(command) + +/* Compare the identifier of the previous command */ +#define sieve_ast_prev_cmd_is(cmd, id) \ + ((cmd)->prev == NULL ? FALSE : \ + strncasecmp((cmd)->prev->identifier, id, sizeof(id)-1) == 0) + +/* AST test macros */ +#define sieve_ast_test_count(node) __AST_NODE_LIST_COUNT(node, tests) +#define sieve_ast_test_first(node) __AST_NODE_LIST_FIRST(node, tests) +#define sieve_ast_test_next(test) __AST_LIST_NEXT(test) + +/* AST argument macros */ +#define sieve_ast_argument_pool(node) (sieve_ast_pool((node)->ast)) +#define sieve_ast_argument_first(node) __AST_NODE_LIST_FIRST(node, arguments) +#define sieve_ast_argument_last(node) __AST_NODE_LIST_LAST(node, arguments) +#define sieve_ast_argument_count(node) __AST_NODE_LIST_COUNT(node, arguments) +#define sieve_ast_argument_prev(argument) __AST_LIST_PREV(argument) +#define sieve_ast_argument_next(argument) __AST_LIST_NEXT(argument) +#define sieve_ast_argument_type(argument) (argument)->type +#define sieve_ast_argument_line(argument) (argument)->source_line + +#define sieve_ast_argument_str(argument) ((argument)->_value.str) +#define sieve_ast_argument_strc(argument) (str_c((argument)->_value.str)) +#define sieve_ast_argument_tag(argument) ((argument)->_value.tag) +#define sieve_ast_argument_number(argument) ((argument)->_value.number) + +/* AST string list macros */ +// @UNSAFE: should check whether we are actually accessing a string list +#define sieve_ast_strlist_first(list) \ + __AST_NODE_LIST_FIRST(list, _value.strlist) +#define sieve_ast_strlist_last(list) \ + __AST_NODE_LIST_LAST(list, _value.strlist) +#define sieve_ast_strlist_count(list) \ + __AST_NODE_LIST_COUNT(list, _value.strlist) +#define sieve_ast_strlist_next(str) __AST_LIST_NEXT(str) +#define sieve_ast_strlist_prev(str) __AST_LIST_PREV(str) +#define sieve_ast_strlist_str(str) sieve_ast_argument_str(str) +#define sieve_ast_strlist_strc(str) sieve_ast_argument_strc(str) + +/* + * Debug + */ + +void sieve_ast_unparse(struct sieve_ast *ast); + +#endif |