diff --git a/theme.c b/theme.c new file mode 100644 index 0000000..eee1cdb --- /dev/null +++ b/theme.c @@ -0,0 +1,319 @@ +/* + * theme: use a template to create a webpage (markdown-style) + * + * usage: theme [-d root] [-t template] [-o html] [source] + * + */ +/* + * Copyright (C) 2007 David L Parsons. + * The redistribution terms are provided in the COPYRIGHT file that must + * be distributed with this source code. + */ +#include "config.h" + +#include +#include +#include +#if defined(HAVE_BASENAME) && defined(HAVE_LIBGEN_H) +# include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "mkdio.h" +#include "cstring.h" + +char *pgm = "theme"; +char *output = 0; +char *source = 0; +char *root = 0; + +#ifndef HAVE_BASENAME +char * +basename(char *path) +{ + char *p; + + if (( p = strrchr(path, '/') )) + return 1+p; + return path; +} +#endif + +void +fail(char *why, ...) +{ + va_list ptr; + + va_start(ptr,why); + fprintf(stderr, "%s: ", pgm); + vfprintf(stderr, why, ptr); + fputc('\n', stderr); + va_end(ptr); + exit(1); +} + + +/* open_template() -- start at the current directory and work up, + * looking for the deepest nested template. + * Stop looking when we reach $root or / + */ +FILE * +open_template(char *template) +{ + char *cwd; + int szcwd; + int here = open(".", O_RDONLY); + FILE *ret; + + if ( here == -1 ) + fail("cannot access the current directory"); + + szcwd = root ? 1 + strlen(root) : 2; + + cwd = alloca(szcwd); + + while ( !(ret = fopen(template, "r")) ) { + if ( getcwd(cwd, szcwd) == 0 ) { + if ( errno == ERANGE ) + goto up; + break; + } + + if ( root && (strcmp(root, cwd) == 0) ) + break; /* ran out of paths to search */ + else if ( (strcmp(cwd, "/") == 0) || (*cwd == 0) ) + break; /* reached / */ + + up: if ( chdir("..") == -1 ) + break; + } + fchdir(here); + close(here); + return ret; +} /* open_template */ + + +static STRING(int) pattern; +static int psp; + +static int +prepare(FILE *input) +{ + int c; + + CREATE(pattern); + psp = 0; + while ( (c = getc(input)) != EOF ) + EXPAND(pattern) = c; + fclose(input); + return 1; +} + +static int +pull() +{ + if ( psp < S(pattern) ) + return T(pattern)[psp++]; + return EOF; +} + +static int +peek(int offset) +{ + int pos = (psp + offset)-1; + + if ( pos >= 0 && pos < S(pattern) ) + return T(pattern)[pos]; + + return EOF; +} + +static int +shift(int shiftwidth) +{ + psp += shiftwidth; + return psp; +} + +static int* +cursor() +{ + return T(pattern) + psp; +} + + +static int +thesame(int *p, char *pat) +{ + int i; + + for ( i=0; pat[i]; i++ ) { + if ( pat[i] == ' ' ) { + if ( !isspace(peek(i+1)) ) { + return 0; + } + } + else if ( tolower(peek(i+1)) != pat[i] ) { + return 0; + } + } + return 1; +} + + +/* spin() - run through the theme template, looking for -- the document date (from header) + * -- the document title (from header) + * -- the document author (from header) + * -- the document body + */ +void +spin(FILE *template, MMIOT doc, FILE *output) +{ + int c; + int *p; + char *h; + + prepare(template); + + while ( (c = pull()) != EOF ) { + if ( c == '<' ) { + if ( peek(1) == '!' && peek(2) == '-' && peek(3) == '-' ) { + fputs("