[SR-Dev] git:andrei/script_vars: script: basic support for parsing pvar names

Andrei Pelinescu-Onciul andrei at iptel.org
Mon Dec 1 13:20:51 CET 2008


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

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at iptel.org>
Date:   Fri Nov 28 20:24:04 2008 +0100

script: basic support for parsing pvar names

- parse pvar names and try to guess on ambiguous pvar/avps identifiers
 (e.g.: $foo)

---

 cfg.lex |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++------------
 cfg.y   |   67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 122 insertions(+), 15 deletions(-)

diff --git a/cfg.lex b/cfg.lex
index 5af02db..56c51e5 100644
--- a/cfg.lex
+++ b/cfg.lex
@@ -75,6 +75,7 @@
  *  2007-11-28  added TCP_OPT_{FD_CACHE, DEFER_ACCEPT, DELAYED_ACK, SYNCNT,
  *              LINGER2, KEEPALIVE, KEEPIDLE, KEEPINTVL, KEEPCNT} (andrei)
  *  2008-01-24  added CFG_DESCRIPTION used by cfg_var (Miklos)
+ *  2008-11-28  added support for kamailio pvars and avp/pvar guessing (andrei)
 */
 
 
@@ -94,8 +95,10 @@
 	#define COMMENT_S		1
 	#define COMMENT_LN_S	        2
 	#define STRING_S		3
-	#define ATTR_S                  4
-        #define SELECT_S                5
+	#define ATTR_S                  4  /* avp/attr */
+	#define SELECT_S                5
+	#define AVP_PVAR_S              6  /* avp or pvar */
+	#define PVAR_P_S                7  /* pvar: $(...)  or $foo(...)*/
 
 	#define STR_BUF_ALLOC_UNIT	128
 	struct str_buf{
@@ -106,6 +109,7 @@
 
 
 	static int comment_nest=0;
+	static int p_nest=0;
 	static int state=0, old_state=0, old_initial=0;
 	static struct str_buf s_buf;
 	int line=1;
@@ -120,7 +124,7 @@
 %}
 
 /* start conditions */
-%x STRING1 STRING2 COMMENT COMMENT_LN ATTR SELECT
+%x STRING1 STRING2 COMMENT COMMENT_LN ATTR SELECT AVP_PVAR PVAR_P
 
 /* action keywords */
 FORWARD	forward
@@ -219,7 +223,8 @@ PLUS	"+"
 MINUS	"-"
 
 /* Attribute specification */
-ATTR_MARK   "$"|"%"
+ATTR_MARK   "%"
+VAR_MARK    "$"
 SELECT_MARK  "@"
 ATTR_FROM         "f"
 ATTR_TO           "t"
@@ -231,6 +236,9 @@ ATTR_FROMDOMAIN   "fd"
 ATTR_TODOMAIN     "td"
 ATTR_GLOBAL       "g"
 
+/* avp prefix */
+AVP_PREF	(([ft][rud]?)|g)\.
+
 /* config vars. */
 DEBUG	debug
 FORK	fork
@@ -729,7 +737,8 @@ EAT_ABLE	[\ \t\b\r]
 <SELECT>{BINNUMBER}     { count(); yylval.intval=(int)strtol(yytext, 0, 2); return NUMBER; }
 
 
-<INITIAL>{ATTR_MARK}    { count(); state = ATTR_S; BEGIN(ATTR); return ATTR_MARK; }
+<INITIAL>{ATTR_MARK}    { count(); state = ATTR_S; BEGIN(ATTR);
+							return ATTR_MARK; }
 <ATTR>{ATTR_FROM}       { count(); return ATTR_FROM; }
 <ATTR>{ATTR_TO}         { count(); return ATTR_TO; }
 <ATTR>{ATTR_FROMURI}    { count(); return ATTR_FROMURI; }
@@ -742,15 +751,48 @@ EAT_ABLE	[\ \t\b\r]
 <ATTR>{DOT}             { count(); return DOT; }
 <ATTR>{LBRACK}          { count(); return LBRACK; }
 <ATTR>{RBRACK}          { count(); return RBRACK; }
-<ATTR>{STAR}		{ count(); return STAR; }
-<ATTR>{DECNUMBER}	{ count(); yylval.intval=atoi(yytext);return NUMBER; }
-<ATTR>{ID}		{ count(); addstr(&s_buf, yytext, yyleng);
-                           yylval.strval=s_buf.s;
-			   memset(&s_buf, 0, sizeof(s_buf));
-                           state = INITIAL_S;
-                           BEGIN(INITIAL);
-			   return ID;
-                        }
+<ATTR>{STAR}			{ count(); return STAR; }
+<ATTR>{DECNUMBER}		{ count(); yylval.intval=atoi(yytext);return NUMBER; }
+<ATTR>{ID}				{ count(); addstr(&s_buf, yytext, yyleng);
+							yylval.strval=s_buf.s;
+							memset(&s_buf, 0, sizeof(s_buf));
+							state = INITIAL_S;
+							BEGIN(INITIAL);
+							return ID;
+						}
+
+<INITIAL>{VAR_MARK}{LPAREN}	{ state = PVAR_P_S; BEGIN(PVAR_P); p_nest=1; 
+								yymore();}
+	/* eat everything between 2 () and return PVAR token and a string
+	   containing everything (including $ and ()) */
+<PVAR_P>{RPAREN}			{	p_nest--;
+								if (p_nest==0){
+									count();
+									addstr(&s_buf, yytext, yyleng);
+									yylval.strval=s_buf.s;
+									memset(&s_buf, 0, sizeof(s_buf));
+									state=INITIAL_S;
+									BEGIN(INITIAL);
+									return PVAR;
+								}
+								yymore();
+							}
+<PVAR_P>.					{ yymore(); }
+
+
+<INITIAL>{VAR_MARK}			{  state=AVP_PVAR_S; BEGIN(AVP_PVAR); yymore(); }
+	/* avp prefix detected -> go to avp mode */
+<AVP_PVAR>{AVP_PREF}		|
+<AVP_PVAR>{ID}{LBRACK}		{ state = ATTR_S; BEGIN(ATTR); yyless(1); 
+							  return ATTR_MARK; }
+<AVP_PVAR>{ID}{LPAREN}		{ state = PVAR_P_S; BEGIN(PVAR_P); yymore(); }
+<AVP_PVAR>{ID}				{ count(); addstr(&s_buf, yytext, yyleng);
+								yylval.strval=s_buf.s;
+								memset(&s_buf, 0, sizeof(s_buf));
+								state = INITIAL_S;
+								BEGIN(INITIAL);
+								return AVP_OR_PVAR;
+							}
 
 <INITIAL>{IPV6ADDR}		{ count(); yylval.strval=yytext; return IPV6ADDR; }
 <INITIAL>{DECNUMBER}		{ count(); yylval.intval=atoi(yytext);return NUMBER; }
diff --git a/cfg.y b/cfg.y
index 5adc111..228d909 100644
--- a/cfg.y
+++ b/cfg.y
@@ -185,8 +185,17 @@ static struct ip_addr* ip_tmp;
 static struct avp_spec* s_attr;
 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 void warn(char* s);
 static struct socket_id* mk_listen_id(char*, int, int);
 static struct name_lst* mk_name_lst(char* name, int flags);
@@ -207,6 +216,8 @@ 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;
 	select_t* select;
 }
 
@@ -426,6 +437,7 @@ static void free_socket_id_lst(struct socket_id* i);
 %token ATTR_GLOBAL
 %token ADDEQ
 
+
 %token STUN_REFRESH_INTERVAL
 %token STUN_ALLOW_STUN
 %token STUN_ALLOW_FP
@@ -452,6 +464,9 @@ static void free_socket_id_lst(struct socket_id* i);
 %token <strval> ID
 %token <strval> STRING
 %token <strval> IPV6ADDR
+%token <strval> PVAR
+/* not clear yet if this is an avp or pvar */
+%token <strval> AVP_OR_PVAR
 
 /* other */
 %token COMMA
@@ -492,6 +507,8 @@ static void free_socket_id_lst(struct socket_id* i);
 %type <attr> attr_id_val
 %type <attr> attr_id_any
 %type <attr> attr_id_any_str
+%type <pvar> pvar
+%type <avp_pvar_s> avp_pvar
 /* %type <intval> class_id */
 %type <intval> assign_op
 %type <select> select_id
@@ -1954,7 +1971,7 @@ attr_id_any_str:
 		s.len = strlen(s.s);
 		if (parse_avp_name(&s, &type, &avp_spec->name, &idx)) {
 			yyerror("error when parsing AVP");
-		        pkg_free(avp_spec);
+			pkg_free(avp_spec);
 			YYABORT;
 		}
 		avp_spec->type = type;
@@ -1962,6 +1979,52 @@ attr_id_any_str:
 		$$ = avp_spec;
 	}
 	;
+
+pvar:	PVAR {
+			pv_spec=pkg_malloc(sizeof(*pv_spec));
+			if (!pv_spec) {
+				yyerror("Not enough memory");
+				YYABORT;
+			}
+			s.s=$1; s.len=strlen(s.s);
+			if (pv_parse_spec(&s, 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);
+					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;
+			}
+			$$ = apv_spec;
+			BUG("parsed ambigous avp/pvar \"%.*s\" to %d\n", s.len, s.s,
+					apv_spec.type);
+		}
+	;
+
+
 /*
 assign_op:
 	ADDEQ { $$ = ADD_T; }
@@ -1979,6 +2042,8 @@ 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; }
 	| RESETAVPFLAG { $$ = 0; }




More information about the sr-dev mailing list