aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael G. Martins <rafael@rafaelmartins.eng.br>2015-04-18 17:17:37 -0300
committerRafael G. Martins <rafael@rafaelmartins.eng.br>2015-04-18 17:17:37 -0300
commitde39a41da62c4b3820b4805ddb7c4970c36bc257 (patch)
tree33da0f360932be9c76dd79a05a9bceaaed5a0441
parentd3e1e90f0979621f741357484e5a8f9656ee4a22 (diff)
downloadblogc-de39a41da62c4b3820b4805ddb7c4970c36bc257.tar.gz
blogc-de39a41da62c4b3820b4805ddb7c4970c36bc257.tar.bz2
blogc-de39a41da62c4b3820b4805ddb7c4970c36bc257.zip
added loader, error handling and cli. tests needed
-rw-r--r--Makefile.am6
-rw-r--r--src/error.c116
-rw-r--r--src/error.h34
-rw-r--r--src/loader.c104
-rw-r--r--src/loader.h22
-rw-r--r--src/main.c98
-rw-r--r--src/output.c39
-rw-r--r--src/output.h17
-rw-r--r--src/source-parser.c37
-rw-r--r--src/source-parser.h6
-rw-r--r--src/template-parser.c87
-rw-r--r--src/template-parser.h4
-rw-r--r--tests/check_source_parser.c9
-rw-r--r--tests/check_template_parser.c9
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 */
diff --git a/src/main.c b/src/main.c
index 4e72b6e..90e374c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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);