image-loader.h \
cairo-util.c \
cairo-util.h
+
+TESTS = config-parser-test
+
+check_PROGRAMS = $(TESTS)
+
+config_parser_test_LDADD = $(COMPOSITOR_LIBS)
+config_parser_test_SOURCES = \
+ config-parser.c \
+ config-parser.h \
+ config-parser-test.c
--- /dev/null
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "config-parser.h"
+
+static struct weston_config *
+run_test(const char *text)
+{
+ struct weston_config *config;
+ char file[] = "/tmp/weston-config-parser-test-XXXXXX";
+ int fd, len;
+
+ fd = mkstemp(file);
+ len = write(fd, text, strlen(text));
+ assert(len == strlen(text));
+
+ config = weston_config_parse(fd);
+ close(fd);
+ unlink(file);
+
+ return config;
+}
+
+static const char t0[] =
+ "# nothing in this file...\n";
+
+static const char t1[] =
+ "# comment line here...\n"
+ "\n"
+ "[foo]\n"
+ "a=b\n"
+ "name= Roy Batty \n"
+ "\n"
+ "\n"
+ "[bar]\n"
+ "# more comments\n"
+ "number=5252\n"
+ "flag=false\n"
+ "\n"
+ "[stuff]\n"
+ "flag= true \n"
+ "\n"
+ "[bucket]\n"
+ "color=blue \n"
+ "contents=live crabs\n"
+ "pinchy=true\n"
+ "\n"
+ "[bucket]\n"
+ "material=plastic \n"
+ "color=red\n"
+ "contents=sand\n";
+
+static const char t2[] =
+ "# invalid section...\n"
+ "[this bracket isn't closed\n";
+
+static const char t3[] =
+ "# line without = ...\n"
+ "[bambam]\n"
+ "this line isn't any kind of valid\n";
+
+static const char t4[] =
+ "# starting with = ...\n"
+ "[bambam]\n"
+ "=not valid at all\n";
+
+int main(int argc, char *argv[])
+{
+ struct weston_config *config;
+ struct weston_config_section *section;
+ char *s;
+ int r, b;
+ int32_t n;
+ uint32_t u;
+
+ config = run_test(t0);
+ assert(config);
+ weston_config_destroy(config);
+
+ config = run_test(t1);
+ assert(config);
+ section = weston_config_get_section(config, "mollusc", NULL, NULL);
+ assert(section == NULL);
+
+ section = weston_config_get_section(config, "foo", NULL, NULL);
+ r = weston_config_section_get_string(section, "a", &s, NULL);
+ assert(r == 0 && strcmp(s, "b") == 0);
+ free(s);
+
+ section = weston_config_get_section(config, "foo", NULL, NULL);
+ r = weston_config_section_get_string(section, "b", &s, NULL);
+ assert(r == -1 && errno == ENOENT && s == NULL);
+
+ section = weston_config_get_section(config, "foo", NULL, NULL);
+ r = weston_config_section_get_string(section, "name", &s, NULL);
+ assert(r == 0 && strcmp(s, "Roy Batty") == 0);
+ free(s);
+
+ section = weston_config_get_section(config, "bar", NULL, NULL);
+ r = weston_config_section_get_string(section, "a", &s, "boo");
+ assert(r == -1 && errno == ENOENT && strcmp(s, "boo") == 0);
+ free(s);
+
+ section = weston_config_get_section(config, "bar", NULL, NULL);
+ r = weston_config_section_get_int(section, "number", &n, 600);
+ assert(r == 0 && n == 5252);
+
+ section = weston_config_get_section(config, "bar", NULL, NULL);
+ r = weston_config_section_get_int(section, "+++", &n, 700);
+ assert(r == -1 && errno == ENOENT && n == 700);
+
+ section = weston_config_get_section(config, "bar", NULL, NULL);
+ r = weston_config_section_get_uint(section, "number", &u, 600);
+ assert(r == 0 && u == 5252);
+
+ section = weston_config_get_section(config, "bar", NULL, NULL);
+ r = weston_config_section_get_uint(section, "+++", &u, 600);
+ assert(r == -1 && errno == ENOENT && u == 600);
+
+ section = weston_config_get_section(config, "bar", NULL, NULL);
+ r = weston_config_section_get_bool(section, "flag", &b, 600);
+ assert(r == 0 && b == 0);
+
+ section = weston_config_get_section(config, "stuff", NULL, NULL);
+ r = weston_config_section_get_bool(section, "flag", &b, -1);
+ assert(r == 0 && b == 1);
+
+ section = weston_config_get_section(config, "stuff", NULL, NULL);
+ r = weston_config_section_get_bool(section, "bonk", &b, -1);
+ assert(r == -1 && errno == ENOENT && b == -1);
+
+ section = weston_config_get_section(config, "bucket", "color", "blue");
+ r = weston_config_section_get_string(section, "contents", &s, NULL);
+ assert(r == 0 && strcmp(s, "live crabs") == 0);
+ free(s);
+
+ section = weston_config_get_section(config, "bucket", "color", "red");
+ r = weston_config_section_get_string(section, "contents", &s, NULL);
+ assert(r == 0 && strcmp(s, "sand") == 0);
+ free(s);
+
+ section = weston_config_get_section(config, "bucket", "color", "pink");
+ assert(section == NULL);
+ r = weston_config_section_get_string(section, "contents", &s, "eels");
+ assert(r == -1 && errno == ENOENT && strcmp(s, "eels") == 0);
+ free(s);
+
+ weston_config_destroy(config);
+
+ config = run_test(t2);
+ assert(config == NULL);
+
+ config = run_test(t3);
+ assert(config == NULL);
+
+ config = run_test(t4);
+ assert(config == NULL);
+
+ return 0;
+}
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
+#include <errno.h>
+#include <wayland-util.h>
#include "config-parser.h"
static int
return fd;
}
+
+struct weston_config_entry {
+ char *key;
+ char *value;
+ struct wl_list link;
+};
+
+struct weston_config_section {
+ char *name;
+ struct wl_list entry_list;
+ struct wl_list link;
+};
+
+struct weston_config {
+ struct wl_list section_list;
+};
+
+static struct weston_config_entry *
+config_section_get_entry(struct weston_config_section *section,
+ const char *key)
+{
+ struct weston_config_entry *e;
+
+ if (section == NULL)
+ return NULL;
+ wl_list_for_each(e, §ion->entry_list, link)
+ if (strcmp(e->key, key) == 0)
+ return e;
+
+ return NULL;
+}
+
+struct weston_config_section *
+weston_config_get_section(struct weston_config *config, const char *section,
+ const char *key, const char *value)
+{
+ struct weston_config_section *s;
+ struct weston_config_entry *e;
+
+ wl_list_for_each(s, &config->section_list, link) {
+ if (strcmp(s->name, section) != 0)
+ continue;
+ if (key == NULL)
+ return s;
+ e = config_section_get_entry(s, key);
+ if (e && strcmp(e->value, value) == 0)
+ return s;
+ }
+
+ return NULL;
+}
+
+int
+weston_config_section_get_int(struct weston_config_section *section,
+ const char *key,
+ int32_t *value, int32_t default_value)
+{
+ struct weston_config_entry *entry;
+ char *end;
+
+ entry = config_section_get_entry(section, key);
+ if (entry == NULL) {
+ *value = default_value;
+ errno = ENOENT;
+ return -1;
+ }
+
+ *value = strtol(entry->value, &end, 0);
+ if (*end != '\0') {
+ *value = default_value;
+ errno = EINVAL;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+weston_config_section_get_uint(struct weston_config_section *section,
+ const char *key,
+ uint32_t *value, uint32_t default_value)
+{
+ struct weston_config_entry *entry;
+ char *end;
+
+ entry = config_section_get_entry(section, key);
+ if (entry == NULL) {
+ *value = default_value;
+ errno = ENOENT;
+ return -1;
+ }
+
+ *value = strtoul(entry->value, &end, 0);
+ if (*end != '\0') {
+ *value = default_value;
+ errno = EINVAL;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+weston_config_section_get_string(struct weston_config_section *section,
+ const char *key,
+ char **value, const char *default_value)
+{
+ struct weston_config_entry *entry;
+
+ entry = config_section_get_entry(section, key);
+ if (entry == NULL) {
+ if (default_value)
+ *value = strdup(default_value);
+ else
+ *value = NULL;
+ errno = ENOENT;
+ return -1;
+ }
+
+ *value = strdup(entry->value);
+
+ return 0;
+}
+
+int
+weston_config_section_get_bool(struct weston_config_section *section,
+ const char *key,
+ int *value, int default_value)
+{
+ struct weston_config_entry *entry;
+
+ entry = config_section_get_entry(section, key);
+ if (entry == NULL) {
+ *value = default_value;
+ errno = ENOENT;
+ return -1;
+ }
+
+ if (strcmp(entry->value, "false") == 0)
+ *value = 0;
+ else if (strcmp(entry->value, "true") == 0)
+ *value = 1;
+ else {
+ *value = default_value;
+ errno = EINVAL;
+ return -1;
+ }
+
+ return 0;
+}
+
+static struct weston_config_section *
+config_add_section(struct weston_config *config, const char *name)
+{
+ struct weston_config_section *section;
+
+ section = malloc(sizeof *section);
+ section->name = strdup(name);
+ wl_list_init(§ion->entry_list);
+ wl_list_insert(config->section_list.prev, §ion->link);
+
+ return section;
+}
+
+static struct weston_config_entry *
+section_add_entry(struct weston_config_section *section,
+ const char *key, const char *value)
+{
+ struct weston_config_entry *entry;
+
+ entry = malloc(sizeof *entry);
+ entry->key = strdup(key);
+ entry->value = strdup(value);
+ wl_list_insert(section->entry_list.prev, &entry->link);
+
+ return entry;
+}
+
+struct weston_config *
+weston_config_parse(int fd)
+{
+ FILE *fp;
+ char line[512], *p;
+ struct weston_config *config;
+ struct weston_config_section *section = NULL;
+ int i;
+
+ config = malloc(sizeof *config);
+ if (config == NULL)
+ return NULL;
+
+ wl_list_init(&config->section_list);
+
+ fp = fdopen(dup(fd), "r");
+ if (fp == NULL) {
+ free(config);
+ return NULL;
+ }
+
+ rewind(fp);
+
+ while (fgets(line, sizeof line, fp)) {
+ switch (line[0]) {
+ case '#':
+ case '\n':
+ continue;
+ case '[':
+ p = strchr(&line[1], ']');
+ if (!p || p[1] != '\n') {
+ fprintf(stderr, "malformed "
+ "section header: %s\n", line);
+ fclose(fp);
+ weston_config_destroy(config);
+ return NULL;
+ }
+ p[0] = '\0';
+ section = config_add_section(config, &line[1]);
+ continue;
+ default:
+ p = strchr(line, '=');
+ if (!p || p == line || !section) {
+ fprintf(stderr, "malformed "
+ "config line: %s\n", line);
+ fclose(fp);
+ weston_config_destroy(config);
+ return NULL;
+ }
+
+ p[0] = '\0';
+ p++;
+ while (isspace(*p))
+ p++;
+ i = strlen(p);
+ while (i > 0 && isspace(p[i - 1])) {
+ p[i - 1] = '\0';
+ i--;
+ }
+ section_add_entry(section, line, p);
+ continue;
+ }
+ }
+
+ fclose(fp);
+
+ return config;
+}
+
+void
+weston_config_destroy(struct weston_config *config)
+{
+ struct weston_config_section *s, *next_s;
+ struct weston_config_entry *e, *next_e;
+
+ wl_list_for_each_safe(s, next_s, &config->section_list, link) {
+ wl_list_for_each_safe(e, next_e, &s->entry_list, link) {
+ free(e->key);
+ free(e->value);
+ free(e);
+ }
+ free(s->name);
+ free(s);
+ }
+
+ free(config);
+}
parse_options(const struct weston_option *options,
int count, int *argc, char *argv[]);
+struct weston_config_section;
+struct weston_config;
+
+struct weston_config_section *
+weston_config_get_section(struct weston_config *config, const char *section,
+ const char *key, const char *value);
+int
+weston_config_section_get_int(struct weston_config_section *section,
+ const char *key,
+ int32_t *value, int32_t default_value);
+int
+weston_config_section_get_uint(struct weston_config_section *section,
+ const char *key,
+ uint32_t *value, uint32_t default_value);
+int
+weston_config_section_get_string(struct weston_config_section *section,
+ const char *key,
+ char **value,
+ const char *default_value);
+int
+weston_config_section_get_bool(struct weston_config_section *section,
+ const char *key,
+ int *value, int default_value);
+struct weston_config *
+weston_config_parse(int fd);
+
+void
+weston_config_destroy(struct weston_config *config);
+
#ifdef __cplusplus
}
#endif
memset(&xkb_names, 0, sizeof(xkb_names));
ec->config_fd = config_fd;
+ ec->config = weston_config_parse(config_fd);
parse_config_file(config_fd, cs, ARRAY_LENGTH(cs), ec);
ec->wl_display = display;
struct wl_display *wl_display;
struct weston_shell_interface shell_interface;
+ struct weston_config *config;
struct wl_signal activate_signal;
struct wl_signal kill_signal;