]> mj.ucw.cz Git - umpf.git/blob - int.c
part of conditions, printing variables
[umpf.git] / int.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <pcre.h>
4
5 #include "cond.tab.h"
6 #include "brum.h"
7
8 #define OVECCOUNT 3
9 #define HASHSIZE 103
10 #define MAGIC 19
11
12 struct variable**
13 new_var_hash(void)
14 {
15         struct variable** res;
16
17         res = xmalloc (HASHSIZE * sizeof(struct variable*));
18         memset(res, 0, sizeof(struct variable*)*HASHSIZE);
19
20         return res;
21 }
22
23 static int
24 get_bucket_number(char* name)
25 {
26         unsigned int n = 0;
27         unsigned char* p = name;
28
29         while (*p != '\0'){
30                 n = n * MAGIC + *p++;
31         }
32         n %= HASHSIZE;
33
34         return n;
35 }
36
37 /* value NULL for finding without modyfiing */
38 static struct variable*
39 find_var(char* name, char* value, struct variable** hash)
40 {
41         int n;
42         struct variable *p;
43
44         n = get_bucket_number(name);
45
46         p = hash[n];
47         while(p && strcmp(p->name,name))
48                 p = p->next;
49
50         if (p && value){
51                 free(p->value);
52                 p->value = value;
53         } else if (p && !value)
54                 return p;
55         else {
56                 p = xmalloc(sizeof(struct variable));
57                 p->next = hash[n];
58                 hash[n] = p;
59                 p->name = xstrdup(name);
60                 p->value = (value? value:xstrdup(""));
61         }
62
63         return p;
64 }
65
66 static int 
67 regex_cmp(char* s, char* r)
68 {
69         pcre *brum;
70         int erroroffset;
71         const char* error;
72         int ovector[OVECCOUNT];
73         
74         brum = pcre_compile(r,0,&error,&erroroffset,NULL);
75         if (!brum)
76                 return -1;
77         
78         int res = pcre_exec(brum,NULL,s,strlen(s),0,0,ovector,OVECCOUNT);
79         pcre_free(brum);
80
81         return res;
82 }
83
84 void
85 print_tree(struct tree* t, int ind)
86 {
87         if (!t)
88                 return; 
89
90         switch (t->st){
91                 case ST_IF:
92                         printf("%*s if\n", ind, "");
93                         print_tree(t->pt.tif.c,ind+1);
94                         printf("%*s then\n", ind, "");
95                         print_tree(t->pt.tif.i,ind+1);
96                         printf("%*s else\n", ind, "");
97                         print_tree(t->pt.tif.e,ind+1);
98                         break;
99                 case ST_COND:
100 #define UPPER(a) ((a) >> 8)
101 #define LOWER(a) ((a) & 0xFF)
102                         print_tree(t->pt.cond.left, ind+1);
103                         printf("%*s", ind, "");
104                         if (UPPER(t->pt.cond.op) > 0)
105                                 putchar(UPPER(t->pt.cond.op));
106                         putchar(LOWER(t->pt.cond.op));
107                         putchar('\n'); 
108                         print_tree(t->pt.cond.right, ind+1);    
109                         break;
110                 case ST_BLOCK:
111                         print_tree(t->pt.block.head,ind);
112                         print_tree(t->pt.block.tail,ind);
113                         break;
114                 case ST_ASS:
115                         print_tree(t->pt.ass.left, ind+1);
116                         printf("%*s =\n", ind, "");
117                         print_tree(t->pt.ass.right, ind+1);
118                         break;
119                 case ST_LEAF:
120                         printf("%*s", ind, "");
121                         switch (t->pt.leaf.type){
122                                 case L_VAR:
123                                         putchar('$');
124                                 case L_CONST:
125                                         puts(t->pt.leaf.value);
126                                         break;
127                         }
128                         break;
129                 case ST_ARROW:
130                         if (t->pt.arrow.kw_left)
131                                 printf("%*s%s\n", ind+1, "", t->pt.arrow.kw_left);
132                         printf("%*s ->\n", ind, "");
133                         if (t->pt.arrow.kw_right)
134                                 printf("%*s%s\n", ind+1, "", t->pt.arrow.kw_right);
135                         print_tree(t->pt.arrow.s,ind+1);
136                         break;
137                 case ST_OP:
138                         print_tree(t->pt.op.left, ind+1);
139                         printf("%*s%c\n", ind, "", t->pt.op.op);
140                         print_tree(t->pt.op.right, ind+1);
141                         break;  
142                 case ST_EMPTY:
143                         break;  
144
145
146         }
147 }
148
149 static char*
150 xcat(char* left, char* right)
151 {
152         char* res = xmalloc(strlen(left) + strlen(right) + 1);
153
154         strcpy(res,left);
155         strcat(left,right);
156
157         free(left);
158         free(right);    
159
160         return res;
161 }
162
163 char*
164 interp_ass_right(struct tree* t, struct variable** hash)
165 {
166         switch (t->st){
167                 case ST_LEAF:
168                         if (t->pt.leaf.type == L_VAR)
169                                 return xstrdup(find_var(t->pt.leaf.value,NULL,hash)->value);
170                         else 
171                                 return xstrdup(t->pt.leaf.value);
172                 case ST_OP:
173                         switch (t->pt.op.op){
174                                 case '.':
175                                         return xcat(interp_ass_right(t->pt.op.left, hash),interp_ass_right(t->pt.op.right, hash));
176                         }       
177                 case ST_EMPTY:
178                         return xstrdup("");
179                 default:
180                         die("interp_ass_right: got to default");        
181                 }
182 }       
183
184 int
185 interp_cond(struct tree* t, struct variable** hash)
186 {
187         if (t->st != ST_COND)
188                 die("Muhehehechlemst?");
189
190         if (t->pt.cond.type == OP_REL){
191                 if (t->pt.cond.left->st != ST_LEAF || t->pt.cond.right->st != ST_LEAF)
192         die("Chlemst");
193
194                 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);
195         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);
196                 switch (t->pt.cond.op){
197                         case CC('=','='):
198                                 return !strcmp(left,right);
199                         case CC('!','='):
200                                 return strcmp(left,right);
201                         case CC('~','~'):
202                                 return regex_cmp(left,right);
203                         case CC('!','~'):
204                                 return !regex_cmp(left,right);
205                 }
206
207         } else {
208                 int left = interp_cond(t->pt.cond.left, hash);
209                 int right;
210
211                 if (t->pt.cond.op != '!')
212                         right = interp_cond(t->pt.cond.right, hash);
213
214                 switch (t->pt.cond.op){
215                         case '&':
216                                 return left && right;
217                         case '|':
218                                 return left || right;
219                         case '^':
220                                 return (left || right) && !(left && right);
221                         case '!':
222                                 return !left;
223                 }
224         }
225 }
226
227 void
228 interp(struct tree* t, struct variable** hash)
229 {
230         if (!t)
231                 return;
232
233         switch(t->st){
234                 case ST_BLOCK:
235                         interp(t->pt.block.head, hash);
236                         interp(t->pt.block.tail, hash);
237                         break;
238                 case ST_ASS:
239                         find_var(t->pt.ass.left->pt.leaf.value, interp_ass_right(t->pt.ass.right, hash), hash);
240                         break;
241                 case ST_IF:
242                         if (interp_cond(t->pt.tif.c, hash))
243                                 interp(t->pt.tif.i, hash);
244                         else 
245                                 interp(t->pt.tif.e, hash);
246                         break;
247                 case ST_EMPTY:
248                         break;  
249                 default:
250                         die("interp: got to default");
251         }
252
253 }
254
255 void
256 print_vars(struct variable** hash)
257 {
258         int i;
259         struct variable* p;
260
261         for (i=0; i<HASHSIZE; i++){
262                 p = hash[i];
263                 while(p){
264                         printf("%s=%s\n",p->name, p->value);
265                         p = p->next;
266                 }               
267         }
268 }