]> mj.ucw.cz Git - umpf.git/blob - int.c
69f22852b80d1376f666b69e9420a495fa82b155
[umpf.git] / int.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <pcre.h>
4 #include <ctype.h>
5 #include <limits.h>
6
7 #include "cond.tab.h"
8 #include "umpf.h"
9
10 #define OVECCOUNT 3
11 #define HASHSIZE 103
12 #define MAGIC 19
13
14 #define INT_TO_STRING_LEN ((sizeof(int)*4*CHAR_BIT)/10 + 6)
15
16 static void
17 clear_var(int var)
18 {
19         if (var_tab[var])
20                 free(var_tab[var]);
21 }
22
23 static void
24 set_var(int var, char* value)
25 {
26         clear_var(var);
27         var_tab[var] = xstrdup(value);
28         
29 }
30
31 static char*
32 get_var(int var)
33 {
34         if (var < 0)
35                 return const_tab[-var];
36         return var_tab[var];
37 }
38
39 /* return var struct or NULL if not found */
40 static struct variable*
41 get_var_struct(char* name, struct list* hash)
42 {
43         int n;
44         struct variable *p;
45
46         n = get_bucket_number(name);
47         int nocase = isupper(*name);
48         LIST_FOREACH(p, hash + n)
49                 if (!(nocase ? strcasecmp : strcmp)(p->name,name))
50                         return p;
51
52         return NULL;
53 }
54
55 static int 
56 regex_cmp(char* s, char* r)
57 {
58         pcre *brum;
59         int erroroffset;
60         const char* error;
61         int ovector[OVECCOUNT];
62         
63         brum = pcre_compile(r,0,&error,&erroroffset,NULL);
64         if (!brum)
65                 return -1;
66         
67         int res = pcre_exec(brum,NULL,s,strlen(s),0,0,ovector,OVECCOUNT);
68         pcre_free(brum);
69
70         return res;
71 }
72
73 #define UPPER(a) ((a) >> 8)
74 #define LOWER(a) ((a) & 0xFF)
75
76 static char*
77 xcat(char* left, char* right)
78 {
79         char* res = xmalloc(strlen(left) + strlen(right) + 1);
80
81         strcpy(res,left);
82         strcat(left,right);
83
84         free(left);
85         free(right);    
86
87         return res;
88 }
89
90 static void
91 modify_headers(struct list* headers, struct list* hash)
92 {
93         struct hlist* p;
94         int i;
95         struct variable* pv;
96         
97
98         LIST_FOREACH(p, headers){
99                 pv = get_var_struct(p->name, hash);
100                 if (!pv)
101                         continue;
102                 if (pv->modified){
103                         pv->modified = 0;
104                         free(p->value);
105                         p->value = xstrdup(get_var(pv->varcode)); //FIXME: fold it
106                 }
107         }
108
109         // find new headers 
110         for (i = 0; i < HASHSIZE; i++){
111                 LIST_FOREACH(pv, hash + i){
112                         if (isupper(pv->name[0]) && pv->modified){
113                                 pv->modified = 0;
114
115                                 p = xmalloc(sizeof(struct hlist));
116                                 p->name = xstrdup(pv->name);
117                                 p->value = xstrdup(get_var(pv->varcode));
118
119                                 list_add_last(headers,&p->car);
120                         }
121                 }
122         }
123 }
124
125 static struct list*
126 copy_headers(struct list* orig)
127 {
128         struct list* new = xmalloc(sizeof(struct list));
129         struct hlist* po, *pn;
130
131         list_init(new);
132
133         LIST_FOREACH(po, orig){
134                 pn = xmalloc(sizeof(struct hlist));
135                 pn->name = xstrdup(po->name);
136                 pn->value = xstrdup(po->value);
137                 pn->have_var = 0;
138
139                 list_add_last(new, &pn->car);
140         }
141
142         return new;
143 }
144
145 static struct email* 
146 prepare_email(struct list* hash)
147 {
148         struct email* em;
149
150         em = xmalloc(sizeof(struct email));
151
152         modify_headers(current_headers, hash);
153         em->headers = copy_headers(current_headers);
154         em->body_len = current_body->body_len; 
155         em->body = xmalloc(em->body_len);
156         memcpy(em->body, current_body->body, em->body_len);
157
158         return em;
159 }
160
161 static void
162 do_string_ternary_op(struct code* p)
163 {
164         char* l = get_var(p->u.tpop.l);
165         char* r = get_var(p->u.tpop.r);
166         char* result;
167
168         switch(p->opcode) {
169                 case OPC_RE:
170                         result = xmalloc(INT_TO_STRING_LEN);
171                         sprintf(result, "%d", regex_cmp(l, r));
172                 case OPC_NRE:
173                         result = xmalloc(INT_TO_STRING_LEN);
174                         sprintf(result, "%d", !regex_cmp(l, r));
175                 case OPC_CAT:
176                         result = xcat(l, r);
177                 default:
178                         break;
179         };
180
181         set_var(p->u.tpop.res, result); 
182 }
183
184 static void
185 do_num_ternary_op(struct code* p)
186 {
187         int l, r, res;
188         char* result = xmalloc(INT_TO_STRING_LEN);
189
190         sscanf(get_var(p->u.tpop.l),"%d", &l);
191         sscanf(get_var(p->u.tpop.r),"%d", &r);
192
193         switch(p->opcode) {
194                 case OPC_GT:
195                         res = (l > r);
196                         break;
197                 case OPC_LT:
198                         res = (l < r);
199                         break;
200                 case OPC_LE:
201                         res = (l <= r);
202                         break;
203                 case OPC_GE:
204                         res = (l >= r);
205                         break;
206                 case OPC_EQ:
207                         res = (l == r);
208                         break;
209                 case OPC_NEQ:
210                         res = (l != r);
211                         break;
212                 case OPC_AND:
213                         res = (l && r);
214                         break;
215                 case OPC_OR:
216                         res = (l || r);
217                         break;
218                 case OPC_XOR:
219                         res = ((l || r) && !(l && r));
220                         break;
221                 case OPC_PLUS:
222                         res = (l + r);
223                         break;
224                 case OPC_MINUS:
225                         res = (l - r);
226                         break;
227                 case OPC_MUL:
228                         res = (l * r);
229                         break;
230                 case OPC_DIV:
231                         res = (l / r);
232                         break;
233                 default:
234                         break;
235         }
236
237         sprintf(result, "%d", res);
238         set_var(p->u.tpop.res, result);
239 }
240
241 static int
242 eval_cond(int var)
243 {
244         char* val = get_var(var);
245         int v;
246
247         if (! val)
248                 return 0;
249         if (! *val)
250                 return 0;
251         sscanf(val, "%d", &v);
252
253         return !!v;
254 }
255
256 void
257 interp(struct list* ins)
258 {
259         struct code* p;
260         char* result;
261         int v;
262         
263         LIST_FOREACH(p, ins) {
264         switch (p->opcode) {
265                 case OPC_SET:
266                         set_var(p->u.set.l, get_var(p->u.set.r));
267                         break;  
268                 case OPC_JUMP:
269                         p = p->u.jump.target;
270                         continue;
271                         break;
272                 case OPC_JUMP_IF:
273                         if (eval_cond(p->u.jump_if.cond))
274                                 p = p->u.jump_if.target;
275                         continue;
276                         break;
277                 case OPC_JUMP_UNLESS:
278                         if (!eval_cond(p->u.jump_unless.cond))
279                                 p = p->u.jump_unless.target;
280                         continue;
281                         break;
282                 case OPC_NOP:
283                         continue;
284                         break;
285                 case OPC_GT:
286                 case OPC_LT:
287                 case OPC_LE:
288                 case OPC_GE:
289                 case OPC_EQ:
290                 case OPC_NEQ:
291                 case OPC_AND:
292                 case OPC_OR:
293                 case OPC_XOR:
294                 case OPC_PLUS:
295                 case OPC_MINUS:
296                 case OPC_MUL:
297                 case OPC_DIV:
298                         do_num_ternary_op(p);
299                         break;
300                 case OPC_NOT:
301                         result = xmalloc(INT_TO_STRING_LEN);
302                         sscanf(get_var(p->u.tpop.l),"%d", &v);
303                         sprintf(result, "%d", !v);
304                         set_var(p->u.tpop.res, result);
305                 case OPC_CAT:
306                 case OPC_RE:
307                 case OPC_NRE:
308                         do_string_ternary_op(p);
309                         break;
310                 case OPC_PIPE:
311                         break;
312                 case OPC_MAIL:
313                         break;
314                 case OPC_DELIVER:
315                         break;
316                 case OPC_CALL_EXT:
317                         break;
318                 case OPC_DISCARD:
319                         break;
320         }}
321 }
322
323 void
324 print_vars(struct list* hash)
325 {
326         int i;
327         struct variable* p;
328
329         for (i=0; i<HASHSIZE; i++){
330                 LIST_FOREACH(p, hash + i)
331                         printf("%s=%s\n",p->name, get_var(p->varcode));
332         }
333 }
334
335 static char*
336 unfold(char* u)
337 {
338         char* new;
339         char* pu = u; 
340         char* pn;
341
342         new = xmalloc(strlen(u)+1);
343         pn = new;
344
345 #define IS_WHITE(c) ((c) == '\t' || (c)==' ' || c=='\n')
346
347         while (IS_WHITE(*pu))
348                 pu++;
349
350         while (*pu != 0){
351                 if (IS_WHITE(*pu)){
352                         while (IS_WHITE(*pu))
353                                 pu++;
354                         if (*pu != 0)
355                                 *pn++ = ' ';
356                 } else
357                         *pn++ = *pu++;          
358         }
359         *pn = 0;
360
361         return new;
362 }
363
364 void
365 save_current_headers(struct list* hash)
366 {
367         struct hlist* p;
368         char* u;
369         struct variable* pv;
370
371         LIST_FOREACH(p, current_headers){
372                 pv = get_var_struct(p->name, hash);
373                 if (!pv)
374                         continue;
375                 u = unfold(p->value);
376                 set_var(pv->varcode, u);
377                 pv->modified = 0;
378                 p->have_var = 1;
379         }
380
381 }
382
383 static void
384 get_default_mailbox(char* mb)
385 {
386         default_mailbox = mb;
387 }