[SR-Dev] git:master: core script engine: if switched to rval_expr

Andrei Pelinescu-Onciul andrei at iptel.org
Mon May 4 23:39:44 CEST 2009


Module: sip-router
Branch: master
Commit: 8637f3408456dcc4e2df2cf6b2530cc7f1588042
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=8637f3408456dcc4e2df2cf6b2530cc7f1588042

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at iptel.org>
Date:   Mon May  4 21:58:40 2009 +0200

core script engine: if switched to rval_expr

- switched if to use directly rval_expr
- warn on startup if "if" expression is constant
- fail to start if "if" expression evaluates to non-int

---

 action.c |   23 +++++++--------------
 cfg.y    |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 route.c  |   42 +++++++++++++++++++++++++++++++++------
 3 files changed, 104 insertions(+), 26 deletions(-)

diff --git a/action.c b/action.c
index ffc0051..f99079a 100644
--- a/action.c
+++ b/action.c
@@ -49,6 +49,7 @@
  *  2008-11-18  support for variable parameter module functions (andrei)
  *  2008-12-03  use lvalues/rvalues for assignments (andrei)
  *  2008-12-17  added UDP_MTU_TRY_PROTO_T (andrei)
+ *  2009-05-04  switched IF_T to rval_expr (andrei)
  */
 
 
@@ -813,21 +814,14 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
 				ret=1;
 				break;
 		case IF_T:
-				/* if null expr => ignore if? */
-				if ((a->val[0].type==EXPR_ST)&&a->val[0].u.data){
-					v=eval_expr(h, (struct expr*)a->val[0].u.data, msg);
-#if 0
-					if (v<0){
-						if (v==EXPR_DROP){ /* hack to quit on DROP*/
-							ret=0;
-							break;
-						}else{
-							LOG(L_WARN,"WARNING: do_action:"
-										"error in expression\n");
-						}
+					rve=(struct rval_expr*)a->val[0].u.data;
+					if (unlikely(rval_expr_eval_int(h, msg, &v, rve) != 0)){
+						ERR("if expression evaluation failed (%d,%d-%d,%d)\n",
+								rve->fpos.s_line, rve->fpos.s_col,
+								rve->fpos.e_line, rve->fpos.e_col);
+						v=0; /* false */
 					}
-#endif
-					if (h->run_flags & EXIT_R_F){
+					if (unlikely(h->run_flags & EXIT_R_F)){
 						ret=0;
 						break;
 					}
@@ -843,7 +837,6 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
 							ret=run_actions(h,
 										(struct action*)a->val[2].u.data, msg);
 					}
-				}
 			break;
 		case MODULE_T:
 			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
diff --git a/cfg.y b/cfg.y
index 5c0c3f2..21e81a1 100644
--- a/cfg.y
+++ b/cfg.y
@@ -95,6 +95,7 @@
  *             NUMBER is now always positive; cleanup (andrei)
  * 2009-01-26  case/switch() support (andrei)
  * 2009-03-10  added SET_USERPHONE action (Miklos)
+ * 2009-05-04  switched if to rval_expr (andrei)
 */
 
 %{
@@ -212,6 +213,8 @@ static struct rval_expr* mk_rve_rval(enum rval_type, void* v);
 static struct rval_expr* mk_rve1(enum rval_expr_op op, struct rval_expr* rve1);
 static struct rval_expr* mk_rve2(enum rval_expr_op op, struct rval_expr* rve1,
 									struct rval_expr* rve2);
+static int rval_expr_int_check(struct rval_expr *rve);
+static int warn_ct_rve(struct rval_expr *rve, char* name);
 static struct socket_id* mk_listen_id(char*, int, int);
 static struct name_lst* mk_name_lst(char* name, int flags);
 static struct socket_id* mk_listen_id2(struct name_lst*, int, int);
@@ -520,7 +523,8 @@ static int case_check_default(struct case_stms* stms);
 
 
 /*non-terminals */
-%type <expr> exp exp_elem
+/*%type <expr> exp */
+%type <expr> exp_elem
 %type <intval> intno eint_op eint_op_onsend
 %type <intval> eip_op eip_op_onsend
 %type <action> action actions cmd fcmd if_cmd stm /*exp_stm*/ assign_action
@@ -1566,7 +1570,7 @@ send_route_stm: ROUTE_SEND LBRACE actions RBRACE {
 	| ROUTE_SEND error { yyerror("invalid onsend_route statement"); }
 	;
 
-exp:	rval_expr
+/*exp:	rval_expr
 		{
 			if ($1==0){
 				yyerror("invalid expression");
@@ -1581,6 +1585,7 @@ exp:	rval_expr
 				$$=mk_elem(NO_OP, RVEXP_O, $1, 0, 0);
 		}
 	;
+*/
 
 /* exp elem operators */
 equalop:
@@ -1852,8 +1857,18 @@ action:
 	| fcmd error { $$=0; yyerror("bad command: missing ';'?"); }
 	;
 if_cmd:
-	IF exp stm		{ $$=mk_action( IF_T, 3, EXPR_ST, $2, ACTIONS_ST, $3, NOSUBTYPE, 0); }
-	| IF exp stm ELSE stm	{ $$=mk_action( IF_T, 3, EXPR_ST, $2, ACTIONS_ST, $3, ACTIONS_ST, $5); }
+	IF rval_expr stm	{
+		if (rval_expr_int_check($2)==0){
+			warn_ct_rve($2, "if");
+		}
+		$$=mk_action( IF_T, 3, RVE_ST, $2, ACTIONS_ST, $3, NOSUBTYPE, 0);
+	}
+	| IF rval_expr stm ELSE stm	{ 
+		if (rval_expr_int_check($2)==0){
+			warn_ct_rve($2, "if");
+		}
+		$$=mk_action( IF_T, 3, RVE_ST, $2, ACTIONS_ST, $3, ACTIONS_ST, $5); 
+	}
 	;
 
 ct_rval: rval_expr {
@@ -2930,6 +2945,48 @@ static struct rval_expr* mk_rve2(enum rval_expr_op op, struct rval_expr* rve1,
 }
 
 
+/** check if the expression is an int.
+ * if the expression does not evaluate to an int return -1 and
+ * log an error.
+ * @return 0 on success, -1 on error */
+static int rval_expr_int_check(struct rval_expr *rve)
+{
+	struct rval_expr* bad_rve;
+	enum rval_type type, bad_t, exp_t;
+	
+	if (rve==0){
+		yyerror("invalid expression");
+		return -1;
+	}else if (!rve_check_type(&type, rve, &bad_rve, &bad_t ,&exp_t)){
+		if (bad_rve)
+			yyerror_at(&rve->fpos, "bad expression: type mismatch:"
+						" %s instead of %s at (%d,%d)",
+						rval_type_name(bad_t), rval_type_name(exp_t),
+						bad_rve->fpos.s_line, bad_rve->fpos.s_col);
+		else
+			yyerror("BUG: unexpected null \"bad\" expression\n");
+		return -1;
+	}else if (type!=RV_INT && type!=RV_NONE){
+		yyerror_at(&rve->fpos, "invalid expression type, int expected\n");
+		return -1;
+	}
+	return 0;
+}
+
+
+/** warn if the expression is constant.
+ * @return 0 on success (no warning), 1 when warning */
+static int warn_ct_rve(struct rval_expr *rve, char* name)
+{
+	if (rve && rve_is_constant(rve)){
+		warn_at(&rve->fpos, "constant value in %s%s",
+				name?name:"expression", name?"(...)":"");
+		return 1;
+	}
+	return 0;
+}
+
+
 static struct name_lst* mk_name_lst(char* host, int flags)
 {
 	struct name_lst* l;
diff --git a/route.c b/route.c
index 7b831e2..4ba116a 100644
--- a/route.c
+++ b/route.c
@@ -49,6 +49,7 @@
  *  2008-04-23  errors are treated as false during expression evaluation
  *  		unless the operator is DIFF_OP (Miklos)
  *  2008-12-03  fixups for rvalues in assignments (andrei)
+ *  2009-05-04  switched IF_T to rval_expr (andrei)
  */
 
 
@@ -674,24 +675,50 @@ int fix_actions(struct action* a)
 					}
 					break;
 			case IF_T:
-				if (t->val[0].type!=EXPR_ST){
+				if (t->val[0].type!=RVE_ST){
 					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
-								"%d for if (should be expr)\n",
+								"%d for if (should be rval expr)\n",
 								t->val[0].type);
 					return E_BUG;
-				}else if( (t->val[1].type!=ACTIONS_ST)&&(t->val[1].type!=NOSUBTYPE) ){
+				}else if( (t->val[1].type!=ACTIONS_ST) &&
+							(t->val[1].type!=NOSUBTYPE) ){
 					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
 								"%d for if() {...} (should be action)\n",
 								t->val[1].type);
 					return E_BUG;
-				}else if( (t->val[2].type!=ACTIONS_ST)&&(t->val[2].type!=NOSUBTYPE) ){
+				}else if( (t->val[2].type!=ACTIONS_ST) &&
+							(t->val[2].type!=NOSUBTYPE) ){
 					LOG(L_CRIT, "BUG: fix_actions: invalid subtype"
 								"%d for if() {} else{...}(should be action)\n",
 								t->val[2].type);
 					return E_BUG;
 				}
-				if (t->val[0].u.data){
-					if ((ret=fix_expr((struct expr*)t->val[0].u.data))<0)
+				rve=(struct rval_expr*)t->val[0].u.data;
+				if (rve){
+					err_rve=0;
+					if (!rve_check_type(&rve_type, rve, &err_rve,
+											&err_type, &expected_type)){
+						if (err_rve)
+							LOG(L_ERR, "fix_actions: invalid expression "
+									"(%d,%d): subexpression (%d,%d) has type"
+									" %s,  but %s is expected\n",
+									rve->fpos.s_line, rve->fpos.s_col,
+									err_rve->fpos.s_line, err_rve->fpos.s_col,
+									rval_type_name(err_type),
+									rval_type_name(expected_type) );
+						else
+							LOG(L_ERR, "fix_actions: invalid expression "
+									"(%d,%d): type mismatch?",
+									rve->fpos.s_line, rve->fpos.s_col);
+						return E_UNSPEC;
+					}
+					if (rve_type!=RV_INT && rve_type!=RV_NONE){
+						LOG(L_ERR, "fix_actions: invalid expression (%d,%d):"
+								" bad type, integer expected\n",
+								rve->fpos.s_line, rve->fpos.s_col);
+						return E_UNSPEC;
+					}
+					if ((ret=fix_rval_expr((void**)&rve))<0)
 						return ret;
 				}
 				if ( (t->val[1].type==ACTIONS_ST)&&(t->val[1].u.data) ){
@@ -699,7 +726,8 @@ int fix_actions(struct action* a)
 						return ret;
 				}
 				if ( (t->val[2].type==ACTIONS_ST)&&(t->val[2].u.data) ){
-						if ((ret=fix_actions((struct action*)t->val[2].u.data))<0)
+						if ((ret=fix_actions((struct action*)t->val[2].u.data))
+								<0)
 						return ret;
 				}
 				break;




More information about the sr-dev mailing list