[SR-Dev] git:andrei/script_vars: script engine: rve_check_type() extended

Andrei Pelinescu-Onciul andrei at iptel.org
Mon Dec 15 23:14:47 CET 2008


Module: sip-router
Branch: andrei/script_vars
Commit: 70341d3b4f46c8a6bdbbdfcb314f01cee08a226d
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=70341d3b4f46c8a6bdbbdfcb314f01cee08a226d

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at 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
   */




More information about the sr-dev mailing list