Hello Bogdan,
this looks very good and it is very useful. Thanks!
I will look over it, since these makes the include addition complete, it
worth being in next release. We will get today in touch at devel meeting
and discuss if it is the case.
Cheers,
Daniel
On 02.10.2009 2:51 Uhr, Bogdan Harjoc wrote:
Since include_file was just added, why not go one
extra step and
allow things like (adapted from etc/kamailio.cfg):
#!define PRESENCE
#!ifdef PRESENCE
loadmodule "presence.so"
loadmodule "presence_xml.so"
#!else
#!ifndef KAMAILIO
...
#!endif
#!endif
M4 is already used and a better alternative IMO, but cfg is clearly not a
typical language, so I imagine someone may find this useful. Patch against
commit 7362f824.
For a minimal test input, this can be used:
=====
listen=::1
#!define xyz
#!ifdef xyz
listen=::2
#!ifndef abc
listen=::3
#!else
listen=::4
#!endif
listen=::5
#!endif
=====
While wr're at it, the ID token seemed wrong -- it misses
_ids_that_start_with_underscores (?).
Bogdan
diff --git a/cfg.lex b/cfg.lex
index 8490364..df4a2ee 100644
--- a/cfg.lex
+++ b/cfg.lex
@@ -105,6 +105,12 @@
#define PVAR_P_S 7 /* pvar: $(...) or $foo(...)*/
#define PVARID_S 8 /* $foo.bar...*/
#define STR_BETWEEN_S 9
+ #define LINECOMMENT_S 10
+ #define DEFINE_S 11
+ #define DEFINE_EOL_S 12
+ #define IFDEF_S 13
+ #define IFDEF_EOL_S 14
+ #define IFDEF_SKIP_S 15
#define STR_BUF_ALLOC_UNIT 128
struct str_buf{
@@ -152,11 +158,18 @@
struct sr_yy_fname *next;
} *sr_yy_fname_list = 0;
+ static int pp_define(int len, const char * text);
+ static int pp_ifdef_type(int pos);
+ static void pp_ifdef_var(int len, const char * text);
+ static void pp_ifdef();
+ static void pp_else();
+ static void pp_endif();
%}
/* start conditions */
%x STRING1 STRING2 STR_BETWEEN COMMENT COMMENT_LN ATTR SELECT
AVP_PVAR PVAR_P
%x PVARID INCLF
+%x LINECOMMENT DEFINE_ID DEFINE_EOL IFDEF_ID IFDEF_EOL IFDEF_SKIP
/* config script types : #!SER or #!KAMAILIO or #!MAX_COMPAT */
SER_CFG SER
@@ -474,8 +487,9 @@ TLSv1
"tlsv1"|"TLSv1"|"TLSV1"
LETTER [a-zA-Z]
DIGIT [0-9]
-ALPHANUM {LETTER}|{DIGIT}|[_]
-ID {LETTER}{ALPHANUM}*
+LETTER_ {LETTER}|[_]
+ALPHANUM {LETTER_}|{DIGIT}
+ID {LETTER_}{ALPHANUM}*
NUM_ID {ALPHANUM}+
HEX [0-9a-fA-F]
HEXNUMBER 0x{HEX}+
@@ -506,6 +520,12 @@ COM_LINE #
COM_START "/\*"
COM_END "\*/"
+DEFINE define
+IFDEF ifdef
+IFNDEF ifndef
+ENDIF endif
+/* else is already defined */
+
EAT_ABLE [\ \t\b\r]
%%
@@ -1121,7 +1141,36 @@ EAT_ABLE [\ \t\b\r]
sr_cfg_compat=SR_COMPAT_KAMAILIO;}
<INITIAL>{COM_LINE}!{MAXCOMPAT_CFG}{CR} { count();
sr_cfg_compat=SR_COMPAT_MAX;}
-<INITIAL>{COM_LINE}.*{CR} { count(); }
+
+<INITIAL>{COM_LINE}!{DEFINE}{EAT_ABLE}+ { count();
+ state = DEFINE_S;
BEGIN(DEFINE_ID); }
+<DEFINE_ID>{ID} { count();
+ if (pp_define(yyleng,
yytext)) return 1;
+ state = DEFINE_EOL_S;
BEGIN(DEFINE_EOL); }
+<DEFINE_EOL>{EAT_ABLE}*{CR} { count();
+ state = INITIAL;
BEGIN(INITIAL); }
+
+<INITIAL,IFDEF_SKIP>{COM_LINE}!{IFDEF}{EAT_ABLE}+ { count();
+ if
(pp_ifdef_type(1)) return 1;
+ state =
IFDEF_S; BEGIN(IFDEF_ID); }
+<INITIAL,IFDEF_SKIP>{COM_LINE}!{IFNDEF}{EAT_ABLE}+ { count();
+ if
(pp_ifdef_type(0)) return 1;
+ state =
IFDEF_S; BEGIN(IFDEF_ID); }
+<IFDEF_ID>{ID} { count();
+ pp_ifdef_var(yyleng, yytext);
+ state = IFDEF_EOL_S; BEGIN(IFDEF_EOL); }
+<IFDEF_EOL>{EAT_ABLE}*{CR} { count(); pp_ifdef(); }
+
+<INITIAL,IFDEF_SKIP>{COM_LINE}!{ELSE}{EAT_ABLE}*{CR} { count();
pp_else(); }
+
+<INITIAL,IFDEF_SKIP>{COM_LINE}!{ENDIF}{EAT_ABLE}*{CR} { count();
pp_endif(); }
+
+ /* we're in an ifdef that evaluated to false -- throw it away */
+<IFDEF_SKIP>.|{CR} { count(); }
+
+ /* this is split so the shebangs match more, giving them priority */
+<INITIAL>{COM_LINE} { count(); state = LINECOMMENT_S;
BEGIN(LINECOMMENT); }
+<LINECOMMENT>.*{CR} { count(); state = INITIAL_S;
BEGIN(INITIAL); }
<INITIAL>{ID} { count(); addstr(&s_buf, yytext, yyleng);
yylval.strval=s_buf.s;
@@ -1472,3 +1521,102 @@ static int sr_pop_yy_state()
return 0;
}
+/* define/ifdef support */
+
+#define MAX_DEFINES 1024
+static str pp_defines[MAX_DEFINES];
+static int pp_num_defines = 0;
+
+/* pp_ifdef_stack[i] is 1 if the ifdef test at depth i is either
+ * ifdef(defined), ifndef(undefined), or the opposite of these
+ * two, but in an else branch
+ */
+#define MAX_IFDEFS 16
+static int pp_ifdef_stack[MAX_IFDEFS];
+static int pp_sptr = 0; /* stack pointer */
+
+static int pp_lookup(int len, const char * text)
+{
+ str var = {(char *)text, len};
+ int i;
+
+ for (i=0; i<pp_num_defines; i++)
+ if (STR_EQ(pp_defines[i], var))
+ return i;
+
+ return -1;
+}
+
+static int pp_define(int len, const char * text)
+{
+ if (pp_num_defines == MAX_DEFINES) {
+ LOG(L_CRIT, "ERROR: too many defines -- adjust MAX_DEFINES\n");
+ return -1;
+ }
+
+ if (pp_lookup(len, text) >= 0) {
+ LOG(L_CRIT, "ERROR: already defined: %.*s\n", len, text);
+ return -1;
+ }
+
+ pp_defines[pp_num_defines].len = len;
+ pp_defines[pp_num_defines].s = (char*)pkg_malloc(len+1);
+ memcpy(pp_defines[pp_num_defines].s, text, len);
+ pp_num_defines++;
+
+ return 0;
+}
+
+static int pp_ifdef_type(int type)
+{
+ if (pp_sptr == MAX_IFDEFS) {
+ LOG(L_CRIT, "ERROR: too many nested ifdefs -- adjust
MAX_IFDEFS\n");
+ return -1;
+ }
+
+ pp_ifdef_stack[pp_sptr] = type;
+ return 0;
+}
+
+/* this sets the result of the if[n]def expr:
+ * ifdef defined -> 1
+ * ifdef undefined -> 0
+ * ifndef defined -> 0
+ * ifndef undefined -> 1
+ */
+static void pp_ifdef_var(int len, const char * text)
+{
+ pp_ifdef_stack[pp_sptr] ^= (pp_lookup(len, text) < 0);
+}
+
+static void pp_update_state()
+{
+ int i;
+
+ for (i=0; i<pp_sptr; i++)
+ if (! pp_ifdef_stack[i]) {
+ state = IFDEF_SKIP_S; BEGIN(IFDEF_SKIP);
+ return;
+ }
+
+ state = INITIAL; BEGIN(INITIAL);
+}
+
+static void pp_ifdef()
+{
+ pp_sptr++;
+ pp_update_state();
+}
+
+static void pp_else()
+{
+ pp_ifdef_stack[pp_sptr-1] ^= 1;
+ pp_update_state();
+}
+
+static void pp_endif()
+{
+ pp_sptr--;
+ pp_update_state();
+}
+
------------------------------------------------------------------------
_______________________________________________
sr-dev mailing list
sr-dev(a)lists.sip-router.org
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
--
Daniel-Constantin Mierla
* Kamailio SIP Masterclass, Nov 9-13, 2009, Berlin
*