Compare commits
4 Commits
50a6f1a716
...
85282bed0e
Author | SHA1 | Date |
---|---|---|
Vftdan | 85282bed0e | |
Vftdan | 174d57666b | |
Vftdan | 820480cc8a | |
Vftdan | 5946bf2bcd |
121
config.c
121
config.c
|
@ -47,7 +47,7 @@ load_nodes_section(const config_setting_t *config_section)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void
|
inline static void
|
||||||
load_channel_end_config(const config_setting_t *config_member, const char **name_ptr, size_t *index_ptr)
|
load_channel_end_config(const config_setting_t *config_member, const char **name_ptr, size_t *index_ptr, const ConstantRegistry *constants)
|
||||||
{
|
{
|
||||||
ssize_t length = config_setting_length(config_member);
|
ssize_t length = config_setting_length(config_member);
|
||||||
if (length < 1) {
|
if (length < 1) {
|
||||||
|
@ -59,15 +59,15 @@ load_channel_end_config(const config_setting_t *config_member, const char **name
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*name_ptr = config_setting_name(kv);
|
*name_ptr = config_setting_name(kv);
|
||||||
*index_ptr = config_setting_get_int64(kv);
|
*index_ptr = resolve_constant(constants, kv);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*name_ptr = config_setting_get_string_elem(config_member, 0);
|
*name_ptr = config_setting_get_string_elem(config_member, 0);
|
||||||
*index_ptr = config_setting_get_int64_elem(config_member, 1);
|
*index_ptr = resolve_constant(constants, config_setting_get_elem(config_member, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static GraphChannelConfig
|
static GraphChannelConfig
|
||||||
load_single_channel_config(const config_setting_t *config_member)
|
load_single_channel_config(const config_setting_t *config_member, const ConstantRegistry *constants)
|
||||||
{
|
{
|
||||||
GraphChannelConfig result = {
|
GraphChannelConfig result = {
|
||||||
.from = {NULL, 0},
|
.from = {NULL, 0},
|
||||||
|
@ -93,13 +93,13 @@ load_single_channel_config(const config_setting_t *config_member)
|
||||||
ends[0] = ends[1];
|
ends[0] = ends[1];
|
||||||
ends[1] = tmp;
|
ends[1] = tmp;
|
||||||
}
|
}
|
||||||
load_channel_end_config(ends[0], &result.from.name, &result.from.index);
|
load_channel_end_config(ends[0], &result.from.name, &result.from.index, constants);
|
||||||
load_channel_end_config(ends[1], &result.to.name, &result.to.index);
|
load_channel_end_config(ends[1], &result.to.name, &result.to.index, constants);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GraphChannelConfigSection
|
static GraphChannelConfigSection
|
||||||
load_channels_section(const config_setting_t *config_section)
|
load_channels_section(const config_setting_t *config_section, const ConstantRegistry *constants)
|
||||||
{
|
{
|
||||||
GraphChannelConfigSection result = {
|
GraphChannelConfigSection result = {
|
||||||
.length = 0,
|
.length = 0,
|
||||||
|
@ -117,7 +117,7 @@ load_channels_section(const config_setting_t *config_section)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
for (ssize_t i = 0; i < length; ++i) {
|
for (ssize_t i = 0; i < length; ++i) {
|
||||||
result.items[i] = load_single_channel_config(config_setting_get_elem(config_section, i));
|
result.items[i] = load_single_channel_config(config_setting_get_elem(config_section, i), constants);
|
||||||
}
|
}
|
||||||
result.length = length;
|
result.length = length;
|
||||||
return result;
|
return result;
|
||||||
|
@ -126,6 +126,9 @@ load_channels_section(const config_setting_t *config_section)
|
||||||
static void
|
static void
|
||||||
load_constants_section(const config_setting_t *config_section, ConstantRegistry *constants)
|
load_constants_section(const config_setting_t *config_section, ConstantRegistry *constants)
|
||||||
{
|
{
|
||||||
|
if (!config_section) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
ssize_t length = config_setting_length(config_section);
|
ssize_t length = config_setting_length(config_section);
|
||||||
if (length <= 0) {
|
if (length <= 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -156,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
|
bool
|
||||||
load_config(const config_setting_t *config_root, FullConfig *config)
|
load_config(const config_setting_t *config_root, FullConfig *config)
|
||||||
{
|
{
|
||||||
|
@ -165,10 +253,12 @@ 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 *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 *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 *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);
|
hash_table_init(&config->constants, NULL);
|
||||||
load_constants_section(constants_config, &config->constants);
|
load_constants_section(constants_config, &config->constants);
|
||||||
|
load_enums_section(enums_config, &config->constants);
|
||||||
config->nodes = load_nodes_section(node_config);
|
config->nodes = load_nodes_section(node_config);
|
||||||
config->channels = load_channels_section(channel_config);
|
config->channels = load_channels_section(channel_config, &config->constants);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,21 +282,24 @@ reset_config(FullConfig *config)
|
||||||
}
|
}
|
||||||
|
|
||||||
long long
|
long long
|
||||||
resolve_constant(const ConstantRegistry * registry, const config_setting_t * setting)
|
resolve_constant_or(const ConstantRegistry * registry, const config_setting_t * setting, long long dflt)
|
||||||
{
|
{
|
||||||
if (!setting) {
|
if (!setting) {
|
||||||
return 0;
|
return dflt;
|
||||||
}
|
}
|
||||||
if (config_setting_type(setting) == CONFIG_TYPE_STRING) {
|
if (config_setting_type(setting) == CONFIG_TYPE_STRING) {
|
||||||
if (!registry) {
|
if (!registry) {
|
||||||
return 1;
|
return dflt;
|
||||||
}
|
}
|
||||||
const char *name = config_setting_get_string(setting);
|
const char *name = config_setting_get_string(setting);
|
||||||
HashTableIndex idx = hash_table_find(registry, hash_table_key_from_cstr(name));
|
HashTableIndex idx = hash_table_find(registry, hash_table_key_from_cstr(name));
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
return 0;
|
return dflt;
|
||||||
}
|
}
|
||||||
return registry->value_array[idx];
|
return registry->value_array[idx];
|
||||||
}
|
}
|
||||||
return config_setting_get_int64(setting);
|
if (config_setting_is_number(setting)) {
|
||||||
|
return config_setting_get_int64(setting);
|
||||||
|
}
|
||||||
|
return dflt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
constants = {
|
enums = {
|
||||||
ns_stdin = 0;
|
namespaces: ["stdin", "clickpad"];
|
||||||
ns_clickpad = 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
nodes = {
|
nodes = {
|
||||||
stdin = {
|
stdin = {
|
||||||
type = "getchar";
|
type = "getchar";
|
||||||
options = {
|
options = {
|
||||||
namespace = "ns_stdin";
|
namespace = "namespaces.stdin";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
print = {
|
print = {
|
||||||
|
@ -18,7 +17,7 @@ nodes = {
|
||||||
type = "evdev";
|
type = "evdev";
|
||||||
options = {
|
options = {
|
||||||
file = "/dev/input/event7";
|
file = "/dev/input/event7";
|
||||||
namespace = "ns_clickpad";
|
namespace = "namespaces.clickpad";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
8
config.h
8
config.h
|
@ -38,6 +38,12 @@ typedef struct {
|
||||||
|
|
||||||
bool load_config(const config_setting_t *config_root, FullConfig *config);
|
bool load_config(const config_setting_t *config_root, FullConfig *config);
|
||||||
void reset_config(FullConfig *config);
|
void reset_config(FullConfig *config);
|
||||||
long long resolve_constant(const ConstantRegistry * registry, const config_setting_t * setting);
|
long long resolve_constant_or(const ConstantRegistry * registry, const config_setting_t * setting, long long dflt);
|
||||||
|
|
||||||
|
__attribute__((unused)) inline static long long
|
||||||
|
resolve_constant(const ConstantRegistry * registry, const config_setting_t * setting)
|
||||||
|
{
|
||||||
|
return resolve_constant_or(registry, setting, 0);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* end of include guard: CONFIG_H_ */
|
#endif /* end of include guard: CONFIG_H_ */
|
||||||
|
|
Loading…
Reference in New Issue