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