2
0
Эх сурвалжийг харах

- new config parser (not finished yet)

Andrei Pelinescu-Onciul 24 жил өмнө
parent
commit
3c1a8ef8f8
2 өөрчлөгдсөн 435 нэмэгдсэн , 0 устгасан
  1. 252 0
      cfg.lex
  2. 183 0
      cfg.y

+ 252 - 0
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++;
+		}
+	}
+}
+
+

+ 183 - 0
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");
+}