19 res = xmalloc (HASHSIZE * sizeof(struct list));
20 for (i = 0; i < HASHSIZE; i++)
28 get_bucket_number(char* name)
31 unsigned char* p = name;
34 n = n * MAGIC + toupper(*p++);
41 /* value NULL for finding without modyfiing */
42 static struct variable*
43 find_var(char* name, char* value, struct list* hash)
48 n = get_bucket_number(name);
49 int nocase = isupper(*name);
50 LIST_FOREACH(p, hash + n)
51 if (!(nocase ? strcasecmp : strcmp)(p->name,name)){
60 p = xmalloc(sizeof(struct variable));
61 p->name = xstrdup(name);
62 p->value = (value? value:xstrdup(""));
64 list_add_last(hash+n, &p->car);
69 regex_cmp(char* s, char* r)
74 int ovector[OVECCOUNT];
76 brum = pcre_compile(r,0,&error,&erroroffset,NULL);
80 int res = pcre_exec(brum,NULL,s,strlen(s),0,0,ovector,OVECCOUNT);
87 print_tree(struct tree* t, int ind)
94 printf("%*s if\n", ind, "");
95 print_tree(t->pt.tif.c,ind+1);
96 printf("%*s then\n", ind, "");
97 print_tree(t->pt.tif.i,ind+1);
98 printf("%*s else\n", ind, "");
99 print_tree(t->pt.tif.e,ind+1);
102 #define UPPER(a) ((a) >> 8)
103 #define LOWER(a) ((a) & 0xFF)
104 print_tree(t->pt.cond.left, ind+1);
105 printf("%*s", ind, "");
106 if (UPPER(t->pt.cond.op) > 0)
107 putchar(UPPER(t->pt.cond.op));
108 putchar(LOWER(t->pt.cond.op));
110 print_tree(t->pt.cond.right, ind+1);
113 print_tree(t->pt.block.head,ind);
114 print_tree(t->pt.block.tail,ind);
117 print_tree(t->pt.ass.left, ind+1);
118 printf("%*s =\n", ind, "");
119 print_tree(t->pt.ass.right, ind+1);
122 printf("%*s", ind, "");
123 switch (t->pt.leaf.type){
127 puts(t->pt.leaf.value);
132 if (t->pt.arrow.kw_left)
133 printf("%*s%s\n", ind+1, "", t->pt.arrow.kw_left);
134 printf("%*s ->\n", ind, "");
135 if (t->pt.arrow.kw_right)
136 printf("%*s%s\n", ind+1, "", t->pt.arrow.kw_right);
138 print_tree(t->pt.arrow.s,ind+1);
141 print_tree(t->pt.op.left, ind+1);
142 printf("%*s%c\n", ind, "", t->pt.op.op);
143 print_tree(t->pt.op.right, ind+1);
153 xcat(char* left, char* right)
155 char* res = xmalloc(strlen(left) + strlen(right) + 1);
167 interp_ass_right(struct tree* t, struct list* hash)
171 if (t->pt.leaf.type == L_VAR)
172 return xstrdup(find_var(t->pt.leaf.value,NULL,hash)->value);
174 return xstrdup(t->pt.leaf.value);
176 switch (t->pt.op.op){
178 return xcat(interp_ass_right(t->pt.op.left, hash),interp_ass_right(t->pt.op.right, hash));
183 die("interp_ass_right: got to default");
187 // FIXME: we would like to be able also do things like ($a & $b) == $c
189 interp_cond(struct tree* t, struct list* hash)
191 if (t->st != ST_COND)
192 die("Muhehehechlemst?");
194 if (t->pt.cond.type == OP_REL){
195 if (t->pt.cond.left->st != ST_LEAF || t->pt.cond.right->st != ST_LEAF)
198 char* left = (t->pt.cond.left->pt.leaf.type == L_VAR ? find_var(t->pt.cond.left->pt.leaf.value,NULL,hash)->value : t->pt.cond.left->pt.leaf.value);
199 char* right = (t->pt.cond.right->pt.leaf.type == L_VAR ? find_var(t->pt.cond.right->pt.leaf.value,NULL,hash)->value : t->pt.cond.right->pt.leaf.value);
200 switch (t->pt.cond.op){
202 return !strcmp(left,right);
204 return strcmp(left,right);
206 return regex_cmp(left,right);
208 return !regex_cmp(left,right);
211 } //TODO: add numbers
214 int left = interp_cond(t->pt.cond.left, hash);
217 if (t->pt.cond.op != '!')
218 right = interp_cond(t->pt.cond.right, hash);
220 switch (t->pt.cond.op){
222 return left && right;
224 return left || right;
226 return (left || right) && !(left && right);
236 modify_headers(struct list* headers, struct list* hash)
242 LIST_FOREACH(p, headers){
243 pv = find_var(p->name,NULL,hash);
247 p->value = xstrdup(pv->value); //FIXME: fold it
251 /* find new headers */
252 for (i = 0; i < HASHSIZE; i++){
253 LIST_FOREACH(pv, hash + i){
254 if (isupper(pv->name[0]) && pv->modified){
257 p = xmalloc(sizeof(struct hlist));
258 p->name = xstrdup(pv->name);
259 p->value = xstrdup(pv->value);
261 list_add_last(headers,&p->car);
268 copy_headers(struct list* orig)
270 struct list* new = xmalloc(sizeof(struct list));
271 struct hlist* po, *pn;
275 LIST_FOREACH(po, orig){
276 pn = xmalloc(sizeof(struct hlist));
277 pn->name = xstrdup(po->name);
278 pn->value = xstrdup(po->value);
280 list_add_last(new, &pn->car);
287 new_action(char* l, char* r, char* s, struct list* hash)
291 a = xmalloc(sizeof(struct action));
293 modify_headers(current_headers, hash);
294 a->e.headers = copy_headers(current_headers);
295 a->e.body = xstrdup(current_body);
304 interp(struct tree* t, struct list* hash)
311 interp(t->pt.block.head, hash);
312 interp(t->pt.block.tail, hash);
315 find_var(t->pt.ass.left->pt.leaf.value, interp_ass_right(t->pt.ass.right, hash), hash);
318 if (interp_cond(t->pt.tif.c, hash))
319 interp(t->pt.tif.i, hash);
321 interp(t->pt.tif.e, hash);
324 new_action(t->pt.arrow.kw_left, t->pt.arrow.kw_right, interp_ass_right(t->pt.arrow.s, hash),hash);
329 die("interp: got to default");
335 print_vars(struct list* hash)
340 for (i=0; i<HASHSIZE; i++){
341 LIST_FOREACH(p, hash + i)
342 printf("%s=%s\n",p->name, p->value);
353 new = xmalloc(strlen(u)+1);
356 #define IS_WHITE(c) ((c) == '\t' || (c)==' ' || c=='\n')
358 while (IS_WHITE(*pu))
363 while (IS_WHITE(*pu))
376 save_current_headers(struct list* hash)
382 LIST_FOREACH(p, current_headers){
383 u = unfold(p->value);
384 pv = find_var(p->name,u,hash);
391 get_default_mailbox(char* mb)
393 default_mailbox = mb;