aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2016-03-17 14:13:45 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2016-03-17 14:13:45 +0000
commitfb236b262fab5adb864b2766910a80590c12611a (patch)
tree50b9a28dd9b79402cc6937b488229391b3b11674
parent2020bd22fff005ac5ba32dda3b4f848f3027640c (diff)
downloadrspamd-fb236b262fab5adb864b2766910a80590c12611a.tar.gz
rspamd-fb236b262fab5adb864b2766910a80590c12611a.zip
[Feature] Save operation node for expressions atoms
-rw-r--r--src/libutil/expression.c51
-rw-r--r--src/libutil/expression.h29
2 files changed, 62 insertions, 18 deletions
diff --git a/src/libutil/expression.c b/src/libutil/expression.c
index 2bbc5fa3b..782ad2371 100644
--- a/src/libutil/expression.c
+++ b/src/libutil/expression.c
@@ -27,21 +27,6 @@
#define MIN_RESORT_EVALS 50
#define MAX_RESORT_EVALS 150
-enum rspamd_expression_op {
- OP_INVALID = 0,
- OP_PLUS, /* || or + */
- OP_MULT, /* && or * */
- OP_OR, /* || or | */
- OP_AND, /* && or & */
- OP_NOT, /* ! */
- OP_LT, /* < */
- OP_GT, /* > */
- OP_LE, /* <= */
- OP_GE, /* >= */
- OP_OBRACE, /* ( */
- OP_CBRACE /* ) */
-};
-
enum rspamd_expression_elt_type {
ELT_OP = 0,
ELT_ATOM,
@@ -372,12 +357,19 @@ rspamd_ast_add_node (GPtrArray *operands, struct rspamd_expression_elt *op,
/* Unary operator */
res = g_node_new (op);
a1 = rspamd_expr_stack_elt_pop (operands);
- g_node_append (res, a1);
+
if (a1 == NULL) {
g_set_error (err, rspamd_expr_quark(), EINVAL, "no operand to "
"unary '%s' operation", rspamd_expr_op_to_str (op->p.op));
return FALSE;
}
+
+ g_node_append (res, a1);
+ test_elt = a1->data;
+
+ if (test_elt->type == ELT_ATOM) {
+ test_elt->p.atom->parent = res;
+ }
}
else {
/* For binary operators we might want to examine chains */
@@ -404,6 +396,7 @@ rspamd_ast_add_node (GPtrArray *operands, struct rspamd_expression_elt *op,
rspamd_expr_stack_elt_push (operands, a1);
return TRUE;
}
+
/* Now test a2 */
test = a2;
test_elt = test->data;
@@ -419,6 +412,16 @@ rspamd_ast_add_node (GPtrArray *operands, struct rspamd_expression_elt *op,
res = g_node_new (op);
g_node_append (res, a1);
g_node_append (res, a2);
+
+ test_elt = a1->data;
+ if (test_elt->type == ELT_ATOM) {
+ test_elt->p.atom->parent = res;
+ }
+
+ test_elt = a2->data;
+ if (test_elt->type == ELT_ATOM) {
+ test_elt->p.atom->parent = res;
+ }
}
/* Push back resulting node to the stack */
@@ -1139,3 +1142,19 @@ rspamd_expression_atom_foreach (struct rspamd_expression *expr,
g_node_traverse (expr->ast, G_POST_ORDER, G_TRAVERSE_ALL, -1,
rspamd_ast_atom_traverse, &data);
}
+
+gboolean
+rspamd_expression_node_is_op (GNode *node, enum rspamd_expression_op op)
+{
+ struct rspamd_expression_elt *elt;
+
+ g_assert (node != NULL);
+
+ elt = node->data;
+
+ if (elt->type == ELT_OP && elt->p.op == op) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/src/libutil/expression.h b/src/libutil/expression.h
index 97cbfec4b..82c0c60c1 100644
--- a/src/libutil/expression.h
+++ b/src/libutil/expression.h
@@ -24,19 +24,36 @@
#define RSPAMD_EXPRESSION_FLAG_NOOPT (1 << 0)
+enum rspamd_expression_op {
+ OP_INVALID = 0,
+ OP_PLUS, /* || or + */
+ OP_MULT, /* && or * */
+ OP_OR, /* || or | */
+ OP_AND, /* && or & */
+ OP_NOT, /* ! */
+ OP_LT, /* < */
+ OP_GT, /* > */
+ OP_LE, /* <= */
+ OP_GE, /* >= */
+ OP_OBRACE, /* ( */
+ OP_CBRACE /* ) */
+};
+
typedef struct rspamd_expression_atom_s {
+ /* Parent node */
+ GNode *parent;
/* Opaque userdata */
gpointer data;
/* String representation of atom */
const gchar *str;
/* Length of the string representation of atom */
gsize len;
- /* Relative priority */
- gint priority;
/* Average execution time (in ticks) */
gdouble avg_ticks;
/* Amount of positive triggers */
guint hits;
+ /* Relative priority */
+ gint priority;
} rspamd_expression_atom_t;
struct rspamd_atom_subr {
@@ -101,4 +118,12 @@ typedef void (*rspamd_expression_atom_foreach_cb) (const rspamd_ftok_t *atom,
void rspamd_expression_atom_foreach (struct rspamd_expression *expr,
rspamd_expression_atom_foreach_cb cb, gpointer cbdata);
+/**
+ * Checks if a specified node in AST is the specified operation
+ * @param node AST node packed in GNode container
+ * @param op operation to check
+ * @return TRUE if node is operation node and is exactly the specified option
+ */
+gboolean rspamd_expression_node_is_op (GNode *node, enum rspamd_expression_op op);
+
#endif /* SRC_LIBUTIL_EXPRESSION_H_ */