[SR-Dev] git:andrei/script_vars: script parsing: better expression error reporting

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


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

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at iptel.org>
Date:   Mon Dec 15 23:13:20 2008 +0100

script parsing: better expression error reporting

- report bad expression position on type mismatch
e.g.:
 *** PARSE ERROR *** (42,8-18): bad expression: type
     mismatch: str instead of int at (42,16)

---

 cfg.y          |   97 ++++++++++++++++++++++++++++++++++++++++++--------------
 route_struct.h |    9 +++++
 rvalue.c       |   15 ++++++--
 rvalue.h       |   11 +++++--
 4 files changed, 101 insertions(+), 31 deletions(-)

diff --git a/cfg.y b/cfg.y
index d6422f6..7ced7c1 100644
--- a/cfg.y
+++ b/cfg.y
@@ -200,6 +200,9 @@ static struct lvalue* lval_tmp;
 static struct rvalue* rval_tmp;
 
 static void warn(char* s);
+static void get_cpos(struct cfg_pos* pos);
+static void get_rve2_pos(struct cfg_pos* res,
+							struct cfg_pos* pos1, struct cfg_pos* pos2);
 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,
@@ -2057,7 +2060,7 @@ rval_expr: rval						{ $$=$1;
 			{ $$=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; }
+		| 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"); }
@@ -2551,6 +2554,16 @@ extern int column;
 extern int startcolumn;
 extern int startline;
 
+
+static void get_cpos(struct cfg_pos* pos)
+{
+	pos->s_line=startline;
+	pos->e_line=line;
+	pos->s_col=startcolumn;
+	pos->e_col=column-1;
+}
+
+
 static void warn(char* s)
 {
 	if (line!=startline)
@@ -2564,7 +2577,7 @@ static void warn(char* s)
 	cfg_warnings++;
 }
 
-static void yyerror(char* format, ...)
+static void yyerror_at(struct cfg_pos* p, char* format, ...)
 {
 	va_list ap;
 	char s[256];
@@ -2572,19 +2585,53 @@ static void yyerror(char* format, ...)
 	va_start(ap, format);
 	vsnprintf(s, sizeof(s), format, ap);
 	va_end(ap);
-	if (line!=startline)
+	if (p->e_line!=p->s_line)
 		LOG(L_CRIT, "*** PARSE ERROR *** (%d,%d-%d,%d): %s\n", 
-					startline, startcolumn, line, column-1, s);
-	else if (startcolumn!=(column-1))
+					p->s_line, p->s_col, p->e_line, p->e_col, s);
+	else if (p->s_col!=p->e_col)
 		LOG(L_CRIT, "*** PARSE ERROR *** (%d,%d-%d): %s\n", 
-					startline, startcolumn, column-1, s);
+					p->s_line, p->s_col, p->e_col, s);
 	else
 		LOG(L_CRIT, "*** PARSE ERROR *** (%d,%d): %s\n", 
-					startline, startcolumn, s);
+					p->s_line, p->s_col, s);
 	cfg_errors++;
 }
 
 
+static void yyerror(char* format, ...)
+{
+	va_list ap;
+	char s[256];
+	struct cfg_pos pos;
+	
+	get_cpos(&pos);
+	va_start(ap, format);
+	vsnprintf(s, sizeof(s), format, ap);
+	va_end(ap);
+	yyerror_at(&pos, s);
+}
+
+
+
+static void get_rve2_pos(struct cfg_pos* res,
+							struct cfg_pos* pos1, struct cfg_pos* pos2)
+{
+	*res=*pos1;
+	if ((res->s_line == 0) || (res->s_line > pos2->s_line)){
+		res->s_line=pos2->s_line;
+		res->s_col=pos2->s_col;
+	}else if ((res->s_line == pos2->s_line) && (res->s_col > pos2->s_col)){
+		res->s_col=pos2->s_col;
+	}
+	if ((res->e_line == 0) || (res->e_line < pos2->e_line)){
+		res->e_line=pos2->e_line;
+		res->e_col=pos2->e_col;
+	}else if ((res->e_line == pos2->e_line) && (res->e_col < pos2->e_col)){
+		res->e_col=pos2->e_col;
+	}
+}
+
+
 /** mk_rval_expr_v wrapper.
  *  checks mk_rval_expr_v return value and sets the cfg. pos
  *  (line and column numbers)
@@ -2593,8 +2640,10 @@ static void yyerror(char* format, ...)
 static struct rval_expr* mk_rve_rval(enum rval_type type, void* v)
 {
 	struct rval_expr* ret;
+	struct cfg_pos pos;
 
-	ret=mk_rval_expr_v(type, v);
+	get_cpos(&pos);
+	ret=mk_rval_expr_v(type, v, &pos);
 	if (ret==0){
 		yyerror("internal error: failed to create rval expr");
 		/* YYABORT; */
@@ -2613,10 +2662,13 @@ static struct rval_expr* mk_rve1(enum rval_expr_op op, struct rval_expr* rve1)
 	struct rval_expr* bad_rve;
 	enum rval_type type, bad_t, exp_t;
 	
-	ret=mk_rval_expr1(op, rve1);
+	if (rve1==0)
+		return 0;
+	ret=mk_rval_expr1(op, rve1, &rve1->fpos);
 	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));
+		yyerror_at(&rve1->fpos, "bad expression: type mismatch"
+					" (%s instead of %s)", rval_type_name(bad_t),
+					rval_type_name(exp_t));
 	}
 	return ret;
 }
@@ -2631,21 +2683,18 @@ static struct rval_expr* mk_rve2(enum rval_expr_op op, struct rval_expr* rve1,
 {
 	struct rval_expr* ret;
 	struct rval_expr* bad_rve;
-	enum rval_type type, type1, type2, bad_t, exp_t;
+	enum rval_type type, bad_t, exp_t;
+	struct cfg_pos pos;
 	
-	ret=mk_rval_expr2(op, rve1, rve2);
+	if ((rve1==0) || (rve2==0))
+		return 0;
+	get_rve2_pos(&pos, &rve1->fpos, &rve2->fpos);
+	ret=mk_rval_expr2(op, rve1, rve2, &pos);
 	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));
+		yyerror_at(&pos, "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);
 	}
 	return ret;
 }
diff --git a/route_struct.h b/route_struct.h
index c27fef2..ba5046e 100644
--- a/route_struct.h
+++ b/route_struct.h
@@ -102,6 +102,15 @@ enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST,
 #define EXIT_R_F   1
 #define RETURN_R_F 2
 
+
+struct cfg_pos{
+	int s_line;
+	int e_line;
+	unsigned short s_col;
+	unsigned short e_col;
+};
+
+
 /* Expression operand */
 union exp_op {
 	void* param;
diff --git a/rvalue.c b/rvalue.c
index c637dec..6f9b118 100644
--- a/rvalue.c
+++ b/rvalue.c
@@ -543,7 +543,7 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
 				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_rve) *bad_rve=rve->right.rve;
 						if (bad_t) *bad_t=type2;
 						if (exp_t) *exp_t=RV_INT;
 						return 0;
@@ -1597,9 +1597,11 @@ error:
  *
  * @param rv_type - rval type
  * @param val     - rval value
+ * @param pos     - config position
  * @return new pkg_malloc'ed rval_expr or 0 on error.
  */
-struct rval_expr* mk_rval_expr_v(enum rval_type rv_type, void* val)
+struct rval_expr* mk_rval_expr_v(enum rval_type rv_type, void* val, 
+									struct cfg_pos* pos)
 {
 	struct rval_expr* rve;
 	union rval_val v;
@@ -1649,6 +1651,7 @@ struct rval_expr* mk_rval_expr_v(enum rval_type rv_type, void* val)
 	}
 	rval_init(&rve->left.rval, rv_type, &v, flags);
 	rve->op=RVE_RVAL_OP;
+	if (pos) rve->fpos=*pos;
 	return rve;
 }
 
@@ -1660,7 +1663,8 @@ struct rval_expr* mk_rval_expr_v(enum rval_type rv_type, void* val)
  * @param rve1 - rval expr. on which the operator will act.
  * @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)
+struct rval_expr* mk_rval_expr1(enum rval_expr_op op, struct rval_expr* rve1,
+								struct cfg_pos* pos)
 {
 	struct rval_expr* ret;
 	
@@ -1679,6 +1683,7 @@ struct rval_expr* mk_rval_expr1(enum rval_expr_op op, struct rval_expr* rve1)
 	memset(ret, sizeof(*ret), 0);
 	ret->op=op;
 	ret->left.rve=rve1;
+	if (pos) ret->fpos=*pos;
 	return ret;
 }
 
@@ -1692,7 +1697,8 @@ struct rval_expr* mk_rval_expr1(enum rval_expr_op op, struct rval_expr* rve1)
  * @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,
-													  struct rval_expr* rve2)
+													  struct rval_expr* rve2,
+													  struct cfg_pos* pos)
 {
 	struct rval_expr* ret;
 	
@@ -1723,6 +1729,7 @@ struct rval_expr* mk_rval_expr2(enum rval_expr_op op, struct rval_expr* rve1,
 	ret->op=op;
 	ret->left.rve=rve1;
 	ret->right.rve=rve2;
+	if (pos) ret->fpos=*pos;
 	return ret;
 }
 
diff --git a/rvalue.h b/rvalue.h
index 5a1c10b..f36f189 100644
--- a/rvalue.h
+++ b/rvalue.h
@@ -94,6 +94,7 @@ struct rvalue{
 #define RV_RV_ALLOCED_F   2  /* free rv itself (pkg_free(rv)) */
 #define RV_ALL_ALLOCED_F  (RV_CNT_ALLOCED|RV_RV_ALLOCED)
 
+
 struct rval_expr{
 	enum rval_expr_op op;
 	union{
@@ -104,6 +105,7 @@ struct rval_expr{
 		struct rval_expr* rve;
 		struct rvalue rval;
 	}right;
+	struct cfg_pos fpos;
 };
 
 
@@ -193,12 +195,15 @@ char* rval_type_name(enum rval_type type);
 
 /** create a RVE_RVAL_OP rval_expr, containing a single rval of the given type
   */
-struct rval_expr* mk_rval_expr_v(enum rval_type rv_type, void* val);
+struct rval_expr* mk_rval_expr_v(enum rval_type rv_type, void* val,
+									struct cfg_pos* pos);
 /** create a unary op. rval_expr.. */
-struct rval_expr* mk_rval_expr1(enum rval_expr_op op, struct rval_expr* rve1);
+struct rval_expr* mk_rval_expr1(enum rval_expr_op op, struct rval_expr* rve1,
+									struct cfg_pos* pos);
 /** create a rval_expr. from 2 other rval exprs, using op. */
 struct rval_expr* mk_rval_expr2(enum rval_expr_op op, struct rval_expr* rve1,
-													  struct rval_expr* rve2);
+													  struct rval_expr* rve2,
+													  struct cfg_pos* pos);
 
 /** fix a rval_expr. */
 int fix_rval_expr(void** p);




More information about the sr-dev mailing list