[sr-dev] [PATCH] Adding define/ifdef/ifndef to cfg preprocessing
Andrei Pelinescu-Onciul
andrei at iptel.org
Tue Oct 13 12:13:10 CEST 2009
On Oct 02, 2009 at 02:51, Bogdan Harjoc <harjoc at gmail.com> 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.
Good idea. I would only add support for comments
(e.g. endif # from ifdef FOO) and probaby would also allow defines on
the command line.
What we should decide is if we go with #!define or some other format
(e.g. .define FOO). We should use the same format for
include/include_file.
Once we get this solved we could apply the patch (though probably on
master, it should go on sr_3.0 only if someone tests it extensively).
Andrei
>
> 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 at lists.sip-router.org
> http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
More information about the sr-dev
mailing list