diff --git a/lib/cfg-block-generator.c b/lib/cfg-block-generator.c index 00811f2784..2179acb247 100644 --- a/lib/cfg-block-generator.c +++ b/lib/cfg-block-generator.c @@ -73,11 +73,11 @@ cfg_block_generator_init_instance(CfgBlockGenerator *self, gint context, const g self->context = context; self->name = g_strdup(name); self->format_name = cfg_block_generator_format_name_method; - self->free_fn = cfg_block_generator_free_instance; + self->free_fn = cfg_block_generator_free_method; } void -cfg_block_generator_free_instance(CfgBlockGenerator *self) +cfg_block_generator_free_method(CfgBlockGenerator *self) { g_free(self->name); } diff --git a/lib/cfg-block-generator.h b/lib/cfg-block-generator.h index 8f928136e9..c12c11f6e2 100644 --- a/lib/cfg-block-generator.h +++ b/lib/cfg-block-generator.h @@ -59,7 +59,7 @@ cfg_block_generator_format_name(CfgBlockGenerator *self, gchar *buf, gsize buf_l gboolean cfg_block_generator_generate(CfgBlockGenerator *self, GlobalConfig *cfg, gpointer args, GString *result, const gchar *reference); void cfg_block_generator_init_instance(CfgBlockGenerator *self, gint context, const gchar *name); -void cfg_block_generator_free_instance(CfgBlockGenerator *self); +void cfg_block_generator_free_method(CfgBlockGenerator *self); CfgBlockGenerator *cfg_block_generator_ref(CfgBlockGenerator *self); void cfg_block_generator_unref(CfgBlockGenerator *self); diff --git a/lib/cfg-block.c b/lib/cfg-block.c index 89ae229bea..abbe74ba1a 100644 --- a/lib/cfg-block.c +++ b/lib/cfg-block.c @@ -196,7 +196,7 @@ cfg_block_free_instance(CfgBlockGenerator *s) g_free(self->filename); g_free(self->content); cfg_args_unref(self->arg_defs); - cfg_block_generator_free_instance(s); + cfg_block_generator_free_method(s); } diff --git a/lib/cfg-parser.c b/lib/cfg-parser.c index 87a6c30019..ed185fc799 100644 --- a/lib/cfg-parser.c +++ b/lib/cfg-parser.c @@ -378,3 +378,43 @@ cfg_process_yesno(const gchar *yesno) return TRUE; return FALSE; } + +gboolean +cfg_process_list_of_literals(const gchar *input, GList **result) +{ + if (strchr(input, '"') || strchr(input, '\'')) + { + fprintf(stderr, "Error: list of literals must not contain single or double quotes: %s\n", input); + return FALSE; + } + + *result = NULL; + + gchar *input_copy = g_strdup(input); + const gchar delimiters[] = ", \t\n"; + const gchar *elem = strtok(input_copy, delimiters); + while (elem) + { + if (strlen(elem) > 0) + *result = g_list_append(*result, __normalize_key(elem)); + elem = strtok(NULL, delimiters); + } + + g_free(input_copy); + return TRUE; +} + +static gint +_compare_literals_normalized(gconstpointer a, gconstpointer b) +{ + gchar *normalized_b = __normalize_key(b); + gint result = strcmp(a, normalized_b); + g_free(normalized_b); + return result; +} + +gboolean +cfg_is_literal_in_list_of_literals(GList *list, const gchar *literal) +{ + return !!g_list_find_custom(list, literal, _compare_literals_normalized); +} diff --git a/lib/cfg-parser.h b/lib/cfg-parser.h index a60915e277..1c8551a577 100644 --- a/lib/cfg-parser.h +++ b/lib/cfg-parser.h @@ -74,7 +74,8 @@ typedef enum _CfgYesNoAuto gboolean cfg_process_flag(CfgFlagHandler *handlers, gpointer base, const gchar *flag); gboolean cfg_process_yesno(const gchar *yesno); - +gboolean cfg_process_list_of_literals(const gchar *input, GList **result); +gboolean cfg_is_literal_in_list_of_literals(GList *list, const gchar *literal); extern CfgParser main_parser; diff --git a/modules/appmodel/app-object-generator.c b/modules/appmodel/app-object-generator.c index 9393e37e7d..96f4bef195 100644 --- a/modules/appmodel/app-object-generator.c +++ b/modules/appmodel/app-object-generator.c @@ -33,7 +33,7 @@ app_object_generator_is_application_included(AppObjectGenerator *self, const gch /* include everything if we don't have the option */ if (!self->included_apps) return TRUE; - return strstr(self->included_apps, app_name) != NULL; + return cfg_is_literal_in_list_of_literals(self->included_apps, app_name); } gboolean @@ -41,7 +41,7 @@ app_object_generator_is_application_excluded(AppObjectGenerator *self, const gch { if (!self->excluded_apps) return FALSE; - return strstr(self->excluded_apps, app_name) != NULL; + return cfg_is_literal_in_list_of_literals(self->excluded_apps, app_name); } static gboolean @@ -62,8 +62,7 @@ _parse_auto_parse_exclude_arg(AppObjectGenerator *self, CfgArgs *args, const gch const gchar *v = cfg_args_get(args, "auto-parse-exclude"); if (!v) return TRUE; - self->excluded_apps = g_strdup(v); - return TRUE; + return cfg_process_list_of_literals(v, &self->excluded_apps); } static gboolean @@ -72,8 +71,7 @@ _parse_auto_parse_include_arg(AppObjectGenerator *self, CfgArgs *args, const gch const gchar *v = cfg_args_get(args, "auto-parse-include"); if (!v) return TRUE; - self->included_apps = g_strdup(v); - return TRUE; + return cfg_process_list_of_literals(v, &self->included_apps); } gboolean @@ -104,10 +102,21 @@ _generate(CfgBlockGenerator *s, GlobalConfig *cfg, gpointer args, GString *resul return TRUE; } +void +app_object_generator_free_method(CfgBlockGenerator *s) +{ + AppObjectGenerator *self = (AppObjectGenerator *) s; + + g_list_free_full(self->included_apps, g_free); + g_list_free_full(self->excluded_apps, g_free); + cfg_block_generator_free_method(s); +} + void app_object_generator_init_instance(AppObjectGenerator *self, gint context, const gchar *name) { cfg_block_generator_init_instance(&self->super, context, name); self->super.generate = _generate; self->parse_arguments = app_object_generator_parse_arguments_method; + self->super.free_fn = app_object_generator_free_method; } diff --git a/modules/appmodel/app-object-generator.h b/modules/appmodel/app-object-generator.h index 330db1344e..6e5c88ceb4 100644 --- a/modules/appmodel/app-object-generator.h +++ b/modules/appmodel/app-object-generator.h @@ -34,8 +34,8 @@ struct _AppObjectGenerator CfgBlockGenerator super; gboolean (*parse_arguments)(AppObjectGenerator *self, CfgArgs *args, const gchar *reference); void (*generate_config)(AppObjectGenerator *self, GlobalConfig *cfg, GString *result); - const gchar *included_apps; - const gchar *excluded_apps; + GList *included_apps; + GList *excluded_apps; gboolean is_parsing_enabled; }; @@ -44,6 +44,7 @@ gboolean app_object_generator_is_application_excluded(AppObjectGenerator *self, gboolean app_object_generator_parse_arguments_method(AppObjectGenerator *self, CfgArgs *args, const gchar *reference); void app_object_generator_init_instance(AppObjectGenerator *self, gint context, const gchar *name); +void app_object_generator_free_method(CfgBlockGenerator *s); #endif diff --git a/modules/appmodel/app-transform-generator.c b/modules/appmodel/app-transform-generator.c index b806013e7b..04f7e0ea35 100644 --- a/modules/appmodel/app-transform-generator.c +++ b/modules/appmodel/app-transform-generator.c @@ -30,6 +30,8 @@ typedef struct _AppTransformGenerator AppObjectGenerator super; const gchar *flavour; const gchar *filterx_app_variable; + GList *included_transforms; + GList *excluded_transforms; GString *block; } AppTransformGenerator; @@ -55,6 +57,24 @@ _parse_filterx_app_variable(AppTransformGenerator *self, CfgArgs *args, const gc return TRUE; } +static gboolean +_parse_include_transforms_arg(AppTransformGenerator *self, CfgArgs *args, const gchar *reference) +{ + const gchar *v = cfg_args_get(args, "include-transforms"); + if (!v) + return TRUE; + return cfg_process_list_of_literals(v, &self->included_transforms); +} + +static gboolean +_parse_exclude_transforms_arg(AppTransformGenerator *self, CfgArgs *args, const gchar *reference) +{ + const gchar *v = cfg_args_get(args, "exclude-transforms"); + if (!v) + return TRUE; + return cfg_process_list_of_literals(v, &self->excluded_transforms); +} + static gboolean app_transform_generator_parse_arguments(AppObjectGenerator *s, CfgArgs *args, const gchar *reference) { @@ -67,6 +87,12 @@ app_transform_generator_parse_arguments(AppObjectGenerator *s, CfgArgs *args, co if (!_parse_filterx_app_variable(self, args, reference)) return FALSE; + if (!_parse_include_transforms_arg(self, args, reference)) + return FALSE; + + if (!_parse_exclude_transforms_arg(self, args, reference)) + return FALSE; + if (!app_object_generator_parse_arguments_method(&self->super, args, reference)) return FALSE; @@ -78,12 +104,28 @@ _generate_steps(AppTransformGenerator *self, GList *steps) { for (GList *l = steps; l; l = l->next) { - TransformationStep *step = l->data; + TransformStep *step = l->data; g_string_append_printf(self->block, " # step: %s", step->name); g_string_append_printf(self->block, " %s\n", step->expr); } } +static gboolean +_is_transform_included(AppTransformGenerator *self, const gchar *name) +{ + if (!self->included_transforms) + return TRUE; + return cfg_is_literal_in_list_of_literals(self->included_transforms, name); +} + +static gboolean +_is_transform_excluded(AppTransformGenerator *self, const gchar *name) +{ + if (!self->excluded_transforms) + return FALSE; + return cfg_is_literal_in_list_of_literals(self->excluded_transforms, name); +} + static void _generate_app_transform(Transformation *transformation, gpointer user_data) { @@ -101,11 +143,14 @@ _generate_app_transform(Transformation *transformation, gpointer user_data) g_string_append_printf(self->block, "\n#Start Application %s\n", transformation->super.name); g_string_append_printf(self->block, " if (%s == '%s') {\n", self->filterx_app_variable, transformation->super.name); - for (GList *l = transformation->blocks; l; l = l->next) + for (GList *l = transformation->transforms; l; l = l->next) { - TransformationBlock *block = l->data; + Transform *transform = l->data; - _generate_steps(self, block->steps); + if (!_is_transform_included(self, transform->name) || _is_transform_excluded(self, transform->name)) + continue; + + _generate_steps(self, transform->steps); } g_string_append(self->block, " };\n"); g_string_append_printf(self->block, "\n#End Application %s\n", transformation->super.name); @@ -127,6 +172,16 @@ app_transform_generate_config(AppObjectGenerator *s, GlobalConfig *cfg, GString self->block = NULL; } +static void +_free(CfgBlockGenerator *s) +{ + AppTransformGenerator *self = (AppTransformGenerator *) s; + + g_list_free_full(self->included_transforms, g_free); + g_list_free_full(self->excluded_transforms, g_free); + app_object_generator_free_method(s); +} + CfgBlockGenerator * app_transform_generator_new(gint context, const gchar *name) { @@ -135,5 +190,6 @@ app_transform_generator_new(gint context, const gchar *name) app_object_generator_init_instance(&self->super, context, name); self->super.parse_arguments = app_transform_generator_parse_arguments; self->super.generate_config = app_transform_generate_config; + self->super.super.free_fn = _free; return &self->super.super; } diff --git a/modules/appmodel/appmodel-grammar.ym b/modules/appmodel/appmodel-grammar.ym index 78d2600e69..8764a2a1e0 100644 --- a/modules/appmodel/appmodel-grammar.ym +++ b/modules/appmodel/appmodel-grammar.ym @@ -118,21 +118,21 @@ transformation_options /* $0 is Transformation */ transformation_option - : KW_TRANSFORM '[' string ']' '{' { $$ = transformation_block_new($3); } transformation_steps '}' - { free($3); transformation_add_block($0, $6); } + : KW_TRANSFORM '[' string ']' '{' { $$ = transform_new($3); } transform_steps '}' + { free($3); transformation_add_transform($0, $6); } ; -/* $0 is TransformationBlock */ -transformation_steps - : transformation_step semicolons { $$ = $0; } transformation_steps +/* $0 is Transform */ +transform_steps + : transform_step semicolons { $$ = $0; } transform_steps | ; -/* $0 is TransformationBlock */ -transformation_step +/* $0 is Transform */ +transform_step : KW_STEP '[' string ']' _block_content_context_push LL_BLOCK _block_content_context_pop { - transformation_block_add_step($0, $3, $6); free($3); free($6); + transform_add_step($0, $3, $6); free($3); free($6); } ; diff --git a/modules/appmodel/transformation.c b/modules/appmodel/transformation.c index d11119f776..516fcfaaec 100644 --- a/modules/appmodel/transformation.c +++ b/modules/appmodel/transformation.c @@ -22,56 +22,55 @@ #include "transformation.h" -/* TransformationStep: a named filterx expression */ +/* TransformStep: a named filterx block */ -TransformationStep * -transformation_step_new(const gchar *name, const gchar *expr) +TransformStep * +transform_step_new(const gchar *name, const gchar *expr) { - TransformationStep *self = g_new0(TransformationStep, 1); + TransformStep *self = g_new0(TransformStep, 1); self->name = g_strdup(name); self->expr = g_strdup(expr); return self; } void -transformation_step_free(TransformationStep *self) +transform_step_free(TransformStep *self) { g_free(self->name); g_free(self->expr); g_free(self); } -/* TransformationBlock: named list of steps */ +/* Transform: named list of TransformSteps */ void -transformation_block_add_step(TransformationBlock *self, const gchar *name, const gchar *expr) +transform_add_step(Transform *self, const gchar *name, const gchar *expr) { - self->steps = g_list_append(self->steps, transformation_step_new(name, expr)); + self->steps = g_list_append(self->steps, transform_step_new(name, expr)); } -TransformationBlock * -transformation_block_new(const gchar *name) +Transform * +transform_new(const gchar *name) { - TransformationBlock *self = g_new0(TransformationBlock, 1); + Transform *self = g_new0(Transform, 1); self->name = g_strdup(name); return self; } void -transformation_block_free(TransformationBlock *self) +transform_free(Transform *self) { g_free(self->name); - g_list_free_full(self->steps, (GDestroyNotify) transformation_step_free); + g_list_free_full(self->steps, (GDestroyNotify) transform_step_free); g_free(self); } -/* Transformation */ -/* list of blocks */ +/* Transformation: list of Transforms corresponding to an app (with optional flavour) */ void -transformation_add_block(Transformation *self, TransformationBlock *block) +transformation_add_transform(Transformation *self, Transform *transform) { - self->blocks = g_list_append(self->blocks, block); + self->transforms = g_list_append(self->transforms, transform); } static void @@ -79,7 +78,7 @@ transformation_free(AppModelObject *s) { Transformation *self = (Transformation *) s; - g_list_free_full(self->blocks, (GDestroyNotify) transformation_block_free); + g_list_free_full(self->transforms, (GDestroyNotify) transform_free); } Transformation * diff --git a/modules/appmodel/transformation.h b/modules/appmodel/transformation.h index 07aa31cbda..bc1240d4b1 100644 --- a/modules/appmodel/transformation.h +++ b/modules/appmodel/transformation.h @@ -27,33 +27,33 @@ #define TRANSFORMATION_TYPE_NAME "transformation" -typedef struct _TransformationStep +typedef struct _TransformStep { gchar *name; gchar *expr; -} TransformationStep; +} TransformStep; -TransformationStep *transformation_step_new(const gchar *name, const gchar *expr); -void transformation_step_free(TransformationStep *self); +TransformStep *transform_step_new(const gchar *name, const gchar *expr); +void transform_step_free(TransformStep *self); -typedef struct _TransformationBlock +typedef struct _Transform { gchar *name; GList *steps; -} TransformationBlock; +} Transform; -void transformation_block_add_step(TransformationBlock *self, const gchar *name, const gchar *step); -TransformationBlock *transformation_block_new(const gchar *name); -void transformation_block_free(TransformationBlock *self); +void transform_add_step(Transform *self, const gchar *name, const gchar *step); +Transform *transform_new(const gchar *name); +void transform_free(Transform *self); typedef struct _Transformation { AppModelObject super; - GList *blocks; + GList *transforms; } Transformation; -void transformation_add_block(Transformation *self, TransformationBlock *block); +void transformation_add_transform(Transformation *self, Transform *transform); Transformation *transformation_new(const gchar *app, const gchar *name); #endif diff --git a/modules/confgen/confgen-plugin.c b/modules/confgen/confgen-plugin.c index f439c40a5e..5e3246ca71 100644 --- a/modules/confgen/confgen-plugin.c +++ b/modules/confgen/confgen-plugin.c @@ -129,7 +129,7 @@ confgen_exec_free(CfgBlockGenerator *s) ConfgenExec *self = (ConfgenExec *) s; g_free(self->exec); - cfg_block_generator_free_instance(s); + cfg_block_generator_free_method(s); } static CfgBlockGenerator * diff --git a/modules/python/python-confgen.c b/modules/python/python-confgen.c index 812264d1da..fc41127f53 100644 --- a/modules/python/python-confgen.c +++ b/modules/python/python-confgen.c @@ -78,7 +78,7 @@ python_config_generator_free(CfgBlockGenerator *s) gstate = PyGILState_Ensure(); Py_XDECREF(self->py_generator_function); PyGILState_Release(gstate); - cfg_block_generator_free_instance(s); + cfg_block_generator_free_method(s); } CfgBlockGenerator *