diff options
Diffstat (limited to 'src/blogc-make/rules.c')
-rw-r--r-- | src/blogc-make/rules.c | 1078 |
1 files changed, 0 insertions, 1078 deletions
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); - } - } -} |