Module: sip-router
Branch: andrei/type_conversion
Commit: bb4d414574c35b1ba2c0497e19313b4cd000f775
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=bb4d414…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Tue Apr 28 19:54:03 2009 +0200
news: update (new operators, expr. eval behaviour a.s.o.)
---
NEWS | 27 +++++++++++++++++++++++++++
1 files changed, 27 insertions(+), 0 deletions(-)
diff --git a/NEWS b/NEWS
index fade123..ed1ab96 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,33 @@ $Id$
sip-router changes
core:
+ - new operators eq, ne for string compares and ieq, ine for interger
+ compares. The names are not yet final (use them at your own risk).
+ Future version might use ==/!= only for ints (ieq/ine) and eq/ne for
+ strings (under debate).
+ They are almost equivalent to == or !=, but they force the conversion
+ of their operands (eq to string and ieq to int), allowing among other
+ things better type checking on startup and more optimizations.
+ Non equiv. examples: 0 == "" (true) is not equivalent to 0 eq ""
+ (false: it evaluates to "0" eq ""). "a" ieq "b" (true: (int)"a" is 0
+ and (int)"b" is 0) is not equivalent to "a" == "b" (false).
+ Note: internally == and != are converted on startup to eq/ne/ieq/ine
+ whenever possible (both operand types can be safely determined at
+ start time and they are the same).
+ - try to guess what the user wanted when operators that support multiple
+ types are used on different typed operands. In general convert the
+ the right operand to the type of the left operand and then perform the
+ operation. Exception: the left operand is undef.
+ This applies to the following operators: +, == and !=.
+ Special case: undef as left operand:
+ For +: undef + expr -> undef is converted to string => "" + expr.
+ For == and !=: undef == expr -> undef is converted to type_of expr.
+ If expr is undef, then undef == undef is true (internally is converted
+ to string).
+ - expression evaluation changes: auto-convert to interger or string
+ in function of the operators:
+ int(undef)==0, int("")==0, int("123")==123, int("abc")==0
+ str(undef)=="", str(123)=="123".
- new script operators: defined, strlen, strempty
defined expr - returns true if expr is defined, and false if not.
Note: only a standalone avp or pvar can be
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
Module: sip-router
Branch: andrei/type_conversion
Commit: 970e1f64e93410101a3dcf8914151388991ba800
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=970e1f6…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Tue Apr 28 09:50:07 2009 +0200
core expr eval: defined @select
- a select can now be undefined (defined @select when run_select
returns >0 or error => true)
- RV_CACHE_SELECT introduced
---
rvalue.c | 21 +++++++++++++++------
rvalue.h | 3 ++-
2 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/rvalue.c b/rvalue.c
index 897fb4d..aa99131 100644
--- a/rvalue.c
+++ b/rvalue.c
@@ -1386,9 +1386,11 @@ error:
/** checks if rv is defined.
* @param res - set to the result 1 - defined, 0 not defined
* @return 0 on success, -1 on error
- * Can use cached rvalues (c1).
- * Note: a rv can be undefined if it's an undefined avp or pvar or
+ * Can use cached rvalues (cache).
+ * Note: a rv can be undefined if it's an undefined avp or pvar or select or
* if it's NONE
+ * Note2: an error in the avp, pvar or select search is equivalent to
+ * undefined (and it's not reported)
*/
inline static int rv_defined(struct run_act_ctx* h,
struct sip_msg* msg, int* res,
@@ -1397,13 +1399,21 @@ inline static int rv_defined(struct run_act_ctx* h,
avp_t* r_avp;
int_str avp_val;
pv_value_t pval;
+ str tmp;
*res=1;
switch(rv->type){
+ case RV_SEL:
+ if (unlikely(cache && cache->cache_type==RV_CACHE_SELECT)){
+ *res=(cache->val_type!=RV_NONE);
+ }else
+ /* run select returns 0 on success, -1 on error and >0 on
+ undefined. error is considered undefined */
+ *res=(run_select(&tmp, &rv->v.sel, msg)==0);
+ break;
case RV_AVP:
if (unlikely(cache && cache->cache_type==RV_CACHE_AVP)){
- if (cache->val_type==RV_NONE)
- *res=0;
+ *res=(cache->val_type!=RV_NONE);
}else{
r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
&avp_val, rv->v.avps.index);
@@ -1415,8 +1425,7 @@ inline static int rv_defined(struct run_act_ctx* h,
case RV_PVAR:
/* PV_VAL_NULL or pv_get_spec_value error => undef */
if (unlikely(cache && cache->cache_type==RV_CACHE_PVAR)){
- if (cache->val_type==RV_NONE)
- *res=0;
+ *res=(cache->val_type==RV_NONE);
}else{
memset(&pval, 0, sizeof(pval));
if (likely(pv_get_spec_value(msg, &rv->v.pvs, &pval)==0)){
diff --git a/rvalue.h b/rvalue.h
index a9dbe0d..e99d1f8 100644
--- a/rvalue.h
+++ b/rvalue.h
@@ -118,7 +118,8 @@ struct rval_expr{
enum rval_cache_type{
RV_CACHE_EMPTY,
RV_CACHE_PVAR,
- RV_CACHE_AVP
+ RV_CACHE_AVP,
+ RV_CACHE_SELECT
};
/** value cache for a rvalue struct.