From 7b8334a831a9783f574fbd24af5d35bc61dbe71e Mon Sep 17 00:00:00 2001 From: Attila Szakacs Date: Wed, 7 Aug 2024 15:38:12 +0200 Subject: [PATCH 1/8] filterx/expr-function: return FilterXExpr from function ctor We are planning to introduce a FilterXGeneratorFunction alongside FilterXFunction, and the evaluation side expects FilterXExpr anyways, so let's loosen the interface a bit, to fit for both kinds of functions. Signed-off-by: Attila Szakacs --- lib/filterx/expr-function.c | 5 +-- lib/filterx/expr-function.h | 2 +- lib/filterx/expr-regexp.c | 6 ++-- lib/filterx/expr-regexp.h | 5 ++- lib/filterx/expr-unset.c | 4 +-- lib/filterx/expr-unset.h | 2 +- lib/filterx/func-flatten.c | 4 +-- lib/filterx/func-flatten.h | 2 +- lib/filterx/func-istype.c | 4 +-- lib/filterx/func-istype.h | 2 +- lib/filterx/func-unset-empties.c | 4 +-- lib/filterx/func-unset-empties.h | 3 +- lib/filterx/object-datetime.c | 4 +-- lib/filterx/object-datetime.h | 2 +- lib/filterx/tests/test_builtin_functions.c | 10 +++--- lib/filterx/tests/test_expr_regexp.c | 18 +++++----- lib/filterx/tests/test_func_flatten.c | 8 ++--- lib/filterx/tests/test_func_istype.c | 24 ++++++------- lib/filterx/tests/test_func_unset_empties.c | 8 ++--- lib/filterx/tests/test_object_datetime.c | 34 +++++++++---------- .../filterx/func-update-metric.c | 4 +-- .../filterx/func-update-metric.h | 3 +- .../tests/test_filterx_func_update_metric.c | 6 ++-- 23 files changed, 79 insertions(+), 85 deletions(-) diff --git a/lib/filterx/expr-function.c b/lib/filterx/expr-function.c index f2aef4c074..e1706c0cb6 100644 --- a/lib/filterx/expr-function.c +++ b/lib/filterx/expr-function.c @@ -549,10 +549,7 @@ _lookup_function(GlobalConfig *cfg, const gchar *function_name, FilterXFunctionA if (!ctor) return NULL; - FilterXFunction *func_expr = ctor(function_name, args, error); - if (!func_expr) - return NULL; - return &func_expr->super; + return ctor(function_name, args, error); } /* NOTE: takes the reference of "args_list" */ diff --git a/lib/filterx/expr-function.h b/lib/filterx/expr-function.h index 8627dcb0dc..987832f70a 100644 --- a/lib/filterx/expr-function.h +++ b/lib/filterx/expr-function.h @@ -49,7 +49,7 @@ typedef struct _FilterXFunctionArg gboolean retrieved; } FilterXFunctionArg; -typedef FilterXFunction *(*FilterXFunctionCtor)(const gchar *, FilterXFunctionArgs *, GError **); +typedef FilterXExpr *(*FilterXFunctionCtor)(const gchar *, FilterXFunctionArgs *, GError **); #define FILTERX_FUNCTION_ERROR filterx_function_error_quark() GQuark filterx_function_error_quark(void); diff --git a/lib/filterx/expr-regexp.c b/lib/filterx/expr-regexp.c index 7e888e123e..d7b2566c64 100644 --- a/lib/filterx/expr-regexp.c +++ b/lib/filterx/expr-regexp.c @@ -661,7 +661,7 @@ _opts_init(FilterXFuncRegexpSubstOpts *opts) opts->jit = TRUE; } -FilterXFunction * +FilterXExpr * filterx_function_regexp_subst_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error) { FilterXFuncRegexpSubst *self = g_new0(FilterXFuncRegexpSubst, 1); @@ -676,7 +676,7 @@ filterx_function_regexp_subst_new(const gchar *function_name, FilterXFunctionArg goto error; filterx_function_args_free(args); - return &self->super; + return &self->super.super; error: filterx_function_args_free(args); @@ -685,7 +685,7 @@ filterx_function_regexp_subst_new(const gchar *function_name, FilterXFunctionArg } gboolean -filterx_regexp_subst_is_jit_enabled(FilterXFunction *s) +filterx_regexp_subst_is_jit_enabled(FilterXExpr *s) { g_assert(s); FilterXFuncRegexpSubst *self = (FilterXFuncRegexpSubst *)s; diff --git a/lib/filterx/expr-regexp.h b/lib/filterx/expr-regexp.h index 30d49a9c2b..81530fe267 100644 --- a/lib/filterx/expr-regexp.h +++ b/lib/filterx/expr-regexp.h @@ -46,8 +46,7 @@ typedef struct FilterXFuncRegexpSubstOpts_ FilterXExpr *filterx_expr_regexp_match_new(FilterXExpr *lhs, const gchar *pattern); FilterXExpr *filterx_expr_regexp_nomatch_new(FilterXExpr *lhs, const gchar *pattern); FilterXExpr *filterx_expr_regexp_search_generator_new(FilterXExpr *lhs, const gchar *pattern); -FilterXFunction *filterx_function_regexp_subst_new(const gchar *function_name, FilterXFunctionArgs *args, - GError **error); -gboolean filterx_regexp_subst_is_jit_enabled(FilterXFunction *s); +FilterXExpr *filterx_function_regexp_subst_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error); +gboolean filterx_regexp_subst_is_jit_enabled(FilterXExpr *s); #endif diff --git a/lib/filterx/expr-unset.c b/lib/filterx/expr-unset.c index f5582eecf6..eefd50737a 100644 --- a/lib/filterx/expr-unset.c +++ b/lib/filterx/expr-unset.c @@ -55,7 +55,7 @@ _free(FilterXExpr *s) filterx_function_free_method(&self->super); } -FilterXFunction * +FilterXExpr * filterx_function_unset_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error) { FilterXExprUnset *self = g_new0(FilterXExprUnset, 1); @@ -72,7 +72,7 @@ filterx_function_unset_new(const gchar *function_name, FilterXFunctionArgs *args goto error; filterx_function_args_free(args); - return &self->super; + return &self->super.super; error: filterx_function_args_free(args); diff --git a/lib/filterx/expr-unset.h b/lib/filterx/expr-unset.h index e975044533..c7a0e21465 100644 --- a/lib/filterx/expr-unset.h +++ b/lib/filterx/expr-unset.h @@ -25,6 +25,6 @@ #include "filterx/expr-function.h" -FilterXFunction *filterx_function_unset_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error); +FilterXExpr *filterx_function_unset_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error); #endif diff --git a/lib/filterx/func-flatten.c b/lib/filterx/func-flatten.c index d4b117b3cb..46ad84e990 100644 --- a/lib/filterx/func-flatten.c +++ b/lib/filterx/func-flatten.c @@ -252,7 +252,7 @@ _extract_args(FilterXFunctionFlatten *self, FilterXFunctionArgs *args, GError ** return TRUE; } -FilterXFunction * +FilterXExpr * filterx_function_flatten_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error) { FilterXFunctionFlatten *self = g_new0(FilterXFunctionFlatten, 1); @@ -264,7 +264,7 @@ filterx_function_flatten_new(const gchar *function_name, FilterXFunctionArgs *ar goto error; filterx_function_args_free(args); - return &self->super; + return &self->super.super; error: filterx_function_args_free(args); diff --git a/lib/filterx/func-flatten.h b/lib/filterx/func-flatten.h index f2b844a41c..a086983efd 100644 --- a/lib/filterx/func-flatten.h +++ b/lib/filterx/func-flatten.h @@ -27,6 +27,6 @@ #include "filterx/expr-function.h" -FilterXFunction *filterx_function_flatten_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error); +FilterXExpr *filterx_function_flatten_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error); #endif diff --git a/lib/filterx/func-istype.c b/lib/filterx/func-istype.c index 4dfe646017..03f8612b79 100644 --- a/lib/filterx/func-istype.c +++ b/lib/filterx/func-istype.c @@ -120,7 +120,7 @@ _extract_args(FilterXFunctionIsType *self, FilterXFunctionArgs *args, GError **e return TRUE; } -FilterXFunction * +FilterXExpr * filterx_function_istype_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error) { FilterXFunctionIsType *self = g_new0(FilterXFunctionIsType, 1); @@ -133,7 +133,7 @@ filterx_function_istype_new(const gchar *function_name, FilterXFunctionArgs *arg goto error; filterx_function_args_free(args); - return &self->super; + return &self->super.super; error: filterx_function_args_free(args); diff --git a/lib/filterx/func-istype.h b/lib/filterx/func-istype.h index a63591e3df..18257a9856 100644 --- a/lib/filterx/func-istype.h +++ b/lib/filterx/func-istype.h @@ -27,6 +27,6 @@ #include "filterx/expr-function.h" -FilterXFunction *filterx_function_istype_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error); +FilterXExpr *filterx_function_istype_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error); #endif diff --git a/lib/filterx/func-unset-empties.c b/lib/filterx/func-unset-empties.c index bec385fdd8..d88a4d3ddc 100644 --- a/lib/filterx/func-unset-empties.c +++ b/lib/filterx/func-unset-empties.c @@ -254,7 +254,7 @@ _extract_args(FilterXFunctionUnsetEmpties *self, FilterXFunctionArgs *args, GErr return TRUE; } -FilterXFunction * +FilterXExpr * filterx_function_unset_empties_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error) { FilterXFunctionUnsetEmpties *self = g_new0(FilterXFunctionUnsetEmpties, 1); @@ -268,7 +268,7 @@ filterx_function_unset_empties_new(const gchar *function_name, FilterXFunctionAr goto error; filterx_function_args_free(args); - return &self->super; + return &self->super.super; error: filterx_function_args_free(args); diff --git a/lib/filterx/func-unset-empties.h b/lib/filterx/func-unset-empties.h index 5ca8253b1c..fe707811bd 100644 --- a/lib/filterx/func-unset-empties.h +++ b/lib/filterx/func-unset-empties.h @@ -26,7 +26,6 @@ #include "filterx/expr-function.h" -FilterXFunction *filterx_function_unset_empties_new(const gchar *function_name, FilterXFunctionArgs *args, - GError **error); +FilterXExpr *filterx_function_unset_empties_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error); #endif diff --git a/lib/filterx/object-datetime.c b/lib/filterx/object-datetime.c index bb5f4c0cba..324563dc3d 100644 --- a/lib/filterx/object-datetime.c +++ b/lib/filterx/object-datetime.c @@ -365,7 +365,7 @@ _extract_args(FilterXFunctionStrptime *self, FilterXFunctionArgs *args, GError * } /* Takes reference of args */ -FilterXFunction * +FilterXExpr * filterx_function_strptime_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error) { FilterXFunctionStrptime *self = g_new0(FilterXFunctionStrptime, 1); @@ -378,7 +378,7 @@ filterx_function_strptime_new(const gchar *function_name, FilterXFunctionArgs *a goto error; filterx_function_args_free(args); - return &self->super; + return &self->super.super; error: filterx_function_args_free(args); diff --git a/lib/filterx/object-datetime.h b/lib/filterx/object-datetime.h index aeb22a737d..330c21f74e 100644 --- a/lib/filterx/object-datetime.h +++ b/lib/filterx/object-datetime.h @@ -34,7 +34,7 @@ FilterXObject *filterx_datetime_new(const UnixTime *ut); UnixTime filterx_datetime_get_value(FilterXObject *s); FilterXObject *filterx_typecast_datetime(FilterXExpr *s, GPtrArray *args); FilterXObject *filterx_typecast_datetime_isodate(FilterXExpr *, GPtrArray *args); -FilterXFunction *filterx_function_strptime_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error); +FilterXExpr *filterx_function_strptime_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error); gboolean datetime_repr(const UnixTime *ut, GString *repr); diff --git a/lib/filterx/tests/test_builtin_functions.c b/lib/filterx/tests/test_builtin_functions.c index a59bd32d53..9471a4354e 100644 --- a/lib/filterx/tests/test_builtin_functions.c +++ b/lib/filterx/tests/test_builtin_functions.c @@ -101,7 +101,7 @@ _dummy_eval(FilterXExpr *s) return filterx_string_new("test-builtin-functions", -1); } -static FilterXFunction * +static FilterXExpr * _test_builtin_dummy_function_ctor(const gchar *function_name, FilterXFunctionArgs *args, GError **error) { FilterXFunction *self = g_new0(FilterXFunction, 1); @@ -109,7 +109,7 @@ _test_builtin_dummy_function_ctor(const gchar *function_name, FilterXFunctionArg self->super.eval = _dummy_eval; filterx_function_args_free(args); - return self; + return &self->super; } Test(builtin_functions, test_builtin_function_ctors_registering_existing_key_returns_false) @@ -143,10 +143,10 @@ Test(builtin_functions, test_builtin_function_ctors_lookup) cr_assert(ctor != NULL); // check dummy ctor as result - FilterXFunction *func_expr = ctor(TEST_BUILTIN_FUNCTION_NAME, filterx_function_args_new(NULL, NULL), NULL); + FilterXExpr *func_expr = ctor(TEST_BUILTIN_FUNCTION_NAME, filterx_function_args_new(NULL, NULL), NULL); cr_assert(func_expr != NULL); - FilterXObject *res = filterx_expr_eval(&func_expr->super); + FilterXObject *res = filterx_expr_eval(func_expr); cr_assert(filterx_object_is_type(res, &FILTERX_TYPE_NAME(string))); gsize len; const gchar *str = filterx_string_get_value(res, &len); @@ -156,7 +156,7 @@ Test(builtin_functions, test_builtin_function_ctors_lookup) filterx_builtin_function_ctors_deinit_private(ht); filterx_object_unref(res); - filterx_expr_unref(&func_expr->super); + filterx_expr_unref(func_expr); } static void diff --git a/lib/filterx/tests/test_expr_regexp.c b/lib/filterx/tests/test_expr_regexp.c index 4c09bf1686..5627221060 100644 --- a/lib/filterx/tests/test_expr_regexp.c +++ b/lib/filterx/tests/test_expr_regexp.c @@ -237,7 +237,7 @@ Test(filterx_expr_regexp, regexp_search_init_error) _assert_search_init_error("foobarbaz", "("); } -static FilterXFunction * +static FilterXExpr * _build_subst_func(const gchar *pattern, const gchar *repr, const gchar *str, FilterXFuncRegexpSubstOpts opts) { GList *args = NULL; @@ -261,7 +261,7 @@ _build_subst_func(const gchar *pattern, const gchar *repr, const gchar *str, Fil filterx_literal_new(filterx_boolean_new(TRUE)))); GError *err = NULL; - FilterXFunction *func = filterx_function_regexp_subst_new("test", filterx_function_args_new(args, NULL), &err); + FilterXExpr *func = filterx_function_regexp_subst_new("test", filterx_function_args_new(args, NULL), &err); cr_assert_null(err); return func; } @@ -269,10 +269,10 @@ _build_subst_func(const gchar *pattern, const gchar *repr, const gchar *str, Fil static FilterXObject * _sub(const gchar *pattern, const gchar *repr, const gchar *str, FilterXFuncRegexpSubstOpts opts) { - FilterXFunction *func = _build_subst_func(pattern, repr, str, opts); + FilterXExpr *func = _build_subst_func(pattern, repr, str, opts); - FilterXObject *res = filterx_expr_eval(&func->super); - filterx_expr_unref(&func->super); + FilterXObject *res = filterx_expr_eval(func); + filterx_expr_unref(func); return res; } @@ -463,16 +463,16 @@ Test(filterx_expr_regexp, regexp_subst_accept_groups_with_global) Test(filterx_expr_regexp, regexp_subst_nojit_arg) { FilterXFuncRegexpSubstOpts opts = {.jit = TRUE}; - FilterXFunction *func = _build_subst_func("o", "X", "foobarbaz", opts); + FilterXExpr *func = _build_subst_func("o", "X", "foobarbaz", opts); cr_assert_not_null(func); cr_assert(filterx_regexp_subst_is_jit_enabled(func)); - filterx_expr_unref(&func->super); + filterx_expr_unref(func); FilterXFuncRegexpSubstOpts opts_nojit = {}; - FilterXFunction *func_nojit = _build_subst_func("o", "X", "foobarbaz", opts_nojit); + FilterXExpr *func_nojit = _build_subst_func("o", "X", "foobarbaz", opts_nojit); cr_assert_not_null(func_nojit); cr_assert(!filterx_regexp_subst_is_jit_enabled(func_nojit)); - filterx_expr_unref(&func_nojit->super); + filterx_expr_unref(func_nojit); } Test(filterx_expr_regexp, regexp_subst_match_opt_ignorecase) diff --git a/lib/filterx/tests/test_func_flatten.c b/lib/filterx/tests/test_func_flatten.c index 79cfd57e58..6d194d2a9e 100644 --- a/lib/filterx/tests/test_func_flatten.c +++ b/lib/filterx/tests/test_func_flatten.c @@ -39,7 +39,7 @@ _assert_flatten_init_fail(GList *args) { GError *err = NULL; GError *args_err = NULL; - FilterXFunction *func = filterx_function_flatten_new("test", filterx_function_args_new(args, &args_err), &err); + FilterXExpr *func = filterx_function_flatten_new("test", filterx_function_args_new(args, &args_err), &err); cr_assert(!func); cr_assert(err); g_error_free(err); @@ -52,10 +52,10 @@ _assert_flatten(GList *args, const gchar *expected_repr) GError *err = NULL; GError *args_err = NULL; - FilterXFunction *func = filterx_function_flatten_new("test", filterx_function_args_new(args, &args_err), &err); + FilterXExpr *func = filterx_function_flatten_new("test", filterx_function_args_new(args, &args_err), &err); cr_assert(!err); - FilterXObject *obj = filterx_expr_eval(&func->super); + FilterXObject *obj = filterx_expr_eval(func); cr_assert(obj); gboolean success; cr_assert(filterx_boolean_unwrap(obj, &success)); @@ -71,7 +71,7 @@ _assert_flatten(GList *args, const gchar *expected_repr) g_string_free(repr, TRUE); filterx_object_unref(obj); - filterx_expr_unref(&func->super); + filterx_expr_unref(func); filterx_object_unref(modifiable_object); filterx_expr_unref(modifiable_object_expr); } diff --git a/lib/filterx/tests/test_func_istype.c b/lib/filterx/tests/test_func_istype.c index 421a3d494a..787ea831e5 100644 --- a/lib/filterx/tests/test_func_istype.c +++ b/lib/filterx/tests/test_func_istype.c @@ -111,10 +111,10 @@ Test(filterx_func_istype, non_matching_type) filterx_literal_new(filterx_object_new(&FILTERX_TYPE_NAME(dummy))))); args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new("string", -1)))); - FilterXFunction *func_expr = filterx_function_istype_new("istype", filterx_function_args_new(args, NULL), NULL); + FilterXExpr *func_expr = filterx_function_istype_new("istype", filterx_function_args_new(args, NULL), NULL); cr_assert(func_expr); - FilterXObject *result_obj = filterx_expr_eval(&func_expr->super); + FilterXObject *result_obj = filterx_expr_eval(func_expr); cr_assert(result_obj); gboolean result; @@ -122,7 +122,7 @@ Test(filterx_func_istype, non_matching_type) cr_assert_not(result); filterx_object_unref(result_obj); - filterx_expr_unref(&func_expr->super); + filterx_expr_unref(func_expr); } Test(filterx_func_istype, matching_type) @@ -132,10 +132,10 @@ Test(filterx_func_istype, matching_type) filterx_literal_new(filterx_object_new(&FILTERX_TYPE_NAME(dummy))))); args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new("dummy", -1)))); - FilterXFunction *func_expr = filterx_function_istype_new("istype", filterx_function_args_new(args, NULL), NULL); + FilterXExpr *func_expr = filterx_function_istype_new("istype", filterx_function_args_new(args, NULL), NULL); cr_assert(func_expr); - FilterXObject *result_obj = filterx_expr_eval(&func_expr->super); + FilterXObject *result_obj = filterx_expr_eval(func_expr); cr_assert(result_obj); gboolean result; @@ -143,7 +143,7 @@ Test(filterx_func_istype, matching_type) cr_assert(result); filterx_object_unref(result_obj); - filterx_expr_unref(&func_expr->super); + filterx_expr_unref(func_expr); } Test(filterx_func_istype, matching_type_for_super_type) @@ -153,10 +153,10 @@ Test(filterx_func_istype, matching_type_for_super_type) filterx_literal_new(filterx_object_new(&FILTERX_TYPE_NAME(dummy))))); args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new("dummy_base", -1)))); - FilterXFunction *func_expr = filterx_function_istype_new("istype", filterx_function_args_new(args, NULL), NULL); + FilterXExpr *func_expr = filterx_function_istype_new("istype", filterx_function_args_new(args, NULL), NULL); cr_assert(func_expr); - FilterXObject *result_obj = filterx_expr_eval(&func_expr->super); + FilterXObject *result_obj = filterx_expr_eval(func_expr); cr_assert(result_obj); gboolean result; @@ -164,7 +164,7 @@ Test(filterx_func_istype, matching_type_for_super_type) cr_assert(result); filterx_object_unref(result_obj); - filterx_expr_unref(&func_expr->super); + filterx_expr_unref(func_expr); } Test(filterx_func_istype, matching_type_for_root_type) @@ -174,10 +174,10 @@ Test(filterx_func_istype, matching_type_for_root_type) filterx_literal_new(filterx_object_new(&FILTERX_TYPE_NAME(dummy))))); args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new("object", -1)))); - FilterXFunction *func_expr = filterx_function_istype_new("istype", filterx_function_args_new(args, NULL), NULL); + FilterXExpr *func_expr = filterx_function_istype_new("istype", filterx_function_args_new(args, NULL), NULL); cr_assert(func_expr); - FilterXObject *result_obj = filterx_expr_eval(&func_expr->super); + FilterXObject *result_obj = filterx_expr_eval(func_expr); cr_assert(result_obj); gboolean result; @@ -185,7 +185,7 @@ Test(filterx_func_istype, matching_type_for_root_type) cr_assert(result); filterx_object_unref(result_obj); - filterx_expr_unref(&func_expr->super); + filterx_expr_unref(func_expr); } static void diff --git a/lib/filterx/tests/test_func_unset_empties.c b/lib/filterx/tests/test_func_unset_empties.c index 62931980d2..bc56332da3 100644 --- a/lib/filterx/tests/test_func_unset_empties.c +++ b/lib/filterx/tests/test_func_unset_empties.c @@ -38,7 +38,7 @@ _assert_unset_empties_init_fail(GList *args) { GError *err = NULL; GError *args_err = NULL; - FilterXFunction *func = filterx_function_unset_empties_new("test", filterx_function_args_new(args, &args_err), &err); + FilterXExpr *func = filterx_function_unset_empties_new("test", filterx_function_args_new(args, &args_err), &err); cr_assert(!func); cr_assert(err); g_error_free(err); @@ -51,10 +51,10 @@ _assert_unset_empties(GList *args, const gchar *expected_repr) GError *err = NULL; GError *args_err = NULL; - FilterXFunction *func = filterx_function_unset_empties_new("test", filterx_function_args_new(args, &args_err), &err); + FilterXExpr *func = filterx_function_unset_empties_new("test", filterx_function_args_new(args, &args_err), &err); cr_assert(!err); - FilterXObject *obj = filterx_expr_eval(&func->super); + FilterXObject *obj = filterx_expr_eval(func); cr_assert(obj); gboolean success; cr_assert(filterx_boolean_unwrap(obj, &success)); @@ -70,7 +70,7 @@ _assert_unset_empties(GList *args, const gchar *expected_repr) g_string_free(repr, TRUE); filterx_object_unref(obj); - filterx_expr_unref(&func->super); + filterx_expr_unref(func); filterx_object_unref(modifiable_object); filterx_expr_unref(modifiable_object_expr); } diff --git a/lib/filterx/tests/test_object_datetime.c b/lib/filterx/tests/test_object_datetime.c index 72ed938b13..bed3a330d9 100644 --- a/lib/filterx/tests/test_object_datetime.c +++ b/lib/filterx/tests/test_object_datetime.c @@ -226,7 +226,7 @@ Test(filterx_datetime, test_filterx_datetime_repr_isodate_Z) Test(filterx_datetime, test_filterx_datetime_strptime_with_null_args) { GError *error = NULL; - FilterXFunction *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(NULL, &error), NULL); + FilterXExpr *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(NULL, &error), NULL); cr_assert_null(func_expr); } @@ -236,7 +236,7 @@ Test(filterx_datetime, test_filterx_datetime_strptime_without_args) args = g_list_append(args, filterx_function_arg_new(NULL, NULL)); args = g_list_append(args, filterx_function_arg_new(NULL, NULL)); - FilterXFunction *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); + FilterXExpr *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); cr_assert_null(func_expr); } @@ -246,7 +246,7 @@ Test(filterx_datetime, test_filterx_datetime_strptime_without_timefmt) GList *args = NULL; args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new(test_time_str, -1)))); - FilterXFunction *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); + FilterXExpr *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); cr_assert_null(func_expr); } @@ -258,15 +258,15 @@ Test(filterx_datetime, test_filterx_datetime_strptime_non_matching_timefmt) args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new("non matching timefmt", -1)))); - FilterXFunction *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); + FilterXExpr *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); cr_assert(func_expr); - FilterXObject *obj = filterx_expr_eval(&func_expr->super); + FilterXObject *obj = filterx_expr_eval(func_expr); cr_assert(obj); cr_assert(filterx_object_is_type(obj, &FILTERX_TYPE_NAME(null))); filterx_object_unref(obj); - filterx_expr_unref(&func_expr->super); + filterx_expr_unref(func_expr); } Test(filterx_datetime, test_filterx_datetime_strptime_matching_timefmt) @@ -277,10 +277,10 @@ Test(filterx_datetime, test_filterx_datetime_strptime_matching_timefmt) args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new(datefmt_isodate, -1)))); - FilterXFunction *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); + FilterXExpr *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); cr_assert(func_expr); - FilterXObject *obj = filterx_expr_eval(&func_expr->super); + FilterXObject *obj = filterx_expr_eval(func_expr); cr_assert(obj); cr_assert(filterx_object_is_type(obj, &FILTERX_TYPE_NAME(datetime))); @@ -289,7 +289,7 @@ Test(filterx_datetime, test_filterx_datetime_strptime_matching_timefmt) cr_assert_str_eq(repr->str, "2024-04-08T10:11:12.000+00:00"); filterx_object_unref(obj); - filterx_expr_unref(&func_expr->super); + filterx_expr_unref(func_expr); } Test(filterx_datetime, test_filterx_datetime_strptime_matching_nth_timefmt) @@ -302,10 +302,10 @@ Test(filterx_datetime, test_filterx_datetime_strptime_matching_nth_timefmt) args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new(datefmt_isodate, -1)))); - FilterXFunction *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); + FilterXExpr *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); cr_assert(func_expr); - FilterXObject *obj = filterx_expr_eval(&func_expr->super); + FilterXObject *obj = filterx_expr_eval(func_expr); cr_assert(obj); cr_assert(filterx_object_is_type(obj, &FILTERX_TYPE_NAME(datetime))); @@ -314,7 +314,7 @@ Test(filterx_datetime, test_filterx_datetime_strptime_matching_nth_timefmt) cr_assert_str_eq(repr->str, "2024-04-08T10:11:12.000+01:00"); filterx_object_unref(obj); - filterx_expr_unref(&func_expr->super); + filterx_expr_unref(func_expr); } Test(filterx_datetime, test_filterx_datetime_strptime_non_matching_nth_timefmt) @@ -327,15 +327,15 @@ Test(filterx_datetime, test_filterx_datetime_strptime_non_matching_nth_timefmt) args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new("non matching fmt", -1)))); - FilterXFunction *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); + FilterXExpr *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); cr_assert(func_expr); - FilterXObject *obj = filterx_expr_eval(&func_expr->super); + FilterXObject *obj = filterx_expr_eval(func_expr); cr_assert(obj); cr_assert(filterx_object_is_type(obj, &FILTERX_TYPE_NAME(null))); filterx_object_unref(obj); - filterx_expr_unref(&func_expr->super); + filterx_expr_unref(func_expr); } Test(filterx_datetime, test_filterx_datetime_strptime_invalid_arg_type) @@ -347,7 +347,7 @@ Test(filterx_datetime, test_filterx_datetime_strptime_invalid_arg_type) args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new(datefmt_isodate, -1)))); - FilterXFunction *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); + FilterXExpr *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); cr_assert_null(func_expr); } @@ -366,7 +366,7 @@ Test(filterx_datetime, test_filterx_datetime_strptime_with_non_literal_format) args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new(test_time_str, -1)))); args = g_list_append(args, filterx_function_arg_new(NULL, format_expr)); - FilterXFunction *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); + FilterXExpr *func_expr = filterx_function_strptime_new("strptime", filterx_function_args_new(args, NULL), NULL); cr_assert_null(func_expr, "%p", func_expr); } diff --git a/modules/metrics-probe/filterx/func-update-metric.c b/modules/metrics-probe/filterx/func-update-metric.c index 9a623c6a2d..03fe89171f 100644 --- a/modules/metrics-probe/filterx/func-update-metric.c +++ b/modules/metrics-probe/filterx/func-update-metric.c @@ -194,7 +194,7 @@ _extract_args(FilterXFunctionUpdateMetric *self, FilterXFunctionArgs *args, GErr return TRUE; } -FilterXFunction * +FilterXExpr * filterx_function_update_metric_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error) { FilterXFunctionUpdateMetric *self = g_new0(FilterXFunctionUpdateMetric, 1); @@ -208,7 +208,7 @@ filterx_function_update_metric_new(const gchar *function_name, FilterXFunctionAr goto error; filterx_function_args_free(args); - return &self->super; + return &self->super.super; error: filterx_function_args_free(args); diff --git a/modules/metrics-probe/filterx/func-update-metric.h b/modules/metrics-probe/filterx/func-update-metric.h index ba13f80a1e..400d16db0b 100644 --- a/modules/metrics-probe/filterx/func-update-metric.h +++ b/modules/metrics-probe/filterx/func-update-metric.h @@ -28,7 +28,6 @@ FILTERX_FUNCTION_DECLARE(update_metric); -FilterXFunction *filterx_function_update_metric_new(const gchar *function_name, FilterXFunctionArgs *args, - GError **error); +FilterXExpr *filterx_function_update_metric_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error); #endif diff --git a/modules/metrics-probe/tests/test_filterx_func_update_metric.c b/modules/metrics-probe/tests/test_filterx_func_update_metric.c index e40361b03a..53e06f4570 100644 --- a/modules/metrics-probe/tests/test_filterx_func_update_metric.c +++ b/modules/metrics-probe/tests/test_filterx_func_update_metric.c @@ -66,12 +66,12 @@ _create_func(FilterXExpr *key, FilterXExpr *labels, FilterXExpr *increment, Filt args_list = g_list_append(args_list, filterx_function_arg_new("level", level)); GError *error = NULL; - FilterXFunction *func = filterx_function_update_metric_new("update_metric", - filterx_function_args_new(args_list, &error), &error); + FilterXExpr *func = filterx_function_update_metric_new("update_metric", + filterx_function_args_new(args_list, &error), &error); cr_assert(!error, "Failed to create update_metric(): %s", error->message); cr_assert(func); - return &func->super; + return func; } static gboolean From 013c5eaa6bc77e2cd73c663f0149dfb1025ee189 Mon Sep 17 00:00:00 2001 From: Attila Szakacs Date: Wed, 7 Aug 2024 15:57:39 +0200 Subject: [PATCH 2/8] filterx/filterx-globals: add filterx_builtin_function_exists() Signed-off-by: Attila Szakacs --- lib/filterx/filterx-globals.c | 7 +++++++ lib/filterx/filterx-globals.h | 1 + 2 files changed, 8 insertions(+) diff --git a/lib/filterx/filterx-globals.c b/lib/filterx/filterx-globals.c index 55076a6557..a64bfb0004 100644 --- a/lib/filterx/filterx-globals.c +++ b/lib/filterx/filterx-globals.c @@ -73,6 +73,13 @@ filterx_builtin_simple_function_lookup(const gchar *fn_name) return filterx_builtin_simple_function_lookup_private(filterx_builtin_simple_functions, fn_name); } +gboolean +filterx_builtin_function_exists(const gchar *function_name) +{ + return !!filterx_builtin_simple_function_lookup(function_name) || + !!filterx_builtin_function_ctor_lookup(function_name); +} + static void _simple_init(void) { diff --git a/lib/filterx/filterx-globals.h b/lib/filterx/filterx-globals.h index a3249a6977..df74222a01 100644 --- a/lib/filterx/filterx-globals.h +++ b/lib/filterx/filterx-globals.h @@ -35,6 +35,7 @@ void filterx_global_deinit(void); // Builtin functions FilterXSimpleFunctionProto filterx_builtin_simple_function_lookup(const gchar *); FilterXFunctionCtor filterx_builtin_function_ctor_lookup(const gchar *function_name); +gboolean filterx_builtin_function_exists(const gchar *function_name); // FilterX types FilterXType *filterx_type_lookup(const gchar *type_name); From 8cd67453477cff1530d7a32f98c6eb35cef65bdb Mon Sep 17 00:00:00 2001 From: Attila Szakacs Date: Wed, 7 Aug 2024 15:59:45 +0200 Subject: [PATCH 3/8] filterx/filterx-globals: create generator function hashtable We are storing generator functions separately, so we can differentiate between them and regular functions. Signed-off-by: Attila Szakacs --- lib/filterx/filterx-globals.c | 34 ++++++++++++++++++++++++++++++++++ lib/filterx/filterx-globals.h | 2 ++ 2 files changed, 36 insertions(+) diff --git a/lib/filterx/filterx-globals.c b/lib/filterx/filterx-globals.c index a64bfb0004..284fc74dbb 100644 --- a/lib/filterx/filterx-globals.c +++ b/lib/filterx/filterx-globals.c @@ -42,6 +42,7 @@ static GHashTable *filterx_builtin_simple_functions = NULL; static GHashTable *filterx_builtin_function_ctors = NULL; +static GHashTable *filterx_builtin_generator_function_ctors = NULL; static GHashTable *filterx_types = NULL; void @@ -136,11 +137,43 @@ _ctors_deinit(void) filterx_builtin_function_ctors_deinit_private(filterx_builtin_function_ctors); } +static gboolean +filterx_builtin_generator_function_ctor_register(const gchar *fn_name, FilterXFunctionCtor ctor) +{ + return filterx_builtin_function_ctor_register_private(filterx_builtin_generator_function_ctors, fn_name, ctor); +} + +FilterXFunctionCtor +filterx_builtin_generator_function_ctor_lookup(const gchar *function_name) +{ + return filterx_builtin_function_ctor_lookup_private(filterx_builtin_generator_function_ctors, function_name); +} + +gboolean +filterx_builtin_generator_function_exists(const gchar *function_name) +{ + return !!filterx_builtin_generator_function_ctor_lookup(function_name); +} + +static void +_generator_ctors_init(void) +{ + filterx_builtin_function_ctors_init_private(&filterx_builtin_generator_function_ctors); +} + +static void +_generator_ctors_deinit(void) +{ + filterx_builtin_function_ctors_deinit_private(filterx_builtin_generator_function_ctors); + +} + void filterx_builtin_functions_init(void) { _simple_init(); _ctors_init(); + _generator_ctors_init(); } void @@ -148,6 +181,7 @@ filterx_builtin_functions_deinit(void) { _simple_deinit(); _ctors_deinit(); + _generator_ctors_deinit(); } // FilterX types diff --git a/lib/filterx/filterx-globals.h b/lib/filterx/filterx-globals.h index df74222a01..7b2bd312e7 100644 --- a/lib/filterx/filterx-globals.h +++ b/lib/filterx/filterx-globals.h @@ -35,7 +35,9 @@ void filterx_global_deinit(void); // Builtin functions FilterXSimpleFunctionProto filterx_builtin_simple_function_lookup(const gchar *); FilterXFunctionCtor filterx_builtin_function_ctor_lookup(const gchar *function_name); +FilterXFunctionCtor filterx_builtin_generator_function_ctor_lookup(const gchar *function_name); gboolean filterx_builtin_function_exists(const gchar *function_name); +gboolean filterx_builtin_generator_function_exists(const gchar *function_name); // FilterX types FilterXType *filterx_type_lookup(const gchar *type_name); From edee3d7645544cd57ab4ea5a9a16a00e140845ce Mon Sep 17 00:00:00 2001 From: Attila Szakacs Date: Wed, 7 Aug 2024 15:39:08 +0200 Subject: [PATCH 4/8] filterx,cfg-lexer: pre-validate function names in lexer We will introduce generator functions in the next commit. Generator functions have the exact same syntax as regular functions, but we need to write separate rules in the grammar to handle them, but if we don't know whether an identifier is a regular function name or generator function name, the rules will conflict. We can solve this by preprocessing LL_IDENTIFIERs in the lexer, and trying to find a corresponding function for it, and if it exists, returning a separate token: LL_FILTERX_FUNC. Some of this commit's code changes on their own might not really make sense, but it will in the next commit. Signed-off-by: Attila Szakacs --- lib/cfg-grammar.y | 1 + lib/cfg-lexer.c | 16 +++++++++++++ lib/filterx/filterx-grammar.ym | 44 ++++++++++++++++++++++++---------- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/lib/cfg-grammar.y b/lib/cfg-grammar.y index 365d79fbc4..4ff12bee1c 100644 --- a/lib/cfg-grammar.y +++ b/lib/cfg-grammar.y @@ -409,6 +409,7 @@ main_location_print (FILE *yyo, YYLTYPE const * const yylocp) %token LL_PLUGIN 10436 %token LL_TEMPLATE_REF 10437 %token LL_MESSAGE_REF 10438 +%token LL_FILTERX_FUNC 10439 %destructor { free($$); } diff --git a/lib/cfg-lexer.c b/lib/cfg-lexer.c index 83e74c13c3..cbeae48f17 100644 --- a/lib/cfg-lexer.c +++ b/lib/cfg-lexer.c @@ -32,6 +32,7 @@ #include "pathutils.h" #include "plugin.h" #include "plugin-types.h" +#include "filterx/filterx-globals.h" #include #include @@ -1219,6 +1220,21 @@ cfg_lexer_lex(CfgLexer *self, CFG_STYPE *yylval, CFG_LTYPE *yylloc) } } } + + if (cfg_lexer_get_context_type(self) == LL_CONTEXT_FILTERX) + { + if (tok == LL_IDENTIFIER) + { + PluginContext *plugin_context = &self->cfg->plugin_context; + + if ((self->cfg && plugin_is_plugin_available(plugin_context, LL_CONTEXT_FILTERX_FUNC, yylval->cptr)) || + (self->cfg && plugin_is_plugin_available(plugin_context, LL_CONTEXT_FILTERX_SIMPLE_FUNC, yylval->cptr)) || + filterx_builtin_function_exists(yylval->cptr)) + { + tok = LL_FILTERX_FUNC; + } + } + } } preprocess_result = cfg_lexer_preprocess(self, tok, yylval, yylloc); diff --git a/lib/filterx/filterx-grammar.ym b/lib/filterx/filterx-grammar.ym index 1ea790be6c..289b96fd2a 100644 --- a/lib/filterx/filterx-grammar.ym +++ b/lib/filterx/filterx-grammar.ym @@ -147,6 +147,8 @@ construct_template_expr(LogTemplate *template) %type if %type ternary %type default +%type identifier +%type func_name %% @@ -188,7 +190,7 @@ stmt_expr plus_assignment : variable KW_PLUS_ASSIGN expr { $$ = filterx_assign_new(filterx_expr_ref($1), filterx_operator_plus_new($1, $3)); } | expr '[' expr ']' KW_PLUS_ASSIGN expr { $$ = filterx_set_subscript_new(filterx_expr_ref($1), filterx_expr_ref($3), filterx_operator_plus_new(filterx_get_subscript_new($1, $3), $6)); } - | expr '.' LL_IDENTIFIER KW_PLUS_ASSIGN expr + | expr '.' identifier KW_PLUS_ASSIGN expr { $$ = filterx_setattr_new(filterx_expr_ref($1), $3, filterx_operator_plus_new(filterx_getattr_new($1, $3), $5)); free($3); @@ -199,7 +201,7 @@ plus_assignment assignment /* TODO extract lvalues */ : variable KW_ASSIGN expr { $$ = filterx_assign_new($1, $3); } - | expr '.' LL_IDENTIFIER KW_ASSIGN expr { $$ = filterx_setattr_new($1, $3, $5); free($3); } + | expr '.' identifier KW_ASSIGN expr { $$ = filterx_setattr_new($1, $3, $5); free($3); } | expr '[' expr ']' KW_ASSIGN expr { $$ = filterx_set_subscript_new($1, $3, $6); } | expr '[' ']' KW_ASSIGN expr { $$ = filterx_set_subscript_new($1, NULL, $5); } | generator_assignment @@ -210,7 +212,7 @@ assignment generator_assignment /* TODO extract lvalues */ - : expr '.' LL_IDENTIFIER KW_ASSIGN expr_generator + : expr '.' identifier KW_ASSIGN expr_generator { filterx_generator_set_fillable($5, filterx_getattr_new(filterx_expr_ref($1), $3)); @@ -249,11 +251,11 @@ generator_assignment generator_plus_assignment : variable KW_PLUS_ASSIGN expr_generator { $$ = $3; filterx_generator_set_fillable($3, $1); } | expr '[' expr ']' KW_PLUS_ASSIGN expr_generator { $$ = $6; filterx_generator_set_fillable($6, filterx_get_subscript_new($1, $3)); } - | expr '.' LL_IDENTIFIER KW_PLUS_ASSIGN expr_generator { $$ = $5; filterx_generator_set_fillable($5, filterx_getattr_new($1, $3)); free($3);} + | expr '.' identifier KW_PLUS_ASSIGN expr_generator { $$ = $5; filterx_generator_set_fillable($5, filterx_getattr_new($1, $3)); free($3);} generator_casted_assignment /* TODO extract lvalues */ - : variable KW_ASSIGN LL_IDENTIFIER '(' expr_generator ')' + : variable KW_ASSIGN func_name '(' expr_generator ')' { GError *error = NULL; FilterXExpr *func = filterx_function_lookup(configuration, $3, NULL, &error); @@ -268,7 +270,7 @@ generator_casted_assignment ); free($3); } - | expr '.' LL_IDENTIFIER KW_ASSIGN LL_IDENTIFIER '(' expr_generator ')' + | expr '.' identifier KW_ASSIGN func_name '(' expr_generator ')' { GError *error = NULL; FilterXExpr *func = filterx_function_lookup(configuration, $5, NULL, &error); @@ -283,7 +285,7 @@ generator_casted_assignment ); free($3); } - | expr '[' expr ']' KW_ASSIGN LL_IDENTIFIER '(' expr_generator ')' + | expr '[' expr ']' KW_ASSIGN func_name '(' expr_generator ')' { GError *error = NULL; FilterXExpr *func = filterx_function_lookup(configuration, $6, NULL, &error); @@ -298,7 +300,7 @@ generator_casted_assignment ); free($6); } - | expr '[' ']' KW_ASSIGN LL_IDENTIFIER '(' expr_generator ')' + | expr '[' ']' KW_ASSIGN func_name '(' expr_generator ')' { GError *error = NULL; FilterXExpr *func = filterx_function_lookup(configuration, $5, NULL, &error); @@ -327,7 +329,7 @@ expr | expr KW_OR expr { $$ = filterx_binary_or_new($1, $3); } | expr KW_AND expr { $$ = filterx_binary_and_new($1, $3); } /* TODO extract lvalues */ - | expr '.' LL_IDENTIFIER { $$ = filterx_getattr_new($1, $3); free($3); } + | expr '.' identifier { $$ = filterx_getattr_new($1, $3); free($3); } | expr '[' expr ']' { $$ = filterx_get_subscript_new($1, $3); } | expr KW_TA_LT expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AWARE | FCMPX_LT); } | expr KW_TA_LE expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AWARE | FCMPX_LT | FCMPX_EQ); } @@ -375,7 +377,7 @@ expr_generator_unchecked ; function_call - : LL_IDENTIFIER '(' arguments ')' { + : func_name '(' arguments ')' { GError *error = NULL; FilterXExpr *res = filterx_function_lookup(configuration, $1, $3, &error); CHECK_FUNCTION_ERROR(res, @$, $1, error); @@ -436,13 +438,13 @@ literal_object ; variable - : '$' LL_IDENTIFIER { $$ = filterx_msg_variable_expr_new($2); free($2); } + : '$' identifier { $$ = filterx_msg_variable_expr_new($2); free($2); } | LL_MESSAGE_REF { $$ = filterx_msg_variable_expr_new($1); free($1); } | filterx_variable ; filterx_variable - : LL_IDENTIFIER { $$ = filterx_floating_variable_expr_new($1); free($1); } + : identifier { $$ = filterx_floating_variable_expr_new($1); free($1); } ; boolean @@ -571,6 +573,24 @@ default } ; +identifier + : LL_IDENTIFIER + | LL_FILTERX_FUNC + ; + +/* + * The lexer returns LL_FILTERX_FUNC if a corresponding function + * is available, so LL_IDENTIFIER will never return a function. + * However we should use this nonterminal, where we are defining + * non-generator function related rules, solely for sensible error + * reporting. + * (LL_IDENTIFIER will throw a "function not found" error.) + */ +func_name + : LL_IDENTIFIER + | LL_FILTERX_FUNC + ; + /* INCLUDE_RULES */ %% From 488dc258629dc211bd05fae567e9397e2a82e818 Mon Sep 17 00:00:00 2001 From: Attila Szakacs Date: Wed, 7 Aug 2024 16:01:53 +0200 Subject: [PATCH 5/8] filterx: introduce generator functions Signed-off-by: Attila Szakacs --- lib/cfg-grammar.y | 4 ++- lib/cfg-lexer.c | 6 ++++ lib/filterx/expr-function.c | 59 ++++++++++++++++++++++++++++++++++ lib/filterx/expr-function.h | 32 ++++++++++++++++++ lib/filterx/filterx-grammar.ym | 19 +++++++++++ 5 files changed, 119 insertions(+), 1 deletion(-) diff --git a/lib/cfg-grammar.y b/lib/cfg-grammar.y index 4ff12bee1c..1da422b4af 100644 --- a/lib/cfg-grammar.y +++ b/lib/cfg-grammar.y @@ -197,9 +197,10 @@ main_location_print (FILE *yyo, YYLTYPE const * const yylocp) %token LL_CONTEXT_FILTERX_SIMPLE_FUNC 24 %token LL_CONTEXT_FILTERX_ENUM 25 %token LL_CONTEXT_FILTERX_FUNC 26 +%token LL_CONTEXT_FILTERX_GEN_FUNC 27 /* this is a placeholder for unit tests, must be the latest & largest */ -%token LL_CONTEXT_MAX 27 +%token LL_CONTEXT_MAX 28 %left ';' @@ -410,6 +411,7 @@ main_location_print (FILE *yyo, YYLTYPE const * const yylocp) %token LL_TEMPLATE_REF 10437 %token LL_MESSAGE_REF 10438 %token LL_FILTERX_FUNC 10439 +%token LL_FILTERX_GEN_FUNC 10440 %destructor { free($$); } diff --git a/lib/cfg-lexer.c b/lib/cfg-lexer.c index cbeae48f17..b673d9e605 100644 --- a/lib/cfg-lexer.c +++ b/lib/cfg-lexer.c @@ -1233,6 +1233,11 @@ cfg_lexer_lex(CfgLexer *self, CFG_STYPE *yylval, CFG_LTYPE *yylloc) { tok = LL_FILTERX_FUNC; } + else if ((self->cfg && plugin_is_plugin_available(plugin_context, LL_CONTEXT_FILTERX_GEN_FUNC, yylval->cptr)) || + filterx_builtin_generator_function_exists(yylval->cptr)) + { + tok = LL_FILTERX_GEN_FUNC; + } } } } @@ -1358,6 +1363,7 @@ static const gchar *lexer_contexts[] = [LL_CONTEXT_FILTERX_SIMPLE_FUNC] = "filterx-simple-func", [LL_CONTEXT_FILTERX_ENUM] = "filterx-enum", [LL_CONTEXT_FILTERX_FUNC] = "filterx-func", + [LL_CONTEXT_FILTERX_GEN_FUNC] = "filterx-gen-func", }; gint diff --git a/lib/filterx/expr-function.c b/lib/filterx/expr-function.c index e1706c0cb6..6400cff841 100644 --- a/lib/filterx/expr-function.c +++ b/lib/filterx/expr-function.c @@ -156,6 +156,28 @@ filterx_function_init_instance(FilterXFunction *s, const gchar *function_name) s->super.free_fn = _function_free; } +void +filterx_generator_function_free_method(FilterXGeneratorFunction *s) +{ + g_free(s->function_name); + filterx_generator_free_method(&s->super.super); +} + +static void +_generator_function_free(FilterXExpr *s) +{ + FilterXGeneratorFunction *self = (FilterXGeneratorFunction *) s; + filterx_generator_function_free_method(self); +} + +void +filterx_generator_function_init_instance(FilterXGeneratorFunction *s, const gchar *function_name) +{ + filterx_generator_init_instance(&s->super.super); + s->function_name = g_strdup_printf("%s()", function_name); + s->super.super.free_fn = _generator_function_free; +} + struct _FilterXFunctionArgs { GPtrArray *positional_args; @@ -572,3 +594,40 @@ filterx_function_lookup(GlobalConfig *cfg, const gchar *function_name, GList *ar g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_FUNCTION_NOT_FOUND, "function not found"); return NULL; } + +static FilterXExpr * +_lookup_generator_function(GlobalConfig *cfg, const gchar *function_name, FilterXFunctionArgs *args, GError **error) +{ + // Checking filterx builtin generator functions first + FilterXFunctionCtor ctor = filterx_builtin_generator_function_ctor_lookup(function_name); + + if (!ctor) + { + // fallback to plugin lookup + Plugin *p = cfg_find_plugin(cfg, LL_CONTEXT_FILTERX_GEN_FUNC, function_name); + if (!p) + return NULL; + ctor = plugin_construct(p); + } + + if (!ctor) + return NULL; + return ctor(function_name, args, error); +} + +/* NOTE: takes the references of objects passed in "arguments" */ +FilterXExpr * +filterx_generator_function_lookup(GlobalConfig *cfg, const gchar *function_name, GList *args_list, GError **error) +{ + FilterXFunctionArgs *args = filterx_function_args_new(args_list, error); + if (!args) + return NULL; + + FilterXExpr *expr = _lookup_generator_function(cfg, function_name, args, error); + if (expr) + return expr; + + if (!(*error)) + g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_FUNCTION_NOT_FOUND, "function not found"); + return NULL; +} diff --git a/lib/filterx/expr-function.h b/lib/filterx/expr-function.h index 987832f70a..71b97323ed 100644 --- a/lib/filterx/expr-function.h +++ b/lib/filterx/expr-function.h @@ -28,6 +28,7 @@ #include "filterx/filterx-expr.h" #include "filterx/filterx-object.h" +#include "filterx/expr-generator.h" #include "generic-number.h" #include "plugin.h" @@ -41,6 +42,12 @@ typedef struct _FilterXFunction gchar *function_name; } FilterXFunction; +typedef struct _FilterXGeneratorFunction +{ + FilterXExprGenerator super; + gchar *function_name; +} FilterXGeneratorFunction; + typedef struct _FilterXFunctionArgs FilterXFunctionArgs; typedef struct _FilterXFunctionArg { @@ -63,6 +70,8 @@ enum FilterXFunctionError void filterx_function_init_instance(FilterXFunction *s, const gchar *function_name); void filterx_function_free_method(FilterXFunction *s); +void filterx_generator_function_init_instance(FilterXGeneratorFunction *s, const gchar *function_name); +void filterx_generator_function_free_method(FilterXGeneratorFunction *s); FilterXFunctionArg *filterx_function_arg_new(const gchar *name, FilterXExpr *value); FilterXFunctionArgs *filterx_function_args_new(GList *args, GError **error); @@ -90,6 +99,8 @@ gboolean filterx_function_args_check(FilterXFunctionArgs *self, GError **error); void filterx_function_args_free(FilterXFunctionArgs *self); FilterXExpr *filterx_function_lookup(GlobalConfig *cfg, const gchar *function_name, GList *args, GError **error); +FilterXExpr *filterx_generator_function_lookup(GlobalConfig *cfg, const gchar *function_name, GList *args, + GError **error); #define FILTERX_SIMPLE_FUNCTION_PROTOTYPE(func_name) \ @@ -135,4 +146,25 @@ FilterXExpr *filterx_function_lookup(GlobalConfig *cfg, const gchar *function_na .construct = filterx_function_ ## func_name ## _construct, \ } +#define FILTERX_GENERATOR_FUNCTION_PROTOTYPE(func_name) \ + gpointer \ + filterx_generator_function_ ## func_name ## _construct(Plugin *self) + +#define FILTERX_GENERATOR_FUNCTION_DECLARE(func_name) \ + FILTERX_GENERATOR_FUNCTION_PROTOTYPE(func_name); + +#define FILTERX_GENERATOR_FUNCTION(func_name, ctor) \ + FILTERX_GENERATOR_FUNCTION_PROTOTYPE(func_name) \ + { \ + FilterXFunctionCtor f = ctor; \ + return (gpointer) f; \ + } + +#define FILTERX_GENERATOR_FUNCTION_PLUGIN(func_name) \ + { \ + .type = LL_CONTEXT_FILTERX_GEN_FUNC, \ + .name = # func_name, \ + .construct = filterx_generator_function_ ## func_name ## _construct, \ + } + #endif diff --git a/lib/filterx/filterx-grammar.ym b/lib/filterx/filterx-grammar.ym index 289b96fd2a..da75e96135 100644 --- a/lib/filterx/filterx-grammar.ym +++ b/lib/filterx/filterx-grammar.ym @@ -121,6 +121,7 @@ construct_template_expr(LogTemplate *template) %type expr_value %type expr_generator %type expr_generator_unchecked +%type generator_function_call %type function_call %type arguments %type argument @@ -149,6 +150,7 @@ construct_template_expr(LogTemplate *template) %type default %type identifier %type func_name +%type gen_func_name %% @@ -369,6 +371,7 @@ expr_generator expr_generator_unchecked : dict_generator | list_generator + | generator_function_call | regexp_search | '(' expr_generator ')' { $$ = $2; } | expr '+' expr_generator { $$ = filterx_operator_plus_generator_new($1, $3); } @@ -376,6 +379,17 @@ expr_generator_unchecked | expr_generator '+' expr_generator { $$ = filterx_operator_plus_generator_new($1, $3); } ; +generator_function_call + : gen_func_name '(' arguments ')' { + GError *error = NULL; + FilterXExpr *res = filterx_generator_function_lookup(configuration, $1, $3, &error); + CHECK_FUNCTION_ERROR(res, @$, $1, error); + free($1); + $$ = res; + } + ; + + function_call : func_name '(' arguments ')' { GError *error = NULL; @@ -576,6 +590,7 @@ default identifier : LL_IDENTIFIER | LL_FILTERX_FUNC + | LL_FILTERX_GEN_FUNC ; /* @@ -591,6 +606,10 @@ func_name | LL_FILTERX_FUNC ; +gen_func_name + : LL_FILTERX_GEN_FUNC + ; + /* INCLUDE_RULES */ %% From 18e927ebe9bea093ed16c482d67db3b33d32ac63 Mon Sep 17 00:00:00 2001 From: Attila Szakacs Date: Wed, 7 Aug 2024 15:39:31 +0200 Subject: [PATCH 6/8] filterx/expr-subst: add "Usage: " to error message Signed-off-by: Attila Szakacs --- lib/filterx/expr-regexp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/filterx/expr-regexp.c b/lib/filterx/expr-regexp.c index d7b2566c64..8e2381cfed 100644 --- a/lib/filterx/expr-regexp.c +++ b/lib/filterx/expr-regexp.c @@ -30,7 +30,7 @@ #include "compat/pcre.h" #include "scratch-buffers.h" -#define FILTERX_FUNC_REGEXP_SUBST_USAGE "regexp_subst(string, pattern, replacement, " \ +#define FILTERX_FUNC_REGEXP_SUBST_USAGE "Usage: regexp_subst(string, pattern, replacement, " \ FILTERX_FUNC_REGEXP_SUBST_FLAG_JIT_NAME"=(boolean) " \ FILTERX_FUNC_REGEXP_SUBST_FLAG_GLOBAL_NAME"=(boolean) " \ FILTERX_FUNC_REGEXP_SUBST_FLAG_UTF8_NAME"=(boolean) " \ From 9b43793012bd9aae08786e336016e7c20998191a Mon Sep 17 00:00:00 2001 From: Attila Szakacs Date: Wed, 7 Aug 2024 15:41:33 +0200 Subject: [PATCH 7/8] filterx/expr-regexp: transform regexp_search() to generator fn Signed-off-by: Attila Szakacs --- lib/filterx/expr-regexp.c | 66 ++++++++++++++++++++++------ lib/filterx/expr-regexp.h | 3 +- lib/filterx/filterx-globals.c | 2 + lib/filterx/filterx-grammar.ym | 7 --- lib/filterx/filterx-parser.c | 3 -- lib/filterx/tests/test_expr_regexp.c | 26 +++++++++-- 6 files changed, 79 insertions(+), 28 deletions(-) diff --git a/lib/filterx/expr-regexp.c b/lib/filterx/expr-regexp.c index 8e2381cfed..e41be59a7a 100644 --- a/lib/filterx/expr-regexp.c +++ b/lib/filterx/expr-regexp.c @@ -27,6 +27,7 @@ #include "filterx/object-string.h" #include "filterx/object-list-interface.h" #include "filterx/object-dict-interface.h" +#include "filterx/expr-function.h" #include "compat/pcre.h" #include "scratch-buffers.h" @@ -37,6 +38,8 @@ FILTERX_FUNC_REGEXP_SUBST_FLAG_IGNORECASE_NAME"=(boolean) " \ FILTERX_FUNC_REGEXP_SUBST_FLAG_NEWLINE_NAME"=(boolean))" \ +#define FILTERX_FUNC_REGEXP_SEARCH_USAGE "Usage: regexp_search(string, pattern)" + typedef struct FilterXReMatchState_ { pcre2_match_data *match_data; @@ -350,7 +353,7 @@ filterx_expr_regexp_nomatch_new(FilterXExpr *lhs, const gchar *pattern) typedef struct FilterXExprRegexpSearchGenerator_ { - FilterXExprGenerator super; + FilterXGeneratorFunction super; FilterXExpr *lhs; pcre2_code_8 *pattern; } FilterXExprRegexpSearchGenerator; @@ -412,31 +415,66 @@ _regexp_search_generator_free(FilterXExpr *s) filterx_expr_unref(self->lhs); if (self->pattern) pcre2_code_free(self->pattern); - filterx_generator_free_method(s); + filterx_generator_function_free_method(&self->super); } -/* Takes reference of lhs */ -FilterXExpr * -filterx_expr_regexp_search_generator_new(FilterXExpr *lhs, const gchar *pattern) +static gboolean +_extract_search_args(FilterXExprRegexpSearchGenerator *self, FilterXFunctionArgs *args, GError **error) { - FilterXExprRegexpSearchGenerator *self = g_new0(FilterXExprRegexpSearchGenerator, 1); + if (filterx_function_args_len(args) != 2) + { + g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL, + "invalid number of arguments. " FILTERX_FUNC_REGEXP_SEARCH_USAGE); + return FALSE; + } - filterx_generator_init_instance(&self->super.super); - self->super.generate = _regexp_search_generator_generate; - self->super.super.free_fn = _regexp_search_generator_free; - self->super.create_container = _regexp_search_generator_create_container; + self->lhs = filterx_function_args_get_expr(args, 0); + + const gchar *pattern = filterx_function_args_get_literal_string(args, 1, NULL); + if (!pattern) + { + g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL, + "pattern must be string literal. " FILTERX_FUNC_REGEXP_SEARCH_USAGE); + return FALSE; + } - self->lhs = lhs; self->pattern = _compile_pattern_defaults(pattern); if (!self->pattern) { - filterx_expr_unref(&self->super.super); - return NULL; + g_set_error(error, FILTERX_FUNCTION_ERROR, FILTERX_FUNCTION_ERROR_CTOR_FAIL, + "failed to compile pattern. " FILTERX_FUNC_REGEXP_SEARCH_USAGE); + return FALSE; } - return &self->super.super; + return TRUE; + +} + +/* Takes reference of lhs */ +FilterXExpr * +filterx_generator_function_regexp_search_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error) +{ + FilterXExprRegexpSearchGenerator *self = g_new0(FilterXExprRegexpSearchGenerator, 1); + + filterx_generator_function_init_instance(&self->super, function_name); + self->super.super.generate = _regexp_search_generator_generate; + self->super.super.super.free_fn = _regexp_search_generator_free; + self->super.super.create_container = _regexp_search_generator_create_container; + + if (!_extract_search_args(self, args, error) || + !filterx_function_args_check(args, error)) + goto error; + + filterx_function_args_free(args); + return &self->super.super.super; + +error: + filterx_function_args_free(args); + filterx_expr_unref(&self->super.super.super); + return NULL; } + typedef struct FilterXFuncRegexpSubst_ { FilterXFunction super; diff --git a/lib/filterx/expr-regexp.h b/lib/filterx/expr-regexp.h index 81530fe267..ca63d2556e 100644 --- a/lib/filterx/expr-regexp.h +++ b/lib/filterx/expr-regexp.h @@ -45,7 +45,8 @@ typedef struct FilterXFuncRegexpSubstOpts_ FilterXExpr *filterx_expr_regexp_match_new(FilterXExpr *lhs, const gchar *pattern); FilterXExpr *filterx_expr_regexp_nomatch_new(FilterXExpr *lhs, const gchar *pattern); -FilterXExpr *filterx_expr_regexp_search_generator_new(FilterXExpr *lhs, const gchar *pattern); +FilterXExpr *filterx_generator_function_regexp_search_new(const gchar *function_name, FilterXFunctionArgs *args, + GError **error); FilterXExpr *filterx_function_regexp_subst_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error); gboolean filterx_regexp_subst_is_jit_enabled(FilterXExpr *s); diff --git a/lib/filterx/filterx-globals.c b/lib/filterx/filterx-globals.c index 284fc74dbb..15840114a7 100644 --- a/lib/filterx/filterx-globals.c +++ b/lib/filterx/filterx-globals.c @@ -159,6 +159,8 @@ static void _generator_ctors_init(void) { filterx_builtin_function_ctors_init_private(&filterx_builtin_generator_function_ctors); + g_assert(filterx_builtin_generator_function_ctor_register("regexp_search", + filterx_generator_function_regexp_search_new)); } static void diff --git a/lib/filterx/filterx-grammar.ym b/lib/filterx/filterx-grammar.ym index da75e96135..0703ec3d8b 100644 --- a/lib/filterx/filterx-grammar.ym +++ b/lib/filterx/filterx-grammar.ym @@ -105,7 +105,6 @@ construct_template_expr(LogTemplate *template) %token KW_ENUM %token KW_ISSET %token KW_DECLARE -%token KW_REGEXP_SEARCH %type block %type stmts @@ -140,7 +139,6 @@ construct_template_expr(LogTemplate *template) %type inner_list_generator %type list_element %type list_elements -%type regexp_search %type regexp_match %type boolean %type conditional @@ -372,7 +370,6 @@ expr_generator_unchecked : dict_generator | list_generator | generator_function_call - | regexp_search | '(' expr_generator ')' { $$ = $2; } | expr '+' expr_generator { $$ = filterx_operator_plus_generator_new($1, $3); } | expr_generator '+' expr { $$ = filterx_operator_plus_generator_new($1, $3); } @@ -521,10 +518,6 @@ list_element | inner_list_generator { $$ = filterx_literal_generator_elem_new(NULL, $1, FALSE); } ; -regexp_search - : KW_REGEXP_SEARCH '(' expr ',' string ')' { $$ = filterx_expr_regexp_search_generator_new($3, $5); free($5); } - ; - regexp_match : expr KW_REGEXP_MATCH string { $$ = filterx_expr_regexp_match_new($1, $3); free($3); } | expr KW_REGEXP_NOMATCH string { $$ = filterx_expr_regexp_nomatch_new($1, $3); free($3); } diff --git a/lib/filterx/filterx-parser.c b/lib/filterx/filterx-parser.c index 979cdfff2e..6c7b77c52a 100644 --- a/lib/filterx/filterx-parser.c +++ b/lib/filterx/filterx-parser.c @@ -51,9 +51,6 @@ static CfgLexerKeyword filterx_keywords[] = { "isset", KW_ISSET }, { "declare", KW_DECLARE }, - /* TODO: This should be done via generator function. */ - { "regexp_search", KW_REGEXP_SEARCH }, - { CFG_KEYWORD_STOP }, }; diff --git a/lib/filterx/tests/test_expr_regexp.c b/lib/filterx/tests/test_expr_regexp.c index 5627221060..0cefdc6bc8 100644 --- a/lib/filterx/tests/test_expr_regexp.c +++ b/lib/filterx/tests/test_expr_regexp.c @@ -80,7 +80,11 @@ Test(filterx_expr_regexp, regexp_match) static FilterXObject * _search(const gchar *lhs, const gchar *pattern) { - FilterXExpr *expr = filterx_expr_regexp_search_generator_new(filterx_literal_new(filterx_string_new(lhs, -1)), pattern); + GList *args = NULL; + args = g_list_append(args, filterx_function_arg_new(NULL, filterx_non_literal_new(filterx_string_new(lhs, -1)))); + args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new(pattern, -1)))); + + FilterXExpr *expr = filterx_generator_function_regexp_search_new("test", filterx_function_args_new(args, NULL), NULL); FilterXExpr *parent_fillable_expr_new = filterx_literal_new(filterx_test_dict_new()); FilterXExpr *cc_expr = filterx_generator_create_container_new(expr, parent_fillable_expr_new); FilterXExpr *fillable_expr = filterx_literal_new(filterx_expr_eval(cc_expr)); @@ -104,7 +108,12 @@ _search(const gchar *lhs, const gchar *pattern) static void _search_with_fillable(const gchar *lhs, const gchar *pattern, FilterXObject *fillable) { - FilterXExpr *expr = filterx_expr_regexp_search_generator_new(filterx_literal_new(filterx_string_new(lhs, -1)), pattern); + GList *args = NULL; + args = g_list_append(args, filterx_function_arg_new(NULL, filterx_non_literal_new(filterx_string_new(lhs, -1)))); + args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new(pattern, -1)))); + + FilterXExpr *expr = filterx_generator_function_regexp_search_new("test", + filterx_function_args_new(args, NULL), NULL); filterx_generator_set_fillable(expr, filterx_literal_new(filterx_object_ref(fillable))); FilterXObject *result_obj = filterx_expr_eval(expr); @@ -118,7 +127,18 @@ _search_with_fillable(const gchar *lhs, const gchar *pattern, FilterXObject *fil static void _assert_search_init_error(const gchar *lhs, const gchar *pattern) { - cr_assert_not(filterx_expr_regexp_search_generator_new(filterx_literal_new(filterx_string_new(lhs, -1)), pattern)); + GList *args = NULL; + args = g_list_append(args, filterx_function_arg_new(NULL, filterx_non_literal_new(filterx_string_new(lhs, -1)))); + args = g_list_append(args, filterx_function_arg_new(NULL, filterx_literal_new(filterx_string_new(pattern, -1)))); + + GError *arg_err = NULL; + GError *func_err = NULL; + cr_assert_not(filterx_generator_function_regexp_search_new("test", + filterx_function_args_new(args, &arg_err), &func_err)); + + cr_assert(arg_err || func_err); + g_clear_error(&arg_err); + g_clear_error(&func_err); } static void From 72cc2500bad86a166ffef7a83c239cb36e7aba0c Mon Sep 17 00:00:00 2001 From: Attila Szakacs Date: Wed, 7 Aug 2024 16:09:19 +0200 Subject: [PATCH 8/8] filterx/filterx-grammar: factor out expr_plus_generator Signed-off-by: Attila Szakacs --- lib/filterx/filterx-grammar.ym | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/filterx/filterx-grammar.ym b/lib/filterx/filterx-grammar.ym index 0703ec3d8b..d726d41f04 100644 --- a/lib/filterx/filterx-grammar.ym +++ b/lib/filterx/filterx-grammar.ym @@ -120,6 +120,7 @@ construct_template_expr(LogTemplate *template) %type expr_value %type expr_generator %type expr_generator_unchecked +%type expr_plus_generator %type generator_function_call %type function_call %type arguments @@ -370,8 +371,12 @@ expr_generator_unchecked : dict_generator | list_generator | generator_function_call + | expr_plus_generator | '(' expr_generator ')' { $$ = $2; } - | expr '+' expr_generator { $$ = filterx_operator_plus_generator_new($1, $3); } + ; + +expr_plus_generator + : expr '+' expr_generator { $$ = filterx_operator_plus_generator_new($1, $3); } | expr_generator '+' expr { $$ = filterx_operator_plus_generator_new($1, $3); } | expr_generator '+' expr_generator { $$ = filterx_operator_plus_generator_new($1, $3); } ;