Code generator functions
Showing
1 changed file
with
248 additions
and
0 deletions
libsieve/prog.c
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU Lesser General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | #include <stdio.h> | ||
22 | #include <stdlib.h> | ||
23 | #include <assert.h> | ||
24 | #include <sieve.h> | ||
25 | |||
26 | int | ||
27 | sieve_code (sieve_op_t *op) | ||
28 | { | ||
29 | if (sieve_machine->pc >= sieve_machine->progsize) | ||
30 | { | ||
31 | size_t newsize = sieve_machine->progsize + SIEVE_CODE_INCR; | ||
32 | sieve_op_t *newprog = sieve_prealloc (&sieve_machine->memory_pool, | ||
33 | sieve_machine->prog, | ||
34 | newsize * | ||
35 | sizeof sieve_machine->prog[0]); | ||
36 | if (!newprog) | ||
37 | { | ||
38 | sieve_error ("%s:%d: out of memory!", | ||
39 | sieve_filename, sieve_line_num); | ||
40 | return 1; | ||
41 | } | ||
42 | sieve_machine->prog = newprog; | ||
43 | sieve_machine->progsize = newsize; | ||
44 | } | ||
45 | sieve_machine->prog[sieve_machine->pc++] = *op; | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | int | ||
50 | sieve_code_instr (sieve_instr_t instr) | ||
51 | { | ||
52 | sieve_op_t op; | ||
53 | |||
54 | op.instr = instr; | ||
55 | return sieve_code (&op); | ||
56 | } | ||
57 | |||
58 | int | ||
59 | sieve_code_handler (sieve_handler_t handler) | ||
60 | { | ||
61 | sieve_op_t op; | ||
62 | |||
63 | op.handler = handler; | ||
64 | return sieve_code (&op); | ||
65 | } | ||
66 | |||
67 | int | ||
68 | sieve_code_list (list_t list) | ||
69 | { | ||
70 | sieve_op_t op; | ||
71 | |||
72 | op.list = list; | ||
73 | return sieve_code (&op); | ||
74 | } | ||
75 | |||
76 | int | ||
77 | sieve_code_number (long num) | ||
78 | { | ||
79 | sieve_op_t op; | ||
80 | |||
81 | op.number = num; | ||
82 | return sieve_code (&op); | ||
83 | } | ||
84 | |||
85 | int | ||
86 | sieve_code_string (char *string) | ||
87 | { | ||
88 | sieve_op_t op; | ||
89 | |||
90 | op.string = string; | ||
91 | return sieve_code (&op); | ||
92 | } | ||
93 | |||
94 | sieve_tag_def_t * | ||
95 | find_tag (sieve_tag_def_t *taglist, char *tagname) | ||
96 | { | ||
97 | if (!taglist) | ||
98 | return NULL; | ||
99 | |||
100 | for (; taglist->name; taglist++) | ||
101 | if (strcmp (taglist->name, tagname) == 0) | ||
102 | return taglist; | ||
103 | return NULL; | ||
104 | } | ||
105 | |||
106 | int | ||
107 | sieve_code_command (sieve_register_t *reg, list_t arglist) | ||
108 | { | ||
109 | iterator_t itr; | ||
110 | list_t arg_list = NULL; | ||
111 | list_t tag_list = NULL; | ||
112 | sieve_data_type *exp_arg; | ||
113 | int rc, err = 0; | ||
114 | static sieve_data_type empty[] = { SVT_VOID }; | ||
115 | |||
116 | if (sieve_code_handler (reg->handler)) | ||
117 | return 1; | ||
118 | |||
119 | exp_arg = reg->req_args ? reg->req_args : empty; | ||
120 | |||
121 | if (arglist) | ||
122 | { | ||
123 | rc = iterator_create (&itr, arglist); | ||
124 | |||
125 | if (rc) | ||
126 | { | ||
127 | sieve_error ("%s:%d: can't create iterator: %s", | ||
128 | sieve_filename, sieve_line_num, | ||
129 | mu_errstring (rc)); | ||
130 | return 1; | ||
131 | } | ||
132 | |||
133 | for (iterator_first (itr); !iterator_is_done (itr); iterator_next (itr)) | ||
134 | { | ||
135 | sieve_value_t *val; | ||
136 | sieve_runtime_tag_t tagrec, *tagptr; | ||
137 | |||
138 | iterator_current (itr, (void **)&val); | ||
139 | |||
140 | if (val->type == SVT_TAG) | ||
141 | { | ||
142 | sieve_tag_def_t *tag = find_tag (reg->tags, val->v.string); | ||
143 | if (!tag) | ||
144 | { | ||
145 | sieve_error ("%s:%d: invalid tag name `%s' for `%s'", | ||
146 | sieve_filename, sieve_line_num, | ||
147 | val->v.string, reg->name); | ||
148 | err = 1; | ||
149 | break; | ||
150 | } | ||
151 | |||
152 | if (!tag_list && (rc = list_create (&tag_list))) | ||
153 | { | ||
154 | sieve_error ("%s:%d: can't create tag list: %s", | ||
155 | sieve_filename, sieve_line_num, | ||
156 | mu_errstring (rc)); | ||
157 | err = 1; | ||
158 | break; | ||
159 | } | ||
160 | |||
161 | tagrec.tag = tag->num; | ||
162 | if (tag->argtype != SVT_VOID) | ||
163 | { | ||
164 | iterator_next (itr); | ||
165 | iterator_current (itr, (void **)&tagrec.arg); | ||
166 | } | ||
167 | else | ||
168 | tagrec.arg = NULL; | ||
169 | |||
170 | tagptr = sieve_palloc (&sieve_machine->memory_pool, | ||
171 | sizeof (*tagptr)); | ||
172 | *tagptr = tagrec; | ||
173 | list_append (tag_list, tagptr); | ||
174 | } | ||
175 | else if (*exp_arg == SVT_VOID) | ||
176 | { | ||
177 | sieve_error ("%s:%d: too many arguments in call to `%s'", | ||
178 | sieve_filename, sieve_line_num, | ||
179 | reg->name); | ||
180 | err = 1; | ||
181 | break; | ||
182 | } | ||
183 | else if (*exp_arg != val->type) | ||
184 | { | ||
185 | sieve_error ("%s:%d: type mismatch in argument %d to `%s'", | ||
186 | sieve_filename, sieve_line_num, | ||
187 | exp_arg - reg->req_args + 1, | ||
188 | reg->name); | ||
189 | err = 1; | ||
190 | break; | ||
191 | } | ||
192 | else | ||
193 | { | ||
194 | if (!arg_list && (rc = list_create (&arg_list))) | ||
195 | { | ||
196 | sieve_error ("%s:%d: can't create arg list: %s", | ||
197 | sieve_filename, sieve_line_num, | ||
198 | mu_errstring (rc)); | ||
199 | err = 1; | ||
200 | break; | ||
201 | } | ||
202 | |||
203 | list_append (arg_list, val); | ||
204 | exp_arg++; | ||
205 | } | ||
206 | } | ||
207 | iterator_destroy (&itr); | ||
208 | } | ||
209 | |||
210 | if (!err) | ||
211 | { | ||
212 | if (*exp_arg != SVT_VOID) | ||
213 | { | ||
214 | sieve_error ("%s:%d: too few arguments in call to `%s'", | ||
215 | sieve_filename, sieve_line_num, | ||
216 | reg->name); | ||
217 | err = 1; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | if (!err) | ||
222 | err = sieve_code_list (arg_list) | ||
223 | || sieve_code_list (tag_list) | ||
224 | || sieve_code_string (reg->name); | ||
225 | |||
226 | if (err) | ||
227 | { | ||
228 | list_destroy (&arg_list); | ||
229 | list_destroy (&tag_list); | ||
230 | } | ||
231 | |||
232 | return err; | ||
233 | } | ||
234 | |||
235 | int | ||
236 | sieve_code_action (sieve_register_t *reg, list_t arglist) | ||
237 | { | ||
238 | return sieve_code_instr (instr_action) | ||
239 | || sieve_code_command (reg, arglist); | ||
240 | } | ||
241 | |||
242 | int | ||
243 | sieve_code_test (sieve_register_t *reg, list_t arglist) | ||
244 | { | ||
245 | return sieve_code_instr (instr_test) | ||
246 | || sieve_code_command (reg, arglist); | ||
247 | } | ||
248 |
-
Please register or sign in to post a comment