summaryrefslogtreecommitdiffstats
path: root/src/blogc-make
diff options
context:
space:
mode:
Diffstat (limited to 'src/blogc-make')
-rw-r--r--src/blogc-make/atom.c137
-rw-r--r--src/blogc-make/atom.h19
-rw-r--r--src/blogc-make/ctx.c409
-rw-r--r--src/blogc-make/ctx.h84
-rw-r--r--src/blogc-make/exec-native.c192
-rw-r--r--src/blogc-make/exec-native.h20
-rw-r--r--src/blogc-make/exec.c498
-rw-r--r--src/blogc-make/exec.h35
-rw-r--r--src/blogc-make/httpd.c121
-rw-r--r--src/blogc-make/httpd.h19
-rw-r--r--src/blogc-make/main.c134
-rw-r--r--src/blogc-make/reloader.c116
-rw-r--r--src/blogc-make/reloader.h20
-rw-r--r--src/blogc-make/rules.c1078
-rw-r--r--src/blogc-make/rules.h36
-rw-r--r--src/blogc-make/settings.c203
-rw-r--r--src/blogc-make/settings.h29
-rw-r--r--src/blogc-make/utils.c128
-rw-r--r--src/blogc-make/utils.h20
19 files changed, 0 insertions, 3298 deletions
diff --git a/src/blogc-make/atom.c b/src/blogc-make/atom.c
deleted file mode 100644
index 0b8cfd1..0000000
--- a/src/blogc-make/atom.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2020 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include "../common/error.h"
-#include "../common/utils.h"
-#include "settings.h"
-#include "utils.h"
-#include "atom.h"
-
-static const char atom_template[] =
- "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
- "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n"
- " <title type=\"text\">{{ SITE_TITLE }}{%% ifdef FILTER_TAG %%} - "
- "{{ FILTER_TAG }}{%% endif %%}</title>\n"
- " <id>{{ BASE_DOMAIN }}{{ BASE_URL }}%s</id>\n"
- " <updated>{{ DATE_FIRST_FORMATTED }}</updated>\n"
- " <link href=\"{{ BASE_DOMAIN }}{{ BASE_URL }}/\" />\n"
- " <link href=\"{{ BASE_DOMAIN }}{{ BASE_URL }}%s\" rel=\"self\" />\n"
- " <author>\n"
- " <name>{{ AUTHOR_NAME }}</name>\n"
- " <email>{{ AUTHOR_EMAIL }}</email>\n"
- " </author>\n"
- " <subtitle type=\"text\">{{ SITE_TAGLINE }}</subtitle>\n"
- " {%%- block listing %%}\n"
- " <entry>\n"
- " <title type=\"text\">{{ TITLE }}</title>\n"
- " <id>{{ BASE_DOMAIN }}{{ BASE_URL }}%s</id>\n"
- " <updated>{{ DATE_FORMATTED }}</updated>\n"
- " <published>{{ DATE_FORMATTED }}</published>\n"
- " <link href=\"{{ BASE_DOMAIN }}{{ BASE_URL }}%s\" />\n"
- " <author>\n"
- " <name>{{ AUTHOR_NAME }}</name>\n"
- " <email>{{ AUTHOR_EMAIL }}</email>\n"
- " </author>\n"
- " <content type=\"html\"><![CDATA[{{ CONTENT }}]]></content>\n"
- " </entry>\n"
- " {%%- endblock %%}\n"
- "</feed>\n";
-
-
-char*
-bm_atom_generate(bm_settings_t *settings)
-{
- if (settings == NULL)
- return NULL;
-
- const char *atom_prefix = bc_trie_lookup(settings->settings, "atom_prefix");
- const char *atom_ext = bc_trie_lookup(settings->settings, "atom_ext");
- const char *post_prefix = bc_trie_lookup(settings->settings, "post_prefix");
- const char *post_ext = bc_trie_lookup(settings->settings, "html_ext");
-
- bc_string_t *atom_url = bc_string_new();
-
- if (atom_prefix[0] != '\0')
- bc_string_append_c(atom_url, '/');
-
- bc_string_append(atom_url, atom_prefix);
- bc_string_append(atom_url, "{% ifdef FILTER_TAG %}/{{ FILTER_TAG }}");
-
- if (atom_prefix[0] == '\0' && atom_ext[0] != '/')
- bc_string_append(atom_url, "{% else %}/index");
-
- bc_string_append(atom_url, "{% endif %}");
- bc_string_append(atom_url, atom_ext);
-
- char *post_url = bm_generate_filename(NULL, post_prefix, "{{ FILENAME }}",
- post_ext);
-
- char *rv = bc_strdup_printf(atom_template, atom_url->str, atom_url->str,
- post_url, post_url);
-
- bc_string_free(atom_url, true);
- free(post_url);
-
- return rv;
-}
-
-
-char*
-bm_atom_deploy(bm_settings_t *settings, bc_error_t **err)
-{
- if (settings == NULL || err == NULL || *err != NULL)
- return NULL;
-
- if (NULL != bc_trie_lookup(settings->settings, "atom_legacy_entry_id")) {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_ATOM,
- "'atom_legacy_entry_id' setting is not supported anymore. see "
- "https://blogc.rgm.io/news/blogc-0.16.1/ for details");
- return NULL;
- }
-
- // this is not really portable
- char fname[] = "/tmp/blogc-make_XXXXXX";
- int fd;
- if (-1 == (fd = mkstemp(fname))) {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_ATOM,
- "Failed to create temporary atom template: %s", strerror(errno));
- return NULL;
- }
-
- char *content = bm_atom_generate(settings);
- if (content == NULL) {
- close(fd);
- unlink(fname);
- return NULL;
- }
-
- if (-1 == write(fd, content, strlen(content))) {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_ATOM,
- "Failed to write to temporary atom template: %s", strerror(errno));
- free(content);
- close(fd);
- unlink(fname);
- return NULL;
- }
-
- free(content);
- close(fd);
-
- return bc_strdup(fname);
-}
-
-
-void
-bm_atom_destroy(const char *fname)
-{
- unlink(fname);
-}
diff --git a/src/blogc-make/atom.h b/src/blogc-make/atom.h
deleted file mode 100644
index 29a6dcb..0000000
--- a/src/blogc-make/atom.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _MAKE_ATOM_H
-#define _MAKE_ATOM_H
-
-#include "../common/error.h"
-#include "settings.h"
-
-char* bm_atom_generate(bm_settings_t *settings);
-char* bm_atom_deploy(bm_settings_t *settings, bc_error_t **err);
-void bm_atom_destroy(const char *fname);
-
-#endif /* _MAKE_ATOM_H */
diff --git a/src/blogc-make/ctx.c b/src/blogc-make/ctx.c
deleted file mode 100644
index b8d23dd..0000000
--- a/src/blogc-make/ctx.c
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2020 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <errno.h>
-#include <libgen.h>
-#include <limits.h>
-#include <time.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include "../common/error.h"
-#include "../common/file.h"
-#include "../common/utils.h"
-#include "atom.h"
-#include "settings.h"
-#include "exec.h"
-#include "utils.h"
-#include "ctx.h"
-
-
-bm_filectx_t*
-bm_filectx_new(bm_ctx_t *ctx, const char *filename, const char *slug,
- struct stat *st)
-{
- if (ctx == NULL || filename == NULL)
- return NULL;
-
- char *f = filename[0] == '/' ? bc_strdup(filename) :
- bc_strdup_printf("%s/%s", ctx->root_dir, filename);
-
- bm_filectx_t *rv = bc_malloc(sizeof(bm_filectx_t));
- rv->path = f;
- rv->short_path = bc_strdup(filename);
- rv->slug = bc_strdup(slug);
-
- if (st == NULL) {
- struct stat buf;
-
- if (0 != stat(f, &buf)) {
- rv->tv_sec = 0;
- rv->tv_nsec = 0;
- rv->readable = false;
- return rv;
- }
-
- st = &buf;
- }
-
- // if it isn't NULL the file exists for sure
- rv->tv_sec = st->st_mtim_tv_sec;
- rv->tv_nsec = st->st_mtim_tv_nsec;
- rv->readable = true;
- return rv;
-}
-
-
-bc_slist_t*
-bm_filectx_new_r(bc_slist_t *l, bm_ctx_t *ctx, const char *filename)
-{
- if (ctx == NULL || filename == NULL)
- return NULL;
-
- char *f = filename[0] == '/' ? bc_strdup(filename) :
- bc_strdup_printf("%s/%s", ctx->root_dir, filename);
-
- struct stat buf;
- if (0 != stat(f, &buf)) {
- free(f);
- return l;
- }
-
- if (S_ISDIR(buf.st_mode)) {
- DIR *dir = opendir(f);
- if (dir == NULL) {
- free(f);
- return l;
- }
-
- struct dirent *e;
- while (NULL != (e = readdir(dir))) {
- if ((0 == strcmp(e->d_name, ".")) || (0 == strcmp(e->d_name, "..")))
- continue;
- char *tmp = bc_strdup_printf("%s/%s", filename, e->d_name);
- l = bm_filectx_new_r(l, ctx, tmp);
- free(tmp);
- }
-
- closedir(dir);
- free(f);
- return l;
- }
-
- l = bc_slist_append(l, bm_filectx_new(ctx, filename, NULL, &buf));
- free(f);
- return l;
-}
-
-
-bool
-bm_filectx_changed(bm_filectx_t *ctx, time_t *tv_sec, long *tv_nsec)
-{
- if (ctx == NULL)
- return false;
-
- struct stat buf;
-
- if (0 == stat(ctx->path, &buf)) {
- if (buf.st_mtim_tv_sec == ctx->tv_sec) {
- if (buf.st_mtim_tv_nsec > ctx->tv_nsec) {
- if (tv_sec != NULL)
- *tv_sec = buf.st_mtim_tv_sec;
- if (tv_nsec != NULL)
- *tv_nsec = buf.st_mtim_tv_nsec;
- return true;
- }
- }
- else if (buf.st_mtim_tv_sec > ctx->tv_sec) {
- if (tv_sec != NULL)
- *tv_sec = buf.st_mtim_tv_sec;
- if (tv_nsec != NULL)
- *tv_nsec = buf.st_mtim_tv_nsec;
- return true;
- }
- }
-
- return false;
-}
-
-
-void
-bm_filectx_reload(bm_filectx_t *ctx)
-{
- if (ctx == NULL)
- return;
-
- time_t tv_sec;
- long tv_nsec;
-
- if (!bm_filectx_changed(ctx, &tv_sec, &tv_nsec))
- return;
-
- ctx->tv_sec = tv_sec;
- ctx->tv_nsec = tv_nsec;
- ctx->readable = true;
-}
-
-
-void
-bm_filectx_free(bm_filectx_t *fctx)
-{
- if (fctx == NULL)
- return;
- free(fctx->path);
- free(fctx->short_path);
- free(fctx->slug);
- free(fctx);
-}
-
-
-bm_ctx_t*
-bm_ctx_new(bm_ctx_t *base, const char *settings_file, const char *argv0,
- bc_error_t **err)
-{
- if (settings_file == NULL || err == NULL || *err != NULL)
- return NULL;
-
- char *abs_filename = bm_abspath(settings_file, err);
- if (*err != NULL)
- return NULL;
-
- size_t content_len;
- char *content = bc_file_get_contents(abs_filename, true, &content_len,
- err);
- if (*err != NULL) {
- free(abs_filename);
- return NULL;
- }
-
- bm_settings_t *settings = bm_settings_parse(content, content_len, err);
- if (settings == NULL || *err != NULL) {
- free(abs_filename);
- free(content);
- return NULL;
- }
- free(content);
-
- const char *template_dir = bc_trie_lookup(settings->settings, "template_dir");
- if (template_dir == NULL)
- template_dir = "";
-
- char *atom_template = NULL;
- bool atom_template_tmp = false;
- const char *atom_template_conf = bc_trie_lookup(settings->settings,
- "atom_template");
- if (atom_template_conf != NULL) {
- atom_template = bc_strdup_printf("%s/%s", template_dir, atom_template_conf);
- }
- else {
- atom_template = bm_atom_deploy(settings, err);
- atom_template_tmp = true;
- if (*err != NULL) {
- free(abs_filename);
- bm_settings_free(settings);
- return NULL;
- }
- }
-
- bm_ctx_t *rv = NULL;
- if (base == NULL) {
- rv = bc_malloc(sizeof(bm_ctx_t));
- rv->blogc = bm_exec_find_binary(argv0, "blogc", "BLOGC");
- rv->blogc_runserver = bm_exec_find_binary(argv0, "blogc-runserver",
- "BLOGC_RUNSERVER");
- rv->dev = false;
- rv->verbose = false;
- }
- else {
- bm_ctx_free_internal(base);
- rv = base;
- }
- rv->settings = settings;
-
- rv->settings_fctx = bm_filectx_new(rv, abs_filename, NULL, NULL);
- rv->root_dir = bc_strdup(dirname(abs_filename));
- free(abs_filename);
-
- const char *output_dir = getenv("OUTPUT_DIR");
- rv->short_output_dir = bc_strdup(output_dir != NULL ? output_dir : "_build");
-
- if (rv->short_output_dir[0] == '/') {
- rv->output_dir = bc_strdup(rv->short_output_dir);
- }
- else {
- rv->output_dir = bc_strdup_printf("%s/%s", rv->root_dir,
- rv->short_output_dir);
- }
-
- // can't return null and set error after this!
-
- char *main_template = bc_strdup_printf("%s/%s", template_dir,
- bm_ctx_settings_lookup(rv, "main_template"));
- rv->main_template_fctx = bm_filectx_new(rv, main_template, NULL, NULL);
- free(main_template);
-
- rv->atom_template_tmp = atom_template_tmp;
- rv->atom_template_fctx = bm_filectx_new(rv, atom_template, NULL, NULL);
- free(atom_template);
-
- const char *content_dir = bm_ctx_settings_lookup(rv, "content_dir");
- const char *post_prefix = bm_ctx_settings_lookup(rv, "post_prefix");
- const char *source_ext = bm_ctx_settings_lookup(rv, "source_ext");
- const char *listing_entry = bm_ctx_settings_lookup(rv, "listing_entry");
-
- rv->listing_entry_fctx = NULL;
- if (listing_entry != NULL) {
- char *f = bm_generate_filename(content_dir, NULL, listing_entry, source_ext);
- rv->listing_entry_fctx = bm_filectx_new(rv, f, listing_entry, NULL);
- free(f);
- }
-
- rv->posts_fctx = NULL;
- if (settings->posts != NULL) {
- for (size_t i = 0; settings->posts[i] != NULL; i++) {
- char *f = bm_generate_filename(content_dir, post_prefix,
- settings->posts[i], source_ext);
- rv->posts_fctx = bc_slist_append(rv->posts_fctx,
- bm_filectx_new(rv, f, settings->posts[i], NULL));
- free(f);
- }
- }
-
- rv->pages_fctx = NULL;
- if (settings->pages != NULL) {
- for (size_t i = 0; settings->pages[i] != NULL; i++) {
- char *f = bm_generate_filename(content_dir, NULL, settings->pages[i],
- source_ext);
- rv->pages_fctx = bc_slist_append(rv->pages_fctx,
- bm_filectx_new(rv, f, settings->pages[i], NULL));
- free(f);
- }
- }
-
- rv->copy_fctx = NULL;
- if (settings->copy != NULL) {
- for (size_t i = 0; settings->copy[i] != NULL; i++) {
- rv->copy_fctx = bm_filectx_new_r(rv->copy_fctx, rv,
- settings->copy[i]);
- }
- }
-
- return rv;
-}
-
-
-bool
-bm_ctx_reload(bm_ctx_t **ctx)
-{
- if (*ctx == NULL || (*ctx)->settings_fctx == NULL)
- return false;
-
- if (bm_filectx_changed((*ctx)->settings_fctx, NULL, NULL)) {
- // reload everything! we could just reload settings_fctx, as this
- // would force rebuilding everything, but we need to know new/deleted
- // files
-
- // needs to dup path, because it may be freed when reloading.
- char *tmp = bc_strdup((*ctx)->settings_fctx->path);
- bc_error_t *err = NULL;
- *ctx = bm_ctx_new(*ctx, tmp, NULL, &err);
- free(tmp);
- if (err != NULL) {
- bc_error_print(err, "blogc-make");
- bc_error_free(err);
- return false;
- }
- return true;
- }
-
- bm_filectx_reload((*ctx)->main_template_fctx);
- bm_filectx_reload((*ctx)->atom_template_fctx);
- bm_filectx_reload((*ctx)->listing_entry_fctx);
-
- for (bc_slist_t *tmp = (*ctx)->posts_fctx; tmp != NULL; tmp = tmp->next)
- bm_filectx_reload((bm_filectx_t*) tmp->data);
-
- for (bc_slist_t *tmp = (*ctx)->pages_fctx; tmp != NULL; tmp = tmp->next)
- bm_filectx_reload((bm_filectx_t*) tmp->data);
-
- for (bc_slist_t *tmp = (*ctx)->copy_fctx; tmp != NULL; tmp = tmp->next)
- bm_filectx_reload((bm_filectx_t*) tmp->data);
-
- return true;
-}
-
-
-void
-bm_ctx_free_internal(bm_ctx_t *ctx)
-{
- if (ctx == NULL)
- return;
-
- bm_settings_free(ctx->settings);
- ctx->settings = NULL;
-
- free(ctx->root_dir);
- ctx->root_dir = NULL;
- free(ctx->short_output_dir);
- ctx->short_output_dir = NULL;
- free(ctx->output_dir);
- ctx->output_dir = NULL;
-
- if (ctx->atom_template_tmp)
- bm_atom_destroy(ctx->atom_template_fctx->path);
- ctx->atom_template_tmp = false;
-
- bm_filectx_free(ctx->main_template_fctx);
- ctx->main_template_fctx = NULL;
- bm_filectx_free(ctx->atom_template_fctx);
- ctx->atom_template_fctx = NULL;
- bm_filectx_free(ctx->settings_fctx);
- ctx->settings_fctx = NULL;
- bm_filectx_free(ctx->listing_entry_fctx);
- ctx->listing_entry_fctx = NULL;
-
- bc_slist_free_full(ctx->posts_fctx, (bc_free_func_t) bm_filectx_free);
- ctx->posts_fctx = NULL;
- bc_slist_free_full(ctx->pages_fctx, (bc_free_func_t) bm_filectx_free);
- ctx->pages_fctx = NULL;
- bc_slist_free_full(ctx->copy_fctx, (bc_free_func_t) bm_filectx_free);
- ctx->copy_fctx = NULL;
-}
-
-
-void
-bm_ctx_free(bm_ctx_t *ctx)
-{
- if (ctx == NULL)
- return;
- bm_ctx_free_internal(ctx);
- free(ctx->blogc);
- free(ctx->blogc_runserver);
- free(ctx);
-}
-
-
-const char*
-bm_ctx_settings_lookup(bm_ctx_t *ctx, const char *key)
-{
- if (ctx == NULL || ctx->settings == NULL || ctx->settings->settings == NULL)
- return NULL;
- return bc_trie_lookup(ctx->settings->settings, key);
-}
-
-
-const char*
-bm_ctx_settings_lookup_str(bm_ctx_t *ctx, const char *key)
-{
- const char *rv = bm_ctx_settings_lookup(ctx, key);
- return rv == NULL ? "" : rv;
-}
diff --git a/src/blogc-make/ctx.h b/src/blogc-make/ctx.h
deleted file mode 100644
index a66d51c..0000000
--- a/src/blogc-make/ctx.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _MAKE_CTX_H
-#define _MAKE_CTX_H
-
-#include <sys/stat.h>
-#include <stdbool.h>
-#include <time.h>
-#include "settings.h"
-#include "../common/error.h"
-#include "../common/utils.h"
-
-#ifdef __APPLE__
-#define st_mtim_tv_sec st_mtimespec.tv_sec
-#define st_mtim_tv_nsec st_mtimespec.tv_nsec
-#endif
-
-#ifdef __ANDROID__
-#define st_mtim_tv_sec st_mtime
-#define st_mtim_tv_nsec st_mtime_nsec
-#endif
-
-#ifndef st_mtim_tv_sec
-#define st_mtim_tv_sec st_mtim.tv_sec
-#endif
-#ifndef st_mtim_tv_nsec
-#define st_mtim_tv_nsec st_mtim.tv_nsec
-#endif
-
-
-typedef struct {
- char *path;
- char *short_path;
- char *slug;
- time_t tv_sec;
- long tv_nsec;
- bool readable;
-} bm_filectx_t;
-
-typedef struct {
- char *blogc;
- char *blogc_runserver;
-
- bool dev;
- bool verbose;
- bool atom_template_tmp;
-
- bm_settings_t *settings;
-
- char *root_dir;
- char *output_dir;
- char *short_output_dir;
-
- bm_filectx_t *main_template_fctx;
- bm_filectx_t *atom_template_fctx;
- bm_filectx_t *settings_fctx;
- bm_filectx_t *listing_entry_fctx;
-
- bc_slist_t *posts_fctx;
- bc_slist_t *pages_fctx;
- bc_slist_t *copy_fctx;
-} bm_ctx_t;
-
-bm_filectx_t* bm_filectx_new(bm_ctx_t *ctx, const char *filename, const char *slug,
- struct stat *st);
-bc_slist_t* bm_filectx_new_r(bc_slist_t *l, bm_ctx_t *ctx, const char *filename);
-bool bm_filectx_changed(bm_filectx_t *ctx, time_t *tv_sec, long *tv_nsec);
-void bm_filectx_reload(bm_filectx_t *ctx);
-void bm_filectx_free(bm_filectx_t *fctx);
-bm_ctx_t* bm_ctx_new(bm_ctx_t *base, const char *settings_file,
- const char *argv0, bc_error_t **err);
-bool bm_ctx_reload(bm_ctx_t **ctx);
-void bm_ctx_free_internal(bm_ctx_t *ctx);
-void bm_ctx_free(bm_ctx_t *ctx);
-const char* bm_ctx_settings_lookup(bm_ctx_t *ctx, const char *key);
-const char* bm_ctx_settings_lookup_str(bm_ctx_t *ctx, const char *key);
-
-#endif /* _MAKE_CTX_H */
diff --git a/src/blogc-make/exec-native.c b/src/blogc-make/exec-native.c
deleted file mode 100644
index 6d7f58f..0000000
--- a/src/blogc-make/exec-native.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2020 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <libgen.h>
-#include <errno.h>
-#include "../common/error.h"
-#include "../common/file.h"
-#include "../common/utils.h"
-#include "exec-native.h"
-#include "ctx.h"
-
-
-int
-bm_exec_native_cp(bm_filectx_t *source, bm_filectx_t *dest, bool verbose)
-{
- if (verbose)
- printf("Copying '%s' to '%s'\n", source->path, dest->path);
- else
- printf(" COPY %s\n", dest->short_path);
- fflush(stdout);
-
- char *fname = bc_strdup(dest->path);
- for (char *tmp = fname; *tmp != '\0'; tmp++) {
- if (*tmp != '/' && *tmp != '\\')
- continue;
- char bkp = *tmp;
- *tmp = '\0';
- if ((strlen(fname) > 0) &&
- (-1 == mkdir(fname, 0777)) &&
- (errno != EEXIST))
- {
- fprintf(stderr, "blogc-make: error: failed to create output "
- "directory (%s): %s\n", fname, strerror(errno));
- free(fname);
- return 1;
- }
- *tmp = bkp;
- }
- free(fname);
-
- int fd_from = open(source->path, O_RDONLY);
- if (fd_from < 0) {
- fprintf(stderr, "blogc-make: error: failed to open source file to copy "
- " (%s): %s\n", source->path, strerror(errno));
- return 1;
- }
-
- int fd_to = open(dest->path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
- if (fd_to < 0) {
- fprintf(stderr, "blogc-make: error: failed to open destination file to "
- "copy (%s): %s\n", dest->path, strerror(errno));
- close(fd_from);
- return 1;
- }
-
- ssize_t nread;
- char buffer[BC_FILE_CHUNK_SIZE];
- while (0 < (nread = read(fd_from, buffer, BC_FILE_CHUNK_SIZE))) {
- char *out_ptr = buffer;
- do {
- ssize_t nwritten = write(fd_to, out_ptr, nread);
- if (nwritten == -1) {
- fprintf(stderr, "blogc-make: error: failed to write to "
- "destination file (%s): %s\n", dest->path, strerror(errno));
- close(fd_from);
- close(fd_to);
- return 1;
- }
- nread -= nwritten;
- out_ptr += nwritten;
- } while (nread > 0);
- }
-
- close(fd_from);
- close(fd_to);
-
- return 0;
-}
-
-
-bool
-bm_exec_native_is_empty_dir(const char *dir, bc_error_t **err)
-{
- DIR *d = opendir(dir);
- if (d == NULL) {
- if (errno == ENOENT) {
- return true;
- }
- if (err != NULL) {
- *err = bc_error_new_printf(0, "failed to open directory (%s): %s\n",
- dir, strerror(errno));
- }
- return true;
- }
-
- struct dirent *e;
- size_t count = 0;
- while (NULL != (e = readdir(d))) {
- if ((0 == strcmp(e->d_name, ".")) || (0 == strcmp(e->d_name, "..")))
- continue;
- count++;
- break;
- }
-
- if (0 != closedir(d)) {
- if (err != NULL) {
- *err = bc_error_new_printf(0, "failed to close directory (%s): %s\n",
- dir, strerror(errno));
- }
- return true;
- }
-
- return count == 0;
-}
-
-
-int
-bm_exec_native_rm(const char *output_dir, bm_filectx_t *dest, bool verbose)
-{
- if (verbose)
- printf("Removing file '%s'\n", dest->path);
- else
- printf(" CLEAN %s\n", dest->short_path);
- fflush(stdout);
-
- if (0 != unlink(dest->path)) {
- fprintf(stderr, "blogc-make: error: failed to remove file (%s): %s\n",
- dest->path, strerror(errno));
- return 1;
- }
-
- int rv = 0;
-
- // blame freebsd's libc for all of those memory allocations around dirname
- // calls!
- char *short_dir = bc_strdup(dirname(dest->short_path));
- char *dir = bc_strdup(dirname(dest->path));
-
- bc_error_t *err = NULL;
-
- while ((0 != strcmp(short_dir, ".")) && (0 != strcmp(short_dir, "/"))) {
- bool empty = bm_exec_native_is_empty_dir(dir, &err);
- if (err != NULL) {
- fprintf(stderr, "blogc-make: error: %s\n", err->msg);
- bc_error_free(err);
- rv = 1;
- break;
- }
- if (!empty) {
- break;
- }
- if (verbose) {
- printf("Removing directory '%s'\n", dir);
- fflush(stdout);
- }
- if (0 != rmdir(dir)) {
- fprintf(stderr,
- "blogc-make: error: failed to remove directory(%s): %s\n",
- dir, strerror(errno));
- rv = 1;
- break;
- }
- if (0 == strcmp(dir, output_dir)) {
- break;
- }
-
- char *tmp = short_dir;
- short_dir = bc_strdup(dirname(short_dir));
- free(tmp);
- tmp = dir;
- dir = bc_strdup(dirname(dir));
- free(tmp);
- }
-
- free(short_dir);
- free(dir);
-
- return rv;
-}
diff --git a/src/blogc-make/exec-native.h b/src/blogc-make/exec-native.h
deleted file mode 100644
index 56a1da1..0000000
--- a/src/blogc-make/exec-native.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _MAKE_EXEC_NATIVE_H
-#define _MAKE_EXEC_NATIVE_H
-
-#include <stdbool.h>
-#include "../common/error.h"
-#include "ctx.h"
-
-int bm_exec_native_cp(bm_filectx_t *source, bm_filectx_t *dest, bool verbose);
-bool bm_exec_native_is_empty_dir(const char *dir, bc_error_t **err);
-int bm_exec_native_rm(const char *output_dir, bm_filectx_t *dest, bool verbose);
-
-#endif /* _MAKE_EXEC_NATIVE_H */
diff --git a/src/blogc-make/exec.c b/src/blogc-make/exec.c
deleted file mode 100644
index 4b1f6df..0000000
--- a/src/blogc-make/exec.c
+++ /dev/null
@@ -1,498 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2020 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#ifdef HAVE_SYSEXITS_H
-#include <sysexits.h>
-#else
-#define EX_CONFIG 78
-#endif /* HAVE_SYSEXITS_H */
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <libgen.h>
-#include "../common/compat.h"
-#include "../common/error.h"
-#include "../common/file.h"
-#include "../common/utils.h"
-#include "ctx.h"
-#include "exec.h"
-#include "settings.h"
-
-
-char*
-bm_exec_find_binary(const char *argv0, const char *bin, const char *env)
-{
-#ifdef MAKE_EMBEDDED
- // for embedded blogc-make, if we are looking for blogc, we just return
- // argv0, because the static binary may not be named `blogc`, and we
- // prefer to use our own `blogc` instead of some other version around.
- if (argv0 != NULL && bin != NULL && (0 == strcmp(bin, "blogc"))) {
- return bc_shell_quote(argv0);
- }
-#endif
-
- // first try: env var
- const char *env_bin = getenv(env);
- if (env_bin != NULL) {
- return bc_shell_quote(env_bin);
- }
-
- // second try: same dir as current exec
- // we rely on some assumptions here:
- //
- // - if binary is called without a directory, that means location will
- // be resolved from $PATH, we don't care about doing a dir lookup.
- // - we *never* call chdir anywhere in the code, so we can assume
- // that relative paths will work as expected.
- // - windows path sep is not supported
- if (argv0 != NULL && (NULL != strchr(argv0, '/'))) {
- char *path = bc_strdup(argv0);
- char *dir = bc_strdup(dirname(path));
- free(path);
- char *tmp = bc_strdup_printf("%s/%s", dir, bin);
- free(dir);
- if (0 == access(tmp, X_OK)) {
- char *rv = bc_shell_quote(tmp);
- free(tmp);
- return rv;
- }
- free(tmp);
- }
-
- // last try: $PATH
- return bc_strdup(bin);
-}
-
-
-int
-bm_exec_command(const char *cmd, const char *input, char **output,
- char **error, bc_error_t **err)
-{
- if (err == NULL || *err != NULL)
- return 1;
-
- int fd_in[2];
- if (-1 == pipe(fd_in)) {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_EXEC,
- "Failed to create stdin pipe: %s", strerror(errno));
- return 1;
- }
-
- int fd_out[2];
- if (-1 == pipe(fd_out)) {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_EXEC,
- "Failed to create stdout pipe: %s", strerror(errno));
- close(fd_in[0]);
- close(fd_in[1]);
- return 1;
- }
-
- int fd_err[2];
- if (-1 == pipe(fd_err)) {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_EXEC,
- "Failed to create stderr pipe: %s", strerror(errno));
- close(fd_in[0]);
- close(fd_in[1]);
- close(fd_out[0]);
- close(fd_out[1]);
- return 1;
- }
-
- pid_t pid = fork();
- if (pid == -1) {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_EXEC,
- "Failed to fork: %s", strerror(errno));
- close(fd_in[0]);
- close(fd_in[1]);
- close(fd_out[0]);
- close(fd_out[1]);
- close(fd_err[0]);
- close(fd_err[1]);
- return 1;
- }
-
- // child
- if (pid == 0) {
- close(fd_in[1]);
- close(fd_out[0]);
- close(fd_err[0]);
-
- dup2(fd_in[0], STDIN_FILENO);
- dup2(fd_out[1], STDOUT_FILENO);
- dup2(fd_err[1], STDERR_FILENO);
-
- char *const argv[] = {
- "/bin/sh",
- "-c",
- (char*) cmd,
- NULL,
- };
-
- execv(argv[0], argv);
-
- exit(1);
- }
-
- // parent
- close(fd_in[0]);
- close(fd_out[1]);
- close(fd_err[1]);
-
- if (input != NULL) {
- if (-1 == write(fd_in[1], input, strlen(input))) {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_EXEC,
- "Failed to write to stdin pipe: %s", strerror(errno));
- close(fd_in[1]);
- close(fd_out[0]);
- close(fd_err[0]);
- return 1;
- }
- }
-
- close(fd_in[1]);
-
- char buffer[BC_FILE_CHUNK_SIZE];
- ssize_t s;
-
- bc_string_t *out = NULL;
- while(0 != (s = read(fd_out[0], buffer, BC_FILE_CHUNK_SIZE))) {
- if (s == -1) {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_EXEC,
- "Failed to read from stdout pipe: %s", strerror(errno));
- close(fd_out[0]);
- close(fd_err[0]);
- bc_string_free(out, true);
- return 1;
- }
- if (out == NULL) {
- out = bc_string_new();
- }
- bc_string_append_len(out, buffer, s);
- }
- if (out != NULL) {
- *output = bc_string_free(out, false);
- }
- close(fd_out[0]);
-
- out = NULL;
- while(0 != (s = read(fd_err[0], buffer, BC_FILE_CHUNK_SIZE))) {
- if (s == -1) {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_EXEC,
- "Failed to read from stderr pipe: %s", strerror(errno));
- close(fd_err[0]);
- bc_string_free(out, true);
- return 1;
- }
- if (out == NULL)
- out = bc_string_new();
- bc_string_append_len(out, buffer, s);
- }
- if (out != NULL) {
- *error = bc_string_free(out, false);
- }
- close(fd_err[0]);
-
- int status;
- waitpid(pid, &status, 0);
-
- return bc_compat_status_code(status);
-}
-
-
-static void
-list_variables(const char *key, const char *value, bc_string_t *str)
-{
- char *tmp = bc_shell_quote(value);
- bc_string_append_printf(str, " -D %s=%s", key, tmp);
- free(tmp);
-}
-
-
-char*
-bm_exec_build_blogc_cmd(const char *blogc_bin, bm_settings_t *settings,
- bc_trie_t *global_variables, bc_trie_t *local_variables, const char *print,
- bool listing, const char *listing_entry, const char *template,
- const char *output, bool dev, bool sources_stdin)
-{
- bc_string_t *rv = bc_string_new();
-
- const char *locale = NULL;
- if (settings != NULL) {
- locale = bc_trie_lookup(settings->settings, "locale");
- }
- if (locale != NULL) {
- char *tmp = bc_shell_quote(locale);
- bc_string_append_printf(rv, "LC_ALL=%s ", tmp);
- free(tmp);
- }
-
- bc_string_append(rv, blogc_bin);
-
- if (settings != NULL) {
- if (settings->tags != NULL) {
- char *tags = bc_strv_join(settings->tags, " ");
- bc_string_append_printf(rv, " -D MAKE_TAGS='%s'", tags);
- free(tags);
- }
-
- bc_trie_foreach(settings->global,
- (bc_trie_foreach_func_t) list_variables, rv);
- }
-
- bc_trie_foreach(global_variables, (bc_trie_foreach_func_t) list_variables, rv);
- bc_trie_foreach(local_variables, (bc_trie_foreach_func_t) list_variables, rv);
-
- if (dev) {
- bc_string_append(rv, " -D MAKE_ENV_DEV=1 -D MAKE_ENV='dev'");
- }
-
- if (print != NULL) {
- bc_string_append_printf(rv, " -p %s", print);
- }
-
- if (listing) {
- bc_string_append(rv, " -l");
- if (listing_entry != NULL) {
- char *tmp = bc_shell_quote(listing_entry);
- bc_string_append_printf(rv, " -e %s", tmp);
- free(tmp);
- }
- }
-
- if (template != NULL) {
- char *tmp = bc_shell_quote(template);
- bc_string_append_printf(rv, " -t %s", tmp);
- free(tmp);
- }
-
- if (output != NULL) {
- char *tmp = bc_shell_quote(output);
- bc_string_append_printf(rv, " -o %s", tmp);
- free(tmp);
- }
-
- if (sources_stdin) {
- bc_string_append(rv, " -i");
- }
-
- return bc_string_free(rv, false);
-}
-
-
-int
-bm_exec_blogc(bm_ctx_t *ctx, bc_trie_t *global_variables, bc_trie_t *local_variables,
- bool listing, bm_filectx_t *listing_entry, bm_filectx_t *template,
- bm_filectx_t *output, bc_slist_t *sources, bool only_first_source)
-{
- if (ctx == NULL)
- return 1;
-
- bc_string_t *input = bc_string_new();
- for (bc_slist_t *l = sources; l != NULL; l = l->next) {
- bc_string_append_printf(input, "%s\n", ((bm_filectx_t*) l->data)->path);
- if (only_first_source)
- break;
- }
-
- char *cmd = bm_exec_build_blogc_cmd(ctx->blogc, ctx->settings, global_variables,
- local_variables, NULL, listing, listing_entry == NULL ? NULL : listing_entry->path,
- template->path, output->path, ctx->dev, input->len > 0);
-
- if (ctx->verbose)
- printf("%s\n", cmd);
- else
- printf(" BLOGC %s\n", output->short_path);
- fflush(stdout);
-
- char *out = NULL;
- char *err = NULL;
- bc_error_t *error = NULL;
-
- int rv = bm_exec_command(cmd, input->str, &out, &err, &error);
-
- if (error != NULL) {
- bc_error_print(error, "blogc-make");
- free(cmd);
- free(out);
- free(err);
- bc_string_free(input, true);
- bc_error_free(error);
- return 1;
- }
-
- if (rv != 0 && ctx->verbose) {
- fprintf(stderr,
- "blogc-make: error: Failed to execute command.\n"
- "\n"
- "STATUS CODE: %d\n", rv);
- if (input->len > 0) {
- fprintf(stderr, "\nSTDIN:\n"
- "----------------------------->8-----------------------------\n"
- "%s\n"
- "----------------------------->8-----------------------------\n",
- bc_str_strip(input->str));
- }
- if (out != NULL) {
- fprintf(stderr, "\nSTDOUT:\n"
- "----------------------------->8-----------------------------\n"
- "%s\n"
- "----------------------------->8-----------------------------\n",
- bc_str_strip(out));
- }
- if (err != NULL) {
- fprintf(stderr, "\nSTDERR:\n"
- "----------------------------->8-----------------------------\n"
- "%s\n"
- "----------------------------->8-----------------------------\n",
- bc_str_strip(err));
- }
- fprintf(stderr, "\n");
- }
- else if (err != NULL) {
- fprintf(stderr, "%s\n", err);
- }
-
- bc_string_free(input, true);
- free(cmd);
- free(out);
- free(err);
-
- return rv == 127 ? 1 : rv;
-}
-
-
-char*
-bm_exec_blogc_get_variable(bm_ctx_t *ctx, bc_trie_t *global_variables,
- bc_trie_t *local_variables, const char *variable, bool listing,
- bc_slist_t *sources, bool only_first_source)
-{
- if (ctx == NULL)
- return NULL;
-
- bc_string_t *input = bc_string_new();
- for (bc_slist_t *l = sources; l != NULL; l = l->next) {
- bc_string_append_printf(input, "%s\n", ((bm_filectx_t*) l->data)->path);
- if (only_first_source)
- break;
- }
-
- char *cmd = bm_exec_build_blogc_cmd(ctx->blogc, ctx->settings, global_variables,
- local_variables, variable, listing, NULL, NULL, NULL, ctx->dev, input->len > 0);
-
- if (ctx->verbose)
- printf("%s\n", cmd);
- fflush(stdout);
-
- char *out = NULL;
- char *err = NULL;
- bc_error_t *error = NULL;
-
- int rv = bm_exec_command(cmd, input->str, &out, &err, &error);
-
- if (error != NULL) {
- bc_error_print(error, "blogc-make");
- bc_error_free(error);
- bc_string_free(input, true);
- free(cmd);
- free(out);
- free(err);
- return NULL;
- }
-
- if (rv != 0) {
- if (rv != EX_CONFIG)
- fprintf(stderr, "blogc-make: error: %s\n", bc_str_strip(err));
- bc_string_free(input, true);
- free(cmd);
- free(out);
- free(err);
- return NULL;
- }
-
- char *val = NULL;
- if (out != NULL)
- val = bc_strndup(out, strlen(out) - 1);
-
- bc_string_free(input, true);
- free(cmd);
- free(out);
- free(err);
-
- return val;
-}
-
-
-int
-bm_exec_blogc_runserver(bm_ctx_t *ctx, const char *host, const char *port,
- const char *threads)
-{
- if (ctx == NULL)
- return 1;
-
- bc_string_t *cmd = bc_string_new();
-
- bc_string_append(cmd, ctx->blogc_runserver);
-
- if (host != NULL) {
- char *tmp = bc_shell_quote(host);
- bc_string_append_printf(cmd, " -t %s", tmp);
- free(tmp);
- }
-
- if (port != NULL) {
- char *tmp = bc_shell_quote(port);
- bc_string_append_printf(cmd, " -p %s", tmp);
- free(tmp);
- }
-
- if (threads != NULL) {
- char *tmp = bc_shell_quote(threads);
- bc_string_append_printf(cmd, " -m %s", tmp);
- free(tmp);
- }
-
- char *tmp = bc_shell_quote(ctx->output_dir);
- bc_string_append_printf(cmd, " %s", tmp);
- free(tmp);
-
- if (ctx->verbose)
- printf("%s\n\n", cmd->str);
- else
- printf("\n");
- fflush(stdout);
-
- // we don't need pipes to run blogc-runserver, because it is "interactive"
- int status = system(cmd->str);
- int rv = bc_compat_status_code(status);
- bc_string_free(cmd, true);
-
- if (rv != 0 && rv != 130) {
- if (rv == 127) {
- fprintf(stderr,
- "blogc-make: error: blogc-runserver command not found. Maybe "
- "it is not installed?\n");
- rv = 1; // blogc-make exists, so we should not return 127
- }
- else {
- fprintf(stderr,
- "blogc-make: error: Failed to execute command, returned "
- "status code: %d\n", rv);
- }
- }
-
- return rv;
-}
diff --git a/src/blogc-make/exec.h b/src/blogc-make/exec.h
deleted file mode 100644
index 6bc206f..0000000
--- a/src/blogc-make/exec.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _MAKE_EXEC_H
-#define _MAKE_EXEC_H
-
-#include <stdbool.h>
-#include "../common/error.h"
-#include "../common/utils.h"
-#include "ctx.h"
-#include "settings.h"
-
-char* bm_exec_find_binary(const char *argv0, const char *bin, const char *env);
-int bm_exec_command(const char *cmd, const char *input, char **output,
- char **error, bc_error_t **err);
-char* bm_exec_build_blogc_cmd(const char *blogc_bin, bm_settings_t *settings,
- bc_trie_t *global_variables, bc_trie_t *local_variables, const char *print,
- bool listing, const char *listing_entry, const char *template,
- const char *output, bool dev, bool sources_stdin);
-int bm_exec_blogc(bm_ctx_t *ctx, bc_trie_t *global_variables,
- bc_trie_t *local_variables, bool listing, bm_filectx_t *listing_entry,
- bm_filectx_t *template, bm_filectx_t *output, bc_slist_t *sources,
- bool only_first_source);
-char* bm_exec_blogc_get_variable(bm_ctx_t *ctx, bc_trie_t *global_variables,
- bc_trie_t *local_variables, const char *variable, bool listing,
- bc_slist_t *sources, bool only_first_source);
-int bm_exec_blogc_runserver(bm_ctx_t *ctx, const char *host, const char *port,
- const char *threads);
-
-#endif /* _MAKE_EXEC_H */
diff --git a/src/blogc-make/httpd.c b/src/blogc-make/httpd.c
deleted file mode 100644
index c352da0..0000000
--- a/src/blogc-make/httpd.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2020 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <unistd.h>
-#include "../common/utils.h"
-#include "ctx.h"
-#include "exec.h"
-#include "reloader.h"
-#include "httpd.h"
-
-// we are not going to unit-test these functions, then printing errors
-// directly is not a big issue
-
-
-typedef struct {
- bm_ctx_t *ctx;
- bc_trie_t *args;
-} bm_httpd_t;
-
-static pthread_mutex_t mutex_httpd_starting = PTHREAD_MUTEX_INITIALIZER;
-static bool httpd_starting = false;
-
-
-static void*
-httpd_thread(void *arg)
-{
- bm_httpd_t *httpd = arg;
-
- pthread_mutex_lock(&mutex_httpd_starting);
- httpd_starting = true;
- pthread_mutex_unlock(&mutex_httpd_starting);
-
- int rv = bm_exec_blogc_runserver(httpd->ctx, bc_trie_lookup(httpd->args, "host"),
- bc_trie_lookup(httpd->args, "port"), bc_trie_lookup(httpd->args, "threads"));
-
- pthread_mutex_lock(&mutex_httpd_starting);
- httpd_starting = false;
- pthread_mutex_unlock(&mutex_httpd_starting);
-
- free(httpd);
-
- // stop the reloader
- bm_reloader_stop(rv);
-
- return NULL;
-}
-
-
-int
-bm_httpd_run(bm_ctx_t **ctx, bm_rule_exec_func_t rule_exec, bc_slist_t *outputs,
- bc_trie_t *args)
-{
- pthread_mutex_lock(&mutex_httpd_starting);
- bool starting = httpd_starting;
- pthread_mutex_unlock(&mutex_httpd_starting);
-
- if (starting) {
- fprintf(stderr, "blogc-make: error: httpd already running\n");
- return 1;
- }
-
- int err;
-
- pthread_attr_t attr;
- if (0 != (err = pthread_attr_init(&attr))) {
- fprintf(stderr, "blogc-make: error: failed to initialize httpd "
- "thread attributes: %s\n", strerror(err));
- return 1;
- }
-
- // we run the thread detached, because we don't want to wait it to join
- // before exiting. the OS can clean it properly
- if (0 != (err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))) {
- fprintf(stderr, "blogc-make: error: failed to mark httpd thread as "
- "detached: %s\n", strerror(err));
- return 1;
- }
-
- bm_httpd_t *rv = bc_malloc(sizeof(bm_httpd_t));
- rv->ctx = *ctx;
- rv->args = args;
-
- pthread_t thread;
- if (0 != (err = pthread_create(&thread, &attr, httpd_thread, rv))) {
- fprintf(stderr, "blogc-make: error: failed to create httpd "
- "thread: %s\n", strerror(err));
- free(rv);
- return 1;
- }
-
- // we could use some pthread_*_timedwait() apis here, but I decided to
- // just use simple mutexes for the sake of portability.
- size_t count = 0;
- while (true) {
- pthread_mutex_lock(&mutex_httpd_starting);
- starting = httpd_starting;
- pthread_mutex_unlock(&mutex_httpd_starting);
-
- if (starting)
- break;
-
- if (++count > 100) {
- fprintf(stderr, "blogc-make: error: failed to start httpd thread: "
- "too many retries\n");
- // rv will leak, but it is not safe to free here
- return 1;
- }
- usleep(100000);
- }
-
- return bm_reloader_run(ctx, rule_exec, outputs, args);
-}
diff --git a/src/blogc-make/httpd.h b/src/blogc-make/httpd.h
deleted file mode 100644
index b0fa87d..0000000
--- a/src/blogc-make/httpd.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _MAKE_HTTPD_H
-#define _MAKE_HTTPD_H
-
-#include "../common/utils.h"
-#include "ctx.h"
-#include "rules.h"
-
-int bm_httpd_run(bm_ctx_t **ctx, bm_rule_exec_func_t rule_exec, bc_slist_t *outputs,
- bc_trie_t *args);
-
-#endif /* _MAKE_HTTPD_H */
diff --git a/src/blogc-make/main.c b/src/blogc-make/main.c
deleted file mode 100644
index 5b4a030..0000000
--- a/src/blogc-make/main.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif /* HAVE_CONFIG_H */
-
-#include <locale.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "../common/error.h"
-#include "../common/utils.h"
-#include "ctx.h"
-#include "rules.h"
-
-
-static void
-print_help(void)
-{
- printf(
- "usage:\n"
- " blogc-make [-h] [-v] [-D] [-V] [-f FILE] [RULE ...]\n"
- " - A simple build tool for blogc.\n"
- "\n"
- "positional arguments:\n"
- " RULE build rule(s) to run. can include comma-separated\n"
- " key-value pairs of rule arguments in the format\n"
- " RULE:arg1=value1,arg2=value2,... (default: all)\n"
- "\n"
- "optional arguments:\n"
- " -h show this help message and exit\n"
- " -v show version and exit\n"
- " -D build for development environment\n"
- " -V be verbose when executing commands\n"
- " -f FILE read FILE as blogcfile\n");
- bm_rule_print_help();
-}
-
-
-static void
-print_usage(void)
-{
- printf("usage: blogc-make [-h] [-v] [-D] [-V] [-f FILE] [RULE ...]\n");
-}
-
-
-int
-#ifdef MAKE_EMBEDDED
-bm_main(int argc, char **argv)
-#else
-main(int argc, char **argv)
-#endif
-{
- setlocale(LC_ALL, "");
-
- int rv = 0;
- bc_error_t *err = NULL;
-
- bc_slist_t *rules = NULL;
- bool verbose = false;
- bool dev = false;
- char *blogcfile = NULL;
- bm_ctx_t *ctx = NULL;
-
- for (size_t 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 'D':
- dev = true;
- break;
- case 'V':
- verbose = true;
- break;
- case 'f':
- if (argv[i][2] != '\0')
- blogcfile = bc_strdup(argv[i] + 2);
- else if (i + 1 < argc)
- blogcfile = bc_strdup(argv[++i]);
- break;
-#ifdef MAKE_EMBEDDED
- case 'm':
- // no-op, for embedding into blogc binary.
- break;
-#endif
- default:
- print_usage();
- fprintf(stderr, "blogc-make: error: invalid argument: "
- "-%c\n", argv[i][1]);
- rv = 1;
- goto cleanup;
- }
- }
- else {
- rules = bc_slist_append(rules, bc_strdup(argv[i]));
- }
- }
-
- if (rules == NULL) {
- rules = bc_slist_append(rules, bc_strdup("all"));
- }
-
- ctx = bm_ctx_new(NULL, blogcfile ? blogcfile : "blogcfile",
- argc > 0 ? argv[0] : NULL, &err);
- if (err != NULL) {
- bc_error_print(err, "blogc-make");
- rv = 1;
- goto cleanup;
- }
- ctx->dev = dev;
- ctx->verbose = verbose;
-
- rv = bm_rule_executor(ctx, rules);
-
-cleanup:
-
- bc_slist_free_full(rules, free);
- free(blogcfile);
- bm_ctx_free(ctx);
- bc_error_free(err);
-
- return rv;
-}
diff --git a/src/blogc-make/reloader.c b/src/blogc-make/reloader.c
deleted file mode 100644
index fea8bd4..0000000
--- a/src/blogc-make/reloader.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <string.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <errno.h>
-#include "../common/utils.h"
-#include "ctx.h"
-#include "rules.h"
-#include "reloader.h"
-
-// we are not going to unit-test these functions, then printing errors
-// directly is not a big issue
-
-static pthread_mutex_t mutex_running = PTHREAD_MUTEX_INITIALIZER;
-static bool running = false;
-static int reloader_status_code = 0;
-static void (*handler_func)(int) = NULL;
-
-static void
-sig_handler(int signum)
-{
- bm_reloader_stop(signum + 128);
-}
-
-
-int
-bm_reloader_run(bm_ctx_t **ctx, bm_rule_exec_func_t rule_exec,
- bc_slist_t *outputs, bc_trie_t *args)
-{
- // install ^C handler
- struct sigaction current_action;
- if (sigaction(SIGINT, NULL, &current_action) < 0) {
- fprintf(stderr, "blogc-make: failed to run reloader: %s\n", strerror(errno));
- return 1;
- }
- if (current_action.sa_handler != sig_handler) { // not installed yet
- // backup current handler
- pthread_mutex_lock(&mutex_running);
- handler_func = current_action.sa_handler;
- pthread_mutex_unlock(&mutex_running);
-
- // set new handler
- struct sigaction new_action;
- new_action.sa_handler = sig_handler;
- sigemptyset(&new_action.sa_mask);
- new_action.sa_flags = 0;
- if (sigaction(SIGINT, &new_action, NULL) < 0) {
- fprintf(stderr, "blogc-make: failed to run reloader: %s\n",
- strerror(errno));
- return 1;
- }
- }
-
- pthread_mutex_lock(&mutex_running);
- running = true;
- pthread_mutex_unlock(&mutex_running);
-
- while (running) {
- if (!bm_ctx_reload(ctx)) {
- fprintf(stderr, "blogc-make: warning: failed to reload context. "
- "retrying in 5 seconds ...\n\n");
- sleep(5);
- continue;
- }
- if (0 != rule_exec(*ctx, outputs, args)) {
- fprintf(stderr, "blogc-make: warning: failed to rebuild website. "
- "retrying in 5 seconds ...\n\n");
- sleep(5);
- continue;
- }
- sleep(1);
- }
-
- return reloader_status_code;
-}
-
-
-void
-bm_reloader_stop(int status_code)
-{
- pthread_mutex_lock(&mutex_running);
-
- running = false;
- reloader_status_code = status_code;
-
- // reraise if SIGINT
- if (status_code == SIGINT + 128) {
-
- // reinstall old ^C handler
- struct sigaction new_action;
- new_action.sa_handler = handler_func;
- sigemptyset(&new_action.sa_mask);
- new_action.sa_flags = 0;
- sigaction(SIGINT, &new_action, NULL);
-
- // run it
- raise(SIGINT);
-
- // SIGINT will usually kill the process, but in the case that the
- // `handler_func` prevents it, our custom handler will be reinstalled
- // by `bm_reloader_run`.
- }
-
- pthread_mutex_unlock(&mutex_running);
-}
diff --git a/src/blogc-make/reloader.h b/src/blogc-make/reloader.h
deleted file mode 100644
index f3fddf4..0000000
--- a/src/blogc-make/reloader.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _MAKE_RELOADER_H
-#define _MAKE_RELOADER_H
-
-#include "../common/utils.h"
-#include "ctx.h"
-#include "rules.h"
-
-int bm_reloader_run(bm_ctx_t **ctx, bm_rule_exec_func_t rule_exec,
- bc_slist_t *outputs, bc_trie_t *args);
-void bm_reloader_stop(int status_code);
-
-#endif /* _MAKE_RELOADER_H */
diff --git a/src/blogc-make/rules.c b/src/blogc-make/rules.c
deleted file mode 100644
index 7d92b95..0000000
--- a/src/blogc-make/rules.c
+++ /dev/null
@@ -1,1078 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2020 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
-#include "../common/utils.h"
-#include "atom.h"
-#include "ctx.h"
-#include "exec.h"
-#include "exec-native.h"
-#include "httpd.h"
-#include "reloader.h"
-#include "settings.h"
-#include "utils.h"
-#include "rules.h"
-
-
-static void
-posts_ordering(bm_ctx_t *ctx, bc_trie_t *variables, const char *variable)
-{
- if (ctx == NULL)
- return; // something is wrong, let's not add any variable
-
- const char *value = bm_ctx_settings_lookup_str(ctx, variable);
- bool asc = 0 == strcasecmp(value, "asc");
- bool sort = bc_str_to_bool(bm_ctx_settings_lookup(ctx, "posts_sort"));
-
- if (sort) {
- bc_trie_insert(variables, "FILTER_SORT", bc_strdup("1"));
- }
-
- if ((sort && asc) || (!sort && !asc)) {
- bc_trie_insert(variables, "FILTER_REVERSE", bc_strdup("1"));
- }
-}
-
-
-static void
-posts_pagination(bm_ctx_t *ctx, bc_trie_t *variables, const char *variable)
-{
- if (ctx == NULL)
- return; // something is wrong, let's not add any variable
-
- long posts_per_page = strtol(bm_ctx_settings_lookup_str(ctx, variable), NULL, 10);
- if (posts_per_page >= 0) {
- bc_trie_insert(variables, "FILTER_PAGE", bc_strdup("1"));
- bc_trie_insert(variables, "FILTER_PER_PAGE",
- bc_strdup(bm_ctx_settings_lookup(ctx, variable)));
- }
-}
-
-
-static bool
-posts_pagination_enabled(bm_ctx_t *ctx, const char *variable)
-{
- if (ctx == NULL)
- return false;
-
- long posts_per_page = strtol(bm_ctx_settings_lookup_str(ctx, variable), NULL, 10);
- return posts_per_page != 0;
-}
-
-
-// INDEX RULE
-
-static bc_slist_t*
-index_outputlist(bm_ctx_t *ctx)
-{
- if (ctx == NULL || ctx->settings->posts == NULL)
- return NULL;
-
- if (!posts_pagination_enabled(ctx, "posts_per_page"))
- return NULL;
-
- bc_slist_t *rv = NULL;
-
- const char *index_prefix = bm_ctx_settings_lookup(ctx, "index_prefix");
- const char *html_ext = bm_ctx_settings_lookup(ctx, "html_ext");
-
- char *f = bm_generate_filename(ctx->short_output_dir, index_prefix, NULL,
- html_ext);
- rv = bc_slist_append(rv, bm_filectx_new(ctx, f, NULL, NULL));
- free(f);
-
- return rv;
-}
-
-static int
-index_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
-{
- if (ctx == NULL || ctx->settings->posts == NULL)
- return 0;
-
- int rv = 0;
-
- bc_trie_t *variables = bc_trie_new(free);
- posts_pagination(ctx, variables, "posts_per_page");
- posts_ordering(ctx, variables, "html_order");
- bc_trie_insert(variables, "DATE_FORMAT",
- bc_strdup(bm_ctx_settings_lookup_str(ctx, "date_format")));
- bc_trie_insert(variables, "MAKE_RULE", bc_strdup("index"));
- bc_trie_insert(variables, "MAKE_TYPE", bc_strdup("post"));
-
- for (bc_slist_t *l = outputs; l != NULL; l = l->next) {
- bm_filectx_t *fctx = l->data;
- if (fctx == NULL)
- continue;
- if (bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx,
- ctx->listing_entry_fctx, ctx->main_template_fctx, fctx, false))
- {
- rv = bm_exec_blogc(ctx, variables, NULL, true, ctx->listing_entry_fctx,
- ctx->main_template_fctx, fctx, ctx->posts_fctx, false);
- if (rv != 0)
- break;
- }
- }
-
- bc_trie_free(variables);
-
- return rv;
-}
-
-
-// ATOM RULE
-
-static bc_slist_t*
-atom_outputlist(bm_ctx_t *ctx)
-{
- if (ctx == NULL || ctx->settings->posts == NULL)
- return NULL;
-
- if (!posts_pagination_enabled(ctx, "atom_posts_per_page"))
- return NULL;
-
- bc_slist_t *rv = NULL;
-
- const char *atom_prefix = bm_ctx_settings_lookup(ctx, "atom_prefix");
- const char *atom_ext = bm_ctx_settings_lookup(ctx, "atom_ext");
-
- char *f = bm_generate_filename(ctx->short_output_dir, atom_prefix, NULL,
- atom_ext);
- rv = bc_slist_append(rv, bm_filectx_new(ctx, f, NULL, NULL));
- free(f);
-
- return rv;
-}
-
-static int
-atom_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
-{
- if (ctx == NULL || ctx->settings->posts == NULL)
- return 0;
-
- int rv = 0;
-
- bc_trie_t *variables = bc_trie_new(free);
- posts_pagination(ctx, variables, "atom_posts_per_page");
- posts_ordering(ctx, variables, "atom_order");
- bc_trie_insert(variables, "DATE_FORMAT", bc_strdup("%Y-%m-%dT%H:%M:%SZ"));
- bc_trie_insert(variables, "MAKE_RULE", bc_strdup("atom"));
- bc_trie_insert(variables, "MAKE_TYPE", bc_strdup("atom"));
-
- for (bc_slist_t *l = outputs; l != NULL; l = l->next) {
- bm_filectx_t *fctx = l->data;
- if (fctx == NULL)
- continue;
- if (bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx, NULL,
- ctx->atom_template_tmp ? NULL : ctx->atom_template_fctx,
- fctx, false))
- {
- rv = bm_exec_blogc(ctx, variables, NULL, true, NULL, ctx->atom_template_fctx,
- fctx, ctx->posts_fctx, false);
- if (rv != 0)
- break;
- }
- }
-
- bc_trie_free(variables);
-
- return rv;
-}
-
-
-// ATOM TAGS RULE
-
-static bc_slist_t*
-atom_tags_outputlist(bm_ctx_t *ctx)
-{
- if (ctx == NULL || ctx->settings->posts == NULL || ctx->settings->tags == NULL)
- return NULL;
-
- if (!posts_pagination_enabled(ctx, "atom_posts_per_page"))
- return NULL;
-
- bc_slist_t *rv = NULL;
-
- const char *atom_prefix = bm_ctx_settings_lookup(ctx, "atom_prefix");
- const char *atom_ext = bm_ctx_settings_lookup(ctx, "atom_ext");
-
- for (size_t i = 0; ctx->settings->tags[i] != NULL; i++) {
- char *f = bm_generate_filename(ctx->short_output_dir, atom_prefix,
- ctx->settings->tags[i], atom_ext);
- rv = bc_slist_append(rv, bm_filectx_new(ctx, f, NULL, NULL));
- free(f);
- }
-
- return rv;
-}
-
-static int
-atom_tags_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
-{
- if (ctx == NULL || ctx->settings->posts == NULL || ctx->settings->tags == NULL)
- return 0;
-
- int rv = 0;
- size_t i = 0;
-
- bc_trie_t *variables = bc_trie_new(free);
- posts_pagination(ctx, variables, "atom_posts_per_page");
- posts_ordering(ctx, variables, "atom_order");
- bc_trie_insert(variables, "DATE_FORMAT", bc_strdup("%Y-%m-%dT%H:%M:%SZ"));
- bc_trie_insert(variables, "MAKE_RULE", bc_strdup("atom_tags"));
- bc_trie_insert(variables, "MAKE_TYPE", bc_strdup("atom"));
-
- for (bc_slist_t *l = outputs; l != NULL; l = l->next, i++) {
- bm_filectx_t *fctx = l->data;
- if (fctx == NULL)
- continue;
-
- bc_trie_insert(variables, "FILTER_TAG",
- bc_strdup(ctx->settings->tags[i]));
-
- if (bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx, NULL,
- ctx->atom_template_tmp ? NULL : ctx->atom_template_fctx,
- fctx, false))
- {
- rv = bm_exec_blogc(ctx, variables, NULL, true, NULL, ctx->atom_template_fctx,
- fctx, ctx->posts_fctx, false);
- if (rv != 0)
- break;
- }
- }
-
- bc_trie_free(variables);
-
- return rv;
-}
-
-
-// PAGINATION RULE
-
-static bc_slist_t*
-pagination_outputlist(bm_ctx_t *ctx)
-{
- if (ctx == NULL || ctx->settings->posts == NULL)
- return NULL;
-
- if (!posts_pagination_enabled(ctx, "posts_per_page"))
- return NULL;
-
- bc_trie_t *variables = bc_trie_new(free);
- posts_pagination(ctx, variables, "posts_per_page");
-
- char *last_page = bm_exec_blogc_get_variable(ctx, variables, NULL, "LAST_PAGE",
- true, ctx->posts_fctx, false);
-
- bc_trie_free(variables);
-
- if (last_page == NULL)
- return NULL;
-
- long pages = strtol(last_page, NULL, 10);
- free(last_page);
-
- bc_slist_t *rv = NULL;
-
- const char *pagination_prefix = bm_ctx_settings_lookup(ctx, "pagination_prefix");
- const char *html_ext = bm_ctx_settings_lookup(ctx, "html_ext");
-
- for (size_t i = 0; i < pages; i++) {
- char *j = bc_strdup_printf("%d", i + 1);
- char *f = bm_generate_filename(ctx->short_output_dir, pagination_prefix,
- j, html_ext);
- rv = bc_slist_append(rv, bm_filectx_new(ctx, f, NULL, NULL));
- free(j);
- free(f);
- }
-
- return rv;
-}
-
-static int
-pagination_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
-{
- if (ctx == NULL || ctx->settings->posts == NULL)
- return 0;
-
- int rv = 0;
- size_t page = 1;
-
- bc_trie_t *variables = bc_trie_new(free);
- // not using posts_pagination because we set FILTER_PAGE anyway, and the
- // first value inserted in that function would be useless
- bc_trie_insert(variables, "FILTER_PER_PAGE",
- bc_strdup(bm_ctx_settings_lookup_str(ctx, "posts_per_page")));
- posts_ordering(ctx, variables, "html_order");
- bc_trie_insert(variables, "DATE_FORMAT",
- bc_strdup(bm_ctx_settings_lookup_str(ctx, "date_format")));
- bc_trie_insert(variables, "MAKE_RULE", bc_strdup("pagination"));
- bc_trie_insert(variables, "MAKE_TYPE", bc_strdup("post"));
-
- for (bc_slist_t *l = outputs; l != NULL; l = l->next, page++) {
- bm_filectx_t *fctx = l->data;
- if (fctx == NULL)
- continue;
- bc_trie_insert(variables, "FILTER_PAGE", bc_strdup_printf("%zu", page));
- if (bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx,
- ctx->listing_entry_fctx, ctx->main_template_fctx, fctx, false))
- {
- rv = bm_exec_blogc(ctx, variables, NULL, true, ctx->listing_entry_fctx,
- ctx->main_template_fctx, fctx, ctx->posts_fctx, false);
- if (rv != 0)
- break;
- }
- }
-
- bc_trie_free(variables);
-
- return rv;
-}
-
-
-// PAGINATION TAGS RULE
-
-static bc_slist_t*
-pagination_tags_outputlist(bm_ctx_t *ctx)
-{
- if (ctx == NULL || ctx->settings->posts == NULL || ctx->settings->tags == NULL)
- return NULL;
-
- if (!posts_pagination_enabled(ctx, "posts_per_page"))
- return NULL;
-
- bc_trie_t *variables = bc_trie_new(free);
- posts_pagination(ctx, variables, "posts_per_page");
-
- const char *tag_prefix = bm_ctx_settings_lookup(ctx, "tag_prefix");
- const char *pagination_prefix = bm_ctx_settings_lookup(ctx, "pagination_prefix");
- const char *html_ext = bm_ctx_settings_lookup(ctx, "html_ext");
-
- bc_slist_t *rv = NULL;
-
- for (size_t k = 0; ctx->settings->tags[k] != NULL; k++) {
- bc_trie_t *local = bc_trie_new(free);
- bc_trie_insert(local, "FILTER_TAG", bc_strdup(ctx->settings->tags[k]));
-
- char *last_page = bm_exec_blogc_get_variable(ctx, variables, local,
- "LAST_PAGE", true, ctx->posts_fctx, false);
-
- bc_trie_free(local);
-
- if (last_page == NULL)
- continue;
-
- long pages = strtol(last_page, NULL, 10);
- free(last_page);
-
- for (size_t i = 0; i < pages; i++) {
- char *j = bc_strdup_printf("%d", i + 1);
- char *f = bm_generate_filename2(ctx->short_output_dir, tag_prefix,
- ctx->settings->tags[k], pagination_prefix, j, html_ext);
- rv = bc_slist_append(rv, bm_filectx_new(ctx, f, NULL, NULL));
- free(j);
- free(f);
- }
- }
-
- bc_trie_free(variables);
-
- return rv;
-}
-
-static int
-pagination_tags_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
-{
- if (ctx == NULL || ctx->settings->posts == NULL || ctx->settings->tags == NULL)
- return 0;
-
- int rv = 0;
- size_t page = 1;
-
- bc_trie_t *variables = bc_trie_new(free);
- // not using posts_pagination because we set FILTER_PAGE anyway, and the
- // first value inserted in that function would be useless
- bc_trie_insert(variables, "FILTER_PER_PAGE",
- bc_strdup(bm_ctx_settings_lookup_str(ctx, "posts_per_page")));
- posts_ordering(ctx, variables, "html_order");
- bc_trie_insert(variables, "DATE_FORMAT",
- bc_strdup(bm_ctx_settings_lookup_str(ctx, "date_format")));
- bc_trie_insert(variables, "MAKE_RULE", bc_strdup("pagination_tags"));
- bc_trie_insert(variables, "MAKE_TYPE", bc_strdup("post"));
-
- const char *tag_prefix = bm_ctx_settings_lookup(ctx, "tag_prefix");
- const char *pagination_prefix = bm_ctx_settings_lookup(ctx, "pagination_prefix");
- const char *html_ext = bm_ctx_settings_lookup(ctx, "html_ext");
-
- for (bc_slist_t *l = outputs; l != NULL; l = l->next) {
- bm_filectx_t *fctx = l->data;
- if (fctx == NULL)
- continue;
-
- // this is very expensive, but we don't have another way to detect the
- // tag and page from the file path right now :/
- char *tag = NULL;
- for (size_t i = 0; ctx->settings->tags[i] != NULL; i++) {
- bool b = false;
-
- // it is impossible to have more output files per tag than the whole
- // amount of output pages
- for (size_t k = 1; k <= bc_slist_length(outputs); k++) {
- char *j = bc_strdup_printf("%d", k);
- char *f = bm_generate_filename2(ctx->short_output_dir, tag_prefix,
- ctx->settings->tags[i], pagination_prefix, j, html_ext);
- free(j);
- if (0 == strcmp(fctx->short_path, f)) {
- tag = ctx->settings->tags[i];
- page = k;
- b = true;
- free(f);
- break;
- }
- free(f);
- }
- if (b)
- break;
- }
- if (tag == NULL)
- continue;
-
- bc_trie_insert(variables, "FILTER_TAG", bc_strdup(tag));
- bc_trie_insert(variables, "FILTER_PAGE", bc_strdup_printf("%zu", page));
-
- if (bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx,
- ctx->listing_entry_fctx, ctx->main_template_fctx, fctx, false))
- {
- rv = bm_exec_blogc(ctx, variables, NULL, true, ctx->listing_entry_fctx,
- ctx->main_template_fctx, fctx, ctx->posts_fctx, false);
- if (rv != 0)
- break;
- }
- }
-
- bc_trie_free(variables);
-
- return rv;
-}
-
-
-// POSTS RULE
-
-static bc_slist_t*
-posts_outputlist(bm_ctx_t *ctx)
-{
- if (ctx == NULL || ctx->settings->posts == NULL)
- return NULL;
-
- bc_slist_t *rv = NULL;
-
- const char *post_prefix = bm_ctx_settings_lookup(ctx, "post_prefix");
- const char *html_ext = bm_ctx_settings_lookup(ctx, "html_ext");
-
- for (size_t i = 0; ctx->settings->posts[i] != NULL; i++) {
- char *f = bm_generate_filename(ctx->short_output_dir, post_prefix,
- ctx->settings->posts[i], html_ext);
- rv = bc_slist_append(rv, bm_filectx_new(ctx, f, NULL, NULL));
- free(f);
- }
-
- return rv;
-}
-
-static int
-posts_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
-{
- if (ctx == NULL || ctx->settings->posts == NULL)
- return 0;
-
- int rv = 0;
-
- bc_trie_t *variables = bc_trie_new(free);
- bc_trie_insert(variables, "IS_POST", bc_strdup("1"));
- bc_trie_insert(variables, "DATE_FORMAT",
- bc_strdup(bm_ctx_settings_lookup(ctx, "date_format")));
- posts_ordering(ctx, variables, "html_order");
- bc_trie_insert(variables, "MAKE_RULE", bc_strdup("posts"));
- bc_trie_insert(variables, "MAKE_TYPE", bc_strdup("post"));
-
- bc_slist_t *s, *o;
-
- for (s = ctx->posts_fctx, o = outputs; s != NULL && o != NULL;
- s = s->next, o = o->next)
- {
- bm_filectx_t *s_fctx = s->data;
- bm_filectx_t *o_fctx = o->data;
- if (o_fctx == NULL)
- continue;
- if (bm_rule_need_rebuild(s, ctx->settings_fctx, NULL,
- ctx->main_template_fctx, o_fctx, true))
- {
- bc_trie_t *local = bc_trie_new(NULL);
- bc_trie_insert(local, "MAKE_SLUG", s_fctx->slug); // no need to copy
- rv = bm_exec_blogc(ctx, variables, local, false, NULL, ctx->main_template_fctx,
- o_fctx, s, true);
- bc_trie_free(local);
- if (rv != 0)
- break;
- }
- }
-
- bc_trie_free(variables);
-
- return rv;
-}
-
-
-// TAGS RULE
-
-static bc_slist_t*
-tags_outputlist(bm_ctx_t *ctx)
-{
- if (ctx == NULL || ctx->settings->posts == NULL || ctx->settings->tags == NULL)
- return NULL;
-
- if (!posts_pagination_enabled(ctx, "posts_per_page"))
- return NULL;
-
- bc_slist_t *rv = NULL;
-
- const char *tag_prefix = bm_ctx_settings_lookup(ctx, "tag_prefix");
- const char *html_ext = bm_ctx_settings_lookup(ctx, "html_ext");
-
- for (size_t i = 0; ctx->settings->tags[i] != NULL; i++) {
- char *f = bm_generate_filename(ctx->short_output_dir, tag_prefix,
- ctx->settings->tags[i], html_ext);
- rv = bc_slist_append(rv, bm_filectx_new(ctx, f, NULL, NULL));
- free(f);
- }
-
- return rv;
-}
-
-static int
-tags_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
-{
- if (ctx == NULL || ctx->settings->posts == NULL || ctx->settings->tags == NULL)
- return 0;
-
- int rv = 0;
- size_t i = 0;
-
- bc_trie_t *variables = bc_trie_new(free);
- posts_pagination(ctx, variables, "posts_per_page");
- posts_ordering(ctx, variables, "html_order");
- bc_trie_insert(variables, "DATE_FORMAT",
- bc_strdup(bm_ctx_settings_lookup_str(ctx, "date_format")));
- bc_trie_insert(variables, "MAKE_RULE", bc_strdup("tags"));
- bc_trie_insert(variables, "MAKE_TYPE", bc_strdup("post"));
-
- for (bc_slist_t *l = outputs; l != NULL; l = l->next, i++) {
- bm_filectx_t *fctx = l->data;
- if (fctx == NULL)
- continue;
-
- bc_trie_insert(variables, "FILTER_TAG",
- bc_strdup(ctx->settings->tags[i]));
-
- if (bm_rule_need_rebuild(ctx->posts_fctx, ctx->settings_fctx,
- ctx->listing_entry_fctx, ctx->main_template_fctx, fctx, false))
- {
- rv = bm_exec_blogc(ctx, variables, NULL, true, ctx->listing_entry_fctx,
- ctx->main_template_fctx, fctx, ctx->posts_fctx, false);
- if (rv != 0)
- break;
- }
- }
-
- bc_trie_free(variables);
-
- return rv;
-}
-
-
-// PAGES RULE
-
-static bc_slist_t*
-pages_outputlist(bm_ctx_t *ctx)
-{
- if (ctx == NULL || ctx->settings->pages == NULL)
- return NULL;
-
- bc_slist_t *rv = NULL;
-
- const char *html_ext = bm_ctx_settings_lookup(ctx, "html_ext");
-
- for (size_t i = 0; ctx->settings->pages[i] != NULL; i++) {
- char *f = bm_generate_filename(ctx->short_output_dir, NULL,
- ctx->settings->pages[i], html_ext);
- rv = bc_slist_append(rv, bm_filectx_new(ctx, f, NULL, NULL));
- free(f);
- }
-
- return rv;
-}
-
-static int
-pages_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
-{
- if (ctx == NULL || ctx->settings->pages == NULL)
- return 0;
-
- int rv = 0;
-
- bc_trie_t *variables = bc_trie_new(free);
- bc_trie_insert(variables, "DATE_FORMAT",
- bc_strdup(bm_ctx_settings_lookup(ctx, "date_format")));
- bc_trie_insert(variables, "MAKE_RULE", bc_strdup("pages"));
- bc_trie_insert(variables, "MAKE_TYPE", bc_strdup("page"));
-
- bc_slist_t *s, *o;
-
- for (s = ctx->pages_fctx, o = outputs; s != NULL && o != NULL;
- s = s->next, o = o->next)
- {
- bm_filectx_t *s_fctx = s->data;
- bm_filectx_t *o_fctx = o->data;
- if (o_fctx == NULL)
- continue;
- if (bm_rule_need_rebuild(s, ctx->settings_fctx, NULL,
- ctx->main_template_fctx, o_fctx, true))
- {
- bc_trie_t *local = bc_trie_new(NULL);
- bc_trie_insert(local, "MAKE_SLUG", s_fctx->slug); // no need to copy
- rv = bm_exec_blogc(ctx, variables, local, false, NULL, ctx->main_template_fctx,
- o_fctx, s, true);
- bc_trie_free(local);
- if (rv != 0)
- break;
- }
- }
-
- bc_trie_free(variables);
-
- return rv;
-}
-
-
-// COPY FILES RULE
-
-static bc_slist_t*
-copy_outputlist(bm_ctx_t *ctx)
-{
- if (ctx == NULL || ctx->settings->copy == NULL)
- return NULL;
-
- bc_slist_t *rv = NULL;
-
- // we iterate over ctx->copy_fctx list instead of ctx->settings->copy,
- // because bm_ctx_new() expands directories into its files, recursively.
- for (bc_slist_t *s = ctx->copy_fctx; s != NULL; s = s->next) {
- char *f = bc_strdup_printf("%s/%s", ctx->short_output_dir,
- ((bm_filectx_t*) s->data)->short_path);
- rv = bc_slist_append(rv, bm_filectx_new(ctx, f, NULL, NULL));
- free(f);
- }
-
- return rv;
-}
-
-static int
-copy_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
-{
- if (ctx == NULL || ctx->settings->copy == NULL)
- return 0;
-
- int rv = 0;
-
- bc_slist_t *s, *o;
-
- for (s = ctx->copy_fctx, o = outputs; s != NULL && o != NULL;
- s = s->next, o = o->next)
- {
- bm_filectx_t *o_fctx = o->data;
- if (o_fctx == NULL)
- continue;
-
- if (bm_rule_need_rebuild(s, ctx->settings_fctx, NULL, NULL, o_fctx, true)) {
- rv = bm_exec_native_cp(s->data, o_fctx, ctx->verbose);
- if (rv != 0)
- break;
- }
- }
-
- return rv;
-}
-
-
-// CLEAN RULE
-
-static int
-clean_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
-{
- int rv = 0;
-
- bc_slist_t *files = bm_rule_list_built_files(ctx);
- for (bc_slist_t *l = files; l != NULL; l = l->next) {
- bm_filectx_t *fctx = l->data;
- if (fctx == NULL)
- continue;
-
- if (fctx->readable) {
- rv = bm_exec_native_rm(ctx->output_dir, fctx, ctx->verbose);
- if (rv != 0)
- break;
- }
- }
- bc_slist_free_full(files, (bc_free_func_t) bm_filectx_free);
-
- if (!bm_exec_native_is_empty_dir(ctx->output_dir, NULL)) {
- fprintf(stderr, "blogc-make: warning: output directory is not empty!\n");
- }
-
- return rv;
-}
-
-
-static int all_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args);
-
-
-// RUNSERVER RULE
-
-static int
-runserver_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
-{
- return bm_httpd_run(&ctx, all_exec, outputs, args);
-}
-
-
-// WATCH RULE
-
-static int
-watch_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
-{
- return bm_reloader_run(&ctx, all_exec, outputs, args);
-}
-
-
-// ATOM DUMP RULE
-
-static int
-atom_dump_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
-{
- char *content = bm_atom_generate(ctx->settings);
- if (content == NULL)
- return 1;
- printf("%s", content);
- free(content);
- return 0;
-}
-
-
-const bm_rule_t rules[] = {
- {
- .name = "all",
- .help = "run all build rules",
- .outputlist_func = NULL,
- .exec_func = all_exec,
- },
- {
- .name = "index",
- .help = "build website index from posts",
- .outputlist_func = index_outputlist,
- .exec_func = index_exec,
- },
- {
- .name = "atom",
- .help = "build main atom feed from posts",
- .outputlist_func = atom_outputlist,
- .exec_func = atom_exec,
- },
- {
- .name = "atom_tags",
- .help = "build atom feeds for each tag from posts",
- .outputlist_func = atom_tags_outputlist,
- .exec_func = atom_tags_exec,
- },
- {
- .name = "pagination",
- .help = "build pagination pages from posts",
- .outputlist_func = pagination_outputlist,
- .exec_func = pagination_exec,
- },
- {
- .name = "pagination_tags",
- .help = "build pagination pages for each tag from posts",
- .outputlist_func = pagination_tags_outputlist,
- .exec_func = pagination_tags_exec,
- },
- {
- .name = "posts",
- .help = "build individual pages for each post",
- .outputlist_func = posts_outputlist,
- .exec_func = posts_exec,
- },
- {
- .name = "tags",
- .help = "build post listings for each tag from posts",
- .outputlist_func = tags_outputlist,
- .exec_func = tags_exec,
- },
- {
- .name = "pages",
- .help = "build individual pages for each page",
- .outputlist_func = pages_outputlist,
- .exec_func = pages_exec,
- },
- {
- .name = "copy",
- .help = "copy static files from source directory to output directory",
- .outputlist_func = copy_outputlist,
- .exec_func = copy_exec,
- },
- {
- .name = "clean",
- .help = "clean built files and empty directories in output directory",
- .outputlist_func = NULL,
- .exec_func = clean_exec,
- },
- {
- .name = "runserver",
- .help = "run blogc-runserver pointing to output directory, if available,\n"
- " rebuilding as needed\n"
- " arguments: host (127.0.0.1), port (8080) and threads (20)",
- .outputlist_func = NULL,
- .exec_func = runserver_exec,
- },
- {
- .name = "watch",
- .help = "watch for changes in the source files, rebuilding as needed",
- .outputlist_func = NULL,
- .exec_func = watch_exec,
- },
- {
- .name = "atom_dump",
- .help = "dump default Atom feed template based on current settings",
- .outputlist_func = NULL,
- .exec_func = atom_dump_exec,
- },
- {NULL, NULL, NULL, NULL},
-};
-
-
-// ALL RULE
-
-static int
-all_exec(bm_ctx_t *ctx, bc_slist_t *outputs, bc_trie_t *args)
-{
- for (size_t i = 0; rules[i].name != NULL; i++) {
- if (rules[i].outputlist_func == NULL) {
- continue;
- }
-
- int rv = bm_rule_execute(ctx, &(rules[i]), NULL);
- if (rv != 0) {
- return rv;
- }
- }
-
- return 0;
-}
-
-
-bc_trie_t*
-bm_rule_parse_args(const char *sep)
-{
- if (sep == NULL || *sep == '\0' || *sep != ':')
- return NULL;
-
- bc_trie_t *rv = bc_trie_new(free);
- char *end = (char*) sep + 1;
- char *kv_sep;
- while (NULL != (kv_sep = strchr(end, '='))) {
- char *key = bc_strndup(end, kv_sep - end);
- end = kv_sep + 1;
- kv_sep = strchr(end, ',');
- if (kv_sep == NULL)
- kv_sep = strchr(end, '\0');
- char *value = bc_strndup(end, kv_sep - end);
- bc_trie_insert(rv, key, value);
- free(key);
- if (*kv_sep == '\0')
- break;
- end = kv_sep + 1;
- }
- if (kv_sep == NULL) {
- bc_trie_free(rv);
- return NULL;
- }
-
- return rv;
-}
-
-
-int
-bm_rule_executor(bm_ctx_t *ctx, bc_slist_t *rule_list)
-{
- if (ctx == NULL)
- return 1;
-
- const bm_rule_t *rule = NULL;
- int rv = 0;
-
- for (bc_slist_t *l = rule_list; l != NULL; l = l->next) {
-
- char *rule_str = l->data;
- char *sep = strchr(rule_str, ':');
-
- bc_trie_t *args = NULL;
- if (sep == NULL) {
- sep = strchr(rule_str, '\0');
- }
- else {
- args = bm_rule_parse_args(sep);
- if (args == NULL) {
- fprintf(stderr, "blogc-make: warning: failed to parse rule "
- "arguments, ignoring: %s\n", rule_str);
- }
- }
-
- rule = NULL;
- for (size_t i = 0; rules[i].name != NULL; i++) {
- if (strlen(rules[i].name) != (sep - rule_str))
- continue;
- if (0 == strncmp(rule_str, rules[i].name, sep - rule_str)) {
- rule = &(rules[i]);
- rv = bm_rule_execute(ctx, rule, args);
- if (rv != 0)
- return rv;
- break;
- }
- }
- if (rule == NULL) {
- fprintf(stderr, "blogc-make: error: rule not found: %.*s\n",
- (int) (sep - rule_str), rule_str);
- rv = 1;
- }
- }
-
- return rv;
-}
-
-
-int
-bm_rule_execute(bm_ctx_t *ctx, const bm_rule_t *rule, bc_trie_t *args)
-{
- if (ctx == NULL || rule == NULL)
- return 1;
-
- bc_slist_t *outputs = NULL;
- if (rule->outputlist_func != NULL) {
- outputs = rule->outputlist_func(ctx);
- }
-
- int rv = rule->exec_func(ctx, outputs, args);
-
- bc_slist_free_full(outputs, (bc_free_func_t) bm_filectx_free);
-
- return rv;
-}
-
-
-bool
-bm_rule_need_rebuild(bc_slist_t *sources, bm_filectx_t *settings,
- bm_filectx_t *listing_entry, bm_filectx_t *template, bm_filectx_t *output,
- bool only_first_source)
-{
- if (output == NULL || !output->readable)
- return true;
-
- bool rv = false;
-
- bc_slist_t *s = NULL;
- if (settings != NULL)
- s = bc_slist_append(s, settings);
- if (template != NULL)
- s = bc_slist_append(s, template);
- if (listing_entry != NULL)
- s = bc_slist_append(s, listing_entry);
-
- for (bc_slist_t *l = sources; l != NULL; l = l->next) {
- s = bc_slist_append(s, l->data);
- if (only_first_source)
- break;
- }
-
- for (bc_slist_t *l = s; l != NULL; l = l->next) {
- bm_filectx_t *source = l->data;
- if (source == NULL || !source->readable) {
- // this is unlikely to happen, but lets just say that we need
- // a rebuild and let blogc bail out.
- rv = true;
- break;
- }
- if (source->tv_sec == output->tv_sec) {
- if (source->tv_nsec > output->tv_nsec) {
- rv = true;
- break;
- }
- }
- else if (source->tv_sec > output->tv_sec) {
- rv = true;
- break;
- }
- }
-
- bc_slist_free(s);
-
- return rv;
-}
-
-
-bc_slist_t*
-bm_rule_list_built_files(bm_ctx_t *ctx)
-{
- if (ctx == NULL)
- return NULL;
-
- bc_slist_t *rv = NULL;
- for (size_t i = 0; rules[i].name != NULL; i++) {
- if (rules[i].outputlist_func == NULL) {
- continue;
- }
-
- bc_slist_t *o = rules[i].outputlist_func(ctx);
- for (bc_slist_t *l = o; l != NULL; l = l->next) {
- rv = bc_slist_append(rv, l->data);
- }
- bc_slist_free(o);
- }
-
- return rv;
-}
-
-
-void
-bm_rule_print_help(void)
-{
- printf("\nhelper rules:\n");
- for (size_t i = 0; rules[i].name != NULL; i++) {
- if (rules[i].outputlist_func == NULL) {
- printf(" %-15s %s\n", rules[i].name, rules[i].help);
- }
- }
- printf("\nbuild rules:\n");
- for (size_t i = 0; rules[i].name != NULL; i++) {
- if (rules[i].outputlist_func != NULL) {
- printf(" %-15s %s\n", rules[i].name, rules[i].help);
- }
- }
-}
diff --git a/src/blogc-make/rules.h b/src/blogc-make/rules.h
deleted file mode 100644
index 9ff39ca..0000000
--- a/src/blogc-make/rules.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2020 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _MAKE_RULES_H
-#define _MAKE_RULES_H
-
-#include <stdbool.h>
-#include "ctx.h"
-#include "../common/utils.h"
-
-typedef bc_slist_t* (*bm_rule_outputlist_func_t) (bm_ctx_t *ctx);
-typedef int (*bm_rule_exec_func_t) (bm_ctx_t *ctx, bc_slist_t *outputs,
- bc_trie_t *args);
-
-typedef struct {
- const char *name;
- const char *help;
- bm_rule_outputlist_func_t outputlist_func;
- bm_rule_exec_func_t exec_func;
-} bm_rule_t;
-
-bc_trie_t* bm_rule_parse_args(const char *sep);
-int bm_rule_executor(bm_ctx_t *ctx, bc_slist_t *rule_list);
-int bm_rule_execute(bm_ctx_t *ctx, const bm_rule_t *rule, bc_trie_t *args);
-bool bm_rule_need_rebuild(bc_slist_t *sources, bm_filectx_t *settings,
- bm_filectx_t *listing_entry, bm_filectx_t *template, bm_filectx_t *output,
- bool only_first_source);
-bc_slist_t* bm_rule_list_built_files(bm_ctx_t *ctx);
-void bm_rule_print_help(void);
-
-#endif /* _MAKE_RULES_H */
diff --git a/src/blogc-make/settings.c b/src/blogc-make/settings.c
deleted file mode 100644
index 1079fc0..0000000
--- a/src/blogc-make/settings.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <libgen.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include "../common/config-parser.h"
-#include "../common/error.h"
-#include "../common/file.h"
-#include "../common/utils.h"
-#include "settings.h"
-
-
-static const struct default_settings_map {
- const char *key;
- const char *default_value;
-} default_settings[] = {
-
- // source
- {"content_dir", "content"},
- {"template_dir", "templates"},
- {"atom_template", NULL}, // default: atom.c
- {"main_template", "main.tmpl"},
- {"source_ext", ".txt"},
- {"listing_entry", NULL},
- {"posts_sort", NULL},
-
- // pagination
- {"pagination_prefix", "page"},
- {"posts_per_page", "10"},
- {"atom_posts_per_page", "10"},
-
- // html
- {"html_ext", "/index.html"},
- {"index_prefix", ""},
- {"post_prefix", "post"},
- {"tag_prefix", "tag"},
- {"html_order", "DESC"},
-
- // atom
- {"atom_prefix", "atom"},
- {"atom_ext", ".xml"},
- {"atom_order", "DESC"},
- {"atom_legacy_entry_id", NULL},
-
- // generic
- {"date_format", "%b %d, %Y, %I:%M %p GMT"},
- {"locale", NULL},
-
- {NULL, NULL},
-};
-
-
-static const char* required_global[] = {
- "AUTHOR_NAME",
- "AUTHOR_EMAIL",
- "SITE_TITLE",
- "SITE_TAGLINE",
- "BASE_DOMAIN",
- NULL,
-};
-
-
-static const char* list_sections[] = {
- "posts",
- "pages",
- "copy",
- "copy_files", // backward compatibility
- "tags",
- NULL,
-};
-
-
-bm_settings_t*
-bm_settings_parse(const char *content, size_t content_len, bc_error_t **err)
-{
- if (err == NULL || *err != NULL)
- return NULL;
-
- if (content == NULL)
- return NULL;
-
- bc_config_t *config = bc_config_parse(content, content_len, list_sections,
- err);
- if (config == NULL || (err != NULL && *err != NULL))
- return NULL;
-
- bm_settings_t *rv = bc_malloc(sizeof(bm_settings_t));
- rv->global = bc_trie_new(free);
- rv->settings = bc_trie_new(free);
- rv->posts = NULL;
- rv->pages = NULL;
- rv->copy = NULL;
- rv->tags = NULL;
-
- // this is some code for compatibility with the [environment] section,
- // even if I never released a version with it, but some people is using
- // it already.
- const char *section = NULL;
- char **global = bc_config_list_keys(config, "global");
- if (global != NULL) {
- section = "global";
- }
- else {
- global = bc_config_list_keys(config, "environment");
- if (global != NULL) {
- section = "environment";
- }
- else {
- section = "global";
- }
- }
-
- if (global != NULL) {
- for (size_t i = 0; global[i] != NULL; i++) {
- for (size_t j = 0; global[i][j] != '\0'; j++) {
- if (j == 0) {
- if (!(global[i][j] >= 'A' && global[i][j] <= 'Z')) {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_SETTINGS,
- "Invalid [%s] key (first character must be uppercase): %s",
- section, global[i]);
- bc_strv_free(global);
- bm_settings_free(rv);
- rv = NULL;
- goto cleanup;
- }
- continue;
- }
- if (!((global[i][j] >= 'A' && global[i][j] <= 'Z') ||
- (global[i][j] >= '0' && global[i][j] <= '9') ||
- global[i][j] == '_')) {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_SETTINGS,
- "Invalid [%s] key (must be uppercase with '_' and digits after first character): %s",
- section, global[i]);
- bc_strv_free(global);
- bm_settings_free(rv);
- rv = NULL;
- goto cleanup;
- }
- }
- bc_trie_insert(rv->global, global[i],
- bc_strdup(bc_config_get(config, section, global[i])));
- }
- }
- bc_strv_free(global);
-
- for (size_t i = 0; required_global[i] != NULL; i++) {
- const char *value = bc_trie_lookup(rv->global, required_global[i]);
- if (value == NULL || value[0] == '\0') {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_SETTINGS,
- "[%s] key required but not found or empty: %s", section,
- required_global[i]);
- bm_settings_free(rv);
- rv = NULL;
- goto cleanup;
- }
- }
-
- for (size_t i = 0; default_settings[i].key != NULL; i++) {
- const char *value = bc_config_get_with_default(
- config, "settings", default_settings[i].key,
- default_settings[i].default_value);
- if (value != NULL) {
- bc_trie_insert(rv->settings, default_settings[i].key,
- bc_strdup(value));
- }
- }
-
- rv->posts = bc_config_get_list(config, "posts");
- rv->pages = bc_config_get_list(config, "pages");
- rv->tags = bc_config_get_list(config, "tags");
-
- // this is for backward compatibility too.
- rv->copy = bc_config_get_list(config, "copy");
- if (rv->copy == NULL)
- rv->copy = bc_config_get_list(config, "copy_files");
-
-cleanup:
-
- bc_config_free(config);
-
- return rv;
-}
-
-
-void
-bm_settings_free(bm_settings_t *settings)
-{
- if (settings == NULL)
- return;
- bc_trie_free(settings->global);
- bc_trie_free(settings->settings);
- bc_strv_free(settings->posts);
- bc_strv_free(settings->pages);
- bc_strv_free(settings->copy);
- bc_strv_free(settings->tags);
- free(settings);
-}
diff --git a/src/blogc-make/settings.h b/src/blogc-make/settings.h
deleted file mode 100644
index 69fdbb6..0000000
--- a/src/blogc-make/settings.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _MAKE_SETTINGS_H
-#define _MAKE_SETTINGS_H
-
-#include <stddef.h>
-#include "../common/error.h"
-#include "../common/utils.h"
-
-typedef struct {
- bc_trie_t *global;
- bc_trie_t *settings;
- char **posts;
- char **pages;
- char **copy;
- char **tags;
-} bm_settings_t;
-
-bm_settings_t* bm_settings_parse(const char *content, size_t content_len,
- bc_error_t **err);
-void bm_settings_free(bm_settings_t *settings);
-
-#endif /* _MAKE_SETTINGS_H */
diff --git a/src/blogc-make/utils.c b/src/blogc-make/utils.c
deleted file mode 100644
index 8f69e44..0000000
--- a/src/blogc-make/utils.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#include <errno.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include "../common/error.h"
-#include "../common/utils.h"
-
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-
-char*
-bm_generate_filename(const char *dir, const char *prefix, const char *fname,
- const char *ext)
-{
- bool have_prefix = prefix != NULL && prefix[0] != '\0';
- bool have_fname = fname != NULL && fname[0] != '\0';
- bool have_ext = ext != NULL && ext[0] != '\0';
- bool have_ext_noslash = have_ext && ext[0] != '/';
- bool is_index = have_fname && have_ext && (
- (0 == strcmp(fname, "index")) && ext[0] == '/') && !have_prefix;
-
- bc_string_t *rv = bc_string_new();
-
- if (dir != NULL && (have_prefix || have_fname || have_ext))
- bc_string_append(rv, dir);
-
- if ((have_prefix || have_fname || have_ext_noslash) && !is_index)
- bc_string_append_c(rv, '/');
-
- if (have_prefix)
- bc_string_append(rv, prefix);
-
- // with fname we have posts, pages and tags
- if (have_fname) {
- if (have_prefix && have_fname && fname[0] != '/')
- bc_string_append_c(rv, '/');
- if (!is_index)
- bc_string_append(rv, fname);
- }
-
- // no fname means index
- else if (have_ext_noslash) {
- if (have_fname)
- bc_string_append_c(rv, '/');
- if (!have_prefix)
- bc_string_append(rv, "index");
- }
-
- if (have_ext)
- bc_string_append(rv, ext);
-
- if (rv->len == 0) {
- bc_string_free(rv, true);
- return NULL;
- }
-
- return bc_string_free(rv, false);
-}
-
-
-char*
-bm_generate_filename2(const char *dir, const char *prefix, const char *fname,
- const char *prefix2, const char *fname2, const char *ext)
-{
- bool have_prefix = prefix != NULL && prefix[0] != '\0';
- bool have_fname = fname != NULL && fname[0] != '\0';
- bool have_prefix2 = prefix2 != NULL && prefix2[0] != '\0';
-
- bc_string_t *p = bc_string_new();
-
- if (have_prefix)
- bc_string_append(p, prefix);
-
- if (have_prefix && (have_fname || have_prefix2))
- bc_string_append_c(p, '/');
-
- if (have_fname)
- bc_string_append(p, fname);
-
- if (have_fname && have_prefix2)
- bc_string_append_c(p, '/');
-
- if (have_prefix2)
- bc_string_append(p, prefix2);
-
- char *rv = bm_generate_filename(dir, p->str, fname2, ext);
- bc_string_free(p, true);
-
- return rv;
-}
-
-
-char*
-bm_abspath(const char *path, bc_error_t **err)
-{
- if (err == NULL || *err != NULL)
- return NULL;
-
- if (path[0] == '/') {
- return bc_strdup(path);
- }
-
- char cwd[PATH_MAX];
- if (NULL == getcwd(cwd, sizeof(cwd))) {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_UTILS,
- "Failed to detect absolute path (%s): %s", path, strerror(errno));
- return NULL;
- }
-
- if (cwd[0] != '/') {
- *err = bc_error_new_printf(BLOGC_MAKE_ERROR_UTILS,
- "Failed to get current working directory: %s", cwd);
- return NULL;
- }
-
- return bc_strdup_printf("%s/%s", cwd, path);
-}
diff --git a/src/blogc-make/utils.h b/src/blogc-make/utils.h
deleted file mode 100644
index cbcfc0e..0000000
--- a/src/blogc-make/utils.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * blogc: A blog compiler.
- * Copyright (C) 2014-2019 Rafael G. Martins <rafael@rafaelmartins.eng.br>
- *
- * This program can be distributed under the terms of the BSD License.
- * See the file LICENSE.
- */
-
-#ifndef _MAKE_UTILS_H
-#define _MAKE_UTILS_H
-
-#include "../common/error.h"
-
-char* bm_generate_filename(const char *dir, const char *prefix, const char *fname,
- const char *ext);
-char* bm_generate_filename2(const char *dir, const char *prefix, const char *fname,
- const char *prefix2, const char *fname2, const char *ext);
-char* bm_abspath(const char *path, bc_error_t **err);
-
-#endif /* _MAKE_UTILS_H */