From 85282bed0ea75ae1f18285ed279f3e137ce9794f Mon Sep 17 00:00:00 2001 From: Vftdan Date: Fri, 16 Aug 2024 11:58:19 +0200 Subject: [PATCH] Add "enums" config section --- config.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ config.cfg | 9 +++--- 2 files changed, 91 insertions(+), 5 deletions(-) diff --git a/config.c b/config.c index 7852d91..07dd2be 100644 --- a/config.c +++ b/config.c @@ -159,6 +159,91 @@ load_constants_section(const config_setting_t *config_section, ConstantRegistry } } +static void +put_enum_value(ConstantRegistry *registry, const char *enum_name, const char *member_name, const long long value) +{ + if (!enum_name || !member_name) { + return; + } + size_t enum_len = strlen(enum_name); + size_t member_len = strlen(member_name); + size_t mem_size = enum_len + /* "." */ 1 + member_len + /* terminator */ 1; + char* qualified_name = malloc(mem_size); + qualified_name[0] = '\0'; + strncat(qualified_name, enum_name, enum_len); + strncat(qualified_name, ".", 1); + strncat(qualified_name, member_name, member_len); + hash_table_insert(registry, hash_table_key_from_cstr(qualified_name), &value); + free(qualified_name); +} + +static void +load_single_enum(const char *enum_name, const config_setting_t *enum_def, ConstantRegistry *constants) +{ + ssize_t length = config_setting_length(enum_def); + if (length <= 0) { + return; + } + long long prev_value = -1; + for (ssize_t i = 0; i < length; ++i) { + config_setting_t *member = config_setting_get_elem(enum_def, i); + if (!member) { + continue; + } + + const config_setting_t *value_setting = member; + long long value = prev_value + 1; // FIXME in theory, signed overflow is UB + bool only_name = false; + + const char *name = config_setting_name(member); + if (!name) { + config_setting_lookup_string(member, "name", &name); + } + if (!name) { + name = config_setting_get_string(member); + only_name = true; + } + if (!name) { + continue; + } + + if (config_setting_is_aggregate(member)) { + value_setting = config_setting_get_member(member, "value"); + } + + if (!only_name) { + value = resolve_constant_or(constants, value_setting, value); + } + prev_value = value; + + put_enum_value(constants, enum_name, name, value); + } +} + +static void +load_enums_section(const config_setting_t *config_section, ConstantRegistry *constants) +{ + if (!config_section) { + return; + } + ssize_t length = config_setting_length(config_section); + if (length <= 0) { + return; + } + for (ssize_t i = 0; i < length; ++i) { + config_setting_t *enum_def = config_setting_get_elem(config_section, i); + if (!enum_def) { + continue; + } + const char *name = config_setting_name(enum_def); + // DEBUG_PRINT_VALUE(name, "%s"); + if (!name) { + continue; + } + load_single_enum(name, enum_def, constants); + } +} + bool load_config(const config_setting_t *config_root, FullConfig *config) { @@ -168,8 +253,10 @@ load_config(const config_setting_t *config_root, FullConfig *config) const config_setting_t *node_config = config_setting_get_member(config_root, "nodes"); const config_setting_t *channel_config = config_setting_get_member(config_root, "channels"); const config_setting_t *constants_config = config_setting_get_member(config_root, "constants"); + const config_setting_t *enums_config = config_setting_get_member(config_root, "enums"); hash_table_init(&config->constants, NULL); load_constants_section(constants_config, &config->constants); + load_enums_section(enums_config, &config->constants); config->nodes = load_nodes_section(node_config); config->channels = load_channels_section(channel_config, &config->constants); return true; diff --git a/config.cfg b/config.cfg index 3eb7e08..52f936d 100644 --- a/config.cfg +++ b/config.cfg @@ -1,13 +1,12 @@ -constants = { - ns_stdin = 0; - ns_clickpad = 1; +enums = { + namespaces: ["stdin", "clickpad"]; }; nodes = { stdin = { type = "getchar"; options = { - namespace = "ns_stdin"; + namespace = "namespaces.stdin"; }; }; print = { @@ -18,7 +17,7 @@ nodes = { type = "evdev"; options = { file = "/dev/input/event7"; - namespace = "ns_clickpad"; + namespace = "namespaces.clickpad"; }; }; };