BPredicate.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /**
  2. * @file BPredicate.c
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * This file is part of BadVPN.
  8. *
  9. * BadVPN is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2
  11. * as published by the Free Software Foundation.
  12. *
  13. * BadVPN is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. */
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <misc/debug.h>
  26. #include <misc/offset.h>
  27. #include <misc/balloc.h>
  28. #include <predicate/BPredicate_internal.h>
  29. #include <predicate/BPredicate_parser.h>
  30. #include <predicate/LexMemoryBufferInput.h>
  31. #include <base/BLog.h>
  32. #include <predicate/BPredicate.h>
  33. #include <generated/blog_channel_BPredicate.h>
  34. static int eval_predicate_node (BPredicate *p, struct predicate_node *root);
  35. void yyerror (YYLTYPE *yylloc, yyscan_t scanner, struct predicate_node **result, char *str)
  36. {
  37. }
  38. static int string_comparator (void *user, char *s1, char *s2)
  39. {
  40. int cmp = strcmp(s1, s2);
  41. if (cmp < 0) {
  42. return -1;
  43. }
  44. if (cmp > 0) {
  45. return 1;
  46. }
  47. return 0;
  48. }
  49. static int eval_function (BPredicate *p, struct predicate_node *root)
  50. {
  51. ASSERT(root->type == NODE_FUNCTION)
  52. // lookup function by name
  53. ASSERT(root->function.name)
  54. BAVLNode *tree_node;
  55. if (!(tree_node = BAVL_LookupExact(&p->functions_tree, root->function.name))) {
  56. BLog(BLOG_WARNING, "unknown function");
  57. return 0;
  58. }
  59. BPredicateFunction *func = UPPER_OBJECT(tree_node, BPredicateFunction, tree_node);
  60. // evaluate arguments
  61. struct arguments_node *arg = root->function.args;
  62. void *args[PREDICATE_MAX_ARGS];
  63. for (int i = 0; i < func->num_args; i++) {
  64. if (!arg) {
  65. BLog(BLOG_WARNING, "not enough arguments");
  66. return 0;
  67. }
  68. switch (func->args[i]) {
  69. case PREDICATE_TYPE_BOOL:
  70. if (arg->arg.type != ARGUMENT_PREDICATE) {
  71. BLog(BLOG_WARNING, "expecting predicate argument");
  72. return 0;
  73. }
  74. if (!eval_predicate_node(p, arg->arg.predicate)) {
  75. return 0;
  76. }
  77. args[i] = &arg->arg.predicate->eval_value;
  78. break;
  79. case PREDICATE_TYPE_STRING:
  80. if (arg->arg.type != ARGUMENT_STRING) {
  81. BLog(BLOG_WARNING, "expecting string argument");
  82. return 0;
  83. }
  84. args[i] = arg->arg.string;
  85. break;
  86. default:
  87. ASSERT(0);
  88. }
  89. arg = arg->next;
  90. }
  91. if (arg) {
  92. BLog(BLOG_WARNING, "too many arguments");
  93. return 0;
  94. }
  95. // call callback
  96. #ifndef NDEBUG
  97. p->in_function = 1;
  98. #endif
  99. int res = func->callback(func->user, args);
  100. #ifndef NDEBUG
  101. p->in_function = 0;
  102. #endif
  103. if (res != 0 && res != 1) {
  104. BLog(BLOG_WARNING, "callback returned non-boolean");
  105. return 0;
  106. }
  107. root->eval_value = res;
  108. return 1;
  109. }
  110. int eval_predicate_node (BPredicate *p, struct predicate_node *root)
  111. {
  112. ASSERT(root)
  113. switch (root->type) {
  114. case NODE_CONSTANT:
  115. root->eval_value = root->constant.val;
  116. return 1;
  117. case NODE_NEG:
  118. if (!eval_predicate_node(p, root->neg.op)) {
  119. return 0;
  120. }
  121. root->eval_value = !root->neg.op->eval_value;
  122. return 1;
  123. case NODE_CONJUNCT:
  124. if (!eval_predicate_node(p, root->conjunct.op1)) {
  125. return 0;
  126. }
  127. if (!root->conjunct.op1->eval_value) {
  128. root->eval_value = 0;
  129. return 1;
  130. }
  131. if (!eval_predicate_node(p, root->conjunct.op2)) {
  132. return 0;
  133. }
  134. if (!root->conjunct.op2->eval_value) {
  135. root->eval_value = 0;
  136. return 1;
  137. }
  138. root->eval_value = 1;
  139. return 1;
  140. case NODE_DISJUNCT:
  141. if (!eval_predicate_node(p, root->disjunct.op1)) {
  142. return 0;
  143. }
  144. if (root->disjunct.op1->eval_value) {
  145. root->eval_value = 1;
  146. return 1;
  147. }
  148. if (!eval_predicate_node(p, root->disjunct.op2)) {
  149. return 0;
  150. }
  151. if (root->disjunct.op2->eval_value) {
  152. root->eval_value = 1;
  153. return 1;
  154. }
  155. root->eval_value = 0;
  156. return 1;
  157. case NODE_FUNCTION:
  158. return eval_function(p, root);
  159. default:
  160. ASSERT(0)
  161. return 0;
  162. }
  163. }
  164. int BPredicate_Init (BPredicate *p, char *str)
  165. {
  166. // initialize input buffer object
  167. LexMemoryBufferInput input;
  168. LexMemoryBufferInput_Init(&input, str, strlen(str));
  169. // initialize lexical analyzer
  170. yyscan_t scanner;
  171. yylex_init_extra(&input, &scanner);
  172. // parse
  173. struct predicate_node *root = NULL;
  174. int result = yyparse(scanner, &root);
  175. // free lexical analyzer
  176. yylex_destroy(scanner);
  177. // check for errors
  178. if (LexMemoryBufferInput_HasError(&input) || result != 0 || !root) {
  179. if (root) {
  180. free_predicate_node(root);
  181. }
  182. return 0;
  183. }
  184. // init tree
  185. p->root = root;
  186. // init functions tree
  187. BAVL_Init(&p->functions_tree, OFFSET_DIFF(BPredicateFunction, name, tree_node), (BAVL_comparator)string_comparator, NULL);
  188. // init debuggind
  189. #ifndef NDEBUG
  190. p->in_function = 0;
  191. #endif
  192. // init debug object
  193. DebugObject_Init(&p->d_obj);
  194. return 1;
  195. }
  196. void BPredicate_Free (BPredicate *p)
  197. {
  198. ASSERT(BAVL_IsEmpty(&p->functions_tree))
  199. ASSERT(!p->in_function)
  200. // free debug object
  201. DebugObject_Free(&p->d_obj);
  202. // free tree
  203. free_predicate_node(p->root);
  204. }
  205. int BPredicate_Eval (BPredicate *p)
  206. {
  207. ASSERT(!p->in_function)
  208. if (!eval_predicate_node(p, p->root)) {
  209. return -1;
  210. }
  211. return ((struct predicate_node *)p->root)->eval_value;
  212. }
  213. void BPredicateFunction_Init (BPredicateFunction *o, BPredicate *p, char *name, int *args, int num_args, BPredicate_callback callback, void *user)
  214. {
  215. ASSERT(strlen(name) <= PREDICATE_MAX_NAME)
  216. ASSERT(!BAVL_LookupExact(&p->functions_tree, name))
  217. ASSERT(num_args >= 0)
  218. ASSERT(num_args <= PREDICATE_MAX_ARGS)
  219. for (int i = 0; i < num_args; i++) {
  220. ASSERT(args[i] == PREDICATE_TYPE_BOOL || args[i] == PREDICATE_TYPE_STRING)
  221. }
  222. ASSERT(!p->in_function)
  223. // init arguments
  224. o->p = p;
  225. strcpy(o->name, name);
  226. memcpy(o->args, args, num_args * sizeof(int));
  227. o->num_args = num_args;
  228. o->callback = callback;
  229. o->user = user;
  230. // add to tree
  231. ASSERT_EXECUTE(BAVL_Insert(&p->functions_tree, &o->tree_node, NULL))
  232. // init debug object
  233. DebugObject_Init(&o->d_obj);
  234. }
  235. void BPredicateFunction_Free (BPredicateFunction *o)
  236. {
  237. ASSERT(!o->p->in_function)
  238. BPredicate *p = o->p;
  239. // free debug object
  240. DebugObject_Free(&o->d_obj);
  241. // remove from tree
  242. BAVL_Remove(&p->functions_tree, &o->tree_node);
  243. }