[SR-Dev] git:andrei/script_vars: script: lvalue = rvalue expression support

Andrei Pelinescu-Onciul andrei at iptel.org
Thu Dec 4 01:11:31 CET 2008


Module: sip-router
Branch: andrei/script_vars
Commit: cddb9399efa10f5685a09b617a2ff5cf665fa2dd
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=cddb9399efa10f5685a09b617a2ff5cf665fa2dd

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at 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; }




More information about the sr-dev mailing list