wmcliphist: Remove trailing whitespace.
[dockapps.git] / wmcliphist / rcconfig.c
blob44dce9c7c39d77a4864bd4baa9c4ffd747d4918f
1 #include "wmcliphist.h"
2 #include <sys/stat.h>
4 #define RC_BUF_SIZE 256
6 /* automat state */
7 typedef enum {
8 STATE_BEGINING,
9 STATE_COMMENT,
10 STATE_DIRECTIVE,
11 STATE_VALUE,
12 STATE_EXPRESSION_START,
13 STATE_EXPRESSION,
14 STATE_EXPRESSION_END,
15 STATE_ACTION,
16 STATE_COMMAND
17 } STATE;
20 GList *action_list = NULL;
23 /* add character to buffer */
24 #define add_to_buff(buf, pos, chr) do { \
25 buf[pos++] = chr; \
26 buf[pos] = '\0'; \
27 if (pos + 1 == RC_BUF_SIZE) \
28 error = 7; \
29 } while (0)
32 #define ismywhite(c) (c == '\t' || c == ' ')
36 * returns config/data file name in user's home
38 char *
39 rcconfig_get_name(char *append)
41 static gchar fname[PATH_MAX];
42 const gchar *home;
44 begin_func("rcconfig_get_name");
46 if (!(home = g_getenv("HOME")))
47 return_val(NULL);
49 memset(fname, 0, PATH_MAX);
50 snprintf(fname, PATH_MAX, "%s/.wmcliphist%s", home, append);
52 return_val(fname);
59 * appends parsed action to action list
61 int
62 action_append(char *expr_buf, char *action_buf, char *cmd_buf)
64 ACTION *action;
66 begin_func("action_append");
68 action = g_new0(ACTION, 1);
70 if (regcomp(&action->expression, expr_buf,
71 REG_EXTENDED|REG_ICASE|REG_NOSUB) != 0) {
72 g_free(action);
73 return_val(-101);
76 if (strcmp(action_buf, "exec") == 0)
77 action->action = ACT_EXEC;
78 else if (strcmp(action_buf, "submenu") == 0)
79 action->action = ACT_SUBMENU;
80 else if (strcmp(action_buf, "ignore") == 0)
81 action->action = ACT_IGNORE;
82 else {
83 g_free(action);
84 return_val(-102);
87 action->command = g_strdup(cmd_buf);
89 action_list = g_list_append(action_list, action);
91 return_val(0);
96 * read and parse rcconfig
98 int
99 rcconfig_get(char *fname)
101 int f_rc;
102 char tmp[1024], c;
103 int byte_cnt;
104 STATE state = STATE_BEGINING;
105 char direc_buf[RC_BUF_SIZE],
106 expr_buf[RC_BUF_SIZE],
107 action_buf[RC_BUF_SIZE],
108 cmd_buf[RC_BUF_SIZE];
109 int buf_index = 0;
110 int error = 0, eof = 0;
111 int i;
112 int line = 0;
113 int res;
115 begin_func("rcconfig_get");
117 close(open(fname, O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
119 if ((f_rc = open(fname, O_RDONLY)) < 0) {
120 fprintf(stderr, ".wmcliphistrc not found\n");
121 return_val(1);
124 i = byte_cnt = 0;
125 while (1) {
126 if (i == byte_cnt) {
127 byte_cnt = read(f_rc, tmp, 1024);
128 if (byte_cnt == -1) {
129 fprintf(stderr, "cannot read .wmcliphistrc\n");
130 break;
131 } else if (byte_cnt < 1024) {
132 tmp[byte_cnt++] = 0;
133 eof = 1;
135 i = 0;
138 c = tmp[i++];
139 switch (state) {
140 case STATE_BEGINING:
141 line++;
142 if (isalnum(c)) {
143 state = STATE_DIRECTIVE;
144 buf_index = 0;
145 add_to_buff(direc_buf, buf_index, c);
146 } else if (c == '#')
147 state = STATE_COMMENT;
148 else if (ismywhite(c))
149 line--;
150 else if (c == '\n')
151 state = STATE_BEGINING;
152 else
153 error = 1;
154 break;
156 case STATE_COMMENT:
157 if (c == '\n' || c == '\0')
158 state = STATE_BEGINING;
159 break;
161 case STATE_DIRECTIVE:
162 if (ismywhite(c)) {
163 if (strcmp(direc_buf, "action") == 0) {
164 state = STATE_EXPRESSION_START;
165 buf_index = 0;
166 } else if (strcmp(direc_buf, "menukey") == 0) {
167 state = STATE_VALUE;
168 buf_index = 0;
169 } else if (strcmp(direc_buf, "prev_item_key") == 0) {
170 state = STATE_VALUE;
171 buf_index = 0;
172 } else if (strcmp(direc_buf, "exec_item_key") == 0) {
173 state = STATE_VALUE;
174 buf_index = 0;
175 } else if (strcmp(direc_buf, "keep") == 0) {
176 state = STATE_VALUE;
177 buf_index = 0;
178 } else if (strcmp(direc_buf, "lcolor") == 0) {
179 state = STATE_VALUE;
180 buf_index = 0;
181 } else if (strcmp(direc_buf, "autosave") == 0) {
182 state = STATE_VALUE;
183 buf_index = 0;
184 } else if (strcmp(direc_buf,
185 "confirm_exec") == 0) {
186 state = STATE_VALUE;
187 buf_index = 0;
188 } else if (strcmp(direc_buf, "exec_immediately") == 0) {
189 state = STATE_VALUE;
190 buf_index = 0;
191 } else if (strcmp(direc_buf, "exec_middleclick") == 0) {
192 state = STATE_VALUE;
193 buf_index = 0;
194 } else if (strcmp(direc_buf, "exec_hotkey") == 0) {
195 state = STATE_VALUE;
196 buf_index = 0;
197 } else if (strcmp(direc_buf, "auto_take_up") == 0) {
198 state = STATE_VALUE;
199 buf_index = 0;
200 } else {
201 error = 8;
203 } else if (isalpha(c) || c == '_') {
204 add_to_buff(direc_buf, buf_index, c);
205 } else {
206 error = 1;
208 break;
210 case STATE_VALUE:
211 if (c == '\n' || ismywhite(c)) {
212 if (strcmp(direc_buf, "menukey") == 0) {
213 memset(menukey_str, 0, 32);
214 strncpy(menukey_str,
215 expr_buf, 31);
216 } else if (strcmp(direc_buf, "prev_item_key") == 0) {
217 memset(prev_item_key_str, 0, 32);
218 strncpy(prev_item_key_str,
219 expr_buf, 31);
220 } else if (strcmp(direc_buf, "exec_item_key") == 0) {
221 memset(exec_item_key_str, 0, 32);
222 strncpy(exec_item_key_str,
223 expr_buf, 31);
224 } else if (strcmp(direc_buf, "keep") == 0) {
225 num_items_to_keep =
226 atoi(expr_buf);
227 } else if (strcmp(direc_buf, "lcolor")
228 == 0) {
229 memset(locked_color_str, 0, 32);
230 strncpy(locked_color_str,
231 expr_buf, 31);
232 } else if (strcmp(direc_buf, "autosave") == 0) {
233 autosave_period =
234 atoi(expr_buf);
235 } else if (strcmp(direc_buf,
236 "confirm_exec") == 0) {
237 if (strcasecmp(expr_buf, "yes") == 0) {
238 confirm_exec = 1;
240 } else if (strcmp(direc_buf, "exec_immediately") == 0) {
241 if (strcasecmp(expr_buf, "no") == 0) {
242 exec_immediately= 0;
244 } else if (strcmp(direc_buf, "exec_middleclick") == 0) {
245 if (strcasecmp(expr_buf, "no") == 0) {
246 exec_middleclick = 0;
248 } else if (strcmp(direc_buf, "exec_hotkey") == 0) {
249 if (strcasecmp(expr_buf, "no") == 0) {
250 exec_hotkey = 0;
252 } else if (strcmp(direc_buf, "auto_take_up") == 0) {
253 if (strcasecmp(expr_buf, "no") == 0) {
254 auto_take_up = 0;
256 } else
257 error = 1;
258 } else if (isgraph(c))
259 add_to_buff(expr_buf, buf_index, c);
260 else
261 error = 2;
263 if (error == 0) {
264 if (c == '\n' || c == '\0') {
265 buf_index = 0;
266 state = STATE_BEGINING;
267 } else if (ismywhite(c)) {
268 buf_index = 0;
269 state = STATE_COMMENT;
273 break;
275 case STATE_EXPRESSION_START:
276 if (c == '"')
277 state = STATE_EXPRESSION;
278 else
279 error = 1;
280 break;
282 case STATE_EXPRESSION:
283 if (c == '"')
284 state = STATE_EXPRESSION_END;
285 else if (c == '\n')
286 error = 1;
287 else
288 add_to_buff(expr_buf, buf_index, c);
289 break;
291 case STATE_EXPRESSION_END:
292 if (c != ' ' && c != '\t')
293 error = 1;
294 if (strcmp(direc_buf, "action") == 0) {
295 state = STATE_ACTION;
296 buf_index = 0;
297 } else
298 error = 1;
300 break;
302 case STATE_ACTION:
303 if (c == ' ' || c == '\t') {
304 state = STATE_COMMAND;
305 buf_index = 0;
306 } else if (c == '\0' || c == '\n') {
307 if (strcmp(action_buf, "ignore") == 0) {
308 state = STATE_BEGINING;
309 buf_index = 0;
310 *cmd_buf = '\0';
311 res = action_append(
312 expr_buf,
313 action_buf,
314 cmd_buf);
315 if (res < 0)
316 error = abs(res);
317 } else
318 error = 1;
319 } else if (isalpha(c))
320 add_to_buff(action_buf, buf_index, c);
321 else
322 error = 1;
323 break;
325 case STATE_COMMAND:
326 if (c == '\n' || c == '\0') {
327 state = STATE_BEGINING;
328 buf_index = 0;
329 res = action_append(
330 expr_buf,
331 action_buf,
332 cmd_buf);
333 if (res < 0)
334 error = abs(res);
335 } else
336 add_to_buff(cmd_buf, buf_index, c);
337 break;
340 if (!error && (!eof || i < byte_cnt))
341 continue;
343 switch (state) {
344 case STATE_DIRECTIVE:
345 if (error == 7)
346 fprintf(stderr, "Directive is too long "
347 "(line %d)\n", line);
348 else if (error == 8)
349 fprintf(stderr, "Unknown directive "
350 "(line %d)\n", line);
351 else
352 fprintf(stderr, "Only letters are "
353 "allowed in directive "
354 "name (line %d)\n",
355 line);
356 break;
358 case STATE_EXPRESSION_START:
359 case STATE_EXPRESSION:
360 if (error == 7)
361 fprintf(stderr, "Expression is too long "
362 "(line %d)\n", line);
363 else
364 fprintf(stderr, "Expression must be "
365 "enclosed with quotes "
366 "\" (line %d)\n", line);
367 break;
369 case STATE_EXPRESSION_END:
370 fprintf(stderr, "One space/tab and "
371 "action must follow "
372 "each expression"
373 " (line %d)\n", line);
374 break;
376 case STATE_ACTION:
377 if (error == 1)
378 fprintf(stderr, "Only letters are "
379 "allowed in action "
380 "name (line %d)\n",
381 line);
382 else if (error == 101)
383 fprintf(stderr, "Invalid expression "
384 "(line %d)\n", line);
385 else if (error == 7)
386 fprintf(stderr, "Action is too long "
387 "(line %d)\n", line);
388 else
389 fprintf(stderr, "Invalid action "
390 "(line %d)\n", line);
391 break;
393 case STATE_VALUE:
394 if (error == 1)
395 fprintf(stderr, "Invalid directive "
396 "(line %d)\n", line);
397 else if (error == 7)
398 fprintf(stderr, "Value is too long "
399 "(line %d)\n", line);
400 else
401 fprintf(stderr, "Invalid value "
402 "(line %d)\n", line);
403 break;
405 case STATE_COMMAND:
406 if (error == 101)
407 fprintf(stderr, "Invalid expression "
408 "(line %d)\n", line);
409 else if (error == 7)
410 fprintf(stderr, "Command is too long "
411 "(line %d)\n", line);
412 else
413 fprintf(stderr, "Invalid action "
414 "(line %d)\n", line);
415 break;
417 case STATE_COMMENT:
418 if (!eof)
419 fprintf(stderr, "Unknown error "
420 "(line %d)\n", line);
421 else
422 error = 0;
423 break;
425 case STATE_BEGINING:
426 /* everything is OK */
427 error = 0;
428 break;
431 break;
434 close(f_rc);
436 return_val(error);
441 * free rcconfig data
443 void
444 rcconfig_free()
446 GList *list_node;
448 begin_func("rcconfig_free");
450 list_node = action_list;
451 while (list_node) {
452 ACTION *action = list_node->data;
454 g_free(action->command);
455 regfree(&action->expression);
456 g_free(action);
457 list_node = list_node->next;
459 g_list_free(action_list);
461 return_void();