- new config parser (not finished yet)
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Tue, 18 Sep 2001 04:56:43 +0000 (04:56 +0000)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Tue, 18 Sep 2001 04:56:43 +0000 (04:56 +0000)
cfg.lex [new file with mode: 0644]
cfg.y [new file with mode: 0644]

diff --git a/cfg.lex b/cfg.lex
new file mode 100644 (file)
index 0000000..d31c2b2
--- /dev/null
+++ b/cfg.lex
@@ -0,0 +1,252 @@
+/*
+ * $Id$
+ *
+ * scanner for cfg files
+ */
+
+
+%{
+       #include "cfg.tab.h"
+       #include <string.h>
+
+       /* states */
+       #define INITIAL_S               0
+       #define COMMENT_S               1
+       #define COMMENT_LN_S    2
+       #define STRING_S                3
+
+       
+       static int comment_nest=0;
+       static int state=0;
+       static char* str=0;
+       int line=0;
+       int column=0;
+
+       static char* addstr(char*, char**);
+       static void count();
+
+
+%}
+
+/* start conditions */
+%x STRING1 STRING2 COMMENT COMMENT_LN
+
+/* action keywords */
+FORWARD        forward
+DROP   drop
+SEND   send
+LOG            log
+ERROR  error
+ROUTE  route
+/* condition keywords */
+METHOD method
+URI            uri
+SRCIP  src_ip
+DSTIP  dst_ip
+/* operators */
+EQUAL  =
+EQUAL_T        ==
+MATCH  ~=
+NOT            !
+AND            "and"|"&&"|"&"
+OR             "or"|"||"|"|"
+
+/* config vars. */
+DEBUG  debug
+FORK   fork
+LOGSTDERROR    log_stderror
+LISTEN         listen
+DNS             dns
+REV_DNS         rev_dns
+
+/* values */
+YES                    "yes"|"true"|"on"|"enable"
+NO                     "no"|"false"|"off"|"disable"
+
+LETTER         [a-zA-Z]
+DIGIT          [0-9]
+ALPHANUM       {LETTER}|{DIGIT}
+NUMBER         {DIGIT}+
+ID                     {LETTER}{ALPHANUM}*
+QUOTES         \"
+TICK           \'
+SLASH          "/"
+SEMICOLON      ;
+RPAREN         \)
+LPAREN         \(
+LBRACE         \{
+RBRACE         \}
+LBRACK         \[
+RBRACK         \]
+COMMA          ,
+DOT                    \.
+CR                     \n
+
+
+
+COM_LINE       #
+COM_START      "/\*"
+COM_END                "\*/"
+
+EAT_ABLE       [\ \t\b\r]
+
+%%
+
+
+<INITIAL>{EAT_ABLE}    { count(); }
+
+<INITIAL>{FORWARD}     {count(); yylval.strval=yytext; return FORWARD; }
+<INITIAL>{DROP}        { count(); yylval.strval=yytext; return DROP; }
+<INITIAL>{SEND}        { count(); yylval.strval=yytext; return SEND; }
+<INITIAL>{LOG} { count(); yylval.strval=yytext; return LOG; }
+<INITIAL>{ERROR}       { count(); yylval.strval=yytext; return ERROR; }
+<INITIAL>{ROUTE}       { count(); yylval.strval=yytext; return ROUTE; }
+
+<INITIAL>{METHOD}      { count(); yylval.strval=yytext; return METHOD; }
+<INITIAL>{URI} { count(); yylval.strval=yytext; return URI; }
+<INITIAL>{SRCIP}       { count(); yylval.strval=yytext; return SRCIP; }
+<INITIAL>{DSTIP}       { count(); yylval.strval=yytext; return DSTIP; }
+
+<INITIAL>{DEBUG}       { count(); yylval.strval=yytext; return DEBUG; }
+<INITIAL>{FORK}                { count(); yylval.strval=yytext; return FORK; }
+<INITIAL>{LOGSTDERROR} { yylval.strval=yytext; return LOGSTDERROR; }
+<INITIAL>{LISTEN}      { count(); yylval.strval=yytext; return LISTEN; }
+<INITIAL>{DNS} { count(); yylval.strval=yytext; return DNS; }
+<INITIAL>{REV_DNS}     { count(); yylval.strval=yytext; return REV_DNS; }
+
+<INITIAL>{EQUAL}       { count(); return EQUAL; }
+<INITIAL>{EQUAL_T}     { count(); return EQUAL_T; }
+<INITIAL>{MATCH}       { count(); return MATCH; }
+<INITIAL>{NOT}         { count(); return NOT; }
+<INITIAL>{AND}         { count(); return AND; }
+<INITIAL>{OR}          { count(); return OR;  }
+
+<INITIAL>{NUMBER}              { count(); yylval.intval=atoi(yytext);
+                                                       return NUMBER; }
+<INITIAL>{YES}                 { count(); yylval.intval=1; return NUMBER; }
+<INITIAL>{NO}                  { count(); yylval.intval=0; return NUMBER; }
+
+<INITIAL>{COMMA}               { count(); return COMMA; }
+<INITIAL>{SEMICOLON}   { count(); return SEMICOLON; }
+<INITIAL>{RPAREN}      { count(); return RPAREN; }
+<INITIAL>{LPAREN}      { count(); return LPAREN; }
+<INITIAL>{LBRACE}      { count(); return LBRACE; }
+<INITIAL>{RBRACE}      { count(); return RBRACE; }
+<INITIAL>{LBRACK}      { count(); return LBRACK; }
+<INITIAL>{RBRACK}      { count(); return RBRACK; }
+<INITIAL>{SLASH}       { count(); return SLASH; }
+<INITIAL>{DOT}         { count(); return DOT; }
+<INITIAL>\\{CR}                {count(); } /* eat the escaped CR */
+<INITIAL>{CR}          { count(); return CR; }
+
+
+<INITIAL>{QUOTES} { count(); state=STRING_S; BEGIN(STRING1); }
+<INITIAL>{TICK} { count(); state=STRING_S; BEGIN(STRING2); }
+
+
+<STRING1>{QUOTES} { count(); state=INITIAL_S; BEGIN(INITIAL); 
+                                               yytext[yyleng-1]=0; yyleng--;
+                                               addstr(yytext, &str);
+                                               if (str){
+                                                       printf("Found string1 <%s>\n", str);
+                                                       yyleng=strlen(str)+1;
+                                                       memcpy(yytext, str, yyleng);
+                                                       free(str);
+                                                       str=0;
+                                               }else{
+                                                       printf("WARNING: empty string\n");
+                                               }
+                                               yylval.strval=yytext; return STRING;
+                                       }
+<STRING2>{TICK}  { count(); state=INITIAL_S; BEGIN(INITIAL); 
+                                               yytext[yyleng-1]=0; yyleng--;
+                                               printf("Found string1 <%s>\n", yytext);
+                                               yylval.strval=yytext; return STRING;
+                                       }
+<STRING2>.|{EAT_ABLE}|{CR}     { yymore(); }
+
+<STRING1>\\n           { count(); yytext[yyleng-2]='\n';yytext[yyleng-1]=0; 
+                                               yyleng--; addstr(yytext, &str); }
+<STRING1>\\t           { count(); yytext[yyleng-2]='\t';yytext[yyleng-1]=0; 
+                                               yyleng--; addstr(yytext, &str); }
+<STRING1>\\\\          { count(); yytext[yyleng-2]='\\';yytext[yyleng-1]=0; 
+                                               yyleng--; addstr(yytext, &str); } 
+<STRING1>.|{EAT_ABLE}|{CR}     { yymore(); }
+
+
+<INITIAL,COMMENT>{COM_START}   { count(); comment_nest++; state=COMMENT_S;
+                                                                               BEGIN(COMMENT); }
+<COMMENT>{COM_END}                             { count(); comment_nest--;
+                                                                               if (comment_nest==0){
+                                                                                       state=INITIAL_S;
+                                                                                       BEGIN(INITIAL);
+                                                                               }
+                                                               }
+<COMMENT>.|{EAT_ABLE}|{CR}                             { count(); };
+
+<INITIAL>{COM_LINE}.*{CR}      { count(); } 
+
+<INITIAL>{ID}                  { count(); yylval.strval=yytext; return ID; }
+
+
+<<EOF>>                                                        {
+                                                                       switch(state){
+                                                                               case STRING_S: 
+                                                                                       printf("Unexpected EOF: closed string\n");
+                                                                                       if (str) {free(str); str=0;}
+                                                                                       break;
+                                                                               case COMMENT_S:
+                                                                                       printf("Unexpected EOF:%d comments open\n", comment_nest);
+                                                                                       break;
+                                                                               case COMMENT_LN_S:
+                                                                                       printf("Unexpected EOF: comment line open\n");
+                                                                                       break;
+                                                                       }
+                                                                       return 0;
+                                                               }
+                       
+%%
+
+static char* addstr(char * src, char ** dest)
+{
+       char *tmp;
+       int len1, len2;
+       
+       if (*dest==0){
+               *dest=strdup(src);
+       }else{
+               len1=strlen(*dest);
+               len2=strlen(src);
+               tmp=malloc(len1+len2+1);
+               if (tmp==0) goto error;
+               memcpy(tmp, *dest, len1);
+               memcpy(tmp+len1, src, len2);
+               tmp[len1+len2]=0;
+               free(*dest);
+               *dest=tmp;
+       }
+       return *dest;
+error:
+       fprintf(stderr, "lex:addstr: memory allocation error\n");
+       return 0;
+}
+
+
+
+static void count()
+{
+       int i;
+       
+       for (i=0; i<yyleng;i++){
+               if (yytext[i]=='\n'){
+                       line++;
+                       column=0;
+               }else if (yytext[i]=='\t'){
+                       column+=8 -(column%8);
+               }else{
+                       column++;
+               }
+       }
+}
+
+
diff --git a/cfg.y b/cfg.y
new file mode 100644 (file)
index 0000000..05e7ccb
--- /dev/null
+++ b/cfg.y
@@ -0,0 +1,183 @@
+/*
+ * $Id$
+ *
+ *  cfg grammar
+ */
+
+%{
+
+%}
+
+%union {
+       int intval;
+       char* strval;
+}
+
+/* terminals */
+
+
+/* keywors */
+%token FORWARD
+%token SEND
+%token DROP
+%token LOG
+%token ERROR
+%token ROUTE
+%token METHOD
+%token URI
+%token SRCIP
+%token DSTIP
+
+/* config vars. */
+%token DEBUG
+%token FORK
+%token LOGSTDERROR
+%token LISTEN
+%token DNS
+%token REV_DNS
+
+
+/* operators */
+%nonassoc EQUAL
+%nonassoc EQUAL_T
+%nonassoc MATCH
+%left NOT
+%left AND
+%left OR
+
+/* values */
+%token NUMBER
+%token ID
+%token STRING
+
+/* other */
+%token COMMA
+%token SEMICOLON
+%token RPAREN
+%token LPAREN
+%token LBRACE
+%token RBRACE
+%token LBRACK
+%token RBRACK
+%token SLASH
+%token DOT
+%token CR
+
+
+/*non-terminals */
+
+
+
+%%
+
+
+cfg:   statements
+       ;
+
+statements:    statements statement {printf("got <> <>\n");}
+                       | statement {printf("got a statement<>\n"); }
+       ;
+
+statement:     assign_stm CR
+                       | route_stm CR
+                       | CR    /* null statement*/
+       ;
+
+assign_stm:    DEBUG EQUAL NUMBER |
+                       FORK  EQUAL NUMBER |
+                       LOGSTDERROR EQUAL NUMBER |
+                       DNS EQUAL NUMBER |
+                       REV_DNS EQUAL NUMBER |
+                       LISTEN EQUAL ipv4 |
+                       LISTEN EQUAL ID |
+                       LISTEN EQUAL STRING 
+       ;
+
+
+ipv4:  NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
+       ;
+
+route_stm:     ROUTE LBRACE rules RBRACE |
+                       ROUTE LBRACK NUMBER RBRACK LBRACE rules RBRACE
+       ;
+
+rules: rules rule |
+               rule
+        ;
+
+rule:  condition       actions CR
+               | CR  /* null rule */
+       ;
+
+condition:     exp_elem |
+                       LPAREN exp RPAREN
+       ;
+
+exp:   exp AND condition |
+               exp OR  condition |
+               NOT condition |
+               condition
+       ;
+
+exp_elem:      METHOD EQUAL_T STRING |
+                       METHOD EQUAL_T ID |
+                       METHOD MATCH STRING |
+                       METHOD MATCH ID |
+                       URI EQUAL_T STRING |
+                       URI EQUAL_T ID |
+                       URI MATCH STRING |
+                       URI MATCH ID |
+                       SRCIP EQUAL_T net4 |
+                       SRCIP EQUAL_T STRING |
+                       SRCIP EQUAL_T host |
+                       SRCIP MATCH STRING 
+                       DSTIP EQUAL_T net4 |
+                       DSTIP EQUAL_T STRING |
+                       DSTIP MATCH STRING
+       ;
+
+net4:  ipv4 SLASH ipv4 |
+               ipv4 SLASH NUMBER |
+               ipv4
+       ;
+
+host:  ID |
+               host DOT ID
+       ;
+
+
+actions:       actions action |
+                       action
+       ;
+
+action:                cmd SEMICOLON |
+                       SEMICOLON /* null action */
+
+cmd:           FORWARD LPAREN host RPAREN |
+                       FORWARD LPAREN STRING RPAREN |
+                       FORWARD LPAREN ipv4 RPAREN |
+                       SEND LPAREN host RPAREN |
+                       SEND LPAREN STRING RPAREN |
+                       SEND LPAREN ipv4 RPAREN |
+                       DROP LPAREN RPAREN |
+                       DROP |
+                       LOG LPAREN STRING RPAREN |
+                       ERROR LPAREN STRING COMMA STRING RPAREN |
+                       ROUTE LPAREN NUMBER RPAREN
+       ;
+
+
+%%
+
+extern int line;
+extern int column;
+yyerror(char* s)
+{
+       fprintf(stderr, "parse error (%d,%d): %s\n", line, column, s);
+}
+
+int main(int argc, char ** argv)
+{
+       if (yyparse()!=0)
+               fprintf(stderr, "parsing error\n");
+}