aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael G. Martins <rafael@rafaelmartins.eng.br>2016-07-03 04:49:09 +0200
committerRafael G. Martins <rafael@rafaelmartins.eng.br>2016-07-03 04:49:09 +0200
commit3968529cad2baec099acff5fee47b5fe24624b03 (patch)
treef1140cb53fcb8b5359f29bb4bcff851124d56752
parenta8ec8e389166adc1231930028bf845da5f9f40ef (diff)
downloadblogc-3968529cad2baec099acff5fee47b5fe24624b03.tar.gz
blogc-3968529cad2baec099acff5fee47b5fe24624b03.tar.bz2
blogc-3968529cad2baec099acff5fee47b5fe24624b03.zip
error: improved parser error reporting
now it shows a visual indicator '^' pointing to the position of the error, in the line after the error message. should be helpful for users writing templates, if any.
-rw-r--r--src/error.c4
-rw-r--r--src/template-parser.c2
-rw-r--r--tests/check_error.c24
-rw-r--r--tests/check_source_parser.c28
-rw-r--r--tests/check_template_parser.c141
5 files changed, 135 insertions, 64 deletions
diff --git a/src/error.c b/src/error.c
index 586386a..acce506 100644
--- a/src/error.c
+++ b/src/error.c
@@ -96,8 +96,8 @@ blogc_error_parser(blogc_error_type_t type, const char *src, size_t src_len,
rv = blogc_error_new(type, msg);
else
rv = blogc_error_new_printf(type,
- "%s\nError occurred near line %d, position %d: %s", msg, lineno,
- pos, line);
+ "%s\nError occurred near line %d, position %d:\n%s\n%*s", msg,
+ lineno, pos, line, pos, "^");
free(msg);
free(line);
diff --git a/src/template-parser.c b/src/template-parser.c
index de6eb52..751fd9e 100644
--- a/src/template-parser.c
+++ b/src/template-parser.c
@@ -622,7 +622,7 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err)
if (*err == NULL) {
if (state == TEMPLATE_BLOCK_IF_STRING_OPERAND)
*err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, src_len,
- start2 - 1, "Found an open double-quoted string.");
+ start2, "Found an open double-quoted string.");
else if (if_count != 0)
*err = blogc_error_new_printf(BLOGC_ERROR_TEMPLATE_PARSER,
"%d open 'ifdef' and/or 'ifndef' statements were not closed!",
diff --git a/tests/check_error.c b/tests/check_error.c
index 8818b00..a954095 100644
--- a/tests/check_error.c
+++ b/tests/check_error.c
@@ -49,21 +49,27 @@ test_error_parser(void **state)
assert_non_null(error);
assert_int_equal(error->type, 1);
assert_string_equal(error->msg,
- "asd 10\nError occurred near line 3, position 2: chunda");
+ "asd 10\nError occurred near line 3, position 2:\n"
+ "chunda\n"
+ " ^");
blogc_error_free(error);
a = "bola\nguda\nchunda";
error = blogc_error_parser(1, a, strlen(a), 11, "asd %d", 10);
assert_non_null(error);
assert_int_equal(error->type, 1);
assert_string_equal(error->msg,
- "asd 10\nError occurred near line 3, position 2: chunda");
+ "asd 10\nError occurred near line 3, position 2:\n"
+ "chunda\n"
+ " ^");
blogc_error_free(error);
a = "bola\nguda\nchunda";
error = blogc_error_parser(1, a, strlen(a), 0, "asd %d", 10);
assert_non_null(error);
assert_int_equal(error->type, 1);
assert_string_equal(error->msg,
- "asd 10\nError occurred near line 1, position 1: bola");
+ "asd 10\nError occurred near line 1, position 1:\n"
+ "bola\n"
+ "^");
blogc_error_free(error);
a = "";
error = blogc_error_parser(1, a, strlen(a), 0, "asd %d", 10);
@@ -82,21 +88,27 @@ test_error_parser_crlf(void **state)
assert_non_null(error);
assert_int_equal(error->type, 1);
assert_string_equal(error->msg,
- "asd 10\nError occurred near line 3, position 2: chunda");
+ "asd 10\nError occurred near line 3, position 2:\n"
+ "chunda\n"
+ " ^");
blogc_error_free(error);
a = "bola\r\nguda\r\nchunda";
error = blogc_error_parser(1, a, strlen(a), 13, "asd %d", 10);
assert_non_null(error);
assert_int_equal(error->type, 1);
assert_string_equal(error->msg,
- "asd 10\nError occurred near line 3, position 2: chunda");
+ "asd 10\nError occurred near line 3, position 2:\n"
+ "chunda\n"
+ " ^");
blogc_error_free(error);
a = "bola\r\nguda\r\nchunda";
error = blogc_error_parser(1, a, strlen(a), 0, "asd %d", 10);
assert_non_null(error);
assert_int_equal(error->type, 1);
assert_string_equal(error->msg,
- "asd 10\nError occurred near line 1, position 1: bola");
+ "asd 10\nError occurred near line 1, position 1:\n"
+ "bola\n"
+ "^");
blogc_error_free(error);
}
diff --git a/tests/check_source_parser.c b/tests/check_source_parser.c
index d94dc70..2dcaad6 100644
--- a/tests/check_source_parser.c
+++ b/tests/check_source_parser.c
@@ -220,7 +220,9 @@ test_source_parse_config_invalid_key(void **state)
assert_int_equal(err->type, BLOGC_ERROR_SOURCE_PARSER);
assert_string_equal(err->msg,
"Can't find a configuration key or the content separator.\n"
- "Error occurred near line 1, position 1: bola: guda");
+ "Error occurred near line 1, position 1:\n"
+ "bola: guda\n"
+ "^");
blogc_error_free(err);
sb_trie_free(source);
}
@@ -236,7 +238,9 @@ test_source_parse_config_no_key(void **state)
assert_int_equal(err->type, BLOGC_ERROR_SOURCE_PARSER);
assert_string_equal(err->msg,
"Invalid configuration key.\n"
- "Error occurred near line 1, position 4: BOLa");
+ "Error occurred near line 1, position 4:\n"
+ "BOLa\n"
+ " ^");
blogc_error_free(err);
sb_trie_free(source);
}
@@ -252,7 +256,9 @@ test_source_parse_config_no_key2(void **state)
assert_int_equal(err->type, BLOGC_ERROR_SOURCE_PARSER);
assert_string_equal(err->msg,
"Your last configuration key is missing ':' and the value\n"
- "Error occurred near line 1, position 5: BOLA");
+ "Error occurred near line 1, position 5:\n"
+ "BOLA\n"
+ " ^");
blogc_error_free(err);
sb_trie_free(source);
}
@@ -269,7 +275,9 @@ test_source_parse_config_no_value(void **state)
assert_int_equal(err->type, BLOGC_ERROR_SOURCE_PARSER);
assert_string_equal(err->msg,
"Configuration value not provided for 'BOLA'.\n"
- "Error occurred near line 1, position 6: BOLA:");
+ "Error occurred near line 1, position 6:\n"
+ "BOLA:\n"
+ " ^");
blogc_error_free(err);
sb_trie_free(source);
}
@@ -286,7 +294,9 @@ test_source_parse_config_no_value2(void **state)
assert_int_equal(err->type, BLOGC_ERROR_SOURCE_PARSER);
assert_string_equal(err->msg,
"Configuration value not provided for 'BOLA'.\n"
- "Error occurred near line 1, position 6: BOLA:");
+ "Error occurred near line 1, position 6:\n"
+ "BOLA:\n"
+ " ^");
blogc_error_free(err);
sb_trie_free(source);
}
@@ -490,7 +500,9 @@ test_source_parse_config_value_no_line_ending(void **state)
assert_int_equal(err->type, BLOGC_ERROR_SOURCE_PARSER);
assert_string_equal(err->msg,
"No line ending after the configuration value for 'BOLA'.\n"
- "Error occurred near line 1, position 10: BOLA: asd");
+ "Error occurred near line 1, position 10:\n"
+ "BOLA: asd\n"
+ " ^");
blogc_error_free(err);
sb_trie_free(source);
}
@@ -507,7 +519,9 @@ test_source_parse_invalid_separator(void **state)
assert_int_equal(err->type, BLOGC_ERROR_SOURCE_PARSER);
assert_string_equal(err->msg,
"Invalid content separator. Must be more than one '-' characters.\n"
- "Error occurred near line 2, position 4: ---#");
+ "Error occurred near line 2, position 4:\n"
+ "---#\n"
+ " ^");
blogc_error_free(err);
sb_trie_free(source);
}
diff --git a/tests/check_template_parser.c b/tests/check_template_parser.c
index d2d5e8d..8264ffa 100644
--- a/tests/check_template_parser.c
+++ b/tests/check_template_parser.c
@@ -455,7 +455,9 @@ test_template_parse_invalid_block_start(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid statement syntax. Must begin with lowercase letter.\n"
- "Error occurred near line 1, position 4: {% ASD %}");
+ "Error occurred near line 1, position 4:\n"
+ "{% ASD %}\n"
+ " ^");
blogc_error_free(err);
a = "{%-- block entry %}\n";
err = NULL;
@@ -465,7 +467,9 @@ test_template_parse_invalid_block_start(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid statement syntax. Duplicated whitespace cleaner before statement.\n"
- "Error occurred near line 1, position 4: {%-- block entry %}");
+ "Error occurred near line 1, position 4:\n"
+ "{%-- block entry %}\n"
+ " ^");
blogc_error_free(err);
a = "{% block entry --%}\n";
err = NULL;
@@ -475,7 +479,9 @@ test_template_parse_invalid_block_start(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid statement syntax. Duplicated whitespace cleaner after statement.\n"
- "Error occurred near line 1, position 17: {% block entry --%}");
+ "Error occurred near line 1, position 17:\n"
+ "{% block entry --%}\n"
+ " ^");
blogc_error_free(err);
}
@@ -493,7 +499,9 @@ test_template_parse_invalid_block_nested(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Blocks can't be nested.\n"
- "Error occurred near line 2, position 9: {% block listing %}");
+ "Error occurred near line 2, position 9:\n"
+ "{% block listing %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -511,7 +519,9 @@ test_template_parse_invalid_foreach_nested(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"'foreach' statements can't be nested.\n"
- "Error occurred near line 2, position 11: {% foreach B %}");
+ "Error occurred near line 2, position 11:\n"
+ "{% foreach B %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -527,7 +537,9 @@ test_template_parse_invalid_block_not_open(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"'endblock' statement without an open 'block' statement.\n"
- "Error occurred near line 1, position 12: {% endblock %}");
+ "Error occurred near line 1, position 12:\n"
+ "{% endblock %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -543,8 +555,9 @@ test_template_parse_invalid_endif_not_open(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"'endif' statement without an open 'if', 'ifdef' or 'ifndef' statement.\n"
- "Error occurred near line 1, position 28: "
- "{% block listing %}{% endif %}{% endblock %}");
+ "Error occurred near line 1, position 28:\n"
+ "{% block listing %}{% endif %}{% endblock %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -560,7 +573,9 @@ test_template_parse_invalid_endforeach_not_open(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"'endforeach' statement without an open 'foreach' statement.\n"
- "Error occurred near line 1, position 14: {% endforeach %}");
+ "Error occurred near line 1, position 14:\n"
+ "{% endforeach %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -577,7 +592,9 @@ test_template_parse_invalid_block_name(void **state)
assert_string_equal(err->msg,
"Invalid statement type: Allowed types are: 'block', 'endblock', 'ifdef', "
"'ifndef', 'else', 'endif', 'foreach' and 'endforeach'.\n"
- "Error occurred near line 1, position 10: {% chunda %}");
+ "Error occurred near line 1, position 10:\n"
+ "{% chunda %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -593,7 +610,9 @@ test_template_parse_invalid_block_type_start(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid block syntax. Must begin with lowercase letter.\n"
- "Error occurred near line 1, position 10: {% block ENTRY %}");
+ "Error occurred near line 1, position 10:\n"
+ "{% block ENTRY %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -609,7 +628,9 @@ test_template_parse_invalid_block_type(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid block type. Allowed types are: 'entry', 'listing' and 'listing_once'.\n"
- "Error occurred near line 1, position 16: {% block chunda %}");
+ "Error occurred near line 1, position 16:\n"
+ "{% block chunda %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -625,8 +646,9 @@ test_template_parse_invalid_ifdef_start(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid variable name. Must begin with uppercase letter.\n"
- "Error occurred near line 1, position 27: "
- "{% block entry %}{% ifdef guda %}");
+ "Error occurred near line 1, position 27:\n"
+ "{% block entry %}{% ifdef guda %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -642,8 +664,9 @@ test_template_parse_invalid_foreach_start(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid foreach variable name. Must begin with uppercase letter.\n"
- "Error occurred near line 1, position 29: "
- "{% block entry %}{% foreach guda %}");
+ "Error occurred near line 1, position 29:\n"
+ "{% block entry %}{% foreach guda %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -659,8 +682,9 @@ test_template_parse_invalid_ifdef_variable(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid variable name. Must be uppercase letter, number or '_'.\n"
- "Error occurred near line 1, position 28: "
- "{% block entry %}{% ifdef BoLA %}");
+ "Error occurred near line 1, position 28:\n"
+ "{% block entry %}{% ifdef BoLA %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -676,8 +700,9 @@ test_template_parse_invalid_ifdef_variable2(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid variable name. Must begin with uppercase letter.\n"
- "Error occurred near line 1, position 27: "
- "{% block entry %}{% ifdef 0123 %}");
+ "Error occurred near line 1, position 27:\n"
+ "{% block entry %}{% ifdef 0123 %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -693,8 +718,9 @@ test_template_parse_invalid_foreach_variable(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid foreach variable name. Must be uppercase letter, number or '_'.\n"
- "Error occurred near line 1, position 30: "
- "{% block entry %}{% foreach BoLA %}");
+ "Error occurred near line 1, position 30:\n"
+ "{% block entry %}{% foreach BoLA %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -710,8 +736,9 @@ test_template_parse_invalid_foreach_variable2(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid foreach variable name. Must begin with uppercase letter.\n"
- "Error occurred near line 1, position 29: {% block entry %}"
- "{% foreach 0123 %}");
+ "Error occurred near line 1, position 29:\n"
+ "{% block entry %}{% foreach 0123 %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -727,8 +754,9 @@ test_template_parse_invalid_if_operator(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid 'if' operator. Must be '<', '>', '<=', '>=', '==' or '!='.\n"
- "Error occurred near line 1, position 29: "
- "{% block entry %}{% if BOLA = \"asd\" %}");
+ "Error occurred near line 1, position 29:\n"
+ "{% block entry %}{% if BOLA = \"asd\" %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -744,8 +772,9 @@ test_template_parse_invalid_if_operand(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid 'if' operand. Must be double-quoted static string or variable.\n"
- "Error occurred near line 1, position 32: "
- "{% block entry %}{% if BOLA == asd %}");
+ "Error occurred near line 1, position 32:\n"
+ "{% block entry %}{% if BOLA == asd %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -761,8 +790,9 @@ test_template_parse_invalid_if_operand2(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Found an open double-quoted string.\n"
- "Error occurred near line 1, position 31: "
- "{% block entry %}{% if BOLA == \"asd %}");
+ "Error occurred near line 1, position 32:\n"
+ "{% block entry %}{% if BOLA == \"asd %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -778,8 +808,9 @@ test_template_parse_invalid_if_operand3(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid 'if' operand. Must be double-quoted static string or variable.\n"
- "Error occurred near line 1, position 32: "
- "{% block entry %}{% if BOLA == 0123 %}");
+ "Error occurred near line 1, position 32:\n"
+ "{% block entry %}{% if BOLA == 0123 %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -795,7 +826,9 @@ test_template_parse_invalid_else1(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"'else' statement without an open 'if', 'ifdef' or 'ifndef' statement.\n"
- "Error occurred near line 1, position 8: {% else %}");
+ "Error occurred near line 1, position 8:\n"
+ "{% else %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -811,8 +844,9 @@ test_template_parse_invalid_else2(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"More than one 'else' statement for an open 'if', 'ifdef' or 'ifndef' "
- "statement.\nError occurred near line 1, position 60: {% if BOLA == \"123\" "
- "%}{% if GUDA == \"1\" %}{% else %}{% else %}");
+ "statement.\nError occurred near line 1, position 60:\n"
+ "{% if BOLA == \"123\" %}{% if GUDA == \"1\" %}{% else %}{% else %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -835,7 +869,9 @@ test_template_parse_invalid_else3(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"More than one 'else' statement for an open 'if', 'ifdef' or 'ifndef' "
- "statement.\nError occurred near line 7, position 8: {% else %}");
+ "statement.\nError occurred near line 7, position 8:\n"
+ "{% else %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -851,7 +887,9 @@ test_template_parse_invalid_block_end(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid statement syntax. Must end with '%}'.\n"
- "Error occurred near line 1, position 16: {% block entry }}");
+ "Error occurred near line 1, position 16:\n"
+ "{% block entry }}\n"
+ " ^");
blogc_error_free(err);
}
@@ -867,8 +905,9 @@ test_template_parse_invalid_variable_name(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid variable name. Must begin with uppercase letter.\n"
- "Error occurred near line 1, position 21: "
- "{% block entry %}{{ bola }}{% endblock %}");
+ "Error occurred near line 1, position 21:\n"
+ "{% block entry %}{{ bola }}{% endblock %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -884,8 +923,9 @@ test_template_parse_invalid_variable_name2(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid variable name. Must be uppercase letter, number or '_'.\n"
- "Error occurred near line 1, position 22: "
- "{% block entry %}{{ Bola }}{% endblock %}");
+ "Error occurred near line 1, position 22:\n"
+ "{% block entry %}{{ Bola }}{% endblock %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -901,8 +941,9 @@ test_template_parse_invalid_variable_name3(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid variable name. Must begin with uppercase letter.\n"
- "Error occurred near line 1, position 21: {% block entry %}{{ 0123 }}"
- "{% endblock %}");
+ "Error occurred near line 1, position 21:\n"
+ "{% block entry %}{{ 0123 }}{% endblock %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -918,8 +959,9 @@ test_template_parse_invalid_variable_end(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid statement syntax. Must end with '}}'.\n"
- "Error occurred near line 1, position 26: "
- "{% block entry %}{{ BOLA %}{% endblock %}");
+ "Error occurred near line 1, position 26:\n"
+ "{% block entry %}{{ BOLA %}{% endblock %}\n"
+ " ^");
blogc_error_free(err);
}
@@ -935,7 +977,9 @@ test_template_parse_invalid_close(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid statement syntax. Must end with '}'.\n"
- "Error occurred near line 1, position 17: {% block entry %%");
+ "Error occurred near line 1, position 17:\n"
+ "{% block entry %%\n"
+ " ^");
blogc_error_free(err);
}
@@ -951,8 +995,9 @@ test_template_parse_invalid_close2(void **state)
assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);
assert_string_equal(err->msg,
"Invalid statement syntax. Must end with '}'.\n"
- "Error occurred near line 1, position 27: "
- "{% block entry %}{{ BOLA }%{% endblock %}");
+ "Error occurred near line 1, position 27:\n"
+ "{% block entry %}{{ BOLA }%{% endblock %}\n"
+ " ^");
blogc_error_free(err);
}