From 346355bd9a402a899e1e14df438fb9bef3d9f7fa Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Fri, 17 May 2024 23:44:11 +0200 Subject: [PATCH 1/6] cfg-lex.l: fix LL_BLOCK location start Signed-off-by: Balazs Scheidler --- lib/cfg-lex.l | 2 +- lib/tests/test_lexer.c | 27 ++++++++++++++++----------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/cfg-lex.l b/lib/cfg-lex.l index 29508dd499..45e1848c8f 100644 --- a/lib/cfg-lex.l +++ b/lib/cfg-lex.l @@ -159,7 +159,7 @@ yy_filter_input(CfgLexer *self, gchar *buf, gsize buf_size) #define YY_USER_ACTION \ do { \ CFG_LTYPE *cur_lloc = &yyextra->include_stack[yyextra->include_depth].lloc; \ - if (YY_START == INITIAL || YY_START == filterx) \ + if (YY_START == INITIAL || YY_START == filterx || YY_START == block) \ { \ cur_lloc->first_column = cur_lloc->last_column; \ } \ diff --git a/lib/tests/test_lexer.c b/lib/tests/test_lexer.c index bc869f56c9..e6041b6f93 100644 --- a/lib/tests/test_lexer.c +++ b/lib/tests/test_lexer.c @@ -188,57 +188,62 @@ Test(lexer, block_token_is_taken_literally_between_a_pair_of_enclosing_character _input(" { hello }"); cfg_lexer_start_block_state(parser->lexer, "{}"); assert_parser_block(" hello "); - assert_location_range(1, 1, 1, 11); + assert_location_range(1, 2, 1, 11); _input(" { hello\nworld }"); cfg_lexer_start_block_state(parser->lexer, "{}"); assert_parser_block(" hello\nworld "); - assert_location_range(1, 1, 2, 8); + assert_location_range(1, 2, 2, 8); _input(" { hello\\\nworld }"); cfg_lexer_start_block_state(parser->lexer, "{}"); assert_parser_block(" hello\\\nworld "); - assert_location_range(1, 1, 2, 8); + assert_location_range(1, 2, 2, 8); _input(" { 'hello' }"); cfg_lexer_start_block_state(parser->lexer, "{}"); assert_parser_block(" 'hello' "); - assert_location_range(1, 1, 1, 13); + assert_location_range(1, 2, 1, 13); _input(" { 'hello\nworld' }"); cfg_lexer_start_block_state(parser->lexer, "{}"); assert_parser_block(" 'hello\nworld' "); - assert_location_range(1, 1, 2, 9); + assert_location_range(1, 2, 2, 9); _input(" { 'hello\\\nworld' }"); cfg_lexer_start_block_state(parser->lexer, "{}"); assert_parser_block(" 'hello\\\nworld' "); - assert_location_range(1, 1, 2, 9); + assert_location_range(1, 2, 2, 9); _input(" { \"hello\" }"); cfg_lexer_start_block_state(parser->lexer, "{}"); assert_parser_block(" \"hello\" "); - assert_location_range(1, 1, 1, 13); + assert_location_range(1, 2, 1, 13); _input(" { \"hello\nworld\" }"); cfg_lexer_start_block_state(parser->lexer, "{}"); assert_parser_block(" \"hello\nworld\" "); - assert_location_range(1, 1, 2, 9); + assert_location_range(1, 2, 2, 9); _input(" { \"hello\\\nworld\" }"); cfg_lexer_start_block_state(parser->lexer, "{}"); assert_parser_block(" \"hello\\\nworld\" "); - assert_location_range(1, 1, 2, 9); + assert_location_range(1, 2, 2, 9); _input(" { \"hello \\a\\n\\r\\t\\v\\x40\\o100 world\" }"); cfg_lexer_start_block_state(parser->lexer, "{}"); assert_parser_block(" \"hello \\a\\n\\r\\t\\v\\x40\\o100 world\" "); - assert_location_range(1, 1, 1, 39); + assert_location_range(1, 2, 1, 39); _input(" { \"hello \\\" world\" }"); cfg_lexer_start_block_state(parser->lexer, "{}"); assert_parser_block(" \"hello \\\" world\" "); - assert_location_range(1, 1, 1, 22); + assert_location_range(1, 2, 1, 22); + + _input("\n{\n \"hello \\\" world\" }"); + cfg_lexer_start_block_state(parser->lexer, "{}"); + assert_parser_block("\n \"hello \\\" world\" "); + assert_location_range(2, 1, 3, 20); } Test(lexer, block_new_lines_in_text_leading_to_the_opening_bracket_are_tracked_properly) From 628de05b0344731e7c199d0faf505682962f94fb Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Fri, 17 May 2024 23:47:10 +0200 Subject: [PATCH 2/6] cfg-source: fix off-by-one when extracting source line from CFGI_BUFFER Signed-off-by: Balazs Scheidler --- lib/cfg-source.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/cfg-source.c b/lib/cfg-source.c index e708576821..59665cb42e 100644 --- a/lib/cfg-source.c +++ b/lib/cfg-source.c @@ -234,6 +234,9 @@ _extract_source_from_buffer_location(GString *result, const gchar *buffer_conten if (num_lines <= yylloc->first_line) goto exit; + if (yylloc->first_column < 1) + goto exit; + for (gint lineno = yylloc->first_line; lineno <= yylloc->last_line; lineno++) { gchar *line = lines[lineno - 1]; @@ -242,9 +245,9 @@ _extract_source_from_buffer_location(GString *result, const gchar *buffer_conten if (lineno == yylloc->first_line) { if (yylloc->first_line == yylloc->last_line) - g_string_append_len(result, &line[MIN(linelen, yylloc->first_column)], yylloc->last_column - yylloc->first_column); + g_string_append_len(result, &line[MIN(linelen, yylloc->first_column-1)], yylloc->last_column - yylloc->first_column); else - g_string_append(result, &line[MIN(linelen, yylloc->first_column)]); + g_string_append(result, &line[MIN(linelen, yylloc->first_column-1)]); } else if (lineno < yylloc->last_line) { From 43b8c8e0a87ec5edc27424451bf38848f64b698b Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Mon, 20 May 2024 09:38:26 +0200 Subject: [PATCH 3/6] cfg-lexer: capture original location even if @line is present If @line is encountered in the input stream, we overwrite our idea of where we are in the input file so that we can properly report on file locations, even if we are expanding a block or other generators. This patch makes it possible to recover the original location (e.g. before @line was called), which is needed to extract the source text _after_ generation/substitution has happened. This means that whenever we display the source text (e.g. error report, or as a part of the filterx expr being executed), we can use the post-processed version. Whenever we want to read the file that contained the source, we can use the current yylloc. If we want to extract from the postprocessed buffer, we need to get back to the original yylloc. Signed-off-by: Balazs Scheidler --- lib/cfg-grammar.y | 2 ++ lib/cfg-lexer.c | 65 ++++++++++++++++++++++++++++++++++++++++++++--- lib/cfg-lexer.h | 28 +++++++++++++++----- 3 files changed, 84 insertions(+), 11 deletions(-) diff --git a/lib/cfg-grammar.y b/lib/cfg-grammar.y index 5bc4e6f41e..7478271092 100644 --- a/lib/cfg-grammar.y +++ b/lib/cfg-grammar.y @@ -71,6 +71,7 @@ if (N) \ { \ (Current).name = YYRHSLOC(Rhs, 1).name; \ + (Current).at_line = YYRHSLOC (Rhs, 1).at_line; \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ @@ -79,6 +80,7 @@ else \ { \ (Current).name = YYRHSLOC(Rhs, 0).name; \ + (Current).at_line = YYRHSLOC (Rhs, 0).at_line; \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ diff --git a/lib/cfg-lexer.c b/lib/cfg-lexer.c index 23449752ce..83e74c13c3 100644 --- a/lib/cfg-lexer.c +++ b/lib/cfg-lexer.c @@ -166,15 +166,71 @@ cfg_lexer_format_location_tag(CfgLexer *self, const CFG_LTYPE *yylloc) return evt_tag_str("location", cfg_lexer_format_location(self, yylloc, buf, sizeof(buf))); } +void +cfg_lexer_undo_set_file_location(CfgLexer *self, CFG_LTYPE *yylloc) +{ + if (!yylloc->at_line.present) + return; + + gboolean lloc_is_oneline = yylloc->first_line == yylloc->last_line; + + /* calculate how much we moved, relative to the @line setting */ + gint ofs_lines = yylloc->first_line - yylloc->at_line.line; + gint ofs_columns = yylloc->first_column - yylloc->at_line.column; + + gint range_lines = yylloc->last_line - yylloc->first_line; + + /* the line number moves the same amount as we've processed with the alternative location */ + yylloc->first_line = yylloc->at_line.captured_first_line + ofs_lines; + yylloc->last_line = yylloc->first_line + range_lines; + + if (ofs_lines == 0) + { + /* we remained on the same line (e.g. the one that follows @line), + * starting column is moved to where @line told us to */ + + g_assert(lloc_is_oneline); + + /* save the length of the token within the same line */ + gint range_columns = yylloc->last_column - yylloc->first_column; + + /* adjust the first_column */ + yylloc->first_column = yylloc->at_line.captured_first_column + ofs_columns; + + /* yylloc pointed to a single line and we moved the starting + * column, so let's adjust last_column as well */ + + yylloc->last_column = yylloc->first_column + range_columns; + } + yylloc->name = yylloc->at_line.captured_name; + yylloc->at_line.present = FALSE; +} + void cfg_lexer_set_file_location(CfgLexer *self, const gchar *filename, gint line, gint column) { CfgIncludeLevel *level = &self->include_stack[self->include_depth]; + CFG_LTYPE *yylloc = &level->lloc; - level->lloc.name = g_intern_string(filename); - level->lloc.first_line = level->lloc.last_line = line; - level->lloc.first_column = level->lloc.last_column = column; - level->lloc_changed_by_at_line = TRUE; + /* we already had a previous @line, let's go back as if it didn't exist */ + cfg_lexer_undo_set_file_location(self, yylloc); + + if (!filename) + { + /* reset to previous state but don't establish a new location */ + return; + } + + yylloc->at_line.captured_first_line = yylloc->first_line; + yylloc->at_line.captured_first_column = yylloc->first_column; + yylloc->at_line.captured_name = yylloc->name; + yylloc->at_line.line = line; + yylloc->at_line.column = column; + yylloc->at_line.present = TRUE; + + yylloc->name = g_intern_string(filename); + yylloc->first_line = yylloc->last_line = line; + yylloc->first_column = yylloc->last_column = column; } static int @@ -361,6 +417,7 @@ cfg_lexer_include_level_open_buffer(CfgLexer *self, CfgIncludeLevel *level) level->lloc.first_line = level->lloc.last_line = 1; level->lloc.first_column = level->lloc.last_column = 1; + level->lloc.at_line.present = FALSE; return TRUE; } diff --git a/lib/cfg-lexer.h b/lib/cfg-lexer.h index fe193b87f6..22938982a0 100644 --- a/lib/cfg-lexer.h +++ b/lib/cfg-lexer.h @@ -86,10 +86,24 @@ typedef struct _CfgTokenBlock CfgTokenBlock; typedef struct CFG_LTYPE { - int first_line; - int first_column; - int last_line; - int last_column; + gint first_line; + gint first_column; + gint last_line; + gint last_column; + + /* this value indicates that @line was used which changed lloc relative to + * an actual file */ + struct + { + gboolean present; + /* the first line/column at the point of the @line directive */ + gint captured_first_line; + gint captured_first_column; + const gchar *captured_name; + /* line/column specified by @line */ + gint line; + gint column; + } at_line; const gchar *name; } CFG_LTYPE; @@ -152,9 +166,8 @@ struct _CfgIncludeLevel } buffer; }; - /* this value indicates that @line was used which changed lloc relative to - * an actual file */ - gboolean lloc_changed_by_at_line; + + CFG_LTYPE lloc; struct yy_buffer_state *yybuf; }; @@ -207,6 +220,7 @@ gboolean cfg_lexer_include_buffer(CfgLexer *self, const gchar *name, const gchar gboolean cfg_lexer_include_buffer_without_backtick_substitution(CfgLexer *self, const gchar *name, const gchar *buffer, gsize length); const gchar *cfg_lexer_format_location(CfgLexer *self, const CFG_LTYPE *yylloc, gchar *buf, gsize buf_len); +void cfg_lexer_undo_set_file_location(CfgLexer *self, CFG_LTYPE *yylloc); void cfg_lexer_set_file_location(CfgLexer *self, const gchar *filename, gint line, gint column); EVTTAG *cfg_lexer_format_location_tag(CfgLexer *self, const CFG_LTYPE *yylloc); From 4695a05b2b849758315e834b50a167772be0e19c Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Mon, 20 May 2024 09:40:03 +0200 Subject: [PATCH 4/6] cfg-source: use the postprocessed buffer when extracting source text Signed-off-by: Balazs Scheidler --- lib/cfg-source.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/cfg-source.c b/lib/cfg-source.c index 59665cb42e..4695c40225 100644 --- a/lib/cfg-source.c +++ b/lib/cfg-source.c @@ -129,22 +129,22 @@ _report_file_location(const gchar *filename, const CFG_LTYPE *yylloc) } static void -_report_buffer_location(const gchar *buffer_content, const CFG_LTYPE *yylloc) +_report_buffer_location(const gchar *buffer_content, const CFG_LTYPE *file_lloc, const CFG_LTYPE *buf_lloc) { - gchar **lines = g_strsplit(buffer_content, "\n", yylloc->first_line + CONTEXT + 1); + gchar **lines = g_strsplit(buffer_content, "\n", buf_lloc->first_line + CONTEXT + 1); gint num_lines = g_strv_length(lines); - if (num_lines <= yylloc->first_line) + if (num_lines <= buf_lloc->first_line) goto exit; - gint start = yylloc->first_line - 1 - CONTEXT; + gint start = buf_lloc->first_line - 1 - CONTEXT; gint error_index = CONTEXT; if (start < 0) { error_index += start; start = 0; } - _print_underlined_source_block(yylloc, &lines[start], error_index); + _print_underlined_source_block(file_lloc, &lines[start], error_index); exit: g_strfreev(lines); @@ -159,10 +159,10 @@ cfg_source_print_source_context(CfgLexer *lexer, CfgIncludeLevel *level, const C } else if (level->include_type == CFGI_BUFFER) { - if (level->lloc_changed_by_at_line) - _report_file_location(yylloc->name, yylloc); - else - _report_buffer_location(level->buffer.original_content, yylloc); + CFG_LTYPE buf_lloc = *yylloc; + cfg_lexer_undo_set_file_location(lexer, &buf_lloc); + + _report_buffer_location(level->buffer.original_content, yylloc, &buf_lloc); } return TRUE; } @@ -276,10 +276,10 @@ cfg_source_extract_source_text(CfgLexer *lexer, const CFG_LTYPE *yylloc, GString return _extract_source_from_file_location(result, yylloc->name, yylloc); else if (level->include_type == CFGI_BUFFER) { - if (level->lloc_changed_by_at_line) - return _extract_source_from_file_location(result, yylloc->name, yylloc); - else - return _extract_source_from_buffer_location(result, level->buffer.original_content, yylloc); + CFG_LTYPE buf_lloc = *yylloc; + cfg_lexer_undo_set_file_location(lexer, &buf_lloc); + + return _extract_source_from_buffer_location(result, level->buffer.original_content, &buf_lloc); } else g_assert_not_reached(); From 2c653b922721b2933d3b87f7f6dd66111e624ba1 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Mon, 20 May 2024 09:40:59 +0200 Subject: [PATCH 5/6] pragma-grammar: add @line without arguments This pragma reverts to the original location, as if the previous @line was not even there. Signed-off-by: Balazs Scheidler --- lib/pragma-grammar.ym | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/pragma-grammar.ym b/lib/pragma-grammar.ym index 8086f38881..a13cee2bd7 100644 --- a/lib/pragma-grammar.ym +++ b/lib/pragma-grammar.ym @@ -215,7 +215,12 @@ line_stmt cfg_lexer_set_file_location(lexer, $2, $3, $4); free($2); } + | KW_LINE LL_EOL + { + cfg_lexer_set_file_location(lexer, NULL, 0, 0); + } + ; /* INCLUDE_RULES */ %% From a9fae9382a305278185bada78ec8b2db4d64158b Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Fri, 17 May 2024 23:44:51 +0200 Subject: [PATCH 6/6] appmodel: add @line for generated content Signed-off-by: Balazs Scheidler --- modules/appmodel/app-parser-generator.c | 67 ++++++++++++++++------- modules/appmodel/application.c | 12 +++- modules/appmodel/application.h | 10 +++- modules/appmodel/appmodel-grammar.ym | 6 +- modules/appmodel/tests/test_application.c | 8 +-- 5 files changed, 69 insertions(+), 34 deletions(-) diff --git a/modules/appmodel/app-parser-generator.c b/modules/appmodel/app-parser-generator.c index 0fd1958cf6..21e0f4823d 100644 --- a/modules/appmodel/app-parser-generator.c +++ b/modules/appmodel/app-parser-generator.c @@ -79,33 +79,58 @@ app_parser_generator_parse_arguments(AppObjectGenerator *s, CfgArgs *args, const } static void -_generate_filter(AppParserGenerator *self, const gchar *filter_expr) +_generate_at_line(GString *block, const CFG_LTYPE *lloc) { - if (filter_expr) - g_string_append_printf(self->block, - " filter {\n" - " %s\n" - " };\n", filter_expr); + if (lloc->first_column && lloc->first_line) + g_string_append_printf(block, + "@line \"%s\" %d %d\n", + lloc->name, lloc->first_line, lloc->first_column); + } static void -_generate_parser(AppParserGenerator *self, const gchar *parser_expr) +_generate_filter(AppParserGenerator *self, const Application *app) { - if (parser_expr) - g_string_append_printf(self->block, - " parser {\n" - " %s\n" - " };\n", parser_expr); + if (app->filter_expr) + { + g_string_append(self->block, + " filter {\n"); + _generate_at_line(self->block, &app->filter_lloc); + g_string_append_printf(self->block, + "%s\n" + "@line\n" + " };\n", app->filter_expr); + } } static void -_generate_filterx(AppParserGenerator *self, const gchar *filterx_expr) +_generate_parser(AppParserGenerator *self, const Application *app) { - if (filterx_expr) - g_string_append_printf(self->block, - " filterx {\n" - " %s\n" - " };\n", filterx_expr); + if (app->parser_expr) + { + g_string_append(self->block, + " parser {\n"); + _generate_at_line(self->block, &app->parser_lloc); + g_string_append_printf(self->block, + "%s\n" + "@line\n" + " };\n", app->parser_expr); + } +} + +static void +_generate_filterx(AppParserGenerator *self, const Application *app) +{ + if (app->filterx_expr) + { + g_string_append(self->block, + " filterx {\n"); + _generate_at_line(self->block, &app->filterx_lloc); + g_string_append_printf(self->block, + "%s\n" + "@line\n" + " };\n", app->filterx_expr); + } } static void @@ -163,9 +188,9 @@ _generate_application(Application *app, gpointer user_data) g_string_append_printf(self->block, " #Start Application %s\n", app->super.name); - _generate_filter(self, app->filter_expr); - _generate_parser(self, app->parser_expr); - _generate_filterx(self, app->filterx_expr); + _generate_filter(self, app); + _generate_parser(self, app); + _generate_filterx(self, app); _generate_action(self, app); g_string_append_printf(self->block, " #End Application %s\n", app->super.name); diff --git a/modules/appmodel/application.c b/modules/appmodel/application.c index 672ba4d8c9..cd741fb50d 100644 --- a/modules/appmodel/application.c +++ b/modules/appmodel/application.c @@ -24,24 +24,30 @@ #include "application.h" void -application_set_filter(Application *self, const gchar *filter_expr) +application_set_filter(Application *self, const gchar *filter_expr, CFG_LTYPE *lloc) { g_free(self->filter_expr); self->filter_expr = g_strdup(filter_expr); + if (lloc) + self->filter_lloc = *lloc; } void -application_set_parser(Application *self, const gchar *parser_expr) +application_set_parser(Application *self, const gchar *parser_expr, CFG_LTYPE *lloc) { g_free(self->parser_expr); self->parser_expr = g_strdup(parser_expr); + if (lloc) + self->parser_lloc = *lloc; } void -application_set_filterx(Application *self, const gchar *filterx_expr) +application_set_filterx(Application *self, const gchar *filterx_expr, CFG_LTYPE *lloc) { g_free(self->filterx_expr); self->filterx_expr = g_strdup(filterx_expr); + if (lloc) + self->filterx_lloc = *lloc; } static void diff --git a/modules/appmodel/application.h b/modules/appmodel/application.h index 944f6c63a0..dfa06da82c 100644 --- a/modules/appmodel/application.h +++ b/modules/appmodel/application.h @@ -25,6 +25,7 @@ #define APPMODEL_APPLICATION_H_INCLUDED #include "appmodel-context.h" +#include "cfg-lexer.h" #define APPLICATION_TYPE_NAME "application" @@ -34,11 +35,14 @@ typedef struct _Application gchar *filter_expr; gchar *parser_expr; gchar *filterx_expr; + CFG_LTYPE filter_lloc; + CFG_LTYPE parser_lloc; + CFG_LTYPE filterx_lloc; } Application; -void application_set_filter(Application *self, const gchar *filter_expr); -void application_set_parser(Application *self, const gchar *parser_expr); -void application_set_filterx(Application *self, const gchar *parser_expr); +void application_set_filter(Application *self, const gchar *filter_expr, CFG_LTYPE *lloc); +void application_set_parser(Application *self, const gchar *parser_expr, CFG_LTYPE *lloc); +void application_set_filterx(Application *self, const gchar *parser_expr, CFG_LTYPE *lloc); Application *application_new(const gchar *name, const gchar *topic); diff --git a/modules/appmodel/appmodel-grammar.ym b/modules/appmodel/appmodel-grammar.ym index d368c9c33c..78d2600e69 100644 --- a/modules/appmodel/appmodel-grammar.ym +++ b/modules/appmodel/appmodel-grammar.ym @@ -92,9 +92,9 @@ application_options ; application_option - : KW_FILTER _block_content_context_push LL_BLOCK _block_content_context_pop { application_set_filter($0, $3); free($3); } - | KW_PARSER _block_content_context_push LL_BLOCK _block_content_context_pop { application_set_parser($0, $3); free($3); } - | KW_FILTERX _block_content_context_push LL_BLOCK _block_content_context_pop { application_set_filterx($0, $3); free($3); } + : KW_FILTER _block_content_context_push LL_BLOCK _block_content_context_pop { application_set_filter($0, $3, &@3); free($3); } + | KW_PARSER _block_content_context_push LL_BLOCK _block_content_context_pop { application_set_parser($0, $3, &@3); free($3); } + | KW_FILTERX _block_content_context_push LL_BLOCK _block_content_context_pop { application_set_filterx($0, $3, &@3); free($3); } ; diff --git a/modules/appmodel/tests/test_application.c b/modules/appmodel/tests/test_application.c index a7e02c322a..a91f79d157 100644 --- a/modules/appmodel/tests/test_application.c +++ b/modules/appmodel/tests/test_application.c @@ -40,10 +40,10 @@ Test(application, filter_can_be_set_and_queried) const gchar *filter_expr2 = "'2' eq '2'"; app = application_new("foobar", "*"); - application_set_filter(app, filter_expr); + application_set_filter(app, filter_expr, NULL); cr_assert_str_eq(app->filter_expr, filter_expr); - application_set_filter(app, filter_expr2); + application_set_filter(app, filter_expr2, NULL); cr_assert_str_eq(app->filter_expr, filter_expr2); appmodel_object_free(&app->super); } @@ -55,10 +55,10 @@ Test(application, parser_can_be_set_and_queried) const gchar *parser_expr2 = "csv-parser();"; app = application_new("foobar", "*"); - application_set_parser(app, parser_expr); + application_set_parser(app, parser_expr, NULL); cr_assert_str_eq(app->parser_expr, parser_expr); - application_set_parser(app, parser_expr2); + application_set_parser(app, parser_expr2, NULL); cr_assert_str_eq(app->parser_expr, parser_expr2); appmodel_object_free(&app->super); }