add optimized catfile: %{somevar} - saait - the most boring static page generator
 (HTM) git clone git://git.codemadness.org/saait
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 02992aebcd4d0498ec6c49309c4499e2e420f21b
 (DIR) parent 97a7e89e3e3204a474abe40c86645672c5edaccf
 (HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       Date:   Sun, 21 Jan 2018 16:15:30 +0100
       
       add optimized catfile: %{somevar}
       
       this reads and appends the contents of the value in variable 'somevar'
       
       Diffstat:
         M saait.c                             |      55 ++++++++++++++++++++++++++-----
       
       1 file changed, 47 insertions(+), 8 deletions(-)
       ---
 (DIR) diff --git a/saait.c b/saait.c
       @@ -8,6 +8,7 @@
        #include <unistd.h>
        #endif
        
       +#define READ_BUF_SIZ 16384
        #define LEN(s)     (sizeof(s)/sizeof(*s))
        
        struct variable {
       @@ -79,6 +80,32 @@ efopen(const char *path, const char *mode)
                return fp;
        }
        
       +void
       +catfile(FILE *fpin, const char *ifile, FILE *fpout, const char *ofile)
       +{
       +        char buf[READ_BUF_SIZ];
       +        size_t r, w;
       +
       +        while (!feof(fpin)) {
       +                if (!(r = fread(buf, 1, sizeof(buf), fpin)))
       +                        break;
       +                if ((w = fwrite(buf, 1, r, fpout)) != r)
       +                        break;
       +                if (r != sizeof(buf))
       +                        break;
       +        }
       +        if (ferror(fpin)) {
       +                fprintf(stderr, "%s -> %s: error reading data from stream: %s\n",
       +                        ifile, ofile, strerror(errno));
       +                exit(1);
       +        }
       +        if (ferror(fpout)) {
       +                fprintf(stderr, "%s -> %s: error writing data to stream: %s\n",
       +                        ifile, ofile, strerror(errno));
       +                exit(1);
       +        }
       +}
       +
        char *
        readfile(const char *file)
        {
       @@ -89,18 +116,20 @@ readfile(const char *file)
                fp = efopen(file, "rb");
                buf = ecalloc(1, size + 1); /* always allocate an empty buffer */
                while (!feof(fp)) {
       -                if (len + BUFSIZ + 1 > size) {
       +                if (len + READ_BUF_SIZ + 1 > size) {
                                /* allocate size: common case is small textfiles */
       -                        size += (BUFSIZ * 10);
       +                        size += READ_BUF_SIZ;
                                if (!(buf = realloc(buf, size + 1))) {
                                        fprintf(stderr, "realloc: %s\n", strerror(errno));
                                        exit(1);
                                }
                        }
       -                if (!(n = fread(&buf[len], 1, BUFSIZ, fp)))
       +                if (!(n = fread(&buf[len], 1, READ_BUF_SIZ, fp)))
                                break;
                        len += n;
                        buf[len] = '\0';
       +                if (n != READ_BUF_SIZ)
       +                        break;
                }
                if (ferror(fp)) {
                        fprintf(stderr, "fread: file: %s: %s\n", file, strerror(errno));
       @@ -249,6 +278,7 @@ readconfig(const char *file)
        void
        writepage(FILE *fp, const char *filename, struct variable *c, char *s)
        {
       +        FILE *fpin;
                struct variable *v;
                char *key;
                size_t keylen, line = 0;
       @@ -257,6 +287,7 @@ writepage(FILE *fp, const char *filename, struct variable *c, char *s)
                for (; *s; s++) {
                        op = *s;
                        switch (*s) {
       +                case '%': /* insert contents of filename set in variable */
                        case '#': /* insert value non-escaped */
                        case '$': /* insert value escaped */
                                if (*(s + 1) == '{') {
       @@ -291,12 +322,19 @@ writepage(FILE *fp, const char *filename, struct variable *c, char *s)
                        key[keylen] = tmpc; /* restore NUL terminator to original */
        
                        if (!v) {
       -                        fprintf(stderr, "%s:%zu: unknown variable: '%.*s'\n",
       +                        fprintf(stderr, "%s:%zu: error: undefined variable: '%.*s'\n",
                                        filename, line + 1, (int)keylen, key);
                                exit(1);
                        }
        
                        switch (op) {
       +                case '%':
       +                        if (!v->value[0])
       +                                break;
       +                        fpin = efopen(v->value, "rb");
       +                        catfile(fpin, v->value, fp, filename);
       +                        fclose(fpin);
       +                        break;
                        case '$':
                                xmlencode(v->value, fp);
                                break;
       @@ -320,7 +358,8 @@ main(int argc, char *argv[])
                struct block *b;
                struct variable *c, *v;
                char file[PATH_MAX + 1], htmlfile[PATH_MAX + 1], outputfile[PATH_MAX + 1], *p;
       -        int i, j, k, r;
       +        size_t i, j, k;
       +        int r;
        
                if (pledge("stdio cpath rpath wpath", NULL) == -1) {
                        fprintf(stderr, "pledge: %s\n", strerror(errno));
       @@ -350,7 +389,7 @@ main(int argc, char *argv[])
                                b = &templates[i].blocks[j];
                                r = snprintf(file, sizeof(file), "%s/%s", templatedir,
                                             b->name);
       -                        if (r < 0 || (size_t) r >= sizeof(file)) {
       +                        if (r < 0 || (size_t)r >= sizeof(file)) {
                                        fprintf(stderr, "path truncated: '%s/%s'\n",
                                                templatedir, b->name);
                                        exit(1);
       @@ -365,7 +404,7 @@ main(int argc, char *argv[])
                                continue;
                        r = snprintf(file, sizeof(file), "%s/%s", outputdir,
                                     templates[i].name);
       -                if (r < 0 || (size_t) r >= sizeof(file)) {
       +                if (r < 0 || (size_t)r >= sizeof(file)) {
                                fprintf(stderr, "path truncated: '%s/%s'\n", outputdir,
                                        templates[i].name);
                                exit(1);
       @@ -376,7 +415,7 @@ main(int argc, char *argv[])
                }
        
                /* pages */
       -        for (i = 0; i < argc; i++) {
       +        for (i = 0; i < (size_t)argc; i++) {
                        c = readconfig(argv[i]);
        
                        if ((p = strrchr(argv[i], '.')))