pkg: fix wrong package name, closes FS#148, reported from Andrew Pogrebennyk
[sip-router] / rvalue.c
index 27ab268..00dc19d 100644 (file)
--- a/rvalue.c
+++ b/rvalue.c
@@ -1,6 +1,4 @@
 /* 
- * $Id$
- * 
  * Copyright (C) 2008 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+
 /**
  * @file 
- * @brief rvalue expressions
+ * @brief SIP-router core :: rvalue expressions
+ * @ingroup core
+ * Module: \ref core
  */
+
 /* 
  * History:
  * --------
  *                          ("" == "")
  * NOTE: expr == undef, with defined(expr) is always evaluated this way:
          expr == (type_of(expr))undef
+ *  RV_STR2INT_VERBOSE_ERR - if a string conversion to int fails, log (L_WARN)
+ *                           the string that caused it (only the string, not
+ *                           the expression position).
+ *  RV_STR2INT_ERR         - if a string conversion to int fails, don't ignore
+ *                           the error (return error).
+ *  RVAL_GET_INT_ERR_WARN  - if a conversion to int fails, log a warning with
+ *                           the expression position.
+ *                           Depends on RV_STR2INT_ERR.
+ *  RVAL_GET_INT_ERR_IGN   - if a conversion to int fails, ignore the error
+ *                           (the result will be 0). Can be combined with
+ *                           RVAL_GET_INT_ERR_WARN.
+ *                           Depends on RV_STR2INT_ERR.
  */
 
+
 #include "rvalue.h"
 
 #include <stdlib.h> /* abort() */
 
+/* if defined warn when str2int conversions fail */
+#define RV_STR2INT_VERBOSE_ERR
+
+/* if defined rval_get_int will fail if str2int conversion fail
+   (else convert to 0) */
+#define RV_STR2INT_ERR
+
+/* if a rval_get_int fails (conversion to int), warn
+   Depends on RV_STR2INT_ERR.
+ */
+#define RVAL_GET_INT_ERR_WARN
+
+/* if a rval_get_int fails, ignore it (expression evaluation will not fail,
+   the int conversion will result in 0).
+   Can be combined with RVAL_GET_INT_ERR_WARN.
+   Depends on RV_STR2INT_ERR.
+ */
+#define RVAL_GET_INT_ERR_IGN
+
 /* minimum size alloc'ed for STR RVs (to accomodate
  * strops without reallocs) */
 #define RV_STR_EXTRA 80
@@ -127,15 +161,19 @@ void rve_destroy(struct rval_expr* rve)
                                if (rve->left.rval.refcnt==1)
                                        rval_destroy(&rve->left.rval);
                                else
-                                       BUG("rval expr rval with invalid refcnt: %d\n", 
-                                                       rve->left.rval.refcnt);
+                                       BUG("rval expr rval with invalid refcnt: %d (%d,%d-%d,%d)"
+                                                       "\n", rve->left.rval.refcnt,
+                                                       rve->fpos.s_line, rve->fpos.s_col,
+                                                       rve->fpos.e_line, rve->fpos.e_col);
                        }
                        if (rve->right.rval.refcnt){
                                if (rve->right.rval.refcnt==1)
                                        rval_destroy(&rve->right.rval);
                                else
-                                       BUG("rval expr rval with invalid refcnt: %d\n", 
-                                                       rve->right.rval.refcnt);
+                                       BUG("rval expr rval with invalid refcnt: %d (%d,%d-%d,%d)"
+                                                       "\n", rve->right.rval.refcnt,
+                                                       rve->fpos.s_line, rve->fpos.s_col,
+                                                       rve->fpos.e_line, rve->fpos.e_col);
                        }
                }else{
                        if (rve->left.rve)
@@ -302,14 +340,14 @@ char* rval_type_name(enum rval_type type)
 
 
 
-/** create a new pk_malloc'ed rvalue from a rval_val union.
-  *
-  * @param s - pointer to str, must be non-null
 * @param extra_size - extra space to allocate
 *                    (so that future string operation can reuse
 *                     the space)
 * @return new rv or 0 on error
 */
+/**
+ * @brief create a new pk_malloc'ed rvalue from a rval_val union
+ * @param t rvalue type
* @param v rvalue value
* @param extra_size extra space to allocate
* (so that future string operation can reuse the space)
+ * @return new rv or 0 on error
+ */
 struct rvalue* rval_new(enum rval_type t, union rval_val* v, int extra_size)
 {
        struct rvalue* rv;
@@ -333,18 +371,21 @@ struct rvalue* rval_new(enum rval_type t, union rval_val* v, int extra_size)
 
 
 
-/** get rvalue basic type (RV_INT or RV_STR).
-  *
-  * Given a rvalue it tries to determinte its basic type.
-  * Fills val_cache if non-null and empty (can be used in other rval*
-  * function calls, to avoid re-resolving avps or pvars). It must be
-  * rval_cache_clean()'en when no longer needed.
-  *
-  * @param rv - target rvalue
-  * @param val_cache - write-only: value cache, might be filled if non-null,
-  *                    it _must_ be rval_cache_clean()'en when done.
-  * @return - basic type or RV_NONE on error
-  */
+/**
+ * @brief get rvalue basic type (RV_INT or RV_STR)
+ *
+ * Given a rvalue it tries to determinte its basic type.
+ * Fills val_cache if non-null and empty (can be used in other rval*
+ * function calls, to avoid re-resolving avps or pvars). It must be
+ * rval_cache_clean()'en when no longer needed.
+ *
+ * @param h run action context
+ * @param msg SIP message
+ * @param rv target rvalue
+ * @param val_cache write-only value cache, might be filled if non-null,
+ * it _must_ be rval_cache_clean()'en when done.
+ * @return basic type or RV_NONE on error
+ */
 inline static enum rval_type rval_get_btype(struct run_act_ctx* h,
                                                                                        struct sip_msg* msg,
                                                                                        struct rvalue* rv,
@@ -459,12 +500,16 @@ enum rval_type rve_guess_type( struct rval_expr* rve)
                case RVE_UMINUS_OP:
                case RVE_BOOL_OP:
                case RVE_LNOT_OP:
+               case RVE_BNOT_OP:
                case RVE_MINUS_OP:
                case RVE_MUL_OP:
                case RVE_DIV_OP:
                case RVE_MOD_OP:
                case RVE_BOR_OP:
                case RVE_BAND_OP:
+               case RVE_BXOR_OP:
+               case RVE_BLSHIFT_OP:
+               case RVE_BRSHIFT_OP:
                case RVE_LAND_OP:
                case RVE_LOR_OP:
                case RVE_GT_OP:
@@ -523,6 +568,7 @@ int rve_is_constant(struct rval_expr* rve)
                case RVE_UMINUS_OP:
                case RVE_BOOL_OP:
                case RVE_LNOT_OP:
+               case RVE_BNOT_OP:
                case RVE_STRLEN_OP:
                case RVE_STREMPTY_OP:
                case RVE_DEFINED_OP:
@@ -535,6 +581,9 @@ int rve_is_constant(struct rval_expr* rve)
                case RVE_MOD_OP:
                case RVE_BOR_OP:
                case RVE_BAND_OP:
+               case RVE_BXOR_OP:
+               case RVE_BLSHIFT_OP:
+               case RVE_BRSHIFT_OP:
                case RVE_LAND_OP:
                case RVE_LOR_OP:
                case RVE_GT_OP:
@@ -583,6 +632,7 @@ static int rve_op_unary(enum rval_expr_op op)
                case RVE_UMINUS_OP:
                case RVE_BOOL_OP:
                case RVE_LNOT_OP:
+               case RVE_BNOT_OP:
                case RVE_STRLEN_OP:
                case RVE_STREMPTY_OP:
                case RVE_DEFINED_OP:
@@ -595,6 +645,9 @@ static int rve_op_unary(enum rval_expr_op op)
                case RVE_MOD_OP:
                case RVE_BOR_OP:
                case RVE_BAND_OP:
+               case RVE_BXOR_OP:
+               case RVE_BLSHIFT_OP:
+               case RVE_BRSHIFT_OP:
                case RVE_LAND_OP:
                case RVE_LOR_OP:
                case RVE_GT_OP:
@@ -621,18 +674,19 @@ static int rve_op_unary(enum rval_expr_op op)
 
 
 
-/** returns 1 if expression is valid (type-wise).
-  * @param type - filled with the type of the expression (RV_INT, RV_STR or
-  *                RV_NONE if it's dynamic)
-  * @param rve  - checked expression
-  * @param bad_rve - set on failure to the subexpression for which the 
-  *                    type check failed
-  * @param bad_type - set on failure to the type of the bad subexpression
-  * @param exp_type - set on failure to the expected type for the bad
-  *                   subexpression
-  * @return 0 or 1  and sets *type to the resulting type
-  * (RV_INT, RV_STR or RV_NONE if it can be found only at runtime)
-  */
+/**
+ * @brief Returns 1 if expression is valid (type-wise)
+ * @param type filled with the type of the expression (RV_INT, RV_STR or
+ *                RV_NONE if it's dynamic)
+ * @param rve  checked expression
+ * @param bad_rve set on failure to the subexpression for which the 
+ * type check failed
+ * @param bad_t set on failure to the type of the bad subexpression
+ * @param exp_t set on failure to the expected type for the bad
+ * subexpression
+ * @return 0 or 1 and sets *type to the resulting type
+ * (RV_INT, RV_STR or RV_NONE if it can be found only at runtime)
+ */
 int rve_check_type(enum rval_type* type, struct rval_expr* rve,
                                        struct rval_expr** bad_rve, 
                                        enum rval_type* bad_t,
@@ -647,6 +701,7 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
                case RVE_UMINUS_OP:
                case RVE_BOOL_OP:
                case RVE_LNOT_OP:
+               case RVE_BNOT_OP:
                        *type=RV_INT;
                        if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
                                if (type1==RV_STR){
@@ -665,6 +720,9 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
                case RVE_MOD_OP:
                case RVE_BOR_OP:
                case RVE_BAND_OP:
+               case RVE_BXOR_OP:
+               case RVE_BLSHIFT_OP:
+               case RVE_BRSHIFT_OP:
                case RVE_LAND_OP:
                case RVE_LOR_OP:
                case RVE_GT_OP:
@@ -802,7 +860,9 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
                        break;
                case RVE_NONE_OP:
                default:
-                       BUG("unexpected rve op %d\n", rve->op);
+                       BUG("unexpected rve op %d (%d,%d-%d,%d)\n", rve->op,
+                                       rve->fpos.s_line, rve->fpos.s_col,
+                                       rve->fpos.e_line, rve->fpos.e_col);
                        if (bad_rve) *bad_rve=rve;
                        if (bad_t) *bad_t=RV_NONE;
                        if (exp_t) *exp_t=RV_STR;
@@ -835,11 +895,12 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
        pv_value_t pval;
        str tmp;
        str* s;
-       int r;
+       int r, ret;
        int destroy_pval;
        
        destroy_pval=0;
        s=0;
+       ret=0;
        switch(rv->type){
                case RV_INT:
                        *i=rv->v.l;
@@ -855,9 +916,11 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
                        }
                        break;
                case RV_ACTION_ST:
-                       if (rv->v.action)
-                               *i=(run_actions(h, rv->v.action, msg)>0);
-                       else
+                       if (rv->v.action) {
+                               *i=(run_actions_safe(h, rv->v.action, msg)>0);
+                               h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return &
+                                                                                                                   break in expr*/
+                       } else
                                *i=0;
                        break;
                case RV_SEL:
@@ -931,15 +994,12 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
                        BUG("rv type %d not handled\n", rv->type);
                        goto error;
        }
-       return 0;
+       return ret;
 undef:
 eval_error: /* same as undefined */
        /* handle undefined => result 0, return success */
        *i=0;
        return 0;
-error_cache:
-       BUG("invalid cached value:cache type %d, value type %d\n",
-                       cache?cache->cache_type:0, cache?cache->val_type:0);
 rv_str:
        /* rv is of string type => try to convert it to int */
        /* if "" => 0 (most likely case) */
@@ -947,28 +1007,87 @@ rv_str:
        else if (unlikely(str2sint(s, i)!=0)){
                /* error converting to int => non numeric => 0 */
                *i=0;
+#ifdef RV_STR2INT_VERBOSE_ERR
+               WARN("automatic string to int conversion for \"%.*s\" failed\n",
+                               s->len, ZSW(s->s));
+               /* return an error code */
+#endif
+#ifdef RV_STR2INT_ERR
+               ret=-1;
+#endif
        }
        if (destroy_pval)
                pv_value_destroy(&pval);
-       return 0;
+       return ret;
+error_cache:
+       BUG("invalid cached value:cache type %d, value type %d\n",
+                       cache?cache->cache_type:0, cache?cache->val_type:0);
 error:
+       if (destroy_pval)
+               pv_value_destroy(&pval);
        *i=0;
        return -1;
 }
 
 
 
+/** log a message, appending rve position and a '\n'.*/
+#define RVE_LOG(lev, rve, txt) \
+       LOG((lev), txt " (%d,%d-%d,%d)\n", \
+                       (rve)->fpos.s_line, rve->fpos.s_col, \
+                       (rve)->fpos.e_line, rve->fpos.e_col )
+
+
+/** macro for checking and handling rval_get_int() retcode.
+ * check if the return code is an rval_get_int error and if so
+ * handle the error (e.g. print a log message, ignore the error by
+ * setting ret to 0 a.s.o.)
+ * @param ret - retcode as returned by rval_get_int() (might be changed)
+ * @param txt - warning message txt (no pointer allowed)
+ * @param rve - rval_expr, used to access the config. pos
+ */
+#if defined RVAL_GET_INT_ERR_WARN && defined RVAL_GET_INT_ERR_IGN
+#define rval_get_int_handle_ret(ret, txt, rve) \
+       do { \
+               if (unlikely((ret)<0)) { \
+                       RVE_LOG(L_WARN, rve, txt); \
+                       (ret)=0; \
+               } \
+       }while(0)
+#elif defined RVAL_GET_INT_ERR_WARN
+#define rval_get_int_handle_ret(ret, txt, rve) \
+       do { \
+               if (unlikely((ret)<0)) \
+                       RVE_LOG(L_WARN, rve, txt); \
+       }while(0)
+#elif defined RVAL_GET_INT_ERR_IGN
+#define rval_get_int_handle_ret(ret, txt, rve) \
+       do { \
+               if (unlikely((ret)<0)) \
+                               (ret)=0; \
+       } while(0)
+#else
+#define rval_get_int_handle_ret(ret, txt, rve) /* do nothing */
+#endif
+
+
+
+
+
+
 /** get the string value of an rv in a tmp variable
   * *s=(str)rv
   * if rv == undefined select, avp or pvar, return "".
   * if an error occurs while evaluating a select, avp or pvar, behave as
   * for the undefined case (and return success).
-  * The result points either to a temporary string or inside
-  * new_cache. new_cache must be non zero, initialized previously,
-  * and it _must_ be rval_cache_clean(...)'ed when done.
-  * WARNING: it's not intended for general use, it might return a pointer
-  * to a static buffer (int2str) so use the result a.s.a.p, make a copy.
-  * or use rval_get_str() instead.
+  * The result points either inside the passed rv, inside
+  * new_cache or inside an avp. new_cache must be non zero,
+  * initialized previously and it _must_ be rval_cache_clean(...)'ed when
+  * done.
+  * WARNING: it's not intended for general use. It might return a pointer
+  * inside rv so the result _must_ be treated as read-only. rv and new_cache
+  * must not be released/freed until the result is no longer needed.
+  * For general use see  rval_get_str().
   * @param h - script context handle
   * @param msg - sip msg
   * @param tmpv - str return value (pointer to a str struct that will be
@@ -990,26 +1109,36 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
        
        switch(rv->type){
                case RV_INT:
-                       tmpv->s=int2str(rv->v.l, &tmpv->len);
+                       tmpv->s=sint2strbuf(rv->v.l, tmp_cache->i2s,
+                                                               sizeof(tmp_cache->i2s), &tmpv->len);
+                       tmp_cache->cache_type = RV_CACHE_INT2STR;
                        break;
                case RV_STR:
                        *tmpv=rv->v.s;
                        break;
                case RV_ACTION_ST:
-                       if (rv->v.action)
-                               i=(run_actions(h, rv->v.action, msg)>0);
-                       else
+                       if (rv->v.action) {
+                               i=(run_actions_safe(h, rv->v.action, msg)>0);
+                               h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return &
+                                                                                                                   break in expr*/
+                       } else
                                i=0;
-                       tmpv->s=int2str(i, &tmpv->len);
+                       tmpv->s=sint2strbuf(i, tmp_cache->i2s,
+                                                               sizeof(tmp_cache->i2s), &tmpv->len);
+                       tmp_cache->cache_type = RV_CACHE_INT2STR;
                        break;
                case RV_BEXPR:
                        i=eval_expr(h, rv->v.bexpr, msg);
                        if (i==EXPR_DROP){
                                i=0; /* false */
-                               tmpv->s=int2str(i, &tmpv->len);
+                               tmpv->s=sint2strbuf(i, tmp_cache->i2s,
+                                               sizeof(tmp_cache->i2s), &tmpv->len);
+                               tmp_cache->cache_type = RV_CACHE_INT2STR;
                                return EXPR_DROP;
                        }
-                       tmpv->s=int2str(i, &tmpv->len);
+                       tmpv->s=sint2strbuf(i, tmp_cache->i2s, sizeof(tmp_cache->i2s),
+                                                               &tmpv->len);
+                       tmp_cache->cache_type = RV_CACHE_INT2STR;
                        break;
                case RV_SEL:
                        i=run_select(tmpv, &rv->v.sel, msg);
@@ -1027,7 +1156,9 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
                                        *tmpv=cache->c.avp_val.s;
                                }else if (cache->val_type==RV_INT){
                                        i=cache->c.avp_val.n;
-                                       tmpv->s=int2str(i, &tmpv->len);
+                                       tmpv->s=sint2strbuf(i, tmp_cache->i2s,
+                                                                               sizeof(tmp_cache->i2s), &tmpv->len);
+                                       tmp_cache->cache_type = RV_CACHE_INT2STR;
                                }else if (cache->val_type==RV_NONE){
                                        goto undef;
                                }else goto error_cache;
@@ -1042,7 +1173,9 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
                                                *tmpv=tmp_cache->c.avp_val.s;
                                        }else{
                                                i=tmp_cache->c.avp_val.n;
-                                               tmpv->s=int2str(i, &tmpv->len);
+                                               tmpv->s=sint2strbuf(i, tmp_cache->i2s,
+                                                                               sizeof(tmp_cache->i2s), &tmpv->len);
+                                               tmp_cache->cache_type = RV_CACHE_INT2STR;
                                        }
                                }else goto undef;
                        }
@@ -1053,7 +1186,9 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
                                        *tmpv=cache->c.pval.rs;
                                }else if (cache->val_type==RV_INT){
                                        i=cache->c.pval.ri;
-                                       tmpv->s=int2str(i, &tmpv->len);
+                                       tmpv->s=sint2strbuf(i, tmp_cache->i2s,
+                                                                               sizeof(tmp_cache->i2s), &tmpv->len);
+                                       tmp_cache->cache_type = RV_CACHE_INT2STR;
                                }else if (cache->val_type==RV_NONE){
                                        goto undef;
                                }else goto error_cache;
@@ -1071,7 +1206,9 @@ int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
                                        }else if (likely(tmp_cache->c.pval.flags & PV_VAL_INT)){
                                                i=tmp_cache->c.pval.ri;
                                                pv_value_destroy(&tmp_cache->c.pval);
-                                               tmpv->s=int2str(i, &tmpv->len);
+                                               tmpv->s=sint2strbuf(i, tmp_cache->i2s,
+                                                                               sizeof(tmp_cache->i2s), &tmpv->len);
+                                               tmp_cache->cache_type = RV_CACHE_INT2STR;
                                        }else{
                                                /* no PV_VAL_STR and no PV_VAL_INT => undef
                                                   (PV_VAL_NULL) */
@@ -1137,18 +1274,22 @@ error:
 
 
 
-/** convert a rvalue to another rvalue, of a specific type.
+/**
+ * @brief Convert a rvalue to another rvalue, of a specific type
  *
+ * Convert a rvalue to another rvalue, of a specific type.
  * The result is read-only in most cases (can be a reference
  * to another rvalue, can be checked by using rv_chg_in_place()) and
  * _must_ be rval_destroy()'ed.
  *
+ * @param h run action context
+ * @param msg SIP mesasge
  * @param type - type to convert to
  * @param v - rvalue to convert
  * @param c - rval_cache (cached v value if known/filled by another
  *            function), can be 0 (unknown/not needed)
  * @return pointer to a rvalue (reference to an existing one or a new
- *   one, @see rv_chg_in_place() and the above comment) or 0 on error.
+ * one, @see rv_chg_in_place() and the above comment), or 0 on error.
  */
 struct rvalue* rval_convert(struct run_act_ctx* h, struct sip_msg* msg,
                                                        enum rval_type type, struct rvalue* v,
@@ -1205,6 +1346,9 @@ inline static int int_intop1(int* res, enum rval_expr_op op, int v)
                case RVE_LNOT_OP:
                        *res=!v;
                        break;
+               case RVE_BNOT_OP:
+                       *res=~v;
+                       break;
                default:
                        BUG("rv unsupported intop1 %d\n", op);
                        return -1;
@@ -1250,6 +1394,15 @@ inline static int int_intop2(int* res, enum rval_expr_op op, int v1, int v2)
                case RVE_BAND_OP:
                        *res=v1&v2;
                        break;
+               case RVE_BXOR_OP:
+                       *res=v1^v2;
+                       break;
+               case RVE_BLSHIFT_OP:
+                       *res=v1<<v2;
+                       break;
+               case RVE_BRSHIFT_OP:
+                       *res=v1>>v2;
+                       break;
                case RVE_LAND_OP:
                        *res=v1 && v2;
                        break;
@@ -1612,9 +1765,17 @@ error:
 
 
 
-/** integer operation on rval evaluated as string.
- * Can use cached rvalues (c1 & c2).
- * @param res - will be set to the result
+/**
+ * @brief Integer operation on rval evaluated as string
+ * 
+ * Integer operation on rval evaluated as string, can use cached
+ * rvalues (c1 & c2).
+ * @param h run action context
+ * @param msg SIP message
+ * @param res will be set to the result
+ * @param op rvalue expression operation
+ * @param l rvalue
+ * @param c1 rvalue cache
  * @return 0 success, -1 on error
  */
 inline static int rval_int_strop1(struct run_act_ctx* h,
@@ -1642,14 +1803,18 @@ error:
 
 
 
-/** checks if rv is defined.
- * @param res - set to the result 1 - defined, 0 not defined
+/**
+ * @brief Checks if rv is defined
+ * @param h run action context
+ * @param msg SIP message
+ * @param res set to the result 1 is defined, 0 not defined
+ * @param rv rvalue
+ * @param cache rvalue cache
  * @return 0 on success, -1 on error
- * 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)
+ * @note Can use cached rvalues (cache). A rv can be undefined if it's
+ * an undefined avp or pvar or select or if it's NONE
+ * @note 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,
@@ -1708,9 +1873,13 @@ inline static int rv_defined(struct run_act_ctx* h,
 }
 
 
-/** defined (integer) operation on rve.
+/**
+ * @brief Defined (integer) operation on rve
+ * @param h run action context
+ * @param msg SIP message
  * @param res - set to  1 defined, 0 not defined
- * @return - 0 on success, -1 on error
+ * @param rve rvalue expression
+ * @return 0 on success, -1 on error
  */
 inline static int int_rve_defined(struct run_act_ctx* h,
                                                 struct sip_msg* msg, int* res,
@@ -1743,10 +1912,13 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
        switch(rve->op){
                case RVE_RVAL_OP:
                        ret=rval_get_int(h, msg, res,  &rve->left.rval, 0);
+                       rval_get_int_handle_ret(ret, "rval expression conversion to int"
+                                                                               " failed", rve);
                        break;
                case RVE_UMINUS_OP:
                case RVE_BOOL_OP:
                case RVE_LNOT_OP:
+               case RVE_BNOT_OP:
                        if (unlikely(
                                        (ret=rval_expr_eval_int(h, msg, &i1, rve->left.rve)) <0) )
                                break;
@@ -1763,6 +1935,9 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
                case RVE_IPLUS_OP:
                case RVE_BOR_OP:
                case RVE_BAND_OP:
+               case RVE_BXOR_OP:
+               case RVE_BLSHIFT_OP:
+               case RVE_BRSHIFT_OP:
                case RVE_GT_OP:
                case RVE_GTE_OP:
                case RVE_LT_OP:
@@ -1870,7 +2045,7 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
 #endif /* UNDEF_EQ_* */
                                        rval_cache_clean(&c1);
                                        rval_destroy(rv1);
-                               }else{ 
+                               }else{
                                        /* left value == defined and != int => str
                                         * => lval == (str) val */
                                        if (unlikely((rv2=rval_expr_eval(h, msg,
@@ -1893,8 +2068,10 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
                                ret=-1;
                                break;
                        }
-                       /* conver to int */
+                       /* convert to int */
                        ret=rval_get_int(h, msg, res, rv1, 0); /* convert to int */
+                       rval_get_int_handle_ret(ret, "rval expression conversion to int"
+                                                                               " failed", rve);
                        rval_destroy(rv1);
                        break;
                case RVE_STR_OP:
@@ -1909,6 +2086,8 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
                        if (unlikely(rv1)){
                                /* expr evaluated to string => (int)(str)v == (int)v */
                                ret=rval_get_int(h, msg, res, rv1, &c1); /* convert to int */
+                               rval_get_int_handle_ret(ret, "rval expression conversion"
+                                                                                               " to int failed", rve);
                                rval_destroy(rv1);
                                rval_cache_clean(&c1);
                        } /* else (rv1==0)
@@ -1960,7 +2139,9 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
                        break;
                case RVE_NONE_OP:
                /*default:*/
-                       BUG("invalid rval int expression operation %d\n", rve->op);
+                       BUG("invalid rval int expression operation %d (%d,%d-%d,%d)\n",
+                                       rve->op, rve->fpos.s_line, rve->fpos.s_col,
+                                       rve->fpos.e_line, rve->fpos.e_col);
                        ret=-1;
        };
        return ret;
@@ -1968,22 +2149,22 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
 
 
 
-/** evals a rval expr. into an int or another rv(str).
- * WARNING: rv result (rv_res) must be rval_destroy()'ed if non-null
+/**
+ * @brief Evals a rval expression into an int or another rv(str)
+ * @warning rv result (rv_res) must be rval_destroy()'ed if non-null
  * (it might be a reference to another rval). The result can be
  * modified only if rv_chg_in_place() returns true.
- * @param res_rv - pointer to rvalue result, if non-null it means the 
- *                 expression evaluated to a non-int (str), which will be
- *                 stored here.
- * @param res_i  - pointer to int result, if res_rv==0 and the function
- *                 returns success => the result is an int which will be 
- *                 stored here.
- * @param rve    - expression that will be evaluated.
- * @param cache  - write-only value cache, it might be filled if non-null and
- *                 empty (rval_cache_init()). If non-null, it _must_ be 
- *                 rval_cache_clean()'ed when done. 
- *
- * @result  0 on success, -1 on error,  sets *res_rv or *res_i.
+ * @param h run action context
+ * @param msg SIP message
+ * @param res_rv pointer to rvalue result, if non-null it means the 
+ * expression evaluated to a non-int (str), which will be stored here.
+ * @param res_i pointer to int result, if res_rv==0 and the function
+ * returns success => the result is an int which will be stored here.
+ * @param rve expression that will be evaluated.
+ * @param cache write-only value cache, it might be filled if non-null and
+ * empty (rval_cache_init()). If non-null, it _must_ be rval_cache_clean()'ed
+ * when done. 
+ * @return 0 on success, -1 on error, sets *res_rv or *res_i.
  */
 int rval_expr_eval_rvint(                         struct run_act_ctx* h,
                                                                           struct sip_msg* msg,
@@ -2010,12 +2191,10 @@ int rval_expr_eval_rvint(                          struct run_act_ctx* h,
                        type=rval_get_btype(h, msg, rv1, cache);
                        if (type==RV_INT){
                                        r=rval_get_int(h, msg, res_i, rv1, cache);
-                                       if (unlikely(r<0)){
-                                               ERR("rval expression evaluation failed\n");
-                                               goto error;
-                                       }
+                                       rval_get_int_handle_ret(r, "rval expression conversion"
+                                                                                               " to int failed", rve);
                                        *res_rv=0;
-                                       ret=0;
+                                       ret=r; /* equiv. to if (r<0) goto error */
                        }else{
                                /* RV_STR, RV_PVAR, RV_AVP a.s.o => return rv1 and the 
                                   cached resolved value in cache*/
@@ -2027,12 +2206,16 @@ int rval_expr_eval_rvint(                          struct run_act_ctx* h,
                case RVE_UMINUS_OP:
                case RVE_BOOL_OP:
                case RVE_LNOT_OP:
+               case RVE_BNOT_OP:
                case RVE_MINUS_OP:
                case RVE_MUL_OP:
                case RVE_DIV_OP:
                case RVE_MOD_OP:
                case RVE_BOR_OP:
                case RVE_BAND_OP:
+               case RVE_BXOR_OP:
+               case RVE_BLSHIFT_OP:
+               case RVE_BRSHIFT_OP:
                case RVE_LAND_OP:
                case RVE_LOR_OP:
                case RVE_GT_OP:
@@ -2059,14 +2242,21 @@ int rval_expr_eval_rvint(                          struct run_act_ctx* h,
                        rval_cache_init(&c1);
                        r=rval_expr_eval_rvint(h, msg, &rv1, &i, rve->left.rve, &c1);
                        if (unlikely(r<0)){
-                               ERR("rval expression evaluation failed\n");
+                               ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
+                                               rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
+                                               rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col
+                                       );
                                rval_cache_clean(&c1);
                                goto error;
                        }
                        if (rv1==0){
                                if (unlikely((r=rval_expr_eval_int(h, msg, &j,
                                                                                                                rve->right.rve))<0)){
-                                               ERR("rval expression evaluation failed\n");
+                                               ERR("rval expression evaluation failed (%d,%d-%d,%d)"
+                                                               "\n", rve->right.rve->fpos.s_line,
+                                                               rve->right.rve->fpos.s_col,
+                                                               rve->right.rve->fpos.e_line,
+                                                               rve->right.rve->fpos.e_col);
                                                rval_cache_clean(&c1);
                                                goto error;
                                }
@@ -2075,7 +2265,11 @@ int rval_expr_eval_rvint(                           struct run_act_ctx* h,
                        }else{
                                rv2=rval_expr_eval(h, msg, rve->right.rve);
                                if (unlikely(rv2==0)){
-                                       ERR("rval expression evaluation failed\n");
+                                       ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
+                                                               rve->right.rve->fpos.s_line,
+                                                               rve->right.rve->fpos.s_col,
+                                                               rve->right.rve->fpos.e_line,
+                                                               rve->right.rve->fpos.e_col);
                                        rval_cache_clean(&c1);
                                        goto error;
                                }
@@ -2091,7 +2285,9 @@ int rval_expr_eval_rvint(                    struct run_act_ctx* h,
                        break;
                case RVE_NONE_OP:
                /*default:*/
-                       BUG("invalid rval expression operation %d\n", rve->op);
+                       BUG("invalid rval expression operation %d (%d,%d-%d,%d)\n",
+                                       rve->op, rve->fpos.s_line, rve->fpos.s_col,
+                                       rve->fpos.e_line, rve->fpos.e_col);
                        goto error;
        };
        rval_destroy(rv1);
@@ -2105,10 +2301,14 @@ error:
 
 
 
-/** evals a rval expr..
- * WARNING: result must be rval_destroy()'ed if non-null (it might be
+/**
+ * @brief Evals a rval expression
+ * @warning result must be rval_destroy()'ed if non-null (it might be
  * a reference to another rval). The result can be modified only
  * if rv_chg_in_place() returns true.
+ * @param h run action context
+ * @param msg SIP message
+ * @param rve rvalue expression
  * @return rvalue on success, 0 on error
  */
 struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
@@ -2133,12 +2333,16 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
                case RVE_UMINUS_OP:
                case RVE_BOOL_OP:
                case RVE_LNOT_OP:
+               case RVE_BNOT_OP:
                case RVE_MINUS_OP:
                case RVE_MUL_OP:
                case RVE_DIV_OP:
                case RVE_MOD_OP:
                case RVE_BOR_OP:
                case RVE_BAND_OP:
+               case RVE_BXOR_OP:
+               case RVE_BLSHIFT_OP:
+               case RVE_BRSHIFT_OP:
                case RVE_LAND_OP:
                case RVE_LOR_OP:
                case RVE_GT_OP:
@@ -2168,29 +2372,39 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
                                }
                                return ret;
                        }else{
-                               ERR("rval expression evaluation failed\n");
+                               ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
+                                               rve->fpos.s_line, rve->fpos.s_col,
+                                               rve->fpos.e_line, rve->fpos.e_col);
                                goto error;
                        }
                        break;
                case RVE_PLUS_OP:
                        rv1=rval_expr_eval(h, msg, rve->left.rve);
                        if (unlikely(rv1==0)){
-                               ERR("rval expression evaluation failed\n");
+                               ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
+                                               rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
+                                               rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col);
                                goto error;
                        }
                        rval_cache_init(&c1);
                        type=rval_get_btype(h, msg, rv1, &c1);
                        switch(type){
                                case RV_INT:
-                                       if (unlikely((r=rval_get_int(h, msg, &i, rv1, &c1))<0)){
+                                       r=rval_get_int(h, msg, &i, rv1, &c1);
+                                       rval_get_int_handle_ret(r, "rval expression left side "
+                                                                                               "conversion to int failed",
+                                                                                       rve);
+                                       if (unlikely(r<0)){
                                                rval_cache_clean(&c1);
-                                               ERR("rval expression evaluation failed\n");
                                                goto error;
                                        }
                                        if (unlikely((r=rval_expr_eval_int(h, msg, &j,
                                                                                                                rve->right.rve))<0)){
                                                rval_cache_clean(&c1);
-                                               ERR("rval expression evaluation failed\n");
+                                               ERR("rval expression evaluation failed (%d,%d-%d,%d):"
+                                                               " could not evaluate right side to int\n",
+                                                               rve->fpos.s_line, rve->fpos.s_col,
+                                                               rve->fpos.e_line, rve->fpos.e_col);
                                                goto error;
                                        }
                                        int_intop2(&r, rve->op, i, j);
@@ -2212,26 +2426,38 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
                                case RV_NONE:
                                        rv2=rval_expr_eval(h, msg, rve->right.rve);
                                        if (unlikely(rv2==0)){
-                                               ERR("rval expression evaluation failed\n");
+                                               ERR("rval expression evaluation failed (%d,%d-%d,%d)"
+                                                               "\n", rve->right.rve->fpos.s_line,
+                                                               rve->right.rve->fpos.s_col,
+                                                               rve->right.rve->fpos.e_line,
+                                                               rve->right.rve->fpos.e_col);
                                                rval_cache_clean(&c1);
                                                goto error;
                                        }
                                        ret=rval_str_add2(h, msg, rv1, &c1, rv2, 0);
                                        break;
                                default:
-                                       BUG("rv unsupported basic type %d\n", type);
+                                       BUG("rv unsupported basic type %d (%d,%d-%d,%d)\n", type,
+                                                       rve->fpos.s_line, rve->fpos.s_col,
+                                                       rve->fpos.e_line, rve->fpos.e_col);
                        }
                        rval_cache_clean(&c1);
                        break;
                case RVE_CONCAT_OP:
                        rv1=rval_expr_eval(h, msg, rve->left.rve);
                        if (unlikely(rv1==0)){
-                               ERR("rval expression evaluation failed\n");
+                               ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
+                                               rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
+                                               rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col);
                                goto error;
                        }
                        rv2=rval_expr_eval(h, msg, rve->right.rve);
                        if (unlikely(rv2==0)){
-                               ERR("rval expression evaluation failed\n");
+                               ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
+                                               rve->right.rve->fpos.s_line,
+                                               rve->right.rve->fpos.s_col,
+                                               rve->right.rve->fpos.e_line,
+                                               rve->right.rve->fpos.e_col);
                                goto error;
                        }
                        ret=rval_str_add2(h, msg, rv1, 0, rv2, 0);
@@ -2239,14 +2465,18 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
                case RVE_STR_OP:
                        rv1=rval_expr_eval(h, msg, rve->left.rve);
                        if (unlikely(rv1==0)){
-                               ERR("rval expression evaluation failed\n");
+                               ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
+                                               rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
+                                               rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col);
                                goto error;
                        }
                        ret=rval_convert(h, msg, RV_STR, rv1, 0);
                        break;
                case RVE_NONE_OP:
                /*default:*/
-                       BUG("invalid rval expression operation %d\n", rve->op);
+                       BUG("invalid rval expression operation %d (%d,%d-%d,%d)\n",
+                                       rve->op, rve->fpos.s_line, rve->fpos.s_col,
+                                       rve->fpos.e_line, rve->fpos.e_col);
                        goto error;
        };
        rval_destroy(rv1);
@@ -2304,7 +2534,7 @@ struct rval_expr* mk_rval_expr_v(enum rval_type rv_type, void* val,
        rve=pkg_malloc(sizeof(*rve));
        if (rve==0) 
                return 0;
-       memset(rve, sizeof(*rve), 0);
+       memset(rve, 0, sizeof(*rve));
        flags=0;
        switch(rv_type){
                case RV_INT:
@@ -2350,10 +2580,12 @@ struct rval_expr* mk_rval_expr_v(enum rval_type rv_type, void* val,
 
 
 
-/** create a unary op. rval_expr..
+/**
+ * @brief Create a unary op. rval_expr
  * ret= op rve1
  * @param op   - rval expr. unary operator
  * @param rve1 - rval expr. on which the operator will act.
+ * @param pos configuration position
  * @return new pkg_malloc'ed rval_expr or 0 on error.
  */
 struct rval_expr* mk_rval_expr1(enum rval_expr_op op, struct rval_expr* rve1,
@@ -2365,6 +2597,7 @@ struct rval_expr* mk_rval_expr1(enum rval_expr_op op, struct rval_expr* rve1,
                case RVE_UMINUS_OP:
                case RVE_BOOL_OP:
                case RVE_LNOT_OP:
+               case RVE_BNOT_OP:
                case RVE_STRLEN_OP:
                case RVE_STREMPTY_OP:
                case RVE_DEFINED_OP:
@@ -2378,7 +2611,7 @@ struct rval_expr* mk_rval_expr1(enum rval_expr_op op, struct rval_expr* rve1,
        ret=pkg_malloc(sizeof(*ret));
        if (ret==0) 
                return 0;
-       memset(ret, sizeof(*ret), 0);
+       memset(ret, 0, sizeof(*ret));
        ret->op=op;
        ret->left.rve=rve1;
        if (pos) ret->fpos=*pos;
@@ -2387,11 +2620,13 @@ struct rval_expr* mk_rval_expr1(enum rval_expr_op op, struct rval_expr* rve1,
 
 
 
-/** create a rval_expr. from 2 other rval exprs, using op.
+/**
+ * @brief Create a rval_expr. from 2 other rval exprs, using op
  * ret = rve1 op rve2
  * @param op   - rval expr. operator
  * @param rve1 - rval expr. on which the operator will act.
  * @param rve2 - rval expr. on which the operator will act.
+ * @param pos configuration position
  * @return new pkg_malloc'ed rval_expr or 0 on error.
  */
 struct rval_expr* mk_rval_expr2(enum rval_expr_op op, struct rval_expr* rve1,
@@ -2407,6 +2642,9 @@ struct rval_expr* mk_rval_expr2(enum rval_expr_op op, struct rval_expr* rve1,
                case RVE_MINUS_OP:
                case RVE_BOR_OP:
                case RVE_BAND_OP:
+               case RVE_BXOR_OP:
+               case RVE_BLSHIFT_OP:
+               case RVE_BRSHIFT_OP:
                case RVE_LAND_OP:
                case RVE_LOR_OP:
                case RVE_GT_OP:
@@ -2431,7 +2669,7 @@ struct rval_expr* mk_rval_expr2(enum rval_expr_op op, struct rval_expr* rve1,
        ret=pkg_malloc(sizeof(*ret));
        if (ret==0) 
                return 0;
-       memset(ret, sizeof(*ret), 0);
+       memset(ret, 0, sizeof(*ret));
        ret->op=op;
        ret->left.rve=rve1;
        ret->right.rve=rve2;
@@ -2450,6 +2688,7 @@ static int rve_op_is_assoc(enum rval_expr_op op)
                case RVE_UMINUS_OP:
                case RVE_BOOL_OP:
                case RVE_LNOT_OP:
+               case RVE_BNOT_OP:
                case RVE_STRLEN_OP:
                case RVE_STREMPTY_OP:
                case RVE_DEFINED_OP:
@@ -2460,6 +2699,8 @@ static int rve_op_is_assoc(enum rval_expr_op op)
                case RVE_DIV_OP:
                case RVE_MOD_OP:
                case RVE_MINUS_OP:
+               case RVE_BLSHIFT_OP:
+               case RVE_BRSHIFT_OP:
                        return 0;
                case RVE_PLUS_OP:
                        /* the generic plus is not assoc, e.g.
@@ -2470,6 +2711,7 @@ static int rve_op_is_assoc(enum rval_expr_op op)
                case RVE_MUL_OP:
                case RVE_BAND_OP:
                case RVE_BOR_OP:
+               case RVE_BXOR_OP:
                        return 1;
                case RVE_LAND_OP:
                case RVE_LOR_OP:
@@ -2501,6 +2743,7 @@ static int rve_op_is_commutative(enum rval_expr_op op)
                case RVE_UMINUS_OP:
                case RVE_BOOL_OP:
                case RVE_LNOT_OP:
+               case RVE_BNOT_OP:
                case RVE_STRLEN_OP:
                case RVE_STREMPTY_OP:
                case RVE_DEFINED_OP:
@@ -2511,6 +2754,8 @@ static int rve_op_is_commutative(enum rval_expr_op op)
                case RVE_DIV_OP:
                case RVE_MOD_OP:
                case RVE_MINUS_OP:
+               case RVE_BLSHIFT_OP:
+               case RVE_BRSHIFT_OP:
                        return 0;
                case RVE_PLUS_OP:
                        /* non commut. when diff. type 
@@ -2521,6 +2766,7 @@ static int rve_op_is_commutative(enum rval_expr_op op)
                case RVE_MUL_OP:
                case RVE_BAND_OP:
                case RVE_BOR_OP:
+               case RVE_BXOR_OP:
                case RVE_LAND_OP:
                case RVE_LOR_OP:
                case RVE_IEQ_OP:
@@ -2624,7 +2870,7 @@ static int fix_rval(struct rvalue* rv)
                        return fix_actions(rv->v.action);
                case RV_SEL:
                        if (resolve_select(&rv->v.sel)<0){
-                               BUG("Unable to resolve select\n");
+                               ERR("Unable to resolve select\n");
                                print_select(&rv->v.sel);
                        }
                        return 0;
@@ -2644,15 +2890,17 @@ static int fix_rval(struct rvalue* rv)
 
 
 
-/** helper function: replace a rve (in-place) with a constant rval_val.
- * WARNING: since it replaces in-place, one should make sure that if
+/**
+ * @brief Helper function: replace a rve (in-place) with a constant rval_val
+ * @warning since it replaces in-place, one should make sure that if
  * rve is in fact a rval (rve->op==RVE_RVAL_OP), no reference is kept
  * to the rval!
- * @param rve - expression to be replaced (in-place)
- * @param v   - pointer to a rval_val union containing the replacement
- *              value.
- * @param flags - value flags (how it was alloc'ed, e.g.: RV_CNT_ALLOCED_F)
- * @return 0 on success, -1 on error */
+ * @param rve expression to be replaced (in-place)
+ * @param type rvalue type
+ * @param v pointer to a rval_val union containing the replacement value.
+ * @param flags value flags (how it was alloc'ed, e.g.: RV_CNT_ALLOCED_F)
+ * @return 0 on success, -1 on error
+ */
 static int rve_replace_with_val(struct rval_expr* rve, enum rval_type type,
                                                                union rval_val* v, int flags)
 {
@@ -2697,18 +2945,24 @@ static int rve_replace_with_ct_rv(struct rval_expr* rve, struct rvalue* rv)
        flags=0;
        if (rv->type==RV_INT){
                if (rval_get_int(0, 0, &i, rv, 0)!=0){
-                       BUG("unexpected int evaluation failure\n");
+                       BUG("unexpected int evaluation failure (%d,%d-%d,%d)\n",
+                                       rve->fpos.s_line, rve->fpos.s_col,
+                                       rve->fpos.e_line, rve->fpos.e_col);
                        return -1;
                }
                v.l=i;
        }else if(rv->type==RV_STR){
                if (rval_get_str(0, 0, &v.s, rv, 0)<0){
-                       BUG("unexpected str evaluation failure\n");
+                       BUG("unexpected str evaluation failure(%d,%d-%d,%d)\n",
+                                       rve->fpos.s_line, rve->fpos.s_col,
+                                       rve->fpos.e_line, rve->fpos.e_col);
                        return -1;
                }
                flags|=RV_CNT_ALLOCED_F;
        }else{
-               BUG("unknown constant expression type %d\n", rv->type);
+               BUG("unknown constant expression type %d (%d,%d-%d,%d)\n", rv->type,
+                               rve->fpos.s_line, rve->fpos.s_col,
+                               rve->fpos.e_line, rve->fpos.e_col);
                return -1;
        }
        return rve_replace_with_val(rve, type, &v, flags);
@@ -2731,7 +2985,7 @@ static int fix_match_rve(struct rval_expr* rve)
        v.s.s=0;
        v.re.regex=0;
        /* normal fix-up for the  left side */
-       ret=fix_rval_expr((void**)&rve->left.rve);
+       ret=fix_rval_expr((void*)rve->left.rve);
        if (ret<0) return ret;
        
        /* fixup the right side (RE) */
@@ -2778,7 +3032,7 @@ static int fix_match_rve(struct rval_expr* rve)
                        goto error;
        }else{
                /* right side is not constant => normal fixup */
-               return fix_rval_expr((void**)&rve->right.rve);
+               return fix_rval_expr((void*)rve->right.rve);
        }
        return 0;
 error:
@@ -2862,7 +3116,9 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
           referencing a ct_rve->left.rval if ct_rve is a rval, which
           would prevent rve_destroy(ct_rve) from working */
        if ((rv=rval_expr_eval_new(0, 0, ct_rve))==0){
-               ERR("optimization failure, bad expression\n");
+               ERR("optimization failure, bad expression (%d,%d-%d,%d)\n",
+                               ct_rve->fpos.s_line, ct_rve->fpos.s_col,
+                               ct_rve->fpos.e_line, ct_rve->fpos.e_col);
                goto error;
        }
        op=rve->op;
@@ -3198,14 +3454,12 @@ static int rve_optimize(struct rval_expr* rve)
        struct rvalue* rv;
        struct rvalue* trv; /* used only for DBG() */
        enum rval_expr_op op;
-       int flags;
        struct rval_expr tmp_rve;
        enum rval_type type, l_type;
        struct rval_expr* bad_rve;
        enum rval_type bad_type, exp_type;
        
        ret=0;
-       flags=0;
        rv=0;
        if (scr_opt_lev<1)
                return 0;
@@ -3213,7 +3467,9 @@ static int rve_optimize(struct rval_expr* rve)
                return 0;
        if (rve_is_constant(rve)){
                if ((rv=rval_expr_eval_new(0, 0, rve))==0){
-                       ERR("optimization failure, bad expression\n");
+                       ERR("optimization failure, bad expression (%d,%d-%d,%d)\n",
+                                       rve->fpos.s_line, rve->fpos.s_col,
+                                       rve->fpos.e_line, rve->fpos.e_col);
                        goto error;
                }
                op=rve->op;
@@ -3256,7 +3512,11 @@ static int rve_optimize(struct rval_expr* rve)
                /* $v - a => $v + (-a)  (easier to optimize)*/
                if ((rve->op==RVE_MINUS_OP) && (rve_is_constant(rve->right.rve))){
                        if ((rv=rval_expr_eval_new(0, 0, rve->right.rve))==0){
-                               ERR("optimization failure, bad expression\n");
+                               ERR("optimization failure, bad expression (%d,%d-%d,%d)\n",
+                                                               rve->right.rve->fpos.s_line,
+                                                               rve->right.rve->fpos.s_col,
+                                                               rve->right.rve->fpos.e_line,
+                                                               rve->right.rve->fpos.e_col);
                                goto error;
                        }
                        if (rv->type==RV_INT){
@@ -3512,19 +3772,16 @@ error:
 /** fix a rval_expr.
  * fixes action, bexprs, resolves selects, pvars and
  * optimizes simple sub expressions (e.g. 1+2).
- * It might modify *p.
  *
- * @param p - double pointer to a rval_expr (might be changed to a new one)
- * @return 0 on success, <0 on error (modifies also *p)
+ * @param p - pointer to a rval_expr
+ * @return 0 on success, <0 on error (modifies also *(struct rval_expr*)p)
  */
-int fix_rval_expr(void** p)
+int fix_rval_expr(void* p)
 {
-       struct rval_expr** prve;
        struct rval_expr* rve;
        int ret;
        
-       prve=(struct rval_expr**)p;
-       rve=*prve;
+       rve=(struct rval_expr*)p;
        
        switch(rve->op){
                case RVE_NONE_OP:
@@ -3535,12 +3792,13 @@ int fix_rval_expr(void** p)
                case RVE_UMINUS_OP: /* unary operators */
                case RVE_BOOL_OP:
                case RVE_LNOT_OP:
+               case RVE_BNOT_OP:
                case RVE_STRLEN_OP:
                case RVE_STREMPTY_OP:
                case RVE_DEFINED_OP:
                case RVE_INT_OP:
                case RVE_STR_OP:
-                       ret=fix_rval_expr((void**)&rve->left.rve);
+                       ret=fix_rval_expr((void*)rve->left.rve);
                        if (ret<0) return ret;
                        break;
                case RVE_MUL_OP:
@@ -3549,6 +3807,9 @@ int fix_rval_expr(void** p)
                case RVE_MINUS_OP:
                case RVE_BOR_OP:
                case RVE_BAND_OP:
+               case RVE_BXOR_OP:
+               case RVE_BLSHIFT_OP:
+               case RVE_BRSHIFT_OP:
                case RVE_LAND_OP:
                case RVE_LOR_OP:
                case RVE_GT_OP:
@@ -3564,9 +3825,9 @@ int fix_rval_expr(void** p)
                case RVE_STREQ_OP:
                case RVE_STRDIFF_OP:
                case RVE_CONCAT_OP:
-                       ret=fix_rval_expr((void**)&rve->left.rve);
+                       ret=fix_rval_expr((void*)rve->left.rve);
                        if (ret<0) return ret;
-                       ret=fix_rval_expr((void**)&rve->right.rve);
+                       ret=fix_rval_expr((void*)rve->right.rve);
                        if (ret<0) return ret;
                        break;
                case RVE_MATCH_OP: