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