compositor: make functions static
[profile/ivi/weston-ivi-shell.git] / shared / 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 #include <string.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <assert.h>
27
28 #include "config-parser.h"
29
30 static int
31 handle_key(const struct config_key *key, const char *value)
32 {
33         char *end, *s;
34         int i, len;
35         unsigned int ui;
36         
37         switch (key->type) {
38         case CONFIG_KEY_INTEGER:
39                 i = strtol(value, &end, 0);
40                 if (*end != '\n') {
41                         fprintf(stderr, "invalid integer: %s\n", value);
42                         return -1;
43                 }
44                 *(int *)key->data = i;
45                 return 0;
46
47         case CONFIG_KEY_UNSIGNED_INTEGER:
48                 ui = strtoul(value, &end, 0);
49                 if (*end != '\n') {
50                         fprintf(stderr, "invalid integer: %s\n", value);
51                         return -1;
52                 }
53                 *(unsigned int *)key->data = ui;
54                 return 0;
55
56         case CONFIG_KEY_STRING:
57                 len = strlen(value);
58                 s = malloc(len);
59                 if (s == NULL)
60                         return -1;
61                 memcpy(s, value, len - 1);
62                 s[len - 1] = '\0';
63                 *(char **)key->data = s;
64                 return 0;
65
66         case CONFIG_KEY_BOOLEAN:
67                 if (strcmp(value, "false\n") == 0)
68                         *(int *)key->data = 0;
69                 else if (strcmp(value, "true\n") == 0)
70                         *(int *)key->data = 1;
71                 else {
72                         fprintf(stderr, "invalid bool: %s\n", value);
73                         return -1;
74                 }
75                 return 0;
76
77         default:
78                 assert(0);
79                 break;
80         }
81 }
82
83 int
84 parse_config_file(const char *path,
85                   const struct config_section *sections, int num_sections,
86                   void *data)
87 {
88         FILE *fp;
89         char line[512], *p;
90         const struct config_section *current = NULL;
91         int i;
92
93         fp = fopen(path, "r");
94         if (fp == NULL) {
95                 fprintf(stderr, "couldn't open %s\n", path);
96                 return -1;
97         }
98
99         while (fgets(line, sizeof line, fp)) {
100                 if (line[0] == '#' || line[0] == '\n') {
101                         continue;
102                 } if (line[0] == '[') {
103                         p = strchr(&line[1], ']');
104                         if (!p || p[1] != '\n') {
105                                 fprintf(stderr, "malformed "
106                                         "section header: %s\n", line);
107                                 fclose(fp);
108                                 return -1;
109                         }
110                         if (current && current->done)
111                                 current->done(data);
112                         p[0] = '\0';
113                         for (i = 0; i < num_sections; i++) {
114                                 if (strcmp(sections[i].name, &line[1]) == 0) {
115                                         current = &sections[i];
116                                         break;
117                                 }
118                         }
119                         if (i == num_sections)
120                                 current = NULL;
121                 } else if (p = strchr(line, '='), p != NULL) {
122                         if (current == NULL)
123                                 continue;
124                         p[0] = '\0';
125                         for (i = 0; i < current->num_keys; i++) {
126                                 if (strcmp(current->keys[i].name, line) == 0) {
127                                         if (handle_key(&current->keys[i], &p[1]) < 0) {
128                                                 fclose(fp);
129                                                 return -1;
130                                         }
131                                         break;
132                                 }
133                         }
134                 } else {
135                         fprintf(stderr, "malformed config line: %s\n", line);
136                         fclose(fp);
137                         return -1;
138                 }
139         }
140
141         if (current && current->done)
142                 current->done(data);
143
144         fclose(fp);
145
146         return 0;
147 }
148
149 char *
150 config_file_path(const char *name)
151 {
152         const char dotconf[] = "/.config/";
153         const char *config_dir;
154         const char *home_dir;
155         char *path;
156         size_t size;
157
158         config_dir = getenv("XDG_CONFIG_HOME");
159         if (!config_dir) {
160                 home_dir = getenv("HOME");
161                 if (!home_dir) {
162                         fprintf(stderr, "HOME is not set, using cwd.\n");
163                         return strdup(name);
164                 }
165
166                 size = strlen(home_dir) + sizeof dotconf + strlen(name);
167                 path = malloc(size);
168                 if (!path)
169                         return NULL;
170
171                 snprintf(path, size, "%s%s%s", home_dir, dotconf, name);
172                 return path;
173         }
174
175         size = strlen(config_dir) + 1 + strlen(name) + 1;
176         path = malloc(size);
177         if (!path)
178                 return NULL;
179
180         snprintf(path, size, "%s/%s", config_dir, name);
181         return path;
182 }