]> mj.ucw.cz Git - umpf.git/blobdiff - int.c
rename to umpf, guess default mailbox
[umpf.git] / int.c
diff --git a/int.c b/int.c
index 5f0a9366362a74ac1ed0cd75ce973b8792f92282..f7fe023b592f5c5538c33d003251a2494e02d86a 100644 (file)
--- a/int.c
+++ b/int.c
@@ -1,28 +1,25 @@
 #include <stdio.h>
 #include <string.h>
 #include <pcre.h>
+#include <ctype.h>
 
 #include "cond.tab.h"
-#include "brum.h"
+#include "umpf.h"
 
 #define OVECCOUNT 3
-
 #define HASHSIZE 103
 #define MAGIC 19
 
-struct variable {
-       char* name;
-       char* value;
-       struct variable* next;
-};
-
-struct variable**
+struct list* 
 new_var_hash(void)
 {
-       struct variable** res;
+       struct list* res;
+       int i;
 
-       res = xmalloc (HASHSIZE * sizeof(struct variable*));
-       memset(res, 0, sizeof(struct variable*)*HASHSIZE);
+       res = xmalloc (HASHSIZE * sizeof(struct list));
+       for (i = 0; i < HASHSIZE; i++)
+               list_init(res + i);
+       
 
        return res;
 }
@@ -34,7 +31,7 @@ get_bucket_number(char* name)
        unsigned char* p = name;
 
         while (*p != '\0'){
-                n = n * MAGIC + *p++;
+                n = n * MAGIC + toupper(*p++);
         }
         n %= HASHSIZE;
 
@@ -43,44 +40,31 @@ get_bucket_number(char* name)
 
 /* value NULL for finding without modyfiing */
 static struct variable*
-find_var(char* name, char* value, struct variable** hash)
+find_var(char* name, char* value, struct list* hash)
 {
        int n;
        struct variable *p;
 
        n = get_bucket_number(name);
+       int nocase = isupper(*name);
+       LIST_FOREACH(p, hash + n)
+               if (!(nocase ? strcasecmp : strcmp)(p->name,name)){
+                       if (value){
+                               free(p->value);
+                               p->value = value;
+                               p->modified = 1;
+                       }
+                       return p;
+               }
 
-       p = hash[n];
-       while(p && strcmp(p->name,name))
-               p = p->next;
-
-       if (!value)
-               return p;
-       if (p)
-               free(p->value);
-       else {
-               p = xmalloc(sizeof(struct variable));
-               p->next = hash[n]->next;
-               hash[n]->next = p;
-               p->name = xstrdup(name);
-       }
-
-       p->value = xstrdup(value);
-
+       p = xmalloc(sizeof(struct variable));
+       p->name = xstrdup(name); 
+       p->value = (value? value:xstrdup(""));
+       p->modified = 1;
+       list_add_last(hash+n, &p->car);
        return p;
 }
 
-static void
-print_ind(int num, char c)
-{
-       int i;
-
-       for (i = 0; i < num; i++){
-               putchar(c);
-       }
-//printf("%*s", num, "");
-}
-
 static int 
 regex_cmp(char* s, char* r)
 {
@@ -107,22 +91,18 @@ print_tree(struct tree* t, int ind)
 
        switch (t->st){
                case ST_IF:
-                       print_ind(ind,' ');
-                       puts("if");
+                       printf("%*s if\n", ind, "");
                        print_tree(t->pt.tif.c,ind+1);
-                       print_ind(ind,' ');
-                       puts("then");
+                       printf("%*s then\n", ind, "");
                        print_tree(t->pt.tif.i,ind+1);
-                       print_ind(ind,' ');
-                       puts("else");
+                       printf("%*s else\n", ind, "");
                        print_tree(t->pt.tif.e,ind+1);
                        break;
                case ST_COND:
 #define UPPER(a) ((a) >> 8)
 #define LOWER(a) ((a) & 0xFF)
                        print_tree(t->pt.cond.left, ind+1);
-                       print_ind(ind,' ');
-
+                       printf("%*s", ind, "");
                        if (UPPER(t->pt.cond.op) > 0)
                                putchar(UPPER(t->pt.cond.op));
                        putchar(LOWER(t->pt.cond.op));
@@ -135,12 +115,11 @@ print_tree(struct tree* t, int ind)
                        break;
                case ST_ASS:
                        print_tree(t->pt.ass.left, ind+1);
-                       print_ind(ind,' ');     
-                       puts("=");
+                       printf("%*s =\n", ind, "");
                        print_tree(t->pt.ass.right, ind+1);
                        break;
                case ST_LEAF:
-                       print_ind(ind, ' ');
+                       printf("%*s", ind, "");
                        switch (t->pt.leaf.type){
                                case L_VAR:
                                        putchar('$');
@@ -150,23 +129,17 @@ print_tree(struct tree* t, int ind)
                        }
                        break;
                case ST_ARROW:
-                       if (t->pt.arrow.kw_left){
-                               print_ind(ind+1, ' ');
-                               puts(t->pt.arrow.kw_left);
-                       }
-                       print_ind(ind, ' ');
-                       printf("->\n");
-                       if (t->pt.arrow.kw_right){
-                               print_ind(ind+1, ' ');
-                               puts(t->pt.arrow.kw_right);
-                       }
-                       print_tree(t->pt.arrow.s,ind+1);
+                       if (t->pt.arrow.kw_left)
+                               printf("%*s%s\n", ind+1, "", t->pt.arrow.kw_left);
+                       printf("%*s ->\n", ind, "");
+                       if (t->pt.arrow.kw_right)
+                               printf("%*s%s\n", ind+1, "", t->pt.arrow.kw_right);
+                       if (t->pt.arrow.s)
+                               print_tree(t->pt.arrow.s,ind+1);
                        break;
                case ST_OP:
                        print_tree(t->pt.op.left, ind+1);
-                       print_ind(ind,' ');     
-                       putchar(t->pt.op.op);
-                       putchar('\n');
+                       printf("%*s%c\n", ind, "", t->pt.op.op);
                        print_tree(t->pt.op.right, ind+1);
                        break;  
                case ST_EMPTY:
@@ -176,20 +149,248 @@ print_tree(struct tree* t, int ind)
        }
 }
 
+static char*
+xcat(char* left, char* right)
+{
+       char* res = xmalloc(strlen(left) + strlen(right) + 1);
+
+       strcpy(res,left);
+       strcat(left,right);
+
+       free(left);
+       free(right);    
+
+       return res;
+}
+
+static char*
+interp_ass_right(struct tree* t, struct list* hash)
+{
+       switch (t->st){
+               case ST_LEAF:
+                       if (t->pt.leaf.type == L_VAR)
+                               return xstrdup(find_var(t->pt.leaf.value,NULL,hash)->value);
+                       else 
+                               return xstrdup(t->pt.leaf.value);
+               case ST_OP:
+                       switch (t->pt.op.op){
+                               case '.':
+                                       return xcat(interp_ass_right(t->pt.op.left, hash),interp_ass_right(t->pt.op.right, hash));
+                       }       
+               case ST_EMPTY:
+                       return xstrdup("");
+               default:
+                       die("interp_ass_right: got to default");        
+               }
+}      
+
+// FIXME: we would like to be able also do things like ($a & $b) == $c
+static int
+interp_cond(struct tree* t, struct list* hash)
+{
+       if (t->st != ST_COND)
+               die("Muhehehechlemst?");
+
+       if (t->pt.cond.type == OP_REL){
+               if (t->pt.cond.left->st != ST_LEAF || t->pt.cond.right->st != ST_LEAF)
+                       die("Chlemst");
+
+               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);
+       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);
+               switch (t->pt.cond.op){
+                       case CC('=','='):
+                               return !strcmp(left,right);
+                       case CC('!','='):
+                               return strcmp(left,right);
+                       case CC('~','~'):
+                               return regex_cmp(left,right);
+                       case CC('!','~'):
+                               return !regex_cmp(left,right);
+                       default:
+                               die("Brrrchlemst!");
+               } //TODO: add numbers
+
+       } else {
+               int left = interp_cond(t->pt.cond.left, hash);
+               int right;
+
+               if (t->pt.cond.op != '!')
+                       right = interp_cond(t->pt.cond.right, hash);
+
+               switch (t->pt.cond.op){
+                       case '&':
+                               return left && right;
+                       case '|':
+                               return left || right;
+                       case '^':
+                               return (left || right) && !(left && right);
+                       case '!':
+                               return !left;
+                       default:
+                               die("Brrrchlemst!");
+               }
+       }
+}
+
+static void
+modify_headers(struct list* headers, struct list* hash)
+{
+       struct hlist* p;
+       struct variable* pv;
+       int i;
+
+       LIST_FOREACH(p, headers){
+               pv = find_var(p->name,NULL,hash);
+               if (pv->modified){
+                       pv->modified = 0;
+                       free(p->value);
+                       p->value = xstrdup(pv->value); //FIXME: fold it
+               }
+       }
+
+       /* find new headers */
+       for (i = 0; i < HASHSIZE; i++){
+               LIST_FOREACH(pv, hash + i){
+                       if (isupper(pv->name[0]) && pv->modified){
+                               pv->modified = 0;
+
+                               p = xmalloc(sizeof(struct hlist));
+                               p->name = xstrdup(pv->name);
+                               p->value = xstrdup(pv->value);
+
+                               list_add_last(headers,&p->car);
+                       }
+               }
+       }
+}
+
+static struct list*
+copy_headers(struct list* orig)
+{
+       struct list* new = xmalloc(sizeof(struct list));
+       struct hlist* po, *pn;
+
+       list_init(new);
+
+       LIST_FOREACH(po, orig){
+               pn = xmalloc(sizeof(struct hlist));
+               pn->name = xstrdup(po->name);
+               pn->value = xstrdup(po->value);
+
+               list_add_last(new, &pn->car);
+       }
+
+       return new;
+}
+
+static void
+new_action(char* l, char* r, char* s, struct list* hash)
+{
+       struct action* a;
+
+       a = xmalloc(sizeof(struct action));
+
+       modify_headers(current_headers, hash);
+       a->e.headers = copy_headers(current_headers);
+       a->e.body_len = current_body->body_len; 
+       a->e.body = xmalloc(a->e.body_len);
+       memcpy(a->e.body, current_body->body, a->e.body_len);
+       a->l = l;
+       a->r = r;
+       a->s = s;
+
+       do_action(a);
+}
+
 void
-interp(struct tree* t)
+interp(struct tree* t, struct list* hash)
 {
        if (!t)
                return;
 
        switch(t->st){
                case ST_BLOCK:
-                       interp(t->pt.block.head);
-                       interp(t->pt.block.tail);
-               break;
+                       interp(t->pt.block.head, hash);
+                       interp(t->pt.block.tail, hash);
+                       break;
                case ST_ASS:
-               //      find_name(t->pt.ass.left->pt.leaf.value.s, interp_ass_right(t->pt.ass.right), var_hash);
-               break;
+                       find_var(t->pt.ass.left->pt.leaf.value, interp_ass_right(t->pt.ass.right, hash), hash);
+                       break;
+               case ST_IF:
+                       if (interp_cond(t->pt.tif.c, hash))
+                               interp(t->pt.tif.i, hash);
+                       else 
+                               interp(t->pt.tif.e, hash);
+                       break;
+               case ST_ARROW:
+                       new_action(t->pt.arrow.kw_left, t->pt.arrow.kw_right, interp_ass_right(t->pt.arrow.s, hash),hash);
+                       break;
+               case ST_EMPTY:
+                       break;  
+               default:
+                       die("interp: got to default");
+       }
+
+}
+
+void
+print_vars(struct list* hash)
+{
+       int i;
+       struct variable* p;
+
+       for (i=0; i<HASHSIZE; i++){
+               LIST_FOREACH(p, hash + i)
+                       printf("%s=%s\n",p->name, p->value);
+       }
+}
+
+static char*
+unfold(char* u)
+{
+       char* new;
+       char* pu = u; 
+       char* pn;
+
+       new = xmalloc(strlen(u)+1);
+       pn = new;
+
+#define IS_WHITE(c) ((c) == '\t' || (c)==' ' || c=='\n')
+
+       while (IS_WHITE(*pu))
+               pu++;
+
+       while (*pu != 0){
+               if (IS_WHITE(*pu)){
+                       while (IS_WHITE(*pu))
+                               pu++;
+                       if (*pu != 0)
+                               *pn++ = ' ';
+               } else
+                       *pn++ = *pu++;          
        }
+       *pn = 0;
+
+       return new;
+}
 
-};
+void
+save_current_headers(struct list* hash)
+{
+       struct hlist* p;
+       struct variable* pv;
+       char* u;
+
+       LIST_FOREACH(p, current_headers){
+               u = unfold(p->value);
+               pv = find_var(p->name,u,hash);
+               pv->modified = 0;
+       }
+
+}
+
+void
+get_default_mailbox(char* mb)
+{
+       default_mailbox = mb;
+}