Quellcode durchsuchen

- return values unified
- print token info only when EXTRA_DEBUG is defined
- cfg_get_token calls accept flags from the parent function
- cfg_eat_eol implemented
- parser functions are supposed to handle EOL themselves
- various flags implemented to tell parser functions how
to return strings (pkgmem, shmmem, malloc, static buf)
- *_opt functions parse the whole option body, every of
them has an alternative without _opt suffix which parses
one token.
- cfg_parse_section accepts memory allocation flags just
like cfg_parse_str

Jan Janak vor 17 Jahren
Ursprung
Commit
7ed7f2ae33
2 geänderte Dateien mit 152 neuen und 108 gelöschten Zeilen
  1. 137 103
      cfg_parser.c
  2. 15 5
      cfg_parser.h

+ 137 - 103
cfg_parser.c

@@ -214,7 +214,7 @@ enum st {
     token->end.col = st->col;   \
     token->type = (c);          \
     print_token(token);         \
-    return 1;
+    return 0;
 
 
 /*
@@ -252,6 +252,7 @@ static void print_token(cfg_token_t* token)
 	int i, j;
 	char* buf;
 
+#ifdef EXTRA_DEBUG
 	if ((buf = pkg_malloc(token->val.len * 2)) == NULL) {
 		DBG("token(%d, '%.*s', <%d,%d>-<%d,%d>)\n", 
 			token->type, STR_FMT(&token->val),
@@ -274,8 +275,10 @@ static void print_token(cfg_token_t* token)
 			token->end.line, token->end.col);
 		pkg_free(buf);
 	}
+#endif /* EXTRA_DEBUG */
 }
 
+
 int cfg_get_token(cfg_token_t* token, cfg_parser_t* st, unsigned int flags)
 {
 	static int look_ahead = EOF;
@@ -481,7 +484,7 @@ int cfg_get_token(cfg_token_t* token, cfg_parser_t* st, unsigned int flags)
 	case ST_S: 
 	case ST_C:
 	case ST_CE:
-		return 0;
+		return 1;
 
 	case ST_A:
 		RETURN(CFG_TOKEN_ALPHA);
@@ -508,37 +511,18 @@ int cfg_parse_section(void* param, cfg_parser_t* st, unsigned int flags)
 {
 	cfg_token_t t;
 	int ret;
-	str* name;
-
-	name = (str*)param;
-	if (name == NULL) {
-		BUG("cfg_parser: Invalid parameter value to cfg_parse_section\n");
-		return -1;
-	}
-
-	ret = cfg_get_token(&t, st, 0);
-	if (ret < 0) return -1;
-	if (ret == 0) {
-		ERR("%s:%d:%d: Section name missing.\n", st->file, st->line, st->col);
-		return -1;
-	}
 
-	if (t.type != CFG_TOKEN_ALPHA) {
-		ERR("%s:%d:%d: Invalid table name %d:'%.*s'\n", 
-		    st->file, t.start.line, t.start.col,
-		    t.type, STR_FMT(&t.val));
-		return -1;
+	ret = cfg_parse_str(param, st, flags);
+	if (ret < 0) return ret;
+	if (ret > 0) {
+		ERR("%s:%d:%d: Section name missing.\n",
+			st->file, st->line, st->col);
+		return ret;
 	}
-	
-	if ((name->s = as_asciiz(&t.val)) == NULL) {
-		ERR("%s:%d:%d: Out of memory\n", st->file, t.start.line, t.start.col);
-		return -1;
-	}
-	name->len = t.val.len;
 
-	ret = cfg_get_token(&t, st, 0);
+	ret = cfg_get_token(&t, st, flags);
 	if (ret < 0) goto error;
-	if (ret == 0) {
+	if (ret > 0) {
 		ERR("%s:%d:%d: Closing ']' missing\n", st->file, st->line, st->col);
 		goto error;
 	}
@@ -547,10 +531,23 @@ int cfg_parse_section(void* param, cfg_parser_t* st, unsigned int flags)
 		    st->file, t.start.line, t.start.col);
 		goto error;
 	}
+
+	if (cfg_eat_eol(st, flags)) goto error;
 	return 0;
 
  error:
-	if (name->s) pkg_free(name->s);
+	if (param && ((str*)param)->s) {
+		if (flags & CFG_STR_PKGMEM) {
+			pkg_free(((str*)param)->s);
+			((str*)param)->s = NULL;
+		} else if (flags & CFG_STR_SHMMEM) {
+			shm_free(((str*)param)->s);
+			((str*)param)->s = NULL;
+		} else if (flags & CFG_STR_MALLOC) {
+			free(((str*)param)->s);
+			((str*)param)->s = NULL;
+		}		
+	}
 	return -1;
 }
 
@@ -679,7 +676,8 @@ int cfg_parse(cfg_parser_t* st)
 
 	while(1) {
 		ret = cfg_get_token(&t, st, 0);
-		if (ret <= 0) return ret;
+		if (ret < 0) return ret;
+		if (ret > 0) break;
 
 		switch(t.type) {
 		case CFG_TOKEN_ALPHA:
@@ -711,15 +709,6 @@ int cfg_parse(cfg_parser_t* st)
 			    st->file, t.start.line, t.start.col);
 			return -1;
 		}
-
-		     /* Skip EOL */
-		ret = cfg_get_token(&t, st, 0);
-		if (ret <= 0) return ret;
-		if (t.type != '\n') {
-			ERR("%s:%d:%d: End of line expected\n", 
-			    st->file, t.start.line, t.start.col);
-			return -1;
-		}
 	}
 	return 0;
 }
@@ -728,7 +717,7 @@ int cfg_parse(cfg_parser_t* st)
 cfg_option_t* cfg_lookup_token(cfg_option_t* table, str* token)
 {
 	int len, i;
-	int (*cmp)(const char* s12, const char* s2, size_t n) = NULL;
+	int (*cmp)(const char* s1, const char* s2, size_t n) = NULL;
 
 
 	if (table == NULL) return NULL;
@@ -755,17 +744,17 @@ cfg_option_t* cfg_lookup_token(cfg_option_t* table, str* token)
 }
 
 
-int cfg_eat_equal(cfg_parser_t* st)
+int cfg_eat_equal(cfg_parser_t* st, unsigned int flags)
 {
 	cfg_token_t t;
 	int ret;
 
-	ret = cfg_get_token(&t, st, 0);
-	if (ret < 0) return -1;
-	if (ret == 0) {
-		ERR("%s:%d:%d: Option value missing\n", 
+	ret = cfg_get_token(&t, st, flags);
+	if (ret < 0) return ret;
+	if (ret > 0) {
+		ERR("%s:%d:%d: Delimiter '=' missing\n", 
 		    st->file, st->line, st->col);
-		return -1;
+		return ret;
 	}
 
 	if (t.type != '=') {
@@ -777,7 +766,25 @@ int cfg_eat_equal(cfg_parser_t* st)
 }
 
 
-int cfg_parse_enum_val(void* param, cfg_parser_t* st, unsigned int flags)
+int cfg_eat_eol(cfg_parser_t* st, unsigned int flags)
+{
+	cfg_token_t t;
+	int ret;
+
+	/* Skip EOL */
+	ret = cfg_get_token(&t, st, 0);
+	if (ret < 0) return ret;
+	if (ret > 0) return 0;
+	if (t.type != '\n') {
+		ERR("%s:%d:%d: End of line expected\n", 
+			st->file, t.start.line, t.start.col);
+		return -1;
+	}
+	return 0;
+}
+
+
+int cfg_parse_enum(void* param, cfg_parser_t* st, unsigned int flags)
 {
 	int ret;
     cfg_token_t t;
@@ -785,25 +792,18 @@ int cfg_parse_enum_val(void* param, cfg_parser_t* st, unsigned int flags)
 	
 	values = (cfg_option_t*)param;
 
-	if (cfg_eat_equal(st)) return -1;
+	ret = cfg_get_token(&t, st, flags);
+	if (ret != 0) return ret;
 
-	ret = cfg_get_token(&t, st, CFG_EXTENDED_ALPHA);
-	if (ret < 0) return -1;
-	if (ret == 0) {
-		ERR("%s:%d:%d: Option value missing\n",
-		    st->file, st->line, st->col);
-		return -1;
-	}
-	
 	if (t.type != CFG_TOKEN_ALPHA && t.type != CFG_TOKEN_STRING) {
-		ERR("%s:%d:%d: Invalid option value '%.*s'\n",
+		ERR("%s:%d:%d: Invalid enum value '%.*s'\n",
 		    st->file, t.start.line, t.start.col, STR_FMT(&t.val));
 		return -1;
 	}
 
 	if (values) {
 		if ((val = cfg_lookup_token(values, &t.val)) == NULL) {
-			ERR("%s:%d:%d Unsupported option value '%.*s'\n", 
+			ERR("%s:%d:%d Unsupported enum value '%.*s'\n", 
 				st->file, t.start.line, t.start.col, STR_FMT(&t.val));
 			return -1;
 		}
@@ -814,25 +814,36 @@ int cfg_parse_enum_val(void* param, cfg_parser_t* st, unsigned int flags)
 }
 
 
-int cfg_parse_str_val(void* param, cfg_parser_t* st, unsigned int flags)
+int cfg_parse_enum_opt(void* param, cfg_parser_t* st, unsigned int flags)
+{
+	int ret;
+
+	if (cfg_eat_equal(st, flags)) return -1;
+
+	ret = cfg_parse_enum(param, st, CFG_EXTENDED_ALPHA | flags);
+	if (ret > 0) {
+		ERR("%s:%d:%d: Option value missing\n",
+		    st->file, st->line, st->col);
+		return ret;
+	} else if (ret < 0) return ret;
+
+	if (cfg_eat_eol(st, flags)) return -1;
+	return 0;
+}
+
+
+int cfg_parse_str(void* param, cfg_parser_t* st, unsigned int flags)
 {
 	str* val;
 	int ret;
 	char* buf;
     cfg_token_t t;
 	
-	if (cfg_eat_equal(st)) return -1;
-
-	ret = cfg_get_token(&t, st, CFG_EXTENDED_ALPHA);
-	if (ret < 0) return -1;
-	if (ret == 0) {
-		ERR("%s:%d:%d: Option value missing\n",
-		    st->file, t.start.line, t.start.col);
-		return -1;
-	}
+	ret = cfg_get_token(&t, st, flags);
+	if (ret != 0) return ret;
 	
 	if (t.type != CFG_TOKEN_ALPHA && t.type != CFG_TOKEN_STRING) {
-		ERR("%s:%d:%d: Invalid option value '%.*s'\n",
+		ERR("%s:%d:%d: Invalid string value '%.*s', a string expected.\n",
 		    st->file, t.start.line, t.start.col, STR_FMT(&t.val));
 		return -1;
 	}
@@ -881,8 +892,24 @@ int cfg_parse_str_val(void* param, cfg_parser_t* st, unsigned int flags)
 }
 
 
+int cfg_parse_str_opt(void* param, cfg_parser_t* st, unsigned int flags)
+{
+	int ret;
+
+	if (cfg_eat_equal(st, flags)) return -1;
+
+	ret = cfg_parse_str(param, st, flags | CFG_EXTENDED_ALPHA);
+	if (ret > 0) {
+		ERR("%s:%d:%d: Option value missing\n",
+		    st->file, st->line, st->col);
+	} else if (ret < 0) return ret;
+
+	if (cfg_eat_eol(st, flags)) return -1;
+	return 0;
+}
 
-int cfg_parse_int_val(void* param, cfg_parser_t* st, unsigned int flags)
+
+int cfg_parse_int(void* param, cfg_parser_t* st, unsigned int flags)
 {
 	int* val;
 	int ret, tmp;
@@ -890,18 +917,11 @@ int cfg_parse_int_val(void* param, cfg_parser_t* st, unsigned int flags)
 
 	val = (int*)param;
 
-	if (cfg_eat_equal(st)) return -1;
-	
-	ret = cfg_get_token(&t, st, CFG_EXTENDED_ALPHA);
-	if (ret < 0) return -1;
-	if (ret == 0) {
-		ERR("%s:%d:%d: Option value missing\n", 
-		    st->file, t.start.line, t.start.col);
-		return -1;
-	}
+	ret = cfg_get_token(&t, st, flags);
+	if (ret != 0) return ret;
 
 	if (t.type != CFG_TOKEN_ALPHA && t.type != CFG_TOKEN_STRING) {
-		ERR("%s:%d:%d: Invalid option value '%.*s', integer expected\n", 
+		ERR("%s:%d:%d: Invalid integer value '%.*s'\n", 
 		    st->file, t.start.line, t.start.col, STR_FMT(&t.val));
 		return -1;
 	}
@@ -917,7 +937,24 @@ int cfg_parse_int_val(void* param, cfg_parser_t* st, unsigned int flags)
 }
 
 
-int cfg_parse_bool_val(void* param, cfg_parser_t* st, unsigned int flags)
+int cfg_parse_int_opt(void* param, cfg_parser_t* st, unsigned int flags)
+{
+	int ret;
+
+	if (cfg_eat_equal(st, flags)) return -1;
+
+	ret = cfg_parse_int(param, st, flags);
+	if (ret > 0) {
+		ERR("%s:%d:%d: Option value missing\n", 
+		    st->file, st->line, st->col);
+	} else if (ret < 0) return ret;
+
+	if (cfg_eat_eol(st, flags)) return -1;
+	return 0;
+}
+
+
+int cfg_parse_bool(void* param, cfg_parser_t* st, unsigned int flags)
 {
 	int ret, *val;
 	cfg_token_t t;
@@ -925,27 +962,8 @@ int cfg_parse_bool_val(void* param, cfg_parser_t* st, unsigned int flags)
 	
 	val = (int*)param;
 
-	ret = cfg_get_token(&t, st, 0);
-	if (ret < 0) return -1;
-	if (ret == 0) {
-		ERR("%s:%d:%d: Option value missing\n", 
-		    st->file, t.start.line, t.start.col);
-		return -1;
-	}
-	
-	if (t.type != '=') {
-		ERR("%s:%d:%d: Syntax error, '=' expected\n", 
-		    st->file, t.start.line, t.start.col);
-		return -1;
-	}
-
-	ret = cfg_get_token(&t, st, CFG_EXTENDED_ALPHA);
-	if (ret < 0) return -1;
-	if (ret == 0) {
-		ERR("%s:%d:%d: Option value missing\n", 
-		    st->file, t.start.line, t.start.col);
-		return -1;
-	}
+	ret = cfg_get_token(&t, st, flags);
+	if (ret != 0) return ret;
 
 	if (t.type != CFG_TOKEN_ALPHA && t.type != CFG_TOKEN_STRING) {
 		ERR("%s:%d:%d: Invalid option value '%.*s', boolean expected\n", 
@@ -962,3 +980,19 @@ int cfg_parse_bool_val(void* param, cfg_parser_t* st, unsigned int flags)
 	if (val) *val = map->val;
 	return 0;
 }
+
+
+int cfg_parse_bool_opt(void* param, cfg_parser_t* st, unsigned int flags)
+{
+	int ret;
+	if (cfg_eat_equal(st, flags)) return -1;
+
+    ret = cfg_parse_bool(param, st, CFG_EXTENDED_ALPHA | flags);
+	if (ret > 0) {
+		ERR("%s:%d:%d: Option value missing\n", 
+		    st->file, st->line, st->col);
+	} else if (ret < 0) return ret;
+
+	if (cfg_eat_eol(st, flags)) return -1;
+	return 0;
+}

+ 15 - 5
cfg_parser.h

@@ -156,7 +156,9 @@ int cfg_get_token(struct cfg_token* token, struct cfg_parser* st, unsigned int f
 
 /* Commonly needed parser functions */
 
-int cfg_eat_equal(struct cfg_parser* st);
+int cfg_eat_equal(struct cfg_parser* st, unsigned int flags);
+
+int cfg_eat_eol(struct cfg_parser* st, unsigned int flags);
 
 /* Parse section identifier of form [section]. The function expects parameter
  * param to be of type (str*). The result string is allocated using pkg_malloc
@@ -165,14 +167,22 @@ int cfg_eat_equal(struct cfg_parser* st);
 int cfg_parse_section(void* param, struct cfg_parser* st, unsigned int flags);
 
 /* Parse string parameter value, either quoted or unquoted */
-int cfg_parse_str_val(void* param, struct cfg_parser* st, unsigned int flags);
+int cfg_parse_str_opt(void* param, struct cfg_parser* st, unsigned int flags);
+
+int cfg_parse_str(void* param, struct cfg_parser* st, unsigned int flags);
+
+int cfg_parse_enum_opt(void* param, struct cfg_parser* st, unsigned int flags);
 
-int cfg_parse_enum_val(void* param, struct cfg_parser* st, unsigned int flags);
+int cfg_parse_enum(void* param, struct cfg_parser* st, unsigned int flags);
 
 /* Parser integer parameter value */
-int cfg_parse_int_val(void* param, struct cfg_parser* st, unsigned int flags);
+int cfg_parse_int_opt(void* param, struct cfg_parser* st, unsigned int flags);
+
+int cfg_parse_int(void* param, struct cfg_parser* st, unsigned int flags);
 
 /* Parse boolean parameter value */
-int cfg_parse_bool_val(void* param, struct cfg_parser* st, unsigned int flags);
+int cfg_parse_bool_opt(void* param, struct cfg_parser* st, unsigned int flags);
+
+int cfg_parse_bool(void* param, struct cfg_parser* st, unsigned int flags);
 
 #endif /* _CFG_PARSER_H */