Module: sip-router
Branch: master
Commit: d20565193c1176312a29d75710d494707abdf6a5
URL:    
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=d20565193c1176312a29d75710d494707abdf6a5

Author: Daniel-Constantin Mierla <[email protected]>
Committer: Daniel-Constantin Mierla <[email protected]>
Date:   Tue Aug 25 19:27:01 2009 +0300

core: support for include file in cfg

- syntax:
include path/to/file
- example:
include checks.cfg
- path can be absolute or relative
- if path is relative:
        - first attempt is to open the file relative to current directory
        - second attempt is to open the file relative to the directory
        of the file including it
- if include file fails, then print error and exit
- cfg syntax error messages print file name
- there is no restriction where 'include' can be used, can have
global parameters, module configs or entire/parts of route blocks

---

 cfg.lex        |  159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 cfg.y          |   29 ++++++-----
 route_struct.h |    1 +
 3 files changed, 174 insertions(+), 15 deletions(-)

diff --git a/cfg.lex b/cfg.lex
index ebe2b6d..079613d 100644
--- a/cfg.lex
+++ b/cfg.lex
@@ -122,6 +122,7 @@
        int column=1;
        int startcolumn=1;
        int startline=1;
+       char *finame = 0;
        static int ign_lines=0;
        static int ign_columns=0;
        char* yy_number_str=0; /* str correspondent for the current NUMBER 
token */
@@ -132,12 +133,30 @@
        static void count_more();
        static void count_ignore();
 
+       #define MAX_INCLUDE_DEPTH 10
+       static struct sr_yy_state {
+               YY_BUFFER_STATE state;
+               int line;
+               int column;
+               int startcolumn;
+               int startline;
+               char *finame;
+       } include_stack[MAX_INCLUDE_DEPTH];
+       static int include_stack_ptr = 0;
+
+       static int sr_push_yy_state(char *fin);
+       static int sr_pop_yy_state();
+
+       static struct sr_yy_fname {
+               char *fname;
+               struct sr_yy_fname *next;
+       } *sr_yy_fname_list = 0;
 
 %}
 
 /* start conditions */
 %x STRING1 STRING2 STR_BETWEEN COMMENT COMMENT_LN ATTR SELECT AVP_PVAR PVAR_P 
-%x PVARID
+%x PVARID INCL
 
 /* config script types : #!SER  or #!KAMAILIO or #!MAX_COMPAT */
 SER_CFG                        SER
@@ -201,6 +220,8 @@ CASE                        "case"
 DEFAULT                        "default"
 WHILE                  "while"
 
+INCLUDE         "include"
+
 /*ACTION LVALUES*/
 URIHOST                        "uri:host"
 URIPORT                        "uri:port"
@@ -556,6 +577,8 @@ EAT_ABLE    [\ \t\b\r]
 <INITIAL>{DEFAULT}     { count(); yylval.strval=yytext; return DEFAULT; }
 <INITIAL>{WHILE}       { count(); yylval.strval=yytext; return WHILE; }
 
+<INITIAL>{INCLUDE}  { BEGIN(INCL); }
+
 <INITIAL>{URIHOST}     { count(); yylval.strval=yytext; return URIHOST; }
 <INITIAL>{URIPORT}     { count(); yylval.strval=yytext; return URIPORT; }
 
@@ -1097,6 +1120,13 @@ EAT_ABLE [\ \t\b\r]
 
 <SELECT>.               { unput(yytext[0]); state = INITIAL_S; BEGIN(INITIAL); 
} /* Rescan the token in INITIAL state */
 
+<INCL>[ \t]*      /* eat the whitespace */
+<INCL>[^ \t\n]+   { /* get the include file name */
+                               if(sr_push_yy_state(yytext)<0)
+                                       exit(-1);
+                               BEGIN(INITIAL);
+}
+
 
 <<EOF>>                                                        {
                                                                        
switch(state){
@@ -1141,7 +1171,8 @@ EAT_ABLE  [\ \t\b\r]
                                                                                
                        " while parsing"
                                                                                
                        " avp or pvar name\n");
                                                                        }
-                                                                       return 
0;
+                                                                       
if(sr_pop_yy_state()<0)
+                                                                               
return 0;
                                                                }
 
 %%
@@ -1253,3 +1284,127 @@ int yywrap()
 {
        return 1;
 }
+
+static int sr_push_yy_state(char *fin)
+{
+       struct sr_yy_fname *fn = NULL;
+       char *x = NULL;
+       char *newf = NULL;
+
+       if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
+       {
+               LOG(L_CRIT, "too many includes\n");
+               return -1;
+       }
+
+       include_stack[include_stack_ptr].state = YY_CURRENT_BUFFER;
+       include_stack[include_stack_ptr].line = line;
+       include_stack[include_stack_ptr].column = column;
+       include_stack[include_stack_ptr].startline = startline;
+       include_stack[include_stack_ptr].startcolumn = startcolumn;
+       include_stack[include_stack_ptr].finame = finame;
+       include_stack_ptr++;
+
+       line=1;
+       column=1;
+       startline=1;
+       startcolumn=1;
+
+       yyin = fopen(fin, "r" );
+
+       if ( ! yyin )
+       {
+               finame = (finame==0)?cfg_file:finame;
+               if(finame==0 || fin[0]=='/')
+               {
+                       LOG(L_CRIT, "cannot open included file: %s\n", fin);
+                       return -1;
+               }
+               x = strrchr(finame, '/');
+               if(x)
+               {
+                       newf = (char*)pkg_malloc(x-finame+strlen(fin)+2);
+                       if(newf==0)
+                       {
+                               LOG(L_CRIT, "no more pkg\n");
+                               return -1;
+                       }
+                       newf[0] = '\0';
+                       strncat(newf, finame, x-finame);
+                       strcat(newf, "/");
+                       strcat(newf, fin);
+               }
+               yyin = fopen(newf, "r" );
+               if ( ! yyin )
+               {
+                       LOG(L_CRIT, "cannot open included file: %s (%s)\n", 
fin, newf);
+                       return -1;
+               }
+               LOG(L_DBG, "including file: %s (%s)\n", fin, newf);
+       } else {
+               newf = fin;
+       }
+
+       fn = sr_yy_fname_list;
+       while(fn!=0)
+       {
+               if(strcmp(fn->fname, newf)==0)
+               {
+                       if(newf!=fin)
+                               pkg_free(newf);
+                       newf = fin;
+                       break;
+               }
+               fn = fn->next;
+       }
+       if(fn==0)
+       {
+               fn = (struct sr_yy_fname*)pkg_malloc(sizeof(struct 
sr_yy_fname));
+               if(fn==0)
+               {
+                       if(newf!=fin)
+                               pkg_free(newf);
+                       LOG(L_CRIT, "no more pkg\n");
+                       return -1;
+               }
+               if(newf==fin)
+               {
+                       fn->fname = (char*)pkg_malloc(strlen(fin)+1);
+                       if(fn->fname==0)
+                       {
+                               pkg_free(fn);
+                               LOG(L_CRIT, "no more pkg!\n");
+                               return -1;
+                       }
+                       strcpy(fn->fname, fin);
+               } else {
+                       fn->fname = newf;
+               }
+               fn->next = sr_yy_fname_list;
+               sr_yy_fname_list = fn;
+       }
+
+       finame = fn->fname;
+
+       yy_switch_to_buffer( yy_create_buffer(yyin, YY_BUF_SIZE ) );
+
+       return 0;
+
+}
+
+static int sr_pop_yy_state()
+{
+       include_stack_ptr--;
+       if (include_stack_ptr<0 )
+               return -1;
+
+       yy_delete_buffer( YY_CURRENT_BUFFER );
+       yy_switch_to_buffer(include_stack[include_stack_ptr].state);
+       line=include_stack[include_stack_ptr].line;
+       column=include_stack[include_stack_ptr].column;
+       startline=include_stack[include_stack_ptr].startline;
+       startcolumn=include_stack[include_stack_ptr].startcolumn;
+       finame = include_stack[include_stack_ptr].finame;
+       return 0;
+}
+
diff --git a/cfg.y b/cfg.y
index 6950d88..25dd635 100644
--- a/cfg.y
+++ b/cfg.y
@@ -3070,7 +3070,7 @@ extern int line;
 extern int column;
 extern int startcolumn;
 extern int startline;
-
+extern char *finame;
 
 static void get_cpos(struct cfg_pos* pos)
 {
@@ -3078,6 +3078,9 @@ static void get_cpos(struct cfg_pos* pos)
        pos->e_line=line;
        pos->s_col=startcolumn;
        pos->e_col=column-1;
+       if(finame==0)
+               finame = (cfg_file!=0)?cfg_file:"default";
+       pos->fname=finame;
 }
 
 
@@ -3090,15 +3093,15 @@ static void warn_at(struct cfg_pos* p, char* format, 
...)
        vsnprintf(s, sizeof(s), format, ap);
        va_end(ap);
        if (p->e_line!=p->s_line)
-               LOG(L_WARN, "warning in config file, from line %d, column %d to"
+               LOG(L_WARN, "warning in config file %s, from line %d, column %d 
to"
                                        " line %d, column %d: %s\n",
-                                       p->s_line, p->s_col, p->e_line, 
p->e_col, s);
+                                       p->fname, p->s_line, p->s_col, 
p->e_line, p->e_col, s);
        else if (p->s_col!=p->e_col)
-               LOG(L_WARN, "warning in config file, line %d, column %d-%d: 
%s\n",
-                                       p->s_line, p->s_col, p->e_col, s);
+               LOG(L_WARN, "warning in config file %s, line %d, column %d-%d: 
%s\n",
+                                       p->fname, p->s_line, p->s_col, 
p->e_col, s);
        else
-               LOG(L_WARN, "warning in config file, line %d, column %d: %s\n",
-                               p->s_line, p->s_col, s);
+               LOG(L_WARN, "warning in config file %s, line %d, column %d: 
%s\n",
+                               p->fname, p->s_line, p->s_col, s);
        cfg_warnings++;
 }
 
@@ -3113,15 +3116,15 @@ static void yyerror_at(struct cfg_pos* p, char* format, 
...)
        vsnprintf(s, sizeof(s), format, ap);
        va_end(ap);
        if (p->e_line!=p->s_line)
-               LOG(L_CRIT, "parse error in config file, from line %d, column 
%d"
+               LOG(L_CRIT, "parse error in config file %s, from line %d, 
column %d"
                                        " to line %d, column %d: %s\n",
-                                       p->s_line, p->s_col, p->e_line, 
p->e_col, s);
+                                       p->fname, p->s_line, p->s_col, 
p->e_line, p->e_col, s);
        else if (p->s_col!=p->e_col)
-               LOG(L_CRIT, "parse error in config file, line %d, column %d-%d: 
%s\n",
-                                       p->s_line, p->s_col, p->e_col, s);
+               LOG(L_CRIT,"parse error in config file %s, line %d, column 
%d-%d: %s\n",
+                                       p->fname, p->s_line, p->s_col, 
p->e_col, s);
        else
-               LOG(L_CRIT, "parse error in config file, line %d, column %d: 
%s\n",
-                                       p->s_line, p->s_col, s);
+               LOG(L_CRIT, "parse error in config file %s, line %d, column %d: 
%s\n",
+                                       p->fname, p->s_line, p->s_col, s);
        cfg_errors++;
 }
 
diff --git a/route_struct.h b/route_struct.h
index 9274340..fcc475e 100644
--- a/route_struct.h
+++ b/route_struct.h
@@ -136,6 +136,7 @@ struct cfg_pos{
        int e_line;
        unsigned short s_col;
        unsigned short e_col;
+       char *fname;
 };
 
 


_______________________________________________
sr-dev mailing list
[email protected]
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev

Reply via email to