17 extern int yylex(void);
22 void yyerror(const char *str) {
23 fprintf(stderr,"error: %s\n",str);
30 void parse_file(const char *f) {
31 SLIST_HEAD(variables_head, Variable) variables = SLIST_HEAD_INITIALIZER(&variables);
32 int fd, ret, read_bytes = 0;
36 char buffer[1026], key[512], value[512];
38 if ((fd = open(f, O_RDONLY)) == -1)
39 die("Could not open configuration file: %s\n", strerror(errno));
41 if (fstat(fd, &stbuf) == -1)
42 die("Could not fstat file: %s\n", strerror(errno));
44 buf = smalloc(stbuf.st_size * sizeof(char));
45 while (read_bytes < stbuf.st_size) {
46 if ((ret = read(fd, buf + read_bytes, (stbuf.st_size - read_bytes))) < 0)
47 die("Could not read(): %s\n", strerror(errno));
51 if (lseek(fd, 0, SEEK_SET) == (off_t)-1)
52 die("Could not lseek: %s\n", strerror(errno));
54 if ((fstr = fdopen(fd, "r")) == NULL)
55 die("Could not fdopen: %s\n", strerror(errno));
58 if (fgets(buffer, 1024, fstr) == NULL) {
61 die("Could not read configuration file\n");
64 /* sscanf implicitly strips whitespace. Also, we skip comments and empty lines. */
65 if (sscanf(buffer, "%s %[^\n]", key, value) < 1 ||
66 key[0] == '#' || strlen(key) < 3)
69 if (strcasecmp(key, "set") == 0) {
71 die("Malformed variable assignment, name has to start with $\n");
73 /* get key/value for this variable */
74 char *v_key = value, *v_value;
75 if ((v_value = strstr(value, " ")) == NULL)
76 die("Malformed variable assignment, need a value\n");
80 struct Variable *new = scalloc(sizeof(struct Variable));
81 new->key = sstrdup(v_key);
82 new->value = sstrdup(v_value);
83 SLIST_INSERT_HEAD(&variables, new, variables);
84 LOG("Got new variable %s = %s\n", v_key, v_value);
89 /* For every custom variable, see how often it occurs in the file and
90 * how much extra bytes it requires when replaced. */
91 struct Variable *current, *nearest;
93 SLIST_FOREACH(current, &variables, variables) {
94 int extra = (strlen(current->value) - strlen(current->key));
97 (next = strcasestr(buf + (next - buf), current->key)) != NULL;
98 next += strlen(current->key))
102 /* Then, allocate a new buffer and copy the file over to the new one,
103 * but replace occurences of our variables */
104 char *walk = buf, *destwalk;
105 char *new = smalloc((stbuf.st_size + extra_bytes) * sizeof(char));
107 while (walk < (buf + stbuf.st_size)) {
108 /* Find the next variable */
109 SLIST_FOREACH(current, &variables, variables)
110 current->next_match = strcasestr(walk, current->key);
112 int distance = stbuf.st_size;
113 SLIST_FOREACH(current, &variables, variables) {
114 if (current->next_match == NULL)
116 if ((current->next_match - walk) < distance) {
117 distance = (current->next_match - walk);
121 if (nearest == NULL) {
122 /* If there are no more variables, we just copy the rest */
123 strncpy(destwalk, walk, (buf + stbuf.st_size) - walk);
124 destwalk += (buf + stbuf.st_size) - walk;
128 /* Copy until the next variable, then copy its value */
129 strncpy(destwalk, walk, distance);
130 strncpy(destwalk + distance, nearest->value, strlen(nearest->value));
131 walk += distance + strlen(nearest->key);
132 destwalk += distance + strlen(nearest->value);
138 if (yyparse() != 0) {
139 fprintf(stderr, "Could not parse configfile\n");
152 struct Colortriple *color;
155 %token <number>NUMBER
158 %token <string>STR_NG
169 %token TOKFLOATING_MODIFIER
183 | lines WHITESPACE line
210 TOKBIND WHITESPACE binding_modifiers NUMBER WHITESPACE command
212 printf("\tFound binding mod%d with key %d and command %s\n", $<number>3, $4, $<string>6);
217 TOKBINDSYM WHITESPACE binding_modifiers WORD WHITESPACE command
219 printf("\tFound symbolic mod%d with key %s and command %s\n", $<number>3, $4, $<string>6);
224 TOKFLOATING_MODIFIER WHITESPACE binding_modifiers
226 printf("\tfloating modifier %d\n", $<number>3);
231 TOKWORKSPACE WHITESPACE NUMBER WHITESPACE TOKSCREEN WHITESPACE screen
233 printf("\t workspace %d to screen %s\n", $<number>3, $<string>7);
235 | TOKWORKSPACE WHITESPACE NUMBER WHITESPACE TOKSCREEN WHITESPACE screen WHITESPACE workspace_name
237 printf("\t quoted: %s\n", $<string>9);
247 NUMBER { asprintf(&$<string>$, "%d", $<number>1); }
248 | NUMBER 'x' { asprintf(&$<string>$, "%d", $<number>1); }
249 | NUMBER 'x' NUMBER { asprintf(&$<string>$, "%dx%d", $<number>1, $<number>3); }
250 | 'x' NUMBER { asprintf(&$<string>$, "x%d", $<number>2); }
254 TOKASSIGN WHITESPACE window_class WHITESPACE optional_arrow NUMBER
256 printf("assignment of %s to %d\n", $<string>3, $<number>6);
267 | TOKARROW WHITESPACE
271 TOKIPCSOCKET WHITESPACE STR
273 printf("ipc %s\n", $<string>3);
278 TOKEXEC WHITESPACE STR
280 printf("exec %s\n", $<string>3);
285 TOKTERMINAL WHITESPACE STR
287 printf("terminal %s\n", $<string>3);
292 TOKFONT WHITESPACE STR
294 printf("font %s\n", $<string>3);
300 TOKCOLOR WHITESPACE '#' HEX WHITESPACE '#' HEX WHITESPACE '#' HEX
302 printf("color %p, %s and %s and %s\n", $<color>1, $<string>4, $<string>7, $<string>10);
308 /* NULL */ { $<number>$ = 0; }
310 | binding_modifiers '+' binding_modifier { $<number>$ = $<number>1 | $<number>3; }
311 | binding_modifiers '+' { $<number>$ = $<number>1; }
315 MODIFIER { $<number>$ = $<number>1; }
316 | TOKCONTROL { $<number>$ = BIND_CONTROL; }
317 | TOKSHIFT { $<number>$ = BIND_SHIFT; }