struct {
int op;
+ enum {
+ OP_REL,
+ OP_BOOL
+ } type;
struct tree* left;
struct tree* right;
} cond; /* binary operator */
struct tree* input_tree;
/* lex.c */
+#define CC(a,b) ((a<<8)|b)
void* xmalloc(size_t size);
char* xstrdup(char* s);
void __attribute__ ((noreturn)) die(char* msg, ...);
void print_tree(struct tree* t, int ind);
void interp(struct tree* t, struct variable** hash);
struct variable** new_var_hash(void);
+void print_vars(struct variable** hash);
cond: '!' cond {
$$ = tree_malloc(ST_COND);
$$->pt.cond.left = $2;
- $$->pt.cond.right = tree_malloc(ST_EMPTY);
+ $$->pt.cond.right = NULL;
$$->pt.cond.op = $1;
-
+ $$->pt.cond.type = OP_BOOL;
}
| cond '|' cond {
$$ = tree_malloc(ST_COND);
$$->pt.cond.left = $1;
$$->pt.cond.right = $3;
$$->pt.cond.op = $2;
-
+ $$->pt.cond.type = OP_BOOL;
}
| cond '&' cond {
$$ = tree_malloc(ST_COND);
$$->pt.cond.left = $1;
$$->pt.cond.right = $3;
$$->pt.cond.op = $2;
-
+ $$->pt.cond.type = OP_BOOL;
}
| cond '^' cond {
$$ = tree_malloc(ST_COND);
$$->pt.cond.left = $1;
$$->pt.cond.right = $3;
$$->pt.cond.op = $2;
+ $$->pt.cond.type = OP_BOOL;
}
| '(' cond ')' { $$ = $2; }
$$->pt.cond.left = $1;
$$->pt.cond.right = $3;
$$->pt.cond.op = $2;
+ $$->pt.cond.type = OP_REL;
}
;
if (p && value){
free(p->value);
p->value = value;
- } else {
+ } else if (p && !value)
+ return p;
+ else {
p = xmalloc(sizeof(struct variable));
p->next = hash[n];
hash[n] = p;
}
}
+int
+interp_cond(struct tree* t, struct variable** 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);
+ }
+
+ } 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;
+ }
+ }
+}
+
void
interp(struct tree* t, struct variable** hash)
{
case ST_BLOCK:
interp(t->pt.block.head, hash);
interp(t->pt.block.tail, hash);
- break;
+ break;
case ST_ASS:
find_var(t->pt.ass.left->pt.leaf.value, interp_ass_right(t->pt.ass.right, hash), hash);
- break;
+ 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);
+ break;
+ case ST_EMPTY:
+ break;
default:
die("interp: got to default");
}
-};
+}
+
+void
+print_vars(struct variable** hash)
+{
+ int i;
+ struct variable* p;
+
+ for (i=0; i<HASHSIZE; i++){
+ p = hash[i];
+ while(p){
+ printf("%s=%s\n",p->name, p->value);
+ p = p->next;
+ }
+ }
+}