diff options
Diffstat (limited to 'src/bindings_file.c')
-rw-r--r-- | src/bindings_file.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/bindings_file.c b/src/bindings_file.c new file mode 100644 index 0000000..4eab11f --- /dev/null +++ b/src/bindings_file.c @@ -0,0 +1,128 @@ +#include "bindings_file.h" +#include "binding.h" + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <ctype.h> +#include <string.h> + + +struct binding *bindings = NULL; +size_t nbindings = 0; + +void skip_space(char **c) +{ + for (; **c && isspace(**c); (*c)++); +} + +int read_int(char **c, int out[static 1]) +{ + if (!isdigit(**c)) + { + return -1; + } + errno = 0; + char *end = NULL; + *out = strtol(*c, &end, 10); + if (errno) + { + return -1; + } + *c = end; + return 0; +} + +void parse_bindings_file(const char path[static 1]) +{ + size_t cap = 512; + bindings = malloc(sizeof (struct binding) * cap); + FILE *f = fopen(path, "r"); + if (f == NULL) + { + fprintf(stderr, "failed to open bindings file: %s: %s\n", path, + strerror(errno)); + exit(EXIT_FAILURE); + } + + size_t line_nb = 0; + char *line = NULL; + size_t n; + while (getline(&line, &n, f) != -1) + { + line_nb++; + struct binding binding = {0}; + char *end = strchr(line, '#'); + if (end == NULL) + { + end = line + strlen(line); + } + *end = '\0'; + char *c = line; + + skip_space(&c); + if (c == end) continue; + + /* code */ + int code; + for (;;) + { + if (read_int(&c, &code) < 0 || c >= end) + { + goto fail; + } + set_key(binding.keys, code); + if (*c++ != '+') + { + c--; + break; + } + } + + /* press | release */ + skip_space(&c); + if (strncmp(c, "press", strlen("press")) == 0) + { + c += strlen("press"); + binding.value = PRESSED; + } + else if (strncmp(c, "release", strlen("release")) == 0) + { + c += strlen("release"); + binding.value = RELEASED; + } + else + { + goto fail; + } + + /* cmd */ + skip_space(&c); + if (c >= end) + { + goto fail; + } + binding.cmd = malloc(end - c + 1); + memcpy(binding.cmd, c, end - c + 1); + + if (nbindings >= cap) + { + cap *= 2; + bindings = realloc(bindings, cap * sizeof (struct binding)); + } + bindings[nbindings++] = binding; + } + if (!feof(f)) + { + fprintf(stderr, "failed to read bindings file: %s: %s\n", path, + strerror(errno)); + } + free(line); + fclose(f); + return; + +fail: + fprintf(stderr, "syntax error at line %ld\n", line_nb); + exit(EXIT_FAILURE); +} + |