#include "bindings_file.h" #include "binding.h" #include #include #include #include #include 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); }