Compare commits
3 Commits
1704817009
...
011772a24a
Author | SHA1 | Date |
---|---|---|
Vftdan | 011772a24a | |
Vftdan | 23a0fa002f | |
Vftdan | 39ea42018f |
2
Makefile
2
Makefile
|
@ -12,7 +12,7 @@ CPPFLAGS += $(shell pkg-config --cflags $(DEPS))
|
|||
LDLIBS += $(shell pkg-config --libs $(DEPS))
|
||||
INTERP ?=
|
||||
MAIN = main
|
||||
OBJS = main.o events.o processing.o graph.o config.o event_code_names.o hash_table.o module_registry.o nodes/getchar.o nodes/print.o nodes/evdev.o nodes/tee.o
|
||||
OBJS = main.o events.o processing.o graph.o config.o event_code_names.o hash_table.o module_registry.o event_predicate.o nodes/getchar.o nodes/print.o nodes/evdev.o nodes/tee.o
|
||||
|
||||
all: $(MAIN)
|
||||
|
||||
|
|
144
config.c
144
config.c
|
@ -245,6 +245,126 @@ load_enums_section(const config_setting_t *config_section, ConstantRegistry *con
|
|||
}
|
||||
}
|
||||
|
||||
static EventPredicateType
|
||||
parse_event_predicate_type(const char *name)
|
||||
{
|
||||
if (!name) {
|
||||
return EVPRED_INVALID;
|
||||
}
|
||||
if (strcmp(name, "accept") == 0) {
|
||||
return EVPRED_ACCEPT;
|
||||
}
|
||||
if (strcmp(name, "code_ns") == 0) {
|
||||
return EVPRED_CODE_NS;
|
||||
}
|
||||
if (strcmp(name, "code_major") == 0) {
|
||||
return EVPRED_CODE_MAJOR;
|
||||
}
|
||||
if (strcmp(name, "code_minor") == 0) {
|
||||
return EVPRED_CODE_MINOR;
|
||||
}
|
||||
if (strcmp(name, "payload") == 0) {
|
||||
return EVPRED_PAYLOAD;
|
||||
}
|
||||
if (strcmp(name, "conjunction") == 0 || strcmp(name, "and") == 0) {
|
||||
return EVPRED_CONJUNCTION;
|
||||
}
|
||||
if (strcmp(name, "disjunction") == 0 || strcmp(name, "or") == 0) {
|
||||
return EVPRED_DISJUNCTION;
|
||||
}
|
||||
return EVPRED_INVALID;
|
||||
}
|
||||
|
||||
static EventPredicateHandle
|
||||
load_single_predicate(const config_setting_t * setting, EventPredicateHandleRegistry * registry, const ConstantRegistry * constants)
|
||||
{
|
||||
const char *name = NULL;
|
||||
const char *type_name = NULL;
|
||||
config_setting_lookup_string(setting, "name", &name);
|
||||
config_setting_lookup_string(setting, "type", &type_name);
|
||||
if (!type_name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
EventPredicate predicate;
|
||||
EventPredicateType type = parse_event_predicate_type(type_name);
|
||||
predicate.type = type;
|
||||
|
||||
switch (type) {
|
||||
case EVPRED_INVALID:
|
||||
return -1;
|
||||
case EVPRED_ACCEPT:
|
||||
break;
|
||||
case EVPRED_CODE_NS...EVPRED_PAYLOAD:
|
||||
{
|
||||
int64_t min_value = INT64_MIN;
|
||||
int64_t max_value = INT64_MAX;
|
||||
min_value = resolve_constant_or(constants, config_setting_get_member(setting, "min"), min_value);
|
||||
max_value = resolve_constant_or(constants, config_setting_get_member(setting, "max"), max_value);
|
||||
predicate.range_data.min_value = min_value;
|
||||
predicate.range_data.max_value = max_value;
|
||||
}
|
||||
break;
|
||||
case EVPRED_CONJUNCTION:
|
||||
case EVPRED_DISJUNCTION:
|
||||
{
|
||||
config_setting_t *args = config_setting_get_member(setting, "args");
|
||||
EventPredicateHandle *handles = NULL;
|
||||
ssize_t length = config_setting_length(args);
|
||||
if (length > 0) {
|
||||
handles = T_ALLOC(length, EventPredicateHandle);
|
||||
for (ssize_t i = 0; i < length; ++i) {
|
||||
handles[i] = resolve_event_predicate(registry, constants, config_setting_get_elem(args, i));
|
||||
}
|
||||
}
|
||||
predicate.aggregate_data.length = length;
|
||||
predicate.aggregate_data.handles = handles;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
long long enabled = resolve_constant_or(constants, config_setting_get_member(setting, "enabled"), true);
|
||||
long long inverted = resolve_constant_or(constants, config_setting_get_member(setting, "inverted"), false);
|
||||
predicate.enabled = enabled != 0;
|
||||
predicate.inverted = inverted != 0;
|
||||
|
||||
EventPredicateHandle handle = event_predicate_register(predicate);
|
||||
if (handle < 0) {
|
||||
if ((predicate.type == EVPRED_CONJUNCTION || predicate.type == EVPRED_DISJUNCTION) && predicate.aggregate_data.handles) {
|
||||
free(predicate.aggregate_data.handles);
|
||||
predicate.aggregate_data.handles = NULL;
|
||||
predicate.aggregate_data.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
static void
|
||||
load_predicates_section(const config_setting_t *config_section, EventPredicateHandleRegistry *predicates, const 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 *predicate_def = config_setting_get_elem(config_section, i);
|
||||
if (!predicate_def) {
|
||||
continue;
|
||||
}
|
||||
const char *name = config_setting_name(predicate_def);
|
||||
EventPredicateHandle handle = resolve_event_predicate(predicates, constants, predicate_def);
|
||||
if (handle >= 0 && name != NULL) {
|
||||
hash_table_insert(predicates, hash_table_key_from_cstr(name), &handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
load_config(const config_setting_t *config_root, FullConfig *config)
|
||||
{
|
||||
|
@ -255,10 +375,13 @@ load_config(const config_setting_t *config_root, FullConfig *config)
|
|||
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");
|
||||
const config_setting_t *predicates_config = config_setting_get_member(config_root, "predicates");
|
||||
hash_table_init(&config->constants, NULL);
|
||||
populate_event_codes(&config->constants);
|
||||
load_constants_section(constants_config, &config->constants);
|
||||
load_enums_section(enums_config, &config->constants);
|
||||
hash_table_init(&config->predicates, NULL);
|
||||
load_predicates_section(predicates_config, &config->predicates, &config->constants);
|
||||
config->nodes = load_nodes_section(node_config);
|
||||
config->channels = load_channels_section(channel_config, &config->constants);
|
||||
return true;
|
||||
|
@ -281,6 +404,7 @@ reset_config(FullConfig *config)
|
|||
config->channels.length = 0;
|
||||
}
|
||||
hash_table_deinit(&config->constants);
|
||||
hash_table_deinit(&config->predicates);
|
||||
}
|
||||
|
||||
long long
|
||||
|
@ -305,3 +429,23 @@ resolve_constant_or(const ConstantRegistry * registry, const config_setting_t *
|
|||
}
|
||||
return dflt;
|
||||
}
|
||||
|
||||
EventPredicateHandle
|
||||
resolve_event_predicate(EventPredicateHandleRegistry * registry, const ConstantRegistry * constants, const config_setting_t * setting)
|
||||
{
|
||||
if (!setting) {
|
||||
return -1;
|
||||
}
|
||||
if (config_setting_type(setting) == CONFIG_TYPE_STRING) {
|
||||
if (!registry) {
|
||||
return -1;
|
||||
}
|
||||
const char *name = config_setting_get_string(setting);
|
||||
HashTableIndex idx = hash_table_find(registry, hash_table_key_from_cstr(name));
|
||||
if (idx < 0) {
|
||||
return -1;
|
||||
}
|
||||
return registry->value_array[idx];
|
||||
}
|
||||
return load_single_predicate(setting, registry, constants);
|
||||
}
|
||||
|
|
19
config.cfg
19
config.cfg
|
@ -2,6 +2,25 @@ enums = {
|
|||
namespaces: ["stdin", "clickpad"];
|
||||
};
|
||||
|
||||
predicates = {
|
||||
is_evdev = {
|
||||
type = "code_ns";
|
||||
min = "namespaces.clickpad";
|
||||
max = "namespaces.clickpad";
|
||||
};
|
||||
key_event = {
|
||||
type = "and";
|
||||
args = (
|
||||
"is_evdev",
|
||||
{
|
||||
type = "code_major";
|
||||
min = "event_type.KEY";
|
||||
max = "event_type.KEY";
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
nodes = {
|
||||
stdin = {
|
||||
type = "getchar";
|
||||
|
|
4
config.h
4
config.h
|
@ -4,6 +4,7 @@
|
|||
#include <libconfig.h>
|
||||
#include "defs.h"
|
||||
#include "hash_table.h"
|
||||
#include "event_predicate.h"
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
|
@ -29,16 +30,19 @@ typedef struct {
|
|||
} GraphChannelConfigSection;
|
||||
|
||||
typedef TYPED_HASH_TABLE(long long) ConstantRegistry;
|
||||
typedef TYPED_HASH_TABLE(EventPredicateHandle) EventPredicateHandleRegistry;
|
||||
|
||||
typedef struct {
|
||||
GraphNodeConfigSection nodes;
|
||||
GraphChannelConfigSection channels;
|
||||
ConstantRegistry constants;
|
||||
EventPredicateHandleRegistry predicates;
|
||||
} FullConfig;
|
||||
|
||||
bool load_config(const config_setting_t *config_root, FullConfig *config);
|
||||
void reset_config(FullConfig *config);
|
||||
long long resolve_constant_or(const ConstantRegistry * registry, const config_setting_t * setting, long long dflt);
|
||||
EventPredicateHandle resolve_event_predicate(EventPredicateHandleRegistry * registry, const ConstantRegistry * constants, const config_setting_t * setting);
|
||||
|
||||
__attribute__((unused)) inline static long long
|
||||
resolve_constant(const ConstantRegistry * registry, const config_setting_t * setting)
|
||||
|
|
|
@ -38,6 +38,14 @@ static void
|
|||
event_predicate_list_clear(EventPredicateList * lst)
|
||||
{
|
||||
if (lst->values) {
|
||||
for (size_t i = 0; i < lst->length; ++i) {
|
||||
EventPredicateType type = lst->values[i].type;
|
||||
if (type == EVPRED_CONJUNCTION || type == EVPRED_DISJUNCTION) {
|
||||
if (lst->values[i].aggregate_data.handles) {
|
||||
free(lst->values[i].aggregate_data.handles);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(lst->values);
|
||||
lst->values = NULL;
|
||||
}
|
||||
|
@ -46,16 +54,16 @@ event_predicate_list_clear(EventPredicateList * lst)
|
|||
}
|
||||
|
||||
EventPredicateHandle
|
||||
event_predicate_register(EventPredicate filter)
|
||||
event_predicate_register(EventPredicate predicate)
|
||||
{
|
||||
size_t i = predicates.length;
|
||||
if (i >= INT32_MAX) {
|
||||
return -1;
|
||||
}
|
||||
while (i <= predicates.capacity) {
|
||||
while (i >= predicates.capacity) {
|
||||
event_predicate_list_extend(&predicates);
|
||||
}
|
||||
predicates.values[i] = filter;
|
||||
predicates.values[i] = predicate;
|
||||
predicates.length = i + 1;
|
||||
return (EventPredicateHandle) i;
|
||||
}
|
||||
|
@ -157,6 +165,8 @@ event_predicate_apply(EventPredicateHandle handle, EventNode * event)
|
|||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return EVPREDRES_DISABLED;
|
||||
}
|
||||
if (ptr->inverted) {
|
||||
accepted = !accepted;
|
||||
|
|
|
@ -41,7 +41,7 @@ struct event_predicate {
|
|||
};
|
||||
};
|
||||
|
||||
EventPredicateHandle event_predicate_register(EventPredicate filter);
|
||||
EventPredicateHandle event_predicate_register(EventPredicate predicate);
|
||||
EventPredicate event_predicate_get(EventPredicateHandle handle);
|
||||
EventPredicateResult event_predicate_apply(EventPredicateHandle handle, EventNode * event);
|
||||
void event_predicate_set_enabled(EventPredicateHandle handle, bool enabled);
|
||||
|
|
Loading…
Reference in New Issue