1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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);
}
|