Skip to content

Commit 0f51c01

Browse files
authored
Merge pull request syslog-ng#4929 from bazsi/filterx-support-filterx-blocks
Filterx support filterx blocks
2 parents 67bc4e1 + 9467b05 commit 0f51c01

7 files changed

+159
-36
lines changed

lib/block-ref-grammar.ym

+43-7
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,57 @@
4343
%%
4444

4545
start
46-
: {
47-
*result = cfg_args_new();
48-
}
49-
'(' block_args ')' { YYACCEPT; }
46+
: { *result = cfg_args_new(); } block_args { YYACCEPT; }
5047
;
5148

49+
5250
block_args
53-
: block_arg block_args
54-
|
51+
: driver_like_context '(' driver_block_args ')'
52+
| function_like_context '(' function_block_args ')'
53+
;
54+
55+
driver_like_context
56+
: LL_CONTEXT_ROOT
57+
| LL_CONTEXT_DESTINATION
58+
| LL_CONTEXT_SOURCE
59+
| LL_CONTEXT_PARSER
60+
| LL_CONTEXT_REWRITE
61+
| LL_CONTEXT_FILTER
62+
| LL_CONTEXT_LOG
63+
| LL_CONTEXT_INNER_DEST
64+
| LL_CONTEXT_INNER_SRC
65+
| LL_CONTEXT_OPTIONS
66+
;
67+
68+
function_like_context
69+
: LL_CONTEXT_FILTERX
70+
;
71+
72+
73+
/* generator(arg1(value) arg2(value)...) */
74+
driver_block_args
75+
: driver_block_arg driver_block_args
76+
|
5577
;
5678

57-
block_arg
79+
driver_block_arg
5880
: LL_IDENTIFIER _block_arg_context_push LL_BLOCK _block_arg_context_pop { cfg_args_set(*result, $1, $3); free($1); free($3); }
5981
;
6082

83+
/* generator(arg1=value, arg2=value, ...) */
84+
function_block_args
85+
: function_block_arg ',' function_block_args
86+
| function_block_arg
87+
|
88+
;
89+
90+
function_block_arg
91+
: LL_IDENTIFIER KW_ASSIGN _block_func_arg_context_push LL_BLOCK _block_func_arg_context_pop
92+
{
93+
cfg_args_set(*result, $1, $4); free($1); free($4);
94+
}
95+
;
96+
6197
/* INCLUDE_RULES */
6298

6399
%%

lib/cfg-block-generator.c

+8
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ cfg_block_generator_format_name_method(CfgBlockGenerator *self, gchar *buf, gsiz
3434
return buf;
3535
}
3636

37+
static void
38+
_report_generator_args(gpointer key, gpointer value, gpointer user_data)
39+
{
40+
GString *result = (GString *) user_data;
41+
g_string_append_printf(result, "## %s=%s\n", (gchar *) key, (gchar *) value);
42+
}
43+
3744
gboolean
3845
cfg_block_generator_generate(CfgBlockGenerator *self, GlobalConfig *cfg, gpointer args, GString *result,
3946
const gchar *reference)
@@ -42,6 +49,7 @@ cfg_block_generator_generate(CfgBlockGenerator *self, GlobalConfig *cfg, gpointe
4249
cfg_block_generator_format_name(self, block_name, sizeof(block_name)/sizeof(block_name[0]));
4350

4451
g_string_append_printf(result, "\n#Start Block %s\n", block_name);
52+
cfg_args_foreach(args, _report_generator_args, result);
4553
const gboolean res = self->generate(self, cfg, args, result, reference);
4654
g_string_append_printf(result, "\n#End Block %s\n", block_name);
4755

lib/cfg-grammar.y

+18-15
Original file line numberDiff line numberDiff line change
@@ -138,23 +138,24 @@
138138
%token LL_CONTEXT_BLOCK_REF 9
139139
%token LL_CONTEXT_BLOCK_CONTENT 10
140140
%token LL_CONTEXT_BLOCK_ARG 11
141-
%token LL_CONTEXT_PRAGMA 12
142-
%token LL_CONTEXT_FORMAT 13
143-
%token LL_CONTEXT_TEMPLATE_FUNC 14
144-
%token LL_CONTEXT_INNER_DEST 15
145-
%token LL_CONTEXT_INNER_SRC 16
146-
%token LL_CONTEXT_CLIENT_PROTO 17
147-
%token LL_CONTEXT_SERVER_PROTO 18
148-
%token LL_CONTEXT_OPTIONS 19
149-
%token LL_CONTEXT_CONFIG 20
150-
%token LL_CONTEXT_TEMPLATE_REF 21
151-
%token LL_CONTEXT_FILTERX 22
152-
%token LL_CONTEXT_FILTERX_SIMPLE_FUNC 23
153-
%token LL_CONTEXT_FILTERX_ENUM 24
154-
%token LL_CONTEXT_FILTERX_FUNC 25
141+
%token LL_CONTEXT_BLOCK_FUNCARG 12
142+
%token LL_CONTEXT_PRAGMA 13
143+
%token LL_CONTEXT_FORMAT 14
144+
%token LL_CONTEXT_TEMPLATE_FUNC 15
145+
%token LL_CONTEXT_INNER_DEST 16
146+
%token LL_CONTEXT_INNER_SRC 17
147+
%token LL_CONTEXT_CLIENT_PROTO 18
148+
%token LL_CONTEXT_SERVER_PROTO 19
149+
%token LL_CONTEXT_OPTIONS 20
150+
%token LL_CONTEXT_CONFIG 21
151+
%token LL_CONTEXT_TEMPLATE_REF 22
152+
%token LL_CONTEXT_FILTERX 23
153+
%token LL_CONTEXT_FILTERX_SIMPLE_FUNC 24
154+
%token LL_CONTEXT_FILTERX_ENUM 25
155+
%token LL_CONTEXT_FILTERX_FUNC 26
155156

156157
/* this is a placeholder for unit tests, must be the latest & largest */
157-
%token LL_CONTEXT_MAX 26
158+
%token LL_CONTEXT_MAX 27
158159

159160
/* operators in the filter language, the order of this determines precedence */
160161
%right KW_ASSIGN 9000
@@ -1727,6 +1728,8 @@ _block_content_context_push: { cfg_lexer_push_context(lexer, LL_CONTEXT_BLOCK_CO
17271728
_block_content_context_pop: { cfg_lexer_pop_context(lexer); };
17281729
_block_arg_context_push: { cfg_lexer_push_context(lexer, LL_CONTEXT_BLOCK_ARG, NULL, "block argument"); };
17291730
_block_arg_context_pop: { cfg_lexer_pop_context(lexer); };
1731+
_block_func_arg_context_push: { cfg_lexer_push_context(lexer, LL_CONTEXT_BLOCK_FUNCARG, NULL, "block argument"); };
1732+
_block_func_arg_context_pop: { cfg_lexer_pop_context(lexer); };
17301733
_template_ref_context_push: { cfg_lexer_push_context(lexer, LL_CONTEXT_TEMPLATE_REF, NULL, "template reference"); };
17311734
_inner_dest_context_push: { cfg_lexer_push_context(lexer, LL_CONTEXT_INNER_DEST, NULL, "within destination"); };
17321735
_inner_dest_context_pop: { cfg_lexer_pop_context(lexer); };

lib/cfg-lex.l

+45-1
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ filterx_word [^ \#'"/\(\)\{\}\[\]\\;\r\n\t,|\.@:]
281281
%x qstring
282282
%x slash_string
283283
%x block
284+
%x block_arg
284285
%x block_content
285286
%x block_string
286287
%x block_qstring
@@ -489,11 +490,46 @@ filterx_word [^ \#'"/\(\)\{\}\[\]\\;\r\n\t,|\.@:]
489490
490491
}
491492
492-
493493
<block_content>[^{}()\"\'\n\r#]+ {
494494
g_string_append(yyextra->string_buffer, yytext);
495495
}
496496
497+
<block_arg>[\(\[\{] {
498+
g_string_append_c(yyextra->string_buffer, yytext[0]);
499+
yyextra->brace_count++;
500+
}
501+
<block_arg>[\)\]\}] {
502+
if (yyextra->brace_count > 0)
503+
{
504+
g_string_append_c(yyextra->string_buffer, yytext[0]);
505+
yyextra->brace_count--;
506+
}
507+
else
508+
{
509+
yy_pop_state(yyscanner);
510+
yylval->cptr = strdup(yyextra->string_buffer->str);
511+
unput(')');
512+
return LL_BLOCK;
513+
}
514+
}
515+
516+
517+
<block_arg>, {
518+
if (yyextra->brace_count > 0)
519+
{
520+
g_string_append_c(yyextra->string_buffer, yytext[0]);
521+
}
522+
else
523+
{
524+
yy_pop_state(yyscanner);
525+
yylval->cptr = strdup(yyextra->string_buffer->str);
526+
unput(',');
527+
return LL_BLOCK;
528+
}
529+
}
530+
<block_arg>[^\[\]\{\}\(\),] { g_string_append_c(yyextra->string_buffer, yytext[0]); }
531+
532+
497533
<block_string>[^\\"\r\n]+ { g_string_append(yyextra->string_buffer, yytext); }
498534
<block_string>\\. { g_string_append(yyextra->string_buffer, yytext); }
499535
<block_string>\" {
@@ -556,6 +592,14 @@ cfg_lexer_start_block_state(CfgLexer *self, const gchar block_boundary[2])
556592
yy_push_state(block, self->state);
557593
}
558594
595+
void
596+
cfg_lexer_start_block_arg_state(CfgLexer *self)
597+
{
598+
g_string_truncate(self->string_buffer, 0);
599+
self->brace_count = 0;
600+
yy_push_state(block_arg, self->state);
601+
}
602+
559603
void
560604
cfg_lexer_push_filterx_state(CfgLexer *self)
561605
{

lib/cfg-lexer.c

+29-5
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,26 @@ cfg_lexer_append_preprocessed_output(CfgLexer *self, const gchar *token_text)
971971
g_string_append_printf(self->preprocess_output, "%s", token_text);
972972
}
973973

974+
static CfgTokenBlock *
975+
_construct_block_ref_prelude(CfgLexer *self)
976+
{
977+
CfgTokenBlock *block;
978+
CFG_STYPE token;
979+
980+
/* we inject one token to a new token-block:
981+
* 1) the context from which the block ref parser is invoked
982+
*/
983+
block = cfg_token_block_new();
984+
985+
/* add plugin->type as a token */
986+
memset(&token, 0, sizeof(token));
987+
token.type = LL_TOKEN;
988+
token.token = cfg_lexer_get_context_type(self);
989+
cfg_token_block_add_and_consume_token(block, &token);
990+
991+
return block;
992+
}
993+
974994
static gboolean
975995
cfg_lexer_parse_and_run_block_generator(CfgLexer *self, Plugin *p, CFG_STYPE *yylval)
976996
{
@@ -983,10 +1003,11 @@ cfg_lexer_parse_and_run_block_generator(CfgLexer *self, Plugin *p, CFG_STYPE *yy
9831003

9841004
gint saved_line = level->lloc.first_line;
9851005
gint saved_column = level->lloc.first_column;
986-
CfgParser *gen_parser = p->parser;
987-
if (gen_parser && !cfg_parser_parse(gen_parser, self, (gpointer *) &args, NULL))
1006+
1007+
cfg_lexer_inject_token_block(self, _construct_block_ref_prelude(self));
1008+
if (!cfg_parser_parse(p->parser, self, (gpointer *) &args, NULL))
9881009
{
989-
cfg_parser_cleanup(gen_parser, args);
1010+
cfg_parser_cleanup(p->parser, args);
9901011

9911012
level->lloc.first_line = saved_line;
9921013
level->lloc.first_column = saved_column;
@@ -1005,8 +1026,8 @@ cfg_lexer_parse_and_run_block_generator(CfgLexer *self, Plugin *p, CFG_STYPE *yy
10051026
success = cfg_block_generator_generate(gen, self->cfg, args, result,
10061027
cfg_lexer_format_location(self, &level->lloc, buf, sizeof(buf)));
10071028

1008-
free(yylval->cptr);
1009-
cfg_parser_cleanup(gen_parser, args);
1029+
cfg_lexer_free_token(yylval);
1030+
cfg_parser_cleanup(p->parser, args);
10101031

10111032
if (!success)
10121033
{
@@ -1120,6 +1141,8 @@ cfg_lexer_lex(CfgLexer *self, CFG_STYPE *yylval, CFG_LTYPE *yylloc)
11201141
cfg_lexer_start_block_state(self, "{}");
11211142
else if (cfg_lexer_get_context_type(self) == LL_CONTEXT_BLOCK_ARG)
11221143
cfg_lexer_start_block_state(self, "()");
1144+
else if (cfg_lexer_get_context_type(self) == LL_CONTEXT_BLOCK_FUNCARG)
1145+
cfg_lexer_start_block_arg_state(self);
11231146

11241147
tok = cfg_lexer_lex_next_token(self, yylval, yylloc);
11251148
cfg_lexer_append_preprocessed_output(self, self->token_pretext->str);
@@ -1247,6 +1270,7 @@ static const gchar *lexer_contexts[] =
12471270
[LL_CONTEXT_BLOCK_ARG] = "block-arg",
12481271
[LL_CONTEXT_BLOCK_REF] = "block-ref",
12491272
[LL_CONTEXT_BLOCK_CONTENT] = "block-content",
1273+
[LL_CONTEXT_BLOCK_FUNCARG] = "block-func-arg",
12501274
[LL_CONTEXT_PRAGMA] = "pragma",
12511275
[LL_CONTEXT_FORMAT] = "format",
12521276
[LL_CONTEXT_TEMPLATE_FUNC] = "template-func",

lib/cfg-lexer.h

+1
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ void cfg_lexer_unput_token(CfgLexer *self, CFG_STYPE *yylval);
190190
void cfg_lexer_start_block_state(CfgLexer *self, const gchar block_boundary[2]);
191191
void cfg_lexer_push_filterx_state(CfgLexer *self);
192192
void cfg_lexer_pop_filterx_state(CfgLexer *self);
193+
void cfg_lexer_start_block_arg_state(CfgLexer *self);
193194

194195
void cfg_lexer_append_string(CfgLexer *self, int length, char *str);
195196
void cfg_lexer_append_char(CfgLexer *self, char c);

lib/filterx/filterx-grammar.ym

+15-8
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ construct_template_expr(LogTemplate *template)
9595

9696
%type <ptr> stmts
9797
%type <node> stmt
98+
%type <node> stmt_expr
9899
%type <node> assignment
99100
%type <node> generator_assignment
100101
%type <node> generator_casted_assignment
@@ -134,19 +135,25 @@ start
134135
;
135136

136137
stmts
137-
: stmt stmts {
138+
: stmt stmts { if ($1) $$ = g_list_prepend($2, $1); else $$ = $2; }
139+
| { $$ = NULL; }
140+
;
141+
142+
143+
stmt
144+
: stmt_expr ';' {
138145
CHECK_ERROR($1, @1, "failed to initialize statement");
139146
filterx_expr_set_location($1, lexer, &@1);
140-
$$ = g_list_prepend($2, $1);
147+
$$ = $1;
141148
}
142-
| { $$ = NULL; }
149+
| ';' { $$ = NULL; }
143150
;
144151

145-
stmt
146-
: expr ';' { $$ = $1; }
147-
| conditional ';' { $$ = $1; }
148-
| assignment ';' { $$ = $1; }
149-
| declaration ';' { $$ = $1; }
152+
stmt_expr
153+
: expr { $$ = $1; }
154+
| conditional { $$ = $1; }
155+
| assignment { $$ = $1; }
156+
| declaration { $$ = $1; }
150157
;
151158

152159
assignment

0 commit comments

Comments
 (0)