static rspamd_expression_atom_t * rspamd_mime_expr_parse (const gchar *line, gsize len,
rspamd_mempool_t *pool, gpointer ud, GError **err);
-static gint rspamd_mime_expr_process (gpointer input, rspamd_expression_atom_t *atom);
+static gdouble rspamd_mime_expr_process (gpointer input, rspamd_expression_atom_t *atom);
static gint rspamd_mime_expr_priority (rspamd_expression_atom_t *atom);
static void rspamd_mime_expr_destroy (rspamd_expression_atom_t *atom);
return selected->func (task, func->args, selected->user_data);
}
-static gint
+static gdouble
rspamd_mime_expr_process (gpointer input, rspamd_expression_atom_t *atom)
{
struct rspamd_task *task = input;
struct rspamd_mime_atom *mime_atom;
lua_State *L;
- gint ret = 0;
+ gdouble ret = 0;
g_assert (task != NULL);
g_assert (atom != NULL);
static rspamd_expression_atom_t * rspamd_composite_expr_parse (const gchar *line, gsize len,
rspamd_mempool_t *pool, gpointer ud, GError **err);
-static gint rspamd_composite_expr_process (gpointer input, rspamd_expression_atom_t *atom);
+static gdouble rspamd_composite_expr_process (gpointer input, rspamd_expression_atom_t *atom);
static gint rspamd_composite_expr_priority (rspamd_expression_atom_t *atom);
static void rspamd_composite_expr_destroy (rspamd_expression_atom_t *atom);
return rc;
}
-static gint
+static gdouble
rspamd_composite_expr_process (gpointer input, rspamd_expression_atom_t *atom)
{
struct composites_data *cd = (struct composites_data *)input;
#include "util.h"
#include "utlist.h"
#include "ottery.h"
+#include <math.h>
#define RSPAMD_EXPR_FLAG_NEGATE (1 << 0)
#define RSPAMD_EXPR_FLAG_PROCESSED (1 << 1)
#define MIN_RESORT_EVALS 50
#define MAX_RESORT_EVALS 150
+#define DOUBLE_EPSILON 1e-9
enum rspamd_expression_elt_type {
ELT_OP = 0,
} lim;
} p;
gint flags;
- gint value;
+ gdouble value;
gint priority;
};
static gboolean
rspamd_ast_node_done (struct rspamd_expression_elt *elt,
- struct rspamd_expression_elt *parelt, gint acc, gint lim)
+ struct rspamd_expression_elt *parelt, gdouble acc, gdouble lim)
{
gboolean ret = FALSE;
return ret;
}
-static gint
+static gdouble
rspamd_ast_do_op (struct rspamd_expression_elt *elt, gint val,
- gint acc, gint lim, gboolean first_elt)
+ gdouble acc, gdouble lim, gboolean first_elt)
{
- gint ret = val;
+ gdouble ret = val;
g_assert (elt->type == ELT_OP);
switch (elt->p.op) {
case OP_NOT:
- ret = !val;
+ ret = fabs (val) > DOUBLE_EPSILON ? 0.0 : 1.0;
break;
case OP_PLUS:
ret = acc + val;
break;
case OP_MULT:
case OP_AND:
- ret = first_elt ? (val) : (acc && val);
+ ret = first_elt ? (val) : (acc * val);
break;
case OP_OR:
- ret = first_elt ? (val) : (acc || val);
+ ret = first_elt ? (val) : (acc + val);
break;
default:
g_assert (0);
return ret;
}
-static gint
+static gdouble
rspamd_ast_process_node (struct rspamd_expression *expr, gint flags, GNode *node,
gpointer data, GPtrArray *track)
{
struct rspamd_expression_elt *elt, *celt, *parelt = NULL;
GNode *cld;
- gint acc = G_MININT, lim = G_MININT, val;
- gdouble t1, t2;
+ gdouble acc = NAN, lim = 0;
+ gdouble t1, t2, val;
gboolean calc_ticks = FALSE;
elt = node->data;
elt->value = expr->subr->process (data, elt->p.atom);
- if (elt->value) {
+ if (fabs (elt->value) > 1e-9) {
elt->p.atom->hits ++;
if (track) {
elt->flags |= RSPAMD_EXPR_FLAG_PROCESSED;
}
- return elt->value;
+ acc = elt->value;
break;
case ELT_LIMIT:
- return elt->p.lim.val;
+ acc = elt->p.lim.val;
break;
case ELT_OP:
g_assert (node->children != NULL);
- cld = node->children;
/* Try to find limit at the parent node */
if (node->parent) {
val = rspamd_ast_process_node (expr, flags, cld, data, track);
- if (acc == G_MININT) {
+ if (isnan (acc)) {
acc = rspamd_ast_do_op (elt, val, 0, lim, TRUE);
}
else {
return FALSE;
}
-gint
+gdouble
rspamd_process_expression_track (struct rspamd_expression *expr, gint flags,
gpointer data, GPtrArray *track)
{
- gint ret = 0;
+ gdouble ret = 0;
g_assert (expr != NULL);
/* Ensure that stack is empty at this point */
return ret;
}
-gint
+gdouble
rspamd_process_expression (struct rspamd_expression *expr, gint flags,
gpointer data)
{
rspamd_expression_atom_t * (*parse)(const gchar *line, gsize len,
rspamd_mempool_t *pool, gpointer ud, GError **err);
/* Process atom via the opaque pointer (e.g. struct rspamd_task *) */
- gint (*process) (gpointer input, rspamd_expression_atom_t *atom);
+ gdouble (*process) (gpointer input, rspamd_expression_atom_t *atom);
/* Calculates the relative priority of the expression */
gint (*priority) (rspamd_expression_atom_t *atom);
void (*destroy) (rspamd_expression_atom_t *atom);
* @param data opaque data pointer for all the atoms
* @return the value of expression
*/
-gint rspamd_process_expression (struct rspamd_expression *expr, gint flags,
+gdouble rspamd_process_expression (struct rspamd_expression *expr, gint flags,
gpointer data);
/**
* @param track pointer array to atoms tracking
* @return the value of expression
*/
-gint rspamd_process_expression_track (struct rspamd_expression *expr, gint flags,
+gdouble rspamd_process_expression_track (struct rspamd_expression *expr, gint flags,
gpointer data, GPtrArray *track);
/**
static rspamd_expression_atom_t * lua_atom_parse (const gchar *line, gsize len,
rspamd_mempool_t *pool, gpointer ud, GError **err);
-static gint lua_atom_process (gpointer input, rspamd_expression_atom_t *atom);
+static gdouble lua_atom_process (gpointer input, rspamd_expression_atom_t *atom);
static const struct rspamd_atom_subr lua_atom_subr = {
.parse = lua_atom_parse,
return atom;
}
-static gint
+static gdouble
lua_atom_process (gpointer input, rspamd_expression_atom_t *atom)
{
struct lua_expression *e = (struct lua_expression *)atom->data;
- gint ret = 0;
+ gdouble ret = 0;
lua_rawgeti (e->L, LUA_REGISTRYINDEX, e->process_idx);
lua_pushlstring (e->L, atom->str, atom->len);
lua_expr_process (lua_State *L)
{
struct lua_expression *e = rspamd_lua_expression (L, 1);
- gint res;
+ gdouble res;
gint flags = 0;
if (lua_gettop (L) >= 3) {