BPredicate.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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 <predicate/BPredicate_internal.h>
  28. #include <predicate/BPredicate_parser.h>
  29. #include <predicate/LexMemoryBufferInput.h>
  30. #include <system/BLog.h>
  31. #include <predicate/BPredicate.h>
  32. #include <generated/blog_channel_BPredicate.h>
  33. static int eval_predicate_node (BPredicate *p, struct predicate_node *root);
  34. void yyerror (YYLTYPE *yylloc, yyscan_t scanner, struct predicate_node **result, char *str)
  35. {
  36. }
  37. static int string_comparator (void *user, char *s1, char *s2)
  38. {
  39. int cmp = strcmp(s1, s2);
  40. if (cmp < 0) {
  41. return -1;
  42. }
  43. if (cmp > 0) {
  44. return 1;
  45. }
  46. return 0;
  47. }
  48. static int eval_function (BPredicate *p, struct predicate_node *root)
  49. {
  50. ASSERT(root->type == NODE_FUNCTION)
  51. // lookup function by name
  52. ASSERT(root->function.name)
  53. BAVLNode *tree_node;
  54. if (!(tree_node = BAVL_LookupExact(&p->functions_tree, root->function.name))) {
  55. BLog(BLOG_WARNING, "unknown function");
  56. return 0;
  57. }
  58. BPredicateFunction *func = UPPER_OBJECT(tree_node, BPredicateFunction, tree_node);
  59. // evaluate arguments
  60. struct arguments_node *arg = root->function.args;
  61. void *args[func->num_args];
  62. for (int i = 0; i < func->num_args; i++) {
  63. if (!arg) {
  64. BLog(BLOG_WARNING, "not enough arguments");
  65. return 0;
  66. }
  67. switch (func->args[i]) {
  68. case PREDICATE_TYPE_BOOL:
  69. if (arg->arg.type != ARGUMENT_PREDICATE) {
  70. BLog(BLOG_WARNING, "expecting predicate argument");
  71. return 0;
  72. }
  73. if (!eval_predicate_node(p, arg->arg.predicate)) {
  74. return 0;
  75. }
  76. args[i] = &arg->arg.predicate->eval_value;
  77. break;
  78. case PREDICATE_TYPE_STRING:
  79. if (arg->arg.type != ARGUMENT_STRING) {
  80. BLog(BLOG_WARNING, "expecting string argument");
  81. return 0;
  82. }
  83. args[i] = arg->arg.string;
  84. break;
  85. default:
  86. ASSERT(0);
  87. }
  88. arg = arg->next;
  89. }
  90. if (arg) {
  91. BLog(BLOG_WARNING, "too many arguments");
  92. return 0;
  93. }
  94. // call callback
  95. #ifndef NDEBUG
  96. p->in_function = 1;
  97. #endif
  98. int res = func->callback(func->user, args);
  99. #ifndef NDEBUG
  100. p->in_function = 0;
  101. #endif
  102. if (res != 0 && res != 1) {
  103. BLog(BLOG_WARNING, "callback returned non-boolean");
  104. return 0;
  105. }
  106. root->eval_value = res;
  107. return 1;
  108. }
  109. int eval_predicate_node (BPredicate *p, struct predicate_node *root)
  110. {
  111. ASSERT(root)
  112. switch (root->type) {
  113. case NODE_CONSTANT:
  114. root->eval_value = root->constant.val;
  115. return 1;
  116. case NODE_NEG:
  117. if (!eval_predicate_node(p, root->neg.op)) {
  118. return 0;
  119. }
  120. root->eval_value = !root->neg.op->eval_value;
  121. return 1;
  122. case NODE_CONJUNCT:
  123. if (!eval_predicate_node(p, root->conjunct.op1)) {
  124. return 0;
  125. }
  126. if (!root->conjunct.op1->eval_value) {
  127. root->eval_value = 0;
  128. return 1;
  129. }
  130. if (!eval_predicate_node(p, root->conjunct.op2)) {
  131. return 0;
  132. }
  133. if (!root->conjunct.op2->eval_value) {
  134. root->eval_value = 0;
  135. return 1;
  136. }
  137. root->eval_value = 1;
  138. return 1;
  139. case NODE_DISJUNCT:
  140. if (!eval_predicate_node(p, root->disjunct.op1)) {
  141. return 0;
  142. }
  143. if (root->disjunct.op1->eval_value) {
  144. root->eval_value = 1;
  145. return 1;
  146. }
  147. if (!eval_predicate_node(p, root->disjunct.op2)) {
  148. return 0;
  149. }
  150. if (root->disjunct.op2->eval_value) {
  151. root->eval_value = 1;
  152. return 1;
  153. }
  154. root->eval_value = 0;
  155. return 1;
  156. case NODE_FUNCTION:
  157. return eval_function(p, root);
  158. default:
  159. ASSERT(0)
  160. return 0;
  161. }
  162. }
  163. int BPredicate_Init (BPredicate *p, char *str)
  164. {
  165. // initialize input buffer object
  166. LexMemoryBufferInput input;
  167. LexMemoryBufferInput_Init(&input, str, strlen(str));
  168. // initialize lexical analyzer
  169. yyscan_t scanner;
  170. yylex_init_extra(&input, &scanner);
  171. // parse
  172. struct predicate_node *root = NULL;
  173. int result = yyparse(scanner, &root);
  174. // free lexical analyzer
  175. yylex_destroy(scanner);
  176. // check for errors
  177. if (LexMemoryBufferInput_HasError(&input) || result != 0 || !root) {
  178. if (root) {
  179. free_predicate_node(root);
  180. }
  181. return 0;
  182. }
  183. // init tree
  184. p->root = root;
  185. // init functions tree
  186. BAVL_Init(&p->functions_tree, OFFSET_DIFF(BPredicateFunction, name, tree_node), (BAVL_comparator)string_comparator, NULL);
  187. // init debuggind
  188. #ifndef NDEBUG
  189. p->in_function = 0;
  190. #endif
  191. // init debug object
  192. DebugObject_Init(&p->d_obj);
  193. return 1;
  194. }
  195. void BPredicate_Free (BPredicate *p)
  196. {
  197. ASSERT(BAVL_IsEmpty(&p->functions_tree))
  198. ASSERT(!p->in_function)
  199. // free debug object
  200. DebugObject_Free(&p->d_obj);
  201. // free tree
  202. free_predicate_node(p->root);
  203. }
  204. int BPredicate_Eval (BPredicate *p)
  205. {
  206. ASSERT(!p->in_function)
  207. if (!eval_predicate_node(p, p->root)) {
  208. return -1;
  209. }
  210. return ((struct predicate_node *)p->root)->eval_value;
  211. }
  212. void BPredicateFunction_Init (BPredicateFunction *o, BPredicate *p, char *name, int *args, int num_args, BPredicate_callback callback, void *user)
  213. {
  214. ASSERT(strlen(name) <= PREDICATE_MAX_NAME)
  215. ASSERT(!BAVL_LookupExact(&p->functions_tree, name))
  216. ASSERT(num_args >= 0)
  217. ASSERT(num_args <= PREDICATE_MAX_ARGS)
  218. for (int i = 0; i < num_args; i++) {
  219. ASSERT(args[i] == PREDICATE_TYPE_BOOL || args[i] == PREDICATE_TYPE_STRING)
  220. }
  221. ASSERT(!p->in_function)
  222. // init arguments
  223. o->p = p;
  224. strcpy(o->name, name);
  225. memcpy(o->args, args, num_args * sizeof(int));
  226. o->num_args = num_args;
  227. o->callback = callback;
  228. o->user = user;
  229. // add to tree
  230. ASSERT_EXECUTE(BAVL_Insert(&p->functions_tree, &o->tree_node, NULL))
  231. // init debug object
  232. DebugObject_Init(&o->d_obj);
  233. }
  234. void BPredicateFunction_Free (BPredicateFunction *o)
  235. {
  236. ASSERT(!o->p->in_function)
  237. BPredicate *p = o->p;
  238. // free debug object
  239. DebugObject_Free(&o->d_obj);
  240. // remove from tree
  241. BAVL_Remove(&p->functions_tree, &o->tree_node);
  242. }