Commit e4d186ff e4d186ff991138c8834950ebb1320a35fa2b7357 by Sergey Poznyakoff

Code generator functions

1 parent c42807f1
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