Browse code

script: basic support for parsing pvar names

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

Andrei Pelinescu-Onciul authored on 28/11/2008 19:24:04
Showing 2 changed files
... ...
@@ -75,6 +75,7 @@
75 75
  *  2007-11-28  added TCP_OPT_{FD_CACHE, DEFER_ACCEPT, DELAYED_ACK, SYNCNT,
76 76
  *              LINGER2, KEEPALIVE, KEEPIDLE, KEEPINTVL, KEEPCNT} (andrei)
77 77
  *  2008-01-24  added CFG_DESCRIPTION used by cfg_var (Miklos)
78
+ *  2008-11-28  added support for kamailio pvars and avp/pvar guessing (andrei)
78 79
 */
79 80
 
80 81
 
... ...
@@ -94,8 +95,10 @@
94 94
 	#define COMMENT_S		1
95 95
 	#define COMMENT_LN_S	        2
96 96
 	#define STRING_S		3
97
-	#define ATTR_S                  4
98
-        #define SELECT_S                5
97
+	#define ATTR_S                  4  /* avp/attr */
98
+	#define SELECT_S                5
99
+	#define AVP_PVAR_S              6  /* avp or pvar */
100
+	#define PVAR_P_S                7  /* pvar: $(...)  or $foo(...)*/
99 101
 
100 102
 	#define STR_BUF_ALLOC_UNIT	128
101 103
 	struct str_buf{
... ...
@@ -106,6 +109,7 @@
106 106
 
107 107
 
108 108
 	static int comment_nest=0;
109
+	static int p_nest=0;
109 110
 	static int state=0, old_state=0, old_initial=0;
110 111
 	static struct str_buf s_buf;
111 112
 	int line=1;
... ...
@@ -120,7 +124,7 @@
120 120
 %}
121 121
 
122 122
 /* start conditions */
123
-%x STRING1 STRING2 COMMENT COMMENT_LN ATTR SELECT
123
+%x STRING1 STRING2 COMMENT COMMENT_LN ATTR SELECT AVP_PVAR PVAR_P
124 124
 
125 125
 /* action keywords */
126 126
 FORWARD	forward
... ...
@@ -219,7 +223,8 @@ PLUS	"+"
219 219
 MINUS	"-"
220 220
 
221 221
 /* Attribute specification */
222
-ATTR_MARK   "$"|"%"
222
+ATTR_MARK   "%"
223
+VAR_MARK    "$"
223 224
 SELECT_MARK  "@"
224 225
 ATTR_FROM         "f"
225 226
 ATTR_TO           "t"
... ...
@@ -231,6 +236,9 @@ ATTR_FROMDOMAIN   "fd"
231 231
 ATTR_TODOMAIN     "td"
232 232
 ATTR_GLOBAL       "g"
233 233
 
234
+/* avp prefix */
235
+AVP_PREF	(([ft][rud]?)|g)\.
236
+
234 237
 /* config vars. */
235 238
 DEBUG	debug
236 239
 FORK	fork
... ...
@@ -729,7 +737,8 @@ EAT_ABLE	[\ \t\b\r]
729 729
 <SELECT>{BINNUMBER}     { count(); yylval.intval=(int)strtol(yytext, 0, 2); return NUMBER; }
730 730
 
731 731
 
732
-<INITIAL>{ATTR_MARK}    { count(); state = ATTR_S; BEGIN(ATTR); return ATTR_MARK; }
732
+<INITIAL>{ATTR_MARK}    { count(); state = ATTR_S; BEGIN(ATTR);
733
+							return ATTR_MARK; }
733 734
 <ATTR>{ATTR_FROM}       { count(); return ATTR_FROM; }
734 735
 <ATTR>{ATTR_TO}         { count(); return ATTR_TO; }
735 736
 <ATTR>{ATTR_FROMURI}    { count(); return ATTR_FROMURI; }
... ...
@@ -742,15 +751,48 @@ EAT_ABLE	[\ \t\b\r]
742 742
 <ATTR>{DOT}             { count(); return DOT; }
743 743
 <ATTR>{LBRACK}          { count(); return LBRACK; }
744 744
 <ATTR>{RBRACK}          { count(); return RBRACK; }
745
-<ATTR>{STAR}		{ count(); return STAR; }
746
-<ATTR>{DECNUMBER}	{ count(); yylval.intval=atoi(yytext);return NUMBER; }
747
-<ATTR>{ID}		{ count(); addstr(&s_buf, yytext, yyleng);
748
-                           yylval.strval=s_buf.s;
749
-			   memset(&s_buf, 0, sizeof(s_buf));
750
-                           state = INITIAL_S;
751
-                           BEGIN(INITIAL);
752
-			   return ID;
753
-                        }
745
+<ATTR>{STAR}			{ count(); return STAR; }
746
+<ATTR>{DECNUMBER}		{ count(); yylval.intval=atoi(yytext);return NUMBER; }
747
+<ATTR>{ID}				{ count(); addstr(&s_buf, yytext, yyleng);
748
+							yylval.strval=s_buf.s;
749
+							memset(&s_buf, 0, sizeof(s_buf));
750
+							state = INITIAL_S;
751
+							BEGIN(INITIAL);
752
+							return ID;
753
+						}
754
+
755
+<INITIAL>{VAR_MARK}{LPAREN}	{ state = PVAR_P_S; BEGIN(PVAR_P); p_nest=1; 
756
+								yymore();}
757
+	/* eat everything between 2 () and return PVAR token and a string
758
+	   containing everything (including $ and ()) */
759
+<PVAR_P>{RPAREN}			{	p_nest--;
760
+								if (p_nest==0){
761
+									count();
762
+									addstr(&s_buf, yytext, yyleng);
763
+									yylval.strval=s_buf.s;
764
+									memset(&s_buf, 0, sizeof(s_buf));
765
+									state=INITIAL_S;
766
+									BEGIN(INITIAL);
767
+									return PVAR;
768
+								}
769
+								yymore();
770
+							}
771
+<PVAR_P>.					{ yymore(); }
772
+
773
+
774
+<INITIAL>{VAR_MARK}			{  state=AVP_PVAR_S; BEGIN(AVP_PVAR); yymore(); }
775
+	/* avp prefix detected -> go to avp mode */
776
+<AVP_PVAR>{AVP_PREF}		|
777
+<AVP_PVAR>{ID}{LBRACK}		{ state = ATTR_S; BEGIN(ATTR); yyless(1); 
778
+							  return ATTR_MARK; }
779
+<AVP_PVAR>{ID}{LPAREN}		{ state = PVAR_P_S; BEGIN(PVAR_P); yymore(); }
780
+<AVP_PVAR>{ID}				{ count(); addstr(&s_buf, yytext, yyleng);
781
+								yylval.strval=s_buf.s;
782
+								memset(&s_buf, 0, sizeof(s_buf));
783
+								state = INITIAL_S;
784
+								BEGIN(INITIAL);
785
+								return AVP_OR_PVAR;
786
+							}
754 787
 
755 788
 <INITIAL>{IPV6ADDR}		{ count(); yylval.strval=yytext; return IPV6ADDR; }
756 789
 <INITIAL>{DECNUMBER}		{ count(); yylval.intval=atoi(yytext);return NUMBER; }
... ...
@@ -185,8 +185,17 @@ static struct ip_addr* ip_tmp;
185 185
 static struct avp_spec* s_attr;
186 186
 static select_t sel;
187 187
 static select_t* sel_ptr;
188
+static pv_spec_t* pv_spec;
188 189
 static struct action *mod_func_action;
189 190
 
191
+static struct avp_pvar_spec{
192
+	int type;
193
+	union{
194
+		struct avp_spec avp;
195
+		pv_spec_t pv;
196
+	}u;
197
+} *apv_spec;
198
+
190 199
 static void warn(char* s);
191 200
 static struct socket_id* mk_listen_id(char*, int, int);
192 201
 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);
207 207
 	struct socket_id* sockid;
208 208
 	struct name_lst* name_l;
209 209
 	struct avp_spec* attr;
210
+	struct pv_spec_t* pvar;
211
+	struct avp_pvar_spec* avp_pvar_s;
210 212
 	select_t* select;
211 213
 }
212 214
 
... ...
@@ -426,6 +437,7 @@ static void free_socket_id_lst(struct socket_id* i);
426 426
 %token ATTR_GLOBAL
427 427
 %token ADDEQ
428 428
 
429
+
429 430
 %token STUN_REFRESH_INTERVAL
430 431
 %token STUN_ALLOW_STUN
431 432
 %token STUN_ALLOW_FP
... ...
@@ -452,6 +464,9 @@ static void free_socket_id_lst(struct socket_id* i);
452 452
 %token <strval> ID
453 453
 %token <strval> STRING
454 454
 %token <strval> IPV6ADDR
455
+%token <strval> PVAR
456
+/* not clear yet if this is an avp or pvar */
457
+%token <strval> AVP_OR_PVAR
455 458
 
456 459
 /* other */
457 460
 %token COMMA
... ...
@@ -492,6 +507,8 @@ static void free_socket_id_lst(struct socket_id* i);
492 492
 %type <attr> attr_id_val
493 493
 %type <attr> attr_id_any
494 494
 %type <attr> attr_id_any_str
495
+%type <pvar> pvar
496
+%type <avp_pvar_s> avp_pvar
495 497
 /* %type <intval> class_id */
496 498
 %type <intval> assign_op
497 499
 %type <select> select_id
... ...
@@ -1954,7 +1971,7 @@ attr_id_any_str:
1954 1954
 		s.len = strlen(s.s);
1955 1955
 		if (parse_avp_name(&s, &type, &avp_spec->name, &idx)) {
1956 1956
 			yyerror("error when parsing AVP");
1957
-		        pkg_free(avp_spec);
1957
+			pkg_free(avp_spec);
1958 1958
 			YYABORT;
1959 1959
 		}
1960 1960
 		avp_spec->type = type;
... ...
@@ -1962,6 +1979,52 @@ attr_id_any_str:
1962 1962
 		$$ = avp_spec;
1963 1963
 	}
1964 1964
 	;
1965
+
1966
+pvar:	PVAR {
1967
+			pv_spec=pkg_malloc(sizeof(*pv_spec));
1968
+			if (!pv_spec) {
1969
+				yyerror("Not enough memory");
1970
+				YYABORT;
1971
+			}
1972
+			s.s=$1; s.len=strlen(s.s);
1973
+			if (pv_parse_spec(&s, pv_spec)==0){
1974
+				yyerror("unknown script pseudo variable");
1975
+				pkg_free(pv_spec);
1976
+				YYABORT;
1977
+			}
1978
+			$$=pv_spec;
1979
+			BUG("parsed pvar \"%.*s\"\n", s.len, s.s);
1980
+		}
1981
+	;
1982
+
1983
+avp_pvar:	AVP_OR_PVAR {
1984
+			apv=pkg_malloc(sizeof(*apv));
1985
+			if (!apv) {
1986
+				yyerror("Not enough memory");
1987
+				YYABORT;
1988
+			}
1989
+			s.s=$1; s.len=strlen(s.s);
1990
+			if (pv_parse_spec(&s, &apv_spec->u.pv)==0){
1991
+				/* not a pvar, try avps */
1992
+				/* TODO: test if in ser or k mode */
1993
+				if (parse_avp_name(&s, &type, &apv_spec->u.avp.name, &idx)) {
1994
+					yyerror("error when parsing AVP");
1995
+					pkg_free(apv_spec);
1996
+					YYABORT;
1997
+				}
1998
+				apv_spec->u.avp.type = type;
1999
+				apv_spec->u.avp.index = idx;
2000
+				apv_spec.type=APV_AVP_T;
2001
+			}else{
2002
+				apv_spec.type=APV_PVAR_T;
2003
+			}
2004
+			$$ = apv_spec;
2005
+			BUG("parsed ambigous avp/pvar \"%.*s\" to %d\n", s.len, s.s,
2006
+					apv_spec.type);
2007
+		}
2008
+	;
2009
+
2010
+
1965 2011
 /*
1966 2012
 assign_op:
1967 2013
 	ADDEQ { $$ = ADD_T; }
... ...
@@ -1979,6 +2042,8 @@ assign_action:
1979 1979
 	| attr_id_ass assign_op select_id { $$=mk_action($2, 2, AVP_ST, (void*)$1, SELECT_ST, (void*)$3); }
1980 1980
 	| attr_id_ass assign_op LPAREN exp RPAREN { $$ = mk_action($2, 2, AVP_ST, $1, EXPR_ST, $4); }
1981 1981
 	;
1982
+
1983
+
1982 1984
 avpflag_oper:
1983 1985
 	SETAVPFLAG { $$ = 1; }
1984 1986
 	| RESETAVPFLAG { $$ = 0; }