%%
-[\t ]*#[^\n]* /* eat comments */
-[\t ]+ /* eat whitespace */
+[\t ]*#[^\r\n]* /* eat comments */
+[\t\r ]+ /* eat whitespace */
\n|#.*\n return NEWLINE; /* also eats comments at the end of a line */
"{" |
yy_push_state(str, yyscanner);
}
-[^#{}="\n\t ]+ {
+[^#{}="\r\n\t ]+ {
yylval->s = strdup(yytext);
return NAME;
}
<inc>{
+ \r /* just ignore these */
/* we allow all characters except #, } and spaces, they can be escaped */
<<EOF>> |
[#}\n\t ] {
\\["#} ] {
yyextra->string_add(yyextra, yytext+1);
}
- [^"\\#}\n\t ]+ {
+ [^"\\#}\r\n\t ]+ {
yyextra->string_add(yyextra, yytext);
}
}
<str>{
+ \r /* just ignore these */
"\"" |
<<EOF>> |
\\ {
return STRING;
}
}
+
\\n yyextra->string_add(yyextra, "\n");
\\r yyextra->string_add(yyextra, "\r");
\\t yyextra->string_add(yyextra, "\t");
- \\\r?\n /* merge lines that end with EOL characters */
+ \\\r?\n /* merge lines that end with escaped EOL characters */
\\. yyextra->string_add(yyextra, yytext+1);
- [^\\"]+ {
+ [^\\\r"]+ {
yyextra->string_add(yyextra, yytext);
}
}
}
END_TEST
+START_SETUP(setup_crlf_config)
+{
+ chunk_t inc1 = chunk_from_str(
+ "main {\r\n"
+ " key1 = n1\r\n"
+ " key2 = n2\n"
+ " key3 = val3\n"
+ " none = \n"
+ " sub1 {\n"
+ " key3 = value\n"
+ " }\n"
+ " sub2 {\n"
+ " sub3 = val3\n"
+ " }\n"
+ " include " include2 "\n"
+ "}");
+ chunk_t inc2 = chunk_from_str(
+ "key2 = v2\n"
+ "sub1 {\n"
+ " key = val\n"
+ "}");
+ ck_assert(chunk_write(inc1, include1, 0022, TRUE));
+ ck_assert(chunk_write(inc2, include2, 0022, TRUE));
+}
+END_SETUP
+
+START_TEST(test_crlf)
+{
+ chunk_t contents = chunk_from_str(
+ "main {\r\n"
+ " key1 = val1\r\n"
+ " none =\r\n"
+ " sub1 {\r\n"
+ " key2 = v2\r\n"
+ " # key2 = v3\r\n"
+ " sub1 {\r\n"
+ " key = val\r\n"
+ " }\r\n"
+ " }\r\n"
+ "}");
+
+ create_settings(contents);
+
+ verify_string("val1", "main.key1");
+ verify_string("v2", "main.sub1.key2");
+ verify_string("val", "main.sub1.sub1.key");
+ verify_null("main.none");
+}
+END_TEST
+
+START_TEST(test_crlf_string)
+{
+ chunk_t contents = chunk_from_str(
+ "main {\r\n"
+ " key1 = \"new\r\nline\"\r\n"
+ " key2 = \"joi\\\r\nned\"\r\n"
+ " none =\r\n"
+ " sub1 {\r\n"
+ " key2 = v2\r\n"
+ " sub1 {\r\n"
+ " key = val\r\n"
+ " }\r\n"
+ " }\r\n"
+ "}");
+
+ create_settings(contents);
+
+ verify_string("new\nline", "main.key1");
+ verify_string("joined", "main.key2");
+ verify_string("v2", "main.sub1.key2");
+ verify_string("val", "main.sub1.sub1.key");
+ verify_null("main.none");
+}
+END_TEST
+
+START_TEST(test_crlf_include)
+{
+ chunk_t contents = chunk_from_str(
+ "main {\r\n"
+ " key1 = val1\r\n"
+ " none =\r\n"
+ " sub1 {\r\n"
+ " key2 = v2\r\n"
+ " sub1 {\r\n"
+ " key = val\r\n"
+ " }\r\n"
+ " }\r\n"
+ "}");
+
+ create_settings(contents);
+
+ verify_string("val1", "main.key1");
+ verify_string("v2", "main.sub1.key2");
+ verify_string("val", "main.sub1.sub1.key");
+ verify_null("main.none");
+}
+END_TEST
+
Suite *settings_suite_create()
{
Suite *s;
tcase_add_test(tc, test_invalid);
suite_add_tcase(s, tc);
+ tc = tcase_create("crlf");
+ tcase_add_checked_fixture(tc, setup_crlf_config, teardown_include_config);
+ tcase_add_test(tc, test_crlf);
+ tcase_add_test(tc, test_crlf_string);
+ tcase_add_test(tc, test_crlf_include);
+ suite_add_tcase(s, tc);
+
return s;
}