#include <ctype.h>
#include "cond.tab.h"
-#include "brum.h"
+#include "umpf.h"
#define OVECCOUNT 3
#define HASHSIZE 103
#define MAGIC 19
-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;
}
unsigned char* p = name;
while (*p != '\0'){
- n = n * MAGIC + *p++;
+ n = n * MAGIC + toupper(*p++);
}
n %= HASHSIZE;
return n;
}
-void
-cap(char* s)
-{
- char* p;
- for(p = s; *p; p++)
- *p = toupper(*p);
-}
-
/* 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;
- name = xstrdup(name);
- if (isupper(*name))
- cap(name);
-
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 (p && value){
- free(p->value);
- p->value = value;
- } else if (p && !value)
- return p;
- else {
- p = xmalloc(sizeof(struct variable));
- p->next = hash[n];
- hash[n] = p;
- p->name = name;
- p->value = (value? value:xstrdup(""));
- }
-
+ 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 res;
}
-char*
-interp_ass_right(struct tree* t, struct variable** hash)
+static char*
+interp_ass_right(struct tree* t, struct list* hash)
{
switch (t->st){
case ST_LEAF:
}
// FIXME: we would like to be able also do things like ($a & $b) == $c
-int
-interp_cond(struct tree* t, struct variable** hash)
+static int
+interp_cond(struct tree* t, struct list* hash)
{
if (t->st != ST_COND)
die("Muhehehechlemst?");
return regex_cmp(left,right);
case CC('!','~'):
return !regex_cmp(left,right);
+ default:
+ die("Brrrchlemst!");
} //TODO: add numbers
} else {
return (left || right) && !(left && right);
case '!':
return !left;
+ default:
+ die("Brrrchlemst!");
}
}
}
-void
-new_action(char* l, char* r, char* s)
+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)
{
- //TODO: modify headers according to variable values
+ 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, struct variable** hash)
+interp(struct tree* t, struct list* hash)
{
if (!t)
return;
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));
+ 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;
}
void
-print_vars(struct variable** hash)
+print_vars(struct list* hash)
{
int i;
struct variable* p;
for (i=0; i<HASHSIZE; i++){
- p = hash[i];
- while(p){
+ LIST_FOREACH(p, hash + i)
printf("%s=%s\n",p->name, p->value);
- p = p->next;
- }
}
}
}
void
-save_current_headers(struct variable** hash)
+save_current_headers(struct list* hash)
{
struct hlist* p;
+ struct variable* pv;
char* u;
- for (p = current_headers;p;p = p->next){
+ LIST_FOREACH(p, current_headers){
u = unfold(p->value);
- find_var(p->name,u,hash);
+ pv = find_var(p->name,u,hash);
+ pv->modified = 0;
}
}
+
+void
+get_default_mailbox(char* mb)
+{
+ default_mailbox = mb;
+}