Fixed a lot.

This commit is contained in:
Neil Edelman 2017-03-26 04:47:35 -04:00
parent 2b2daae97a
commit 7613e60e86
11 changed files with 640 additions and 190 deletions

View File

@ -1,37 +0,0 @@
# Windows port cross-compiling with MacOSX MinGW 4.3.0
# (good luck)
PROJ := MakeIndex
VA := 0
VB := 8
FILES := Recursor Parser Widget Files
BDIR := win
BACK := backup
EXE := $(PROJ).exe
INST := $(PROJ)-$(VA)_$(VB)
OBJS := $(patsubst %,$(BDIR)/%.o,$(FILES))
SRCS := $(patsubst %,%.c,$(FILES))
H := $(patsubst %,%.h,$(FILES))
CC := /usr/local/i386-mingw32-4.3.0/bin/i386-mingw32-gcc
CF := -Wall -O3 -fasm -fomit-frame-pointer -ffast-math -funroll-loops -pedantic -ansi
default: $(BDIR)/$(EXE)
$(BDIR)/$(EXE): $(OBJS)
$(CC) $(CF) -o $@ $^
$(BDIR)/%.o: %.c
@mkdir -p $(BDIR)
$(CC) $(CF) -c $? -o $@
.PHONY: clean backup
clean:
-rm $(OBJS)
setup: $(BDIR)/$(EXE)
@mkdir -p $(INST)
cp $(BDIR)/$(EXE) readme.txt gpl.txt copying.txt $(INST)
cp -a bin/example $(INST)
zip $(BDIR)/$(INST)-Win32-`date +%Y-%m-%dT%H%M%S` $(INST)/$(EXE) -r $(INST)
rm -R $(INST)

View File

@ -41,22 +41,22 @@
<p> <p>
Copyright 2008, 2012 Neil Edelman, distributed under the terms of the Copyright 2008, 2012 Neil Edelman, distributed under the terms of the
GNU General Public License, see copying.txt, or GNU General Public License, see copying.txt, or
<a href = "https://opensource.org/licenses/GPL-3.0">https://opensource.org/licenses/GPL-3.0</a>. <a href = "https://opensource.org/licenses/GPL-3.0">https://opensource.org/licenses/GPL-3.0</a>.
</p> </p>
<p> <p>
Files is a list of File (private class defiend below,) the Files can have Files is a list of File (private class defiend below,) the Files can have
a relation to other Files by 'parent' and 'favourite' (@(pwd) uses this.) a relation to other Files by 'parent' and 'favourite' (@(pwd) uses this.)
</p> </p>
<dl> <dl>
<dt>author:</dt> <dt>minimum standard</dt>
<dd>C89/90</dd>
<dt>author</dt>
<dd>Neil</dd> <dd>Neil</dd>
<dt>version:</dt> <dt>version</dt>
<dd>0.9; 2017-03 fixed pedantic warnings</dd> <dd>1.1; 2017-03 fixed pedantic warnings; took out arg</dd>
<dt>since:</dt> <dt>since</dt>
<dd>0.8; 2013-07 case-insensitive sort <dd>0.6; 2008-03-24</dd>
0.7; 2012 sth.dsth.d handled properly
0.6; 2008-03-24</dd>
</dl> </dl>
@ -200,12 +200,8 @@ After FilesSetFarourite, this enumerates them.
<div><a name = "FilesName"><!-- --></a> <div><a name = "FilesName"><!-- --></a>
<h3>FilesName</h3> <h3>FilesName</h3>
<pre>char * <b>FilesName</b> (const struct Files *files)</pre> <pre>char * <b>FilesName</b> (const struct Files *files)</pre>
<p>
</p>
<p>
</p>
<dl> <dl>
<dt>return:</dt> <dt>return</dt>
<dd>The file name of the selected file.</dd> <dd>The file name of the selected file.</dd>
</dl> </dl>
</div> </div>
@ -213,12 +209,8 @@ After FilesSetFarourite, this enumerates them.
<div><a name = "FilesSize"><!-- --></a> <div><a name = "FilesSize"><!-- --></a>
<h3>FilesSize</h3> <h3>FilesSize</h3>
<pre>int <b>FilesSize</b> (const struct Files *files)</pre> <pre>int <b>FilesSize</b> (const struct Files *files)</pre>
<p>
</p>
<p>
</p>
<dl> <dl>
<dt>return:</dt> <dt>return</dt>
<dd>File size of the selected file.</dd> <dd>File size of the selected file.</dd>
</dl> </dl>
</div> </div>
@ -226,12 +218,8 @@ After FilesSetFarourite, this enumerates them.
<div><a name = "FilesIsDir"><!-- --></a> <div><a name = "FilesIsDir"><!-- --></a>
<h3>FilesIsDir</h3> <h3>FilesIsDir</h3>
<pre>int <b>FilesIsDir</b> (const struct Files *files)</pre> <pre>int <b>FilesIsDir</b> (const struct Files *files)</pre>
<p>
</p>
<p>
</p>
<dl> <dl>
<dt>return:</dt> <dt>return</dt>
<dd>Whether the file is a directory.</dd> <dd>Whether the file is a directory.</dd>
</dl> </dl>
</div> </div>

View File

@ -45,31 +45,90 @@
<a name = "_declarations"><!-- --></a><h2>Declarations</h2> <a name = "_declarations"><!-- --></a><h2>Declarations</h2>
<div><a name = "struct Parser"><!-- --></a>
<h3>struct Parser</h3>
<pre><b>struct Parser</b></pre>
<p>
See <a href = "#Parser">Parser</a>.
</p>
<dl>
</dl>
</div>
<div><a name = "struct Files"><!-- --></a>
<h3>struct Files</h3>
<pre><b>struct Files</b></pre>
<p>
Dependancy on <em>Files</em>
</p>
<dl>
</dl>
</div>
<div><a name = "typedef int (*ParserWidget)(const struct Files *, FILE *fp)"><!-- --></a>
<h3>typedef int (*ParserWidget)(const struct Files *, FILE *fp)</h3>
<pre><b>typedef int (*ParserWidget)(const struct Files *, FILE *fp)</b></pre>
<p>
All <em>ParserWidget</em>s are in <em>Widget.c</em>
</p>
<dl>
</dl>
</div>
<a name = "_summary"><!-- --></a><h2>Function Summary</h2> <a name = "_summary"><!-- --></a><h2>Function Summary</h2>
<table> <table>
<tr><th>Return Type</th><th>Function Name</th><th>Argument List</th></tr> <tr><th>Return Type</th><th>Function Name</th><th>Argument List</th></tr>
<tr> <tr>
<td>const struct Symbol *</td> <td>struct Parser *</td>
<td><a href = "#match">match</a></td> <td><a href = "#Parser">Parser</a></td>
<td>const char *str, const char *end</td> <td>const char *str</td>
</tr>
<tr>
<td>void</td>
<td><a href = "#Parser_">Parser_</a></td>
<td>struct Parser **const p_ptr</td>
</tr>
<tr>
<td>void</td>
<td><a href = "#ParserRewind">ParserRewind</a></td>
<td>struct Parser *p</td>
</tr> </tr>
<tr> <tr>
<td>int</td> <td>int</td>
<td><a href = "#ParserParse">ParserParse</a></td> <td><a href = "#ParserParse">ParserParse</a></td>
<td>struct Parser *p, const struct Files *f, int invisible, FILE *fp</td> <td>struct Parser *p, const struct Files *f, int invisible,
FILE *fp</td>
</tr> </tr>
</table> </table>
<a name = "_detail"><!-- --></a><h2>Function Detail</h2> <a name = "_detail"><!-- --></a><h2>Function Detail</h2>
<div><a name = "match"><!-- --></a> <div><a name = "Parser"><!-- --></a>
<h3>match</h3> <h3>Parser</h3>
<pre>const struct Symbol * <b>match</b> (const char *str, const char *end)</pre> <pre>struct Parser * <b>Parser</b> (const char *str)</pre>
<dl>
<dt>return</dt>
<dd>Creates a parser for the string, <em>str</em>.</dd>
</dl>
</div>
<div><a name = "Parser_"><!-- --></a>
<h3>Parser_</h3>
<pre>void <b>Parser_</b> (struct Parser **const p_ptr)</pre>
<dl>
<dt>parameter: p_ptr</dt>
<dd>A pointer to the <em>Parser</em> that's to be destucted.</dd>
</dl>
</div>
<div><a name = "ParserRewind"><!-- --></a>
<h3>ParserRewind</h3>
<pre>void <b>ParserRewind</b> (struct Parser *p)</pre>
<p> <p>
binary search Resets the parser, <em>p</em>.
</p> </p>
<dl> <dl>
</dl> </dl>
@ -77,11 +136,22 @@ binary search
<div><a name = "ParserParse"><!-- --></a> <div><a name = "ParserParse"><!-- --></a>
<h3>ParserParse</h3> <h3>ParserParse</h3>
<pre>int <b>ParserParse</b> (struct Parser *p, const struct Files *f, int invisible, FILE *fp)</pre> <pre>int <b>ParserParse</b> (struct Parser *p, const struct Files *f, int invisible,
FILE *fp)</pre>
<p> <p>
parse, called recusively (invisible, hack) fixme: this fn needs rewriting, messy Parse, called recursively.
</p> </p>
<dl> <dl>
<dt>parameter: f</dt>
<dd>Called in the handler to <em>ParserWidget</em>s.</dd>
<dt>parameter: invisible</dt>
<dd>No output.</dd>
<dt>parameter: fp</dt>
<dd>Output.</dd>
<dt>fixme</dt>
<dd>This fn needs rewriting; messy.</dd>
<dt>fixme</dt>
<dd>Invisible, hack.</dd>
</dl> </dl>
</div> </div>

View File

@ -25,13 +25,13 @@
padding: 4px; padding: 4px;
} }
</style> </style>
<title></title> <title>Parser</title>
</head> </head>
<body> <body>
<h1></h1> <h1>Parser</h1>
<ul> <ul>
<li><a href = "#_declarations">Declarations</a></li> <li><a href = "#_declarations">Declarations</a></li>
@ -41,18 +41,85 @@
<p> <p>
Copyright 2008, 2012 Neil Edelman, distributed under the terms of the Copyright 2008, 2012 Neil Edelman, distributed under the terms of the
GNU General Public License, see copying.txt GNU General Public License, see copying.txt
</p> </p>
<p> <p>
This is the main program. I didn't know what to call it. <em>MakeIndex</em> is a simple content management system that generates static
content, (mostly index.html,) on all the directories rooted at the directory
specified by the argument. It is based on a template file, ".index.html" and
".newsfeed.rss". Also included are files to summarise the directory structure
for a <em>xml</em> site map, compatible with Google, and any <em>.news</em> for an <em>rss</em>
feed. It takes one argument, &lt;directory&gt;, which is the root of the recursion.
</p>
<p>
There should be an &lt;example&gt; directory that has a bunch of files in it. Run
<em>bin/MakeIndex example/</em>; it should make a webpage out of the directory
structure and <em>.index.html</em>, open <em>example/index.html</em> after running to see.
</p>
<ul>
<li>
If the <em>.index.html</em> file exists in the &lt;directory&gt;, prints &lt;index.html&gt;
recursively; overwrites any <em>index.html</em> on all the directories rooted at
&lt;directory&gt;;
</li>
<li>
if the <em>.sitemap.xml</em> file exists in &lt;directory&gt;, prints (and overwrites) an
index called <em>sitemap.xml</em>;
</li>
<li>
if the <em>.newsfeed.rss</em> file exists in &lt;directory&gt;, prints (and overwrites)
to <em>newsfeed.rss</em> all the <em>.news</em> files (if there are any.)
</li>
</ul>
<ul>
<li>
Treats <em>.d</em> as a description of the file without the <em>.d</em>;
if this is an empty text-file or a zero-byte file, it skips over this file.
</li>
<li>
treats <em>index.d</em> as a description of the directory;
</li>
<li>
treats <em>content.d</em> as an in-depth description of the directory,
replacing &lt;index.d&gt; when in the directory;
</li>
<li>
treats <em>.d.jpg</em> as a image that will go with the description;
</li>
<li>
treats <em>.news</em> as a newsworthy item; the format of this file is ISO 8601
date (YYYY-MM-DD,) next line title;
</li>
<li>
treats <em>.link</em> as a link with the href in the file.
</li>
</ul>
<p>
<em>.index.html</em>, <em>.sitemap.xml</em>, <em>.newsfeed.rss</em>, see <em>Parser</em> for recognised
symbols. Assumes '..' is the parent directory, '.' is the current directory,
and '/' is the directory separator; works for UNIX, MacOS, Windows.
If this is not the case, the constants are in <em>Files.c</em>.
</p> </p>
<dl> <dl>
<dt>author:</dt> <dt>minimum standard</dt>
<dd>C89/90</dd>
<dt>author</dt>
<dd>Neil</dd> <dd>Neil</dd>
<dt>version:</dt> <dt>version</dt>
<dd>1.0; 2016-09-19 Added umask</dd> <dd>1.1; 2017-03 fixed pedantic warnings; took out arg</dd>
<dt>since:</dt> <dt>since</dt>
<dd>1.0; 2008-03-27</dd> <dd>1.0; 2016-09-19 Added umask
0.8; 2013-07 case-insensitive sort
0.7; 2012 sth.dsth.d handled properly
0.6; 2008-03-27</dd>
<dt>fixme</dt>
<dd>Don't have &lt;directory&gt; be an argument; just do it in the current.</dd>
<dt>fixme</dt>
<dd>Have a subset of LaTeX converted into html for the .d files?</dd>
<dt>fixme</dt>
<dd>Encoding is an issue; especially the newsfeed, 7bit.</dd>
<dt>fixme</dt>
<dd>It's not robust; eg @(files)<em>@(files){Don't do this.}</em>.</dd>
</dl> </dl>

View File

@ -50,11 +50,221 @@
<table> <table>
<tr><th>Return Type</th><th>Function Name</th><th>Argument List</th></tr> <tr><th>Return Type</th><th>Function Name</th><th>Argument List</th></tr>
<tr>
<td>int</td>
<td><a href = "#WidgetContent">WidgetContent</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
<tr>
<td>int</td>
<td><a href = "#WidgetDate">WidgetDate</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
<tr>
<td>int</td>
<td><a href = "#WidgetFilealt">WidgetFilealt</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
<tr>
<td>int</td>
<td><a href = "#WidgetFiledesc">WidgetFiledesc</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
<tr>
<td>int</td>
<td><a href = "#WidgetFilehref">WidgetFilehref</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
<tr>
<td>int</td>
<td><a href = "#WidgetFileicon">WidgetFileicon</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
<tr>
<td>int</td>
<td><a href = "#WidgetFilename">WidgetFilename</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
<tr>
<td>int</td>
<td><a href = "#WidgetFiles">WidgetFiles</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
<tr>
<td>int</td>
<td><a href = "#WidgetFilesize">WidgetFilesize</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
<tr>
<td>int</td>
<td><a href = "#WidgetNews">WidgetNews</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
<tr>
<td>int</td>
<td><a href = "#WidgetNewsname">WidgetNewsname</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
<tr>
<td>int</td>
<td><a href = "#WidgetNow">WidgetNow</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
<tr>
<td>int</td>
<td><a href = "#WidgetPwd">WidgetPwd</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
<tr>
<td>int</td>
<td><a href = "#WidgetRoot">WidgetRoot</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
<tr>
<td>int</td>
<td><a href = "#WidgetTitle">WidgetTitle</a></td>
<td>const struct Files *f, FILE *fp</td>
</tr>
</table> </table>
<a name = "_detail"><!-- --></a><h2>Function Detail</h2> <a name = "_detail"><!-- --></a><h2>Function Detail</h2>
<div><a name = "WidgetContent"><!-- --></a>
<h3>WidgetContent</h3>
<pre>int <b>WidgetContent</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
<div><a name = "WidgetDate"><!-- --></a>
<h3>WidgetDate</h3>
<pre>int <b>WidgetDate</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
<div><a name = "WidgetFilealt"><!-- --></a>
<h3>WidgetFilealt</h3>
<pre>int <b>WidgetFilealt</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
<div><a name = "WidgetFiledesc"><!-- --></a>
<h3>WidgetFiledesc</h3>
<pre>int <b>WidgetFiledesc</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
<div><a name = "WidgetFilehref"><!-- --></a>
<h3>WidgetFilehref</h3>
<pre>int <b>WidgetFilehref</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
<div><a name = "WidgetFileicon"><!-- --></a>
<h3>WidgetFileicon</h3>
<pre>int <b>WidgetFileicon</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
<div><a name = "WidgetFilename"><!-- --></a>
<h3>WidgetFilename</h3>
<pre>int <b>WidgetFilename</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
<div><a name = "WidgetFiles"><!-- --></a>
<h3>WidgetFiles</h3>
<pre>int <b>WidgetFiles</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
<div><a name = "WidgetFilesize"><!-- --></a>
<h3>WidgetFilesize</h3>
<pre>int <b>WidgetFilesize</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
<div><a name = "WidgetNews"><!-- --></a>
<h3>WidgetNews</h3>
<pre>int <b>WidgetNews</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
<div><a name = "WidgetNewsname"><!-- --></a>
<h3>WidgetNewsname</h3>
<pre>int <b>WidgetNewsname</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
<div><a name = "WidgetNow"><!-- --></a>
<h3>WidgetNow</h3>
<pre>int <b>WidgetNow</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
<div><a name = "WidgetPwd"><!-- --></a>
<h3>WidgetPwd</h3>
<pre>int <b>WidgetPwd</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
<div><a name = "WidgetRoot"><!-- --></a>
<h3>WidgetRoot</h3>
<pre>int <b>WidgetRoot</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
<div><a name = "WidgetTitle"><!-- --></a>
<h3>WidgetTitle</h3>
<pre>int <b>WidgetTitle</b> (const struct Files *f, FILE *fp)</pre>
<dl>
<dt>implements</dt>
<dd>ParserWidget</dd>
</dl>
</div>
</body> </body>
</html> </html>

View File

@ -5,12 +5,11 @@
Files is a list of File (private class defiend below,) the Files can have Files is a list of File (private class defiend below,) the Files can have
a relation to other Files by 'parent' and 'favourite' (@(pwd) uses this.) a relation to other Files by 'parent' and 'favourite' (@(pwd) uses this.)
@file Files @title Files
@author Neil @author Neil
@version 0.9; 2017-03 fixed pedantic warnings @std C89/90
@since 0.8; 2013-07 case-insensitive sort @version 1.1; 2017-03 fixed pedantic warnings; took out arg
0.7; 2012 sth.dsth.d handled properly @since 0.6; 2008-03-24 */
0.6; 2008-03-24 */
#include <stdlib.h> /* malloc free */ #include <stdlib.h> /* malloc free */
#include <stdio.h> /* fprintf */ #include <stdio.h> /* fprintf */
@ -20,9 +19,9 @@
#include "Files.h" #include "Files.h"
/* constants */ /* constants */
const char *dirCurrent = "."; /* used in multiple files */ const char *dirCurrent = "."; /* used in multiple files */
const char *dirParent = ".."; const char *dirParent = "..";
static const int maxFilename = 128; static const size_t maxFilename = 128;
/* public */ /* public */
struct Files { struct Files {
@ -161,10 +160,10 @@ int FilesIsDir(const struct Files *files) {
/* this is just a list of filenames, (not public) "class File" */ /* this is just a list of filenames, (not public) "class File" */
static struct File *File(const char *name, const int size, const int isDir) { static struct File *File(const char *name, const int size, const int isDir) {
int len; size_t len;
struct File *file; struct File *file;
if(!name || !*name) { fprintf(stderr, "File: file has no name.\n"); return 0; } if(!name || !*name) { fprintf(stderr, "File: file has no name.\n"); return 0; }
if((len = strlen(name)) > maxFilename) { fprintf(stderr, "File: file name \"%s\" is too long (%d.)\n", name, maxFilename); return 0; } if((len = strlen(name)) > maxFilename) { fprintf(stderr, "File: file name \"%s\" is too long (%lu.)\n", name, maxFilename); return 0; }
file = malloc(sizeof(struct File) + (len + 1)); file = malloc(sizeof(struct File) + (len + 1));
if(!file) { File_(file); return 0; } if(!file) { File_(file); return 0; }
file->next = 0; file->next = 0;

View File

@ -1,6 +1,5 @@
/** See \see{Files}. */ /** See \see{Files}. */
struct Files; struct Files;
struct Recursor;
/** Returns a boolean value. */ /** Returns a boolean value. */
typedef int (*FilesFilter)(const struct Files *, const char *); typedef int (*FilesFilter)(const struct Files *, const char *);

View File

@ -1,8 +1,43 @@
/* Copyright 2008, 2012 Neil Edelman, distributed under the terms of the /* Copyright 2008, 2012 Neil Edelman, distributed under the terms of the
GNU General Public License, see copying.txt */ GNU General Public License, see copying.txt
/* Parsing of strings. Parsing of strings. '~' on a line by itself is recognised in ".newsfile.rss"
* Created by Neil Edelman on 2008-03-21. */ and ".sitemap.xml" as a <head>~<body>~<tail>; there should be two of them.
Parsed in ".index.html",
* @(content) prints {content.d}, or, if it is missing, {index.d};
* @(files){} repeats for all the files in the directory the contents of the
argument;
* @(htmlcontent);
* @(pwd){} prints the directory, the argument is the separator; eg, @(pwd){/};
* @(root){}, like @(pwd), except up instead of down;
* @(now) prints the date and the time in UTC.
Further parsed in @(files){} in ".index.html",
* @(filealt) prints Dir or File;
* @(filedesc);
* @(filehref) prints the filename or the {.link};
* @(fileicon) prints it's {.d.jpeg}, or if it is not there, {dir.jpeg} or
{file.jpeg};
* @(filename) prints the file name;
* @(filesize) prints the file size, if it exits;
* @(now) prints the date and the time in UTC.
Parsed in ".newsfeed.rss",
* @(date) prints the date on the news file;
* @(news) prints the contents of the file (as a text file);
* @(newsname) prints the filename of the news story;
* @(now) prints the date and the time in UTC;
* @(title) prints the second line in the {.news}.
@title Parser
@author Neil
@std C89/90
@version 1.1; 2017-03 fixed pedantic warnings; took out arg
@since 0.6; 2008-03-21 */
#include <stdio.h> /* [f]printf FILE */ #include <stdio.h> /* [f]printf FILE */
#include <stdlib.h> /* malloc */ #include <stdlib.h> /* malloc */
@ -22,11 +57,11 @@ struct Parser {
}; };
/* private - this is the list of 'widgets', see Widget.c - add widgets to here /* private - this is the list of 'widgets', see Widget.c - add widgets to here
to make them recognised - ASCIIbetical */ to make them recognised - ASCIIbetical */
struct Symbol { static const struct Symbol {
char *symbol; char *symbol;
int (*handler)(const struct Files *, FILE *fp); const ParserWidget handler;
int onlyInRoot; /* fixme: not used, just trust the users? haha */ int onlyInRoot; /* fixme: not used, just trust the users? haha */
} static const sym[] = { } sym[] = {
{ "content", &WidgetContent, 0 }, /* index */ { "content", &WidgetContent, 0 }, /* index */
{ "date", &WidgetDate, 0 }, /* news */ { "date", &WidgetDate, 0 }, /* news */
{ "filealt", &WidgetFilealt, 0 }, /* files */ { "filealt", &WidgetFilealt, 0 }, /* files */
@ -41,54 +76,52 @@ struct Symbol {
{ "news", &WidgetNews, 0 }, /* news */ { "news", &WidgetNews, 0 }, /* news */
{ "newsname", &WidgetNewsname, 0 }, /* news */ { "newsname", &WidgetNewsname, 0 }, /* news */
{ "now", &WidgetNow, 0 }, /* any */ { "now", &WidgetNow, 0 }, /* any */
{ "pwd", &WidgetPwd, -1 }, /* don't put it where it doesn't make sense */ { "pwd", &WidgetPwd, -1 }, /* index */
{ "root", &WidgetRoot, -1 }, /* like pwd exept up instead of dn */ { "root", &WidgetRoot, -1 }, /* like pwd except up instead of dn */
{ "title", &WidgetTitle, 0 } /* news */ { "title", &WidgetTitle, 0 } /* news */
}; };
/* private */ /* private */
int parse(struct Parser *p, int invisible, FILE *fp); static const struct Symbol *match(const char *str, const char *end);
/** @return Creates a parser for the string, {str}. */
struct Parser *Parser(const char *str) { struct Parser *Parser(const char *str) {
struct Parser *p; struct Parser *p;
p = malloc(sizeof(struct Parser)); if(!(p = malloc(sizeof *p))) return 0;
p->str = (char *)str; p->str = (char *)str;
p->pos = p->str; p->pos = p->str;
p->rew = p->str; p->rew = p->str;
p->recursion = 0; p->recursion = 0;
return p; return p;
} }
void Parser_(struct Parser *p) {
if(!p) return; /** @param p_ptr: A pointer to the {Parser} that's to be destucted. */
void Parser_(struct Parser **const p_ptr) {
struct Parser *p;
if(!p_ptr || !(p = *p_ptr)) return;
if(p->recursion) fprintf(stderr, "Parser~: a file was closed with recursion level of %d; syntax error?\n", p->recursion); if(p->recursion) fprintf(stderr, "Parser~: a file was closed with recursion level of %d; syntax error?\n", p->recursion);
free(p); free(p);
*p_ptr = 0;
} }
/** binary search */ /** Resets the parser, {p}. */
const struct Symbol *match(const char *str, const char *end) {
const int N = sizeof(sym) / sizeof(struct Symbol);
int a, lenMatch, lenComp, lo = 0, mid, hi = N - 1;
lenMatch = end - str;
while(lo <= hi) {
mid = (lo + hi) >> 1;
/* this is highly inefficient */
lenComp = strlen(sym[mid].symbol);
a = strncmp(str, sym[mid].symbol, lenMatch > lenComp ? lenMatch : lenComp);
if (a < 0) hi = mid - 1;
else if(a > 0) lo = mid + 1;
else return &sym[mid];
}
return 0;
}
void ParserRewind(struct Parser *p) { void ParserRewind(struct Parser *p) {
if(!p) return; if(!p) return;
p->pos = p->rew; p->pos = p->rew;
} }
/** parse, called recusively (invisible, hack) fixme: this fn needs rewriting, messy */
int ParserParse(struct Parser *p, const struct Files *f, int invisible, FILE *fp) { /** Parse, called recursively.
@param f: Called in the handler to {ParserWidget}s.
@param invisible: No output.
@param fp: Output.
@fixme This fn needs rewriting; messy.
@fixme Invisible, hack. */
int ParserParse(struct Parser *p, const struct Files *f, int invisible,
FILE *fp) {
char *mark; char *mark;
if(!p || !fp || !p->pos) return 0; if(!p || !fp || !p->pos) return 0;
if(++p->recursion > maxRecursion) fprintf(stderr, "Parser::parse: %d recursion levels reached (Ctrl-C to stop!)\n", p->recursion); if(++p->recursion > maxRecursion) fprintf(stderr, "Parser::parse: %d "
"recursion levels reached (Ctrl-C to stop!)\n", p->recursion);
mark = p->pos; mark = p->pos;
if(p->recursion == 1) p->rew = mark; if(p->recursion == 1) p->rew = mark;
for( ; ; ) { for( ; ; ) {
@ -117,7 +150,8 @@ int ParserParse(struct Parser *p, const struct Files *f, int invisible, FILE *fp
char *start = p->pos + 2, *end; char *start = p->pos + 2, *end;
if(!invisible) fprintf(fp, "%.*s", (int)(p->pos - mark), mark); if(!invisible) fprintf(fp, "%.*s", (int)(p->pos - mark), mark);
if(!(end = strpbrk(start, ")"))) break; /* syntax error */ if(!(end = strpbrk(start, ")"))) break; /* syntax error */
if(!(m = match(start, end))) fprintf(stderr, "Parser::parse: symbol not reconised, '%.*s.'\n", (int)(end - start), start); if(!(m = match(start, end))) fprintf(stderr, "Parser::parse: "
"symbol not reconised, '%.*s.'\n", (int)(end - start), start);
/* if(p->recursion == 1 && m && m->onlyInRoot) return -1; ? */ /* if(p->recursion == 1 && m && m->onlyInRoot) return -1; ? */
open = *(end + 1) == '{' ? -1 : 0; open = *(end + 1) == '{' ? -1 : 0;
do { do {
@ -135,3 +169,22 @@ int ParserParse(struct Parser *p, const struct Files *f, int invisible, FILE *fp
p->recursion--; p->recursion--;
return 0; return 0;
} }
/** binary search */
static const struct Symbol *match(const char *str, const char *end) {
const int N = sizeof(sym) / sizeof(struct Symbol);
int a, lo = 0, mid, hi = N - 1;
size_t lenMatch, lenComp;
lenMatch = end - str;
while(lo <= hi) {
mid = (lo + hi) >> 1;
/* this is highly inefficient */
lenComp = strlen(sym[mid].symbol);
a = strncmp(str, sym[mid].symbol,
lenMatch > lenComp ? lenMatch : lenComp);
if (a < 0) hi = mid - 1;
else if(a > 0) lo = mid + 1;
else return &sym[mid];
}
return 0;
}

View File

@ -1,7 +1,14 @@
/** See \see{Parser}. */
struct Parser; struct Parser;
/** Dependancy on {Files} */
struct Files; struct Files;
/** All {ParserWidget}s are in {Widget.c} */
typedef int (*ParserWidget)(const struct Files *, FILE *fp);
struct Parser *Parser(const char *str); struct Parser *Parser(const char *str);
void Parser_(struct Parser *p); void Parser_(struct Parser **const p_ptr);
void ParserRewind(struct Parser *p); void ParserRewind(struct Parser *p);
int ParserParse(struct Parser *p, const struct Files *f, int invisible, FILE *fp); int ParserParse(struct Parser *p, const struct Files *f, int invisible,
FILE *fp);

View File

@ -1,11 +1,52 @@
/** Copyright 2008, 2012 Neil Edelman, distributed under the terms of the /** Copyright 2008, 2012 Neil Edelman, distributed under the terms of the
GNU General Public License, see copying.txt GNU General Public License, see copying.txt
This is the main program. I didn't know what to call it. {MakeIndex} is a simple content management system that generates static
content, (mostly index.html,) on all the directories rooted at the directory
specified by the argument. It is based on a template file, ".index.html" and
".newsfeed.rss". Also included are files to summarise the directory structure
for a {xml} site map, compatible with Google, and any {.news} for an {rss}
feed. It takes one argument, <directory>, which is the root of the recursion.
There should be an <example> directory that has a bunch of files in it. Run
{bin/MakeIndex example/}; it should make a webpage out of the directory
structure and {.index.html}, open {example/index.html} after running to see.
* If the {.index.html} file exists in the <directory>, prints <index.html>
recursively; overwrites any {index.html} on all the directories rooted at
<directory>;
* if the {.sitemap.xml} file exists in <directory>, prints (and overwrites) an
index called {sitemap.xml};
* if the {.newsfeed.rss} file exists in <directory>, prints (and overwrites)
to {newsfeed.rss} all the {.news} files (if there are any.)
* Treats {.d} as a description of the file without the {.d};
if this is an empty text-file or a zero-byte file, it skips over this file.
* treats {index.d} as a description of the directory;
* treats {content.d} as an in-depth description of the directory,
replacing <index.d> when in the directory;
* treats {.d.jpg} as a image that will go with the description;
* treats {.news} as a newsworthy item; the format of this file is ISO 8601
date (YYYY-MM-DD,) next line title;
* treats {.link} as a link with the href in the file.
{.index.html}, {.sitemap.xml}, {.newsfeed.rss}, see {Parser} for recognised
symbols. Assumes '..' is the parent directory, '.' is the current directory,
and '/' is the directory separator; works for UNIX, MacOS, Windows.
If this is not the case, the constants are in {Files.c}.
@title Parser
@author Neil @author Neil
@version 1.0; 2016-09-19 Added umask @std C89/90
@since 1.0; 2008-03-27 */ @version 1.1; 2017-03 fixed pedantic warnings; took out arg
@since 1.0; 2016-09-19 Added umask
0.8; 2013-07 case-insensitive sort
0.7; 2012 sth.dsth.d handled properly
0.6; 2008-03-27
@fixme Don't have <directory> be an argument; just do it in the current.
@fixme Have a subset of LaTeX converted into html for the .d files?
@fixme Encoding is an issue; especially the newsfeed, 7bit.
@fixme It's not robust; eg @(files){@(files){Don't do this.}}. */
#include <stdlib.h> /* malloc free fgets */ #include <stdlib.h> /* malloc free fgets */
#include <stdio.h> /* fprintf FILE */ #include <stdio.h> /* fprintf FILE */
@ -38,7 +79,7 @@ void usage(const char *programme);
/* constants */ /* constants */
static const int versionMajor = 0; static const int versionMajor = 0;
static const int versionMinor = 8; static const int versionMinor = 8;
static const int granularity = 1024; static const size_t granularity= 1024;
static const int maxRead = 0x1000; static const int maxRead = 0x1000;
const char *htmlIndex = "index.html"; /* in multiple files */ const char *htmlIndex = "index.html"; /* in multiple files */
static const char *xmlSitemap = "sitemap.xml"; static const char *xmlSitemap = "sitemap.xml";
@ -50,15 +91,15 @@ static const char *tmplNewsfeed= ".newsfeed.rss";
extern const char *dirCurrent; extern const char *dirCurrent;
extern const char *dirParent; extern const char *dirParent;
/* in Widget.c */ /* in Widget.c */
extern const char *desc; extern const char *dot_desc;
extern const char *news; extern const char *dot_news;
/* there can only be one recursor at a time, sorry */ /* there can only be one recursor at a time, sorry */
static struct Recursor *r = 0; static struct Recursor *r = 0;
/* public */ /* public */
struct Recursor *Recursor(const char *index, const char *map, const char *news) { struct Recursor *Recursor(const char *idx, const char *map, const char *news) {
if(!index || !index || !map || !news) return 0; if(!idx || !idx || !map || !news) return 0;
if(r) { fprintf(stderr, "Recursor: there is already a Recursor.\n"); return 0; } if(r) { fprintf(stderr, "Recursor: there is already a Recursor.\n"); return 0; }
r = malloc(sizeof(struct Recursor)); r = malloc(sizeof(struct Recursor));
if(!r) { perror("recursor"); Recursor_(); return 0; } if(!r) { perror("recursor"); Recursor_(); return 0; }
@ -74,8 +115,8 @@ struct Recursor *Recursor(const char *index, const char *map, const char *news)
if(!(r->sitemap = fopen(xmlSitemap, "w"))) perror(xmlSitemap); if(!(r->sitemap = fopen(xmlSitemap, "w"))) perror(xmlSitemap);
if(!(r->newsfeed = fopen(rssNewsfeed, "w"))) perror(rssNewsfeed); if(!(r->newsfeed = fopen(rssNewsfeed, "w"))) perror(rssNewsfeed);
/* read from the input files */ /* read from the input files */
if( !(r->indexString = readFile(index))) { if( !(r->indexString = readFile(idx))) {
fprintf(stderr, "Recursor: to make an index, create the file <%s>.\n", index); fprintf(stderr, "Recursor: to make an index, create the file <%s>.\n", idx);
} }
if(r->sitemap && !(r->sitemapString = readFile(map))) { if(r->sitemap && !(r->sitemapString = readFile(map))) {
fprintf(stderr, "Recursor: to make an sitemap, create the file <%s>.\n", map); fprintf(stderr, "Recursor: to make an sitemap, create the file <%s>.\n", map);
@ -85,7 +126,7 @@ struct Recursor *Recursor(const char *index, const char *map, const char *news)
} }
/* create Parsers attached to them */ /* create Parsers attached to them */
if(r->indexString && !(r->indexParser = Parser(r->indexString))) { if(r->indexString && !(r->indexParser = Parser(r->indexString))) {
fprintf(stderr, "Recursor: error generating Parser from <%s>.\n", index); fprintf(stderr, "Recursor: error generating Parser from <%s>.\n", idx);
} }
if(r->sitemapString && !(r->sitemapParser = Parser(r->sitemapString))) { if(r->sitemapString && !(r->sitemapParser = Parser(r->sitemapString))) {
fprintf(stderr, "Recursor: error generating Parser from <%s>.\n", map); fprintf(stderr, "Recursor: error generating Parser from <%s>.\n", map);
@ -117,11 +158,11 @@ void Recursor_(void) {
ParserParse(r->newsfeedParser, 0, 0, r->newsfeed); ParserParse(r->newsfeedParser, 0, 0, r->newsfeed);
} }
if(r->newsfeed && fclose(r->newsfeed)) perror(rssNewsfeed); if(r->newsfeed && fclose(r->newsfeed)) perror(rssNewsfeed);
Parser_(r->indexParser); Parser_(&r->indexParser);
free(r->indexString); free(r->indexString);
Parser_(r->sitemapParser); Parser_(&r->sitemapParser);
free(r->sitemapString); free(r->sitemapString);
Parser_(r->newsfeedParser); Parser_(&r->newsfeedParser);
free(r->newsfeedString); free(r->newsfeedString);
free(r); free(r);
r = 0; r = 0;
@ -137,7 +178,7 @@ int main(int argc, char **argv) {
if(chdir(argv[1])) { perror(argv[1]); return EXIT_FAILURE; } if(chdir(argv[1])) { perror(argv[1]); return EXIT_FAILURE; }
/* make sure that umask is set so that others can read what we create */ /* make sure that umask is set so that others can read what we create */
umask(S_IWGRP | S_IWOTH); umask((mode_t)(S_IWGRP | S_IWOTH));
/* recursing; fixme: this should be configurable */ /* recursing; fixme: this should be configurable */
if(!Recursor(tmplIndex, tmplSitemap, tmplNewsfeed)) return EXIT_FAILURE; if(!Recursor(tmplIndex, tmplSitemap, tmplNewsfeed)) return EXIT_FAILURE;
@ -153,13 +194,13 @@ int filter(const struct Files *files, const char *fn) {
FILE *fd; FILE *fd;
if(!r) { fprintf(stderr, "Recusor::filter: recursor not initialised.\n"); return 0; } if(!r) { fprintf(stderr, "Recusor::filter: recursor not initialised.\n"); return 0; }
/* *.d[.0]* */ /* *.d[.0]* */
for(str = (char *)fn; (str = strstr(str, desc)); ) { for(str = (char *)fn; (str = strstr(str, dot_desc)); ) {
str += strlen(desc); str += strlen(dot_desc);
if(*str == '\0' || *str == '.') return 0; if(*str == '\0' || *str == '.') return 0;
} }
/* *.news$ */ /* *.news$ */
if((str = strstr(fn, news))) { if((str = strstr(fn, dot_news))) {
str += strlen(news); str += strlen(dot_news);
if(*str == '\0') { if(*str == '\0') {
if(WidgetSetNews(fn) && ParserParse(r->newsfeedParser, files, 0, r->newsfeed)) { if(WidgetSetNews(fn) && ParserParse(r->newsfeedParser, files, 0, r->newsfeed)) {
ParserRewind(r->newsfeedParser); ParserRewind(r->newsfeedParser);
@ -176,12 +217,12 @@ int filter(const struct Files *files, const char *fn) {
/* index.html */ /* index.html */
if(!strcmp(fn, htmlIndex)) return 0; if(!strcmp(fn, htmlIndex)) return 0;
/* add .d, check 1 line for \n (hmm, this must be a real time waster) */ /* add .d, check 1 line for \n (hmm, this must be a real time waster) */
if(strlen(fn) > sizeof(filed) - strlen(desc) - 1) { if(strlen(fn) > sizeof(filed) - strlen(dot_desc) - 1) {
fprintf(stderr, "Recusor::filter: regected '%s' because it was too long (%d.)\n", fn, (int)sizeof(filed)); fprintf(stderr, "Recusor::filter: regected '%s' because it was too long (%d.)\n", fn, (int)sizeof(filed));
return 0; return 0;
} }
strcpy(filed, fn); strcpy(filed, fn);
strcat(filed, desc); strcat(filed, dot_desc);
if((fd = fopen(filed, "r"))) { if((fd = fopen(filed, "r"))) {
int ch = fgetc(fd); int ch = fgetc(fd);
if(ch == '\n' || ch == '\r' || ch == EOF) { if(ch == '\n' || ch == '\r' || ch == EOF) {
@ -223,19 +264,20 @@ int recurse(const struct Files *parent) {
} }
char *readFile(const char *filename) { char *readFile(const char *filename) {
char *buf = 0, *newBuf; char *buf = 0, *newBuf;
int bufPos = 0, bufSize = 0, read; size_t bufPos = 0, bufSize = 0, rd;
FILE *fp; FILE *fp;
if(!filename) return 0; if(!filename) return 0;
if(!(fp = fopen(filename, "r"))) { perror(filename); return 0; } if(!(fp = fopen(filename, "r"))) { perror(filename); return 0; }
for( ; ; ) { for( ; ; ) {
newBuf = realloc(buf, (bufSize += granularity) * sizeof(char)); newBuf = realloc(buf, (bufSize += granularity) * sizeof(char));
if(!newBuf) { perror(filename); free(buf); return 0; } if(!newBuf) { perror(filename); free(buf); return 0; }
buf = newBuf; buf = newBuf;
read = fread(buf + bufPos, sizeof(char), granularity, fp); rd = fread(buf + bufPos, sizeof(char), granularity, fp);
bufPos += read; bufPos += rd;
if(read < granularity) { buf[bufPos] = '\0'; break; } if(rd < granularity) { buf[bufPos] = '\0'; break; }
} }
fprintf(stderr, "Opened '%s' and alloted %d bytes to read %d characters.\n", filename, bufSize, bufPos); fprintf(stderr, "Opened '%s' and alloted %lu bytes to read %lu "
"characters.\n", filename, bufSize, bufPos);
if(fclose(fp)) perror(filename); if(fclose(fp)) perror(filename);
return buf; /** you must free() the memory! */ return buf; /** you must free() the memory! */
} }

View File

@ -1,13 +1,18 @@
/* Copyright 2008, 2012 Neil Edelman, distributed under the terms of the /* Copyright 2008, 2012 Neil Edelman, distributed under the terms of the
GNU General Public License, see copying.txt */ GNU General Public License, see copying.txt
/* Widgets like @files @pwd. How to create a widget? Widgets like @files @pwd. To create a widget:
1. stick the code below, it's prototype must be the same, int(FILE *), where
the FILE* is called with the output file * stick the code below implementing {ParserWidget};
2. create a prototype in Widget.h * create a prototype in Widget.h;
3. in Parser.c, add to the symbol table, sym[] with the symbol you want, in * in {Parser.c}, add to the symbol table, sym[] with the symbol you want, in
ASCIIbetical order ASCIIbetical order.
* Created by Neil Edelman on 2008-03-25. */
@title Widget
@author Neil
@std C89/90
@version 1.1; 2017-03 fixed pedantic warnings; took out arg
@since 0.6; 2008-03-25 */
#include <string.h> /* strncat strncpy */ #include <string.h> /* strncat strncpy */
#include <stdio.h> /* fprintf FILE */ #include <stdio.h> /* fprintf FILE */
@ -17,15 +22,28 @@
#include "Recursor.h" #include "Recursor.h"
#include "Widget.h" #include "Widget.h"
/* <-- ugly */
#ifndef _MSC_VER /* <-- not msvc */
#define UNUSED(a) while(0 && (a))
#else /* not msvc --><-- msvc: not a C89/90 compiler; needs a little help */
#pragma warning(push)
/* "Assignment within conditional expression." No. */
#pragma warning(disable: 4706)
/* "<ANSI/ISO name>: The POSIX name for this item is deprecated." No. */
#pragma warning(disable: 4996)
#define UNUSED(a) (void)(sizeof((a), 0))
#endif /* msvc --> */
/* ugly --> */
/* constants */ /* constants */
static const char *htmlDesc = "index.d"; static const char *htmlDesc = "index.d";
static const char *htmlContent = "content.d"; static const char *htmlContent = "content.d";
static const char *separator = "/"; static const char *separator = "/";
static const char *picture = ".jpeg"; /* yeah, I hard coded this */ static const char *picture = ".jpeg"; /* yeah, I hard coded this */
static const size_t maxRead = 512; static const size_t maxRead = 512;
static const char *link = ".link"; static const char *dot_link = ".link";
const char *desc = ".d"; /* used in multiple files */ const char *dot_desc = ".d"; /* used in multiple files */
const char *news = ".news"; const char *dot_news = ".news";
extern const char *dirCurrent; extern const char *dirCurrent;
extern const char *dirParent; extern const char *dirParent;
extern const char *htmlIndex; extern const char *htmlIndex;
@ -38,15 +56,17 @@ static char title[64] = "(no title)";
static char filenews[64] = "(no file name)"; static char filenews[64] = "(no file name)";
/* private */ /* private */
int correctNo(int no, const int low, const int high); int clip(int no, const int low, const int high);
int WidgetSetNews(const char *fn) { int WidgetSetNews(const char *fn) {
char *dot; char *dot;
int read, tLen; int read;
size_t tLen;
FILE *fp; FILE *fp;
if(!fn || !(dot = strstr(fn, news))) return 0; if(!fn || !(dot = strstr(fn, dot_news))) return 0;
if(strlen(fn) > sizeof(filenews) / sizeof(char) - sizeof(char)) { if(strlen(fn) > sizeof(filenews) / sizeof(char) - sizeof(char)) {
fprintf(stderr, "Widget::SetNews: news file name, \"%s,\" doesn't fit in buffer (%d.)\n", fn, (int)(sizeof(filenews) / sizeof(char))); fprintf(stderr, "Widget::SetNews: news file name, \"%s,\" doesn't fit "
"in buffer (%d.)\n", fn, (int)(sizeof(filenews) / sizeof(char)));
return 0; return 0;
} }
/* save the fn, safe because we checked it, and strip off .news */ /* save the fn, safe because we checked it, and strip off .news */
@ -55,44 +75,56 @@ int WidgetSetNews(const char *fn) {
/* open .news */ /* open .news */
if(!(fp = fopen(fn, "r"))) { perror(fn); return 0; } if(!(fp = fopen(fn, "r"))) { perror(fn); return 0; }
read = fscanf(fp, "%d-%d-%d\n", &year, &month, &day); read = fscanf(fp, "%d-%d-%d\n", &year, &month, &day);
if(read < 3) fprintf(stderr, "Widget::setNews: error parsing ISO 8601 date, <YYYY-MM-DD>.\n"); if(read < 3) fprintf(stderr, "Widget::setNews: error parsing ISO 8601 "
month = correctNo(month, 1, 12); "date, <YYYY-MM-DD>.\n");
day = correctNo(day, 1, 31); month = clip(month, 1, 12);
day = clip(day, 1, 31);
/* fgets reads a newline at the end (annoying) so we strip that off */ /* fgets reads a newline at the end (annoying) so we strip that off */
if(!fgets(title, sizeof(title), fp)) { perror(fn); *title = '\0'; } if(!fgets(title, (int)sizeof(title), fp)) { perror(fn); *title = '\0'; }
else if((tLen = strlen(title)) > 0 && title[tLen - 1] == '\n') title[tLen - 1] = '\0'; else if((tLen = strlen(title)) > 0 && title[tLen - 1] == '\n')
title[tLen - 1] = '\0';
if(fclose(fp)) perror(fn); if(fclose(fp)) perror(fn);
fprintf(stderr, "News <%s>, '%s' %d-%d-%d.\n", filenews, title, year, month, day); fprintf(stderr, "News <%s>, '%s' %d-%d-%d.\n", filenews, title, year,
month, day);
return -1; return -1;
} }
/* the widget handlers */ /* the widget handlers */
/** @implements ParserWidget */
int WidgetContent(const struct Files *f, FILE *fp) { int WidgetContent(const struct Files *f, FILE *fp) {
char buf[81], *bufpos; char buf[81], *bufpos;
int i; size_t i;
FILE *in; FILE *in;
UNUSED(f);
/* it's a nightmare to test if this is text (which most is,) in which case /* it's a nightmare to test if this is text (which most is,) in which case
we should insert <p>...</p> after every paragraph, <>& -> &lt;&gt;&amp;, we should insert <p>...</p> after every paragraph, <>& -> &lt;&gt;&amp;,
but we have to not translate already encoded html; the only solution that but we have to not translate already encoded html; the only solution that
a could see is have a new langauge (like-LaTeX) that gracefully handles a could see is have a new langauge (like-LaTeX) that gracefully handles
plain-text */ plain-text */
if((in = fopen(htmlContent, "r")) || (in = fopen(htmlDesc, "r"))) { if((in = fopen(htmlContent, "r")) || (in = fopen(htmlDesc, "r"))) {
for(i = 0; (i < maxRead) && (bufpos = fgets(buf, sizeof(buf), in)); i++) { for(i = 0; (i < maxRead)
&& (bufpos = fgets(buf, (int)sizeof(buf), in)); i++) {
fprintf(fp, "%s", bufpos); fprintf(fp, "%s", bufpos);
} }
if(fclose(in)) perror(htmlDesc); if(fclose(in)) perror(htmlDesc);
} }
return 0; return 0;
} }
/** @implements ParserWidget */
int WidgetDate(const struct Files *f, FILE *fp) { int WidgetDate(const struct Files *f, FILE *fp) {
UNUSED(f);
/* ISO 8601 - YYYY-MM-DD */ /* ISO 8601 - YYYY-MM-DD */
fprintf(fp, "%4.4d-%2.2d-%2.2d", year, month, day); fprintf(fp, "%4.4d-%2.2d-%2.2d", year, month, day);
return 0; return 0;
} }
/** @implements ParserWidget */
int WidgetFilealt(const struct Files *f, FILE *fp) { int WidgetFilealt(const struct Files *f, FILE *fp) {
fprintf(fp, "%s", FilesIsDir(f) ? "Dir" : "File"); fprintf(fp, "%s", FilesIsDir(f) ? "Dir" : "File");
return 0; return 0;
} }
/** @implements ParserWidget */
int WidgetFiledesc(const struct Files *f, FILE *fp) { int WidgetFiledesc(const struct Files *f, FILE *fp) {
char buf[256], *name; char buf[256], *name;
FILE *in; FILE *in;
@ -100,29 +132,32 @@ int WidgetFiledesc(const struct Files *f, FILE *fp) {
if(FilesIsDir(f)) { if(FilesIsDir(f)) {
/* <file>/index.d */ /* <file>/index.d */
strncpy(buf, name, sizeof(buf) - 9); strncpy(buf, name, sizeof(buf) - 9);
strncat(buf, separator, 1); strncat(buf, separator, 1lu);
strncat(buf, htmlDesc, 7); strncat(buf, htmlDesc, 7lu);
} else { } else {
/* <file>.d */ /* <file>.d */
strncpy(buf, name, sizeof(buf) - 6); strncpy(buf, name, sizeof(buf) - 6);
strncat(buf, desc, 5); strncat(buf, dot_desc, 5lu);
} }
if((in = fopen(buf, "r"))) { if((in = fopen(buf, "r"))) {
char *bufpos; char *bufpos;
int i; size_t i;
for(i = 0; (i < maxRead) && (bufpos = fgets(buf, sizeof(buf), in)); i++) { for(i = 0; (i < maxRead)
&& (bufpos = fgets(buf, (int)sizeof(buf), in)); i++) {
fprintf(fp, "%s", bufpos); fprintf(fp, "%s", bufpos);
} }
if(fclose(in)) perror(buf); if(fclose(in)) perror(buf);
} }
return 0; return 0;
} }
/** @implements ParserWidget */
int WidgetFilehref(const struct Files *f, FILE *fp) { int WidgetFilehref(const struct Files *f, FILE *fp) {
char *str, *name; char *str, *name;
int ch; int ch;
FILE *fhref; FILE *fhref;
if(!(name = FilesName(f))) return 0; if(!(name = FilesName(f))) return 0;
if((str = strstr(name, link)) && *(str += strlen(link)) == '\0' && (fhref = fopen(name, "r"))) { if((str = strstr(name, dot_link)) && *(str += strlen(dot_link)) == '\0'
&& (fhref = fopen(name, "r"))) {
/* fixme: not too good, with the reading one char at a time */ /* fixme: not too good, with the reading one char at a time */
for( ; ; ) { for( ; ; ) {
ch = fgetc(fhref); ch = fgetc(fhref);
@ -135,14 +170,15 @@ int WidgetFilehref(const struct Files *f, FILE *fp) {
} }
return 0; return 0;
} }
/** @implements ParserWidget */
int WidgetFileicon(const struct Files *f, FILE *fp) { int WidgetFileicon(const struct Files *f, FILE *fp) {
char buf[256], *name; char buf[256], *name;
FILE *in; FILE *in;
if(!(name = FilesName(f))) return 0; if(!(name = FilesName(f))) return 0;
/* insert <file>.d.jpeg if available */ /* insert <file>.d.jpeg if available */
strncpy(buf, name, sizeof(buf) - 12); strncpy(buf, name, sizeof(buf) - 12);
strncat(buf, desc, 5); strncat(buf, dot_desc,5lu);
strncat(buf, picture, 6); strncat(buf, picture, 6lu);
if((in = fopen(buf, "r"))) { if((in = fopen(buf, "r"))) {
fprintf(fp, "%s", buf); fprintf(fp, "%s", buf);
if(fclose(in)) perror(buf); if(fclose(in)) perror(buf);
@ -158,44 +194,57 @@ int WidgetFileicon(const struct Files *f, FILE *fp) {
} }
return 0; return 0;
} }
/** @implements ParserWidget */
int WidgetFilename(const struct Files *f, FILE *fp) { int WidgetFilename(const struct Files *f, FILE *fp) {
fprintf(fp, "%s", FilesName(f)); fprintf(fp, "%s", FilesName(f));
return 0; return 0;
} }
/** @implements ParserWidget */
int WidgetFiles(const struct Files *f, FILE *fp) { int WidgetFiles(const struct Files *f, FILE *fp) {
while(0 && fp);
return FilesAdvance((struct Files *)f) ? -1 : 0; return FilesAdvance((struct Files *)f) ? -1 : 0;
} }
/** @implements ParserWidget */
int WidgetFilesize(const struct Files *f, FILE *fp) { /* eww */ int WidgetFilesize(const struct Files *f, FILE *fp) { /* eww */
if(!FilesIsDir(f)) fprintf(fp, " (%d KB)", FilesSize(f)); if(!FilesIsDir(f)) fprintf(fp, " (%d KB)", FilesSize(f));
return 0; return 0;
} }
/** @implements ParserWidget */
int WidgetNews(const struct Files *f, FILE *fp) { int WidgetNews(const struct Files *f, FILE *fp) {
char buf[256], *bufpos; char buf[256], *bufpos;
int i; size_t i;
FILE *in; FILE *in;
UNUSED(f);
if(!filenews[0]) return 0; if(!filenews[0]) return 0;
if(!(in = fopen(filenews, "r"))) { perror(filenews); return 0; } if(!(in = fopen(filenews, "r"))) { perror(filenews); return 0; }
for(i = 0; (i < maxRead) && (bufpos = fgets(buf, sizeof(buf), in)); i++) { for(i = 0; (i < maxRead)&&(bufpos = fgets(buf, (int)sizeof(buf), in)); i++){
fprintf(fp, "%s", bufpos); fprintf(fp, "%s", bufpos);
} }
if(fclose(in)) perror(filenews); if(fclose(in)) perror(filenews);
return 0; return 0;
} }
/** @implements ParserWidget */
int WidgetNewsname(const struct Files *f, FILE *fp) { int WidgetNewsname(const struct Files *f, FILE *fp) {
UNUSED(f);
fprintf(fp, "%s", filenews); fprintf(fp, "%s", filenews);
return 0; return 0;
} }
/** @implements ParserWidget */
int WidgetNow(const struct Files *f, FILE *fp) { int WidgetNow(const struct Files *f, FILE *fp) {
char t[22]; char t[22];
time_t currentTime; time_t currentTime;
struct tm *formatedTime; struct tm *formatedTime;
UNUSED(f);
if((currentTime = time(0)) == (time_t)(-1)) { perror("@date"); return 0; } if((currentTime = time(0)) == (time_t)(-1)) { perror("@date"); return 0; }
formatedTime = gmtime(&currentTime); formatedTime = gmtime(&currentTime);
/* ISO 8601 - YYYY-MM-DDThh:mm:ssTZD */ /* ISO 8601 - YYYY-MM-DDThh:mm:ssTZD */
strftime(t, 21, "%Y-%m-%dT%H:%M:%SZ", formatedTime); strftime(t, 21lu, "%Y-%m-%dT%H:%M:%SZ", formatedTime);
fprintf(fp, "%s", t); fprintf(fp, "%s", t);
return 0; return 0;
} }
/** @implements ParserWidget */
int WidgetPwd(const struct Files *f, FILE *fp) { int WidgetPwd(const struct Files *f, FILE *fp) {
static int persistant = 0; /* ick, be very careful! */ static int persistant = 0; /* ick, be very careful! */
char *pwd; char *pwd;
@ -205,6 +254,7 @@ int WidgetPwd(const struct Files *f, FILE *fp) {
fprintf(fp, "%s", pwd); fprintf(fp, "%s", pwd);
return -1; return -1;
} }
/** @implements ParserWidget */
int WidgetRoot(const struct Files *f, FILE *fp) { int WidgetRoot(const struct Files *f, FILE *fp) {
static int persistant = 0; /* ick, be very careful! */ static int persistant = 0; /* ick, be very careful! */
char *pwd; char *pwd;
@ -214,12 +264,14 @@ int WidgetRoot(const struct Files *f, FILE *fp) {
fprintf(fp, "%s", dirParent); fprintf(fp, "%s", dirParent);
return -1; return -1;
} }
/** @implements ParserWidget */
int WidgetTitle(const struct Files *f, FILE *fp) { int WidgetTitle(const struct Files *f, FILE *fp) {
UNUSED(f);
fprintf(fp, "%s", title); fprintf(fp, "%s", title);
return 0; return 0;
} }
int correctNo(int no, const int low, const int high) { int clip(int no, const int low, const int high) {
if(no < low) no = low; if(no < low) no = low;
else if(no > high) no = high; else if(no > high) no = high;
return no; return no;