summaryrefslogtreecommitdiff
path: root/src/bindings_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bindings_file.c')
-rw-r--r--src/bindings_file.c128
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);
+}
+