Module: sip-router Branch: andrei/script_vars Commit: cddb9399efa10f5685a09b617a2ff5cf665fa2dd URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=cddb9399...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@iptel.org Date: Thu Dec 4 01:10:12 2008 +0100
script: lvalue = rvalue expression support
- lvalue = rvalue op rvalue ...
---
cfg.y | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 129 insertions(+), 36 deletions(-)
diff --git a/cfg.y b/cfg.y index 228d909..5cc36f9 100644 --- a/cfg.y +++ b/cfg.y @@ -89,6 +89,8 @@ * LINGER2, KEEPALIVE, KEEPIDLE, KEEPINTVL, KEEPCNT} (andrei) * 2008-01-24 added cfg_var definition (Miklos) * 2008-11-18 support for variable parameter module functions (andrei) + * 2007-12-03 support for generalised lvalues and rvalues: + * lval=rval_expr, where lval=avp|pvar (andrei) */
%{ @@ -118,6 +120,10 @@ #include "tcp_init.h" #include "tcp_options.h" #include "sctp_options.h" +#include "pvar.h" +#include "lvalue.h" +#include "rvalue.h" +#include "sr_compat.h"
#include "config.h" #include "cfg_core.h" @@ -187,14 +193,7 @@ static select_t sel; static select_t* sel_ptr; static pv_spec_t* pv_spec; static struct action *mod_func_action; - -static struct avp_pvar_spec{ - int type; - union{ - struct avp_spec avp; - pv_spec_t pv; - }u; -} *apv_spec; +static struct lvalue* lval_tmp;
static void warn(char* s); static struct socket_id* mk_listen_id(char*, int, int); @@ -216,8 +215,10 @@ static void free_socket_id_lst(struct socket_id* i); struct socket_id* sockid; struct name_lst* name_l; struct avp_spec* attr; - struct pv_spec_t* pvar; - struct avp_pvar_spec* avp_pvar_s; + struct _pv_spec* pvar; + struct lvalue* lval; + struct rvalue* rval; + struct rval_expr* rv_expr; select_t* select; }
@@ -508,13 +509,17 @@ static void free_socket_id_lst(struct socket_id* i); %type <attr> attr_id_any %type <attr> attr_id_any_str %type <pvar> pvar -%type <avp_pvar_s> avp_pvar +%type <lval> lval +%type <rv_expr> rval rval_expr +%type <lval> avp_pvar /* %type <intval> class_id */ %type <intval> assign_op %type <select> select_id %type <strval> flag_name; %type <strval> route_name; %type <intval> avpflag_oper +%type <intval> rve_un_op +%type <intval> rve_op
/*%type <route_el> rules; %type <route_el> rule; @@ -1986,42 +1991,38 @@ pvar: PVAR { yyerror("Not enough memory"); YYABORT; } - s.s=$1; s.len=strlen(s.s); - if (pv_parse_spec(&s, pv_spec)==0){ + memset(pv_spec, 0, sizeof(*pv_spec)); + s_tmp.s=$1; s_tmp.len=strlen($1); + if (pv_parse_spec(&s_tmp, pv_spec)==0){ yyerror("unknown script pseudo variable"); pkg_free(pv_spec); YYABORT; } $$=pv_spec; - BUG("parsed pvar "%.*s"\n", s.len, s.s); } ;
avp_pvar: AVP_OR_PVAR { - apv=pkg_malloc(sizeof(*apv)); - if (!apv) { - yyerror("Not enough memory"); - YYABORT; - } - s.s=$1; s.len=strlen(s.s); - if (pv_parse_spec(&s, &apv_spec->u.pv)==0){ - /* not a pvar, try avps */ - /* TODO: test if in ser or k mode */ - if (parse_avp_name(&s, &type, &apv_spec->u.avp.name, &idx)) { - yyerror("error when parsing AVP"); - pkg_free(apv_spec); + lval_tmp=pkg_malloc(sizeof(*lval_tmp)); + if (!lval_tmp) { + yyerror("Not enough memory"); YYABORT; } - apv_spec->u.avp.type = type; - apv_spec->u.avp.index = idx; - apv_spec.type=APV_AVP_T; - }else{ - apv_spec.type=APV_PVAR_T; + memset(lval_tmp, 0, sizeof(*lval_tmp)); + s_tmp.s=$1; s_tmp.len=strlen(s_tmp.s); + if (pv_parse_spec(&s_tmp, &lval_tmp->lv.pvs)==0){ + /* not a pvar, try avps */ + lval_tmp->lv.avps.type|= AVP_NAME_STR; + lval_tmp->lv.avps.name.s.s = s_tmp.s+1; + lval_tmp->lv.avps.name.s.len = s_tmp.len-1; + lval_tmp->type=LV_AVP; + }else{ + lval_tmp->type=LV_PVAR; + } + $$ = lval_tmp; + DBG("parsed ambigous avp/pvar "%.*s" to %d\n", + s_tmp.len, s_tmp.s, lval_tmp->type); } - $$ = apv_spec; - BUG("parsed ambigous avp/pvar "%.*s" to %d\n", s.len, s.s, - apv_spec.type); - } ;
@@ -2034,6 +2035,98 @@ assign_op: assign_op: EQUAL { $$ = ASSIGN_T; } ; + + +lval: attr_id_ass { + lval_tmp=pkg_malloc(sizeof(*lval_tmp)); + if (!lval_tmp) { + yyerror("Not enough memory"); + YYABORT; + } + lval_tmp->type=LV_AVP; lval_tmp->lv.avps=*$1; + pkg_free($1); /* free the avp spec we just copied */ + $$=lval_tmp; + } + | pvar { + if (!pv_is_w($1)) + yyerror("read only pvar in assignment left side"); + if ($1->trans!=0) + yyerror("pvar with transformations in assignment" + " left side"); + lval_tmp=pkg_malloc(sizeof(*lval_tmp)); + if (!lval_tmp) { + yyerror("Not enough memory"); + YYABORT; + } + lval_tmp->type=LV_PVAR; lval_tmp->lv.pvs=*($1); + pkg_free($1); /* free the pvar spec we just copied */ + $$=lval_tmp; + } + | avp_pvar { + if (($1)->type==LV_PVAR){ + if (!pv_is_w(&($1)->lv.pvs)) + yyerror("read only pvar in assignment left side"); + if ($1->lv.pvs.trans!=0) + yyerror("pvar with transformations in assignment" + " left side"); + } + $$=$1; + } + ; + +rval: NUMBER {$$=mk_rval_expr_v(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); } + | avp_pvar { + switch($1->type){ + case LV_AVP: + $$=mk_rval_expr_v(RV_AVP, &$1->lv.avps); + break; + case LV_PVAR: + $$=mk_rval_expr_v(RV_PVAR, &$1->lv.pvs); + break; + default: + yyerror("BUG: invalid lvalue type "); + YYABORT; + } + 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); } + //| exp {$$=mk_rval_expr_v(RV_BEXPR, $1);} + /* missing/TODO: RV_ACTION_ST */ + ; + + +rve_un_op: MINUS { $$=RVE_UMINUS_OP; } + /* TODO: RVE_BOOL_OP, RVE_NOT_OP? */ + ; + +rve_op: PLUS { $$=RVE_PLUS_OP; } + | MINUS { $$=RVE_MINUS_OP; } + | STAR { $$=RVE_MUL_OP; } + /* TODO: RVE_DIV_OP */ + ; + +rval_expr: rval { $$=$1; + if ($$==0){ + yyerror("out of memory\n"); + YYABORT; + } + } + | LPAREN rval_expr RPAREN { $$=$2; } + | rve_un_op rval_expr {$$=mk_rval_expr1($1, $2); } + | rval_expr rve_op rval_expr {$$=mk_rval_expr2($2, $1, $3); } + ; + +assign_action: lval assign_op rval_expr { $$=mk_action($2, 2, LVAL_ST, $1, + RVE_ST, $3); + } + ; + +/* assign_action: attr_id_ass assign_op STRING { $$=mk_action($2, 2, AVP_ST, $1, STRING_ST, $3); } | attr_id_ass assign_op NUMBER { $$=mk_action($2, 2, AVP_ST, $1, NUMBER_ST, (void*)$3); } @@ -2042,7 +2135,7 @@ assign_action: | attr_id_ass assign_op select_id { $$=mk_action($2, 2, AVP_ST, (void*)$1, SELECT_ST, (void*)$3); } | attr_id_ass assign_op LPAREN exp RPAREN { $$ = mk_action($2, 2, AVP_ST, $1, EXPR_ST, $4); } ; - +*/
avpflag_oper: SETAVPFLAG { $$ = 1; }