[SR-Dev] git:andrei/script_vars: script parsing: expression type checking on startup

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


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

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at iptel.org>
Date:   Mon Dec 15 21:24:47 2008 +0100

script parsing: expression type checking on startup

- check expressions type and report errors at script parsing time
- yyerror() uses now a printf style format

---

 cfg.y |  150 ++++++++++++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 112 insertions(+), 38 deletions(-)

diff --git a/cfg.y b/cfg.y
index ce6e130..d6422f6 100644
--- a/cfg.y
+++ b/cfg.y
@@ -99,6 +99,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdarg.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
@@ -180,7 +181,7 @@
 
 
 extern int yylex();
-static void yyerror(char* s);
+static void yyerror(char* s, ...);
 static char* tmp;
 static int i_tmp;
 static unsigned u_tmp;
@@ -199,6 +200,10 @@ static struct lvalue* lval_tmp;
 static struct rvalue* rval_tmp;
 
 static void warn(char* s);
+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 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);
@@ -1489,7 +1494,7 @@ send_route_stm: ROUTE_SEND LBRACE actions RBRACE {
 
 exp:	rval_expr
 		{
-			if (!rve_check_type((enum rval_type*)&i_tmp, $1)){
+			if (!rve_check_type((enum rval_type*)&i_tmp, $1, 0, 0 ,0)){
 				yyerror("invalid expression");
 				$$=0;
 			}else if (i_tmp!=RV_INT && i_tmp!=RV_NONE){
@@ -1992,18 +1997,18 @@ lval: attr_id_ass {
 				}
 	;
 
-rval: intno			{$$=mk_rval_expr_v(RV_INT, (void*)$1); }
+rval: intno			{$$=mk_rve_rval(RV_INT, (void*)$1); }
 	| STRING			{	s_tmp.s=$1; s_tmp.len=strlen($1);
-							$$=mk_rval_expr_v(RV_STR, &s_tmp); }
-	| attr_id_any		{$$=mk_rval_expr_v(RV_AVP, $1); pkg_free($1); }
-	| pvar				{$$=mk_rval_expr_v(RV_PVAR, $1); pkg_free($1); }
+							$$=mk_rve_rval(RV_STR, &s_tmp); }
+	| attr_id_any		{$$=mk_rve_rval(RV_AVP, $1); pkg_free($1); }
+	| pvar				{$$=mk_rve_rval(RV_PVAR, $1); pkg_free($1); }
 	| avp_pvar			{
 							switch($1->type){
 								case LV_AVP:
-									$$=mk_rval_expr_v(RV_AVP, &$1->lv.avps);
+									$$=mk_rve_rval(RV_AVP, &$1->lv.avps);
 									break;
 								case LV_PVAR:
-									$$=mk_rval_expr_v(RV_PVAR, &$1->lv.pvs);
+									$$=mk_rve_rval(RV_PVAR, &$1->lv.pvs);
 									break;
 								default:
 									yyerror("BUG: invalid lvalue type ");
@@ -2011,11 +2016,12 @@ rval: intno			{$$=mk_rval_expr_v(RV_INT, (void*)$1); }
 							}
 							pkg_free($1); /* not needed anymore */
 						}
-	| select_id			{$$=mk_rval_expr_v(RV_SEL, $1); pkg_free($1); }
-	| fcmd				{$$=mk_rval_expr_v(RV_ACTION_ST, $1); }
-	| LBRACE actions RBRACE	{$$=mk_rval_expr_v(RV_ACTION_ST, $2); }
+	| select_id			{$$=mk_rve_rval(RV_SEL, $1); pkg_free($1); }
+	| fcmd				{$$=mk_rve_rval(RV_ACTION_ST, $1); }
+	| exp_elem { $$=mk_rve_rval(RV_BEXPR, $1); }
+	| LBRACE actions RBRACE	{$$=mk_rve_rval(RV_ACTION_ST, $2); }
 	| LBRACE error RBRACE	{ yyerror("bad command block"); }
-	| LPAREN assign_action RPAREN	{$$=mk_rval_expr_v(RV_ACTION_ST, $2); }
+	| LPAREN assign_action RPAREN	{$$=mk_rve_rval(RV_ACTION_ST, $2); }
 	| LPAREN error RPAREN	{ yyerror("bad expression"); }
 	;
 
@@ -2039,36 +2045,32 @@ rval_expr: rval						{ $$=$1;
 												YYABORT;
 											}
 									}
-		| rve_un_op %prec NOT rval_expr 	{$$=mk_rval_expr1($1, $2); }
-		| rval_expr PLUS rval_expr	{$$=mk_rval_expr2(RVE_PLUS_OP, $1, $3); }
-		| rval_expr MINUS rval_expr	{$$=mk_rval_expr2(RVE_MINUS_OP, $1, $3); }
-		| rval_expr STAR rval_expr	{$$=mk_rval_expr2(RVE_MUL_OP, $1, $3); }
-		| rval_expr SLASH rval_expr	{$$=mk_rval_expr2(RVE_DIV_OP, $1, $3); }
-		| rval_expr BIN_OR rval_expr {$$=mk_rval_expr2(RVE_BOR_OP, $1,  $3); }
-		| rval_expr BIN_AND rval_expr {$$=mk_rval_expr2(RVE_BAND_OP, $1,  $3);}
-		| rval_expr rve_cmpop %prec GT rval_expr 
-			{ $$=mk_rval_expr2( $2, $1, $3);}
+		| rve_un_op %prec NOT rval_expr	{$$=mk_rve1($1, $2); }
+		| rval_expr PLUS rval_expr		{$$=mk_rve2(RVE_PLUS_OP, $1, $3); }
+		| rval_expr MINUS rval_expr		{$$=mk_rve2(RVE_MINUS_OP, $1, $3); }
+		| rval_expr STAR rval_expr		{$$=mk_rve2(RVE_MUL_OP, $1, $3); }
+		| rval_expr SLASH rval_expr		{$$=mk_rve2(RVE_DIV_OP, $1, $3); }
+		| rval_expr BIN_OR rval_expr	{$$=mk_rve2(RVE_BOR_OP, $1,  $3); }
+		| rval_expr BIN_AND rval_expr	{$$=mk_rve2(RVE_BAND_OP, $1,  $3);}
+		| rval_expr rve_cmpop %prec GT rval_expr { $$=mk_rve2( $2, $1, $3);}
 		| rval_expr rve_equalop %prec EQUAL_T rval_expr
-			{ $$=mk_rval_expr2( $2, $1, $3);}
-		| rval_expr LOG_AND rval_expr
-			{ $$=mk_rval_expr2(RVE_LAND_OP, $1, $3);}
-		| rval_expr LOG_OR rval_expr
-			{ $$=mk_rval_expr2(RVE_LOR_OP, $1, $3);}
-		| LPAREN rval_expr RPAREN	{ $$=$2; }
-		| exp_elem { $$=mk_rval_expr_v(RV_BEXPR, $1); }
-		| rve_un_op %prec NOT error { yyerror("bad expression"); }
-		| rval_expr PLUS error		{ yyerror("bad expression"); }
-		| rval_expr MINUS error		{ yyerror("bad expression"); }
-		| rval_expr STAR error		{ yyerror("bad expression"); }
-		| rval_expr SLASH error		{ yyerror("bad expression"); }
-		| rval_expr BIN_OR error	{ yyerror("bad expression"); }
-		| rval_expr BIN_AND error	{ yyerror("bad expression"); }
+			{ $$=mk_rve2( $2, $1, $3);}
+		| rval_expr LOG_AND rval_expr	{ $$=mk_rve2(RVE_LAND_OP, $1, $3);}
+		| rval_expr LOG_OR rval_expr	{ $$=mk_rve2(RVE_LOR_OP, $1, $3);}
+		| LPAREN rval_expr RPAREN		{ $$=$2; }
+		| rve_un_op %prec NOT error		{ yyerror("bad expression"); }
+		| rval_expr PLUS error			{ yyerror("bad expression"); }
+		| rval_expr MINUS error			{ yyerror("bad expression"); }
+		| rval_expr STAR error			{ yyerror("bad expression"); }
+		| rval_expr SLASH error			{ yyerror("bad expression"); }
+		| rval_expr BIN_OR error		{ yyerror("bad expression"); }
+		| rval_expr BIN_AND error		{ yyerror("bad expression"); }
 		| rval_expr rve_cmpop %prec GT error
 			{ yyerror("bad expression"); }
 		| rval_expr rve_equalop %prec EQUAL_T error
 			{ yyerror("bad expression"); }
-		| rval_expr LOG_AND error	{ yyerror("bad expression"); }
-		| rval_expr LOG_OR error	{ yyerror("bad expression"); }
+		| rval_expr LOG_AND error		{ yyerror("bad expression"); }
+		| rval_expr LOG_OR error		{ yyerror("bad expression"); }
 		;
 
 assign_action: lval assign_op  rval_expr	{ $$=mk_action($2, 2, LVAL_ST, $1, 
@@ -2562,8 +2564,14 @@ static void warn(char* s)
 	cfg_warnings++;
 }
 
-static void yyerror(char* s)
+static void yyerror(char* format, ...)
 {
+	va_list ap;
+	char s[256];
+	
+	va_start(ap, format);
+	vsnprintf(s, sizeof(s), format, ap);
+	va_end(ap);
 	if (line!=startline)
 		LOG(L_CRIT, "*** PARSE ERROR *** (%d,%d-%d,%d): %s\n", 
 					startline, startcolumn, line, column-1, s);
@@ -2577,6 +2585,72 @@ static void yyerror(char* s)
 }
 
 
+/** mk_rval_expr_v wrapper.
+ *  checks mk_rval_expr_v return value and sets the cfg. pos
+ *  (line and column numbers)
+ *  @return rval_expr* on success, 0 on error (@see mk_rval_expr_v)
+ */
+static struct rval_expr* mk_rve_rval(enum rval_type type, void* v)
+{
+	struct rval_expr* ret;
+
+	ret=mk_rval_expr_v(type, v);
+	if (ret==0){
+		yyerror("internal error: failed to create rval expr");
+		/* YYABORT; */
+	}
+	return ret;
+}
+
+
+/** mk_rval_expr1 wrapper.
+ *  checks mk_rval_expr1 return value (!=0 and type checking)
+ *  @return rval_expr* on success, 0 on error (@see mk_rval_expr1)
+ */
+static struct rval_expr* mk_rve1(enum rval_expr_op op, struct rval_expr* rve1)
+{
+	struct rval_expr* ret;
+	struct rval_expr* bad_rve;
+	enum rval_type type, bad_t, exp_t;
+	
+	ret=mk_rval_expr1(op, rve1);
+	if (ret && (rve_check_type(&type, ret, &bad_rve, &bad_t, &exp_t)!=1)){
+		yyerror("bad expression: type mismatch (%s instead of %s)",
+					rval_type_name(bad_t), rval_type_name(exp_t));
+	}
+	return ret;
+}
+
+
+/** mk_rval_expr2 wrapper.
+ *  checks mk_rval_expr2 return value (!=0 and type checking)
+ *  @return rval_expr* on success, 0 on error (@see mk_rval_expr2)
+ */
+static struct rval_expr* mk_rve2(enum rval_expr_op op, struct rval_expr* rve1,
+									struct rval_expr* rve2)
+{
+	struct rval_expr* ret;
+	struct rval_expr* bad_rve;
+	enum rval_type type, type1, type2, bad_t, exp_t;
+	
+	ret=mk_rval_expr2(op, rve1, rve2);
+	if (ret && (rve_check_type(&type, ret, &bad_rve, &bad_t, &exp_t)!=1)){
+		if (rve_check_type(&type1, rve1, &bad_rve, &bad_t, &exp_t)!=1)
+			yyerror("bad expression: left side type mismatch"
+					" (%s instead of %s)",
+					rval_type_name(bad_t), rval_type_name(exp_t));
+		else if (rve_check_type(&type2, rve2, &bad_rve, &bad_t, &exp_t)!=1)
+			yyerror("bad expression: right side type mismatch"
+					" (%s instead of %s)",
+					rval_type_name(bad_t), rval_type_name(exp_t));
+		else
+			yyerror("bad expression: type mismatch (%s instead of %s)",
+					rval_type_name(bad_t), rval_type_name(exp_t));
+	}
+	return ret;
+}
+
+
 static struct name_lst* mk_name_lst(char* host, int flags)
 {
 	struct name_lst* l;




More information about the sr-dev mailing list