dag

Djmoch's Auto Generator
git clone git://git.danielmoch.com/dag.git
Log | Files | Refs | README | LICENSE

commit 9495d3cbab984d8ba392ebf6a18faa3ea49afd6e
parent 168e2a09a5311c9f8a20d5a6a2f251cf931b50df
Author: Daniel Moch <daniel@danielmoch.com>
Date:   Fri,  1 Jan 2021 10:21:09 -0500

Proper dagging. Still no index generation.

Diffstat:
Mconfig.mk | 16+++++-----------
Mdag.c | 27++++++++-------------------
Adagfile.c | 221+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adagfile.h | 8++++++++
Dlowdown.c | 37-------------------------------------
Dm4.c | 26--------------------------
Dm4.h | 8--------
Mstring.c | 6++++++
Mstring.h | 1+
Mstring_test.c | 44++++++++++++++++++++++++++++++++++++++++++++
Dutil.h | 6------
11 files changed, 293 insertions(+), 107 deletions(-)

diff --git a/config.mk b/config.mk @@ -1,26 +1,20 @@ # See LICENSE file for copyright and license details -# Paths to helper tools -GROFF = \"/usr/local/bin/groff\" -LOWDOWN = \"/usr/local/bin/lowdown\" -M4 = \"/usr/bin/m4\" - -# Number of DEFINES to allow from the command line -MAX_DEFINES = 100 +LOWDOWN := /usr/local/bin/lowdown +SASSC := /usr/local/bin/sassc +M4 := /usr/bin/m4 PREFIX := /usr/local MANPATH := ${PREFIX}/share/man X11BASE := /usr/X11R6 -SRC = dag.c string.c m4.c lowdown.c +SRC = dag.c dagfile.c string.c DIST_SRC = ${SRC} Makefile README config.mk OBJ = ${SRC:.c=.o} INCS = LIBS = VERSION = 0.1.0dev0 -CPPFLAGS := -DVERSION=\"${VERSION}\" -DGROFF=${GROFF} \ - -DLOWDOWN=${LOWDOWN} -DM4=${M4} -DMAX_DEFINES=${MAX_DEFINES} +CPPFLAGS := -DVERSION=\"${VERSION}\" -DLOWDOWN=\"${LOWDOWN}\" -DSASSC=\"${SASSC}\" -DM4=\"${M4}\" CFLAGS := -std=c99 -pedantic-errors -Wall -Wextra -Werror -O1 -c ${INCS} -pipe -#CFLAGS := -std=c99 -pedantic-errors -Wall -Wextra -Werror -O0 -g -c ${INCS} -pipe LDFLAGS := ${LIBS} diff --git a/dag.c b/dag.c @@ -8,6 +8,7 @@ #include <fts.h> #include <unistd.h> +#include "dagfile.h" #include "string.h" static char *argv0; @@ -20,19 +21,19 @@ enum { }; void -usage(int e_val) +usage(int rv) { FILE *fp; - if (e_val) { + if (rv) { fp = stderr; } else { fp = stdout; } - fprintf(fp, "usage: %s [-hv] [-Dname=value ...] in ... out\n", argv0); - exit(e_val); + fprintf(fp, "usage: %s [-hv] in ... out\n", argv0); + exit(rv); } char * @@ -59,18 +60,12 @@ make_outpath(const char *out, const char *srcpath, char *src_argv[]) int main(int argc, char **argv) { - char ch, *header = NULL, *footer = NULL, *defines[MAX_DEFINES]; - char *out; - size_t num_defines = 0; + char ch, *out; argv0 = basename(argv[0]); FTSENT *entry = NULL; - while ((ch = getopt(argc, argv, "D:H:f:vh")) != -1) { + while ((ch = getopt(argc, argv, "vh")) != -1) { switch (ch) { - case 'D': - defines[num_defines] = optarg; - num_defines += 1; - break; case 'h': usage(ERR_NONE); break; @@ -107,9 +102,7 @@ main(int argc, char **argv) while ((entry = fts_read(src_tree)) != NULL) { if ((entry->fts_info & FTS_F) == FTS_F) { char *outpath = make_outpath(out, entry->fts_accpath, path_argv); - printf("%s: found file -- %s\n", - argv0, entry->fts_accpath); - printf("%s: creating file -- %s\n", argv0, outpath); + process_dagfile(entry->fts_accpath, outpath); free(outpath); } } @@ -119,8 +112,4 @@ main(int argc, char **argv) argv0, errno); exit(ERR_FTS); } - - /* find .md files */ - /* process if newer than corresponding html file in output */ - /* also need to process if any template file is newer */ } diff --git a/dagfile.c b/dagfile.c @@ -0,0 +1,221 @@ +/* See LICENSE file for copyright and license details */ +#include <libgen.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "string.h" + +#define HEADER "templates/header.html" +#define FOOTER "templates/footer.html" + +enum { + MD = 0, + SCSS, + HTML, + CSS, + PDF, + OTHER +}; + +char *ext[] = { ".md", ".scss", "/index.html", ".css", ".pdf" }; + +char *xfrm[] = { + NULL, + NULL, + "%s -Thtml %s >>%s", + "%s -t compressed %s %s", + "%s -Tms %s | /usr/local/bin/groff -ms -t -Tpdf >%s", + "cp %s %s" +}; + +static int +getft(const char *infile) +{ + int ft = OTHER; + + for (int i=0; i<OTHER; i++) { + if (strend(infile, ext[i])) { + ft = i; + break; + } + } + + return ft; +} + +static char* +getout(const char *orig, const int from, const int to) +{ + int plen = strlen(orig) + strlen(ext[to]) - strlen(ext[from]); + char *out = malloc(plen * sizeof(char)); + strcpy(out, orig); + strnswp(out, ext[from], ext[to], plen); + + return out; +} + +static char* +getcmd(int ft, const char *in, const char *out) +{ + char *ret, *cmd = xfrm[ft]; + int clen; + + switch (ft) { + case CSS: + clen = strlen(cmd) + strlen(in) + strlen(out) + strlen(SASSC) - 6; + break; + default: + clen = strlen(cmd) + strlen(in) + strlen(out) + strlen(LOWDOWN) - 6; + } + + ret = malloc(clen * sizeof(char)); + + switch (ft) { + case CSS: + sprintf(ret, cmd, SASSC, in, out); + break; + case HTML: + case PDF: + sprintf(ret, cmd, LOWDOWN, in, out); + break; + default: + sprintf(ret, cmd, in, out); + } + + return ret; +} + +static char* +gethdrcmd(const char * in, const char *out) +{ + char *ret, hdrpath[] = HEADER; + const char *slug = out + strlen("target"); /* TODO - don't assume target */ + int clen; + char cmd[] = "%s -DDESCRIPTION=\"$(%s -Xdescription -Tterm %s)\" -DPAGE_TITLE=\"$(%s -Xtitle -Tterm %s)\" -DSLUG=%s %s >%s"; + clen = strlen(cmd) + strlen(M4) + (2 * strlen(LOWDOWN)) + (2 * strlen(in)) + + (2 * strlen(out)) + strlen(hdrpath) - 16; + ret = malloc(clen); + sprintf(ret, cmd, M4, LOWDOWN, in, LOWDOWN, in, slug, hdrpath, out); + return ret; +} + +static char* +getftrcmd(const char *out) +{ + char *ret, ftrpath[] = FOOTER; + int clen; + char cmd[] = "cat <%s >>%s"; + clen = strlen(cmd) + strlen(ftrpath) + strlen(out) - 6; + ret = malloc(clen); + sprintf(ret, cmd, ftrpath, out); + return ret; +} + +void +dag_mkdir(const char *out) +{ + struct stat sb; + char fmt[] = "mkdir -p %s"; + int clen = strlen(fmt) + strlen(out) - 1; + char cmd[clen]; + /* TODO: handle case where out exists, but isn't a directory */ + if (stat(out, &sb) != 0 || !S_ISDIR(sb.st_mode)) { + sprintf(cmd, fmt, out); + printf("%s\n", cmd); + system(cmd); + } +} + +int +outdated(char *dest, int nsrc, ...) { + va_list ap; + struct stat d_sb, s_sb; + int rv = 1; + + if (stat(dest, &d_sb) != 0) { + return rv; + } + + va_start(ap, nsrc); + for (int i=0; i<nsrc; i++) { + stat(va_arg(ap, char *), &s_sb); + if (s_sb.st_mtim.tv_sec > d_sb.st_mtim.tv_sec) { + goto end; + } + else if ((s_sb.st_mtim.tv_sec == d_sb.st_mtim.tv_sec) + && (s_sb.st_mtim.tv_nsec > d_sb.st_mtim.tv_nsec)) { + goto end; + } + } + rv = 0; + +end: + va_end(ap); + return rv; +} + +int +process_dagfile(const char *infile, const char *outfile) +{ + char *out = NULL; + char *cmd = NULL; + + switch (getft(infile)) { + case MD: + out = getout(outfile, MD, HTML); + if (outdated(out, 3, HEADER, FOOTER, infile)) { + dag_mkdir(dirname(out)); + cmd = gethdrcmd(infile, out); + printf("%s\n", cmd); + system(cmd); + free(cmd); + cmd = getcmd(HTML, infile, out); + printf("%s\n", cmd); + system(cmd); + free(cmd); + cmd = getftrcmd(out); + printf("%s\n", cmd); + system(cmd); + free(out); + free(cmd); + } + + out = getout(outfile, MD, PDF); + if (outdated(out, 3, HEADER, FOOTER, infile)) { + dag_mkdir(dirname(out)); + cmd = getcmd(PDF, infile, out); + printf("%s\n", cmd); + system(cmd); + } + break; + case SCSS: + out = getout(outfile, SCSS, CSS); + if (outdated(out, 1, infile)) { + dag_mkdir(dirname(out)); + cmd = getcmd(CSS, infile, out); + printf("%s\n", cmd); + system(cmd); + } + break; + default: + out = malloc(strlen(outfile) * sizeof(char)); + strcpy(out, outfile); + if (outdated(out, 1, infile)) { + dag_mkdir(dirname(out)); + cmd = getcmd(OTHER, infile, outfile); + printf("%s\n", cmd); + system(cmd); + } + } + + free(out); + if (cmd != NULL) { + free(cmd); + } + + return 0; +} diff --git a/dagfile.h b/dagfile.h @@ -0,0 +1,8 @@ +/* See LICENSE file for copyright and license details */ + +#ifndef __DAGFILE_H +#define __DAGFILE_H + +int process_dagfile(char *infile, char *outfile); + +#endif diff --git a/lowdown.c b/lowdown.c @@ -1,37 +0,0 @@ -/* See LICENSE file for copyright and license details */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "util.h" - -static const char redir[] = " > "; - -char * -lowdown_html_cmd(const char *infile, const char *outfile) -{ - char *retval = malloc(strlen(LOWDOWN) + 1); - sprintf(retval, LOWDOWN); - - const char html[] = " -Thtml "; - - retval = realloc(retval, strlen(retval) + strlen(html) + - strlen(infile) + strlen(redir) + strlen(outfile)); - sprintf(retval, "%s %s > %s", retval, infile, outfile); - - return retval; -} - -char * -lowdown_pdf_cmd(const char *infile, const char *outfile) -{ - char *retval = malloc(strlen(LOWDOWN) + 1); - sprintf(retval, LOWDOWN); - - const char pdf[] = " -Tms | TROFF | - retval = realloc(retval, strlen(retval) + strlen(infile) + - strlen(redir) + strlen(outfile)); - sprintf(retval, "%s %s > %s", retval, infile, outfile); - - return retval; -} diff --git a/m4.c b/m4.c @@ -1,26 +0,0 @@ -/* See LICENSE file for copyright and license details */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -char * -make_m4_cmd(const char **defines, const int num_defines, - const char *infile, const char *outfile) -{ - char *retval = malloc(strlen(M4) + 1); - sprintf(retval, M4); - - for (int i=0; i<num_defines; i++) { - /* "-D" + defines[i] + " " + '\0' */ - int len = strlen(defines[i]) + 4; - - retval = realloc(retval, strlen(retval) + len); - sprintf(retval, "%s -D%s", retval, defines[i]); - } - - retval = realloc(retval, strlen(retval) + strlen(infile) + - strlen(" > ") + strlen(outfile)); - sprintf(retval, "%s %s > %s", retval, infile, outfile); - - return retval; -} diff --git a/m4.h b/m4.h @@ -1,8 +0,0 @@ -/* See LICENSE file for copyright and license details */ -#ifdef __m4_h -#define __m4_h - -char * make_m4_cmd(const char **defines, const int num_defines, - const char *infile, const char *outfile); - -#endif diff --git a/string.c b/string.c @@ -8,6 +8,12 @@ strbegin(const char *big, const char *little) return (strstr(big, little) == big); } +int +strend(const char *big, const char *little) +{ + return ((strstr(big, little)) == (big + strlen(big) - strlen(little))); +} + void strnswp(char *big, const char *old, const char *new, size_t max) { diff --git a/string.h b/string.h @@ -8,6 +8,7 @@ #define __DAG_STRING_H int strbegin(const char *big, const char *little); +int strend(const char *big, const char *little); char *strnswp(char *big, const char *old, const char *new, size_t max); /* assumes the last element of strarray is NULL */ diff --git a/string_test.c b/string_test.c @@ -99,6 +99,48 @@ test_strnswp6() return 0; } +int +test_strend1() +{ + char big[] = "thisandthat"; + char little[] = "that"; + int exp = 1, act; + if ((act = strend(big, little)) != exp) { + printf("test_strend1 failed:\n\texp: %d\n\tact: %d\n", exp, act); + return 1; + } + + return 0; +} + +int +test_strend2() +{ + char big[] = "thisandthat"; + char little[] = "this"; + int exp = 0, act; + if ((act = strend(big, little)) != exp) { + printf("test_strend2 failed:\n\texp: %d\n\tact: %d\n", exp, act); + return 1; + } + + return 0; +} + +int +test_strend3() +{ + char big[] = "thisandthat"; + char little[] = "foo"; + int exp = 0, act; + if ((act = strend(big, little)) != exp) { + printf("test_strend3 failed:\n\texp: %d\n\tact: %d\n", exp, act); + return 1; + } + + return 0; +} + int main() { int retval = test_strnswp1(); @@ -107,5 +149,7 @@ int main() retval |= test_strnswp4(); retval |= test_strnswp5(); retval |= test_strnswp6(); + retval |= test_strend1(); + retval |= test_strend2(); return retval; } diff --git a/util.h b/util.h @@ -1,6 +0,0 @@ -/* See LICENSE file for copyright and license details */ - -struct keyval { - char *key; - char *value; -};