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