<div dir="ltr">Sorry, i was a bit too rushing. I made a couple of comments below.<div class="gmail_extra"><br><br><div class="gmail_quote">2013/4/1 Kristian Høgsberg <span dir="ltr"><<a href="mailto:krh@bitplanet.net" target="_blank">krh@bitplanet.net</a>></span><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The current config parser, parses the ini file and pulls out the values<br>
specified by the struct config_section passed to parse_config_file() and<br>
then throw the rest away. This means that every place we want to get<br>
info out of the ini file, we have to parse the whole thing again. It's not<br>
a big overhead, but it's also not a convenient API.<br>
<br>
This patch adds a parser that parses the ini file to a data structure and<br>
puts that in weston_compositor->config along with API to query comfig<br>
keys from the data structure. The old parser is still available, but<br>
we'll transition to the new approach over the next few commits.<br>
---<br>
shared/config-parser.c | 225 +++++++++++++++++++++++++++++++++++++++++++++++++<br>
shared/config-parser.h | 26 ++++++<br>
src/compositor.c | 2 +<br>
src/compositor.h | 1 +<br>
4 files changed, 254 insertions(+)<br>
<br>
diff --git a/shared/config-parser.c b/shared/config-parser.c<br>
index 10ff86a..5582cc4 100644<br>
--- a/shared/config-parser.c<br>
+++ b/shared/config-parser.c<br>
@@ -25,7 +25,9 @@<br>
#include <stdlib.h><br>
#include <assert.h><br>
#include <ctype.h><br>
+#include <errno.h><br>
<br>
+#include <wayland-util.h><br>
#include "config-parser.h"<br>
<br>
static int<br>
@@ -185,3 +187,226 @@ config_file_path(const char *name)<br>
snprintf(path, size, "%s/%s", config_dir, name);<br>
return path;<br>
}<br>
+<br>
+struct weston_config_entry {<br>
+ char *key;<br>
+ char *value;<br>
+ struct wl_list link;<br>
+};<br>
+<br>
+struct weston_config_section {<br>
+ char *name;<br>
+ struct wl_list entry_list;<br>
+ struct wl_list link;<br>
+};<br>
+<br>
+struct weston_config {<br>
+ struct wl_list section_list;<br>
+};<br>
+<br>
+struct weston_config_section *<br>
+weston_config_get_section(struct weston_config *config, const char *section)<br>
+{<br>
+ struct weston_config_section *s;<br>
+<br>
+ wl_list_for_each(s, &config->section_list, link)<br>
+ if (strcmp(s->name, section) == 0)<br>
+ return s;<br>
+<br>
+ return NULL;<br>
+}<br>
+<br>
+static struct weston_config_entry *<br>
+config_section_get_entry(struct weston_config_section *section,<br>
+ const char *key)<br>
+{<br>
+ struct weston_config_entry *e;<br>
+<br>
+ if (section == NULL)<br>
+ return NULL;<br>
+ wl_list_for_each(e, §ion->entry_list, link)<br>
+ if (strcmp(e->key, key) == 0)<br>
+ return e;<br>
+<br>
+ return NULL;<br>
+}<br>
+<br>
+int<br>
+weston_config_section_get_int(struct weston_config_section *section,<br>
+ const char *key,<br>
+ int32_t *value, int32_t default_value)<br>
+{<br>
+ struct weston_config_entry *entry;<br>
+ char *end;<br>
+<br>
+ entry = config_section_get_entry(section, key);<br>
+ if (entry == NULL) {<br>
+ *value = default_value;<br>
+ errno = ENOENT;<br>
+ return -1;<br>
+ }<br>
+<br>
+ *value = strtol(entry->value, &end, 0);<br>
+ if (*end != '\0') {<br>
+ *value = default_value;<br>
+ errno = EINVAL;<br>
+ return -1;<br>
+ }<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+int<br>
+weston_config_section_get_uint(struct weston_config_section *section,<br>
+ const char *key,<br>
+ uint32_t *value, uint32_t default_value)<br>
+{<br>
+ struct weston_config_entry *entry;<br>
+ char *end;<br>
+<br>
+ entry = config_section_get_entry(section, key);<br>
+ if (entry == NULL) {<br>
+ *value = default_value;<br>
+ errno = ENOENT;<br>
+ return -1;<br>
+ }<br>
+<br>
+ *value = strtoul(entry->value, &end, 0);<br>
+ if (*end != '\0') {<br>
+ *value = default_value;<br>
+ errno = EINVAL;<br>
+ return -1;<br>
+ }<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+int<br>
+weston_config_section_get_string(struct weston_config_section *section,<br>
+ const char *key,<br>
+ const char **value, const char *default_value)<br>
+{<br>
+ struct weston_config_entry *entry;<br>
+<br>
+ entry = config_section_get_entry(section, key);<br>
+ if (entry == NULL) {<br>
+ if (default_value)<br>
+ *value = strdup(default_value);<br>
+ errno = ENOENT;<br>
+ return -1;<br>
+ }<br>
+<br>
+ *value = strdup(entry->value);<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+int<br>
+weston_config_section_get_bool(struct weston_config_section *section,<br>
+ const char *key,<br>
+ int *value, int default_value)<br>
+{<br>
+ struct weston_config_entry *entry;<br>
+<br>
+ entry = config_section_get_entry(section, key);<br>
+ if (entry == NULL) {<br>
+ *value = default_value;<br>
+ errno = ENOENT;<br>
+ return -1;<br>
+ }<br>
+<br>
+ if (strcmp(entry->value, "false\n") == 0)<br>
+ *value = 0;<br>
+ else if (strcmp(entry->value, "true\n") == 0)<br>
+ *value = 1;<br>
+ else {<br>
+ *value = default_value;<br>
+ errno = EINVAL;<br>
+ return -1;<br>
+ }<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+static struct weston_config_section *<br>
+config_add_section(struct weston_config *config, const char *name)<br>
+{<br>
+ struct weston_config_section *section;<br>
+<br>
+ section = malloc(sizeof *section);<br>
+ section->name = strdup(name);<br>
+ wl_list_init(§ion->entry_list);<br>
+ wl_list_insert(config->section_list.prev, §ion->link);<br>
+<br>
+ return section;<br>
+}<br>
+<br>
+static struct weston_config_entry *<br>
+section_add_entry(struct weston_config_section *section,<br>
+ const char *key, const char *value)<br>
+{<br>
+ struct weston_config_entry *entry;<br>
+<br>
+ entry = malloc(sizeof *entry);<br>
+ entry->key = strdup(key);<br>
+ entry->value = strdup(value);<br>
+ wl_list_insert(section->entry_list.prev, &entry->link);<br>
+<br>
+ return entry;<br>
+}<br>
+<br>
+struct weston_config *<br>
+weston_config_parse(const char *path)<br>
+{<br>
+ FILE *fp;<br>
+ char line[512], *p;<br>
+ struct weston_config *config;<br>
+ struct weston_config_section *section = NULL;<br>
+ int i;<br>
+<br>
+ config = malloc(sizeof *config);<br>
+ if (config == NULL) {<br>
+ free(path);<br></blockquote><div> </div><div style>This shouldn't free the path. It is a const char* and could well be a literal. The user should free it itself if it is the case.</div><div style><br>
</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ return NULL;<br>
+ }<br>
+<br>
+ wl_list_init(&config->section_list);<br>
+<br>
+ fp = fopen(path, "r");<br>
+ if (fp == NULL) {<br>
+ fprintf(stderr, "couldn't open %s\n", path);<br>
+ free(config);<br>
+ return NULL;<br>
+ }<br>
+<br>
+ while (fgets(line, sizeof line, fp)) {<br>
+ if (line[0] == '#' || line[0] == '\n') {<br>
+ continue;<br>
+ } if (line[0] == '[') {<br>
+ p = strchr(&line[1], ']');<br>
+ if (!p || p[1] != '\n') {<br>
+ fprintf(stderr, "malformed "<br>
+ "section header: %s\n", line);<br>
+ fclose(fp);<br>
+ free(config);<br>
+ return NULL;<br>
+ }<br>
+ p[0] = '\0';<br>
+ section = config_add_section(config, &line[1]);<br>
+ } else if (p = strchr(line, '='), p && section) {<br>
+ p[0] = '\0';<br>
+ i = strlen(&p[1]);<br>
+ p[i + 1] = '\0';<br>
+ section_add_entry(section, line, &p[1]);<br></blockquote><div style><br></div><div style>This is also putting the newline in the value of the entry.</div><div style><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+ } else {<br>
+ fprintf(stderr, "malformed config line: %s\n", line);<br>
+ fclose(fp);<br>
+ free(config);<br>
+ return NULL;<br>
+ }<br>
+ }<br>
+<br>
+ fclose(fp);<br>
+<br>
+ return config;<br>
+}<br>
diff --git a/shared/config-parser.h b/shared/config-parser.h<br>
index 1d0ee3f..0efbac3 100644<br>
--- a/shared/config-parser.h<br>
+++ b/shared/config-parser.h<br>
@@ -73,6 +73,32 @@ int<br>
parse_options(const struct weston_option *options,<br>
int count, int *argc, char *argv[]);<br>
<br>
+struct weston_config_section;<br>
+struct weston_config;<br>
+<br>
+struct weston_config_section *<br>
+weston_config_get_section(struct weston_config *config, const char *section);<br>
+int<br>
+weston_config_section_get_int(struct weston_config_section *section,<br>
+ const char *key,<br>
+ int32_t *value, int32_t default_value);<br>
+int<br>
+weston_config_section_get_uint(struct weston_config_section *section,<br>
+ const char *key,<br>
+ uint32_t *value, uint32_t default_value);<br>
+int<br>
+weston_config_section_get_string(struct weston_config_section *section,<br>
+ const char *key,<br>
+ const char **value,<br>
+ const char *default_value);<br>
+int<br>
+weston_config_section_get_bool(struct weston_config_section *section,<br>
+ const char *key,<br>
+ int *value, int default_value);<br>
+struct weston_config *<br>
+weston_config_parse(const char *basename);<br>
+<br>
+<br>
#ifdef __cplusplus<br>
}<br>
#endif<br>
diff --git a/src/compositor.c b/src/compositor.c<br>
index 1617d96..cb374f7 100644<br>
--- a/src/compositor.c<br>
+++ b/src/compositor.c<br>
@@ -3139,6 +3139,8 @@ weston_compositor_init(struct weston_compositor *ec,<br>
keyboard_config_keys, ARRAY_LENGTH(keyboard_config_keys) },<br>
};<br>
<br>
+ ec->config = weston_config_parse(config_file);<br>
+<br>
memset(&xkb_names, 0, sizeof(xkb_names));<br>
parse_config_file(config_file, cs, ARRAY_LENGTH(cs), ec);<br>
<br>
diff --git a/src/compositor.h b/src/compositor.h<br>
index 7d1d68e..e4c7ab2 100644<br>
--- a/src/compositor.h<br>
+++ b/src/compositor.h<br>
@@ -301,6 +301,7 @@ struct weston_compositor {<br>
<br>
struct wl_display *wl_display;<br>
struct weston_shell_interface shell_interface;<br>
+ struct weston_config *config;<br>
<br>
struct wl_signal activate_signal;<br>
struct wl_signal kill_signal;<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.1.2<br>
<br>
</font></span></blockquote></div><br></div></div>