[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