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