From f63fb03b25b33d5c2ef5ef0eaad016b4ee4aee65 Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Sat, 13 Feb 2016 01:02:12 +0100 Subject: content-parser: fixed bug that parsed text with '!' + link as image --- src/content-parser.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/content-parser.c b/src/content-parser.c index ccb96ef..a334d28 100644 --- a/src/content-parser.c +++ b/src/content-parser.c @@ -231,11 +231,15 @@ blogc_content_parse_inline(const char *src) break; case '!': - if (state == LINK_CLOSED && (open_code || open_code_double)) { - b_string_append_c(rv, c); - break; - } if (state == LINK_CLOSED) { + if (open_code || open_code_double) { + b_string_append_c(rv, c); + break; + } + if (!is_last && src[current + 1] != '[') { + b_string_append_c(rv, c); + break; + } state = LINK_IMAGE; is_image = true; start_state = current; -- cgit v1.2.3-18-g5258 From 31d376735ab2aaaed0934edcce676113f83a7de7 Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Sun, 21 Feb 2016 04:58:13 +0100 Subject: content-parser: fixed parser bug when handling links do not handle something like this as a valid link: [asd] asd (asd) --- src/content-parser.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/content-parser.c b/src/content-parser.c index a334d28..9d4adf6 100644 --- a/src/content-parser.c +++ b/src/content-parser.c @@ -161,6 +161,16 @@ blogc_content_parse_inline(const char *src) if (c != ' ' && c != '\n' && c != '\r') spaces = 0; + if (state == LINK_TEXT_CLOSE && c != ' ' && c != '\n' && c != '\r' && + c != '(') + { + b_string_append_c(rv, src[start_state]); + tmp = blogc_content_parse_inline(src + start_state + 1); + b_string_append(rv, tmp); + // no need to free here, we will exit the loop! + break; + } + switch (c) { case '\\': @@ -390,8 +400,7 @@ blogc_content_parse_inline(const char *src) b_string_append_c(rv, src[start_state]); tmp = blogc_content_parse_inline(src + start_state + 1); b_string_append(rv, tmp); - free(tmp); - tmp = NULL; + // no need to free here, its the last iteration } current++; } -- cgit v1.2.3-18-g5258 From 3b0f9293a3432023cdca91df01418347d9781ffa Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Fri, 26 Feb 2016 01:04:32 +0100 Subject: build: replace src/utils with squareball --- src/content-parser.c | 276 ++++++++++++++++++++++---------------------- src/datetime-parser.c | 4 +- src/error.c | 12 +- src/file.c | 8 +- src/loader.c | 84 +++++++------- src/loader.h | 8 +- src/main.c | 52 ++++----- src/renderer.c | 68 +++++------ src/renderer.h | 16 +-- src/source-parser.c | 26 ++--- src/source-parser.h | 4 +- src/template-parser.c | 42 +++---- src/template-parser.h | 6 +- src/utils/mem.c | 42 ------- src/utils/slist.c | 68 ----------- src/utils/strings.c | 314 -------------------------------------------------- src/utils/trie.c | 199 -------------------------------- src/utils/utils.h | 79 ------------- 18 files changed, 303 insertions(+), 1005 deletions(-) delete mode 100644 src/utils/mem.c delete mode 100644 src/utils/slist.c delete mode 100644 src/utils/strings.c delete mode 100644 src/utils/trie.c delete mode 100644 src/utils/utils.h (limited to 'src') diff --git a/src/content-parser.c b/src/content-parser.c index 9d4adf6..7e2310f 100644 --- a/src/content-parser.c +++ b/src/content-parser.c @@ -13,7 +13,7 @@ #include #include -#include "utils/utils.h" +#include #include "content-parser.h" // this is a half ass implementation of a markdown-like syntax. bugs are @@ -25,7 +25,7 @@ blogc_slugify(const char *str) { if (str == NULL) return NULL; - char *new_str = b_strdup(str); + char *new_str = sb_strdup(str); int diff = 'a' - 'A'; // just to avoid magic numbers for (size_t i = 0; new_str[i] != '\0'; i++) { if (new_str[i] >= 'a' && new_str[i] <= 'z') @@ -46,32 +46,32 @@ blogc_htmlentities(const char *str) { if (str == NULL) return NULL; - b_string_t *rv = b_string_new(); + sb_string_t *rv = sb_string_new(); for (size_t i = 0; str[i] != '\0'; i++) { switch (str[i]) { case '&': - b_string_append(rv, "&"); + sb_string_append(rv, "&"); break; case '<': - b_string_append(rv, "<"); + sb_string_append(rv, "<"); break; case '>': - b_string_append(rv, ">"); + sb_string_append(rv, ">"); break; case '"': - b_string_append(rv, """); + sb_string_append(rv, """); break; case '\'': - b_string_append(rv, "'"); + sb_string_append(rv, "'"); break; case '/': - b_string_append(rv, "/"); + sb_string_append(rv, "/"); break; default: - b_string_append_c(rv, str[i]); + sb_string_append_c(rv, str[i]); } } - return b_string_free(rv, false); + return sb_string_free(rv, false); } @@ -126,7 +126,7 @@ blogc_content_parse_inline(const char *src) size_t start_state = 0; size_t end = 0; - b_string_t *rv = b_string_new(); + sb_string_t *rv = sb_string_new(); bool open_em_ast = false; bool open_strong_ast = false; @@ -152,7 +152,7 @@ blogc_content_parse_inline(const char *src) if (escape) { if (state == LINK_CLOSED) - b_string_append_c(rv, c); + sb_string_append_c(rv, c); current++; escape = false; continue; @@ -164,9 +164,9 @@ blogc_content_parse_inline(const char *src) if (state == LINK_TEXT_CLOSE && c != ' ' && c != '\n' && c != '\r' && c != '(') { - b_string_append_c(rv, src[start_state]); + sb_string_append_c(rv, src[start_state]); tmp = blogc_content_parse_inline(src + start_state + 1); - b_string_append(rv, tmp); + sb_string_append(rv, tmp); // no need to free here, we will exit the loop! break; } @@ -175,7 +175,7 @@ blogc_content_parse_inline(const char *src) case '\\': if (state == LINK_CLOSED && (open_code || open_code_double)) { - b_string_append_c(rv, c); + sb_string_append_c(rv, c); break; } if (!escape) @@ -185,7 +185,7 @@ blogc_content_parse_inline(const char *src) case '*': case '_': if (state == LINK_CLOSED && (open_code || open_code_double)) { - b_string_append_c(rv, c); + sb_string_append_c(rv, c); break; } if (!is_last && src[current + 1] == c) { @@ -194,7 +194,7 @@ blogc_content_parse_inline(const char *src) (c == '_' && open_strong_und)) { if (state == LINK_CLOSED) - b_string_append(rv, ""); + sb_string_append(rv, ""); if (c == '*') open_strong_ast = false; else @@ -202,7 +202,7 @@ blogc_content_parse_inline(const char *src) break; } if (state == LINK_CLOSED) - b_string_append(rv, ""); + sb_string_append(rv, ""); if (c == '*') open_strong_ast = true; else @@ -211,7 +211,7 @@ blogc_content_parse_inline(const char *src) } if ((c == '*' && open_em_ast) || (c == '_' && open_em_und)) { if (state == LINK_CLOSED) - b_string_append(rv, ""); + sb_string_append(rv, ""); if (c == '*') open_em_ast = false; else @@ -219,7 +219,7 @@ blogc_content_parse_inline(const char *src) break; } if (state == LINK_CLOSED) - b_string_append(rv, ""); + sb_string_append(rv, ""); if (c == '*') open_em_ast = true; else @@ -230,24 +230,24 @@ blogc_content_parse_inline(const char *src) if (!is_last && src[current + 1] == c) { current++; if (state == LINK_CLOSED) - b_string_append_printf(rv, "<%scode>", + sb_string_append_printf(rv, "<%scode>", open_code_double ? "/" : ""); open_code_double = !open_code_double; break; } if (state == LINK_CLOSED) - b_string_append_printf(rv, "<%scode>", open_code ? "/" : ""); + sb_string_append_printf(rv, "<%scode>", open_code ? "/" : ""); open_code = !open_code; break; case '!': if (state == LINK_CLOSED) { if (open_code || open_code_double) { - b_string_append_c(rv, c); + sb_string_append_c(rv, c); break; } if (!is_last && src[current + 1] != '[') { - b_string_append_c(rv, c); + sb_string_append_c(rv, c); break; } state = LINK_IMAGE; @@ -258,7 +258,7 @@ blogc_content_parse_inline(const char *src) case '[': if (state == LINK_CLOSED && (open_code || open_code_double)) { - b_string_append_c(rv, c); + sb_string_append_c(rv, c); break; } if (state == LINK_CLOSED || state == LINK_IMAGE) { @@ -288,8 +288,8 @@ blogc_content_parse_inline(const char *src) } if (state == LINK_AUTO_CLOSE) { state = LINK_CLOSED; - tmp = b_strndup(src + start, end - start); - b_string_append_printf(rv, "%s", tmp, tmp); + tmp = sb_strndup(src + start, end - start); + sb_string_append_printf(rv, "%s", tmp, tmp); end = 0; free(tmp); tmp = NULL; @@ -299,7 +299,7 @@ blogc_content_parse_inline(const char *src) if (state == LINK_TEXT) { if (open_bracket-- == 0) { state = LINK_TEXT_CLOSE; - tmp = b_strndup(src + start, current - start); + tmp = sb_strndup(src + start, current - start); tmp2 = blogc_content_parse_inline(tmp); free(tmp); tmp = NULL; @@ -307,7 +307,7 @@ blogc_content_parse_inline(const char *src) break; } if (state == LINK_CLOSED) - b_string_append_c(rv, c); + sb_string_append_c(rv, c); break; case '(': @@ -317,18 +317,18 @@ blogc_content_parse_inline(const char *src) break; } if (state == LINK_CLOSED) - b_string_append_c(rv, c); + sb_string_append_c(rv, c); break; case ')': if (state == LINK_URL) { state = LINK_CLOSED; - tmp = b_strndup(src + start, current - start); + tmp = sb_strndup(src + start, current - start); if (is_image) - b_string_append_printf(rv, "\"%s\"", + sb_string_append_printf(rv, "\"%s\"", tmp, tmp2); else - b_string_append_printf(rv, "%s", + sb_string_append_printf(rv, "%s", tmp, tmp2); free(tmp); tmp = NULL; @@ -338,13 +338,13 @@ blogc_content_parse_inline(const char *src) break; } if (state == LINK_CLOSED) - b_string_append_c(rv, c); + sb_string_append_c(rv, c); break; case ' ': if (state == LINK_CLOSED) { spaces++; - b_string_append_c(rv, c); + sb_string_append_c(rv, c); } if (!is_last) break; @@ -353,53 +353,53 @@ blogc_content_parse_inline(const char *src) case '\r': if (state == LINK_CLOSED) { if (spaces >= 2) { - b_string_append(rv, "
"); + sb_string_append(rv, "
"); spaces = 0; } if (c == '\n' || c == '\r') - b_string_append_c(rv, c); + sb_string_append_c(rv, c); } break; case '&': if (state == LINK_CLOSED) - b_string_append(rv, "&"); + sb_string_append(rv, "&"); break; case '<': if (state == LINK_CLOSED) - b_string_append(rv, "<"); + sb_string_append(rv, "<"); break; case '>': if (state == LINK_CLOSED) - b_string_append(rv, ">"); + sb_string_append(rv, ">"); break; case '"': if (state == LINK_CLOSED) - b_string_append(rv, """); + sb_string_append(rv, """); break; case '\'': if (state == LINK_CLOSED) - b_string_append(rv, "'"); + sb_string_append(rv, "'"); break; case '/': if (state == LINK_CLOSED) - b_string_append(rv, "/"); + sb_string_append(rv, "/"); break; default: if (state == LINK_CLOSED) - b_string_append_c(rv, c); + sb_string_append_c(rv, c); } if (is_last && state != LINK_CLOSED) { - b_string_append_c(rv, src[start_state]); + sb_string_append_c(rv, src[start_state]); tmp = blogc_content_parse_inline(src + start_state + 1); - b_string_append(rv, tmp); + sb_string_append(rv, tmp); // no need to free here, its the last iteration } current++; @@ -408,7 +408,7 @@ blogc_content_parse_inline(const char *src) free(tmp); free(tmp2); - return b_string_free(rv, false); + return sb_string_free(rv, false); } @@ -468,11 +468,11 @@ blogc_content_parse(const char *src, size_t *end_excerpt) char d = '\0'; - b_slist_t *lines = NULL; - b_slist_t *lines2 = NULL; + sb_slist_t *lines = NULL; + sb_slist_t *lines2 = NULL; - b_string_t *rv = b_string_new(); - b_string_t *tmp_str = NULL; + sb_string_t *rv = sb_string_new(); + sb_string_t *tmp_str = NULL; blogc_content_parser_state_t state = CONTENT_START_LINE; @@ -599,14 +599,14 @@ blogc_content_parse(const char *src, size_t *end_excerpt) if (c == '\n' || c == '\r' || is_last) { end = is_last && c != '\n' && c != '\r' ? src_len : (real_end != 0 ? real_end : current); - tmp = b_strndup(src + start, end - start); + tmp = sb_strndup(src + start, end - start); parsed = blogc_content_parse_inline(tmp); slug = blogc_slugify(tmp); if (slug == NULL) - b_string_append_printf(rv, "%s%s", + sb_string_append_printf(rv, "%s%s", header_level, parsed, header_level, line_ending); else - b_string_append_printf(rv, "%s%s", + sb_string_append_printf(rv, "%s%s", header_level, slug, parsed, header_level, line_ending); free(slug); @@ -630,8 +630,8 @@ blogc_content_parse(const char *src, size_t *end_excerpt) case CONTENT_HTML_END: if (c == '\n' || c == '\r' || is_last) { - tmp = b_strndup(src + start, end - start); - b_string_append_printf(rv, "%s%s", tmp, line_ending); + tmp = sb_strndup(src + start, end - start); + sb_string_append_printf(rv, "%s%s", tmp, line_ending); free(tmp); tmp = NULL; state = CONTENT_START_LINE; @@ -644,7 +644,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt) case CONTENT_BLOCKQUOTE: if (c == ' ' || c == '\t') break; - prefix = b_strndup(src + start, current - start); + prefix = sb_strndup(src + start, current - start); state = CONTENT_BLOCKQUOTE_START; break; @@ -652,16 +652,16 @@ blogc_content_parse(const char *src, size_t *end_excerpt) if (c == '\n' || c == '\r' || is_last) { end = is_last && c != '\n' && c != '\r' ? src_len : (real_end != 0 ? real_end : current); - tmp = b_strndup(src + start2, end - start2); - if (b_str_starts_with(tmp, prefix)) { - lines = b_slist_append(lines, b_strdup(tmp + strlen(prefix))); + tmp = sb_strndup(src + start2, end - start2); + if (sb_str_starts_with(tmp, prefix)) { + lines = sb_slist_append(lines, sb_strdup(tmp + strlen(prefix))); state = CONTENT_BLOCKQUOTE_END; } else { state = CONTENT_PARAGRAPH; free(prefix); prefix = NULL; - b_slist_free_full(lines, free); + sb_slist_free_full(lines, free); lines = NULL; if (is_last) { free(tmp); @@ -677,22 +677,22 @@ blogc_content_parse(const char *src, size_t *end_excerpt) case CONTENT_BLOCKQUOTE_END: if (c == '\n' || c == '\r' || is_last) { - tmp_str = b_string_new(); - for (b_slist_t *l = lines; l != NULL; l = l->next) { + tmp_str = sb_string_new(); + for (sb_slist_t *l = lines; l != NULL; l = l->next) { if (l->next == NULL) - b_string_append_printf(tmp_str, "%s", l->data); + sb_string_append_printf(tmp_str, "%s", l->data); else - b_string_append_printf(tmp_str, "%s%s", l->data, + sb_string_append_printf(tmp_str, "%s%s", l->data, line_ending); } tmp = blogc_content_parse(tmp_str->str, NULL); - b_string_append_printf(rv, "
%s
%s", + sb_string_append_printf(rv, "
%s
%s", tmp, line_ending); free(tmp); tmp = NULL; - b_string_free(tmp_str, true); + sb_string_free(tmp_str, true); tmp_str = NULL; - b_slist_free_full(lines, free); + sb_slist_free_full(lines, free); lines = NULL; free(prefix); prefix = NULL; @@ -708,7 +708,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt) case CONTENT_CODE: if (c == ' ' || c == '\t') break; - prefix = b_strndup(src + start, current - start); + prefix = sb_strndup(src + start, current - start); state = CONTENT_CODE_START; break; @@ -716,16 +716,16 @@ blogc_content_parse(const char *src, size_t *end_excerpt) if (c == '\n' || c == '\r' || is_last) { end = is_last && c != '\n' && c != '\r' ? src_len : (real_end != 0 ? real_end : current); - tmp = b_strndup(src + start2, end - start2); - if (b_str_starts_with(tmp, prefix)) { - lines = b_slist_append(lines, b_strdup(tmp + strlen(prefix))); + tmp = sb_strndup(src + start2, end - start2); + if (sb_str_starts_with(tmp, prefix)) { + lines = sb_slist_append(lines, sb_strdup(tmp + strlen(prefix))); state = CONTENT_CODE_END; } else { state = CONTENT_PARAGRAPH; free(prefix); prefix = NULL; - b_slist_free_full(lines, free); + sb_slist_free_full(lines, free); lines = NULL; free(tmp); tmp = NULL; @@ -741,18 +741,18 @@ blogc_content_parse(const char *src, size_t *end_excerpt) case CONTENT_CODE_END: if (c == '\n' || c == '\r' || is_last) { - b_string_append(rv, "
");
-                    for (b_slist_t *l = lines; l != NULL; l = l->next) {
+                    sb_string_append(rv, "
");
+                    for (sb_slist_t *l = lines; l != NULL; l = l->next) {
                         char *tmp_line = blogc_htmlentities(l->data);
                         if (l->next == NULL)
-                            b_string_append_printf(rv, "%s", tmp_line);
+                            sb_string_append_printf(rv, "%s", tmp_line);
                         else
-                            b_string_append_printf(rv, "%s%s", tmp_line,
+                            sb_string_append_printf(rv, "%s%s", tmp_line,
                                 line_ending);
                         free(tmp_line);
                     }
-                    b_string_append_printf(rv, "
%s", line_ending); - b_slist_free_full(lines, free); + sb_string_append_printf(rv, "
%s", line_ending); + sb_slist_free_full(lines, free); lines = NULL; free(prefix); prefix = NULL; @@ -774,7 +774,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt) } if (c == ' ' || c == '\t') break; - prefix = b_strndup(src + start, current - start); + prefix = sb_strndup(src + start, current - start); state = CONTENT_UNORDERED_LIST_START; break; @@ -783,7 +783,7 @@ blogc_content_parse(const char *src, size_t *end_excerpt) break; } if (c == '\n' || c == '\r' || is_last) { - b_string_append_printf(rv, "
%s", line_ending); + sb_string_append_printf(rv, "
%s", line_ending); state = CONTENT_START_LINE; start = current; d = '\0'; @@ -796,30 +796,30 @@ blogc_content_parse(const char *src, size_t *end_excerpt) if (c == '\n' || c == '\r' || is_last) { end = is_last && c != '\n' && c != '\r' ? src_len : (real_end != 0 ? real_end : current); - tmp = b_strndup(src + start2, end - start2); - tmp2 = b_strdup_printf("%-*s", strlen(prefix), ""); - if (b_str_starts_with(tmp, prefix)) { + tmp = sb_strndup(src + start2, end - start2); + tmp2 = sb_strdup_printf("%-*s", strlen(prefix), ""); + if (sb_str_starts_with(tmp, prefix)) { if (lines2 != NULL) { - tmp_str = b_string_new(); - for (b_slist_t *l = lines2; l != NULL; l = l->next) { + tmp_str = sb_string_new(); + for (sb_slist_t *l = lines2; l != NULL; l = l->next) { if (l->next == NULL) - b_string_append_printf(tmp_str, "%s", l->data); + sb_string_append_printf(tmp_str, "%s", l->data); else - b_string_append_printf(tmp_str, "%s%s", l->data, + sb_string_append_printf(tmp_str, "%s%s", l->data, line_ending); } - b_slist_free_full(lines2, free); + sb_slist_free_full(lines2, free); lines2 = NULL; parsed = blogc_content_parse_inline(tmp_str->str); - b_string_free(tmp_str, true); - lines = b_slist_append(lines, b_strdup(parsed)); + sb_string_free(tmp_str, true); + lines = sb_slist_append(lines, sb_strdup(parsed)); free(parsed); parsed = NULL; } - lines2 = b_slist_append(lines2, b_strdup(tmp + strlen(prefix))); + lines2 = sb_slist_append(lines2, sb_strdup(tmp + strlen(prefix))); } - else if (b_str_starts_with(tmp, tmp2)) { - lines2 = b_slist_append(lines2, b_strdup(tmp + strlen(prefix))); + else if (sb_str_starts_with(tmp, tmp2)) { + lines2 = sb_slist_append(lines2, sb_strdup(tmp + strlen(prefix))); } else { state = CONTENT_PARAGRAPH_END; @@ -829,8 +829,8 @@ blogc_content_parse(const char *src, size_t *end_excerpt) tmp2 = NULL; free(prefix); prefix = NULL; - b_slist_free_full(lines, free); - b_slist_free_full(lines2, free); + sb_slist_free_full(lines, free); + sb_slist_free_full(lines2, free); lines = NULL; if (is_last) continue; @@ -849,28 +849,28 @@ blogc_content_parse(const char *src, size_t *end_excerpt) if (c == '\n' || c == '\r' || is_last) { if (lines2 != NULL) { // FIXME: avoid repeting the code below - tmp_str = b_string_new(); - for (b_slist_t *l = lines2; l != NULL; l = l->next) { + tmp_str = sb_string_new(); + for (sb_slist_t *l = lines2; l != NULL; l = l->next) { if (l->next == NULL) - b_string_append_printf(tmp_str, "%s", l->data); + sb_string_append_printf(tmp_str, "%s", l->data); else - b_string_append_printf(tmp_str, "%s%s", l->data, + sb_string_append_printf(tmp_str, "%s%s", l->data, line_ending); } - b_slist_free_full(lines2, free); + sb_slist_free_full(lines2, free); lines2 = NULL; parsed = blogc_content_parse_inline(tmp_str->str); - b_string_free(tmp_str, true); - lines = b_slist_append(lines, b_strdup(parsed)); + sb_string_free(tmp_str, true); + lines = sb_slist_append(lines, sb_strdup(parsed)); free(parsed); parsed = NULL; } - b_string_append_printf(rv, "
    %s", line_ending); - for (b_slist_t *l = lines; l != NULL; l = l->next) - b_string_append_printf(rv, "
  • %s
  • %s", l->data, + sb_string_append_printf(rv, "
      %s", line_ending); + for (sb_slist_t *l = lines; l != NULL; l = l->next) + sb_string_append_printf(rv, "
    • %s
    • %s", l->data, line_ending); - b_string_append_printf(rv, "
    %s", line_ending); - b_slist_free_full(lines, free); + sb_string_append_printf(rv, "
%s", line_ending); + sb_slist_free_full(lines, free); lines = NULL; free(prefix); prefix = NULL; @@ -907,30 +907,30 @@ blogc_content_parse(const char *src, size_t *end_excerpt) if (c == '\n' || c == '\r' || is_last) { end = is_last && c != '\n' && c != '\r' ? src_len : (real_end != 0 ? real_end : current); - tmp = b_strndup(src + start2, end - start2); - tmp2 = b_strdup_printf("%-*s", prefix_len, ""); + tmp = sb_strndup(src + start2, end - start2); + tmp2 = sb_strdup_printf("%-*s", prefix_len, ""); if (blogc_is_ordered_list_item(tmp, prefix_len)) { if (lines2 != NULL) { - tmp_str = b_string_new(); - for (b_slist_t *l = lines2; l != NULL; l = l->next) { + tmp_str = sb_string_new(); + for (sb_slist_t *l = lines2; l != NULL; l = l->next) { if (l->next == NULL) - b_string_append_printf(tmp_str, "%s", l->data); + sb_string_append_printf(tmp_str, "%s", l->data); else - b_string_append_printf(tmp_str, "%s%s", l->data, + sb_string_append_printf(tmp_str, "%s%s", l->data, line_ending); } - b_slist_free_full(lines2, free); + sb_slist_free_full(lines2, free); lines2 = NULL; parsed = blogc_content_parse_inline(tmp_str->str); - b_string_free(tmp_str, true); - lines = b_slist_append(lines, b_strdup(parsed)); + sb_string_free(tmp_str, true); + lines = sb_slist_append(lines, sb_strdup(parsed)); free(parsed); parsed = NULL; } - lines2 = b_slist_append(lines2, b_strdup(tmp + prefix_len)); + lines2 = sb_slist_append(lines2, sb_strdup(tmp + prefix_len)); } - else if (b_str_starts_with(tmp, tmp2)) { - lines2 = b_slist_append(lines2, b_strdup(tmp + prefix_len)); + else if (sb_str_starts_with(tmp, tmp2)) { + lines2 = sb_slist_append(lines2, sb_strdup(tmp + prefix_len)); } else { state = CONTENT_PARAGRAPH_END; @@ -940,8 +940,8 @@ blogc_content_parse(const char *src, size_t *end_excerpt) tmp2 = NULL; free(parsed); parsed = NULL; - b_slist_free_full(lines, free); - b_slist_free_full(lines2, free); + sb_slist_free_full(lines, free); + sb_slist_free_full(lines2, free); lines = NULL; if (is_last) continue; @@ -960,28 +960,28 @@ blogc_content_parse(const char *src, size_t *end_excerpt) if (c == '\n' || c == '\r' || is_last) { if (lines2 != NULL) { // FIXME: avoid repeting the code below - tmp_str = b_string_new(); - for (b_slist_t *l = lines2; l != NULL; l = l->next) { + tmp_str = sb_string_new(); + for (sb_slist_t *l = lines2; l != NULL; l = l->next) { if (l->next == NULL) - b_string_append_printf(tmp_str, "%s", l->data); + sb_string_append_printf(tmp_str, "%s", l->data); else - b_string_append_printf(tmp_str, "%s%s", l->data, + sb_string_append_printf(tmp_str, "%s%s", l->data, line_ending); } - b_slist_free_full(lines2, free); + sb_slist_free_full(lines2, free); lines2 = NULL; parsed = blogc_content_parse_inline(tmp_str->str); - b_string_free(tmp_str, true); - lines = b_slist_append(lines, b_strdup(parsed)); + sb_string_free(tmp_str, true); + lines = sb_slist_append(lines, sb_strdup(parsed)); free(parsed); parsed = NULL; } - b_string_append_printf(rv, "
    %s", line_ending); - for (b_slist_t *l = lines; l != NULL; l = l->next) - b_string_append_printf(rv, "
  1. %s
  2. %s", l->data, + sb_string_append_printf(rv, "
      %s", line_ending); + for (sb_slist_t *l = lines; l != NULL; l = l->next) + sb_string_append_printf(rv, "
    1. %s
    2. %s", l->data, line_ending); - b_string_append_printf(rv, "
    %s", line_ending); - b_slist_free_full(lines, free); + sb_string_append_printf(rv, "
%s", line_ending); + sb_slist_free_full(lines, free); lines = NULL; free(prefix); prefix = NULL; @@ -1005,9 +1005,9 @@ blogc_content_parse(const char *src, size_t *end_excerpt) case CONTENT_PARAGRAPH_END: if (c == '\n' || c == '\r' || is_last) { - tmp = b_strndup(src + start, end - start); + tmp = sb_strndup(src + start, end - start); parsed = blogc_content_parse_inline(tmp); - b_string_append_printf(rv, "

%s

%s", parsed, + sb_string_append_printf(rv, "

%s

%s", parsed, line_ending); free(parsed); parsed = NULL; @@ -1025,5 +1025,5 @@ blogc_content_parse(const char *src, size_t *end_excerpt) current++; } - return b_string_free(rv, false); + return sb_string_free(rv, false); } diff --git a/src/datetime-parser.c b/src/datetime-parser.c index 8785a89..0aeb702 100644 --- a/src/datetime-parser.c +++ b/src/datetime-parser.c @@ -17,7 +17,7 @@ #include #include "error.h" -#include "utils/utils.h" +#include #include "datetime-parser.h" @@ -380,7 +380,7 @@ blogc_convert_datetime(const char *orig, const char *format, return NULL; } - return b_strdup(buf); + return sb_strdup(buf); #endif } diff --git a/src/error.c b/src/error.c index 6256873..f05049c 100644 --- a/src/error.c +++ b/src/error.c @@ -14,16 +14,16 @@ #include #include #include -#include "utils/utils.h" +#include #include "error.h" blogc_error_t* blogc_error_new(blogc_error_type_t type, const char *msg) { - blogc_error_t *err = b_malloc(sizeof(blogc_error_t)); + blogc_error_t *err = sb_malloc(sizeof(blogc_error_t)); err->type = type; - err->msg = b_strdup(msg); + err->msg = sb_strdup(msg); return err; } @@ -33,7 +33,7 @@ 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); + char *tmp = sb_strdup_vprintf(format, ap); va_end(ap); blogc_error_t *rv = blogc_error_new(type, tmp); free(tmp); @@ -47,7 +47,7 @@ blogc_error_parser(blogc_error_type_t type, const char *src, size_t src_len, { va_list ap; va_start(ap, format); - char *msg = b_strdup_vprintf(format, ap); + char *msg = sb_strdup_vprintf(format, ap); va_end(ap); size_t lineno = 1; @@ -88,7 +88,7 @@ blogc_error_parser(blogc_error_type_t type, const char *src, size_t src_len, if (lineend <= linestart && src_len >= linestart) lineend = src_len; - char *line = b_strndup(src + linestart, lineend - linestart); + char *line = sb_strndup(src + linestart, lineend - linestart); blogc_error_t *rv = NULL; diff --git a/src/file.c b/src/file.c index a4c763a..dec7c1b 100644 --- a/src/file.c +++ b/src/file.c @@ -14,7 +14,7 @@ #include #include #include -#include "utils/utils.h" +#include #include "file.h" #include "error.h" @@ -38,16 +38,16 @@ blogc_file_get_contents(const char *path, size_t *len, blogc_error_t **err) return NULL; } - b_string_t *str = b_string_new(); + sb_string_t *str = sb_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); + sb_string_append_len(str, buffer, read_len); } fclose(fp); - return b_string_free(str, false); + return sb_string_free(str, false); } diff --git a/src/loader.c b/src/loader.c index baa81fa..8008c3a 100644 --- a/src/loader.c +++ b/src/loader.c @@ -14,7 +14,7 @@ #include #include #include -#include "utils/utils.h" +#include #include "file.h" #include "source-parser.h" #include "template-parser.h" @@ -31,7 +31,7 @@ blogc_get_filename(const char *f) if (strlen(f) == 0) return NULL; - char *filename = b_strdup(f); + char *filename = sb_strdup(f); // keep a pointer to original string char *tmp = filename; @@ -52,14 +52,14 @@ blogc_get_filename(const char *f) } } - char *final_filename = b_strdup(tmp); + char *final_filename = sb_strdup(tmp); free(filename); return final_filename; } -b_slist_t* +sb_slist_t* blogc_template_parse_from_file(const char *f, blogc_error_t **err) { if (err == NULL || *err != NULL) @@ -68,13 +68,13 @@ blogc_template_parse_from_file(const char *f, blogc_error_t **err) char *s = blogc_file_get_contents(f, &len, err); if (s == NULL) return NULL; - b_slist_t *rv = blogc_template_parse(s, len, err); + sb_slist_t *rv = blogc_template_parse(s, len, err); free(s); return rv; } -b_trie_t* +sb_trie_t* blogc_source_parse_from_file(const char *f, blogc_error_t **err) { if (err == NULL || *err != NULL) @@ -83,13 +83,13 @@ blogc_source_parse_from_file(const char *f, blogc_error_t **err) char *s = blogc_file_get_contents(f, &len, err); if (s == NULL) return NULL; - b_trie_t *rv = blogc_source_parse(s, len, err); + sb_trie_t *rv = blogc_source_parse(s, len, err); // set FILENAME variable if (rv != NULL) { char *filename = blogc_get_filename(f); if (filename != NULL) - b_trie_insert(rv, "FILENAME", filename); + sb_trie_insert(rv, "FILENAME", filename); } free(s); @@ -97,16 +97,16 @@ blogc_source_parse_from_file(const char *f, blogc_error_t **err) } -b_slist_t* -blogc_source_parse_from_files(b_trie_t *conf, b_slist_t *l, blogc_error_t **err) +sb_slist_t* +blogc_source_parse_from_files(sb_trie_t *conf, sb_slist_t *l, blogc_error_t **err) { blogc_error_t *tmp_err = NULL; - b_slist_t *rv = NULL; + sb_slist_t *rv = NULL; unsigned int with_date = 0; - const char *filter_tag = b_trie_lookup(conf, "FILTER_TAG"); - const char *filter_page = b_trie_lookup(conf, "FILTER_PAGE"); - const char *filter_per_page = b_trie_lookup(conf, "FILTER_PER_PAGE"); + const char *filter_tag = sb_trie_lookup(conf, "FILTER_TAG"); + const char *filter_page = sb_trie_lookup(conf, "FILTER_PAGE"); + const char *filter_per_page = sb_trie_lookup(conf, "FILTER_PER_PAGE"); long page = strtol(filter_page != NULL ? filter_page : "", NULL, 10); if (page <= 0) @@ -121,27 +121,27 @@ blogc_source_parse_from_files(b_trie_t *conf, b_slist_t *l, blogc_error_t **err) unsigned int end = start + per_page; unsigned int counter = 0; - for (b_slist_t *tmp = l; tmp != NULL; tmp = tmp->next) { + for (sb_slist_t *tmp = l; tmp != NULL; tmp = tmp->next) { char *f = tmp->data; - b_trie_t *s = blogc_source_parse_from_file(f, &tmp_err); + sb_trie_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, (b_free_func_t) b_trie_free); + sb_slist_free_full(rv, (sb_free_func_t) sb_trie_free); rv = NULL; break; } if (filter_tag != NULL) { - const char *tags_str = b_trie_lookup(s, "TAGS"); + const char *tags_str = sb_trie_lookup(s, "TAGS"); // if user wants to filter by tag and no tag is provided, skip it if (tags_str == NULL) { - b_trie_free(s); + sb_trie_free(s); continue; } - char **tags = b_str_split(tags_str, ' ', 0); + char **tags = sb_str_split(tags_str, ' ', 0); bool found = false; for (unsigned int i = 0; tags[i] != NULL; i++) { if (tags[i][0] == '\0') @@ -149,26 +149,26 @@ blogc_source_parse_from_files(b_trie_t *conf, b_slist_t *l, blogc_error_t **err) if (0 == strcmp(tags[i], filter_tag)) found = true; } - b_strv_free(tags); + sb_strv_free(tags); if (!found) { - b_trie_free(s); + sb_trie_free(s); continue; } } if (filter_page != NULL) { if (counter < start || counter >= end) { counter++; - b_trie_free(s); + sb_trie_free(s); continue; } counter++; } - if (b_trie_lookup(s, "DATE") != NULL) + if (sb_trie_lookup(s, "DATE") != NULL) with_date++; - rv = b_slist_append(rv, s); + rv = sb_slist_append(rv, s); } - if (with_date > 0 && with_date < b_slist_length(rv)) + if (with_date > 0 && with_date < sb_slist_length(rv)) // fatal error, maybe? blogc_fprintf(stderr, "blogc: warning: 'DATE' variable provided for at least one source " @@ -176,38 +176,38 @@ blogc_source_parse_from_files(b_trie_t *conf, b_slist_t *l, blogc_error_t **err) "wrong values for 'DATE_FIRST' and 'DATE_LAST' variables.\n"); bool first = true; - for (b_slist_t *tmp = rv; tmp != NULL; tmp = tmp->next) { - b_trie_t *s = tmp->data; + for (sb_slist_t *tmp = rv; tmp != NULL; tmp = tmp->next) { + sb_trie_t *s = tmp->data; if (first) { - const char *val = b_trie_lookup(s, "DATE"); + const char *val = sb_trie_lookup(s, "DATE"); if (val != NULL) - b_trie_insert(conf, "DATE_FIRST", b_strdup(val)); - val = b_trie_lookup(s, "FILENAME"); + sb_trie_insert(conf, "DATE_FIRST", sb_strdup(val)); + val = sb_trie_lookup(s, "FILENAME"); if (val != NULL) - b_trie_insert(conf, "FILENAME_FIRST", b_strdup(val)); + sb_trie_insert(conf, "FILENAME_FIRST", sb_strdup(val)); first = false; } if (tmp->next == NULL) { // last - const char *val = b_trie_lookup(s, "DATE"); + const char *val = sb_trie_lookup(s, "DATE"); if (val != NULL) - b_trie_insert(conf, "DATE_LAST", b_strdup(val)); - val = b_trie_lookup(s, "FILENAME"); + sb_trie_insert(conf, "DATE_LAST", sb_strdup(val)); + val = sb_trie_lookup(s, "FILENAME"); if (val != NULL) - b_trie_insert(conf, "FILENAME_LAST", b_strdup(val)); + sb_trie_insert(conf, "FILENAME_LAST", sb_strdup(val)); } } if (filter_page != NULL) { unsigned int last_page = ceilf(((float) counter) / per_page); - b_trie_insert(conf, "CURRENT_PAGE", b_strdup_printf("%ld", page)); + sb_trie_insert(conf, "CURRENT_PAGE", sb_strdup_printf("%ld", page)); if (page > 1) - b_trie_insert(conf, "PREVIOUS_PAGE", b_strdup_printf("%ld", page - 1)); + sb_trie_insert(conf, "PREVIOUS_PAGE", sb_strdup_printf("%ld", page - 1)); if (page < last_page) - b_trie_insert(conf, "NEXT_PAGE", b_strdup_printf("%ld", page + 1)); - if (b_slist_length(rv) > 0) - b_trie_insert(conf, "FIRST_PAGE", b_strdup("1")); + sb_trie_insert(conf, "NEXT_PAGE", sb_strdup_printf("%ld", page + 1)); + if (sb_slist_length(rv) > 0) + sb_trie_insert(conf, "FIRST_PAGE", sb_strdup("1")); if (last_page > 0) - b_trie_insert(conf, "LAST_PAGE", b_strdup_printf("%d", last_page)); + sb_trie_insert(conf, "LAST_PAGE", sb_strdup_printf("%d", last_page)); } return rv; diff --git a/src/loader.h b/src/loader.h index c432e20..080aff6 100644 --- a/src/loader.h +++ b/src/loader.h @@ -9,13 +9,13 @@ #ifndef _LOADER_H #define _LOADER_H -#include "utils/utils.h" +#include #include "error.h" char* blogc_get_filename(const char *f); -b_slist_t* blogc_template_parse_from_file(const char *f, blogc_error_t **err); -b_trie_t* blogc_source_parse_from_file(const char *f, blogc_error_t **err); -b_slist_t* blogc_source_parse_from_files(b_trie_t *conf, b_slist_t *l, +sb_slist_t* blogc_template_parse_from_file(const char *f, blogc_error_t **err); +sb_trie_t* blogc_source_parse_from_file(const char *f, blogc_error_t **err); +sb_slist_t* blogc_source_parse_from_files(sb_trie_t *conf, sb_slist_t *l, blogc_error_t **err); #endif /* _LOADER_H */ diff --git a/src/main.c b/src/main.c index f3f990b..143c836 100644 --- a/src/main.c +++ b/src/main.c @@ -24,7 +24,7 @@ #include #include -#include "utils/utils.h" +#include #include "source-parser.h" #include "template-parser.h" #include "loader.h" @@ -71,7 +71,7 @@ blogc_print_usage(void) static void blogc_mkdir_recursive(const char *filename) { - char *fname = b_strdup(filename); + char *fname = sb_strdup(filename); for (char *tmp = fname; *tmp != '\0'; tmp++) { if (*tmp != '/' && *tmp != '\\') continue; @@ -117,9 +117,9 @@ main(int argc, char **argv) char *tmp = NULL; char **pieces = NULL; - b_slist_t *sources = NULL; - b_trie_t *config = b_trie_new(free); - b_trie_insert(config, "BLOGC_VERSION", b_strdup(PACKAGE_VERSION)); + sb_slist_t *sources = NULL; + sb_trie_t *config = sb_trie_new(free); + sb_trie_insert(config, "BLOGC_VERSION", sb_strdup(PACKAGE_VERSION)); for (unsigned int i = 1; i < argc; i++) { tmp = NULL; @@ -136,21 +136,21 @@ main(int argc, char **argv) break; case 't': if (argv[i][2] != '\0') - template = b_strdup(argv[i] + 2); + template = sb_strdup(argv[i] + 2); else if (i + 1 < argc) - template = b_strdup(argv[++i]); + template = sb_strdup(argv[++i]); break; case 'o': if (argv[i][2] != '\0') - output = b_strdup(argv[i] + 2); + output = sb_strdup(argv[i] + 2); else if (i + 1 < argc) - output = b_strdup(argv[++i]); + output = sb_strdup(argv[++i]); break; case 'p': if (argv[i][2] != '\0') - print = b_strdup(argv[i] + 2); + print = sb_strdup(argv[i] + 2); else if (i + 1 < argc) - print = b_strdup(argv[++i]); + print = sb_strdup(argv[++i]); break; case 'D': if (argv[i][2] != '\0') @@ -158,11 +158,11 @@ main(int argc, char **argv) else if (i + 1 < argc) tmp = argv[++i]; if (tmp != NULL) { - pieces = b_str_split(tmp, '=', 2); - if (b_strv_length(pieces) != 2) { + pieces = sb_str_split(tmp, '=', 2); + if (sb_strv_length(pieces) != 2) { fprintf(stderr, "blogc: error: invalid value for " "-D (must have an '='): %s\n", tmp); - b_strv_free(pieces); + sb_strv_free(pieces); rv = 2; goto cleanup; } @@ -173,13 +173,13 @@ main(int argc, char **argv) fprintf(stderr, "blogc: error: invalid value " "for -D (configuration key must be uppercase " "with '_'): %s\n", pieces[0]); - b_strv_free(pieces); + sb_strv_free(pieces); rv = 2; goto cleanup; } } - b_trie_insert(config, pieces[0], b_strdup(pieces[1])); - b_strv_free(pieces); + sb_trie_insert(config, pieces[0], sb_strdup(pieces[1])); + sb_strv_free(pieces); pieces = NULL; } break; @@ -192,17 +192,17 @@ main(int argc, char **argv) } } else - sources = b_slist_append(sources, b_strdup(argv[i])); + sources = sb_slist_append(sources, sb_strdup(argv[i])); } - if (!listing && b_slist_length(sources) == 0) { + if (!listing && sb_slist_length(sources) == 0) { blogc_print_usage(); fprintf(stderr, "blogc: error: one source file is required\n"); rv = 2; goto cleanup; } - if (!listing && b_slist_length(sources) > 1) { + if (!listing && sb_slist_length(sources) > 1) { blogc_print_usage(); fprintf(stderr, "blogc: error: only one source file should be provided, " "if running without '-l'\n"); @@ -212,14 +212,14 @@ main(int argc, char **argv) blogc_error_t *err = NULL; - b_slist_t *s = blogc_source_parse_from_files(config, sources, &err); + sb_slist_t *s = blogc_source_parse_from_files(config, sources, &err); if (err != NULL) { blogc_error_print(err); rv = 2; goto cleanup2; } - b_slist_t* l = blogc_template_parse_from_file(template, &err); + sb_slist_t* l = blogc_template_parse_from_file(template, &err); if (err != NULL) { blogc_error_print(err); rv = 2; @@ -227,7 +227,7 @@ main(int argc, char **argv) } if (print != NULL) { - const char *val = b_trie_lookup(config, print); + const char *val = sb_trie_lookup(config, print); if (val == NULL) { fprintf(stderr, "blogc: error: configuration variable not found: %s\n", print); @@ -273,13 +273,13 @@ cleanup4: cleanup3: blogc_template_free_stmts(l); cleanup2: - b_slist_free_full(s, (b_free_func_t) b_trie_free); + sb_slist_free_full(s, (sb_free_func_t) sb_trie_free); blogc_error_free(err); cleanup: - b_trie_free(config); + sb_trie_free(config); free(template); free(output); free(print); - b_slist_free_full(sources, free); + sb_slist_free_full(sources, free); return rv; } diff --git a/src/renderer.c b/src/renderer.c index 5e07b0c..a7a7dd7 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -13,7 +13,7 @@ #include #include #include -#include "utils/utils.h" +#include #include "datetime-parser.h" #include "error.h" #include "loader.h" @@ -23,59 +23,59 @@ const char* -blogc_get_variable(const char *name, b_trie_t *global, b_trie_t *local) +blogc_get_variable(const char *name, sb_trie_t *global, sb_trie_t *local) { const char *rv = NULL; if (local != NULL) { - rv = b_trie_lookup(local, name); + rv = sb_trie_lookup(local, name); if (rv != NULL) return rv; } if (global != NULL) - rv = b_trie_lookup(global, name); + rv = sb_trie_lookup(global, name); return rv; } char* -blogc_format_date(const char *date, b_trie_t *global, b_trie_t *local) +blogc_format_date(const char *date, sb_trie_t *global, sb_trie_t *local) { const char *date_format = blogc_get_variable("DATE_FORMAT", global, local); if (date == NULL) return NULL; if (date_format == NULL) - return b_strdup(date); + return sb_strdup(date); blogc_error_t *err = NULL; char *rv = blogc_convert_datetime(date, date_format, &err); if (err != NULL) { blogc_error_print(err); blogc_error_free(err); - return b_strdup(date); + return sb_strdup(date); } return rv; } char* -blogc_format_variable(const char *name, b_trie_t *global, b_trie_t *local, - b_slist_t *foreach_var) +blogc_format_variable(const char *name, sb_trie_t *global, sb_trie_t *local, + sb_slist_t *foreach_var) { if (0 == strcmp(name, "FOREACH_ITEM")) { if (foreach_var != NULL && foreach_var->data != NULL) { - return b_strdup(foreach_var->data); + return sb_strdup(foreach_var->data); } return NULL; } char *var = NULL; bool must_format = false; - if (b_str_ends_with(name, "_FORMATTED")) { - var = b_strndup(name, strlen(name) - 10); + if (sb_str_ends_with(name, "_FORMATTED")) { + var = sb_strndup(name, strlen(name) - 10); must_format = true; } if (var == NULL) - var = b_strdup(name); + var = sb_strdup(name); const char *value = blogc_get_variable(var, global, local); free(var); @@ -85,30 +85,30 @@ blogc_format_variable(const char *name, b_trie_t *global, b_trie_t *local, char *rv = NULL; if (must_format) { - if (b_str_starts_with(name, "DATE_")) { + if (sb_str_starts_with(name, "DATE_")) { rv = blogc_format_date(value, global, local); } } if (rv == NULL) - return b_strdup(value); + return sb_strdup(value); return rv; } -b_slist_t* -blogc_split_list_variable(const char *name, b_trie_t *global, b_trie_t *local) +sb_slist_t* +blogc_split_list_variable(const char *name, sb_trie_t *global, sb_trie_t *local) { const char *value = blogc_get_variable(name, global, local); if (value == NULL) return NULL; - b_slist_t *rv = NULL; + sb_slist_t *rv = NULL; - char **tmp = b_str_split(value, ' ', 0); + char **tmp = sb_str_split(value, ' ', 0); for (unsigned int i = 0; tmp[i] != NULL; i++) { if (tmp[i][0] != '\0') // ignore empty strings - rv = b_slist_append(rv, tmp[i]); + rv = sb_slist_append(rv, tmp[i]); else free(tmp[i]); } @@ -119,25 +119,25 @@ blogc_split_list_variable(const char *name, b_trie_t *global, b_trie_t *local) char* -blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing) +blogc_render(sb_slist_t *tmpl, sb_slist_t *sources, sb_trie_t *config, bool listing) { if (tmpl == NULL) return NULL; - b_slist_t *current_source = NULL; - b_slist_t *listing_start = NULL; + sb_slist_t *current_source = NULL; + sb_slist_t *listing_start = NULL; - b_string_t *str = b_string_new(); + sb_string_t *str = sb_string_new(); - b_trie_t *tmp_source = NULL; + sb_trie_t *tmp_source = NULL; char *config_value = NULL; char *defined = NULL; unsigned int if_count = 0; - b_slist_t *foreach_var = NULL; - b_slist_t *foreach_var_start = NULL; - b_slist_t *foreach_start = NULL; + sb_slist_t *foreach_var = NULL; + sb_slist_t *foreach_var_start = NULL; + sb_slist_t *foreach_start = NULL; bool if_not = false; bool inside_block = false; @@ -145,7 +145,7 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing int cmp = 0; - b_slist_t *tmp = tmpl; + sb_slist_t *tmp = tmpl; while (tmp != NULL) { blogc_template_stmt_t *stmt = tmp->data; @@ -153,7 +153,7 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing case BLOGC_TEMPLATE_CONTENT_STMT: if (stmt->value != NULL) - b_string_append(str, stmt->value); + sb_string_append(str, stmt->value); break; case BLOGC_TEMPLATE_BLOCK_STMT: @@ -210,7 +210,7 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing config_value = blogc_format_variable(stmt->value, config, inside_block ? tmp_source : NULL, foreach_var); if (config_value != NULL) { - b_string_append(str, config_value); + sb_string_append(str, config_value); free(config_value); config_value = NULL; break; @@ -252,7 +252,7 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing (stmt->value2[0] == '"') && (stmt->value2[strlen(stmt->value2) - 1] == '"')) { - defined2 = b_strndup(stmt->value2 + 1, + defined2 = sb_strndup(stmt->value2 + 1, strlen(stmt->value2) - 2); } else { @@ -354,7 +354,7 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing } } foreach_start = NULL; - b_slist_free_full(foreach_var_start, free); + sb_slist_free_full(foreach_var_start, free); foreach_var_start = NULL; break; } @@ -364,5 +364,5 @@ blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, bool listing // no need to free temporary variables here. the template parser makes sure // that templates are sane and statements are closed. - return b_string_free(str, false); + return sb_string_free(str, false); } diff --git a/src/renderer.h b/src/renderer.h index 15204e6..3ff62e7 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -10,15 +10,15 @@ #define _RENDERER_H #include -#include "utils/utils.h" +#include -const char* blogc_get_variable(const char *name, b_trie_t *global, b_trie_t *local); -char* blogc_format_date(const char *date, b_trie_t *global, b_trie_t *local); -char* blogc_format_variable(const char *name, b_trie_t *global, b_trie_t *local, - b_slist_t *foreach_var); -b_slist_t* blogc_split_list_variable(const char *name, b_trie_t *global, - b_trie_t *local); -char* blogc_render(b_slist_t *tmpl, b_slist_t *sources, b_trie_t *config, +const char* blogc_get_variable(const char *name, sb_trie_t *global, sb_trie_t *local); +char* blogc_format_date(const char *date, sb_trie_t *global, sb_trie_t *local); +char* blogc_format_variable(const char *name, sb_trie_t *global, sb_trie_t *local, + sb_slist_t *foreach_var); +sb_slist_t* blogc_split_list_variable(const char *name, sb_trie_t *global, + sb_trie_t *local); +char* blogc_render(sb_slist_t *tmpl, sb_slist_t *sources, sb_trie_t *config, bool listing); #endif /* _RENDERER_H */ diff --git a/src/source-parser.c b/src/source-parser.c index 65fdd4e..e3662a2 100644 --- a/src/source-parser.c +++ b/src/source-parser.c @@ -13,7 +13,7 @@ #include #include -#include "utils/utils.h" +#include #include "content-parser.h" #include "source-parser.h" #include "error.h" @@ -30,7 +30,7 @@ typedef enum { } blogc_source_parser_state_t; -b_trie_t* +sb_trie_t* blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err) { if (err == NULL || *err != NULL) @@ -43,7 +43,7 @@ blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err) char *key = NULL; char *tmp = NULL; char *content = NULL; - b_trie_t *rv = b_trie_new(free); + sb_trie_t *rv = sb_trie_new(free); blogc_source_parser_state_t state = SOURCE_START; @@ -73,7 +73,7 @@ blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err) if ((c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_') break; if (c == ':') { - key = b_strndup(src + start, current - start); + key = sb_strndup(src + start, current - start); if (((current - start == 8) && (0 == strncmp("FILENAME", src + start, 8))) || ((current - start == 7) && @@ -122,8 +122,8 @@ blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err) case SOURCE_CONFIG_VALUE: if (c == '\n' || c == '\r') { - tmp = b_strndup(src + start, current - start); - b_trie_insert(rv, key, b_strdup(b_str_strip(tmp))); + tmp = sb_strndup(src + start, current - start); + sb_trie_insert(rv, key, sb_strdup(sb_str_strip(tmp))); free(tmp); free(key); key = NULL; @@ -152,12 +152,12 @@ blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err) case SOURCE_CONTENT: if (current == (src_len - 1)) { - tmp = b_strndup(src + start, src_len - start); - b_trie_insert(rv, "RAW_CONTENT", tmp); + tmp = sb_strndup(src + start, src_len - start); + sb_trie_insert(rv, "RAW_CONTENT", tmp); content = blogc_content_parse(tmp, &end_excerpt); - b_trie_insert(rv, "CONTENT", content); - b_trie_insert(rv, "EXCERPT", end_excerpt == 0 ? - b_strdup(content) : b_strndup(content, end_excerpt)); + sb_trie_insert(rv, "CONTENT", content); + sb_trie_insert(rv, "EXCERPT", end_excerpt == 0 ? + sb_strdup(content) : sb_strndup(content, end_excerpt)); } break; } @@ -168,7 +168,7 @@ blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err) current++; } - if (*err == NULL && b_trie_size(rv) == 0) { + if (*err == NULL && sb_trie_size(rv) == 0) { // ok, nothing found in the config trie, but no error set either. // let's try to be nice with the users and provide some reasonable @@ -202,7 +202,7 @@ blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err) if (*err != NULL) { free(key); - b_trie_free(rv); + sb_trie_free(rv); return NULL; } diff --git a/src/source-parser.h b/src/source-parser.h index f359f9e..460aedb 100644 --- a/src/source-parser.h +++ b/src/source-parser.h @@ -10,10 +10,10 @@ #define _SOURCE_PARSER_H #include -#include "utils/utils.h" +#include #include "error.h" -b_trie_t* blogc_source_parse(const char *src, size_t src_len, +sb_trie_t* blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err); #endif /* _SOURCE_PARSER_H */ diff --git a/src/template-parser.c b/src/template-parser.c index 1d9046e..6f23ef1 100644 --- a/src/template-parser.c +++ b/src/template-parser.c @@ -13,7 +13,7 @@ #include #include -#include "utils/utils.h" +#include #include "template-parser.h" #include "error.h" @@ -52,7 +52,7 @@ typedef enum { } blogc_template_parser_block_state_t; -b_slist_t* +sb_slist_t* blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) { if (err == NULL || *err != NULL) @@ -71,7 +71,7 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) unsigned int if_count = 0; bool foreach_open = false; - b_slist_t *stmts = NULL; + sb_slist_t *stmts = NULL; blogc_template_stmt_t *stmt = NULL; /* @@ -100,21 +100,21 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) case TEMPLATE_START: if (last) { - stmt = b_malloc(sizeof(blogc_template_stmt_t)); + stmt = sb_malloc(sizeof(blogc_template_stmt_t)); stmt->type = type; if (lstrip_next) { - tmp = b_strndup(src + start, src_len - start); - stmt->value = b_strdup(b_str_lstrip(tmp)); + tmp = sb_strndup(src + start, src_len - start); + stmt->value = sb_strdup(sb_str_lstrip(tmp)); free(tmp); tmp = NULL; lstrip_next = false; } else { - stmt->value = b_strndup(src + start, src_len - start); + stmt->value = sb_strndup(src + start, src_len - start); } stmt->op = 0; stmt->value2 = NULL; - stmts = b_slist_append(stmts, stmt); + stmts = sb_slist_append(stmts, stmt); previous = stmt; stmt = NULL; } @@ -131,21 +131,21 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) else state = TEMPLATE_VARIABLE_START; if (end > start) { - stmt = b_malloc(sizeof(blogc_template_stmt_t)); + stmt = sb_malloc(sizeof(blogc_template_stmt_t)); stmt->type = type; if (lstrip_next) { - tmp = b_strndup(src + start, end - start); - stmt->value = b_strdup(b_str_lstrip(tmp)); + tmp = sb_strndup(src + start, end - start); + stmt->value = sb_strdup(sb_str_lstrip(tmp)); free(tmp); tmp = NULL; lstrip_next = false; } else { - stmt->value = b_strndup(src + start, end - start); + stmt->value = sb_strndup(src + start, end - start); } stmt->op = 0; stmt->value2 = NULL; - stmts = b_slist_append(stmts, stmt); + stmts = sb_slist_append(stmts, stmt); previous = stmt; stmt = NULL; } @@ -159,7 +159,7 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) if ((previous != NULL) && (previous->type == BLOGC_TEMPLATE_CONTENT_STMT)) { - previous->value = b_str_rstrip(previous->value); // does not need copy + previous->value = sb_str_rstrip(previous->value); // does not need copy } state = TEMPLATE_BLOCK_START; break; @@ -559,19 +559,19 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) op_start = 0; op_end = 0; } - stmt = b_malloc(sizeof(blogc_template_stmt_t)); + stmt = sb_malloc(sizeof(blogc_template_stmt_t)); stmt->type = type; stmt->value = NULL; stmt->op = tmp_op; stmt->value2 = NULL; if (end > start) - stmt->value = b_strndup(src + start, end - start); + stmt->value = sb_strndup(src + start, end - start); if (end2 > start2) { - stmt->value2 = b_strndup(src + start2, end2 - start2); + stmt->value2 = sb_strndup(src + start2, end2 - start2); start2 = 0; end2 = 0; } - stmts = b_slist_append(stmts, stmt); + stmts = sb_slist_append(stmts, stmt); previous = stmt; stmt = NULL; state = TEMPLATE_START; @@ -622,9 +622,9 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) void -blogc_template_free_stmts(b_slist_t *stmts) +blogc_template_free_stmts(sb_slist_t *stmts) { - for (b_slist_t *tmp = stmts; tmp != NULL; tmp = tmp->next) { + for (sb_slist_t *tmp = stmts; tmp != NULL; tmp = tmp->next) { blogc_template_stmt_t *data = tmp->data; if (data == NULL) continue; @@ -632,5 +632,5 @@ blogc_template_free_stmts(b_slist_t *stmts) free(data->value2); free(data); } - b_slist_free(stmts); + sb_slist_free(stmts); } diff --git a/src/template-parser.h b/src/template-parser.h index 6cd2c80..de5113e 100644 --- a/src/template-parser.h +++ b/src/template-parser.h @@ -9,7 +9,7 @@ #ifndef _TEMPLATE_PARSER_H #define _TEMPLATE_PARSER_H -#include "utils/utils.h" +#include #include "error.h" /* @@ -44,8 +44,8 @@ typedef struct { blogc_template_stmt_operator_t op; } blogc_template_stmt_t; -b_slist_t* blogc_template_parse(const char *src, size_t src_len, +sb_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); +void blogc_template_free_stmts(sb_slist_t *stmts); #endif /* _TEMPLATE_GRAMMAR_H */ diff --git a/src/utils/mem.c b/src/utils/mem.c deleted file mode 100644 index 693d555..0000000 --- a/src/utils/mem.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * blogc: A blog compiler. - * Copyright (C) 2014-2016 Rafael G. Martins - * - * This program can be distributed under the terms of the BSD License. - * See the file LICENSE. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - -#include -#include -#include "utils.h" - - -void* -b_malloc(size_t size) -{ - // simple things simple! - void *rv = malloc(size); - if (rv == NULL) { - fprintf(stderr, "fatal error: Failed to allocate memory!\n"); - exit(1); - } - return rv; -} - - -void* -b_realloc(void *ptr, size_t size) -{ - // simple things even simpler :P - void *rv = realloc(ptr, size); - if (rv == NULL && size != 0) { - fprintf(stderr, "fatal error: Failed to reallocate memory!\n"); - free(ptr); - exit(1); - } - return rv; -} diff --git a/src/utils/slist.c b/src/utils/slist.c deleted file mode 100644 index 9753aa7..0000000 --- a/src/utils/slist.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * blogc: A blog compiler. - * Copyright (C) 2014-2016 Rafael G. Martins - * - * This program can be distributed under the terms of the BSD License. - * See the file LICENSE. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - -#include -#include "utils.h" - - -b_slist_t* -b_slist_append(b_slist_t *l, void *data) -{ - b_slist_t *node = malloc(sizeof(b_slist_t)); - if (node == NULL) { - l = NULL; - return l; - } - node->data = data; - node->next = NULL; - if (l == NULL) - l = node; - else { - b_slist_t *tmp; - for (tmp = l; tmp->next != NULL; tmp = tmp->next); - tmp->next = node; - } - return l; -} - - -void -b_slist_free_full(b_slist_t *l, b_free_func_t free_func) -{ - while (l != NULL) { - b_slist_t *tmp = l->next; - free_func(l->data); - free(l); - l = tmp; - } -} - - -void -b_slist_free(b_slist_t *l) -{ - while (l != NULL) { - b_slist_t *tmp = l->next; - free(l); - l = tmp; - } -} - - -unsigned int -b_slist_length(b_slist_t *l) -{ - unsigned int i; - b_slist_t *tmp; - for (tmp = l, i = 0; tmp != NULL; tmp = tmp->next, i++); - return i; -} diff --git a/src/utils/strings.c b/src/utils/strings.c deleted file mode 100644 index 3151612..0000000 --- a/src/utils/strings.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * blogc: A blog compiler. - * Copyright (C) 2014-2016 Rafael G. Martins - * - * This program can be distributed under the terms of the BSD License. - * See the file LICENSE. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - -#include -#include -#include -#include -#include -#include -#include "utils.h" - - -char* -b_strdup(const char *s) -{ - if (s == NULL) - return NULL; - size_t l = strlen(s); - char *tmp = malloc(l + 1); - if (tmp == NULL) - return NULL; - memcpy(tmp, s, l + 1); - return tmp; -} - - -char* -b_strndup(const char *s, size_t n) -{ - if (s == NULL) - return NULL; - size_t l = strnlen(s, n); - char *tmp = malloc(l + 1); - if (tmp == NULL) - return NULL; - memcpy(tmp, s, l); - tmp[l] = '\0'; - return tmp; -} - - -char* -b_strdup_vprintf(const char *format, va_list ap) -{ - va_list ap2; - va_copy(ap2, ap); - int l = vsnprintf(NULL, 0, format, ap2); - va_end(ap2); - if (l < 0) - return NULL; - char *tmp = malloc(l + 1); - if (!tmp) - return NULL; - int l2 = vsnprintf(tmp, l + 1, format, ap); - if (l2 < 0) { - free(tmp); - return NULL; - } - return tmp; -} - - -char* -b_strdup_printf(const char *format, ...) -{ - va_list ap; - va_start(ap, format); - char *tmp = b_strdup_vprintf(format, ap); - va_end(ap); - return tmp; -} - - -bool -b_str_starts_with(const char *str, const char *prefix) -{ - int str_l = strlen(str); - int str_lp = strlen(prefix); - if (str_lp > str_l) - return false; - return strncmp(str, prefix, str_lp) == 0; -} - - -bool -b_str_ends_with(const char *str, const char *suffix) -{ - int str_l = strlen(str); - int str_ls = strlen(suffix); - if (str_ls > str_l) - return false; - return strcmp(str + str_l - str_ls, suffix) == 0; -} - - -char* -b_str_lstrip(char *str) -{ - if (str == NULL) - return NULL; - int i; - size_t str_len = strlen(str); - for (i = 0; i < str_len; i++) { - if ((str[i] != ' ') && (str[i] != '\t') && (str[i] != '\n') && - (str[i] != '\r') && (str[i] != '\t') && (str[i] != '\f') && - (str[i] != '\v')) - { - str += i; - break; - } - if (i == str_len - 1) { - str += str_len; - break; - } - } - return str; -} - - -char* -b_str_rstrip(char *str) -{ - if (str == NULL) - return NULL; - int i; - size_t str_len = strlen(str); - for (i = str_len - 1; i >= 0; i--) { - if ((str[i] != ' ') && (str[i] != '\t') && (str[i] != '\n') && - (str[i] != '\r') && (str[i] != '\t') && (str[i] != '\f') && - (str[i] != '\v')) - { - str[i + 1] = '\0'; - break; - } - if (i == 0) { - str[0] = '\0'; - break; - } - } - return str; -} - - -char* -b_str_strip(char *str) -{ - return b_str_lstrip(b_str_rstrip(str)); -} - - -char** -b_str_split(const char *str, char c, unsigned int max_pieces) -{ - if (!str) - return NULL; - char **rv = b_malloc(sizeof(char*)); - unsigned int i, start = 0, count = 0; - for (i = 0; i < strlen(str) + 1; i++) { - if (str[0] == '\0') - break; - if ((str[i] == c && (!max_pieces || count + 1 < max_pieces)) || str[i] == '\0') { - rv = b_realloc(rv, (count + 1) * sizeof(char*)); - rv[count] = b_malloc(i - start + 1); - memcpy(rv[count], str + start, i - start); - rv[count++][i - start] = '\0'; - start = i + 1; - } - } - rv = b_realloc(rv, (count + 1) * sizeof(char*)); - rv[count] = NULL; - return rv; -} - - -char* -b_str_replace(const char *str, const char search, const char *replace) -{ - char **pieces = b_str_split(str, search, 0); - if (pieces == NULL) - return NULL; - char* rv = b_strv_join((const char**) pieces, replace); - b_strv_free(pieces); - return rv; -} - - -void -b_strv_free(char **strv) -{ - if (strv == NULL) - return; - unsigned int i; - for (i = 0; strv[i] != NULL; i++) - free(strv[i]); - free(strv); -} - - -char* -b_strv_join(const char **strv, const char *separator) -{ - if (strv == NULL) - return NULL; - unsigned int i = 0; - b_string_t *str = b_string_new(); - for (i = 0; strv[i] != NULL; i++) { - str = b_string_append(str, strv[i]); - if (strv[i+1] != NULL) - str = b_string_append(str, separator); - } - return b_string_free(str, false); -} - - -unsigned int -b_strv_length(char **strv) -{ - if (!strv) - return 0; - unsigned int i; - for (i = 0; strv[i] != NULL; i++); - return i; -} - - -b_string_t* -b_string_new(void) -{ - b_string_t* rv = b_malloc(sizeof(b_string_t)); - rv->str = NULL; - rv->len = 0; - rv->allocated_len = 0; - - // initialize with empty string - rv = b_string_append(rv, ""); - - return rv; -} - - -char* -b_string_free(b_string_t *str, bool free_str) -{ - char *rv = NULL; - if (free_str) - free(str->str); - else - rv = str->str; - free(str); - return rv; -} - - -b_string_t* -b_string_append_len(b_string_t *str, const char *suffix, size_t len) -{ - if (suffix == NULL) - return str; - size_t old_len = str->len; - str->len += len; - if (str->len + 1 > str->allocated_len) { - str->allocated_len = (((str->len + 1) / B_STRING_CHUNK_SIZE) + 1) * B_STRING_CHUNK_SIZE; - str->str = b_realloc(str->str, str->allocated_len); - } - memcpy(str->str + old_len, suffix, len); - str->str[str->len] = '\0'; - return str; -} - - -b_string_t* -b_string_append(b_string_t *str, const char *suffix) -{ - if (suffix == NULL) - return str; - return b_string_append_len(str, suffix, strlen(suffix)); -} - - -b_string_t* -b_string_append_c(b_string_t *str, char c) -{ - size_t old_len = str->len; - str->len += 1; - if (str->len + 1 > str->allocated_len) { - str->allocated_len = (((str->len + 1) / B_STRING_CHUNK_SIZE) + 1) * B_STRING_CHUNK_SIZE; - str->str = b_realloc(str->str, str->allocated_len); - } - str->str[old_len] = c; - str->str[str->len] = '\0'; - return str; -} - - -b_string_t* -b_string_append_printf(b_string_t *str, const char *format, ...) -{ - va_list ap; - va_start(ap, format); - char *tmp = b_strdup_vprintf(format, ap); - va_end(ap); - str = b_string_append(str, tmp); - free(tmp); - return str; -} diff --git a/src/utils/trie.c b/src/utils/trie.c deleted file mode 100644 index b8c1e63..0000000 --- a/src/utils/trie.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * blogc: A blog compiler. - * Copyright (C) 2014-2016 Rafael G. Martins - * - * This program can be distributed under the terms of the BSD License. - * See the file LICENSE. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - -#include -#include "utils.h" - - -b_trie_t* -b_trie_new(b_free_func_t free_func) -{ - b_trie_t *trie = b_malloc(sizeof(b_trie_t)); - trie->root = NULL; - trie->free_func = free_func; - return trie; -} - - -static void -b_trie_free_node(b_trie_t *trie, b_trie_node_t *node) -{ - if (node == NULL) - return; - if (node->data != NULL && trie->free_func != NULL) - trie->free_func(node->data); - b_trie_free_node(trie, node->next); - b_trie_free_node(trie, node->child); - free(node); -} - - -void -b_trie_free(b_trie_t *trie) -{ - if (trie == NULL) - return; - b_trie_free_node(trie, trie->root); - free(trie); -} - - -void -b_trie_insert(b_trie_t *trie, const char *key, void *data) -{ - if (data == NULL || key == NULL) - return; - - b_trie_node_t *parent = NULL; - b_trie_node_t *previous; - b_trie_node_t *current; - b_trie_node_t *tmp; - - while (1) { - - if (trie->root == NULL || (parent != NULL && parent->child == NULL)) { - current = b_malloc(sizeof(b_trie_node_t)); - current->key = *key; - current->data = NULL; - current->next = NULL; - current->child = NULL; - if (trie->root == NULL) - trie->root = current; - else - parent->child = current; - parent = current; - goto clean; - } - - tmp = parent == NULL ? trie->root : parent->child; - previous = NULL; - - while (tmp != NULL && tmp->key != *key) { - previous = tmp; - tmp = tmp->next; - } - - parent = tmp; - - if (previous == NULL || parent != NULL) - goto clean; - - current = b_malloc(sizeof(b_trie_node_t)); - current->key = *key; - current->data = NULL; - current->next = NULL; - current->child = NULL; - previous->next = current; - parent = current; - -clean: - if (*key == '\0') { - if (parent->data != NULL && trie->free_func != NULL) - trie->free_func(parent->data); - parent->data = data; - break; - } - key++; - } -} - - -void* -b_trie_lookup(b_trie_t *trie, const char *key) -{ - if (trie->root == NULL || key == NULL) - return NULL; - - b_trie_node_t *parent = trie->root; - b_trie_node_t *tmp; - while (1) { - for (tmp = parent; tmp != NULL; tmp = tmp->next) { - - if (tmp->key == *key) { - if (tmp->key == '\0') - return tmp->data; - parent = tmp->child; - break; - } - } - if (tmp == NULL) - return NULL; - - if (*key == '\0') - break; - key++; - } - return NULL; -} - - -static void -b_trie_size_node(b_trie_node_t *node, unsigned int *count) -{ - if (node == NULL) - return; - - if (node->key == '\0') - (*count)++; - - b_trie_size_node(node->next, count); - b_trie_size_node(node->child, count); -} - - -unsigned int -b_trie_size(b_trie_t *trie) -{ - if (trie == NULL) - return 0; - - unsigned int count = 0; - b_trie_size_node(trie->root, &count); - return count; -} - - -static void -b_trie_foreach_node(b_trie_node_t *node, b_string_t *str, void (*func)(const char *key, void *data)) -{ - if (node == NULL) - return; - - if (node->key == '\0') { - func(str->str, node->data); - b_string_free(str, true); - } - - if (node->child != NULL) { - b_string_t *child = b_string_new(); - child = b_string_append(child, str->str); - child = b_string_append_c(child, node->key); - b_trie_foreach_node(node->child, child, func); - } - - if (node->next != NULL) - b_trie_foreach_node(node->next, str, func); - - if (node->child != NULL && node->next == NULL) - b_string_free(str, true); -} - - -void -b_trie_foreach(b_trie_t *trie, void (*func)(const char *key, void *data)) -{ - if (trie->root == NULL) - return; - - b_string_t *str = b_string_new(); - b_trie_foreach_node(trie->root, str, func); -} diff --git a/src/utils/utils.h b/src/utils/utils.h deleted file mode 100644 index dc67497..0000000 --- a/src/utils/utils.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * blogc: A blog compiler. - * Copyright (C) 2014-2016 Rafael G. Martins - * - * This program can be distributed under the terms of the BSD License. - * See the file LICENSE. - */ - -#ifndef _UTILS_UTILS_H -#define _UTILS_UTILS_H - -#include -#include -#include - -#define B_STRING_CHUNK_SIZE 128 - -typedef void (*b_free_func_t) (void *ptr); - -typedef struct _b_slist_t { - struct _b_slist_t *next; - void *data; -} b_slist_t; - -typedef struct _b_string_t { - char *str; - size_t len; - size_t allocated_len; -} b_string_t; - -typedef struct _b_trie_node_t { - char key; - void *data; - struct _b_trie_node_t *next, *child; -} b_trie_node_t; - -typedef struct _b_trie_t { - b_trie_node_t *root; - b_free_func_t free_func; -} b_trie_t; - -b_slist_t* b_slist_append(b_slist_t *l, void *data); -void b_slist_free_full(b_slist_t *l, b_free_func_t free_func); -void b_slist_free(b_slist_t *l); -unsigned int b_slist_length(b_slist_t *l); - -char* b_strdup(const char *s); -char* b_strndup(const char *s, size_t n); -char* b_strdup_vprintf(const char *format, va_list ap); -char* b_strdup_printf(const char *format, ...); -bool b_str_starts_with(const char *str, const char *prefix); -bool b_str_ends_with(const char *str, const char *suffix); -char* b_str_lstrip(char *str); -char* b_str_rstrip(char *str); -char* b_str_strip(char *str); -char** b_str_split(const char *str, char c, unsigned int max_pieces); -char* b_str_replace(const char *str, const char search, const char *replace); -void b_strv_free(char **strv); -char* b_strv_join(const char **strv, const char *separator); -unsigned int b_strv_length(char **strv); - -b_string_t* b_string_new(void); -char* b_string_free(b_string_t *str, bool free_str); -b_string_t* b_string_append_len(b_string_t *str, const char *suffix, size_t len); -b_string_t* b_string_append(b_string_t *str, const char *suffix); -b_string_t* b_string_append_c(b_string_t *str, char c); -b_string_t* b_string_append_printf(b_string_t *str, const char *format, ...); - -b_trie_t* b_trie_new(b_free_func_t free_func); -void b_trie_free(b_trie_t *trie); -void b_trie_insert(b_trie_t *trie, const char *key, void *data); -void* b_trie_lookup(b_trie_t *trie, const char *key); -unsigned int b_trie_size(b_trie_t *trie); -void b_trie_foreach(b_trie_t *trie, void (*func)(const char *key, void *data)); - -void* b_malloc(size_t size); -void* b_realloc(void *ptr, size_t size); - -#endif /* _UTILS_UTILS_H */ -- cgit v1.2.3-18-g5258 From 2bfe68f6f9fdd34588b8dde73c1a4e96c5a54b7d Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Sat, 5 Mar 2016 19:35:16 +0100 Subject: content-parser: convert -- and --- to &ndash and &mdash --- src/content-parser.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src') diff --git a/src/content-parser.c b/src/content-parser.c index 7e2310f..f5e3aec 100644 --- a/src/content-parser.c +++ b/src/content-parser.c @@ -361,6 +361,21 @@ blogc_content_parse_inline(const char *src) } break; + case '-': + if (state != LINK_CLOSED) + break; + if (current < (src_len - 1) && src[current + 1] == '-') { + if (current < (src_len - 2) && src[current + 2] == '-') { + sb_string_append(rv, "–"); + current += 2; + } + else { + sb_string_append(rv, "—"); + current += 1; + } + } + break; + case '&': if (state == LINK_CLOSED) sb_string_append(rv, "&"); -- cgit v1.2.3-18-g5258 From de986bafd7d765e94059c0e88df93a352d85d7aa Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Sat, 5 Mar 2016 19:39:45 +0100 Subject: content-parser: fixed a bug in previous patch --- src/content-parser.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/content-parser.c b/src/content-parser.c index f5e3aec..e636636 100644 --- a/src/content-parser.c +++ b/src/content-parser.c @@ -374,6 +374,9 @@ blogc_content_parse_inline(const char *src) current += 1; } } + else { + sb_string_append_c(rv, c); + } break; case '&': -- cgit v1.2.3-18-g5258 From 1645987e132d063847aa95c0693570b44bb2d7d5 Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Sat, 5 Mar 2016 19:46:40 +0100 Subject: content-parser: fixed em/en-dash logic --- src/content-parser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/content-parser.c b/src/content-parser.c index e636636..0a87fcb 100644 --- a/src/content-parser.c +++ b/src/content-parser.c @@ -366,11 +366,11 @@ blogc_content_parse_inline(const char *src) break; if (current < (src_len - 1) && src[current + 1] == '-') { if (current < (src_len - 2) && src[current + 2] == '-') { - sb_string_append(rv, "–"); + sb_string_append(rv, "—"); current += 2; } else { - sb_string_append(rv, "—"); + sb_string_append(rv, "–"); current += 1; } } -- cgit v1.2.3-18-g5258 From a2b3551dfb9460470bd79f5648bf597c517c40d4 Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Sun, 13 Mar 2016 01:48:49 +0100 Subject: *: use squareball error infrastructure --- src/datetime-parser.c | 58 +++++++++++++++++++++++++-------------------------- src/datetime-parser.h | 2 +- src/error.c | 47 +++++++---------------------------------- src/error.h | 15 ++++--------- src/file.c | 4 ++-- src/file.h | 2 +- src/loader.c | 12 +++++------ src/loader.h | 6 +++--- src/main.c | 4 ++-- src/renderer.c | 4 ++-- src/source-parser.c | 4 ++-- src/source-parser.h | 2 +- src/template-parser.c | 8 +++---- src/template-parser.h | 2 +- 14 files changed, 65 insertions(+), 105 deletions(-) (limited to 'src') diff --git a/src/datetime-parser.c b/src/datetime-parser.c index 0aeb702..0fa7aaf 100644 --- a/src/datetime-parser.c +++ b/src/datetime-parser.c @@ -47,14 +47,14 @@ typedef enum { char* blogc_convert_datetime(const char *orig, const char *format, - blogc_error_t **err) + sb_error_t **err) { if (err == NULL || *err != NULL) return NULL; #ifndef HAVE_TIME_H - *err = blogc_error_new(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new(BLOGC_WARNING_DATETIME_PARSER, "Your operating system does not supports the datetime functionalities " "used by blogc. Sorry."); return NULL; @@ -80,7 +80,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_YEAR; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid first digit of year. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -91,7 +91,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_THIRD_YEAR; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid second digit of year. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -102,7 +102,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FOURTH_YEAR; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid third digit of year. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -111,7 +111,7 @@ blogc_convert_datetime(const char *orig, const char *format, if (c >= '0' && c <= '9') { tmp += c - diff - 1900; if (tmp < 0) { - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid year. Found %d, must be >= 1900.", tmp + 1900); break; @@ -120,7 +120,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FIRST_HYPHEN; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid fourth digit of year. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -131,7 +131,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FIRST_MONTH; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid separator between year and month. " "Found '%c', must be '-'.", c); break; @@ -142,7 +142,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_MONTH; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid first digit of month. " "Found '%c', must be integer >= 0 and <= 1.", c); break; @@ -151,7 +151,7 @@ blogc_convert_datetime(const char *orig, const char *format, if (c >= '0' && c <= '9') { tmp += c - diff - 1; if (tmp < 0 || tmp > 11) { - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid month. Found %d, must be >= 1 and <= 12.", tmp + 1); break; @@ -160,7 +160,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_HYPHEN; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid second digit of month. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -171,7 +171,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FIRST_DAY; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid separator between month and day. " "Found '%c', must be '-'.", c); break; @@ -182,7 +182,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_DAY; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid first digit of day. " "Found '%c', must be integer >= 0 and <= 3.", c); break; @@ -191,7 +191,7 @@ blogc_convert_datetime(const char *orig, const char *format, if (c >= '0' && c <= '9') { tmp += c - diff; if (tmp < 1 || tmp > 31) { - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid day. Found %d, must be >= 1 and <= 31.", tmp); break; @@ -200,7 +200,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SPACE; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid second digit of day. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -211,7 +211,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FIRST_HOUR; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid separator between date and time. " "Found '%c', must be ' ' (empty space).", c); break; @@ -222,7 +222,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_HOUR; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid first digit of hours. " "Found '%c', must be integer >= 0 and <= 2.", c); break; @@ -231,7 +231,7 @@ blogc_convert_datetime(const char *orig, const char *format, if (c >= '0' && c <= '9') { tmp += c - diff; if (tmp < 0 || tmp > 23) { - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid hours. Found %d, must be >= 0 and <= 23.", tmp); break; @@ -240,7 +240,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FIRST_COLON; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid second digit of hours. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -251,7 +251,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FIRST_MINUTE; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid separator between hours and minutes. " "Found '%c', must be ':'.", c); break; @@ -262,7 +262,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_MINUTE; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid first digit of minutes. " "Found '%c', must be integer >= 0 and <= 5.", c); break; @@ -274,7 +274,7 @@ blogc_convert_datetime(const char *orig, const char *format, // this won't happen because we are restricting the digits // to 00-59 already, but lets keep the code here for // reference. - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid minutes. Found %d, must be >= 0 and <= 59.", tmp); break; @@ -283,7 +283,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_COLON; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid second digit of minutes. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -294,7 +294,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FIRST_SECOND; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid separator between minutes and seconds. " "Found '%c', must be ':'.", c); break; @@ -305,7 +305,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_SECOND; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid first digit of seconds. " "Found '%c', must be integer >= 0 and <= 6.", c); break; @@ -314,7 +314,7 @@ blogc_convert_datetime(const char *orig, const char *format, if (c >= '0' && c <= '9') { tmp += c - diff; if (tmp < 0 || tmp > 60) { - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid seconds. Found %d, must be >= 0 and <= 60.", tmp); break; @@ -323,7 +323,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_DONE; break; } - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid second digit of seconds. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -355,7 +355,7 @@ blogc_convert_datetime(const char *orig, const char *format, case DATETIME_SECOND_MINUTE: case DATETIME_FIRST_SECOND: case DATETIME_SECOND_SECOND: - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid datetime string. " "Found '%s', formats allowed are: 'yyyy-mm-dd hh:mm:ss', " "'yyyy-mm-dd hh:ss', 'yyyy-mm-dd hh' and 'yyyy-mm-dd'.", @@ -374,7 +374,7 @@ blogc_convert_datetime(const char *orig, const char *format, char buf[1024]; if (0 == strftime(buf, sizeof(buf), format, &t)) { - *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Failed to format DATE variable, FORMAT is too long: %s", format); return NULL; diff --git a/src/datetime-parser.h b/src/datetime-parser.h index a5087b3..b2e65a1 100644 --- a/src/datetime-parser.h +++ b/src/datetime-parser.h @@ -12,6 +12,6 @@ #include "error.h" char* blogc_convert_datetime(const char *orig, const char *format, - blogc_error_t **err); + sb_error_t **err); #endif /* _DATETIME_H */ diff --git a/src/error.c b/src/error.c index f05049c..619ae01 100644 --- a/src/error.c +++ b/src/error.c @@ -18,31 +18,8 @@ #include "error.h" -blogc_error_t* -blogc_error_new(blogc_error_type_t type, const char *msg) -{ - blogc_error_t *err = sb_malloc(sizeof(blogc_error_t)); - err->type = type; - err->msg = sb_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 = sb_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, +sb_error_t* +blogc_error_parser(blogc_error_code_t type, const char *src, size_t src_len, size_t current, const char *format, ...) { va_list ap; @@ -90,12 +67,12 @@ blogc_error_parser(blogc_error_type_t type, const char *src, size_t src_len, char *line = sb_strndup(src + linestart, lineend - linestart); - blogc_error_t *rv = NULL; + sb_error_t *rv = NULL; if (line[0] == '\0') // "near" message isn't useful if line is empty - rv = blogc_error_new(type, msg); + rv = sb_error_new(type, msg); else - rv = blogc_error_new_printf(type, + rv = sb_error_new_printf(type, "%s\nError occurred near line %d, position %d: %s", msg, lineno, pos, line); @@ -107,12 +84,12 @@ blogc_error_parser(blogc_error_type_t type, const char *src, size_t src_len, void -blogc_error_print(blogc_error_t *err) +blogc_error_print(sb_error_t *err) { if (err == NULL) return; - switch(err->type) { + switch(err->code) { case BLOGC_ERROR_SOURCE_PARSER: fprintf(stderr, "blogc: error: source: %s\n", err->msg); break; @@ -129,13 +106,3 @@ blogc_error_print(blogc_error_t *err) fprintf(stderr, "blogc: error: %s\n", err->msg); } } - - -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 index caa86b0..e02afed 100644 --- a/src/error.h +++ b/src/error.h @@ -11,24 +11,17 @@ #include #include +#include typedef enum { BLOGC_ERROR_SOURCE_PARSER = 1, BLOGC_ERROR_TEMPLATE_PARSER, BLOGC_ERROR_LOADER, BLOGC_WARNING_DATETIME_PARSER, -} blogc_error_type_t; +} blogc_error_code_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, +sb_error_t* blogc_error_parser(blogc_error_code_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); +void blogc_error_print(sb_error_t *err); #endif /* _ERROR_H */ diff --git a/src/file.c b/src/file.c index dec7c1b..972f433 100644 --- a/src/file.c +++ b/src/file.c @@ -23,7 +23,7 @@ char* -blogc_file_get_contents(const char *path, size_t *len, blogc_error_t **err) +blogc_file_get_contents(const char *path, size_t *len, sb_error_t **err) { if (path == NULL || err == NULL || *err != NULL) return NULL; @@ -33,7 +33,7 @@ blogc_file_get_contents(const char *path, size_t *len, blogc_error_t **err) if (fp == NULL) { int tmp_errno = errno; - *err = blogc_error_new_printf(BLOGC_ERROR_LOADER, + *err = sb_error_new_printf(BLOGC_ERROR_LOADER, "Failed to open file (%s): %s", path, strerror(tmp_errno)); return NULL; } diff --git a/src/file.h b/src/file.h index 97e5274..9c0674d 100644 --- a/src/file.h +++ b/src/file.h @@ -15,7 +15,7 @@ #define BLOGC_FILE_CHUNK_SIZE 1024 -char* blogc_file_get_contents(const char *path, size_t *len, blogc_error_t **err); +char* blogc_file_get_contents(const char *path, size_t *len, sb_error_t **err); int blogc_fprintf(FILE *stream, const char *format, ...); #endif /* _FILE_H */ diff --git a/src/loader.c b/src/loader.c index 8008c3a..fd184e5 100644 --- a/src/loader.c +++ b/src/loader.c @@ -60,7 +60,7 @@ blogc_get_filename(const char *f) sb_slist_t* -blogc_template_parse_from_file(const char *f, blogc_error_t **err) +blogc_template_parse_from_file(const char *f, sb_error_t **err) { if (err == NULL || *err != NULL) return NULL; @@ -75,7 +75,7 @@ blogc_template_parse_from_file(const char *f, blogc_error_t **err) sb_trie_t* -blogc_source_parse_from_file(const char *f, blogc_error_t **err) +blogc_source_parse_from_file(const char *f, sb_error_t **err) { if (err == NULL || *err != NULL) return NULL; @@ -98,9 +98,9 @@ blogc_source_parse_from_file(const char *f, blogc_error_t **err) sb_slist_t* -blogc_source_parse_from_files(sb_trie_t *conf, sb_slist_t *l, blogc_error_t **err) +blogc_source_parse_from_files(sb_trie_t *conf, sb_slist_t *l, sb_error_t **err) { - blogc_error_t *tmp_err = NULL; + sb_error_t *tmp_err = NULL; sb_slist_t *rv = NULL; unsigned int with_date = 0; @@ -125,10 +125,10 @@ blogc_source_parse_from_files(sb_trie_t *conf, sb_slist_t *l, blogc_error_t **er char *f = tmp->data; sb_trie_t *s = blogc_source_parse_from_file(f, &tmp_err); if (s == NULL) { - *err = blogc_error_new_printf(BLOGC_ERROR_LOADER, + *err = sb_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); + sb_error_free(tmp_err); tmp_err = NULL; sb_slist_free_full(rv, (sb_free_func_t) sb_trie_free); rv = NULL; diff --git a/src/loader.h b/src/loader.h index 080aff6..8b0460e 100644 --- a/src/loader.h +++ b/src/loader.h @@ -13,9 +13,9 @@ #include "error.h" char* blogc_get_filename(const char *f); -sb_slist_t* blogc_template_parse_from_file(const char *f, blogc_error_t **err); -sb_trie_t* blogc_source_parse_from_file(const char *f, blogc_error_t **err); +sb_slist_t* blogc_template_parse_from_file(const char *f, sb_error_t **err); +sb_trie_t* blogc_source_parse_from_file(const char *f, sb_error_t **err); sb_slist_t* blogc_source_parse_from_files(sb_trie_t *conf, sb_slist_t *l, - blogc_error_t **err); + sb_error_t **err); #endif /* _LOADER_H */ diff --git a/src/main.c b/src/main.c index 143c836..709b37e 100644 --- a/src/main.c +++ b/src/main.c @@ -210,7 +210,7 @@ main(int argc, char **argv) goto cleanup; } - blogc_error_t *err = NULL; + sb_error_t *err = NULL; sb_slist_t *s = blogc_source_parse_from_files(config, sources, &err); if (err != NULL) { @@ -274,7 +274,7 @@ cleanup3: blogc_template_free_stmts(l); cleanup2: sb_slist_free_full(s, (sb_free_func_t) sb_trie_free); - blogc_error_free(err); + sb_error_free(err); cleanup: sb_trie_free(config); free(template); diff --git a/src/renderer.c b/src/renderer.c index a7a7dd7..eb58e0d 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -46,11 +46,11 @@ blogc_format_date(const char *date, sb_trie_t *global, sb_trie_t *local) if (date_format == NULL) return sb_strdup(date); - blogc_error_t *err = NULL; + sb_error_t *err = NULL; char *rv = blogc_convert_datetime(date, date_format, &err); if (err != NULL) { blogc_error_print(err); - blogc_error_free(err); + sb_error_free(err); return sb_strdup(date); } return rv; diff --git a/src/source-parser.c b/src/source-parser.c index e3662a2..1047f06 100644 --- a/src/source-parser.c +++ b/src/source-parser.c @@ -31,7 +31,7 @@ typedef enum { sb_trie_t* -blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err) +blogc_source_parse(const char *src, size_t src_len, sb_error_t **err) { if (err == NULL || *err != NULL) return NULL; @@ -97,7 +97,7 @@ blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err) ((current - start == 13) && (0 == strncmp("BLOGC_VERSION", src + start, 13)))) { - *err = blogc_error_new_printf(BLOGC_ERROR_SOURCE_PARSER, + *err = sb_error_new_printf(BLOGC_ERROR_SOURCE_PARSER, "'%s' variable is forbidden in source files. It will " "be set for you by the compiler.", key); break; diff --git a/src/source-parser.h b/src/source-parser.h index 460aedb..fb5306c 100644 --- a/src/source-parser.h +++ b/src/source-parser.h @@ -14,6 +14,6 @@ #include "error.h" sb_trie_t* blogc_source_parse(const char *src, size_t src_len, - blogc_error_t **err); + sb_error_t **err); #endif /* _SOURCE_PARSER_H */ diff --git a/src/template-parser.c b/src/template-parser.c index 6f23ef1..d61f90a 100644 --- a/src/template-parser.c +++ b/src/template-parser.c @@ -53,7 +53,7 @@ typedef enum { sb_slist_t* -blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) +blogc_template_parse(const char *src, size_t src_len, sb_error_t **err) { if (err == NULL || *err != NULL) return NULL; @@ -597,14 +597,14 @@ blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, src_len, start2 - 1, "Found an open double-quoted string."); else if (if_count != 0) - *err = blogc_error_new_printf(BLOGC_ERROR_TEMPLATE_PARSER, + *err = sb_error_new_printf(BLOGC_ERROR_TEMPLATE_PARSER, "%d open 'ifdef' and/or 'ifndef' statements were not closed!", if_count); else if (block_state != BLOCK_CLOSED) - *err = blogc_error_new(BLOGC_ERROR_TEMPLATE_PARSER, + *err = sb_error_new(BLOGC_ERROR_TEMPLATE_PARSER, "An open block was not closed!"); else if (foreach_open) - *err = blogc_error_new(BLOGC_ERROR_TEMPLATE_PARSER, + *err = sb_error_new(BLOGC_ERROR_TEMPLATE_PARSER, "An open 'foreach' statement was not closed!"); } diff --git a/src/template-parser.h b/src/template-parser.h index de5113e..88b46e9 100644 --- a/src/template-parser.h +++ b/src/template-parser.h @@ -45,7 +45,7 @@ typedef struct { } blogc_template_stmt_t; sb_slist_t* blogc_template_parse(const char *src, size_t src_len, - blogc_error_t **err); + sb_error_t **err); void blogc_template_free_stmts(sb_slist_t *stmts); #endif /* _TEMPLATE_GRAMMAR_H */ -- cgit v1.2.3-18-g5258 From c7b4bc4d64a3ce669e54b7c7dae87527d9ee3123 Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Sat, 19 Mar 2016 10:36:16 +0100 Subject: main: loader: use file utils from squareball --- src/file.c | 26 +------------------------- src/main.c | 52 ++++++++++++++++------------------------------------ 2 files changed, 17 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/file.c b/src/file.c index 972f433..a12fbc2 100644 --- a/src/file.c +++ b/src/file.c @@ -10,10 +10,8 @@ #include #endif /* HAVE_CONFIG_H */ -#include #include #include -#include #include #include "file.h" #include "error.h" @@ -25,29 +23,7 @@ char* blogc_file_get_contents(const char *path, size_t *len, sb_error_t **err) { - if (path == NULL || err == NULL || *err != NULL) - return NULL; - - *len = 0; - FILE *fp = fopen(path, "r"); - - if (fp == NULL) { - int tmp_errno = errno; - *err = sb_error_new_printf(BLOGC_ERROR_LOADER, - "Failed to open file (%s): %s", path, strerror(tmp_errno)); - return NULL; - } - - sb_string_t *str = sb_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; - sb_string_append_len(str, buffer, read_len); - } - fclose(fp); - return sb_string_free(str, false); + return sb_file_get_contents(path, len, err); } diff --git a/src/main.c b/src/main.c index 709b37e..1f5c76c 100644 --- a/src/main.c +++ b/src/main.c @@ -18,6 +18,10 @@ #include #endif /* HAVE_SYS_TYPES_H */ +#ifdef HAVE_LIBGEN_H +#include +#endif /* HAVE_LIBGEN_H */ + #include #include #include @@ -68,41 +72,6 @@ blogc_print_usage(void) } -static void -blogc_mkdir_recursive(const char *filename) -{ - char *fname = sb_strdup(filename); - for (char *tmp = fname; *tmp != '\0'; tmp++) { - if (*tmp != '/' && *tmp != '\\') - continue; -#if defined(HAVE_SYS_STAT_H) && defined(HAVE_SYS_TYPES_H) - char bkp = *tmp; - *tmp = '\0'; - if ((strlen(fname) > 0) && -#if defined(WIN32) || defined(_WIN32) - (-1 == mkdir(fname)) && -#else - (-1 == mkdir(fname, 0777)) && -#endif - (errno != EEXIST)) - { - fprintf(stderr, "blogc: error: failed to create output " - "directory (%s): %s\n", fname, strerror(errno)); - free(fname); - exit(2); - } - *tmp = bkp; -#else - // FIXME: show this warning only if actually trying to create a directory. - fprintf(stderr, "blogc: warning: can't create output directories " - "for your platform. please create the directories yourself.\n"); - break; -#endif - } - free(fname); -} - - int main(int argc, char **argv) { @@ -252,7 +221,18 @@ main(int argc, char **argv) FILE *fp = stdout; if (!write_to_stdout) { - blogc_mkdir_recursive(output); + +#ifdef HAVE_LIBGEN_H + char *_output = sb_strdup(output); + sb_mkdir_recursive(dirname(_output), &err); + free(_output); + if (err != NULL) { + blogc_error_print(err); + rv = 2; + goto cleanup4; + } +#endif + fp = fopen(output, "w"); if (fp == NULL) { fprintf(stderr, "blogc: error: failed to open output file (%s): %s\n", -- cgit v1.2.3-18-g5258 From 001c16ac605ee65f5688534e42c10395db3f0d5a Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Sun, 17 Apr 2016 04:01:51 +0200 Subject: content-parser: do not convert -- and --- to &ndash and &mdash inside code --- src/content-parser.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/content-parser.c b/src/content-parser.c index 0a87fcb..782a85d 100644 --- a/src/content-parser.c +++ b/src/content-parser.c @@ -364,7 +364,9 @@ blogc_content_parse_inline(const char *src) case '-': if (state != LINK_CLOSED) break; - if (current < (src_len - 1) && src[current + 1] == '-') { + if ((current < (src_len - 1) && src[current + 1] == '-') && + !(open_code || open_code_double)) + { if (current < (src_len - 2) && src[current + 2] == '-') { sb_string_append(rv, "—"); current += 2; -- cgit v1.2.3-18-g5258 From 9b2a563b4931ca39cd6dd14bf85cda627714a4b2 Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Wed, 20 Apr 2016 02:50:20 +0200 Subject: content-parser: extract post description from content description is the first line of the first paragraph parsed from content file. users can override it declaring DESCRIPTION variable in source file itself. this also fixes a bug with line endings when using single line blockquotes. --- src/content-parser.c | 16 +++++++--------- src/content-parser.h | 3 ++- src/source-parser.c | 14 +++++++++++++- 3 files changed, 22 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/content-parser.c b/src/content-parser.c index 782a85d..795cc34 100644 --- a/src/content-parser.c +++ b/src/content-parser.c @@ -460,7 +460,7 @@ blogc_is_ordered_list_item(const char *str, size_t prefix_len) char* -blogc_content_parse(const char *src, size_t *end_excerpt) +blogc_content_parse(const char *src, size_t *end_excerpt, char **description) { // src is always nul-terminated. size_t src_len = strlen(src); @@ -698,14 +698,10 @@ blogc_content_parse(const char *src, size_t *end_excerpt) case CONTENT_BLOCKQUOTE_END: if (c == '\n' || c == '\r' || is_last) { tmp_str = sb_string_new(); - for (sb_slist_t *l = lines; l != NULL; l = l->next) { - if (l->next == NULL) - sb_string_append_printf(tmp_str, "%s", l->data); - else - sb_string_append_printf(tmp_str, "%s%s", l->data, - line_ending); - } - tmp = blogc_content_parse(tmp_str->str, NULL); + for (sb_slist_t *l = lines; l != NULL; l = l->next) + sb_string_append_printf(tmp_str, "%s%s", l->data, + line_ending); + tmp = blogc_content_parse(tmp_str->str, NULL, description); sb_string_append_printf(rv, "
%s
%s", tmp, line_ending); free(tmp); @@ -1019,6 +1015,8 @@ blogc_content_parse(const char *src, size_t *end_excerpt) state = CONTENT_PARAGRAPH_END; end = is_last && c != '\n' && c != '\r' ? src_len : (real_end != 0 ? real_end : current); + if (description != NULL && *description == NULL) + *description = sb_strndup(src + start, end - start); } if (!is_last) break; diff --git a/src/content-parser.h b/src/content-parser.h index 6617bb4..148d5ed 100644 --- a/src/content-parser.h +++ b/src/content-parser.h @@ -16,6 +16,7 @@ char* blogc_slugify(const char *str); char* blogc_htmlentities(const char *str); char* blogc_content_parse_inline(const char *src); bool blogc_is_ordered_list_item(const char *str, size_t prefix_len); -char* blogc_content_parse(const char *src, size_t *end_excerpt); +char* blogc_content_parse(const char *src, size_t *end_excerpt, + char **description); #endif /* _CONTENT_PARSER_H */ diff --git a/src/source-parser.c b/src/source-parser.c index 1047f06..6e026d2 100644 --- a/src/source-parser.c +++ b/src/source-parser.c @@ -154,7 +154,19 @@ blogc_source_parse(const char *src, size_t src_len, sb_error_t **err) if (current == (src_len - 1)) { tmp = sb_strndup(src + start, src_len - start); sb_trie_insert(rv, "RAW_CONTENT", tmp); - content = blogc_content_parse(tmp, &end_excerpt); + char *description = NULL; + content = blogc_content_parse(tmp, &end_excerpt, &description); + if (description != NULL) { + // do not override source-provided description. + if (NULL == sb_trie_lookup(rv, "DESCRIPTION")) { + // no need to free, because we are transfering memory + // ownership to the trie. + sb_trie_insert(rv, "DESCRIPTION", description); + } + else { + free(description); + } + } sb_trie_insert(rv, "CONTENT", content); sb_trie_insert(rv, "EXCERPT", end_excerpt == 0 ? sb_strdup(content) : sb_strndup(content, end_excerpt)); -- cgit v1.2.3-18-g5258 From 25c2e03228e00f577fac4a52079c601010df4f15 Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Wed, 27 Apr 2016 01:30:12 +0200 Subject: Revert "main: loader: use file utils from squareball" This reverts commit c7b4bc4d64a3ce669e54b7c7dae87527d9ee3123. --- src/file.c | 26 +++++++++++++++++++++++++- src/main.c | 52 ++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 61 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/file.c b/src/file.c index a12fbc2..972f433 100644 --- a/src/file.c +++ b/src/file.c @@ -10,8 +10,10 @@ #include #endif /* HAVE_CONFIG_H */ +#include #include #include +#include #include #include "file.h" #include "error.h" @@ -23,7 +25,29 @@ char* blogc_file_get_contents(const char *path, size_t *len, sb_error_t **err) { - return sb_file_get_contents(path, len, err); + if (path == NULL || err == NULL || *err != NULL) + return NULL; + + *len = 0; + FILE *fp = fopen(path, "r"); + + if (fp == NULL) { + int tmp_errno = errno; + *err = sb_error_new_printf(BLOGC_ERROR_LOADER, + "Failed to open file (%s): %s", path, strerror(tmp_errno)); + return NULL; + } + + sb_string_t *str = sb_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; + sb_string_append_len(str, buffer, read_len); + } + fclose(fp); + return sb_string_free(str, false); } diff --git a/src/main.c b/src/main.c index 1f5c76c..709b37e 100644 --- a/src/main.c +++ b/src/main.c @@ -18,10 +18,6 @@ #include #endif /* HAVE_SYS_TYPES_H */ -#ifdef HAVE_LIBGEN_H -#include -#endif /* HAVE_LIBGEN_H */ - #include #include #include @@ -72,6 +68,41 @@ blogc_print_usage(void) } +static void +blogc_mkdir_recursive(const char *filename) +{ + char *fname = sb_strdup(filename); + for (char *tmp = fname; *tmp != '\0'; tmp++) { + if (*tmp != '/' && *tmp != '\\') + continue; +#if defined(HAVE_SYS_STAT_H) && defined(HAVE_SYS_TYPES_H) + char bkp = *tmp; + *tmp = '\0'; + if ((strlen(fname) > 0) && +#if defined(WIN32) || defined(_WIN32) + (-1 == mkdir(fname)) && +#else + (-1 == mkdir(fname, 0777)) && +#endif + (errno != EEXIST)) + { + fprintf(stderr, "blogc: error: failed to create output " + "directory (%s): %s\n", fname, strerror(errno)); + free(fname); + exit(2); + } + *tmp = bkp; +#else + // FIXME: show this warning only if actually trying to create a directory. + fprintf(stderr, "blogc: warning: can't create output directories " + "for your platform. please create the directories yourself.\n"); + break; +#endif + } + free(fname); +} + + int main(int argc, char **argv) { @@ -221,18 +252,7 @@ main(int argc, char **argv) FILE *fp = stdout; if (!write_to_stdout) { - -#ifdef HAVE_LIBGEN_H - char *_output = sb_strdup(output); - sb_mkdir_recursive(dirname(_output), &err); - free(_output); - if (err != NULL) { - blogc_error_print(err); - rv = 2; - goto cleanup4; - } -#endif - + blogc_mkdir_recursive(output); fp = fopen(output, "w"); if (fp == NULL) { fprintf(stderr, "blogc: error: failed to open output file (%s): %s\n", -- cgit v1.2.3-18-g5258 From 6153580a13e7e7c48e38fa446572c8adcae08084 Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Wed, 27 Apr 2016 01:31:02 +0200 Subject: Revert "*: use squareball error infrastructure" This reverts commit a2b3551dfb9460470bd79f5648bf597c517c40d4. --- src/datetime-parser.c | 58 +++++++++++++++++++++++++-------------------------- src/datetime-parser.h | 2 +- src/error.c | 47 ++++++++++++++++++++++++++++++++++------- src/error.h | 15 +++++++++---- src/file.c | 4 ++-- src/file.h | 2 +- src/loader.c | 12 +++++------ src/loader.h | 6 +++--- src/main.c | 4 ++-- src/renderer.c | 4 ++-- src/source-parser.c | 4 ++-- src/source-parser.h | 2 +- src/template-parser.c | 8 +++---- src/template-parser.h | 2 +- 14 files changed, 105 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/datetime-parser.c b/src/datetime-parser.c index 0fa7aaf..0aeb702 100644 --- a/src/datetime-parser.c +++ b/src/datetime-parser.c @@ -47,14 +47,14 @@ typedef enum { char* blogc_convert_datetime(const char *orig, const char *format, - sb_error_t **err) + blogc_error_t **err) { if (err == NULL || *err != NULL) return NULL; #ifndef HAVE_TIME_H - *err = sb_error_new(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new(BLOGC_WARNING_DATETIME_PARSER, "Your operating system does not supports the datetime functionalities " "used by blogc. Sorry."); return NULL; @@ -80,7 +80,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_YEAR; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid first digit of year. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -91,7 +91,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_THIRD_YEAR; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid second digit of year. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -102,7 +102,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FOURTH_YEAR; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid third digit of year. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -111,7 +111,7 @@ blogc_convert_datetime(const char *orig, const char *format, if (c >= '0' && c <= '9') { tmp += c - diff - 1900; if (tmp < 0) { - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid year. Found %d, must be >= 1900.", tmp + 1900); break; @@ -120,7 +120,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FIRST_HYPHEN; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid fourth digit of year. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -131,7 +131,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FIRST_MONTH; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid separator between year and month. " "Found '%c', must be '-'.", c); break; @@ -142,7 +142,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_MONTH; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid first digit of month. " "Found '%c', must be integer >= 0 and <= 1.", c); break; @@ -151,7 +151,7 @@ blogc_convert_datetime(const char *orig, const char *format, if (c >= '0' && c <= '9') { tmp += c - diff - 1; if (tmp < 0 || tmp > 11) { - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid month. Found %d, must be >= 1 and <= 12.", tmp + 1); break; @@ -160,7 +160,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_HYPHEN; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid second digit of month. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -171,7 +171,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FIRST_DAY; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid separator between month and day. " "Found '%c', must be '-'.", c); break; @@ -182,7 +182,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_DAY; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid first digit of day. " "Found '%c', must be integer >= 0 and <= 3.", c); break; @@ -191,7 +191,7 @@ blogc_convert_datetime(const char *orig, const char *format, if (c >= '0' && c <= '9') { tmp += c - diff; if (tmp < 1 || tmp > 31) { - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid day. Found %d, must be >= 1 and <= 31.", tmp); break; @@ -200,7 +200,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SPACE; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid second digit of day. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -211,7 +211,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FIRST_HOUR; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid separator between date and time. " "Found '%c', must be ' ' (empty space).", c); break; @@ -222,7 +222,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_HOUR; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid first digit of hours. " "Found '%c', must be integer >= 0 and <= 2.", c); break; @@ -231,7 +231,7 @@ blogc_convert_datetime(const char *orig, const char *format, if (c >= '0' && c <= '9') { tmp += c - diff; if (tmp < 0 || tmp > 23) { - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid hours. Found %d, must be >= 0 and <= 23.", tmp); break; @@ -240,7 +240,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FIRST_COLON; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid second digit of hours. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -251,7 +251,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FIRST_MINUTE; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid separator between hours and minutes. " "Found '%c', must be ':'.", c); break; @@ -262,7 +262,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_MINUTE; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid first digit of minutes. " "Found '%c', must be integer >= 0 and <= 5.", c); break; @@ -274,7 +274,7 @@ blogc_convert_datetime(const char *orig, const char *format, // this won't happen because we are restricting the digits // to 00-59 already, but lets keep the code here for // reference. - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid minutes. Found %d, must be >= 0 and <= 59.", tmp); break; @@ -283,7 +283,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_COLON; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid second digit of minutes. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -294,7 +294,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_FIRST_SECOND; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid separator between minutes and seconds. " "Found '%c', must be ':'.", c); break; @@ -305,7 +305,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_SECOND_SECOND; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid first digit of seconds. " "Found '%c', must be integer >= 0 and <= 6.", c); break; @@ -314,7 +314,7 @@ blogc_convert_datetime(const char *orig, const char *format, if (c >= '0' && c <= '9') { tmp += c - diff; if (tmp < 0 || tmp > 60) { - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid seconds. Found %d, must be >= 0 and <= 60.", tmp); break; @@ -323,7 +323,7 @@ blogc_convert_datetime(const char *orig, const char *format, state = DATETIME_DONE; break; } - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid second digit of seconds. " "Found '%c', must be integer >= 0 and <= 9.", c); break; @@ -355,7 +355,7 @@ blogc_convert_datetime(const char *orig, const char *format, case DATETIME_SECOND_MINUTE: case DATETIME_FIRST_SECOND: case DATETIME_SECOND_SECOND: - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Invalid datetime string. " "Found '%s', formats allowed are: 'yyyy-mm-dd hh:mm:ss', " "'yyyy-mm-dd hh:ss', 'yyyy-mm-dd hh' and 'yyyy-mm-dd'.", @@ -374,7 +374,7 @@ blogc_convert_datetime(const char *orig, const char *format, char buf[1024]; if (0 == strftime(buf, sizeof(buf), format, &t)) { - *err = sb_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, + *err = blogc_error_new_printf(BLOGC_WARNING_DATETIME_PARSER, "Failed to format DATE variable, FORMAT is too long: %s", format); return NULL; diff --git a/src/datetime-parser.h b/src/datetime-parser.h index b2e65a1..a5087b3 100644 --- a/src/datetime-parser.h +++ b/src/datetime-parser.h @@ -12,6 +12,6 @@ #include "error.h" char* blogc_convert_datetime(const char *orig, const char *format, - sb_error_t **err); + blogc_error_t **err); #endif /* _DATETIME_H */ diff --git a/src/error.c b/src/error.c index 619ae01..f05049c 100644 --- a/src/error.c +++ b/src/error.c @@ -18,8 +18,31 @@ #include "error.h" -sb_error_t* -blogc_error_parser(blogc_error_code_t type, const char *src, size_t src_len, +blogc_error_t* +blogc_error_new(blogc_error_type_t type, const char *msg) +{ + blogc_error_t *err = sb_malloc(sizeof(blogc_error_t)); + err->type = type; + err->msg = sb_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 = sb_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; @@ -67,12 +90,12 @@ blogc_error_parser(blogc_error_code_t type, const char *src, size_t src_len, char *line = sb_strndup(src + linestart, lineend - linestart); - sb_error_t *rv = NULL; + blogc_error_t *rv = NULL; if (line[0] == '\0') // "near" message isn't useful if line is empty - rv = sb_error_new(type, msg); + rv = blogc_error_new(type, msg); else - rv = sb_error_new_printf(type, + rv = blogc_error_new_printf(type, "%s\nError occurred near line %d, position %d: %s", msg, lineno, pos, line); @@ -84,12 +107,12 @@ blogc_error_parser(blogc_error_code_t type, const char *src, size_t src_len, void -blogc_error_print(sb_error_t *err) +blogc_error_print(blogc_error_t *err) { if (err == NULL) return; - switch(err->code) { + switch(err->type) { case BLOGC_ERROR_SOURCE_PARSER: fprintf(stderr, "blogc: error: source: %s\n", err->msg); break; @@ -106,3 +129,13 @@ blogc_error_print(sb_error_t *err) fprintf(stderr, "blogc: error: %s\n", err->msg); } } + + +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 index e02afed..caa86b0 100644 --- a/src/error.h +++ b/src/error.h @@ -11,17 +11,24 @@ #include #include -#include typedef enum { BLOGC_ERROR_SOURCE_PARSER = 1, BLOGC_ERROR_TEMPLATE_PARSER, BLOGC_ERROR_LOADER, BLOGC_WARNING_DATETIME_PARSER, -} blogc_error_code_t; +} blogc_error_type_t; -sb_error_t* blogc_error_parser(blogc_error_code_t type, const char *src, +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(sb_error_t *err); +void blogc_error_print(blogc_error_t *err); +void blogc_error_free(blogc_error_t *err); #endif /* _ERROR_H */ diff --git a/src/file.c b/src/file.c index 972f433..dec7c1b 100644 --- a/src/file.c +++ b/src/file.c @@ -23,7 +23,7 @@ char* -blogc_file_get_contents(const char *path, size_t *len, sb_error_t **err) +blogc_file_get_contents(const char *path, size_t *len, blogc_error_t **err) { if (path == NULL || err == NULL || *err != NULL) return NULL; @@ -33,7 +33,7 @@ blogc_file_get_contents(const char *path, size_t *len, sb_error_t **err) if (fp == NULL) { int tmp_errno = errno; - *err = sb_error_new_printf(BLOGC_ERROR_LOADER, + *err = blogc_error_new_printf(BLOGC_ERROR_LOADER, "Failed to open file (%s): %s", path, strerror(tmp_errno)); return NULL; } diff --git a/src/file.h b/src/file.h index 9c0674d..97e5274 100644 --- a/src/file.h +++ b/src/file.h @@ -15,7 +15,7 @@ #define BLOGC_FILE_CHUNK_SIZE 1024 -char* blogc_file_get_contents(const char *path, size_t *len, sb_error_t **err); +char* blogc_file_get_contents(const char *path, size_t *len, blogc_error_t **err); int blogc_fprintf(FILE *stream, const char *format, ...); #endif /* _FILE_H */ diff --git a/src/loader.c b/src/loader.c index fd184e5..8008c3a 100644 --- a/src/loader.c +++ b/src/loader.c @@ -60,7 +60,7 @@ blogc_get_filename(const char *f) sb_slist_t* -blogc_template_parse_from_file(const char *f, sb_error_t **err) +blogc_template_parse_from_file(const char *f, blogc_error_t **err) { if (err == NULL || *err != NULL) return NULL; @@ -75,7 +75,7 @@ blogc_template_parse_from_file(const char *f, sb_error_t **err) sb_trie_t* -blogc_source_parse_from_file(const char *f, sb_error_t **err) +blogc_source_parse_from_file(const char *f, blogc_error_t **err) { if (err == NULL || *err != NULL) return NULL; @@ -98,9 +98,9 @@ blogc_source_parse_from_file(const char *f, sb_error_t **err) sb_slist_t* -blogc_source_parse_from_files(sb_trie_t *conf, sb_slist_t *l, sb_error_t **err) +blogc_source_parse_from_files(sb_trie_t *conf, sb_slist_t *l, blogc_error_t **err) { - sb_error_t *tmp_err = NULL; + blogc_error_t *tmp_err = NULL; sb_slist_t *rv = NULL; unsigned int with_date = 0; @@ -125,10 +125,10 @@ blogc_source_parse_from_files(sb_trie_t *conf, sb_slist_t *l, sb_error_t **err) char *f = tmp->data; sb_trie_t *s = blogc_source_parse_from_file(f, &tmp_err); if (s == NULL) { - *err = sb_error_new_printf(BLOGC_ERROR_LOADER, + *err = blogc_error_new_printf(BLOGC_ERROR_LOADER, "An error occurred while parsing source file: %s\n\n%s", f, tmp_err->msg); - sb_error_free(tmp_err); + blogc_error_free(tmp_err); tmp_err = NULL; sb_slist_free_full(rv, (sb_free_func_t) sb_trie_free); rv = NULL; diff --git a/src/loader.h b/src/loader.h index 8b0460e..080aff6 100644 --- a/src/loader.h +++ b/src/loader.h @@ -13,9 +13,9 @@ #include "error.h" char* blogc_get_filename(const char *f); -sb_slist_t* blogc_template_parse_from_file(const char *f, sb_error_t **err); -sb_trie_t* blogc_source_parse_from_file(const char *f, sb_error_t **err); +sb_slist_t* blogc_template_parse_from_file(const char *f, blogc_error_t **err); +sb_trie_t* blogc_source_parse_from_file(const char *f, blogc_error_t **err); sb_slist_t* blogc_source_parse_from_files(sb_trie_t *conf, sb_slist_t *l, - sb_error_t **err); + blogc_error_t **err); #endif /* _LOADER_H */ diff --git a/src/main.c b/src/main.c index 709b37e..143c836 100644 --- a/src/main.c +++ b/src/main.c @@ -210,7 +210,7 @@ main(int argc, char **argv) goto cleanup; } - sb_error_t *err = NULL; + blogc_error_t *err = NULL; sb_slist_t *s = blogc_source_parse_from_files(config, sources, &err); if (err != NULL) { @@ -274,7 +274,7 @@ cleanup3: blogc_template_free_stmts(l); cleanup2: sb_slist_free_full(s, (sb_free_func_t) sb_trie_free); - sb_error_free(err); + blogc_error_free(err); cleanup: sb_trie_free(config); free(template); diff --git a/src/renderer.c b/src/renderer.c index eb58e0d..a7a7dd7 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -46,11 +46,11 @@ blogc_format_date(const char *date, sb_trie_t *global, sb_trie_t *local) if (date_format == NULL) return sb_strdup(date); - sb_error_t *err = NULL; + blogc_error_t *err = NULL; char *rv = blogc_convert_datetime(date, date_format, &err); if (err != NULL) { blogc_error_print(err); - sb_error_free(err); + blogc_error_free(err); return sb_strdup(date); } return rv; diff --git a/src/source-parser.c b/src/source-parser.c index 6e026d2..67c3717 100644 --- a/src/source-parser.c +++ b/src/source-parser.c @@ -31,7 +31,7 @@ typedef enum { sb_trie_t* -blogc_source_parse(const char *src, size_t src_len, sb_error_t **err) +blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err) { if (err == NULL || *err != NULL) return NULL; @@ -97,7 +97,7 @@ blogc_source_parse(const char *src, size_t src_len, sb_error_t **err) ((current - start == 13) && (0 == strncmp("BLOGC_VERSION", src + start, 13)))) { - *err = sb_error_new_printf(BLOGC_ERROR_SOURCE_PARSER, + *err = blogc_error_new_printf(BLOGC_ERROR_SOURCE_PARSER, "'%s' variable is forbidden in source files. It will " "be set for you by the compiler.", key); break; diff --git a/src/source-parser.h b/src/source-parser.h index fb5306c..460aedb 100644 --- a/src/source-parser.h +++ b/src/source-parser.h @@ -14,6 +14,6 @@ #include "error.h" sb_trie_t* blogc_source_parse(const char *src, size_t src_len, - sb_error_t **err); + blogc_error_t **err); #endif /* _SOURCE_PARSER_H */ diff --git a/src/template-parser.c b/src/template-parser.c index d61f90a..6f23ef1 100644 --- a/src/template-parser.c +++ b/src/template-parser.c @@ -53,7 +53,7 @@ typedef enum { sb_slist_t* -blogc_template_parse(const char *src, size_t src_len, sb_error_t **err) +blogc_template_parse(const char *src, size_t src_len, blogc_error_t **err) { if (err == NULL || *err != NULL) return NULL; @@ -597,14 +597,14 @@ blogc_template_parse(const char *src, size_t src_len, sb_error_t **err) *err = blogc_error_parser(BLOGC_ERROR_TEMPLATE_PARSER, src, src_len, start2 - 1, "Found an open double-quoted string."); else if (if_count != 0) - *err = sb_error_new_printf(BLOGC_ERROR_TEMPLATE_PARSER, + *err = blogc_error_new_printf(BLOGC_ERROR_TEMPLATE_PARSER, "%d open 'ifdef' and/or 'ifndef' statements were not closed!", if_count); else if (block_state != BLOCK_CLOSED) - *err = sb_error_new(BLOGC_ERROR_TEMPLATE_PARSER, + *err = blogc_error_new(BLOGC_ERROR_TEMPLATE_PARSER, "An open block was not closed!"); else if (foreach_open) - *err = sb_error_new(BLOGC_ERROR_TEMPLATE_PARSER, + *err = blogc_error_new(BLOGC_ERROR_TEMPLATE_PARSER, "An open 'foreach' statement was not closed!"); } diff --git a/src/template-parser.h b/src/template-parser.h index 88b46e9..de5113e 100644 --- a/src/template-parser.h +++ b/src/template-parser.h @@ -45,7 +45,7 @@ typedef struct { } blogc_template_stmt_t; sb_slist_t* blogc_template_parse(const char *src, size_t src_len, - sb_error_t **err); + blogc_error_t **err); void blogc_template_free_stmts(sb_slist_t *stmts); #endif /* _TEMPLATE_GRAMMAR_H */ -- cgit v1.2.3-18-g5258 From 74b2ee22a6b60d53b1241e0c52284b288e561599 Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Wed, 27 Apr 2016 01:38:10 +0200 Subject: moved squareball back to blogc source tree. i don't have enough time to maintain a separated library at this point, and worry about soname bump, library stability, etc. all the code is trivial enough to be copied around, and all the utils are implemented as single file now, to make it easier to copy. --- src/utils.c | 612 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/utils.h | 102 ++++++++++ 2 files changed, 714 insertions(+) create mode 100644 src/utils.c create mode 100644 src/utils.h (limited to 'src') diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..855b503 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,612 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2016 Rafael G. Martins + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#define SB_STRING_CHUNK_SIZE 128 + +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" + + +void* +sb_malloc(size_t size) +{ + // simple things simple! + void *rv = malloc(size); + if (rv == NULL) { + fprintf(stderr, "fatal: Failed to allocate memory!\n"); + abort(); + } + return rv; +} + + +void* +sb_realloc(void *ptr, size_t size) +{ + // simple things even simpler :P + void *rv = realloc(ptr, size); + if (rv == NULL && size != 0) { + fprintf(stderr, "fatal: Failed to reallocate memory!\n"); + free(ptr); + abort(); + } + return rv; +} + + +sb_slist_t* +sb_slist_append(sb_slist_t *l, void *data) +{ + sb_slist_t *node = sb_malloc(sizeof(sb_slist_t)); + node->data = data; + node->next = NULL; + if (l == NULL) { + l = node; + } + else { + sb_slist_t *tmp; + for (tmp = l; tmp->next != NULL; tmp = tmp->next); + tmp->next = node; + } + return l; +} + + +sb_slist_t* +sb_slist_prepend(sb_slist_t *l, void *data) +{ + sb_slist_t *node = sb_malloc(sizeof(sb_slist_t)); + node->data = data; + node->next = l; + l = node; + return l; +} + + +void +sb_slist_free_full(sb_slist_t *l, sb_free_func_t free_func) +{ + while (l != NULL) { + sb_slist_t *tmp = l->next; + if ((free_func != NULL) && (l->data != NULL)) + free_func(l->data); + free(l); + l = tmp; + } +} + + +void +sb_slist_free(sb_slist_t *l) +{ + sb_slist_free_full(l, NULL); +} + + +size_t +sb_slist_length(sb_slist_t *l) +{ + if (l == NULL) + return 0; + size_t i; + sb_slist_t *tmp; + for (tmp = l, i = 0; tmp != NULL; tmp = tmp->next, i++); + return i; +} + + +char* +sb_strdup(const char *s) +{ + if (s == NULL) + return NULL; + size_t l = strlen(s); + char *tmp = malloc(l + 1); + if (tmp == NULL) + return NULL; + memcpy(tmp, s, l + 1); + return tmp; +} + + +char* +sb_strndup(const char *s, size_t n) +{ + if (s == NULL) + return NULL; + size_t l = strnlen(s, n); + char *tmp = malloc(l + 1); + if (tmp == NULL) + return NULL; + memcpy(tmp, s, l); + tmp[l] = '\0'; + return tmp; +} + + +char* +sb_strdup_vprintf(const char *format, va_list ap) +{ + va_list ap2; + va_copy(ap2, ap); + int l = vsnprintf(NULL, 0, format, ap2); + va_end(ap2); + if (l < 0) + return NULL; + char *tmp = malloc(l + 1); + if (!tmp) + return NULL; + int l2 = vsnprintf(tmp, l + 1, format, ap); + if (l2 < 0) { + free(tmp); + return NULL; + } + return tmp; +} + + +char* +sb_strdup_printf(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + char *tmp = sb_strdup_vprintf(format, ap); + va_end(ap); + return tmp; +} + + +bool +sb_str_starts_with(const char *str, const char *prefix) +{ + int str_l = strlen(str); + int str_lp = strlen(prefix); + if (str_lp > str_l) + return false; + return strncmp(str, prefix, str_lp) == 0; +} + + +bool +sb_str_ends_with(const char *str, const char *suffix) +{ + int str_l = strlen(str); + int str_ls = strlen(suffix); + if (str_ls > str_l) + return false; + return strcmp(str + str_l - str_ls, suffix) == 0; +} + + +char* +sb_str_lstrip(char *str) +{ + if (str == NULL) + return NULL; + int i; + size_t str_len = strlen(str); + for (i = 0; i < str_len; i++) { + if ((str[i] != ' ') && (str[i] != '\t') && (str[i] != '\n') && + (str[i] != '\r') && (str[i] != '\t') && (str[i] != '\f') && + (str[i] != '\v')) + { + str += i; + break; + } + if (i == str_len - 1) { + str += str_len; + break; + } + } + return str; +} + + +char* +sb_str_rstrip(char *str) +{ + if (str == NULL) + return NULL; + int i; + size_t str_len = strlen(str); + for (i = str_len - 1; i >= 0; i--) { + if ((str[i] != ' ') && (str[i] != '\t') && (str[i] != '\n') && + (str[i] != '\r') && (str[i] != '\t') && (str[i] != '\f') && + (str[i] != '\v')) + { + str[i + 1] = '\0'; + break; + } + if (i == 0) { + str[0] = '\0'; + break; + } + } + return str; +} + + +char* +sb_str_strip(char *str) +{ + return sb_str_lstrip(sb_str_rstrip(str)); +} + + +char** +sb_str_split(const char *str, char c, unsigned int max_pieces) +{ + if (str == NULL) + return NULL; + char **rv = sb_malloc(sizeof(char*)); + unsigned int i, start = 0, count = 0; + for (i = 0; i < strlen(str) + 1; i++) { + if (str[0] == '\0') + break; + if ((str[i] == c && (!max_pieces || count + 1 < max_pieces)) || str[i] == '\0') { + rv = sb_realloc(rv, (count + 1) * sizeof(char*)); + rv[count] = sb_malloc(i - start + 1); + memcpy(rv[count], str + start, i - start); + rv[count++][i - start] = '\0'; + start = i + 1; + } + } + rv = sb_realloc(rv, (count + 1) * sizeof(char*)); + rv[count] = NULL; + return rv; +} + + +char* +sb_str_replace(const char *str, const char search, const char *replace) +{ + char **pieces = sb_str_split(str, search, 0); + if (pieces == NULL) + return NULL; + char* rv = sb_strv_join(pieces, replace); + sb_strv_free(pieces); + if (rv == NULL) + return sb_strdup(str); + return rv; +} + + +void +sb_strv_free(char **strv) +{ + if (strv == NULL) + return; + for (size_t i = 0; strv[i] != NULL; i++) + free(strv[i]); + free(strv); +} + + +char* +sb_strv_join(char **strv, const char *separator) +{ + if (strv == NULL || separator == NULL) + return NULL; + sb_string_t *str = sb_string_new(); + for (size_t i = 0; strv[i] != NULL; i++) { + str = sb_string_append(str, strv[i]); + if (strv[i + 1] != NULL) + str = sb_string_append(str, separator); + } + return sb_string_free(str, false); +} + + +size_t +sb_strv_length(char **strv) +{ + if (strv == NULL) + return 0; + size_t i; + for (i = 0; strv[i] != NULL; i++); + return i; +} + + +sb_string_t* +sb_string_new(void) +{ + sb_string_t* rv = sb_malloc(sizeof(sb_string_t)); + rv->str = NULL; + rv->len = 0; + rv->allocated_len = 0; + + // initialize with empty string + rv = sb_string_append(rv, ""); + + return rv; +} + + +char* +sb_string_free(sb_string_t *str, bool free_str) +{ + if (str == NULL) + return NULL; + char *rv = NULL; + if (free_str) + free(str->str); + else + rv = str->str; + free(str); + return rv; +} + + +sb_string_t* +sb_string_dup(sb_string_t *str) +{ + if (str == NULL) + return NULL; + sb_string_t* new = sb_string_new(); + return sb_string_append_len(new, str->str, str->len); +} + + +sb_string_t* +sb_string_append_len(sb_string_t *str, const char *suffix, size_t len) +{ + if (str == NULL) + return NULL; + if (suffix == NULL) + return str; + size_t old_len = str->len; + str->len += len; + if (str->len + 1 > str->allocated_len) { + str->allocated_len = (((str->len + 1) / SB_STRING_CHUNK_SIZE) + 1) * SB_STRING_CHUNK_SIZE; + str->str = sb_realloc(str->str, str->allocated_len); + } + memcpy(str->str + old_len, suffix, len); + str->str[str->len] = '\0'; + return str; +} + + +sb_string_t* +sb_string_append(sb_string_t *str, const char *suffix) +{ + if (str == NULL) + return NULL; + const char *my_suffix = suffix == NULL ? "" : suffix; + return sb_string_append_len(str, my_suffix, strlen(my_suffix)); +} + + +sb_string_t* +sb_string_append_c(sb_string_t *str, char c) +{ + if (str == NULL) + return NULL; + size_t old_len = str->len; + str->len += 1; + if (str->len + 1 > str->allocated_len) { + str->allocated_len = (((str->len + 1) / SB_STRING_CHUNK_SIZE) + 1) * SB_STRING_CHUNK_SIZE; + str->str = sb_realloc(str->str, str->allocated_len); + } + str->str[old_len] = c; + str->str[str->len] = '\0'; + return str; +} + + +sb_string_t* +sb_string_append_printf(sb_string_t *str, const char *format, ...) +{ + if (str == NULL) + return NULL; + va_list ap; + va_start(ap, format); + char *tmp = sb_strdup_vprintf(format, ap); + va_end(ap); + str = sb_string_append(str, tmp); + free(tmp); + return str; +} + + +sb_trie_t* +sb_trie_new(sb_free_func_t free_func) +{ + sb_trie_t *trie = sb_malloc(sizeof(sb_trie_t)); + trie->root = NULL; + trie->free_func = free_func; + return trie; +} + + +static void +sb_trie_free_node(sb_trie_t *trie, sb_trie_node_t *node) +{ + if (trie == NULL || node == NULL) + return; + if (node->data != NULL && trie->free_func != NULL) + trie->free_func(node->data); + sb_trie_free_node(trie, node->next); + sb_trie_free_node(trie, node->child); + free(node); +} + + +void +sb_trie_free(sb_trie_t *trie) +{ + if (trie == NULL) + return; + sb_trie_free_node(trie, trie->root); + free(trie); +} + + +void +sb_trie_insert(sb_trie_t *trie, const char *key, void *data) +{ + if (trie == NULL || key == NULL || data == NULL) + return; + + sb_trie_node_t *parent = NULL; + sb_trie_node_t *previous; + sb_trie_node_t *current; + sb_trie_node_t *tmp; + + while (1) { + + if (trie->root == NULL || (parent != NULL && parent->child == NULL)) { + current = sb_malloc(sizeof(sb_trie_node_t)); + current->key = *key; + current->data = NULL; + current->next = NULL; + current->child = NULL; + if (trie->root == NULL) + trie->root = current; + else + parent->child = current; + parent = current; + goto clean; + } + + tmp = parent == NULL ? trie->root : parent->child; + previous = NULL; + + while (tmp != NULL && tmp->key != *key) { + previous = tmp; + tmp = tmp->next; + } + + parent = tmp; + + if (previous == NULL || parent != NULL) + goto clean; + + current = sb_malloc(sizeof(sb_trie_node_t)); + current->key = *key; + current->data = NULL; + current->next = NULL; + current->child = NULL; + previous->next = current; + parent = current; + +clean: + if (*key == '\0') { + if (parent->data != NULL && trie->free_func != NULL) + trie->free_func(parent->data); + parent->data = data; + break; + } + key++; + } +} + + +void* +sb_trie_lookup(sb_trie_t *trie, const char *key) +{ + if (trie == NULL || trie->root == NULL || key == NULL) + return NULL; + + sb_trie_node_t *parent = trie->root; + sb_trie_node_t *tmp; + while (1) { + for (tmp = parent; tmp != NULL; tmp = tmp->next) { + + if (tmp->key == *key) { + if (tmp->key == '\0') + return tmp->data; + parent = tmp->child; + break; + } + } + if (tmp == NULL) + return NULL; + + if (*key == '\0') + break; + key++; + } + return NULL; +} + + +static void +sb_trie_size_node(sb_trie_node_t *node, size_t *count) +{ + if (node == NULL || count == NULL) + return; + + if (node->key == '\0') + (*count)++; + + sb_trie_size_node(node->next, count); + sb_trie_size_node(node->child, count); +} + + +size_t +sb_trie_size(sb_trie_t *trie) +{ + if (trie == NULL) + return 0; + + size_t count = 0; + sb_trie_size_node(trie->root, &count); + return count; +} + + +static void +sb_trie_foreach_node(sb_trie_node_t *node, sb_string_t *str, + sb_trie_foreach_func_t func, void *user_data) +{ + if (node == NULL || str == NULL || func == NULL) + return; + + if (node->key == '\0') { + char *tmp = sb_string_free(str, false); + func(tmp, node->data, user_data); + free(tmp); + } + + if (node->child != NULL) { + sb_string_t *child = sb_string_dup(str); + child = sb_string_append_c(child, node->key); + sb_trie_foreach_node(node->child, child, func, user_data); + } + + if (node->next != NULL) + sb_trie_foreach_node(node->next, str, func, user_data); + + if (node->child != NULL && node->next == NULL) + sb_string_free(str, true); +} + + +void +sb_trie_foreach(sb_trie_t *trie, sb_trie_foreach_func_t func, + void *user_data) +{ + if (trie == NULL || trie->root == NULL || func == NULL) + return; + + sb_string_t *str = sb_string_new(); + sb_trie_foreach_node(trie->root, str, func, user_data); +} diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..411295a --- /dev/null +++ b/src/utils.h @@ -0,0 +1,102 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2014-2016 Rafael G. Martins + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#ifndef _UTILS_H +#define _UTILS_H + +#include +#include +#include +#include +#include + + +// memory + +typedef void (*sb_free_func_t) (void *ptr); + +void* sb_malloc(size_t size); +void* sb_realloc(void *ptr, size_t size); + + +// slist + +typedef struct _sb_slist_t { + struct _sb_slist_t *next; + void *data; +} sb_slist_t; + +sb_slist_t* sb_slist_append(sb_slist_t *l, void *data); +sb_slist_t* sb_slist_prepend(sb_slist_t *l, void *data); +void sb_slist_free(sb_slist_t *l); +void sb_slist_free_full(sb_slist_t *l, sb_free_func_t free_func); +size_t sb_slist_length(sb_slist_t *l); + + +// strfuncs + +char* sb_strdup(const char *s); +char* sb_strndup(const char *s, size_t n); +char* sb_strdup_vprintf(const char *format, va_list ap); +char* sb_strdup_printf(const char *format, ...); +bool sb_str_starts_with(const char *str, const char *prefix); +bool sb_str_ends_with(const char *str, const char *suffix); +char* sb_str_lstrip(char *str); +char* sb_str_rstrip(char *str); +char* sb_str_strip(char *str); +char** sb_str_split(const char *str, char c, unsigned int max_pieces); +char* sb_str_replace(const char *str, const char search, const char *replace); +void sb_strv_free(char **strv); +char* sb_strv_join(char **strv, const char *separator); +size_t sb_strv_length(char **strv); + + +// string + +typedef struct { + char *str; + size_t len; + size_t allocated_len; +} sb_string_t; + +sb_string_t* sb_string_new(void); +char* sb_string_free(sb_string_t *str, bool free_str); +sb_string_t* sb_string_dup(sb_string_t *str); +sb_string_t* sb_string_append_len(sb_string_t *str, const char *suffix, size_t len); +sb_string_t* sb_string_append(sb_string_t *str, const char *suffix); +sb_string_t* sb_string_append_c(sb_string_t *str, char c); +sb_string_t* sb_string_append_printf(sb_string_t *str, const char *format, ...); + + +// trie + +typedef struct _sb_trie_node_t { + char key; + void *data; + struct _sb_trie_node_t *next, *child; +} sb_trie_node_t; + +struct _sb_trie_t { + sb_trie_node_t *root; + sb_free_func_t free_func; +}; + +typedef struct _sb_trie_t sb_trie_t; + +typedef void (*sb_trie_foreach_func_t)(const char *key, void *data, + void *user_data); + +sb_trie_t* sb_trie_new(sb_free_func_t free_func); +void sb_trie_free(sb_trie_t *trie); +void sb_trie_insert(sb_trie_t *trie, const char *key, void *data); +void* sb_trie_lookup(sb_trie_t *trie, const char *key); +size_t sb_trie_size(sb_trie_t *trie); +void sb_trie_foreach(sb_trie_t *trie, sb_trie_foreach_func_t func, + void *user_data); + +#endif /* _UTILS_H */ -- cgit v1.2.3-18-g5258 From 9699bf0ce6b34c0d05c509925f3367f2200caad5 Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Wed, 27 Apr 2016 02:34:19 +0200 Subject: remove squareball for good --- src/content-parser.c | 2 +- src/datetime-parser.c | 2 +- src/error.c | 2 +- src/file.c | 2 +- src/loader.c | 2 +- src/loader.h | 2 +- src/main.c | 2 +- src/renderer.c | 2 +- src/renderer.h | 2 +- src/source-parser.c | 2 +- src/source-parser.h | 2 +- src/template-parser.c | 2 +- src/template-parser.h | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/content-parser.c b/src/content-parser.c index 795cc34..0c99e31 100644 --- a/src/content-parser.c +++ b/src/content-parser.c @@ -13,8 +13,8 @@ #include #include -#include #include "content-parser.h" +#include "utils.h" // this is a half ass implementation of a markdown-like syntax. bugs are // expected. feel free to improve the parser and add new features. diff --git a/src/datetime-parser.c b/src/datetime-parser.c index 0aeb702..ad65ff7 100644 --- a/src/datetime-parser.c +++ b/src/datetime-parser.c @@ -17,8 +17,8 @@ #include #include "error.h" -#include #include "datetime-parser.h" +#include "utils.h" typedef enum { diff --git a/src/error.c b/src/error.c index f05049c..586386a 100644 --- a/src/error.c +++ b/src/error.c @@ -14,8 +14,8 @@ #include #include #include -#include #include "error.h" +#include "utils.h" blogc_error_t* diff --git a/src/file.c b/src/file.c index dec7c1b..f784d93 100644 --- a/src/file.c +++ b/src/file.c @@ -14,9 +14,9 @@ #include #include #include -#include #include "file.h" #include "error.h" +#include "utils.h" // this would belong to loader.c, but we need it in a separated file to be // able to mock it when unit testing the loader functions. diff --git a/src/loader.c b/src/loader.c index 8008c3a..5ca0aac 100644 --- a/src/loader.c +++ b/src/loader.c @@ -14,12 +14,12 @@ #include #include #include -#include #include "file.h" #include "source-parser.h" #include "template-parser.h" #include "loader.h" #include "error.h" +#include "utils.h" char* diff --git a/src/loader.h b/src/loader.h index 080aff6..32b58be 100644 --- a/src/loader.h +++ b/src/loader.h @@ -9,8 +9,8 @@ #ifndef _LOADER_H #define _LOADER_H -#include #include "error.h" +#include "utils.h" char* blogc_get_filename(const char *f); sb_slist_t* blogc_template_parse_from_file(const char *f, blogc_error_t **err); diff --git a/src/main.c b/src/main.c index 143c836..2338c9e 100644 --- a/src/main.c +++ b/src/main.c @@ -24,12 +24,12 @@ #include #include -#include #include "source-parser.h" #include "template-parser.h" #include "loader.h" #include "renderer.h" #include "error.h" +#include "utils.h" #ifndef PACKAGE_VERSION #define PACKAGE_VERSION "Unknown" diff --git a/src/renderer.c b/src/renderer.c index a7a7dd7..5af3b8a 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -13,13 +13,13 @@ #include #include #include -#include #include "datetime-parser.h" #include "error.h" #include "loader.h" #include "source-parser.h" #include "template-parser.h" #include "renderer.h" +#include "utils.h" const char* diff --git a/src/renderer.h b/src/renderer.h index 3ff62e7..2982ee8 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -10,7 +10,7 @@ #define _RENDERER_H #include -#include +#include "utils.h" const char* blogc_get_variable(const char *name, sb_trie_t *global, sb_trie_t *local); char* blogc_format_date(const char *date, sb_trie_t *global, sb_trie_t *local); diff --git a/src/source-parser.c b/src/source-parser.c index 67c3717..f250bd3 100644 --- a/src/source-parser.c +++ b/src/source-parser.c @@ -13,10 +13,10 @@ #include #include -#include #include "content-parser.h" #include "source-parser.h" #include "error.h" +#include "utils.h" typedef enum { diff --git a/src/source-parser.h b/src/source-parser.h index 460aedb..5cadf95 100644 --- a/src/source-parser.h +++ b/src/source-parser.h @@ -10,8 +10,8 @@ #define _SOURCE_PARSER_H #include -#include #include "error.h" +#include "utils.h" sb_trie_t* blogc_source_parse(const char *src, size_t src_len, blogc_error_t **err); diff --git a/src/template-parser.c b/src/template-parser.c index 6f23ef1..525f5f5 100644 --- a/src/template-parser.c +++ b/src/template-parser.c @@ -13,9 +13,9 @@ #include #include -#include #include "template-parser.h" #include "error.h" +#include "utils.h" typedef enum { diff --git a/src/template-parser.h b/src/template-parser.h index de5113e..a8b4e8b 100644 --- a/src/template-parser.h +++ b/src/template-parser.h @@ -9,8 +9,8 @@ #ifndef _TEMPLATE_PARSER_H #define _TEMPLATE_PARSER_H -#include #include "error.h" +#include "utils.h" /* * note: whitespace cleaners are NOT added to ast. we fix strings right during -- cgit v1.2.3-18-g5258 From 6f975248895d0300c6fd8783b1138bdd4be00bcc Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Wed, 27 Apr 2016 03:22:31 +0200 Subject: blogc-git-receiver: import external tool to blogc repository still in the effort to reduce maintenance work, I'm importing blogc-git-receiver tool to the main blogc repository. the tool is build by default, if needed headers are found. that means that it will probably only be built for posix-compliant operating systems. --- src/blogc-git-receiver.c | 502 +++++++++++++++++++++++++++++++++++++++++++++++ src/blogc.c | 285 +++++++++++++++++++++++++++ src/main.c | 285 --------------------------- 3 files changed, 787 insertions(+), 285 deletions(-) create mode 100644 src/blogc-git-receiver.c create mode 100644 src/blogc.c delete mode 100644 src/main.c (limited to 'src') diff --git a/src/blogc-git-receiver.c b/src/blogc-git-receiver.c new file mode 100644 index 0000000..ffeac61 --- /dev/null +++ b/src/blogc-git-receiver.c @@ -0,0 +1,502 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015-2016 Rafael G. Martins + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" + +#ifndef BUFFER_SIZE +#define BUFFER_SIZE 4096 +#endif + + +static unsigned int +cpu_count(void) +{ +#ifdef _SC_NPROCESSORS_ONLN + long num = sysconf(_SC_NPROCESSORS_ONLN); + if (num >= 1) + return (unsigned int) num; +#endif + return 1; +} + + +static void +rmdir_recursive(const char *dir) +{ + struct stat buf; + if (0 != stat(dir, &buf)) { + fprintf(stderr, "warning: failed to remove directory (%s): %s\n", dir, + strerror(errno)); + return; + } + if (!S_ISDIR(buf.st_mode)) { + fprintf(stderr, "error: trying to remove invalid directory: %s\n", dir); + exit(2); + } + DIR *d = opendir(dir); + if (d == NULL) { + fprintf(stderr, "error: failed to open directory: %s\n", + strerror(errno)); + exit(2); + } + struct dirent *e; + while (NULL != (e = readdir(d))) { + if ((0 == strcmp(e->d_name, ".")) || (0 == strcmp(e->d_name, ".."))) + continue; + char *f = sb_strdup_printf("%s/%s", dir, e->d_name); + if (0 != stat(f, &buf)) { + fprintf(stderr, "error: failed to stat directory entry (%s): %s\n", + e->d_name, strerror(errno)); + free(f); + exit(2); + } + if (S_ISDIR(buf.st_mode)) { + rmdir_recursive(f); + } + else if (0 != unlink(f)) { + fprintf(stderr, "error: failed to remove file (%s): %s\n", f, + strerror(errno)); + free(f); + exit(2); + } + free(f); + } + if (0 != closedir(d)) { + fprintf(stderr, "error: failed to close directory: %s\n", + strerror(errno)); + exit(2); + } + if (0 != rmdir(dir)) { + fprintf(stderr, "error: failed to remove directory: %s\n", + strerror(errno)); + exit(2); + } +} + + +static int +git_shell(int argc, char *argv[]) +{ + int rv = 0; + + char *repo = NULL; + char *command_orig = NULL; + char *command_name = NULL; + char command_new[BUFFER_SIZE]; + + bool exec_git = false; + + // validate git command + size_t len = strlen(argv[2]); + if (!((len > 17 && (0 == strncmp(argv[2], "git-receive-pack ", 17))) || + (len > 16 && (0 == strncmp(argv[2], "git-upload-pack ", 16))) || + (len > 19 && (0 == strncmp(argv[2], "git-upload-archive ", 19))))) + { + fprintf(stderr, "error: unsupported git command: %s\n", argv[2]); + rv = 1; + goto cleanup; + } + + // get shell path + char *self = getenv("SHELL"); + if (self == NULL) { + fprintf(stderr, "error: failed to find blogc-git-receiver path\n"); + rv = 1; + goto cleanup; + } + + // get home path + char *home = getenv("HOME"); + if (home == NULL) { + fprintf(stderr, "error: failed to find user home path\n"); + rv = 1; + goto cleanup; + } + + // get git repository + command_orig = sb_strdup(argv[2]); + char *p, *r; + for (p = command_orig; *p != ' ' && *p != '\0'; p++); + if (*p == ' ') + p++; + if (*p == '\'' || *p == '"') + p++; + if (*p == '/') + p++; + for (r = p; *p != '\'' && *p != '"' && *p != '\0'; p++); + if (*p == '\'' || *p == '"') + *p = '\0'; + if (*--p == '/') + *p = '\0'; + + repo = sb_strdup_printf("repos/%s", r); + + // check if repository is sane + if (0 == strlen(repo)) { + fprintf(stderr, "error: invalid repository\n"); + rv = 1; + goto cleanup; + } + + if (0 == strncmp(argv[2], "git-upload-", 11)) // no need to check len here + goto git_exec; + + if (0 != chdir(home)) { + fprintf(stderr, "error: failed to chdir (%s): %s\n", home, + strerror(errno)); + rv = 1; + goto cleanup; + } + + if (0 != access(repo, F_OK)) { + char *git_init_cmd = sb_strdup_printf( + "git init --bare \"%s\" > /dev/null", repo); + if (0 != system(git_init_cmd)) { + fprintf(stderr, "error: failed to create git repository: %s\n", + repo); + rv = 1; + free(git_init_cmd); + goto cleanup; + } + free(git_init_cmd); + } + + if (0 != chdir(repo)) { + fprintf(stderr, "error: failed to chdir (%s/%s): %s\n", home, repo, + strerror(errno)); + rv = 1; + goto cleanup; + } + + if (0 != access("hooks", F_OK)) { + // openwrt git package won't install git templates, then the git + // repositories created with it won't have the hooks/ directory. + if (0 != mkdir("hooks", 0777)) { // mkdir honors umask for us. + fprintf(stderr, "error: failed to create directory (%s/%s/hooks): " + "%s\n", home, repo, strerror(errno)); + rv = 1; + goto cleanup; + } + } + + if (0 != chdir("hooks")) { + fprintf(stderr, "error: failed to chdir (%s/%s/hooks): %s\n", home, + repo, strerror(errno)); + rv = 1; + goto cleanup; + } + + if (0 == access("pre-receive", F_OK)) { + if (0 != unlink("pre-receive")) { + fprintf(stderr, "error: failed to remove old symlink " + "(%s/%s/hooks/pre-receive): %s\n", home, repo, strerror(errno)); + rv = 1; + goto cleanup; + } + } + + if (0 != symlink(self, "pre-receive")) { + fprintf(stderr, "error: failed to create symlink " + "(%s/%s/hooks/pre-receive): %s\n", home, repo, strerror(errno)); + rv = 1; + goto cleanup; + } + + if (0 == access("post-receive", F_OK)) { + if (0 != unlink("post-receive")) { + fprintf(stderr, "error: failed to remove old symlink " + "(%s/%s/hooks/post-receive): %s\n", home, repo, strerror(errno)); + rv = 1; + goto cleanup; + } + } + + if (0 != symlink(self, "post-receive")) { + fprintf(stderr, "error: failed to create symlink " + "(%s/%s/hooks/post-receive): %s\n", home, repo, strerror(errno)); + rv = 1; + goto cleanup; + } + + if (0 != chdir(home)) { + fprintf(stderr, "error: failed to chdir (%s): %s\n", home, + strerror(errno)); + rv = 1; + goto cleanup; + } + +git_exec: + command_name = sb_strdup(argv[2]); + for (p = command_name; *p != ' ' && *p != '\0'; p++); + if (*p == ' ') + *p = '\0'; + + if (BUFFER_SIZE < (strlen(command_name) + strlen(repo) + 4)) { + fprintf(stderr, "error: git-shell command is too big\n"); + rv = 1; + goto cleanup; + } + + if (snprintf(command_new, BUFFER_SIZE, "%s '%s'", command_name, repo)) + exec_git = true; + +cleanup: + free(repo); + free(command_orig); + free(command_name); + + if (exec_git) { + execlp("git-shell", "git-shell", "-c", command_new, NULL); + + // execlp only returns on error, then something bad happened + fprintf(stderr, "error: failed to execute git-shell\n"); + rv = 1; + } + + return rv; +} + + +static int +git_post_receive_hook(int argc, char *argv[]) +{ + if (0 != system("git remote get-url --push mirror &> /dev/null")) + return 0; + + // at this point we know that we have a remote called mirror, we can just + // push to it. + if (0 != system("git push --mirror mirror")) + fprintf(stderr, "warning: failed push to git mirror\n"); + + return 0; +} + + +typedef enum { + START_OLD = 1, + OLD, + START_NEW, + NEW, + START_REF, + REF +} input_state_t; + + +static int +git_pre_receive_hook(int argc, char *argv[]) +{ + int c; + char buffer[BUFFER_SIZE]; + + input_state_t state = START_OLD; + size_t i = 0; + size_t start = 0; + + int rv = 0; + char *new = NULL; + char *master = NULL; + + while (EOF != (c = getc(stdin))) { + + buffer[i] = (char) c; + + switch (state) { + case START_OLD: + start = i; + state = OLD; + break; + case OLD: + if (c != ' ') + break; + // no need to store old + state = START_NEW; + break; + case START_NEW: + start = i; + state = NEW; + break; + case NEW: + if (c != ' ') + break; + state = START_REF; + new = strndup(buffer + start, i - start); + break; + case START_REF: + start = i; + state = REF; + break; + case REF: + if (c != '\n') + break; + state = START_OLD; + // we just care about a ref (refs/heads/master), everything + // else is disposable :) + if (!((i - start == 17) && + (0 == strncmp("refs/heads/master", buffer + start, 17)))) + { + free(new); + new = NULL; + break; + } + master = new; + break; + } + + if (++i >= BUFFER_SIZE) { + fprintf(stderr, "error: pre-receive hook payload is too big.\n"); + rv = 1; + goto cleanup2; + } + } + + if (master == NULL) { + fprintf(stderr, "warning: no reference to master branch found. " + "nothing to deploy.\n"); + goto cleanup2; + } + + char *repo_dir = NULL; + char *output_dir = NULL; + + if (NULL == getcwd(buffer, BUFFER_SIZE)) { + fprintf(stderr, "error: failed to get repository remote path: %s\n", + strerror(errno)); + rv = 1; + goto cleanup; + } + + repo_dir = sb_strdup(buffer); + + char dir[] = "/tmp/blogc_XXXXXX"; + if (NULL == mkdtemp(dir)) { + rv = 1; + goto cleanup; + } + + char *git_archive_cmd = sb_strdup_printf( + "git archive \"%s\" | tar -x -C \"%s\" -f -", master, dir); + if (0 != system(git_archive_cmd)) { + fprintf(stderr, "error: failed to extract git content to temporary " + "directory: %s\n", dir); + rv = 1; + free(git_archive_cmd); + goto cleanup; + } + free(git_archive_cmd); + + if (0 != chdir(dir)) { + fprintf(stderr, "error: failed to chdir (%s): %s\n", dir, + strerror(errno)); + rv = 1; + goto cleanup; + } + + if ((0 != access("Makefile", F_OK)) && (0 != access("GNUMakefile", F_OK))) { + fprintf(stderr, "warning: no makefile found. skipping ...\n"); + goto cleanup; + } + + char *home = getenv("HOME"); + if (home == NULL) { + fprintf(stderr, "error: failed to find user home path\n"); + rv = 1; + goto cleanup; + } + + unsigned long epoch = time(NULL); + output_dir = sb_strdup_printf("%s/builds/%s-%lu", home, master, epoch); + char *gmake_cmd = sb_strdup_printf( + "gmake -j%d OUTPUT_DIR=\"%s\" BLOGC_GIT_RECEIVER=1", + cpu_count(), output_dir); + fprintf(stdout, "running command: %s\n\n", gmake_cmd); + fflush(stdout); + if (0 != system(gmake_cmd)) { + fprintf(stderr, "error: failed to build website ...\n"); + rmdir_recursive(output_dir); + free(gmake_cmd); + rv = 1; + goto cleanup; + } + free(gmake_cmd); + + if (0 != chdir(repo_dir)) { + fprintf(stderr, "error: failed to chdir (%s): %s\n", repo_dir, + strerror(errno)); + rmdir_recursive(output_dir); + rv = 1; + goto cleanup; + } + + char *htdocs_sym = NULL; + ssize_t htdocs_sym_len = readlink("htdocs", buffer, BUFFER_SIZE); + if (0 < htdocs_sym_len) { + if (0 != unlink("htdocs")) { + fprintf(stderr, "error: failed to remove symlink (%s/htdocs): %s\n", + repo_dir, strerror(errno)); + rmdir_recursive(output_dir); + rv = 1; + goto cleanup; + } + buffer[htdocs_sym_len] = '\0'; + htdocs_sym = buffer; + } + + if (0 != symlink(output_dir, "htdocs")) { + fprintf(stderr, "error: failed to create symlink (%s/htdocs): %s\n", + repo_dir, strerror(errno)); + rmdir_recursive(output_dir); + rv = 1; + goto cleanup; + } + + if (htdocs_sym != NULL) + rmdir_recursive(htdocs_sym); + +cleanup: + free(output_dir); + rmdir_recursive(dir); + free(repo_dir); +cleanup2: + free(new); + return rv; +} + + +int +main(int argc, char *argv[]) +{ + if (argc > 0) { + if (0 == strcmp(basename(argv[0]), "pre-receive")) + return git_pre_receive_hook(argc, argv); + if (0 == strcmp(basename(argv[0]), "post-receive")) + return git_post_receive_hook(argc, argv); + } + + if (argc == 3 && (0 == strcmp(argv[1], "-c"))) + return git_shell(argc, argv); + + fprintf(stderr, "error: this is a special shell, go away!\n"); + return 1; +} diff --git a/src/blogc.c b/src/blogc.c new file mode 100644 index 0000000..2338c9e --- /dev/null +++ b/src/blogc.c @@ -0,0 +1,285 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015-2016 Rafael G. Martins + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#ifdef HAVE_SYS_STAT_H +#include +#endif /* HAVE_SYS_STAT_H */ + +#ifdef HAVE_SYS_TYPES_H +#include +#endif /* HAVE_SYS_TYPES_H */ + +#include +#include +#include +#include +#include + +#include "source-parser.h" +#include "template-parser.h" +#include "loader.h" +#include "renderer.h" +#include "error.h" +#include "utils.h" + +#ifndef PACKAGE_VERSION +#define PACKAGE_VERSION "Unknown" +#endif + + +static void +blogc_print_help(void) +{ + printf( + "usage:\n" + " blogc [-h] [-v] [-l] [-D KEY=VALUE ...] [-p KEY] [-t TEMPLATE]\n" + " [-o OUTPUT] [SOURCE ...] - A blog compiler.\n" + "\n" + "positional arguments:\n" + " SOURCE source file(s)\n" + "\n" + "optional arguments:\n" + " -h show this help message and exit\n" + " -v show version and exit\n" + " -l build listing page, from multiple source files\n" + " -D KEY=VALUE set global configuration parameter\n" + " -p KEY show the value of a global configuration parameter\n" + " after source parsing and exit\n" + " -t TEMPLATE template file\n" + " -o OUTPUT output file\n"); +} + + +static void +blogc_print_usage(void) +{ + printf( + "usage: blogc [-h] [-v] [-l] [-D KEY=VALUE ...] [-p KEY] [-t TEMPLATE]\n" + " [-o OUTPUT] [SOURCE ...]\n"); +} + + +static void +blogc_mkdir_recursive(const char *filename) +{ + char *fname = sb_strdup(filename); + for (char *tmp = fname; *tmp != '\0'; tmp++) { + if (*tmp != '/' && *tmp != '\\') + continue; +#if defined(HAVE_SYS_STAT_H) && defined(HAVE_SYS_TYPES_H) + char bkp = *tmp; + *tmp = '\0'; + if ((strlen(fname) > 0) && +#if defined(WIN32) || defined(_WIN32) + (-1 == mkdir(fname)) && +#else + (-1 == mkdir(fname, 0777)) && +#endif + (errno != EEXIST)) + { + fprintf(stderr, "blogc: error: failed to create output " + "directory (%s): %s\n", fname, strerror(errno)); + free(fname); + exit(2); + } + *tmp = bkp; +#else + // FIXME: show this warning only if actually trying to create a directory. + fprintf(stderr, "blogc: warning: can't create output directories " + "for your platform. please create the directories yourself.\n"); + break; +#endif + } + free(fname); +} + + +int +main(int argc, char **argv) +{ + setlocale(LC_ALL, ""); + + int rv = 0; + + bool listing = false; + char *template = NULL; + char *output = NULL; + char *print = NULL; + char *tmp = NULL; + char **pieces = NULL; + + sb_slist_t *sources = NULL; + sb_trie_t *config = sb_trie_new(free); + sb_trie_insert(config, "BLOGC_VERSION", sb_strdup(PACKAGE_VERSION)); + + for (unsigned int i = 1; i < argc; i++) { + tmp = NULL; + if (argv[i][0] == '-') { + switch (argv[i][1]) { + case 'h': + blogc_print_help(); + goto cleanup; + case 'v': + printf("%s\n", PACKAGE_STRING); + goto cleanup; + case 'l': + listing = true; + break; + case 't': + if (argv[i][2] != '\0') + template = sb_strdup(argv[i] + 2); + else if (i + 1 < argc) + template = sb_strdup(argv[++i]); + break; + case 'o': + if (argv[i][2] != '\0') + output = sb_strdup(argv[i] + 2); + else if (i + 1 < argc) + output = sb_strdup(argv[++i]); + break; + case 'p': + if (argv[i][2] != '\0') + print = sb_strdup(argv[i] + 2); + else if (i + 1 < argc) + print = sb_strdup(argv[++i]); + break; + case 'D': + if (argv[i][2] != '\0') + tmp = argv[i] + 2; + else if (i + 1 < argc) + tmp = argv[++i]; + if (tmp != NULL) { + pieces = sb_str_split(tmp, '=', 2); + if (sb_strv_length(pieces) != 2) { + fprintf(stderr, "blogc: error: invalid value for " + "-D (must have an '='): %s\n", tmp); + sb_strv_free(pieces); + rv = 2; + goto cleanup; + } + for (unsigned int j = 0; pieces[0][j] != '\0'; j++) { + if (!((pieces[0][j] >= 'A' && pieces[0][j] <= 'Z') || + pieces[0][j] == '_')) + { + fprintf(stderr, "blogc: error: invalid value " + "for -D (configuration key must be uppercase " + "with '_'): %s\n", pieces[0]); + sb_strv_free(pieces); + rv = 2; + goto cleanup; + } + } + sb_trie_insert(config, pieces[0], sb_strdup(pieces[1])); + sb_strv_free(pieces); + pieces = NULL; + } + break; + default: + blogc_print_usage(); + fprintf(stderr, "blogc: error: invalid argument: -%c\n", + argv[i][1]); + rv = 2; + goto cleanup; + } + } + else + sources = sb_slist_append(sources, sb_strdup(argv[i])); + } + + if (!listing && sb_slist_length(sources) == 0) { + blogc_print_usage(); + fprintf(stderr, "blogc: error: one source file is required\n"); + rv = 2; + goto cleanup; + } + + if (!listing && sb_slist_length(sources) > 1) { + blogc_print_usage(); + fprintf(stderr, "blogc: error: only one source file should be provided, " + "if running without '-l'\n"); + rv = 2; + goto cleanup; + } + + blogc_error_t *err = NULL; + + sb_slist_t *s = blogc_source_parse_from_files(config, sources, &err); + if (err != NULL) { + blogc_error_print(err); + rv = 2; + goto cleanup2; + } + + sb_slist_t* l = blogc_template_parse_from_file(template, &err); + if (err != NULL) { + blogc_error_print(err); + rv = 2; + goto cleanup3; + } + + if (print != NULL) { + const char *val = sb_trie_lookup(config, print); + if (val == NULL) { + fprintf(stderr, "blogc: error: configuration variable not found: %s\n", + print); + rv = 2; + } + else { + printf("%s\n", val); + } + goto cleanup3; + } + + if (template == NULL) { + blogc_print_usage(); + fprintf(stderr, "blogc: error: argument -t is required when rendering content\n"); + rv = 2; + goto cleanup3; + } + + char *out = blogc_render(l, s, config, listing); + + bool write_to_stdout = (output == NULL || (0 == strcmp(output, "-"))); + + FILE *fp = stdout; + if (!write_to_stdout) { + blogc_mkdir_recursive(output); + fp = fopen(output, "w"); + if (fp == NULL) { + fprintf(stderr, "blogc: error: failed to open output file (%s): %s\n", + output, strerror(errno)); + rv = 2; + goto cleanup4; + } + } + + if (out != NULL) + fprintf(fp, "%s", out); + + if (!write_to_stdout) + fclose(fp); + +cleanup4: + free(out); +cleanup3: + blogc_template_free_stmts(l); +cleanup2: + sb_slist_free_full(s, (sb_free_func_t) sb_trie_free); + blogc_error_free(err); +cleanup: + sb_trie_free(config); + free(template); + free(output); + free(print); + sb_slist_free_full(sources, free); + return rv; +} diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 2338c9e..0000000 --- a/src/main.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * blogc: A blog compiler. - * Copyright (C) 2015-2016 Rafael G. Martins - * - * This program can be distributed under the terms of the BSD License. - * See the file LICENSE. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif /* HAVE_CONFIG_H */ - -#ifdef HAVE_SYS_STAT_H -#include -#endif /* HAVE_SYS_STAT_H */ - -#ifdef HAVE_SYS_TYPES_H -#include -#endif /* HAVE_SYS_TYPES_H */ - -#include -#include -#include -#include -#include - -#include "source-parser.h" -#include "template-parser.h" -#include "loader.h" -#include "renderer.h" -#include "error.h" -#include "utils.h" - -#ifndef PACKAGE_VERSION -#define PACKAGE_VERSION "Unknown" -#endif - - -static void -blogc_print_help(void) -{ - printf( - "usage:\n" - " blogc [-h] [-v] [-l] [-D KEY=VALUE ...] [-p KEY] [-t TEMPLATE]\n" - " [-o OUTPUT] [SOURCE ...] - A blog compiler.\n" - "\n" - "positional arguments:\n" - " SOURCE source file(s)\n" - "\n" - "optional arguments:\n" - " -h show this help message and exit\n" - " -v show version and exit\n" - " -l build listing page, from multiple source files\n" - " -D KEY=VALUE set global configuration parameter\n" - " -p KEY show the value of a global configuration parameter\n" - " after source parsing and exit\n" - " -t TEMPLATE template file\n" - " -o OUTPUT output file\n"); -} - - -static void -blogc_print_usage(void) -{ - printf( - "usage: blogc [-h] [-v] [-l] [-D KEY=VALUE ...] [-p KEY] [-t TEMPLATE]\n" - " [-o OUTPUT] [SOURCE ...]\n"); -} - - -static void -blogc_mkdir_recursive(const char *filename) -{ - char *fname = sb_strdup(filename); - for (char *tmp = fname; *tmp != '\0'; tmp++) { - if (*tmp != '/' && *tmp != '\\') - continue; -#if defined(HAVE_SYS_STAT_H) && defined(HAVE_SYS_TYPES_H) - char bkp = *tmp; - *tmp = '\0'; - if ((strlen(fname) > 0) && -#if defined(WIN32) || defined(_WIN32) - (-1 == mkdir(fname)) && -#else - (-1 == mkdir(fname, 0777)) && -#endif - (errno != EEXIST)) - { - fprintf(stderr, "blogc: error: failed to create output " - "directory (%s): %s\n", fname, strerror(errno)); - free(fname); - exit(2); - } - *tmp = bkp; -#else - // FIXME: show this warning only if actually trying to create a directory. - fprintf(stderr, "blogc: warning: can't create output directories " - "for your platform. please create the directories yourself.\n"); - break; -#endif - } - free(fname); -} - - -int -main(int argc, char **argv) -{ - setlocale(LC_ALL, ""); - - int rv = 0; - - bool listing = false; - char *template = NULL; - char *output = NULL; - char *print = NULL; - char *tmp = NULL; - char **pieces = NULL; - - sb_slist_t *sources = NULL; - sb_trie_t *config = sb_trie_new(free); - sb_trie_insert(config, "BLOGC_VERSION", sb_strdup(PACKAGE_VERSION)); - - for (unsigned int i = 1; i < argc; i++) { - tmp = NULL; - if (argv[i][0] == '-') { - switch (argv[i][1]) { - case 'h': - blogc_print_help(); - goto cleanup; - case 'v': - printf("%s\n", PACKAGE_STRING); - goto cleanup; - case 'l': - listing = true; - break; - case 't': - if (argv[i][2] != '\0') - template = sb_strdup(argv[i] + 2); - else if (i + 1 < argc) - template = sb_strdup(argv[++i]); - break; - case 'o': - if (argv[i][2] != '\0') - output = sb_strdup(argv[i] + 2); - else if (i + 1 < argc) - output = sb_strdup(argv[++i]); - break; - case 'p': - if (argv[i][2] != '\0') - print = sb_strdup(argv[i] + 2); - else if (i + 1 < argc) - print = sb_strdup(argv[++i]); - break; - case 'D': - if (argv[i][2] != '\0') - tmp = argv[i] + 2; - else if (i + 1 < argc) - tmp = argv[++i]; - if (tmp != NULL) { - pieces = sb_str_split(tmp, '=', 2); - if (sb_strv_length(pieces) != 2) { - fprintf(stderr, "blogc: error: invalid value for " - "-D (must have an '='): %s\n", tmp); - sb_strv_free(pieces); - rv = 2; - goto cleanup; - } - for (unsigned int j = 0; pieces[0][j] != '\0'; j++) { - if (!((pieces[0][j] >= 'A' && pieces[0][j] <= 'Z') || - pieces[0][j] == '_')) - { - fprintf(stderr, "blogc: error: invalid value " - "for -D (configuration key must be uppercase " - "with '_'): %s\n", pieces[0]); - sb_strv_free(pieces); - rv = 2; - goto cleanup; - } - } - sb_trie_insert(config, pieces[0], sb_strdup(pieces[1])); - sb_strv_free(pieces); - pieces = NULL; - } - break; - default: - blogc_print_usage(); - fprintf(stderr, "blogc: error: invalid argument: -%c\n", - argv[i][1]); - rv = 2; - goto cleanup; - } - } - else - sources = sb_slist_append(sources, sb_strdup(argv[i])); - } - - if (!listing && sb_slist_length(sources) == 0) { - blogc_print_usage(); - fprintf(stderr, "blogc: error: one source file is required\n"); - rv = 2; - goto cleanup; - } - - if (!listing && sb_slist_length(sources) > 1) { - blogc_print_usage(); - fprintf(stderr, "blogc: error: only one source file should be provided, " - "if running without '-l'\n"); - rv = 2; - goto cleanup; - } - - blogc_error_t *err = NULL; - - sb_slist_t *s = blogc_source_parse_from_files(config, sources, &err); - if (err != NULL) { - blogc_error_print(err); - rv = 2; - goto cleanup2; - } - - sb_slist_t* l = blogc_template_parse_from_file(template, &err); - if (err != NULL) { - blogc_error_print(err); - rv = 2; - goto cleanup3; - } - - if (print != NULL) { - const char *val = sb_trie_lookup(config, print); - if (val == NULL) { - fprintf(stderr, "blogc: error: configuration variable not found: %s\n", - print); - rv = 2; - } - else { - printf("%s\n", val); - } - goto cleanup3; - } - - if (template == NULL) { - blogc_print_usage(); - fprintf(stderr, "blogc: error: argument -t is required when rendering content\n"); - rv = 2; - goto cleanup3; - } - - char *out = blogc_render(l, s, config, listing); - - bool write_to_stdout = (output == NULL || (0 == strcmp(output, "-"))); - - FILE *fp = stdout; - if (!write_to_stdout) { - blogc_mkdir_recursive(output); - fp = fopen(output, "w"); - if (fp == NULL) { - fprintf(stderr, "blogc: error: failed to open output file (%s): %s\n", - output, strerror(errno)); - rv = 2; - goto cleanup4; - } - } - - if (out != NULL) - fprintf(fp, "%s", out); - - if (!write_to_stdout) - fclose(fp); - -cleanup4: - free(out); -cleanup3: - blogc_template_free_stmts(l); -cleanup2: - sb_slist_free_full(s, (sb_free_func_t) sb_trie_free); - blogc_error_free(err); -cleanup: - sb_trie_free(config); - free(template); - free(output); - free(print); - sb_slist_free_full(sources, free); - return rv; -} -- cgit v1.2.3-18-g5258 From c4b294c890c28004d33f650b7af5064c4099f608 Mon Sep 17 00:00:00 2001 From: "Rafael G. Martins" Date: Wed, 27 Apr 2016 03:51:42 +0200 Subject: blogc-runserver: import external tool to blogc repository still in the effort to reduce maintenance work, I'm importing blogc-runserver tool to the main blogc repository. the tool is build by default, if needed headers and libraries are found. --- src/blogc-runserver.c | 389 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 389 insertions(+) create mode 100644 src/blogc-runserver.c (limited to 'src') diff --git a/src/blogc-runserver.c b/src/blogc-runserver.c new file mode 100644 index 0000000..81bd5f9 --- /dev/null +++ b/src/blogc-runserver.c @@ -0,0 +1,389 @@ +/* + * blogc: A blog compiler. + * Copyright (C) 2015-2016 Rafael G. Martins + * + * This program can be distributed under the terms of the BSD License. + * See the file LICENSE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" + + +/** + * this mapping is used to declare "supported" file types, that are forced over + * whatever detected by libmagic, but we will still use the charset provided by + * libmagic anyway. it also helps detecting index files when the client asks + * for a directory. + */ +static const struct content_type_map { + const char *mimetype; + const char *extension; + const char *index; +} content_types[] = { + {"text/html", "html", "index.html"}, + {"text/html", "htm", "index.htm"}, + {"text/xml", "xml", "index.xml"}, + {"text/plain", "txt", "index.txt"}, + {"text/css", "css", NULL}, + {"application/javascript", "js", NULL}, + {NULL, NULL, NULL} +}; + + +static magic_t magic_all = NULL; +static magic_t magic_charset = NULL; + + +static const char* +get_extension(const char *filename) +{ + const char *ext = NULL; + unsigned int i; + for (i = strlen(filename); i > 0; i--) { + if (filename[i] == '.') { + ext = filename + i + 1; + break; + } + } + if (i == 0) + return NULL; + return ext; +} + + +static char* +guess_content_type(const char *filename, int fd) +{ + int newfd; + + // try "supported" types first, and just use libmagic for charset + const char *extension = get_extension(filename); + if (extension == NULL) + goto libmagic; + const char *supported = NULL; + for (unsigned int i = 0; content_types[i].extension != NULL; i++) + if (0 == strcmp(content_types[i].extension, extension)) + supported = content_types[i].mimetype; + if (supported != NULL) { + newfd = dup(fd); + if (-1 != newfd) { + const char* charset = magic_descriptor(magic_charset, newfd); + close(newfd); + if (charset != NULL) + return sb_strdup_printf("%s; charset=%s", supported, charset); + } + return sb_strdup(supported); + } + +libmagic: + + // fallback to use libmagic for everything + newfd = dup(fd); + if (-1 != newfd) { + const char* content_type = magic_descriptor(magic_all, newfd); + close(newfd); + if (content_type != NULL) + return sb_strdup(content_type); + } + return sb_strdup("application/octet-stream"); +} + + +static void +handler(struct evhttp_request *request, void *ptr) +{ + const char *root = ptr; + const char *uri = evhttp_request_get_uri(request); + + struct evhttp_uri *decoded_uri = evhttp_uri_parse(uri); + if (decoded_uri == NULL) { + evhttp_send_error(request, 400, "Bad request"); + return; + } + + const char *path = evhttp_uri_get_path(decoded_uri); + if (path == NULL) + path = "/"; + + char *decoded_path = evhttp_uridecode(path, 0, NULL); + if (decoded_path == NULL) { + evhttp_send_error(request, 400, "Bad request"); + goto point1; + } + + char *abs_path = sb_strdup_printf("%s/%s", root, decoded_path); + char *real_path = realpath(abs_path, NULL); + free(abs_path); + + if (real_path == NULL) { + evhttp_send_error(request, 404, "Not found"); + goto point2; + } + + char *real_root = realpath(root, NULL); + if (real_root == NULL) { + evhttp_send_error(request, 500, "Internal server error"); + goto point3; + } + + if (0 != strncmp(real_root, real_path, strlen(real_root))) { + evhttp_send_error(request, 404, "Not found"); + goto point4; + } + + struct stat st; + if (0 > stat(real_path, &st)) { + evhttp_send_error(request, 404, "Not found"); + goto point4; + } + + bool add_slash = false; + + if (S_ISDIR(st.st_mode)) { + char *found = NULL; + + for (unsigned int i = 0; content_types[i].mimetype != NULL; i++) { + if (content_types[i].index == NULL) + continue; + char *f = sb_strdup_printf("%s/%s", real_path, + content_types[i].index); + if (0 == access(f, F_OK)) { + found = sb_strdup(f); + break; + } + free(f); + } + + if (found == NULL) { + evhttp_send_error(request, 403, "Forbidden"); + goto point4; + } + + size_t path_len = strlen(path); + if (path_len > 0 && path[path_len - 1] != '/') + add_slash = true; + + free(real_path); + real_path = found; + } + + int fd; + if ((fd = open(real_path, O_RDONLY)) < 0) { + evhttp_send_error(request, 500, "Internal server error"); + goto point4; + } + + char *type = guess_content_type(real_path, fd); + + if (fstat(fd, &st) < 0) { + evhttp_send_error(request, 500, "Internal server error"); + goto point5; + } + + struct evkeyvalq *headers = evhttp_request_get_output_headers(request); + + if (add_slash) { + char *tmp = sb_strdup_printf("%s/", path); + evhttp_add_header(headers, "Location", tmp); + free(tmp); + // production webservers usually returns 301 in such cases, but 302 is + // better for development/testing. + evhttp_send_reply(request, 302, "Found", NULL); + goto point5; + } + + evhttp_add_header(headers, "Content-Type", type); + char *content_length = sb_strdup_printf("%zu", st.st_size); + evhttp_add_header(headers, "Content-Length", content_length); + free(content_length); + + struct evbuffer *evb = evbuffer_new(); + evbuffer_add_file(evb, fd, 0, st.st_size); + evhttp_send_reply(request, 200, "OK", evb); + +point5: + free(type); +point4: + free(real_root); +point3: + free(real_path); +point2: + free(decoded_path); +point1: + evhttp_uri_free(decoded_uri); +} + + +static int +runserver(const char *address, unsigned short port, const char *root) +{ + struct event_base *base = event_base_new(); + if (base == NULL) { + fprintf(stderr, "error: failed to initialize event base\n"); + return 1; + } + + struct evhttp *http = evhttp_new(base); + if (http == NULL) { + fprintf(stderr, "error: failed to initialize HTTP server\n"); + return 1; + } + + evhttp_set_gencb(http, handler, (char*) root); + + evhttp_set_allowed_methods(http, EVHTTP_REQ_GET | EVHTTP_REQ_HEAD); + + if (0 != evhttp_bind_socket(http, address, port)) { + fprintf(stderr, "error: failed to bind socket to %s:%d\n", address, + port); + return 1; + } + + fprintf(stderr, " * Running on http://%s:%d/\n", address, port); + + event_base_dispatch(base); + + return 0; +} + + +static void +print_help(void) +{ + printf( + "usage:\n" + " blogc-runserver [-h] [-v] [-t HOST] [-p PORT] DOCROOT\n" + " - A simple HTTP server to test blogc websites.\n" + "\n" + "positional arguments:\n" + " DOCROOT document root directory\n" + "\n" + "optional arguments:\n" + " -h show this help message and exit\n" + " -v show version and exit\n" + " -t HOST set server listen address (default: 127.0.0.1)\n" + " -p PORT set server listen port (default: 8080)\n"); +} + + +static void +print_usage(void) +{ + printf("usage: blogc-runserver [-h] [-v] [-t HOST] [-p PORT] DOCROOT\n"); +} + + +int +main(int argc, char **argv) +{ + signal(SIGPIPE, SIG_IGN); + + int rv = 0; + char *host = NULL; + char *docroot = NULL; + unsigned short port = 8080; + + unsigned int args = 0; + + for (unsigned int i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + switch (argv[i][1]) { + case 'h': + print_help(); + goto cleanup; + case 'v': + printf("%s\n", PACKAGE_STRING); + goto cleanup; + case 't': + if (argv[i][2] != '\0') + host = sb_strdup(argv[i] + 2); + else + host = sb_strdup(argv[++i]); + break; + case 'p': + if (argv[i][2] != '\0') + port = strtoul(argv[i] + 2, NULL, 10); + else + port = strtoul(argv[++i], NULL, 10); + break; + default: + print_usage(); + fprintf(stderr, "blogc-runserver: error: invalid " + "argument: -%c\n", argv[i][1]); + rv = 2; + goto cleanup; + } + } + else { + if (args > 0) { + print_usage(); + fprintf(stderr, "blogc-runserver: error: only one positional " + "argument allowed\n"); + rv = 2; + goto cleanup; + } + args++; + docroot = sb_strdup(argv[i]); + } + } + + if (docroot == NULL) { + print_usage(); + fprintf(stderr, "blogc-runserver: error: document root directory " + "required\n"); + rv = 2; + goto cleanup; + } + + if (host == NULL) + host = sb_strdup("127.0.0.1"); + + magic_all = magic_open(MAGIC_MIME); + magic_charset = magic_open(MAGIC_MIME_ENCODING); + if (magic_all == NULL || magic_charset == NULL) { + fprintf(stderr, "error: failed to initialize libmagic\n"); + rv = 1; + goto cleanup; + } + + if ((0 != magic_load(magic_all, NULL)) || + (0 != magic_load(magic_charset, NULL))) + { + fprintf(stderr, "error: failed to load libmagic data\n"); + magic_close(magic_all); + magic_close(magic_charset); + rv = 1; + goto cleanup; + } + + rv = runserver(host, port, docroot); + + magic_close(magic_all); + magic_close(magic_charset); + +cleanup: + free(host); + free(docroot); + + return rv; +} -- cgit v1.2.3-18-g5258