]> mj.ucw.cz Git - umpf.git/blobdiff - int.c
cleanup
[umpf.git] / int.c
diff --git a/int.c b/int.c
index 73e34ff5f613834fc906bf3805020efc94bb0b26..b83b435178cf96029f0f2139c2f6b3a82db21034 100644 (file)
--- a/int.c
+++ b/int.c
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <pcre.h>
+#include <ctype.h>
 
 #include "cond.tab.h"
 #include "brum.h"
@@ -27,7 +28,7 @@ get_bucket_number(char* name)
        unsigned char* p = name;
 
         while (*p != '\0'){
-                n = n * MAGIC + *p++;
+                n = n * MAGIC + toupper(*p++);
         }
         n %= HASHSIZE;
 
@@ -44,20 +45,28 @@ find_var(char* name, char* value, struct variable** hash)
        n = get_bucket_number(name);
 
        p = hash[n];
-       while(p && strcmp(p->name,name))
-               p = p->next;
+
+       if (isupper(*name)){
+               while(p && strcasecmp(p->name,name))
+                       p = p->next;
+       } else {
+               while(p && strcmp(p->name,name))
+                       p = p->next;
+       }
 
        if (p && value){
                free(p->value);
                p->value = value;
+               p->modified = 1;
        } else if (p && !value)
                return p;
        else {
                p = xmalloc(sizeof(struct variable));
                p->next = hash[n];
                hash[n] = p;
-               p->name = xstrdup(name);
+               p->name = name; 
                p->value = (value? value:xstrdup(""));
+               p->modified = 1;
        }
 
        return p;
@@ -132,7 +141,8 @@ print_tree(struct tree* t, int ind)
                        printf("%*s ->\n", ind, "");
                        if (t->pt.arrow.kw_right)
                                printf("%*s%s\n", ind+1, "", t->pt.arrow.kw_right);
-                       print_tree(t->pt.arrow.s,ind+1);
+                       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);
@@ -181,6 +191,7 @@ interp_ass_right(struct tree* t, struct variable** hash)
                }
 }      
 
+// FIXME: we would like to be able also do things like ($a & $b) == $c
 int
 interp_cond(struct tree* t, struct variable** hash)
 {
@@ -189,7 +200,7 @@ interp_cond(struct tree* t, struct variable** hash)
 
        if (t->pt.cond.type == OP_REL){
                if (t->pt.cond.left->st != ST_LEAF || t->pt.cond.right->st != ST_LEAF)
-       die("Chlemst");
+                       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);
@@ -202,7 +213,7 @@ interp_cond(struct tree* t, struct variable** hash)
                                return regex_cmp(left,right);
                        case CC('!','~'):
                                return !regex_cmp(left,right);
-               }
+               } //TODO: add numbers
 
        } else {
                int left = interp_cond(t->pt.cond.left, hash);
@@ -224,6 +235,77 @@ interp_cond(struct tree* t, struct variable** hash)
        }
 }
 
+static void
+modify_headers(struct hlist* headers, struct variable** hash)
+{
+       struct hlist* p;
+       struct hlist* last = NULL;
+       struct variable* pv;
+       int i;
+
+       for(p = headers; p; p = p->next){
+               pv = find_var(p->name,NULL,hash);
+               if (pv->modified){
+                       pv->modified = 0;
+                       free(pv->value);
+                       pv->value = xstrdup(p->value); //FIXME: fold it
+               }
+               last = p;
+       }
+
+       /* find new headers */
+       for (i = 0; i < HASHSIZE; i++){
+               for(pv = hash[i]; pv; pv = pv->next){
+                       if (isupper(pv->name[0]) && pv->modified){
+                               pv->modified = 0;
+                               p = xmalloc(sizeof(struct hlist));
+
+                               last->next = p; //FIXME
+                               p->next = NULL;
+                               p->name = xstrdup(pv->name);
+                               p->value = xstrdup(pv->value);
+                       }
+               }
+       }
+}
+
+static struct hlist*
+copy_headers(struct hlist* orig)
+{
+       struct hlist* new = NULL;
+       struct hlist* po, * pn = NULL;
+
+       for (po = orig; po; po = po->next){
+               if (!pn)
+                       pn = xmalloc(sizeof(struct hlist));
+               pn->next = xmalloc(sizeof(struct hlist));
+               pn = pn->next;
+               pn->next = NULL;
+               pn->name = xstrdup(po->name);
+               pn->value = xstrdup(po->value);
+               if (!new)
+                       new = pn;
+       }
+
+       return new;
+}
+
+static void
+new_action(char* l, char* r, char* s, struct variable** hash)
+{
+       struct action* a;
+
+       a = xmalloc(sizeof(struct action));
+
+       modify_headers(current_headers, hash);
+       a->e.headers = copy_headers(current_headers);
+       a->l = l;
+       a->r = r;
+       a->s = s;
+
+       do_action(a);
+}
+
 void
 interp(struct tree* t, struct variable** hash)
 {
@@ -244,6 +326,9 @@ interp(struct tree* t, struct variable** 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:
@@ -266,3 +351,47 @@ print_vars(struct variable** hash)
                }               
        }
 }
+
+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 variable** hash)
+{
+       struct hlist* p;
+       struct variable* pv;
+       char* u;
+
+       for (p = current_headers;p;p = p->next){
+               u = unfold(p->value);
+               pv = find_var(p->name,u,hash);
+               pv->modified = 0;
+       }
+
+}