Module: sip-router
Branch: andrei/type_conversion
Commit: 3c8fc182ae386713f15e6a0362924e72b257c31e
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=3c8fc18…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Tue Apr 28 18:34:03 2009 +0200
core expr eval: fix assoc., commut and 0 adding for +, ==
- fix associativity for the generic plus: because of the non-fixed
argument types (can work with strings integers or both in the
same type), RVE_PLUS_OP is associative _only_ if the operand
types match.
Non-assoc. example: "a" + 1 + "2" (can be "a12" or "a3").
Instead of adding extra checks for the same type, rely on the
optimizer having already replaced RVE_PLUS_OP with RVE_IPLUS_OP
or RVE_CONCAT_OP => RVE_PLUS_OP will be used only when the
operands types are mixed or cannot be determined (e.g. AVP), or
when script optimizations are turned off (-O0).
- fix commutativity for the generic plus. Similar to the above.
Non-commut. example: 1 + "2" == 3, but "2" + 1 == "21".
- fix commutativity for the generic == and !=.
Non. commut. example: 0 == "" , but "" != 0.
Similar fix as above, relying on the optimizer and the type specific
operators: RVE_IEQ_OP, RVE_IDIFF_OP, RVE_STREQ_OP and
RVE_STRDIFF_OP.
- fix $v + 0 / 0 + $v -> $v optimizations. Because of the generic
plus and recent changes that allow int + str, even if the result
is an int (left side operant is integer), 0 + $v can be
different from $v. E.g.: 0+"1" == 1, which is different from
"1".
---
rvalue.c | 37 +++++++++++++++++++++++++++----------
1 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/rvalue.c b/rvalue.c
index 7e82503..9a74cda 100644
--- a/rvalue.c
+++ b/rvalue.c
@@ -2281,6 +2281,9 @@ static int rve_op_is_assoc(enum rval_expr_op op)
case RVE_MINUS_OP:
return 0;
case RVE_PLUS_OP:
+ /* the generic plus is not assoc, e.g.
+ "a" + 1 + "2" => "a12" in one case and "a3" in the other */
+ return 0;
case RVE_IPLUS_OP:
case RVE_CONCAT_OP:
case RVE_MUL_OP:
@@ -2308,7 +2311,7 @@ static int rve_op_is_assoc(enum rval_expr_op op)
/** returns true if the operator is commutative. */
-static int rve_op_is_commutative(enum rval_expr_op op, enum rval_type type)
+static int rve_op_is_commutative(enum rval_expr_op op)
{
switch(op){
case RVE_NONE_OP:
@@ -2325,7 +2328,10 @@ static int rve_op_is_commutative(enum rval_expr_op op, enum rval_type type)
case RVE_MINUS_OP:
return 0;
case RVE_PLUS_OP:
- return type==RV_INT; /* commutative only for INT*/
+ /* non commut. when diff. type
+ (e.g 1 + "2" != "2" + 1 ) => non commut. in general
+ (specific same type versions are covered by IPLUS & CONCAT) */
+ return 0;
case RVE_IPLUS_OP:
case RVE_MUL_OP:
case RVE_BAND_OP:
@@ -2345,11 +2351,11 @@ static int rve_op_is_commutative(enum rval_expr_op op, enum rval_type type)
return 0;
case RVE_DIFF_OP:
case RVE_EQ_OP:
-#if !defined(UNDEF_EQ_ALWAYS_FALSE) && !defined(UNDEF_EQ_UNDEF_TRUE)
- return 1;
-#else
+ /* non. commut. in general, only for same type e.g.:
+ "" == 0 diff. 0 == "" ( "" == "0" and 0 == 0)
+ same type versions are covered by IEQ, IDIFF, STREQ, STRDIFF
+ */
return 0 /* asymmetrical undef handling */;
-#endif
}
return 0;
}
@@ -2658,8 +2664,19 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
case RVE_PLUS_OP:
case RVE_IPLUS_OP:
/* we must make sure that this is an int PLUS
- (because "foo"+0 is valid => "foo0") */
- if ((i==0) && ((op==RVE_IPLUS_OP)||(rve_type==RV_INT))){
+ (because "foo"+0 is valid => "foo0")
+ Even if overall type is RV_INT, it's still not safe
+ to optimize a generic PLUS: 0 + $v is not always equivalent
+ to $v (e.g. 0+"1" ==1 != "1") => optimize only if
+ IPLUS (always safe since it converts to int first) or
+ if generic PLUS and result is integer (rve_type) and
+ expression is of the form $v+ct (and not ct+$v).
+ TODO: dropping PLUS_OP all together and relying on the
+ optimizer replacing safe PLUS_OP with IPLUS_OP or CONCAT_OP
+ will simplify things.
+ */
+ if ((i==0) && ((op==RVE_IPLUS_OP)||
+ (rve_type==RV_INT && ct_rve==rve->right.rve))){
/* $v + 0 -> $v
* 0 + $v -> $v */
rve_destroy(ct_rve);
@@ -2908,7 +2925,7 @@ static int rve_optimize(struct rval_expr* rve)
trv->v.s.len, trv->v.s.s, rve->op);
ret=1;
}else if (rve_is_constant(rve->left.rve->left.rve) &&
- rve_op_is_commutative(rve->op, type)){
+ rve_op_is_commutative(rve->op)){
/* op(op(a, $v), b) => op(op(a, b), $v) */
/* rv= op(a, b) */
tmp_rve.op=rve->op;
@@ -2950,7 +2967,7 @@ static int rve_optimize(struct rval_expr* rve)
if ((rve->op==rve->right.rve->op) && rve_op_is_assoc(rve->op)){
/* op(a, op(...)) */
if (rve_is_constant(rve->right.rve->right.rve) &&
- rve_op_is_commutative(rve->op, type)){
+ rve_op_is_commutative(rve->op)){
/* op(a, op($v, b)) => op(op(a, b), $v) */
/* rv= op(a, b) */
tmp_rve.op=rve->op;
Module: sip-router
Branch: master
Commit: 313f52655841f1abf4c0db585699cd31e9494a3f
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=313f526…
Author: Daniel-Constantin Mierla <miconda(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)gmail.com>
Date: Tue Apr 28 16:35:28 2009 +0200
kex: script and branch flags operations
- K script and branch flags operations included in kex module
- the parameters must be now enclosed in quotes
- the parameters can be now integer value or Pseudo-Variable with
integer value
- the optional 'branch' parameter for branch flags parameters is now the
second, for a more logical parameter mapping with the version without
this parameter
---
modules_k/kex/flags.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++
modules_k/kex/flags.h | 35 +++++++++++
modules_k/kex/kex_mod.c | 29 +++++++++-
3 files changed, 205 insertions(+), 3 deletions(-)
diff --git a/modules_k/kex/flags.c b/modules_k/kex/flags.c
new file mode 100644
index 0000000..ae539d1
--- /dev/null
+++ b/modules_k/kex/flags.c
@@ -0,0 +1,144 @@
+/**
+ * $Id$
+ *
+ * Copyright (C) 2009
+ *
+ * This file is part of SIP-Router.org, a free SIP server.
+ *
+ * SIP-Router is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "../../dprint.h"
+#include "../../flags.h"
+#include "../../dset.h"
+#include "../../mod_fix.h"
+#include "flags.h"
+
+int w_issflagset(struct sip_msg *msg, char *flag, str *s2)
+{
+ int fval=0;
+ if(fixup_get_ivalue(msg, (gparam_p)flag, &fval)!=0)
+ {
+ LM_ERR("no flag value\n");
+ return -1;
+ }
+ if(fval<0 || fval>31)
+ return -1;
+ return issflagset((flag_t)fval);
+}
+
+int w_resetsflag(struct sip_msg *msg, char *flag, str *s2)
+{
+ int fval=0;
+ if(fixup_get_ivalue(msg, (gparam_p)flag, &fval)!=0)
+ {
+ LM_ERR("no flag value\n");
+ return -1;
+ }
+ if(fval<0 || fval>31)
+ return -1;
+ return resetsflag((flag_t)fval);
+}
+
+int w_setsflag(struct sip_msg *msg, char *flag, char *s2)
+{
+ int fval=0;
+ if(fixup_get_ivalue(msg, (gparam_p)flag, &fval)!=0)
+ {
+ LM_ERR("no flag value\n");
+ return -1;
+ }
+ if(fval<0 || fval>31)
+ return -1;
+ return setsflag((flag_t)fval);
+}
+
+int w_isbflagset(struct sip_msg *msg, char *flag, str *idx)
+{
+ int fval=0;
+ int ival=0;
+ if(fixup_get_ivalue(msg, (gparam_p)flag, &fval)!=0)
+ {
+ LM_ERR("no flag value\n");
+ return -1;
+ }
+ if(fval<0 || fval>31)
+ return -1;
+ if(idx!=0)
+ {
+ if(fixup_get_ivalue(msg, (gparam_p)idx, &ival)!=0)
+ {
+ LM_ERR("no idx value\n");
+ return -1;
+ }
+ if(ival<0)
+ return -1;
+ }
+ return isbflagset(ival, (flag_t)fval);
+}
+
+int w_resetbflag(struct sip_msg *msg, char *flag, str *idx)
+{
+ int fval=0;
+ int ival=0;
+ if(fixup_get_ivalue(msg, (gparam_p)flag, &fval)!=0)
+ {
+ LM_ERR("no flag value\n");
+ return -1;
+ }
+ if(fval<0 || fval>31)
+ return -1;
+ if(idx!=0)
+ {
+ if(fixup_get_ivalue(msg, (gparam_p)idx, &ival)!=0)
+ {
+ LM_ERR("no idx value\n");
+ return -1;
+ }
+ if(ival<0)
+ return -1;
+ }
+ return resetbflag(ival, (flag_t)fval);
+
+}
+
+int w_setbflag(struct sip_msg *msg, char *flag, char *idx)
+{
+ int fval=0;
+ int ival=0;
+ if(fixup_get_ivalue(msg, (gparam_p)flag, &fval)!=0)
+ {
+ LM_ERR("no flag value\n");
+ return -1;
+ }
+ if(fval<0 || fval>31)
+ return -1;
+ if(idx!=0)
+ {
+ if(fixup_get_ivalue(msg, (gparam_p)idx, &ival)!=0)
+ {
+ LM_ERR("no idx value\n");
+ return -1;
+ }
+ if(ival<0)
+ return -1;
+ }
+ return setbflag(ival, (flag_t)fval);
+}
+
diff --git a/modules_k/kex/flags.h b/modules_k/kex/flags.h
new file mode 100644
index 0000000..d0dbad4
--- /dev/null
+++ b/modules_k/kex/flags.h
@@ -0,0 +1,35 @@
+/**
+ * $Id$
+ *
+ * Copyright (C) 2009
+ *
+ * This file is part of SIP-Router.org, a free SIP server.
+ *
+ * SIP-Router is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * Kamailio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _KEX_FLAGS_H_
+#define _KEX_FLAGS_H_
+
+#include "../../sr_module.h"
+
+int w_issflagset(struct sip_msg *msg, char *flag, str *s2);
+int w_resetsflag(struct sip_msg *msg, char *flag, str *s2);
+int w_setsflag(struct sip_msg *msg, char *flag, char *s2);
+int w_isbflagset(struct sip_msg *msg, char *flag, str *idx);
+int w_resetbflag(struct sip_msg *msg, char *flag, str *idx);
+int w_setbflag(struct sip_msg *msg, char *flag, char *idx);
+
+#endif
diff --git a/modules_k/kex/kex_mod.c b/modules_k/kex/kex_mod.c
index c9c3ae3..e4960c0 100644
--- a/modules_k/kex/kex_mod.c
+++ b/modules_k/kex/kex_mod.c
@@ -3,9 +3,9 @@
*
* Copyright (C) 2009
*
- * This file is part of Kamailio, a free SIP server.
+ * This file is part of SIP-Router.org, a free SIP server.
*
- * Kamailio is free software; you can redistribute it and/or modify
+ * SIP-Router is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
@@ -26,7 +26,11 @@
#include "../../sr_module.h"
#include "../../dprint.h"
+#include "../../flags.h"
+#include "../../dset.h"
+#include "../../mod_fix.h"
+#include "flags.h"
#include "mi_core.h"
#include "core_stats.h"
@@ -38,10 +42,28 @@ MODULE_VERSION
/** module functions */
static int mod_init(void);
-
void destroy(void);
static cmd_export_t cmds[]={
+ {"setsflag", (cmd_function)w_setsflag, 1,fixup_igp_null,
+ 0, ANY_ROUTE },
+ {"resetsflag", (cmd_function)w_resetsflag, 1,fixup_igp_null,
+ 0, ANY_ROUTE },
+ {"issflagset", (cmd_function)w_issflagset, 1,fixup_igp_null,
+ 0, ANY_ROUTE },
+ {"setbflag", (cmd_function)w_setbflag, 1,fixup_igp_null,
+ 0, ANY_ROUTE },
+ {"setbflag", (cmd_function)w_setbflag, 2,fixup_igp_igp,
+ 0, ANY_ROUTE },
+ {"resetbflag", (cmd_function)w_resetbflag, 1,fixup_igp_null,
+ 0, ANY_ROUTE },
+ {"resetbflag", (cmd_function)w_resetbflag, 2,fixup_igp_igp,
+ 0, ANY_ROUTE },
+ {"isbflagset", (cmd_function)w_isbflagset, 1,fixup_igp_null,
+ 0, ANY_ROUTE },
+ {"isbflagset", (cmd_function)w_isbflagset, 2,fixup_igp_igp,
+ 0, ANY_ROUTE },
+
{0,0,0,0,0,0}
};
@@ -93,3 +115,4 @@ void destroy(void)
return;
}
+
Module: sip-router
Branch: andrei/type_conversion
Commit: ab736da560c93b707653d342f7932f8b677e08fc
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=ab736da…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Tue Apr 28 16:07:23 2009 +0200
core expr eval: special handling for undef cmp expr
undef == expression is evaluated in the following way:
- default:
(type_of(expression))(undef) == expression.
If the expression is undef too, the whole comparison it's
evaluated to true (internally it's evaluated to
(str) undef == (str) undef => "" == "" => true).
E.g.: undef == 0 -> (int)undef == 0 -> 0 == 0 -> true
undef == "a" -> (str)undef == "a" -> ""=="a" -> false
undef == undef -> true
- if UNDEF_EQ_UNDEF_TRUE is defined, the == comparison is always
false except for undef == undef which is true.
E.g.: undef == 0 -> false ; undef == "" false
- if UNDEF_EQ_ALWAY_FALSE is defined, the result is always false
!= is always the reverse of ==.
Note: this covers only the case when undef is on the _left_ side
(the case in which we do not know what to convert undef to). If
the undef is on the right side, it will work like for any other
comparison: expr == undef => expr == (type_of(expr)) undef.
---
rvalue.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 79 insertions(+), 12 deletions(-)
diff --git a/rvalue.c b/rvalue.c
index 14c1f16..2961ee9 100644
--- a/rvalue.c
+++ b/rvalue.c
@@ -26,7 +26,23 @@
* 2009-04-24 added support for defined, strempty, strlen (andrei)
* 2009-04-28 int and str automatic conversions: (int)undef=0,
* (str)undef="", (int)""=0, (int)"123"=123, (int)"abc"=0
- * (andrei)
+ * handle undef == expr, in function of the UNDEF_EQ_* defines.
+ * (andrei)
+ */
+
+/* special defines:
+ *
+ * UNDEF_EQ_* - how to behave when undef is on the right side of a generic
+ * compare operator
+ * UNDEF_EQ_ALWAYS_FALSE: undef == something is always false
+ * UNDEF_EQ_UNDEF_TRUE : undef == something false except for undef==undef
+ * which is true
+ * no UNDEF_EQ* define : undef == expr => convert undef to typeof(expr)
+ * and perorm normal ==. undef == undef will be
+ * converted to string and it will be true
+ * ("" == "")
+ * NOTE: expr == undef, with defined(expr) is always evaluated this way:
+ expr == (type_of(expr))undef
*/
#include "rvalue.h"
@@ -1549,7 +1565,7 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
int* res, struct rval_expr* rve)
{
int i1, i2, ret;
- struct rval_cache c1;
+ struct rval_cache c1, c2;
struct rvalue* rv1;
struct rvalue* rv2;
@@ -1616,10 +1632,14 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
case RVE_EQ_OP:
case RVE_DIFF_OP:
/* if left is string, eval left & right as string and
- use string diff, else eval as int */
+ * use string diff.
+ * if left is int eval as int using int diff
+ * if left is undef, look at right and convert to right type
+ */
rval_cache_init(&c1);
if (unlikely( (ret=rval_expr_eval_rvint(h, msg, &rv1, &i1,
rve->left.rve, &c1))<0)){
+ /* error */
rval_cache_clean(&c1);
break;
}
@@ -1628,20 +1648,67 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
rval_cache_clean(&c1);
if (unlikely( (ret=rval_expr_eval_int(h, msg, &i2,
rve->right.rve)) <0) )
- break;
+ break; /* error */
ret=int_intop2(res, rve->op, i1, i2);
}else{
- if (unlikely((rv2=rval_expr_eval(h, msg,
- rve->right.rve))==0)){
+ /* not int => str or undef */
+ /* check for undefined left operand */
+ if (unlikely( c1.cache_type!=RV_CACHE_EMPTY &&
+ c1.val_type==RV_NONE)){
+#ifdef UNDEF_EQ_ALWAYS_FALSE
+ /* undef == something always false
+ undef != something always true*/
+ ret=(rve->op==RVE_DIFF_OP);
+#elif defined UNDEF_EQ_UNDEF_TRUE
+ /* undef == something defined always false
+ undef == undef true */
+ if (int_rve_defined(h, msg, &i2, rve->right.rve)<0){
+ /* error */
+ rval_cache_clean(&c1);
+ rval_destroy(rv1);
+ break;
+ }
+ ret=(!i2) ^ (rve->op==RVE_DIFF_OP);
+#else /* ! UNDEF_EQ_* */
+ /* undef == val
+ * => convert to (type_of(val)) (undef) == val */
+ rval_cache_init(&c2);
+ if (unlikely( (ret=rval_expr_eval_rvint(h, msg, &rv2, &i2,
+ rve->right.rve, &c2))<0)){
+ /* error */
+ rval_cache_clean(&c1);
+ rval_cache_clean(&c2);
+ rval_destroy(rv1);
+ break;
+ }
+ if (rv2==0){
+ /* int */
+ ret=int_intop2(res, rve->op, 0 /* undef */, i2);
+ }else{
+ /* str or undef */
+ ret=rval_str_lop2(h, msg, res, rve->op, rv1, &c1,
+ rv2, &c2);
+ rval_cache_clean(&c2);
+ rval_destroy(rv2);
+ }
+#endif /* UNDEF_EQ_* */
+ rval_cache_clean(&c1);
rval_destroy(rv1);
+ }else{
+ /* left value == defined and != int => str
+ * => lval == (str) val */
+ if (unlikely((rv2=rval_expr_eval(h, msg,
+ rve->right.rve))==0)){
+ /* error */
+ rval_destroy(rv1);
+ rval_cache_clean(&c1);
+ break;
+ }
+ ret=rval_str_lop2(h, msg, res, rve->op, rv1, &c1, rv2, 0);
rval_cache_clean(&c1);
- ret=-1;
- break;
+ rval_destroy(rv1);
+ rval_destroy(rv2);
}
- ret=rval_str_lop2(h, msg, res, rve->op, rv1, &c1, rv2, 0);
- rval_cache_clean(&c1);
- rval_destroy(rv1);
- rval_destroy(rv2);
}
break;
#if 0