49 |
char * trimws(char *s); |
char * trimws(char *s); |
50 |
char * trimcpy(); |
char * trimcpy(); |
51 |
|
|
52 |
|
static void multiline_begin(void); |
53 |
|
static void multiline_add(char *); |
54 |
|
static void multiline_finish(void); |
55 |
|
static char *multiline_strip_tabs(char *text); |
56 |
|
static int isemptystr(char *text); |
57 |
|
|
58 |
|
static char *multiline_delimiter; |
59 |
|
static int strip_tabs; |
60 |
|
|
61 |
static struct string_list *str_head, *str_tail; |
static struct string_list *str_head, *str_tail; |
62 |
int cfg_line_num; |
int cfg_line_num; |
63 |
char *cfg_file; |
char *cfg_file; |
70 |
|
|
71 |
%} |
%} |
72 |
|
|
73 |
%x STR LIT RX RXM |
%x STR LIT ML |
74 |
|
|
75 |
WS [ \t][ \t]* |
WS [ \t][ \t]* |
76 |
IDENT [a-zA-Z_][a-zA-Z_0-9-]+ |
IDENT [a-zA-Z_][a-zA-Z_0-9-]+ |
81 |
#.*\n { cfg_line_num++; } |
#.*\n { cfg_line_num++; } |
82 |
#.* /* end-of-file comment */; |
#.* /* end-of-file comment */; |
83 |
/* Keywords */ |
/* Keywords */ |
|
[aA][nN][dD] return AND; |
|
|
[oO][rR] return OR; |
|
|
[nN][oO][tT] return NOT; |
|
84 |
BEGIN return T_BEGIN; |
BEGIN return T_BEGIN; |
85 |
{LDASHES}BEGIN{WS}{IDENT}{RDASHES} { |
{LDASHES}BEGIN{WS}{IDENT}{RDASHES} { |
86 |
char *p = strstr(yytext, "BEGIN") + 5; |
char *p = strstr(yytext, "BEGIN") + 5; |
99 |
return D_BEGIN; } |
return D_BEGIN; } |
100 |
END | |
END | |
101 |
{LDASHES}END{RDASHES} return T_END; |
{LDASHES}END{RDASHES} return T_END; |
102 |
[hH][eE][aA][dD][eE][rR] return T_HEADER; |
[aA][nN][dD] return AND; |
103 |
[cC][oO][mM][mM][aA][nN][dD] return T_COMMAND; |
[oO][rR] return OR; |
104 |
/* Backward compatible (unquoted) regular expressions */ |
[nN][oO][tT] return NOT; |
105 |
=[^ \t][^!\n]*/\n { yylval.string = trimws(strdup(yytext + 1)); |
[hH][eE][aA][dD][eE][rR] { yylval.num = HEADER; return T_MSGPART; } |
106 |
DBG("RX0", yylval.string); |
[cC][oO][mM][mM][aA][nN][dD] { yylval.num = COMMAND; return T_MSGPART; } |
107 |
return REGEX; } |
[bB][oO][dD][yY] { yylval.num = BODY; return T_MSGPART; } |
108 |
=[^ \t][^!\n]*!= { BEGIN(RXM); |
[sS][tT][oO][pP] return STOP; |
109 |
yylval.string = malloc(yyleng-2); |
[cC][aA][lL][lL] return CALL; |
110 |
memcpy(yylval.string, yytext + 1, yyleng-3); |
[iI][fF] return IF; |
111 |
yylval.string[yyleng-3] = 0; |
[fF][iI] return FI; |
112 |
trimws(yylval.string); |
[eE][lL][sS][eE] return ELSE; |
113 |
DBG("RX1", yylval.string); |
[rR][uU][lL][eE] return RULE; |
114 |
return REGEX; } |
[dD][oO][nN][eE] return DONE; |
115 |
=[^ \t][^!\n]*! { BEGIN(RX); |
[aA][dD][dD] return ADD; |
116 |
string_begin(); |
[rR][eE][mM][oO][vV][eE] return REMOVE; |
117 |
string_add(yytext+1, yyleng-1); } |
[mM][oO][dD][iI][fF][yY] return MODIFY; |
118 |
<RX>[^!\n]*!= { BEGIN(RXM); |
|
|
string_add(yytext, yyleng - 2); |
|
|
string_finish(); |
|
|
trimws(yylval.string); |
|
|
DBG("RX2", yylval.string); |
|
|
return REGEX; } |
|
|
<RX>[^!\n]*/\n { BEGIN(INITIAL); |
|
|
string_add(yytext, yyleng); |
|
|
string_finish(); |
|
|
trimws(yylval.string); |
|
|
DBG("RX2", yylval.string); |
|
|
return REGEX; } |
|
|
<RX>[^!\n]*! { string_add(yytext, yyleng); } |
|
|
<RXM>[^!\n]*/\n { BEGIN(INITIAL); |
|
|
yylval.string = trimcpy(); |
|
|
DBG("RX3", yylval.string); |
|
|
return REGEX; } |
|
|
<RXM>[^!\n]*! { int i; |
|
|
|
|
|
BEGIN(RX); |
|
|
string_begin(); |
|
|
for (i = 0; i < yyleng && isspace(yytext[i]); i++) |
|
|
; |
|
|
string_add(yytext + i, yyleng - i); } |
|
|
= return EQ; |
|
|
!= return NE; |
|
|
[iI][fF] return IF; |
|
|
[fF][iI] return FI; |
|
|
[eE][lL][sS][eE] return ELSE; |
|
|
[rR][uU][lL][eE] return RULE; |
|
|
[dD][oO][nN][eE] return DONE; |
|
119 |
/* Literal */ |
/* Literal */ |
120 |
<LIT>[^\n]*/\n { BEGIN(INITIAL); |
<LIT>[^\n]*/\n { BEGIN(INITIAL); |
121 |
yylval.string = trimcpy(); |
yylval.string = trimcpy(); |
127 |
return IDENT; } |
return IDENT; } |
128 |
/* Quoted strings */ |
/* Quoted strings */ |
129 |
\"[^\\"\n]*\" { return simple_string(); } |
\"[^\\"\n]*\" { return simple_string(); } |
130 |
|
\"[^\\"\n]*\\[0-9] {BEGIN(STR); |
131 |
|
string_begin(); |
132 |
|
string_add(yytext+1, yyleng-1); |
133 |
|
} |
134 |
\"[^\\"\n]*\\. { BEGIN(STR); |
\"[^\\"\n]*\\. { BEGIN(STR); |
135 |
string_begin(); |
string_begin(); |
136 |
string_add(yytext+1, yyleng-3); |
string_add(yytext+1, yyleng-3); |
137 |
string_add_char(escape(yytext[yyleng-1])); } |
string_add_char(escape(yytext[yyleng-1])); } |
138 |
|
<STR>[^\\"\n]*\\[0-9] { string_add(yytext, yyleng); } |
139 |
<STR>[^\\"\n]*\\. { string_add(yytext, yyleng-2); |
<STR>[^\\"\n]*\\. { string_add(yytext, yyleng-2); |
140 |
string_add_char(escape(yytext[yyleng-1])); } |
string_add_char(escape(yytext[yyleng-1])); } |
141 |
<STR>[^\\"\n]*\" { BEGIN(INITIAL); |
<STR>[^\\"\n]*\" { BEGIN(INITIAL); |
142 |
string_add(yytext, yyleng-1); |
string_add(yytext, yyleng-1); |
143 |
string_finish(); |
string_finish(); |
144 |
return STRING; } |
return STRING; } |
145 |
|
/* "Here document" (multiline strings) */ |
146 |
|
"<<"-?{IDENT}[ \t]*\n | |
147 |
|
"<<"-?{IDENT}[ \t]*#.*\n { BEGIN(ML); |
148 |
|
multiline_begin(); |
149 |
|
cfg_line_num++; } |
150 |
|
<ML>.*\n { char *p = multiline_strip_tabs(yytext); |
151 |
|
cfg_line_num++; |
152 |
|
|
153 |
|
if (strncmp(p, multiline_delimiter, strlen(multiline_delimiter)) |
154 |
|
== 0 |
155 |
|
&& isemptystr(p + strlen(multiline_delimiter))) { |
156 |
|
BEGIN(INITIAL); |
157 |
|
multiline_finish(); |
158 |
|
unput('\n'); |
159 |
|
return STRING; |
160 |
|
} |
161 |
|
multiline_add(p); |
162 |
|
} |
163 |
/* Other tokens */ |
/* Other tokens */ |
164 |
{WS} ; |
{WS} ; |
165 |
\n { cfg_line_num++; return EOL; } |
\n { cfg_line_num++; return EOL; } |
240 |
*p = 0; |
*p = 0; |
241 |
} |
} |
242 |
|
|
243 |
|
void |
244 |
|
multiline_begin() |
245 |
|
{ |
246 |
|
char *endp; |
247 |
|
int len; |
248 |
|
char *p = yytext + 2; /* past the << marker */ |
249 |
|
|
250 |
|
if (*p == '-') { |
251 |
|
strip_tabs = 1; |
252 |
|
p++; |
253 |
|
} else |
254 |
|
strip_tabs = 0; |
255 |
|
|
256 |
|
/* Find the delimiter */ |
257 |
|
for (endp = p; *endp; endp++) |
258 |
|
if (isspace(*endp)) |
259 |
|
break; |
260 |
|
|
261 |
|
len = endp - p; |
262 |
|
multiline_delimiter = xmalloc(len + 1); |
263 |
|
memcpy(multiline_delimiter, p, len); |
264 |
|
multiline_delimiter[len] = 0; |
265 |
|
string_begin(); |
266 |
|
} |
267 |
|
|
268 |
|
void |
269 |
|
multiline_finish() |
270 |
|
{ |
271 |
|
free (multiline_delimiter); |
272 |
|
multiline_delimiter = NULL; |
273 |
|
string_finish(); |
274 |
|
} |
275 |
|
|
276 |
|
int |
277 |
|
isemptystr(char *text) |
278 |
|
{ |
279 |
|
for (; *text && isspace(*text); text++) |
280 |
|
; |
281 |
|
return *text == 0; |
282 |
|
} |
283 |
|
|
284 |
|
char * |
285 |
|
multiline_strip_tabs(char *text) |
286 |
|
{ |
287 |
|
if (strip_tabs) |
288 |
|
for (; *text == '\t'; text++) |
289 |
|
; |
290 |
|
return text; |
291 |
|
} |
292 |
|
|
293 |
|
void |
294 |
|
multiline_add(char *p) |
295 |
|
{ |
296 |
|
string_add(p, strlen(p)); |
297 |
|
} |
298 |
|
|
299 |
int |
int |
300 |
escape(int c) |
escape(int c) |
301 |
{ |
{ |