Module: sip-router
Branch: andrei/script_vars
Commit: 70341d3b4f46c8a6bdbbdfcb314f01cee08a226d
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=70341d3…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Mon Dec 15 21:22:09 2008 +0100
script engine: rve_check_type() extended
- extended rve_check_type() to return also the subexpression for
which the check failed, its type and the expected type.
---
rvalue.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++----------
rvalue.h | 6 +++-
2 files changed, 90 insertions(+), 17 deletions(-)
diff --git a/rvalue.c b/rvalue.c
index ed73baf..c637dec 100644
--- a/rvalue.c
+++ b/rvalue.c
@@ -191,6 +191,36 @@ struct rvalue* rval_new_str(str* s, int extra_size)
+/** get string name for a type.
+ *
+ * @return - null terminated name of the type
+ */
+char* rval_type_name(enum rval_type type)
+{
+ switch(type){
+ case RV_NONE:
+ return "none";
+ case RV_INT:
+ return "int";
+ case RV_STR:
+ return "str";
+ case RV_BEXPR:
+ return "bexpr_t";
+ case RV_ACTION_ST:
+ return "action_t";
+ case RV_PVAR:
+ return "pvar";
+ case RV_AVP:
+ return "avp";
+ break;
+ case RV_SEL:
+ return "select";
+ }
+ return "error_unkown_type";
+}
+
+
+
/** create a new pk_malloc'ed rvalue from a rval_val union.
*
* @param s - pointer to str, must be non-null
@@ -242,7 +272,7 @@ inline static enum rval_type rval_get_btype(struct run_act_ctx* h,
pv_value_t* pv;
enum rval_type tmp;
enum rval_type* ptype;
-
+
switch(rv->type){
case RV_INT:
case RV_STR:
@@ -454,10 +484,21 @@ 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)
*/
-int rve_check_type(enum rval_type* type, struct rval_expr* rve)
+int rve_check_type(enum rval_type* type, struct rval_expr* rve,
+ struct rval_expr** bad_rve,
+ enum rval_type* bad_t,
+ enum rval_type* exp_t)
{
enum rval_type type1, type2;
@@ -469,9 +510,13 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve)
case RVE_BOOL_OP:
case RVE_LNOT_OP:
*type=RV_INT;
- if (rve_check_type(&type1, rve->left.rve)){
- if (type1==RV_STR)
+ if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
+ if (type1==RV_STR){
+ if (bad_rve) *bad_rve=rve->left.rve;
+ if (bad_t) *bad_t=type1;
+ if (exp_t) *exp_t=RV_INT;
return 0;
+ }
return 1;
}
return 0;
@@ -488,12 +533,21 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve)
case RVE_LT_OP:
case RVE_LTE_OP:
*type=RV_INT;
- if (rve_check_type(&type1, rve->left.rve)){
- if (type1==RV_STR)
+ if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
+ if (type1==RV_STR){
+ if (bad_rve) *bad_rve=rve->left.rve;
+ if (bad_t) *bad_t=type1;
+ if (exp_t) *exp_t=RV_INT;
return 0;
- if (rve_check_type(&type2, rve->right.rve)){
- if (type2==RV_STR)
+ }
+ if (rve_check_type(&type2, rve->right.rve, bad_rve,
+ bad_t, exp_t)){
+ if (type2==RV_STR){
+ if (bad_rve) *bad_rve=rve->left.rve;
+ if (bad_t) *bad_t=type2;
+ if (exp_t) *exp_t=RV_INT;
return 0;
+ }
return 1;
}
}
@@ -501,23 +555,34 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve)
case RVE_EQ_OP:
case RVE_DIFF_OP:
*type=RV_INT;
- if (rve_check_type(&type1, rve->left.rve)){
- if (rve_check_type(&type2, rve->right.rve)){
+ if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
+ if (rve_check_type(&type2, rve->right.rve, bad_rve, bad_t,
+ exp_t)){
if ((type2!=type1) && (type1!=RV_NONE) &&
(type2!=RV_NONE) &&
- !(type1==RV_STR && type2==RV_INT))
+ !(type1==RV_STR && type2==RV_INT)){
+ if (bad_rve) *bad_rve=rve->right.rve;
+ if (bad_t) *bad_t=type2;
+ if (exp_t) *exp_t=type1;
return 0;
+ }
return 1;
}
}
return 0;
case RVE_PLUS_OP:
- if (rve_check_type(&type1, rve->left.rve)){
- if (rve_check_type(&type2, rve->right.rve)){
+ *type=RV_NONE;
+ if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
+ if (rve_check_type(&type2, rve->right.rve, bad_rve, bad_t,
+ exp_t)){
if ((type2!=type1) && (type1!=RV_NONE) &&
(type2!=RV_NONE) &&
- !(type1==RV_STR && type2==RV_INT))
+ !(type1==RV_STR && type2==RV_INT)){
+ if (bad_rve) *bad_rve=rve->right.rve;
+ if (bad_t) *bad_t=type2;
+ if (exp_t) *exp_t=type1;
return 0;
+ }
*type=type1;
return 1;
}
@@ -1879,6 +1944,8 @@ static int rve_optimize(struct rval_expr* rve)
int flags;
struct rval_expr tmp_rve;
enum rval_type type;
+ struct rval_expr* bad_rve;
+ enum rval_type bad_type, exp_type;
ret=0;
flags=0;
@@ -1912,8 +1979,10 @@ static int rve_optimize(struct rval_expr* rve)
return rve_optimize(rve->left.rve);
rve_optimize(rve->left.rve);
rve_optimize(rve->right.rve);
- if (!rve_check_type(&type, rve)){
- ERR("optimization failure, type mismatch in expression\n");
+ if (!rve_check_type(&type, rve, &bad_rve, &bad_type, &exp_type)){
+ ERR("optimization failure, type mismatch in expression, "
+ "type %s, but expected %s\n",
+ rval_type_name(bad_type), rval_type_name(exp_type));
return 0;
}
/* TODO: $v - a => $v + (-a) */
diff --git a/rvalue.h b/rvalue.h
index faa6143..5a1c10b 100644
--- a/rvalue.h
+++ b/rvalue.h
@@ -185,7 +185,11 @@ enum rval_type rve_guess_type(struct rval_expr* rve);
/** returns true if expression is constant. */
int rve_is_constant(struct rval_expr* rve);
/** returns 1 if expression is valid (type-wise).*/
-int rve_check_type(enum rval_type* type, struct rval_expr* rve);
+int rve_check_type(enum rval_type* type, struct rval_expr* rve,
+ struct rval_expr** bad_rve, enum rval_type* bad_type,
+ enum rval_type* exp_type);
+/** returns a string name for type (debugging).*/
+char* rval_type_name(enum rval_type type);
/** create a RVE_RVAL_OP rval_expr, containing a single rval of the given type
*/