diff options
| -rw-r--r-- | Makefile.am | 6 | ||||
| -rw-r--r-- | src/error.c | 116 | ||||
| -rw-r--r-- | src/error.h | 34 | ||||
| -rw-r--r-- | src/loader.c | 104 | ||||
| -rw-r--r-- | src/loader.h | 22 | ||||
| -rw-r--r-- | src/main.c | 98 | ||||
| -rw-r--r-- | src/output.c | 39 | ||||
| -rw-r--r-- | src/output.h | 17 | ||||
| -rw-r--r-- | src/source-parser.c | 37 | ||||
| -rw-r--r-- | src/source-parser.h | 6 | ||||
| -rw-r--r-- | src/template-parser.c | 87 | ||||
| -rw-r--r-- | src/template-parser.h | 4 | ||||
| -rw-r--r-- | tests/check_source_parser.c | 9 | ||||
| -rw-r--r-- | tests/check_template_parser.c | 9 | 
14 files changed, 489 insertions, 99 deletions
diff --git a/Makefile.am b/Makefile.am index e639307..3b15057 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,7 +20,8 @@ CLEANFILES = \  	$(NULL)  noinst_HEADERS = \ -	src/output.h \ +	src/error.h \ +	src/loader.h \  	src/source-parser.h \  	src/template-parser.h \  	src/utils/utils.h \ @@ -42,7 +43,8 @@ check_PROGRAMS = \  libblogc_la_SOURCES = \ -	src/output.c \ +	src/error.c \ +	src/loader.c \  	src/source-parser.c \  	src/template-parser.c \  	src/utils/slist.c \ diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..8475d66 --- /dev/null +++ b/src/error.c @@ -0,0 +1,116 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include "utils/utils.h" +#include "error.h" + + +blogc_error_t* +blogc_error_new(blogc_error_type_t type, const char *msg) +{ +    blogc_error_t *err = malloc(sizeof(blogc_error_t)); +    err->type = type; +    err->msg = b_strdup(msg); +    return err; +} + + +blogc_error_t* +blogc_error_new_printf(blogc_error_type_t type, const char *format, ...) +{ +    va_list ap; +    va_start(ap, format); +    char *tmp = b_strdup_vprintf(format, ap); +    va_end(ap); +    blogc_error_t *rv = blogc_error_new(type, tmp); +    free(tmp); +    return rv; +} + + +blogc_error_t* +blogc_error_parser(blogc_error_type_t type, const char *src, size_t src_len, +    size_t current, const char *format, ...) +{ +    va_list ap; +    va_start(ap, format); +    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') +            break; + +        b_string_append_c(str, c); + +        current++; +    } +    char *line = b_string_free(str, false); + +    blogc_error_t *rv = NULL; + +    if (strlen(line) == 0)  // "near to" 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); + +    free(msg); +    free(line); + +    return rv; +} + + +void +blogc_error_print(blogc_error_t *err) +{ +    if (err == NULL) +        return; + +    char *tmp = NULL; + +    switch(err->type) { +        case BLOGC_ERROR_SOURCE_PARSER: +            tmp = b_strdup("Source parser error"); +            break; +        case BLOGC_ERROR_TEMPLATE_PARSER: +            tmp = b_strdup("Template parser error"); +            break; +        case BLOGC_ERROR_LOADER: +            tmp = b_strdup("Loader error"); +            break; +        default: +            tmp = b_strdup("Unknown error"); +    } + +    fprintf(stderr, "%s: %s\n", tmp, err->msg); + +    free(tmp); +} + + +void +blogc_error_free(blogc_error_t *err) +{ +    if (err == NULL) +        return; +    free(err->msg); +    free(err); +} diff --git a/src/error.h b/src/error.h new file mode 100644 index 0000000..98aeeb9 --- /dev/null +++ b/src/error.h @@ -0,0 +1,34 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file COPYING. + */ + +#ifndef _ERROR_H +#define _ERROR_H + +#include <stdlib.h> +#include <stdarg.h> +#include "utils/utils.h" + +typedef enum { +    BLOGC_ERROR_SOURCE_PARSER = 1, +    BLOGC_ERROR_TEMPLATE_PARSER, +    BLOGC_ERROR_LOADER, +} blogc_error_type_t; + +typedef struct { +    char *msg; +    blogc_error_type_t type; +} blogc_error_t; + +blogc_error_t* blogc_error_new(blogc_error_type_t type, const char *msg); +blogc_error_t* blogc_error_new_printf(blogc_error_type_t type, const char *format, ...); +blogc_error_t* blogc_error_parser(blogc_error_type_t type, const char *src, +    size_t src_len, size_t current, const char *format, ...); +void blogc_error_print(blogc_error_t *err); +void blogc_error_free(blogc_error_t *err); + +#endif /* _ERROR_H */ diff --git a/src/loader.c b/src/loader.c new file mode 100644 index 0000000..35ecdcf --- /dev/null +++ b/src/loader.c @@ -0,0 +1,104 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include "utils/utils.h" +#include "source-parser.h" +#include "template-parser.h" +#include "loader.h" +#include "error.h" + + +char* +blogc_file_get_contents(const char *path, size_t *len, blogc_error_t **err) +{ +    if (err == NULL || *err != NULL) +        return NULL; + +    *len = 0; +    FILE *fp = fopen(path, "r"); + +    if (fp == NULL) { +        int tmp_errno = errno; +        *err = blogc_error_new_printf(BLOGC_ERROR_LOADER, +            "Failed to open file (%s): %s", path, strerror(tmp_errno)); +        return NULL; +    } + +    b_string_t *str = b_string_new(); +    char buffer[BLOGC_FILE_CHUNK_SIZE]; + +    while (!feof(fp)) { +        size_t read_len = fread(buffer, sizeof(char), BLOGC_FILE_CHUNK_SIZE, fp); +        *len += read_len; +        b_string_append_len(str, buffer, read_len); +    } +    fclose(fp); +    return b_string_free(str, false); +} + + +b_slist_t* +blogc_template_parse_from_file(const char *f, blogc_error_t **err) +{ +    if (err == NULL || *err != NULL) +        return NULL; +    size_t len; +    char *s = blogc_file_get_contents(f, &len, err); +    if (s == NULL) +        return NULL; +    b_slist_t *rv = blogc_template_parse(s, len, err); +    free(s); +    return rv; +} + + +blogc_source_t* +blogc_source_parse_from_file(const char *f, blogc_error_t **err) +{ +    if (err == NULL || *err != NULL) +        return NULL; +    size_t len; +    char *s = blogc_file_get_contents(f, &len, err); +    if (s == NULL) +        return NULL; +    blogc_source_t *rv = blogc_source_parse(s, len, err); +    free(s); +    return rv; +} + + +b_slist_t* +blogc_source_parse_from_files(b_slist_t *l, blogc_error_t **err) +{ +    blogc_error_t *tmp_err = NULL; +    b_slist_t *rv = NULL; + +    for (b_slist_t *tmp = l; tmp != NULL; tmp = tmp->next) { +        char *f = tmp->data; +        blogc_source_t *s = blogc_source_parse_from_file(f, &tmp_err); +        if (s == NULL) { +            *err = blogc_error_new_printf(BLOGC_ERROR_LOADER, +                "An error occurred while parsing source file: %s\n\n%s", +                f, tmp_err->msg); +            blogc_error_free(tmp_err); +            tmp_err = NULL; +            b_slist_free_full(rv, blogc_source_free); +            rv = NULL; +            break; +        } +        rv = b_slist_append(rv, s); +    } +    return rv; +} diff --git a/src/loader.h b/src/loader.h new file mode 100644 index 0000000..42a0abf --- /dev/null +++ b/src/loader.h @@ -0,0 +1,22 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> + * + * This program can be distributed under the terms of the BSD License. + * See the file COPYING. + */ + +#ifndef _LOADER_H +#define _LOADER_H + +#include "utils/utils.h" +#include "error.h" + +#define BLOGC_FILE_CHUNK_SIZE 1024 + +char* blogc_file_get_contents(const char *path, size_t *len, blogc_error_t **err); +b_slist_t* blogc_template_parse_from_file(const char *f, blogc_error_t **err); +blogc_source_t* blogc_source_parse_from_file(const char *f, blogc_error_t **err); +b_slist_t* blogc_source_parse_from_files(b_slist_t *l, blogc_error_t **err); + +#endif /* _LOADER_H */ @@ -10,16 +10,108 @@  #include <config.h>  #endif /* HAVE_CONFIG_H */ +#include <stdbool.h>  #include <stdio.h> +#include <string.h> +#include "utils/utils.h"  #include "source-parser.h"  #include "template-parser.h" -#include <string.h> +#include "loader.h" +#include "error.h" + + +static void +blogc_print_help(void) +{ +    printf( +        "usage:\n" +        "    blogc [-h] -t TEMPLATE [-o OUTPUT] SOURCE [SOURCE ...] - A blog compiler.\n" +        "\n" +        "positional arguments:\n" +        "    SOURCE       source file(s)\n" +        "\n" +        "optional arguments:\n" +        "    -h, --help   show this help message and exit\n" +        "    -t TEMPLATE  template file\n" +        "    -o OUTPUT    output file\n"); +} + + +static void +blogc_print_usage(void) +{ +    printf("usage: blogc [-h] -t TEMPLATE [-o OUTPUT] SOURCE [SOURCE ...]\n"); +}  int  main(int argc, char **argv)  { -    printf("Hello, World!\n"); -    return 0; +    int rv = 0; + +    char *template = NULL; +    char *output = NULL; +    b_slist_t *sources = NULL; + +    for (int i = 1; i < argc; i++) { +        if (argv[i][0] == '-') { +            switch (argv[i][1]) { +                case 'h': +                    blogc_print_help(); +                    goto cleanup; +                case 't': +                    if (i + 1 < argc) +                        template = b_strdup(argv[++i]); +                    break; +                case 'o': +                    if (i + 1 < argc) +                        output = b_strdup(argv[++i]); +                    break; +            } +        } +        else +            sources = b_slist_append(sources, b_strdup(argv[i])); +    } + +    if (template == NULL) { +        blogc_print_usage(); +        fprintf(stderr, "blogc: error: argument -t is required\n"); +        rv = 2; +        goto cleanup; +    } + +    if (b_slist_length(sources) == 0) { +        blogc_print_usage(); +        fprintf(stderr, "blogc: error: at least one source file is required\n"); +        rv = 2; +        goto cleanup; +    } + +    blogc_error_t *err = NULL; + +    b_slist_t* l = blogc_template_parse_from_file(template, &err); +    if (err != NULL) { +        blogc_error_print(err); +        goto cleanup2; +    } + +    b_slist_t *s = blogc_source_parse_from_files(sources, &err); +    if (err != NULL) { +        blogc_error_print(err); +        goto cleanup3; +    } + +    printf("%d\n", s == NULL); + +cleanup3: +    b_slist_free_full(s, blogc_source_free); +cleanup2: +    blogc_template_free_stmts(l); +    blogc_error_free(err); +cleanup: +    free(template); +    free(output); +    b_slist_free_full(sources, free); +    return rv;  } diff --git a/src/output.c b/src/output.c deleted file mode 100644 index 1664afe..0000000 --- a/src/output.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * blogc: A blog compiler. - * Copyright (C) 2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> - * - * This program can be distributed under the terms of the BSD License. - * See the file COPYING. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif /* HAVE_CONFIG_H */ - -#include <stdio.h> -#include "utils/utils.h" -#include "output.h" - - -void -blogc_parser_syntax_error(const char *name, const char *src, size_t src_len, -    size_t current) -{ -    b_string_t *msg = b_string_new(); - -    while (current < src_len) { -        char c = src[current]; - -        if (c == '\r' || c == '\n') -            break; - -        b_string_append_c(msg, c); - -        current++; -    } - -    fprintf(stderr, "%s parser error: failed to parse input near \"%s\".\n", name, -        msg->str); - -    b_string_free(msg, true); -} diff --git a/src/output.h b/src/output.h deleted file mode 100644 index 6995324..0000000 --- a/src/output.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * blogc: A blog compiler. - * Copyright (C) 2015 Rafael G. Martins <rafael@rafaelmartins.eng.br> - * - * This program can be distributed under the terms of the BSD License. - * See the file COPYING. - */ - -#ifndef _OUTPUT_H -#define _OUTPUT_H - -#include <stdlib.h> - -void blogc_parser_syntax_error(const char *name, const char *src, -    size_t src_len, size_t current); - -#endif /* _OUTPUT_H */ diff --git a/src/source-parser.c b/src/source-parser.c index ad7e77d..7cace0c 100644 --- a/src/source-parser.c +++ b/src/source-parser.c @@ -14,7 +14,7 @@  #include "utils/utils.h"  #include "source-parser.h" -#include "output.h" +#include "error.h"  typedef enum { @@ -29,12 +29,14 @@ typedef enum {  blogc_source_t* -blogc_source_parse(const char *src, size_t src_len) +blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err)  { +    if (err == NULL || *err != NULL) +        return NULL; +      size_t current = 0;      size_t start = 0; -    bool error = false;      char *key = NULL;      char *tmp = NULL;      b_trie_t *config = b_trie_new(free); @@ -59,7 +61,9 @@ blogc_source_parse(const char *src, size_t src_len)                      state = SOURCE_SEPARATOR;                      break;                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_SOURCE_PARSER, src, src_len, +                    current, +                    "Can't find a configuration key or the content separator.");                  break;              case SOURCE_CONFIG_KEY: @@ -70,7 +74,8 @@ blogc_source_parse(const char *src, size_t src_len)                      state = SOURCE_CONFIG_VALUE_START;                      break;                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_SOURCE_PARSER, src, src_len, +                    current, "Invalid configuration key.");                  break;              case SOURCE_CONFIG_VALUE_START: @@ -79,7 +84,9 @@ blogc_source_parse(const char *src, size_t src_len)                      start = current;                      break;                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_SOURCE_PARSER, src, src_len, +                    current, "Configuration value not provided for '%s'.", +                    key);                  break;              case SOURCE_CONFIG_VALUE: @@ -100,7 +107,9 @@ blogc_source_parse(const char *src, size_t src_len)                      state = SOURCE_CONTENT_START;                      break;                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_SOURCE_PARSER, src, src_len, +                    current, +                    "Invalid content separator. Must be one or more '-' characters.");                  break;              case SOURCE_CONTENT_START: @@ -114,17 +123,16 @@ blogc_source_parse(const char *src, size_t src_len)                  break;          } -        if (error) +        if (*err != NULL)              break;          current++;      } -    if (error) { +    if (*err != NULL) {          free(key);          free(content);          b_trie_free(config); -        blogc_parser_syntax_error("source", src, src_len, current);          return NULL;      } @@ -137,11 +145,12 @@ blogc_source_parse(const char *src, size_t src_len)  void -blogc_source_free(blogc_source_t *source) +blogc_source_free(void *source)  {      if (source == NULL)          return; -    free(source->content); -    b_trie_free(source->config); -    free(source); +    blogc_source_t *s = source; +    free(s->content); +    b_trie_free(s->config); +    free(s);  } diff --git a/src/source-parser.h b/src/source-parser.h index e33a7d4..c816e5b 100644 --- a/src/source-parser.h +++ b/src/source-parser.h @@ -11,13 +11,15 @@  #include <stdlib.h>  #include "utils/utils.h" +#include "error.h"  typedef struct {      b_trie_t *config;      char *content;  } blogc_source_t; -blogc_source_t* blogc_source_parse(const char *src, size_t src_len); -void blogc_source_free(blogc_source_t *source); +blogc_source_t* blogc_source_parse(const char *src, size_t src_len, +    blogc_error_t **err); +void blogc_source_free(void *source);  #endif /* _SOURCE_PARSER_H */ diff --git a/src/template-parser.c b/src/template-parser.c index 54dc642..1038190 100644 --- a/src/template-parser.c +++ b/src/template-parser.c @@ -15,7 +15,7 @@  #include "utils/utils.h"  #include "template-parser.h" -#include "output.h" +#include "error.h"  typedef enum { @@ -44,13 +44,15 @@ typedef enum {  b_slist_t* -blogc_template_parse(const char *src, size_t src_len) +blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err)  { +    if (err == NULL || *err != NULL) +        return NULL; +      size_t current = 0;      size_t start = 0;      size_t end = 0; -    bool error = false;      char *tmp = NULL;      unsigned int if_count = 0; @@ -95,7 +97,11 @@ blogc_template_parse(const char *src, size_t src_len)                          stmts = b_slist_append(stmts, stmt);                          stmt = NULL;                      } +                    break;                  } +                *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, +                    src_len, current, +                    "Invalid statement syntax. Must be '%%' or '{'.");                  break;              case TEMPLATE_BLOCK_START: @@ -106,7 +112,9 @@ blogc_template_parse(const char *src, size_t src_len)                      start = current;                      break;                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, +                    src_len, current, +                    "Invalid statement syntax. Must begin lowercase letter.");                  break;              case TEMPLATE_BLOCK_TYPE: @@ -120,6 +128,9 @@ blogc_template_parse(const char *src, size_t src_len)                              start = current;                              break;                          } +                        *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, +                            src, src_len, current, "Blocks can't be nested."); +                        break;                      }                      else if (0 == strncmp("endblock", src + start, current - start)) {                          if (block_state != BLOCK_CLOSED) { @@ -128,6 +139,10 @@ blogc_template_parse(const char *src, size_t src_len)                              block_state = BLOCK_CLOSED;                              break;                          } +                        *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, +                            src, src_len, current, +                            "'endblock' statement without an open 'block' statement."); +                        break;                      }                      else if (0 == strncmp("if", src + start, current - start)) {                          if (block_state == BLOCK_SINGLE_SOURCE || block_state == BLOCK_MULTIPLE_SOURCES) { @@ -137,6 +152,11 @@ blogc_template_parse(const char *src, size_t src_len)                              if_count++;                              break;                          } +                        *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, +                            src, src_len, current, +                            "'if' statements only allowed inside 'single_source' " +                            "and 'multiple_sources' blocks."); +                        break;                      }                      else if (0 == strncmp("endif", src + start, current - start)) {                          if (block_state == BLOCK_SINGLE_SOURCE || block_state == BLOCK_MULTIPLE_SOURCES) { @@ -146,10 +166,21 @@ blogc_template_parse(const char *src, size_t src_len)                                  if_count--;                                  break;                              } +                            *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, +                                src, src_len, current, +                                "'endif' statement without an open 'if' statement."); +                            break;                          } +                        *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, +                            src, src_len, current, +                            "'endif' statements only allowed inside 'single_source' " +                            "and 'multiple_sources' blocks."); +                        break;                      }                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, +                    src_len, current, +                    "Invalid statement type: Allowed types are: block, endblock, if, endif.");                  break;              case TEMPLATE_BLOCK_BLOCK_TYPE_START: @@ -160,7 +191,9 @@ blogc_template_parse(const char *src, size_t src_len)                      start = current;                      break;                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, +                    src_len, current, +                    "Invalid block syntax. Must begin with lowercase letter.");                  break;              case TEMPLATE_BLOCK_BLOCK_TYPE: @@ -186,7 +219,9 @@ blogc_template_parse(const char *src, size_t src_len)                          break;                      }                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, +                    src_len, current, +                    "Invalid block type. Allowed types are: single_source, multiple_sources, multiple_sources_once.");                  break;              case TEMPLATE_BLOCK_IF_VARIABLE_START: @@ -197,7 +232,9 @@ blogc_template_parse(const char *src, size_t src_len)                      start = current;                      break;                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, +                    src_len, current, +                    "Invalid variable name. Must begin with uppercase letter.");                  break;              case TEMPLATE_BLOCK_IF_VARIABLE: @@ -208,7 +245,9 @@ blogc_template_parse(const char *src, size_t src_len)                      state = TEMPLATE_BLOCK_END;                      break;                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, +                    src_len, current, +                    "Invalid variable name. Must be uppercase letter, number or '_'.");                  break;              case TEMPLATE_BLOCK_END: @@ -218,7 +257,9 @@ blogc_template_parse(const char *src, size_t src_len)                      state = TEMPLATE_CLOSE_BRACKET;                      break;                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, +                    src_len, current, +                    "Invalid statement syntax. Must end with '%}'.");                  break;              case TEMPLATE_VARIABLE_START: @@ -231,8 +272,15 @@ blogc_template_parse(const char *src, size_t src_len)                          start = current;                          break;                      } +                    *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, +                        src, src_len, current, +                        "variable statements only allowed inside 'single_source' " +                        "and 'multiple_sources' blocks."); +                    break;                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, +                    src_len, current, +                    "Invalid variable name. Must begin with uppercase letter.");                  break;              case TEMPLATE_VARIABLE: @@ -248,7 +296,9 @@ blogc_template_parse(const char *src, size_t src_len)                      state = TEMPLATE_CLOSE_BRACKET;                      break;                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, +                    src_len, current, +                    "Invalid variable name. Must be uppercase letter, number or '_'.");                  break;              case TEMPLATE_VARIABLE_END: @@ -258,7 +308,9 @@ blogc_template_parse(const char *src, size_t src_len)                      state = TEMPLATE_CLOSE_BRACKET;                      break;                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, +                    src_len, current, +                    "Invalid statement syntax. Must end with '}}'.");                  break;              case TEMPLATE_CLOSE_BRACKET: @@ -275,24 +327,25 @@ blogc_template_parse(const char *src, size_t src_len)                      start = current + 1;                      break;                  } -                error = true; +                *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, +                    src_len, current, +                    "Invalid statement syntax. Must end with '}'.");                  break;          } -        if (error) +        if (*err != NULL)              break;          current++;      } -    if (error) { +    if (*err != NULL) {          if (stmt != NULL) {              free(stmt->value);              free(stmt);          }          blogc_template_free_stmts(stmts); -        blogc_parser_syntax_error("template", src, src_len, current);          return NULL;      } diff --git a/src/template-parser.h b/src/template-parser.h index 1f43fe8..d95c87a 100644 --- a/src/template-parser.h +++ b/src/template-parser.h @@ -10,6 +10,7 @@  #define _TEMPLATE_PARSER_H  #include "utils/utils.h" +#include "error.h"  typedef enum {      BLOGC_TEMPLATE_IF_STMT = 1, @@ -25,7 +26,8 @@ typedef struct {      char *value;  } blogc_template_stmt_t; -b_slist_t* blogc_template_parse(const char *src, size_t src_len); +b_slist_t* blogc_template_parse(const char *src, size_t src_len, +    blogc_error_t **err);  void blogc_template_free_stmts(b_slist_t *stmts);  #endif /* _TEMPLATE_GRAMMAR_H */ diff --git a/tests/check_source_parser.c b/tests/check_source_parser.c index 2f5880a..c58479e 100644 --- a/tests/check_source_parser.c +++ b/tests/check_source_parser.c @@ -16,6 +16,7 @@  #include <cmocka.h>  #include <string.h>  #include "../src/source-parser.h" +#include "../src/error.h"  static void @@ -28,7 +29,9 @@ test_source_parse(void **state)          "# This is a test\n"          "\n"          "bola\n"; -    blogc_source_t *source = blogc_source_parse(a, strlen(a)); +    blogc_error_t *err = NULL; +    blogc_source_t *source = blogc_source_parse(a, strlen(a), &err); +    assert_null(err);      assert_non_null(source);      assert_int_equal(b_trie_size(source->config), 2);      assert_string_equal(b_trie_lookup(source->config, "VAR1"), "asd asd"); @@ -53,7 +56,9 @@ test_source_parse_with_spaces(void **state)          "# This is a test\n"          "\n"          "bola\n"; -    blogc_source_t *source = blogc_source_parse(a, strlen(a)); +    blogc_error_t *err = NULL; +    blogc_source_t *source = blogc_source_parse(a, strlen(a), &err); +    assert_null(err);      assert_non_null(source);      assert_int_equal(b_trie_size(source->config), 2);      assert_string_equal(b_trie_lookup(source->config, "VAR1"), "chunda"); diff --git a/tests/check_template_parser.c b/tests/check_template_parser.c index 7839bbf..a0cd95c 100644 --- a/tests/check_template_parser.c +++ b/tests/check_template_parser.c @@ -16,6 +16,7 @@  #include <cmocka.h>  #include <string.h>  #include "../src/template-parser.h" +#include "../src/error.h"  static void @@ -44,7 +45,9 @@ test_template_parse(void **state)          "{% endblock %}\n"          "{% block multiple_sources %}{{ BOLA }}{% endblock %}\n"          "{% block multiple_sources_once %}asd{% endblock %}\n"; -    b_slist_t *stmts = blogc_template_parse(a, strlen(a)); +    blogc_error_t *err = NULL; +    b_slist_t *stmts = blogc_template_parse(a, strlen(a), &err); +    assert_null(err);      assert_non_null(stmts);      blogc_assert_template_stmt(stmts, "Test\n\n    ",          BLOGC_TEMPLATE_CONTENT_STMT); @@ -110,7 +113,9 @@ test_template_parse_html(void **state)          "        {% block multiple_sources_once %}</ul>{% endblock %}\n"          "    </body>\n"          "</html>\n"; -    b_slist_t *stmts = blogc_template_parse(a, strlen(a)); +    blogc_error_t *err = NULL; +    b_slist_t *stmts = blogc_template_parse(a, strlen(a), &err); +    assert_null(err);      assert_non_null(stmts);      blogc_assert_template_stmt(stmts, "<html>\n    <head>\n        ",          BLOGC_TEMPLATE_CONTENT_STMT);  | 
