[Fix:Conflict]Changed the animation of a default defined from none to fade.
[profile/ivi/ico-uxf-weston-plugin.git] / src / config-parser.c
1 /*
2  * Copyright © 2011 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #define _GNU_SOURCE   /* for stchrnul() */
24 #include <string.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <assert.h>
28 #include <ctype.h>
29 #include <limits.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34
35 #include <weston/config-parser.h>
36
37 static int
38 handle_key(const struct config_key *key, const char *value)
39 {
40         char *end, *s;
41         int i, len;
42         unsigned int ui;
43         
44         switch (key->type) {
45         case CONFIG_KEY_INTEGER:
46                 i = strtol(value, &end, 0);
47                 if (*end != '\n') {
48                         fprintf(stderr, "invalid integer: %s\n", value);
49                         return -1;
50                 }
51                 *(int *)key->data = i;
52                 return 0;
53
54         case CONFIG_KEY_UNSIGNED_INTEGER:
55                 ui = strtoul(value, &end, 0);
56                 if (*end != '\n') {
57                         fprintf(stderr, "invalid integer: %s\n", value);
58                         return -1;
59                 }
60                 *(unsigned int *)key->data = ui;
61                 return 0;
62
63         case CONFIG_KEY_STRING:
64                 len = strlen(value);
65                 while (len > 0 && isspace(value[len - 1]))
66                         len--;
67                 s = malloc(len + 1);
68                 if (s == NULL)
69                         return -1;
70                 memcpy(s, value, len);
71                 s[len] = '\0';
72                 *(char **)key->data = s;
73                 return 0;
74
75         case CONFIG_KEY_BOOLEAN:
76                 if (strcmp(value, "false\n") == 0)
77                         *(int *)key->data = 0;
78                 else if (strcmp(value, "true\n") == 0)
79                         *(int *)key->data = 1;
80                 else {
81                         fprintf(stderr, "invalid bool: %s\n", value);
82                         return -1;
83                 }
84                 return 0;
85
86         default:
87                 assert(0);
88                 break;
89         }
90
91         return -1;
92 }
93
94 int
95 parse_config_file(int fd,
96                   const struct config_section *sections, int num_sections,
97                   void *data)
98 {
99         FILE *fp;
100         char line[512], *p;
101         const struct config_section *current = NULL;
102         int i;
103
104         if (fd == -1)
105                 return -1;
106
107         fp = fdopen(dup(fd), "r");
108         if (fp == NULL) {
109             perror("couldn't open config file");
110                 return -1;
111         }
112
113         rewind(fp);
114
115         while (fgets(line, sizeof line, fp)) {
116                 if (line[0] == '#' || line[0] == '\n') {
117                         continue;
118                 } if (line[0] == '[') {
119                         p = strchr(&line[1], ']');
120                         if (!p || p[1] != '\n') {
121                                 fprintf(stderr, "malformed "
122                                         "section header: %s\n", line);
123                                 fclose(fp);
124                                 return -1;
125                         }
126                         if (current && current->done)
127                                 current->done(data);
128                         p[0] = '\0';
129                         for (i = 0; i < num_sections; i++) {
130                                 if (strcmp(sections[i].name, &line[1]) == 0) {
131                                         current = &sections[i];
132                                         break;
133                                 }
134                         }
135                         if (i == num_sections)
136                                 current = NULL;
137                 } else if (p = strchr(line, '='), p != NULL) {
138                         if (current == NULL)
139                                 continue;
140                         p[0] = '\0';
141                         for (i = 0; i < current->num_keys; i++) {
142                                 if (strcmp(current->keys[i].name, line) == 0) {
143                                         if (handle_key(&current->keys[i], &p[1]) < 0) {
144                                                 fclose(fp);
145                                                 return -1;
146                                         }
147                                         break;
148                                 }
149                         }
150                 } else {
151                         fprintf(stderr, "malformed config line: %s\n", line);
152                         fclose(fp);
153                         return -1;
154                 }
155         }
156
157         if (current && current->done)
158                 current->done(data);
159
160         fclose(fp);
161
162         return 0;
163 }
164
165 int
166 open_config_file(const char *name)
167 {
168         const char *config_dir  = getenv("XDG_CONFIG_HOME");
169         const char *home_dir    = getenv("HOME");
170         const char *config_dirs = getenv("XDG_CONFIG_DIRS");
171         char path[PATH_MAX];
172         const char *p, *next;
173         int fd;
174
175         /* Precedence is given to config files in the home directory,
176          * and then to directories listed in XDG_CONFIG_DIRS and
177          * finally to the current working directory. */
178
179         /* $XDG_CONFIG_HOME */
180         if (config_dir) {
181                 snprintf(path, sizeof path, "%s/%s", config_dir, name);
182                 fd = open(path, O_RDONLY | O_CLOEXEC);
183                 if (fd >= 0)
184                         return fd;
185         }
186
187         /* $HOME/.config */
188         if (home_dir) {
189                 snprintf(path, sizeof path, "%s/.config/%s", home_dir, name);
190                 fd = open(path, O_RDONLY | O_CLOEXEC);
191                 if (fd >= 0)
192                         return fd;
193         }
194
195         /* For each $XDG_CONFIG_DIRS: weston/<config_file> */
196         if (!config_dirs)
197                 config_dirs = "/etc/xdg";  /* See XDG base dir spec. */
198
199         for (p = config_dirs; *p != '\0'; p = next) {
200                 next = strchrnul(p, ':');
201                 snprintf(path, sizeof path,
202                          "%.*s/weston/%s", (int)(next - p), p, name);
203                 fd = open(path, O_RDONLY | O_CLOEXEC);
204                 if (fd >= 0)
205                         return fd;
206
207                 if (*next == ':')
208                         next++;
209         }
210
211         /* Current working directory. */
212         snprintf(path, sizeof path, "./%s", name);
213         fd = open(path, O_RDONLY | O_CLOEXEC);
214
215         if (fd >= 0)
216                 fprintf(stderr,
217                         "using config in current working directory: %s\n",
218                         path);
219         else
220                 fprintf(stderr, "config file \"%s\" not found.\n", name);
221
222         return fd;
223 }