dovecot-2.0: config: Code cleanups.

dovecot at dovecot.org dovecot at dovecot.org
Mon Aug 31 19:20:46 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/a0ec16185806
changeset: 9833:a0ec16185806
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Aug 31 12:20:38 2009 -0400
description:
config: Code cleanups.

diffstat:

1 file changed, 212 insertions(+), 157 deletions(-)
src/config/config-parser.c |  369 +++++++++++++++++++++++++-------------------

diffs (truncated from 497 to 300 lines):

diff -r 3a16bec9c961 -r a0ec16185806 src/config/config-parser.c
--- a/src/config/config-parser.c	Mon Aug 31 11:38:42 2009 -0400
+++ b/src/config/config-parser.c	Mon Aug 31 12:20:38 2009 -0400
@@ -92,10 +92,10 @@ static void config_add_type(struct setti
 	i_assert(ret > 0);
 }
 
-static const char *
+static int
 config_parsers_parse_line(struct config_setting_parser_list *parsers,
 			  const char *key, const char *line,
-			  const char *section_name)
+			  const char *section_name, const char **error_r)
 {
 	struct config_setting_parser_list *l;
 	bool found = FALSE;
@@ -107,26 +107,30 @@ config_parsers_parse_line(struct config_
 			found = TRUE;
 			if (section_name != NULL)
 				config_add_type(l->parser, line, section_name);
-		} else if (ret < 0)
-			return settings_parser_get_error(l->parser);
-	}
-
-	return found ? NULL : t_strconcat("Unknown setting: ", key, NULL);
-}
-
-static const char *
-config_parse_line(struct config_setting_parser_list *const *all_parsers,
-		  const char *key, const char *line, const char *section_name)
-{
-	const char *ret;
-
+		} else if (ret < 0) {
+			*error_r = settings_parser_get_error(l->parser);
+			return -1;
+		}
+	}
+	if (!found) {
+		*error_r = t_strconcat("Unknown setting: ", key, NULL);
+		return -1;
+	}
+	return 0;
+}
+
+static int
+config_apply_line(struct config_setting_parser_list *const *all_parsers,
+		  const char *key, const char *line, const char *section_name,
+		  const char **error_r)
+{
 	for (; *all_parsers != NULL; all_parsers++) {
-		ret = config_parsers_parse_line(*all_parsers, key, line,
-						section_name);
-		if (ret != NULL)
-			return ret;
-	}
-	return NULL;
+		if (config_parsers_parse_line(*all_parsers, key, line,
+					      section_name, error_r) < 0)
+			return -1;
+	}
+	*error_r = NULL;
+	return 0;
 }
 
 static const char *
@@ -260,7 +264,7 @@ config_all_parsers_check(struct parser_c
 	return 0;
 }
 
-static void
+static int
 str_append_file(string_t *str, const char *key, const char *path,
 		const char **error_r)
 {
@@ -272,7 +276,7 @@ str_append_file(string_t *str, const cha
 	if (fd == -1) {
 		*error_r = t_strdup_printf("%s: Can't open file %s: %m",
 					   key, path);
-		return;
+		return -1;
 	}
 	while ((ret = read(fd, buf, sizeof(buf))) > 0)
 		str_append_n(str, buf, ret);
@@ -281,6 +285,7 @@ str_append_file(string_t *str, const cha
 					   key, path);
 	}
 	(void)close(fd);
+	return ret < 0 ? -1 : 0;
 }
 
 static int settings_add_include(struct parser_context *ctx, const char *path,
@@ -354,6 +359,133 @@ settings_include(struct parser_context *
 #else
 	return settings_add_include(ctx, pattern, ignore_errors, error_r);
 #endif
+}
+
+enum config_line_type {
+	CONFIG_LINE_TYPE_SKIP,
+	CONFIG_LINE_TYPE_ERROR,
+	CONFIG_LINE_TYPE_KEYVALUE,
+	CONFIG_LINE_TYPE_SECTION_BEGIN,
+	CONFIG_LINE_TYPE_SECTION_END,
+	CONFIG_LINE_TYPE_INCLUDE,
+	CONFIG_LINE_TYPE_INCLUDE_TRY
+};
+
+static enum config_line_type
+config_parse_line(char *line, string_t *full_line, const char **key_r,
+		  const char **section_r, const char **value_r)
+{
+	const char *key;
+	unsigned int len;
+	char *p;
+
+	*key_r = NULL;
+	*value_r = NULL;
+	*section_r = NULL;
+
+	/* @UNSAFE: line is modified */
+
+	/* skip whitespace */
+	while (IS_WHITE(*line))
+		line++;
+
+	/* ignore comments or empty lines */
+	if (*line == '#' || *line == '\0')
+		return CONFIG_LINE_TYPE_SKIP;
+
+	/* strip away comments. pretty kludgy way really.. */
+	for (p = line; *p != '\0'; p++) {
+		if (*p == '\'' || *p == '"') {
+			char quote = *p;
+			for (p++; *p != quote && *p != '\0'; p++) {
+				if (*p == '\\' && p[1] != '\0')
+					p++;
+			}
+			if (*p == '\0')
+				break;
+		} else if (*p == '#') {
+			*p = '\0';
+			break;
+		}
+	}
+
+	/* remove whitespace from end of line */
+	len = strlen(line);
+	while (IS_WHITE(line[len-1]))
+		len--;
+	line[len] = '\0';
+
+	if (len > 0 && line[len-1] == '\\') {
+		/* continues in next line */
+		line[len-1] = '\0';
+		str_append(full_line, line);
+		return CONFIG_LINE_TYPE_SKIP;
+	}
+	if (str_len(full_line) > 0) {
+		str_append(full_line, line);
+		line = str_c_modifiable(full_line);
+	}
+
+	/* a) key = value
+	   b) section_type [section_name] {
+	   c) } */
+	key = line;
+	while (!IS_WHITE(*line) && *line != '\0' && *line != '=')
+		line++;
+	if (IS_WHITE(*line)) {
+		*line++ = '\0';
+		while (IS_WHITE(*line)) line++;
+	}
+	*key_r = key;
+	*value_r = line;
+
+	if (strcmp(key, "!include") == 0)
+		return CONFIG_LINE_TYPE_INCLUDE;
+	if (strcmp(key, "!include_try") == 0)
+		return CONFIG_LINE_TYPE_INCLUDE_TRY;
+
+	if (*line == '=') {
+		/* a) */
+		*line++ = '\0';
+		while (IS_WHITE(*line)) line++;
+
+		len = strlen(line);
+		if (len > 0 &&
+		    ((*line == '"' && line[len-1] == '"') ||
+		     (*line == '\'' && line[len-1] == '\''))) {
+			line[len-1] = '\0';
+			line = str_unescape(line+1);
+		}
+		*value_r = line;
+		return CONFIG_LINE_TYPE_KEYVALUE;
+	}
+
+	if (strcmp(key, "}") == 0 && *line == '\0')
+		return CONFIG_LINE_TYPE_SECTION_END;
+
+	/* b) + errors */
+	line[-1] = '\0';
+
+	if (*line == '{')
+		*section_r = "";
+	else {
+		/* get section name */
+		*section_r = line;
+		while (!IS_WHITE(*line) && *line != '\0')
+			line++;
+
+		if (*line != '\0') {
+			*line++ = '\0';
+			while (IS_WHITE(*line))
+				line++;
+		}
+		if (*line != '{') {
+			*value_r = "Expecting '='";
+			return CONFIG_LINE_TYPE_ERROR;
+		}
+		*value_r = line;
+	}
+	return CONFIG_LINE_TYPE_SECTION_BEGIN;
 }
 
 int config_parse_file(const char *path, bool expand_files,
@@ -367,11 +499,11 @@ int config_parse_file(const char *path, 
 	struct parser_context ctx;
 	unsigned int pathlen = 0;
 	unsigned int i, count, counter = 0, auth_counter = 0, cur_counter;
-	const char *errormsg, *name;
-	char *line, *key, *p;
+	const char *errormsg, *key, *value, *section, *p;
+	string_t *str, *full_line;
+	enum config_line_type type;
+	char *line;
 	int fd, ret = 0;
-	string_t *str, *full_line;
-	size_t len;
 
 	fd = open(path, O_RDONLY);
 	if (fd < 0) {
@@ -401,9 +533,9 @@ int config_parse_file(const char *path, 
 	config_add_new_parser(&ctx);
 	parsers = config_update_cur_parsers(&ctx);
 
-	errormsg = config_parse_line(parsers, "0", "auth=0", NULL);
+	(void)config_apply_line(parsers, "0", "auth=0", NULL, &errormsg);
 	i_assert(errormsg == NULL);
-	errormsg = config_parse_line(parsers, "name", "auth/0/name=default", NULL);
+	(void)config_apply_line(parsers, "name", "auth/0/name=default", NULL, &errormsg);
 	i_assert(errormsg == NULL);
 
 	memset(&root, 0, sizeof(root));
@@ -418,146 +550,61 @@ prevfile:
 prevfile:
 	while ((line = i_stream_read_next_line(ctx.cur_input->input)) != NULL) {
 		ctx.cur_input->linenum++;
-
-		/* @UNSAFE: line is modified */
-
-		/* skip whitespace */
-		while (IS_WHITE(*line))
-			line++;
-
-		/* ignore comments or empty lines */
-		if (*line == '#' || *line == '\0')
-			continue;
-
-		/* strip away comments. pretty kludgy way really.. */
-		for (p = line; *p != '\0'; p++) {
-			if (*p == '\'' || *p == '"') {
-				char quote = *p;
-				for (p++; *p != quote && *p != '\0'; p++) {
-					if (*p == '\\' && p[1] != '\0')
-						p++;
-				}
-				if (*p == '\0')
-					break;
-			} else if (*p == '#') {
-				*p = '\0';
-				break;
-			}
-		}
-
-		/* remove whitespace from end of line */
-		len = strlen(line);
-		while (IS_WHITE(line[len-1]))
-			len--;
-		line[len] = '\0';
-
-		if (len > 0 && line[len-1] == '\\') {
-			/* continues in next line */
-			line[len-1] = '\0';
-			str_append(full_line, line);
-			continue;
-		}
-		if (str_len(full_line) > 0) {
-			str_append(full_line, line);
-			line = str_c_modifiable(full_line);


More information about the dovecot-cvs mailing list