Module: sip-router Branch: andrei/script_vars Commit: 9a31872ccbd89266c5300a0f443f96b6a4934e6f URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=9a31872c...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@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);