Introduction
Introduction Statistics Contact Development Disclaimer Help
rework templates support - saait - the most boring static page generator
git clone git://git.codemadness.org/saait
Log
Files
Refs
README
LICENSE
---
commit 015bc6ccd23e3e1ac78b6373e26d648bff4d08e0
parent aac9d4d389441f56dd883b5eec1aea7672797e27
Author: Hiltjo Posthuma <[email protected]>
Date: Sat, 25 May 2019 20:33:33 +0200
rework templates support
templates are now iterated from the templates directory. It detects the
following prefixes:
"header." - header block
"item." - item block
"footer." - footer block
when a block is missing it is simply skipped (an empty file is not needed
anymore).
- This now allows adding/remove templates at run-time without having to specify…
templates in config.h and recompile.
- remove listing tcc as supported. It has limited POSIX support and does not
support the required opendir,readdir_r,closedir interfaces.
Diffstat:
M README | 2 +-
M config.h | 46 -----------------------------…
M saait.c | 117 ++++++++++++++++++++++++-----…
D templates/urllist.txt/footer.txt | 0
D templates/urllist.txt/header.txt | 0
5 files changed, 91 insertions(+), 74 deletions(-)
---
diff --git a/README b/README
@@ -8,7 +8,7 @@ Some parts are intentionally hardcoded, C knowledge is required.
Dependencies:
-------------
-- C compiler (C99), tested on gcc, clang, tcc.
+- C compiler (C99), tested on gcc, clang.
- libc
diff --git a/config.h b/config.h
@@ -16,49 +16,3 @@ struct template {
/* output FILE * (set at runtime) */
FILE *fp;
};
-
-static struct template templates[] = {
- /* special: will be applied per page */
- {
- .name = "page", .blocks = {
- { .name = "page/header.html" },
- { .name = "page/item.html" },
- { .name = "page/footer.html" }
- }
- },
- {
- .name = "atom.xml", .blocks = {
- { .name = "atom.xml/header.xml" },
- { .name = "atom.xml/item.xml" },
- { .name = "atom.xml/footer.xml" }
- }
- },
- {
- .name = "index.html", .blocks = {
- { .name = "index.html/header.html" },
- { .name = "index.html/item.html" },
- { .name = "index.html/footer.html" }
- }
- },
- {
- .name = "sitemap.xml", .blocks = {
- { .name = "sitemap.xml/header.xml" },
- { .name = "sitemap.xml/item.xml" },
- { .name = "sitemap.xml/footer.xml" }
- }
- },
- {
- .name = "urllist.txt", .blocks = {
- { .name = "urllist.txt/header.txt" },
- { .name = "urllist.txt/item.txt" },
- { .name = "urllist.txt/footer.txt" }
- }
- },
- {
- .name = "twtxt.txt", .blocks = {
- { .name = "twtxt.txt/header.txt" },
- { .name = "twtxt.txt/item.txt" },
- { .name = "twtxt.txt/footer.txt" }
- }
- }
-};
diff --git a/saait.c b/saait.c
@@ -1,7 +1,11 @@
+#include <sys/types.h>
+
#include <ctype.h>
+#include <dirent.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -371,12 +375,15 @@ usage(void)
int
main(int argc, char *argv[])
{
+ struct template *t, *templates = NULL;
struct block *b;
struct variable *c, *v;
- char file[PATH_MAX + 1], htmlfile[PATH_MAX + 1];
- char outputfile[PATH_MAX + 1], *p;
- size_t i, j, k;
- int r;
+ DIR *bdir, *idir;
+ struct dirent be, ie, *br, *ir;
+ char file[PATH_MAX + 1], htmlfile[PATH_MAX + 1], path[PATH_MAX + 1];
+ char outputfile[PATH_MAX + 1], *p, *filename;
+ size_t i, j, k, templateslen;
+ int r, doindex;
if (pledge("stdio cpath rpath wpath", NULL) == -1) {
fprintf(stderr, "pledge: %s\n", strerror(errno));
@@ -400,23 +407,69 @@ main(int argc, char *argv[])
/* global config */
global = readconfig(configfile);
- /* load templates: all templates must be loaded correctly first. */
- for (i = 0; i < LEN(templates); i++) {
- for (j = 0; j < LEN(templates[i].blocks); j++) {
- b = &templates[i].blocks[j];
- r = snprintf(file, sizeof(file), "%s/%s", templatedir,
- b->name);
+ /* load templates, must start with header., item. or footer. */
+ templateslen = 0;
+ if (!(bdir = opendir(templatedir))) {
+ fprintf(stderr, "opendir: %s: %s\n", templatedir, strerror(err…
+ exit(1);
+ }
+
+ while (!readdir_r(bdir, &be, &br) && br) {
+ if (br->d_name[0] == '.')
+ continue;
+
+ r = snprintf(path, sizeof(path), "%s/%s", templatedir,
+ br->d_name);
+ if (r < 0 || (size_t)r >= sizeof(path)) {
+ fprintf(stderr, "path truncated: '%s/%s'\n",
+ templatedir, br->d_name);
+ exit(1);
+ }
+
+ if (!(idir = opendir(path))) {
+ fprintf(stderr, "opendir: %s: %s\n", path, strerror(er…
+ exit(1);
+ }
+
+ templateslen++;
+ /* check overflow */
+ if (SIZE_MAX / templateslen < sizeof(*templates)) {
+ fprintf(stderr, "realloc: too many templates: %zu\n", …
+ exit(1);
+ }
+ templates = realloc(templates, templateslen * sizeof(*template…
+ t = &templates[templateslen - 1];
+ memset(t, 0, sizeof(struct template));
+ t->name = estrdup(br->d_name);
+
+ while (!readdir_r(idir, &ie, &ir) && ir) {
+ if (!strncmp(ir->d_name, "header.", sizeof("header.") …
+ b = &(t->blocks[BlockHeader]);
+ else if (!strncmp(ir->d_name, "item.", sizeof("item.")…
+ b = &(t->blocks[BlockItem]);
+ else if (!strncmp(ir->d_name, "footer.", sizeof("foote…
+ b = &(t->blocks[BlockFooter]);
+ else
+ continue;
+
+ r = snprintf(file, sizeof(file), "%s/%s", path,
+ ir->d_name);
if (r < 0 || (size_t)r >= sizeof(file)) {
fprintf(stderr, "path truncated: '%s/%s'\n",
- templatedir, b->name);
+ path, ir->d_name);
exit(1);
}
b->data = readfile(file);
+ b->name = estrdup(file);
}
+ closedir(idir);
}
+ closedir(bdir);
/* header */
- for (i = 0; i < LEN(templates); i++) {
+ for (i = 0; i < templateslen; i++) {
+ /* TODO: document special "page".
+ TODO: make "page" template mandatory? */
if (!strcmp(templates[i].name, "page"))
continue;
r = snprintf(file, sizeof(file), "%s/%s", outputdir,
@@ -428,13 +481,17 @@ main(int argc, char *argv[])
}
templates[i].fp = efopen(file, "wb");
b = &templates[i].blocks[BlockHeader];
- writepage(templates[i].fp, b->name, NULL, b->data);
+ if (b->name)
+ writepage(templates[i].fp, b->name, NULL, b->data);
}
/* pages */
for (i = 0; i < (size_t)argc; i++) {
c = readconfig(argv[i]);
+ v = getvar(c, "index");
+ doindex = !(v && v->value[0] == '0');
+
if ((p = strrchr(argv[i], '.')))
r = snprintf(htmlfile, sizeof(htmlfile), "%.*s.html",
(int)(p - argv[i]), argv[i]);
@@ -450,35 +507,40 @@ main(int argc, char *argv[])
/* set HTML output filename (with part removed), but allow to
override it */
if ((p = strrchr(htmlfile, '/')))
- setvar(&c, newvar("filename", &htmlfile[p - htmlfile +…
+ filename = &htmlfile[p - htmlfile + 1];
else
- setvar(&c, newvar("filename", htmlfile), 0);
+ filename = htmlfile;
- /* get output filename */
- v = getvar(c, "filename");
+ if ((v = getvar(c, "filename")))
+ filename = v->value;
+ else
+ setvar(&c, newvar("filename", filename), 0);
- /* item block */
- for (j = 0; j < LEN(templates); j++) {
+ /* item blocks */
+ for (j = 0; j < templateslen; j++) {
/* TODO: page is a special case for now */
if (!strcmp(templates[j].name, "page")) {
+ /* TODO: config option to not process as page …
r = snprintf(outputfile, sizeof(outputfile), "…
- outputdir, v->value);
+ outputdir, filename);
if (r < 0 || (size_t)r >= sizeof(outputfile)) {
fprintf(stderr, "path truncated: '%s/%…
- outputdir, v->value);
+ outputdir, filename);
exit(1);
}
+ /* "page" template files are opened per item
+ as opposed to other templates */
templates[j].fp = efopen(outputfile, "wb");
for (k = 0; k < LEN(templates[j].blocks); k++)…
b = &templates[j].blocks[k];
- writepage(templates[j].fp, b->name, c,…
+ if (b->name)
+ writepage(templates[j].fp, b->…
}
fclose(templates[j].fp);
} else {
- v = getvar(c, "index");
- if (v && v->value[0] == '0')
- continue;
+ if (!doindex)
+ continue; /* do not include in index */
b = &templates[j].blocks[BlockItem];
writepage(templates[j].fp, b->name, c, b->data…
}
@@ -486,11 +548,12 @@ main(int argc, char *argv[])
freevars(c);
}
- for (i = 0; i < LEN(templates); i++) {
+ for (i = 0; i < templateslen; i++) {
if (!strcmp(templates[i].name, "page"))
continue;
b = &templates[i].blocks[BlockFooter];
- writepage(templates[i].fp, b->name, NULL, b->data);
+ if (b->name)
+ writepage(templates[i].fp, b->name, NULL, b->data);
}
return 0;
diff --git a/templates/urllist.txt/footer.txt b/templates/urllist.txt/footer.txt
diff --git a/templates/urllist.txt/header.txt b/templates/urllist.txt/header.txt
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.