BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file BPredicate.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29  
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33  
34 #include <misc/debug.h>
35 #include <misc/offset.h>
36 #include <misc/balloc.h>
37 #include <misc/compare.h>
38 #include <predicate/BPredicate_internal.h>
39 #include <predicate/BPredicate_parser.h>
40 #include <predicate/LexMemoryBufferInput.h>
41 #include <base/BLog.h>
42  
43 #include <predicate/BPredicate.h>
44  
45 #include <generated/blog_channel_BPredicate.h>
46  
47 static int eval_predicate_node (BPredicate *p, struct predicate_node *root);
48  
49 void yyerror (YYLTYPE *yylloc, yyscan_t scanner, struct predicate_node **result, char *str)
50 {
51 }
52  
53 static int string_comparator (void *user, char *s1, char *s2)
54 {
55 int cmp = strcmp(s1, s2);
56 return B_COMPARE(cmp, 0);
57 }
58  
59 static int eval_function (BPredicate *p, struct predicate_node *root)
60 {
61 ASSERT(root->type == NODE_FUNCTION)
62  
63 // lookup function by name
64 ASSERT(root->function.name)
65 BAVLNode *tree_node;
66 if (!(tree_node = BAVL_LookupExact(&p->functions_tree, root->function.name))) {
67 BLog(BLOG_WARNING, "unknown function");
68 return 0;
69 }
70 BPredicateFunction *func = UPPER_OBJECT(tree_node, BPredicateFunction, tree_node);
71  
72 // evaluate arguments
73 struct arguments_node *arg = root->function.args;
74 void *args[PREDICATE_MAX_ARGS];
75 for (int i = 0; i < func->num_args; i++) {
76 if (!arg) {
77 BLog(BLOG_WARNING, "not enough arguments");
78 return 0;
79 }
80 switch (func->args[i]) {
81 case PREDICATE_TYPE_BOOL:
82 if (arg->arg.type != ARGUMENT_PREDICATE) {
83 BLog(BLOG_WARNING, "expecting predicate argument");
84 return 0;
85 }
86 if (!eval_predicate_node(p, arg->arg.predicate)) {
87 return 0;
88 }
89 args[i] = &arg->arg.predicate->eval_value;
90 break;
91 case PREDICATE_TYPE_STRING:
92 if (arg->arg.type != ARGUMENT_STRING) {
93 BLog(BLOG_WARNING, "expecting string argument");
94 return 0;
95 }
96 args[i] = arg->arg.string;
97 break;
98 default:
99 ASSERT(0);
100 }
101 arg = arg->next;
102 }
103  
104 if (arg) {
105 BLog(BLOG_WARNING, "too many arguments");
106 return 0;
107 }
108  
109 // call callback
110 #ifndef NDEBUG
111 p->in_function = 1;
112 #endif
113 int res = func->callback(func->user, args);
114 #ifndef NDEBUG
115 p->in_function = 0;
116 #endif
117 if (res != 0 && res != 1) {
118 BLog(BLOG_WARNING, "callback returned non-boolean");
119 return 0;
120 }
121  
122 root->eval_value = res;
123 return 1;
124 }
125  
126 int eval_predicate_node (BPredicate *p, struct predicate_node *root)
127 {
128 ASSERT(root)
129  
130 switch (root->type) {
131 case NODE_CONSTANT:
132 root->eval_value = root->constant.val;
133 return 1;
134 case NODE_NEG:
135 if (!eval_predicate_node(p, root->neg.op)) {
136 return 0;
137 }
138 root->eval_value = !root->neg.op->eval_value;
139 return 1;
140 case NODE_CONJUNCT:
141 if (!eval_predicate_node(p, root->conjunct.op1)) {
142 return 0;
143 }
144 if (!root->conjunct.op1->eval_value) {
145 root->eval_value = 0;
146 return 1;
147 }
148 if (!eval_predicate_node(p, root->conjunct.op2)) {
149 return 0;
150 }
151 if (!root->conjunct.op2->eval_value) {
152 root->eval_value = 0;
153 return 1;
154 }
155 root->eval_value = 1;
156 return 1;
157 case NODE_DISJUNCT:
158 if (!eval_predicate_node(p, root->disjunct.op1)) {
159 return 0;
160 }
161 if (root->disjunct.op1->eval_value) {
162 root->eval_value = 1;
163 return 1;
164 }
165 if (!eval_predicate_node(p, root->disjunct.op2)) {
166 return 0;
167 }
168 if (root->disjunct.op2->eval_value) {
169 root->eval_value = 1;
170 return 1;
171 }
172 root->eval_value = 0;
173 return 1;
174 case NODE_FUNCTION:
175 return eval_function(p, root);
176 default:
177 ASSERT(0)
178 return 0;
179 }
180 }
181  
182 int BPredicate_Init (BPredicate *p, char *str)
183 {
184 // initialize input buffer object
185 LexMemoryBufferInput input;
186 LexMemoryBufferInput_Init(&input, str, strlen(str));
187  
188 // initialize lexical analyzer
189 yyscan_t scanner;
190 yylex_init_extra(&input, &scanner);
191  
192 // parse
193 struct predicate_node *root = NULL;
194 int result = yyparse(scanner, &root);
195  
196 // free lexical analyzer
197 yylex_destroy(scanner);
198  
199 // check for errors
200 if (LexMemoryBufferInput_HasError(&input) || result != 0 || !root) {
201 if (root) {
202 free_predicate_node(root);
203 }
204 return 0;
205 }
206  
207 // init tree
208 p->root = root;
209  
210 // init functions tree
211 BAVL_Init(&p->functions_tree, OFFSET_DIFF(BPredicateFunction, name, tree_node), (BAVL_comparator)string_comparator, NULL);
212  
213 // init debuggind
214 #ifndef NDEBUG
215 p->in_function = 0;
216 #endif
217  
218 // init debug object
219 DebugObject_Init(&p->d_obj);
220  
221 return 1;
222 }
223  
224 void BPredicate_Free (BPredicate *p)
225 {
226 ASSERT(BAVL_IsEmpty(&p->functions_tree))
227 ASSERT(!p->in_function)
228  
229 // free debug object
230 DebugObject_Free(&p->d_obj);
231  
232 // free tree
233 free_predicate_node((struct predicate_node *)p->root);
234 }
235  
236 int BPredicate_Eval (BPredicate *p)
237 {
238 ASSERT(!p->in_function)
239  
240 if (!eval_predicate_node(p, (struct predicate_node *)p->root)) {
241 return -1;
242 }
243  
244 return ((struct predicate_node *)p->root)->eval_value;
245 }
246  
247 void BPredicateFunction_Init (BPredicateFunction *o, BPredicate *p, char *name, int *args, int num_args, BPredicate_callback callback, void *user)
248 {
249 ASSERT(strlen(name) <= PREDICATE_MAX_NAME)
250 ASSERT(!BAVL_LookupExact(&p->functions_tree, name))
251 ASSERT(num_args >= 0)
252 ASSERT(num_args <= PREDICATE_MAX_ARGS)
253 for (int i = 0; i < num_args; i++) {
254 ASSERT(args[i] == PREDICATE_TYPE_BOOL || args[i] == PREDICATE_TYPE_STRING)
255 }
256 ASSERT(!p->in_function)
257  
258 // init arguments
259 o->p = p;
260 strcpy(o->name, name);
261 memcpy(o->args, args, num_args * sizeof(int));
262 o->num_args = num_args;
263 o->callback = callback;
264 o->user = user;
265  
266 // add to tree
267 ASSERT_EXECUTE(BAVL_Insert(&p->functions_tree, &o->tree_node, NULL))
268  
269 // init debug object
270 DebugObject_Init(&o->d_obj);
271 }
272  
273 void BPredicateFunction_Free (BPredicateFunction *o)
274 {
275 ASSERT(!o->p->in_function)
276  
277 BPredicate *p = o->p;
278  
279 // free debug object
280 DebugObject_Free(&o->d_obj);
281  
282 // remove from tree
283 BAVL_Remove(&p->functions_tree, &o->tree_node);
284 }