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