]> mj.ucw.cz Git - umpf.git/blobdiff - code.c
fix content length after filtering mail
[umpf.git] / code.c
diff --git a/code.c b/code.c
index 04b41b3acfb3fb9310ada0627933f46e6342c7ac..932bb9ab5d8766c3a43f508a43b5add5b27825ab 100644 (file)
--- a/code.c
+++ b/code.c
@@ -5,9 +5,6 @@
 
 #include "umpf.h"
 
-#define HASHSIZE 103
-#define MAGIC 19
-
 struct list* 
 new_var_hash(void)
 {
@@ -21,7 +18,7 @@ new_var_hash(void)
        return res;
 }
 
-static int
+int
 get_bucket_number(char* name)
 {
        unsigned int n = 0;
@@ -35,22 +32,36 @@ get_bucket_number(char* name)
         return n;
 }
 
-/* if not found, variable with value "" is created  */ 
+/* return var struct or NULL if not found */
+struct variable*
+get_var_struct(char* name, enum var_type type, struct list* hash)
+{
+       int n;
+       struct variable *p;
+
+       n = get_bucket_number(name);
+       LIST_FOREACH(p, hash + n)
+               if (!strcasecmp(p->name, name) && p->type == type)
+                       return p;
+
+       return NULL;
+}
+
 int
-find_var(char* name, struct list* hash)
+find_var(char* name, enum var_type type, 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 (!strcasecmp(p->name, name) && p->type == type)
                        return p->varcode;
 
        p = xmalloc(sizeof(struct variable));
        p->name = xstrdup(name);
        p->varcode = current_varcode++;
+       p->type = type;
        list_add_last(hash+n, &p->car);
 
        return p->varcode;
@@ -80,38 +91,58 @@ new_instr(struct code c, struct list* where)
                list_add_last(&input_code, &p->car);
 }
 
+static int
+new_3par_instr(int opcode, int left, int right, int pref_var, 
+                struct list* where)
+{
+       struct code ins;
+
+       ins.opcode = opcode;
+       ins.u.tpop.l = left;
+       ins.u.tpop.r = right;
+       if (pref_var >= 0)
+               ins.u.tpop.res = pref_var;
+       else
+               ins.u.tpop.res = current_varcode++;;
+       new_instr(ins, where);
+       return ins.u.tpop.res;
+}
+
 /* return number of variable where lies result 
  * pref_var < 0 => no preference
  */
 static int
 evaluate(struct tree* t, int pref_var, struct list* where)
 {
-       struct code ins;
-
        if (t->st == ST_LEAF) { 
                return t->pt.leaf.n;
-       } else if (t->st == ST_OP) {
-               int left, right;
-               left = evaluate(t->pt.op.left, -1, where);
-               right = evaluate(t->pt.op.right, -1, where);
-               switch (t->pt.op.op) {
-                       case '.':
-                               ins.opcode = CAT;
-                               ins.u.tpop.l = left;
-                               ins.u.tpop.r = right;
-                               if (pref_var >= 0)
-                                       ins.u.tpop.res = pref_var;
-                               else
-                                       ins.u.tpop.res = current_varcode++;;
-                               new_instr(ins, where);
-                               return ins.u.tpop.res;
-                               break;
-                       default:
-                               die("evaluate: got to default");
-               }
-       } else
-               die("evaluate: I can evaluate only expressions but I got %d",
-                       t->st);
+       } 
+       int left, right;
+       left = evaluate(t->pt.op.left, -1, where);
+       right = evaluate(t->pt.op.right, -1, where);
+       switch (t->pt.op.op) {
+               case '.':
+                       return new_3par_instr(OPC_CAT, left, 
+                               right, pref_var, where);
+                       break;
+               case '+':
+                       return new_3par_instr(OPC_PLUS, left, 
+                               right, pref_var, where);
+                       break;
+               case '-':
+                       return new_3par_instr(OPC_MINUS, left, 
+                               right, pref_var, where);
+                       break;
+               case '*':
+                       return new_3par_instr(OPC_MUL, left, 
+                               right, pref_var, where);
+                       break;
+               case '/':
+                       return new_3par_instr(OPC_DIV, left, 
+                               right, pref_var, where);
+                       break;
+       }
+       die("evaluate: Never can get here :)");
 }
 
 static void
@@ -122,30 +153,13 @@ do_ass(struct tree* t, struct list* where)
        var_l = t->pt.ass.left->pt.leaf.n;
        var_r = evaluate(t->pt.ass.right, -1, where);
        
-       ins.opcode = SET;
+       ins.opcode = OPC_SET;
        ins.u.set.l = var_l;
        ins.u.set.r = var_r;
        new_instr(ins, where);
 
 }
 
-static int
-new_cond_instr(int opcode, int left, int right, int pref_var, 
-                struct list* where)
-{
-       struct code ins;
-
-       ins.opcode = opcode;
-       ins.u.tpop.l = left;
-       ins.u.tpop.r = right;
-       if (pref_var >= 0)
-               ins.u.tpop.res = pref_var;
-       else
-               ins.u.tpop.res = current_varcode++;;
-       new_instr(ins, where);
-       return ins.u.tpop.res;
-}
-
 static int
 eval_cond(struct tree *t, int pref_var, struct list* where)
 {
@@ -165,7 +179,35 @@ eval_cond(struct tree *t, int pref_var, struct list* where)
 
                switch (t->pt.cond.op) {                
                        case '>':
-                               return new_cond_instr(GT, left, 
+                               return new_3par_instr (OPC_GT, left, 
+                                       right, pref_var, where);
+                               break;
+                       case '<':
+                               return new_3par_instr (OPC_LT, left, 
+                                       right, pref_var, where);
+                               break;
+                       case CC('<','='):
+                               return new_3par_instr (OPC_LE, left, 
+                                       right, pref_var, where);
+                               break;
+                       case CC('>','='):
+                               return new_3par_instr (OPC_GE, left, 
+                                       right, pref_var, where);
+                               break;
+                       case CC('!','~'):
+                               return new_3par_instr (OPC_NRE, left, 
+                                       right, pref_var, where);
+                               break;
+                       case CC('~','~'):
+                               return new_3par_instr (OPC_RE, left, 
+                                       right, pref_var, where);
+                               break;
+                       case CC('=','='):
+                               return new_3par_instr (OPC_EQ, left, 
+                                       right, pref_var, where);
+                               break;
+                       case CC('!','='):
+                               return new_3par_instr (OPC_NEQ, left, 
                                        right, pref_var, where);
                                break;
                        /* fixme: do more of them */
@@ -176,13 +218,34 @@ eval_cond(struct tree *t, int pref_var, struct list* where)
                }
        }
        if (t->pt.cond.type == OP_BOOL) {
+               struct code ins;
+
                left = eval_cond(t->pt.cond.left, -1, where);
-               right = eval_cond(t->pt.cond.right, -1, where);
+               if (t->pt.cond.op != '!') /* ! is unary */
+                       right = eval_cond(t->pt.cond.right, -1, where);
                switch (t->pt.cond.op) {
                        case '&':
-                               return new_cond_instr(AND, left, 
+                               return new_3par_instr (OPC_AND, left, 
                                        right, pref_var, where);
                                break;
+                       case '|':
+                               return new_3par_instr (OPC_OR, left, 
+                                       right, pref_var, where);
+                               break;
+                       case '^':
+                               return new_3par_instr (OPC_XOR, left, 
+                                       right, pref_var, where);
+                               break;
+                       case '!':
+                               ins.opcode = OPC_NOT;
+                               ins.u.dpop.par = left;
+                               if (pref_var >= 0)
+                                       ins.u.dpop.res = pref_var;
+                               else
+                                       ins.u.dpop.res = current_varcode++;;
+                               new_instr(ins, where);
+                               return ins.u.dpop.res;
+                               break;
                        default:
                                die("eval_cond: unknown boolean op %c\n", 
                                t->pt.cond.op);
@@ -202,8 +265,8 @@ do_if(struct tree *t, struct list* where)
 
        list_init(if_branch);
        list_init(else_branch);
-       nop.opcode  = NOP;
-       jmp.opcode = JUMP;
+       nop.opcode  = OPC_NOP;
+       jmp.opcode = OPC_JUMP;
 
        c = eval_cond(t->pt.tif.c, -1, where);
 
@@ -214,7 +277,7 @@ do_if(struct tree *t, struct list* where)
        jmp.u.jump.target = list_last(else_branch);
        new_instr(jmp, if_branch);
        
-       ins.opcode = JUMP_UNLESS;
+       ins.opcode = OPC_JUMP_UNLESS;
        ins.u.jump_unless.cond = c;
        ins.u.jump_unless.target = list_last(if_branch);
        new_instr(ins, where);
@@ -238,16 +301,19 @@ do_arrow(struct tree* t, struct list* where)
                ins.u.arrow.copy = 0;
        switch (t->pt.arrow.right) {
                case K_EMPTY:
-                       ins.opcode = STORE;
+                       ins.opcode = OPC_DELIVER;
                        break;
                case K_PIPE:
-                       ins.opcode = PIPE;
+                       ins.opcode = OPC_PIPE;
                        break;
                case K_MAIL:
-                       ins.opcode = MAIL;
+                       ins.opcode = OPC_MAIL;
                        break;
                case K_DISCARD:
-                       ins.opcode = DISCARD;
+                       ins.opcode = OPC_DISCARD;
+                       break;
+               case K_FILTER:
+                       ins.opcode = OPC_FILTER;
                        break;
                default:
                        die("do_arrow: This cannot happen ;-)");
@@ -264,6 +330,8 @@ do_arrow(struct tree* t, struct list* where)
 static void
 reset_temp_var_count(void)
 {
+       if (current_varcode > max_varcode)
+               max_varcode = current_varcode;
        current_varcode = temp_varcode_start;
 }
 
@@ -311,38 +379,83 @@ print_code(void)
 
        LIST_FOREACH(p, &input_code) {
                switch (p->opcode) {
-                       case SET:
+                       case OPC_SET:
                                printf("SET %d %d\n", p->u.set.l, p->u.set.r);
                                break; 
-                       case CAT:
+                       case OPC_CAT:
                                printf("CAT %d %d %d\n", p->u.tpop.l,
                                p->u.tpop.r, p->u.tpop.res);
                                break;
-                       case JUMP:
+                       case OPC_JUMP:
                                printf("JUMP %d\n", (int) p->u.jump.target);
                                break;
-                       case JUMP_UNLESS:
+                       case OPC_JUMP_UNLESS:
                                printf("JUMP_UNLESS %d %d\n", p->u.jump_unless.cond,(int) p->u.jump_unless.target);
                                break;
-                       case GT:
+                       case OPC_GT:
                                printf("GT %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
                                break;
-                       case AND:
+                       case OPC_LT:
+                               printf("LT %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
+                               break;
+                       case OPC_LE:
+                               printf("LE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
+                               break;
+                       case OPC_GE:
+                               printf("GE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
+                               break;
+                       case OPC_RE:
+                               printf("RE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
+                               break;
+                       case OPC_NRE:
+                               printf("NRE %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
+                               break;
+                       case OPC_NEQ:
+                               printf("NEQ %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
+                               break;
+                       case OPC_EQ:
+                               printf("EQ %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
+                               break;
+                       case OPC_AND:
                                printf("AND %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
                                break;
-                       case NOP:
+                       case OPC_OR:
+                               printf("OR %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
+                               break;
+                       case OPC_XOR:
+                               printf("XOR %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
+                               break;
+                       case OPC_PLUS:
+                               printf("PLUS %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
+                               break;
+                       case OPC_MINUS:
+                               printf("MINUS %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
+                               break;
+                       case OPC_MUL:
+                               printf("MUL %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
+                               break;
+                       case OPC_DIV:
+                               printf("DIV %d %d %d\n", p->u.tpop.l, p->u.tpop.r, p->u.tpop.res);
+                               break;
+                       case OPC_NOT:
+                               printf("NOT %d %d\n", p->u.dpop.par, p->u.dpop.res);
+                               break;
+                       case OPC_NOP:
                                puts("NOP");    
                                break;
-                       case PIPE:
+                       case OPC_PIPE:
                                printf("PIPE %d %d\n", p->u.arrow.what, p->u.arrow.copy);
                                break;
-                       case STORE:
-                               printf("STORE %d %d\n", p->u.arrow.what, p->u.arrow.copy);
+                       case OPC_FILTER:
+                               printf("FILTER %d %d\n", p->u.arrow.what, p->u.arrow.copy);
+                               break;
+                       case OPC_DELIVER:
+                               printf("DELIVER %d %d\n", p->u.arrow.what, p->u.arrow.copy);
                                break;
-                       case MAIL:
+                       case OPC_MAIL:
                                printf("MAIL %d %d\n", p->u.arrow.what, p->u.arrow.copy);
                                break;
-                       case DISCARD:
+                       case OPC_DISCARD:
                                puts("DISCARD");
                                break;
                        default: