diff options
| -rw-r--r-- | src/error.c | 50 | ||||
| -rw-r--r-- | tests/check_error.c | 40 | ||||
| -rw-r--r-- | tests/check_source_parser.c | 18 | ||||
| -rw-r--r-- | tests/check_template_parser.c | 47 | 
4 files changed, 117 insertions, 38 deletions
diff --git a/src/error.c b/src/error.c index ad4e3f4..d3d045d 100644 --- a/src/error.c +++ b/src/error.c @@ -50,26 +50,54 @@ blogc_error_parser(blogc_error_type_t type, const char *src, size_t src_len,      char *msg = b_strdup_vprintf(format, ap);      va_end(ap); -    b_string_t *str = b_string_new(); -    while (current < src_len) { -        char c = src[current]; - -        if (c == '\r' || c == '\n') +    size_t lineno = 1; +    size_t linestart = 0; +    size_t lineend = 0; +    size_t pos = 1; + +    for (size_t i = 0; i < src_len; i++) { +        char c = src[i]; +        if (i < current) { +            if ((i + 1) < src_len) { +                if ((c == '\n' && src[i + 1] == '\r') || +                    (c == '\r' && src[i + 1] == '\n')) +                { +                    lineno++; +                    pos = 1; +                    c = src[++i]; +                    if ((i + 1) < src_len) +                        linestart = i + 1; +                    continue; +                } +            } +            if (c == '\n' || c == '\r') { +                lineno++; +                pos = 1; +                if ((i + 1) < src_len) +                    linestart = i + 1; +                continue; +            } +            pos++; +        } +        else if (c == '\n' || c == '\r') { +            lineend = i;              break; +        } +    } -        b_string_append_c(str, c); +    if (lineend <= linestart && src_len >= linestart) +        lineend = src_len; -        current++; -    } -    char *line = b_string_free(str, false); +    char *line = b_strndup(src + linestart, lineend - linestart);      blogc_error_t *rv = NULL; -    if (strlen(line) == 0)  // "near to" message isn't useful if line is empty +    if (line[0] == '\0')  // "near" message isn't useful if line is empty          rv = blogc_error_new(type, msg);      else          rv = blogc_error_new_printf(type, -            "%s\nError occurred near to '%s'", msg, line); +            "%s\nError occurred near line %d, position %d: %s", msg, lineno, +            pos, line);      free(msg);      free(line); diff --git a/tests/check_error.c b/tests/check_error.c index 68f287a..17e1c40 100644 --- a/tests/check_error.c +++ b/tests/check_error.c @@ -48,7 +48,28 @@ test_error_parser(void **state)      blogc_error_t *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 to 'hunda'"); +    assert_string_equal(error->msg, +        "asd 10\nError occurred near line 3, position 2: chunda"); +    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"); +    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"); +    blogc_error_free(error); +    a = ""; +    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");      blogc_error_free(error);  } @@ -60,7 +81,22 @@ test_error_parser_crlf(void **state)      blogc_error_t *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 to 'hunda'"); +    assert_string_equal(error->msg, +        "asd 10\nError occurred near line 3, position 2: chunda"); +    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"); +    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");      blogc_error_free(error);  } diff --git a/tests/check_source_parser.c b/tests/check_source_parser.c index 810786b..4d8518e 100644 --- a/tests/check_source_parser.c +++ b/tests/check_source_parser.c @@ -183,7 +183,7 @@ 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 to 'bola: guda'"); +        "Error occurred near line 1, position 1: bola: guda");      blogc_error_free(err);      b_trie_free(source);  } @@ -199,7 +199,7 @@ 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 to 'a'"); +        "Error occurred near line 1, position 4: BOLa");      blogc_error_free(err);      b_trie_free(source);  } @@ -214,7 +214,8 @@ test_source_parse_config_no_key2(void **state)      assert_non_null(err);      assert_int_equal(err->type, BLOGC_ERROR_SOURCE_PARSER);      assert_string_equal(err->msg, -        "Your last configuration key is missing ':' and the value"); +        "Your last configuration key is missing ':' and the value\n" +        "Error occurred near line 1, position 5: BOLA");      blogc_error_free(err);      b_trie_free(source);  } @@ -230,7 +231,8 @@ test_source_parse_config_no_value(void **state)      assert_non_null(err);      assert_int_equal(err->type, BLOGC_ERROR_SOURCE_PARSER);      assert_string_equal(err->msg, -        "Configuration value not provided for 'BOLA'."); +        "Configuration value not provided for 'BOLA'.\n" +        "Error occurred near line 1, position 6: BOLA:");      blogc_error_free(err);      b_trie_free(source);  } @@ -246,7 +248,8 @@ test_source_parse_config_no_value2(void **state)      assert_non_null(err);      assert_int_equal(err->type, BLOGC_ERROR_SOURCE_PARSER);      assert_string_equal(err->msg, -        "Configuration value not provided for 'BOLA'."); +        "Configuration value not provided for 'BOLA'.\n" +        "Error occurred near line 1, position 6: BOLA:");      blogc_error_free(err);      b_trie_free(source);  } @@ -449,7 +452,8 @@ test_source_parse_config_value_no_line_ending(void **state)      assert_non_null(err);      assert_int_equal(err->type, BLOGC_ERROR_SOURCE_PARSER);      assert_string_equal(err->msg, -        "No line ending after the configuration value for 'BOLA'."); +        "No line ending after the configuration value for 'BOLA'.\n" +        "Error occurred near line 1, position 10: BOLA: asd");      blogc_error_free(err);      b_trie_free(source);  } @@ -466,7 +470,7 @@ 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 to '#'"); +        "Error occurred near line 2, position 4: ---#");      blogc_error_free(err);      b_trie_free(source);  } diff --git a/tests/check_template_parser.c b/tests/check_template_parser.c index df5dc4c..94f669b 100644 --- a/tests/check_template_parser.c +++ b/tests/check_template_parser.c @@ -359,7 +359,7 @@ 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 to 'ASD %}'"); +        "Error occurred near line 1, position 4: {% ASD %}");      blogc_error_free(err);  } @@ -377,7 +377,7 @@ 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 to ' listing %}'"); +        "Error occurred near line 2, position 9: {% block listing %}");      blogc_error_free(err);  } @@ -393,7 +393,7 @@ 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 to ' %}'"); +        "Error occurred near line 1, position 12: {% endblock %}");      blogc_error_free(err);  } @@ -409,7 +409,8 @@ 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 'ifdef' or 'ifndef' statement.\n" -        "Error occurred near to ' %}{% endblock %}'"); +        "Error occurred near line 1, position 28: " +        "{% block listing %}{% endif %}{% endblock %}");      blogc_error_free(err);  } @@ -425,7 +426,8 @@ test_template_parse_invalid_block_name(void **state)      assert_int_equal(err->type, BLOGC_ERROR_TEMPLATE_PARSER);      assert_string_equal(err->msg,          "Invalid statement type: Allowed types are: 'block', 'endblock', 'ifdef', " -        "'ifndef' and 'endif'.\nError occurred near to ' %}'"); +        "'ifndef' and 'endif'.\n" +        "Error occurred near line 1, position 10: {% chunda %}");      blogc_error_free(err);  } @@ -441,7 +443,7 @@ 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 to 'ENTRY %}'"); +        "Error occurred near line 1, position 10: {% block ENTRY %}");      blogc_error_free(err);  } @@ -457,7 +459,7 @@ 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 to ' %}'"); +        "Error occurred near line 1, position 16: {% block chunda %}");      blogc_error_free(err);  } @@ -473,7 +475,8 @@ 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 to 'guda %}'"); +        "Error occurred near line 1, position 27: " +        "{% block entry %}{% ifdef guda %}");      blogc_error_free(err);  } @@ -489,7 +492,8 @@ 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 to 'oLA %}'"); +        "Error occurred near line 1, position 28: " +        "{% block entry %}{% ifdef BoLA %}");      blogc_error_free(err);  } @@ -505,7 +509,8 @@ 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 to '= \"asd\" %}'"); +        "Error occurred near line 1, position 29: " +        "{% block entry %}{% if BOLA = \"asd\" %}");      blogc_error_free(err);  } @@ -521,7 +526,8 @@ 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.\n" -        "Error occurred near to 'asd %}'"); +        "Error occurred near line 1, position 32: " +        "{% block entry %}{% if BOLA == asd %}");      blogc_error_free(err);  } @@ -537,7 +543,8 @@ 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 to '\"asd %}'"); +        "Error occurred near line 1, position 32: " +        "{% block entry %}{% if BOLA == \"asd %}");      blogc_error_free(err);  } @@ -553,7 +560,7 @@ 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 to '}}'"); +        "Error occurred near line 1, position 16: {% block entry }}");      blogc_error_free(err);  } @@ -569,7 +576,8 @@ 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 to 'bola }}{% endblock %}'"); +        "Error occurred near line 1, position 21: " +        "{% block entry %}{{ bola }}{% endblock %}");      blogc_error_free(err);  } @@ -585,7 +593,8 @@ 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 to 'ola }}{% endblock %}'"); +        "Error occurred near line 1, position 22: " +        "{% block entry %}{{ Bola }}{% endblock %}");      blogc_error_free(err);  } @@ -601,7 +610,8 @@ 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 to '%}{% endblock %}'"); +        "Error occurred near line 1, position 26: " +        "{% block entry %}{{ BOLA %}{% endblock %}");      blogc_error_free(err);  } @@ -617,7 +627,7 @@ 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 to '%'"); +        "Error occurred near line 1, position 17: {% block entry %%");      blogc_error_free(err);  } @@ -633,7 +643,8 @@ 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 to '%{% endblock %}'"); +        "Error occurred near line 1, position 27: " +        "{% block entry %}{{ BOLA }%{% endblock %}");      blogc_error_free(err);  }  | 
