[sr-dev] [PATCH] Adding define/ifdef/ifndef to cfg preprocessing

Daniel-Constantin Mierla miconda at gmail.com
Fri Oct 2 08:16:51 CEST 2009


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 at 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
* http://www.asipto.com/index.php/sip-router-masterclass/




More information about the sr-dev mailing list