]> mj.ucw.cz Git - umpf.git/commitdiff
started interpreting
authorAnicka Bernathova <anicka@anicka.net>
Thu, 16 Jul 2009 17:21:59 +0000 (19:21 +0200)
committerAnicka Bernathova <anicka@anicka.net>
Thu, 16 Jul 2009 17:21:59 +0000 (19:21 +0200)
Makefile
code.c
int.c
umpf.c
umpf.h

index 86f9523830c364b1b673dafeae49b4c995ba552a..6131357be4a3ca94b79f64cda315cf2a0effbb0d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ CC=gcc
 CFLAGS=-Wall -W -Wno-pointer-sign -Wstrict-prototypes -Wmissing-prototypes -O2 -g
 LDLIBS=-lpcre
 
-umpf: umpf.c cond.tab.o lex.o ham.o lists.o lock.o code.o
+umpf: umpf.c cond.tab.o lex.o ham.o lists.o lock.o code.o int.o
        gcc -o $@ $^ $(LDLIBS)
 
 lock.o: lex.o cond.tab.o
@@ -19,6 +19,8 @@ code.o: code.c
 
 lists.o: lists.c
 
+int.o: int.c
+
 cond.tab.c: cond.y
        bison -dvt cond.y
 
diff --git a/code.c b/code.c
index 2cee897198dc45388e25f9e5d4df268732bbc7be..1f47c3da2530ea0b327df34d58a4bc71b75cb34c 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;
@@ -294,7 +291,7 @@ do_arrow(struct tree* t, struct list* where)
                ins.u.arrow.copy = 0;
        switch (t->pt.arrow.right) {
                case K_EMPTY:
-                       ins.opcode = OPC_STORE;
+                       ins.opcode = OPC_DELIVER;
                        break;
                case K_PIPE:
                        ins.opcode = OPC_PIPE;
@@ -434,8 +431,8 @@ print_code(void)
                        case OPC_PIPE:
                                printf("PIPE %d %d\n", p->u.arrow.what, p->u.arrow.copy);
                                break;
-                       case OPC_STORE:
-                               printf("STORE %d %d\n", p->u.arrow.what, p->u.arrow.copy);
+                       case OPC_DELIVER:
+                               printf("DELIVER %d %d\n", p->u.arrow.what, p->u.arrow.copy);
                                break;
                        case OPC_MAIL:
                                printf("MAIL %d %d\n", p->u.arrow.what, p->u.arrow.copy);
diff --git a/int.c b/int.c
index f7fe023b592f5c5538c33d003251a2494e02d86a..69f22852b80d1376f666b69e9420a495fa82b155 100644 (file)
--- a/int.c
+++ b/int.c
@@ -2,6 +2,7 @@
 #include <string.h>
 #include <pcre.h>
 #include <ctype.h>
+#include <limits.h>
 
 #include "cond.tab.h"
 #include "umpf.h"
 #define HASHSIZE 103
 #define MAGIC 19
 
-struct list* 
-new_var_hash(void)
+#define INT_TO_STRING_LEN ((sizeof(int)*4*CHAR_BIT)/10 + 6)
+
+static void
+clear_var(int var)
 {
-       struct list* res;
-       int i;
+       if (var_tab[var])
+               free(var_tab[var]);
+}
 
-       res = xmalloc (HASHSIZE * sizeof(struct list));
-       for (i = 0; i < HASHSIZE; i++)
-               list_init(res + i);
+static void
+set_var(int var, char* value)
+{
+       clear_var(var);
+       var_tab[var] = xstrdup(value);
        
-
-       return res;
 }
 
-static int
-get_bucket_number(char* name)
+static char*
+get_var(int var)
 {
-       unsigned int n = 0;
-       unsigned char* p = name;
-
-        while (*p != '\0'){
-                n = n * MAGIC + toupper(*p++);
-        }
-        n %= HASHSIZE;
-
-        return n;
+       if (var < 0)
+               return const_tab[-var];
+       return var_tab[var];
 }
 
-/* value NULL for finding without modyfiing */
+/* return var struct or NULL if not found */
 static struct variable*
-find_var(char* name, char* value, struct list* hash)
+get_var_struct(char* name, struct list* hash)
 {
        int n;
        struct variable *p;
@@ -48,21 +46,10 @@ find_var(char* name, char* value, struct list* hash)
        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;
-                       }
+               if (!(nocase ? strcasecmp : strcmp)(p->name,name))
                        return p;
-               }
 
-       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;
+       return NULL;
 }
 
 static int 
@@ -83,71 +70,8 @@ regex_cmp(char* s, char* r)
        return res;
 }
 
-void
-print_tree(struct tree* t, int ind)
-{
-       if (!t)
-               return; 
-
-       switch (t->st){
-               case ST_IF:
-                       printf("%*s if\n", ind, "");
-                       print_tree(t->pt.tif.c,ind+1);
-                       printf("%*s then\n", ind, "");
-                       print_tree(t->pt.tif.i,ind+1);
-                       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);
-                       printf("%*s", ind, "");
-                       if (UPPER(t->pt.cond.op) > 0)
-                               putchar(UPPER(t->pt.cond.op));
-                       putchar(LOWER(t->pt.cond.op));
-                       putchar('\n'); 
-                       print_tree(t->pt.cond.right, ind+1);    
-                       break;
-               case ST_BLOCK:
-                       print_tree(t->pt.block.head,ind);
-                       print_tree(t->pt.block.tail,ind);
-                       break;
-               case ST_ASS:
-                       print_tree(t->pt.ass.left, ind+1);
-                       printf("%*s =\n", ind, "");
-                       print_tree(t->pt.ass.right, ind+1);
-                       break;
-               case ST_LEAF:
-                       printf("%*s", ind, "");
-                       switch (t->pt.leaf.type){
-                               case L_VAR:
-                                       putchar('$');
-                               case L_CONST:
-                                       puts(t->pt.leaf.value);
-                                       break;
-                       }
-                       break;
-               case ST_ARROW:
-                       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);
-                       printf("%*s%c\n", ind, "", t->pt.op.op);
-                       print_tree(t->pt.op.right, ind+1);
-                       break;  
-               case ST_EMPTY:
-                       break;  
-
-
-       }
-}
 
 static char*
 xcat(char* left, char* right)
@@ -163,92 +87,26 @@ xcat(char* left, char* 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;
+       struct variable* pv;
+       
 
        LIST_FOREACH(p, headers){
-               pv = find_var(p->name,NULL,hash);
+               pv = get_var_struct(p->name, hash);
+               if (!pv)
+                       continue;
                if (pv->modified){
                        pv->modified = 0;
                        free(p->value);
-                       p->value = xstrdup(pv->value); //FIXME: fold it
+                       p->value = xstrdup(get_var(pv->varcode)); //FIXME: fold it
                }
        }
 
-       /* find new headers */
+       // find new headers 
        for (i = 0; i < HASHSIZE; i++){
                LIST_FOREACH(pv, hash + i){
                        if (isupper(pv->name[0]) && pv->modified){
@@ -256,7 +114,7 @@ modify_headers(struct list* headers, struct list* hash)
 
                                p = xmalloc(sizeof(struct hlist));
                                p->name = xstrdup(pv->name);
-                               p->value = xstrdup(pv->value);
+                               p->value = xstrdup(get_var(pv->varcode));
 
                                list_add_last(headers,&p->car);
                        }
@@ -276,6 +134,7 @@ copy_headers(struct list* orig)
                pn = xmalloc(sizeof(struct hlist));
                pn->name = xstrdup(po->name);
                pn->value = xstrdup(po->value);
+               pn->have_var = 0;
 
                list_add_last(new, &pn->car);
        }
@@ -283,54 +142,182 @@ copy_headers(struct list* orig)
        return new;
 }
 
-static void
-new_action(char* l, char* r, char* s, struct list* hash)
+static struct email* 
+prepare_email(struct list* hash)
 {
-       struct action* a;
+       struct email* em;
 
-       a = xmalloc(sizeof(struct action));
+       em = xmalloc(sizeof(struct email));
 
        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);
+       em->headers = copy_headers(current_headers);
+       em->body_len = current_body->body_len; 
+       em->body = xmalloc(em->body_len);
+       memcpy(em->body, current_body->body, em->body_len);
+
+       return em;
 }
 
-void
-interp(struct tree* t, struct list* hash)
+static void
+do_string_ternary_op(struct code* p)
 {
-       if (!t)
-               return;
+       char* l = get_var(p->u.tpop.l);
+       char* r = get_var(p->u.tpop.r);
+       char* result;
+
+       switch(p->opcode) {
+               case OPC_RE:
+                       result = xmalloc(INT_TO_STRING_LEN);
+                       sprintf(result, "%d", regex_cmp(l, r));
+               case OPC_NRE:
+                       result = xmalloc(INT_TO_STRING_LEN);
+                       sprintf(result, "%d", !regex_cmp(l, r));
+               case OPC_CAT:
+                       result = xcat(l, r);
+               default:
+                       break;
+       };
+
+       set_var(p->u.tpop.res, result); 
+}
+
+static void
+do_num_ternary_op(struct code* p)
+{
+       int l, r, res;
+       char* result = xmalloc(INT_TO_STRING_LEN);
+
+       sscanf(get_var(p->u.tpop.l),"%d", &l);
+       sscanf(get_var(p->u.tpop.r),"%d", &r);
 
-       switch(t->st){
-               case ST_BLOCK:
-                       interp(t->pt.block.head, hash);
-                       interp(t->pt.block.tail, hash);
+       switch(p->opcode) {
+               case OPC_GT:
+                       res = (l > r);
                        break;
-               case ST_ASS:
-                       find_var(t->pt.ass.left->pt.leaf.value, interp_ass_right(t->pt.ass.right, hash), hash);
+               case OPC_LT:
+                       res = (l < r);
                        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);
+               case OPC_LE:
+                       res = (l <= r);
                        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);
+               case OPC_GE:
+                       res = (l >= r);
+                       break;
+               case OPC_EQ:
+                       res = (l == r);
+                       break;
+               case OPC_NEQ:
+                       res = (l != r);
+                       break;
+               case OPC_AND:
+                       res = (l && r);
+                       break;
+               case OPC_OR:
+                       res = (l || r);
+                       break;
+               case OPC_XOR:
+                       res = ((l || r) && !(l && r));
+                       break;
+               case OPC_PLUS:
+                       res = (l + r);
+                       break;
+               case OPC_MINUS:
+                       res = (l - r);
+                       break;
+               case OPC_MUL:
+                       res = (l * r);
+                       break;
+               case OPC_DIV:
+                       res = (l / r);
                        break;
-               case ST_EMPTY:
-                       break;  
                default:
-                       die("interp: got to default");
+                       break;
        }
 
+       sprintf(result, "%d", res);
+       set_var(p->u.tpop.res, result);
+}
+
+static int
+eval_cond(int var)
+{
+       char* val = get_var(var);
+       int v;
+
+       if (! val)
+               return 0;
+       if (! *val)
+               return 0;
+       sscanf(val, "%d", &v);
+
+       return !!v;
+}
+
+void
+interp(struct list* ins)
+{
+       struct code* p;
+       char* result;
+       int v;
+       
+       LIST_FOREACH(p, ins) {
+       switch (p->opcode) {
+               case OPC_SET:
+                       set_var(p->u.set.l, get_var(p->u.set.r));
+                       break;  
+               case OPC_JUMP:
+                       p = p->u.jump.target;
+                       continue;
+                       break;
+               case OPC_JUMP_IF:
+                       if (eval_cond(p->u.jump_if.cond))
+                               p = p->u.jump_if.target;
+                       continue;
+                       break;
+               case OPC_JUMP_UNLESS:
+                       if (!eval_cond(p->u.jump_unless.cond))
+                               p = p->u.jump_unless.target;
+                       continue;
+                       break;
+               case OPC_NOP:
+                       continue;
+                       break;
+               case OPC_GT:
+               case OPC_LT:
+               case OPC_LE:
+               case OPC_GE:
+               case OPC_EQ:
+               case OPC_NEQ:
+               case OPC_AND:
+               case OPC_OR:
+               case OPC_XOR:
+               case OPC_PLUS:
+               case OPC_MINUS:
+               case OPC_MUL:
+               case OPC_DIV:
+                       do_num_ternary_op(p);
+                       break;
+               case OPC_NOT:
+                       result = xmalloc(INT_TO_STRING_LEN);
+                       sscanf(get_var(p->u.tpop.l),"%d", &v);
+                       sprintf(result, "%d", !v);
+                       set_var(p->u.tpop.res, result);
+               case OPC_CAT:
+               case OPC_RE:
+               case OPC_NRE:
+                       do_string_ternary_op(p);
+                       break;
+               case OPC_PIPE:
+                       break;
+               case OPC_MAIL:
+                       break;
+               case OPC_DELIVER:
+                       break;
+               case OPC_CALL_EXT:
+                       break;
+               case OPC_DISCARD:
+                       break;
+       }}
 }
 
 void
@@ -341,7 +328,7 @@ print_vars(struct list* hash)
 
        for (i=0; i<HASHSIZE; i++){
                LIST_FOREACH(p, hash + i)
-                       printf("%s=%s\n",p->name, p->value);
+                       printf("%s=%s\n",p->name, get_var(p->varcode));
        }
 }
 
@@ -378,18 +365,22 @@ void
 save_current_headers(struct list* hash)
 {
        struct hlist* p;
-       struct variable* pv;
        char* u;
+       struct variable* pv;
 
        LIST_FOREACH(p, current_headers){
+               pv = get_var_struct(p->name, hash);
+               if (!pv)
+                       continue;
                u = unfold(p->value);
-               pv = find_var(p->name,u,hash);
+               set_var(pv->varcode, u);
                pv->modified = 0;
+               p->have_var = 1;
        }
 
 }
 
-void
+static void
 get_default_mailbox(char* mb)
 {
        default_mailbox = mb;
diff --git a/umpf.c b/umpf.c
index ab73285948a50ed8abacb53cbdc7bb8f63f34748..78ea955950ac3cf9522727e946f8f02926e9b127 100644 (file)
--- a/umpf.c
+++ b/umpf.c
@@ -39,15 +39,14 @@ main(int argc, char** argv)
        temp_varcode_start = current_varcode;
        compile(input_tree, NULL);
 
-       print_code();
-
-//     var_hash = new_var_hash();
-//     current_headers = make_hlist();
-//     current_body = get_body();
-//     print_headers(current_headers);
-//     save_current_headers(var_hash);
-//     interp(input_tree, var_hash);
-//     print_vars(var_hash);
+//     print_code();
+
+       current_headers = make_hlist();
+       current_body = get_body();
+       print_headers(current_headers);
+       save_current_headers(var_hash);
+       interp(&input_code);
+       print_vars(var_hash);
 
        return 0;
 }
diff --git a/umpf.h b/umpf.h
index 946279ebc8d0a84699ff8c20e84a8a915bfb6176..e4c80333d019d17a3c55d62429e4417e2854a917 100644 (file)
--- a/umpf.h
+++ b/umpf.h
@@ -87,44 +87,11 @@ void read_conf(char* filename);
 int line;
 FILE* conf;
 
-/* int.c */
-struct hlist {
-       struct node car;
-       char* name;
-       char* value;
-};
-
-struct email {
-       struct list* headers;
-       char* body;
-       int body_len;
-};
-
-struct action {
-       char* l;
-       char* r;
-       char* s;
-       struct email e;
-};
-
-/* ham.c */
-char* default_mailbox;
-
-struct list* current_headers;
-struct email* current_body;
-struct list* make_hlist(void);
-void print_headers(struct list* l);
-void do_action(struct action* a);
-struct email* get_body(void);
-
-/* lock.c */
-void save_gids(void);
-void close_mailbox(int fd, char* path, int is_default_mailbox);
-int open_mailbox(char* path, int is_default_mailbox);
-char* cat(char* l, char* r);
-
 /* code.c */
 #define BUFSIZE 4096 
+#define HASHSIZE 103
+#define MAGIC 19
+
 struct code {
        struct node car;
        enum {
@@ -154,7 +121,6 @@ struct code {
                OPC_DIV,
                OPC_PIPE,
                OPC_MAIL,
-               OPC_STORE,
                OPC_DISCARD
        } opcode;
 
@@ -195,7 +161,8 @@ struct code {
 struct variable {
        struct node car;
        char* name;
-       int varcode;    
+       int varcode;
+       int modified;
 };
 
 struct list input_code;
@@ -212,4 +179,40 @@ void compile(struct tree* t, struct list* where);
 int find_var(char* name, struct list* hash);
 int store_const(char* c);
 struct list* new_var_hash(void);
+int get_bucket_number(char* name);
 void print_code(void);
+
+/* int.c */
+struct hlist {
+       struct node car;
+       char* name;
+       char* value;
+       int have_var;
+};
+
+struct email {
+       struct list* headers;
+       char* body;
+       int body_len;
+};
+
+void save_current_headers(struct list* hash);
+void print_vars(struct list* hash);
+void interp(struct list* ins);
+
+/* ham.c */
+char* default_mailbox;
+
+struct list* current_headers;
+struct email* current_body;
+struct list* make_hlist(void);
+void print_headers(struct list* l);
+struct email* get_body(void);
+
+/* lock.c */
+void save_gids(void);
+void close_mailbox(int fd, char* path, int is_default_mailbox);
+int open_mailbox(char* path, int is_default_mailbox);
+char* cat(char* l, char* r);
+
+