From: Anicka Bernathova Date: Thu, 16 Jul 2009 17:21:59 +0000 (+0200) Subject: started interpreting X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=90f4aa7cc8e71575822beeb5e49ac38c0c522343;p=umpf.git started interpreting --- diff --git a/Makefile b/Makefile index 86f9523..6131357 100644 --- 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 2cee897..1f47c3d 100644 --- 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 f7fe023..69f2285 100644 --- a/int.c +++ b/int.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "cond.tab.h" #include "umpf.h" @@ -10,37 +11,34 @@ #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; iname, 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 ab73285..78ea955 100644 --- 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 946279e..e4c8033 100644 --- 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); + +