Fixed a lot.
This commit is contained in:
parent
2b2daae97a
commit
7613e60e86
@ -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)
|
@ -41,22 +41,22 @@
|
||||
|
||||
<p>
|
||||
Copyright 2008, 2012 Neil Edelman, distributed under the terms of the
|
||||
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>.
|
||||
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>.
|
||||
</p>
|
||||
<p>
|
||||
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.)
|
||||
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.)
|
||||
</p>
|
||||
<dl>
|
||||
<dt>author:</dt>
|
||||
<dt>minimum standard</dt>
|
||||
<dd>C89/90</dd>
|
||||
<dt>author</dt>
|
||||
<dd>Neil</dd>
|
||||
<dt>version:</dt>
|
||||
<dd>0.9; 2017-03 fixed pedantic warnings</dd>
|
||||
<dt>since:</dt>
|
||||
<dd>0.8; 2013-07 case-insensitive sort
|
||||
0.7; 2012 sth.dsth.d handled properly
|
||||
0.6; 2008-03-24</dd>
|
||||
<dt>version</dt>
|
||||
<dd>1.1; 2017-03 fixed pedantic warnings; took out arg</dd>
|
||||
<dt>since</dt>
|
||||
<dd>0.6; 2008-03-24</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
@ -200,12 +200,8 @@ After FilesSetFarourite, this enumerates them.
|
||||
<div><a name = "FilesName"><!-- --></a>
|
||||
<h3>FilesName</h3>
|
||||
<pre>char * <b>FilesName</b> (const struct Files *files)</pre>
|
||||
<p>
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>return:</dt>
|
||||
<dt>return</dt>
|
||||
<dd>The file name of the selected file.</dd>
|
||||
</dl>
|
||||
</div>
|
||||
@ -213,12 +209,8 @@ After FilesSetFarourite, this enumerates them.
|
||||
<div><a name = "FilesSize"><!-- --></a>
|
||||
<h3>FilesSize</h3>
|
||||
<pre>int <b>FilesSize</b> (const struct Files *files)</pre>
|
||||
<p>
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>return:</dt>
|
||||
<dt>return</dt>
|
||||
<dd>File size of the selected file.</dd>
|
||||
</dl>
|
||||
</div>
|
||||
@ -226,12 +218,8 @@ After FilesSetFarourite, this enumerates them.
|
||||
<div><a name = "FilesIsDir"><!-- --></a>
|
||||
<h3>FilesIsDir</h3>
|
||||
<pre>int <b>FilesIsDir</b> (const struct Files *files)</pre>
|
||||
<p>
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>return:</dt>
|
||||
<dt>return</dt>
|
||||
<dd>Whether the file is a directory.</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
@ -45,31 +45,90 @@
|
||||
|
||||
<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>
|
||||
|
||||
<table>
|
||||
<tr><th>Return Type</th><th>Function Name</th><th>Argument List</th></tr>
|
||||
<tr>
|
||||
<td>const struct Symbol *</td>
|
||||
<td><a href = "#match">match</a></td>
|
||||
<td>const char *str, const char *end</td>
|
||||
<td>struct Parser *</td>
|
||||
<td><a href = "#Parser">Parser</a></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>
|
||||
<td>int</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>
|
||||
</table>
|
||||
|
||||
|
||||
<a name = "_detail"><!-- --></a><h2>Function Detail</h2>
|
||||
|
||||
<div><a name = "match"><!-- --></a>
|
||||
<h3>match</h3>
|
||||
<pre>const struct Symbol * <b>match</b> (const char *str, const char *end)</pre>
|
||||
<div><a name = "Parser"><!-- --></a>
|
||||
<h3>Parser</h3>
|
||||
<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>
|
||||
binary search
|
||||
Resets the parser, <em>p</em>.
|
||||
</p>
|
||||
<dl>
|
||||
</dl>
|
||||
@ -77,11 +136,22 @@ binary search
|
||||
|
||||
<div><a name = "ParserParse"><!-- --></a>
|
||||
<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>
|
||||
parse, called recusively (invisible, hack) fixme: this fn needs rewriting, messy
|
||||
Parse, called recursively.
|
||||
</p>
|
||||
<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>
|
||||
</div>
|
||||
|
||||
|
@ -25,13 +25,13 @@
|
||||
padding: 4px;
|
||||
}
|
||||
</style>
|
||||
<title></title>
|
||||
<title>Parser</title>
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
|
||||
<h1></h1>
|
||||
<h1>Parser</h1>
|
||||
|
||||
<ul>
|
||||
<li><a href = "#_declarations">Declarations</a></li>
|
||||
@ -41,18 +41,85 @@
|
||||
|
||||
<p>
|
||||
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>
|
||||
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, <directory>, which is the root of the recursion.
|
||||
</p>
|
||||
<p>
|
||||
There should be an <example> 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 <directory>, prints <index.html>
|
||||
recursively; overwrites any <em>index.html</em> on all the directories rooted at
|
||||
<directory>;
|
||||
</li>
|
||||
<li>
|
||||
if the <em>.sitemap.xml</em> file exists in <directory>, prints (and overwrites) an
|
||||
index called <em>sitemap.xml</em>;
|
||||
</li>
|
||||
<li>
|
||||
if the <em>.newsfeed.rss</em> file exists in <directory>, 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 <index.d> 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>
|
||||
<dl>
|
||||
<dt>author:</dt>
|
||||
<dt>minimum standard</dt>
|
||||
<dd>C89/90</dd>
|
||||
<dt>author</dt>
|
||||
<dd>Neil</dd>
|
||||
<dt>version:</dt>
|
||||
<dd>1.0; 2016-09-19 Added umask</dd>
|
||||
<dt>since:</dt>
|
||||
<dd>1.0; 2008-03-27</dd>
|
||||
<dt>version</dt>
|
||||
<dd>1.1; 2017-03 fixed pedantic warnings; took out arg</dd>
|
||||
<dt>since</dt>
|
||||
<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 <directory> 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>
|
||||
|
||||
|
||||
|
210
doc/Widget.html
210
doc/Widget.html
@ -50,11 +50,221 @@
|
||||
|
||||
<table>
|
||||
<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>
|
||||
|
||||
|
||||
<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>
|
||||
</html>
|
||||
|
19
src/Files.c
19
src/Files.c
@ -5,12 +5,11 @@
|
||||
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.)
|
||||
|
||||
@file Files
|
||||
@title Files
|
||||
@author Neil
|
||||
@version 0.9; 2017-03 fixed pedantic warnings
|
||||
@since 0.8; 2013-07 case-insensitive sort
|
||||
0.7; 2012 sth.dsth.d handled properly
|
||||
0.6; 2008-03-24 */
|
||||
@std C89/90
|
||||
@version 1.1; 2017-03 fixed pedantic warnings; took out arg
|
||||
@since 0.6; 2008-03-24 */
|
||||
|
||||
#include <stdlib.h> /* malloc free */
|
||||
#include <stdio.h> /* fprintf */
|
||||
@ -20,9 +19,9 @@
|
||||
#include "Files.h"
|
||||
|
||||
/* constants */
|
||||
const char *dirCurrent = "."; /* used in multiple files */
|
||||
const char *dirParent = "..";
|
||||
static const int maxFilename = 128;
|
||||
const char *dirCurrent = "."; /* used in multiple files */
|
||||
const char *dirParent = "..";
|
||||
static const size_t maxFilename = 128;
|
||||
|
||||
/* public */
|
||||
struct Files {
|
||||
@ -161,10 +160,10 @@ int FilesIsDir(const struct Files *files) {
|
||||
/* this is just a list of filenames, (not public) "class File" */
|
||||
|
||||
static struct File *File(const char *name, const int size, const int isDir) {
|
||||
int len;
|
||||
size_t len;
|
||||
struct File *file;
|
||||
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));
|
||||
if(!file) { File_(file); return 0; }
|
||||
file->next = 0;
|
||||
|
@ -1,6 +1,5 @@
|
||||
/** See \see{Files}. */
|
||||
struct Files;
|
||||
struct Recursor;
|
||||
|
||||
/** Returns a boolean value. */
|
||||
typedef int (*FilesFilter)(const struct Files *, const char *);
|
||||
|
117
src/Parser.c
117
src/Parser.c
@ -1,8 +1,43 @@
|
||||
/* 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.
|
||||
* Created by Neil Edelman on 2008-03-21. */
|
||||
Parsing of strings. '~' on a line by itself is recognised in ".newsfile.rss"
|
||||
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 <stdlib.h> /* malloc */
|
||||
@ -22,11 +57,11 @@ struct Parser {
|
||||
};
|
||||
/* private - this is the list of 'widgets', see Widget.c - add widgets to here
|
||||
to make them recognised - ASCIIbetical */
|
||||
struct Symbol {
|
||||
static const struct Symbol {
|
||||
char *symbol;
|
||||
int (*handler)(const struct Files *, FILE *fp);
|
||||
const ParserWidget handler;
|
||||
int onlyInRoot; /* fixme: not used, just trust the users? haha */
|
||||
} static const sym[] = {
|
||||
} sym[] = {
|
||||
{ "content", &WidgetContent, 0 }, /* index */
|
||||
{ "date", &WidgetDate, 0 }, /* news */
|
||||
{ "filealt", &WidgetFilealt, 0 }, /* files */
|
||||
@ -41,54 +76,52 @@ struct Symbol {
|
||||
{ "news", &WidgetNews, 0 }, /* news */
|
||||
{ "newsname", &WidgetNewsname, 0 }, /* news */
|
||||
{ "now", &WidgetNow, 0 }, /* any */
|
||||
{ "pwd", &WidgetPwd, -1 }, /* don't put it where it doesn't make sense */
|
||||
{ "root", &WidgetRoot, -1 }, /* like pwd exept up instead of dn */
|
||||
{ "pwd", &WidgetPwd, -1 }, /* index */
|
||||
{ "root", &WidgetRoot, -1 }, /* like pwd except up instead of dn */
|
||||
{ "title", &WidgetTitle, 0 } /* news */
|
||||
};
|
||||
|
||||
/* 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 *p;
|
||||
p = malloc(sizeof(struct Parser));
|
||||
if(!(p = malloc(sizeof *p))) return 0;
|
||||
p->str = (char *)str;
|
||||
p->pos = p->str;
|
||||
p->rew = p->str;
|
||||
p->recursion = 0;
|
||||
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);
|
||||
free(p);
|
||||
*p_ptr = 0;
|
||||
}
|
||||
|
||||
/** binary search */
|
||||
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;
|
||||
}
|
||||
/** Resets the parser, {p}. */
|
||||
void ParserRewind(struct Parser *p) {
|
||||
if(!p) return;
|
||||
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;
|
||||
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;
|
||||
if(p->recursion == 1) p->rew = mark;
|
||||
for( ; ; ) {
|
||||
@ -117,7 +150,8 @@ int ParserParse(struct Parser *p, const struct Files *f, int invisible, FILE *fp
|
||||
char *start = p->pos + 2, *end;
|
||||
if(!invisible) fprintf(fp, "%.*s", (int)(p->pos - mark), mark);
|
||||
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; ? */
|
||||
open = *(end + 1) == '{' ? -1 : 0;
|
||||
do {
|
||||
@ -135,3 +169,22 @@ int ParserParse(struct Parser *p, const struct Files *f, int invisible, FILE *fp
|
||||
p->recursion--;
|
||||
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;
|
||||
}
|
||||
|
11
src/Parser.h
11
src/Parser.h
@ -1,7 +1,14 @@
|
||||
/** See \see{Parser}. */
|
||||
struct Parser;
|
||||
|
||||
/** Dependancy on {Files} */
|
||||
struct Files;
|
||||
|
||||
/** All {ParserWidget}s are in {Widget.c} */
|
||||
typedef int (*ParserWidget)(const struct Files *, FILE *fp);
|
||||
|
||||
struct Parser *Parser(const char *str);
|
||||
void Parser_(struct Parser *p);
|
||||
void Parser_(struct Parser **const p_ptr);
|
||||
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);
|
||||
|
@ -1,11 +1,52 @@
|
||||
/** Copyright 2008, 2012 Neil Edelman, distributed under the terms of the
|
||||
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
|
||||
@version 1.0; 2016-09-19 Added umask
|
||||
@since 1.0; 2008-03-27 */
|
||||
@std C89/90
|
||||
@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 <stdio.h> /* fprintf FILE */
|
||||
@ -38,7 +79,7 @@ void usage(const char *programme);
|
||||
/* constants */
|
||||
static const int versionMajor = 0;
|
||||
static const int versionMinor = 8;
|
||||
static const int granularity = 1024;
|
||||
static const size_t granularity= 1024;
|
||||
static const int maxRead = 0x1000;
|
||||
const char *htmlIndex = "index.html"; /* in multiple files */
|
||||
static const char *xmlSitemap = "sitemap.xml";
|
||||
@ -50,15 +91,15 @@ static const char *tmplNewsfeed= ".newsfeed.rss";
|
||||
extern const char *dirCurrent;
|
||||
extern const char *dirParent;
|
||||
/* in Widget.c */
|
||||
extern const char *desc;
|
||||
extern const char *news;
|
||||
extern const char *dot_desc;
|
||||
extern const char *dot_news;
|
||||
|
||||
/* there can only be one recursor at a time, sorry */
|
||||
static struct Recursor *r = 0;
|
||||
|
||||
/* public */
|
||||
struct Recursor *Recursor(const char *index, const char *map, const char *news) {
|
||||
if(!index || !index || !map || !news) return 0;
|
||||
struct Recursor *Recursor(const char *idx, const char *map, const char *news) {
|
||||
if(!idx || !idx || !map || !news) return 0;
|
||||
if(r) { fprintf(stderr, "Recursor: there is already a Recursor.\n"); return 0; }
|
||||
r = malloc(sizeof(struct Recursor));
|
||||
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->newsfeed = fopen(rssNewsfeed, "w"))) perror(rssNewsfeed);
|
||||
/* read from the input files */
|
||||
if( !(r->indexString = readFile(index))) {
|
||||
fprintf(stderr, "Recursor: to make an index, create the file <%s>.\n", index);
|
||||
if( !(r->indexString = readFile(idx))) {
|
||||
fprintf(stderr, "Recursor: to make an index, create the file <%s>.\n", idx);
|
||||
}
|
||||
if(r->sitemap && !(r->sitemapString = readFile(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 */
|
||||
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))) {
|
||||
fprintf(stderr, "Recursor: error generating Parser from <%s>.\n", map);
|
||||
@ -117,11 +158,11 @@ void Recursor_(void) {
|
||||
ParserParse(r->newsfeedParser, 0, 0, r->newsfeed);
|
||||
}
|
||||
if(r->newsfeed && fclose(r->newsfeed)) perror(rssNewsfeed);
|
||||
Parser_(r->indexParser);
|
||||
Parser_(&r->indexParser);
|
||||
free(r->indexString);
|
||||
Parser_(r->sitemapParser);
|
||||
Parser_(&r->sitemapParser);
|
||||
free(r->sitemapString);
|
||||
Parser_(r->newsfeedParser);
|
||||
Parser_(&r->newsfeedParser);
|
||||
free(r->newsfeedString);
|
||||
free(r);
|
||||
r = 0;
|
||||
@ -137,7 +178,7 @@ int main(int argc, char **argv) {
|
||||
if(chdir(argv[1])) { perror(argv[1]); return EXIT_FAILURE; }
|
||||
|
||||
/* 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 */
|
||||
if(!Recursor(tmplIndex, tmplSitemap, tmplNewsfeed)) return EXIT_FAILURE;
|
||||
@ -153,13 +194,13 @@ int filter(const struct Files *files, const char *fn) {
|
||||
FILE *fd;
|
||||
if(!r) { fprintf(stderr, "Recusor::filter: recursor not initialised.\n"); return 0; }
|
||||
/* *.d[.0]* */
|
||||
for(str = (char *)fn; (str = strstr(str, desc)); ) {
|
||||
str += strlen(desc);
|
||||
for(str = (char *)fn; (str = strstr(str, dot_desc)); ) {
|
||||
str += strlen(dot_desc);
|
||||
if(*str == '\0' || *str == '.') return 0;
|
||||
}
|
||||
/* *.news$ */
|
||||
if((str = strstr(fn, news))) {
|
||||
str += strlen(news);
|
||||
if((str = strstr(fn, dot_news))) {
|
||||
str += strlen(dot_news);
|
||||
if(*str == '\0') {
|
||||
if(WidgetSetNews(fn) && ParserParse(r->newsfeedParser, files, 0, r->newsfeed)) {
|
||||
ParserRewind(r->newsfeedParser);
|
||||
@ -176,12 +217,12 @@ int filter(const struct Files *files, const char *fn) {
|
||||
/* index.html */
|
||||
if(!strcmp(fn, htmlIndex)) return 0;
|
||||
/* 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));
|
||||
return 0;
|
||||
}
|
||||
strcpy(filed, fn);
|
||||
strcat(filed, desc);
|
||||
strcat(filed, dot_desc);
|
||||
if((fd = fopen(filed, "r"))) {
|
||||
int ch = fgetc(fd);
|
||||
if(ch == '\n' || ch == '\r' || ch == EOF) {
|
||||
@ -223,19 +264,20 @@ int recurse(const struct Files *parent) {
|
||||
}
|
||||
char *readFile(const char *filename) {
|
||||
char *buf = 0, *newBuf;
|
||||
int bufPos = 0, bufSize = 0, read;
|
||||
size_t bufPos = 0, bufSize = 0, rd;
|
||||
FILE *fp;
|
||||
if(!filename) return 0;
|
||||
if(!(fp = fopen(filename, "r"))) { perror(filename); return 0; }
|
||||
for( ; ; ) {
|
||||
newBuf = realloc(buf, (bufSize += granularity) * sizeof(char));
|
||||
if(!newBuf) { perror(filename); free(buf); return 0; }
|
||||
buf = newBuf;
|
||||
read = fread(buf + bufPos, sizeof(char), granularity, fp);
|
||||
bufPos += read;
|
||||
if(read < granularity) { buf[bufPos] = '\0'; break; }
|
||||
buf = newBuf;
|
||||
rd = fread(buf + bufPos, sizeof(char), granularity, fp);
|
||||
bufPos += rd;
|
||||
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);
|
||||
return buf; /** you must free() the memory! */
|
||||
}
|
||||
|
122
src/Widget.c
122
src/Widget.c
@ -1,13 +1,18 @@
|
||||
/* 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?
|
||||
1. stick the code below, it's prototype must be the same, int(FILE *), where
|
||||
the FILE* is called with the output file
|
||||
2. create a prototype in Widget.h
|
||||
3. in Parser.c, add to the symbol table, sym[] with the symbol you want, in
|
||||
ASCIIbetical order
|
||||
* Created by Neil Edelman on 2008-03-25. */
|
||||
Widgets like @files @pwd. To create a widget:
|
||||
|
||||
* stick the code below implementing {ParserWidget};
|
||||
* create a prototype in Widget.h;
|
||||
* in {Parser.c}, add to the symbol table, sym[] with the symbol you want, in
|
||||
ASCIIbetical order.
|
||||
|
||||
@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 <stdio.h> /* fprintf FILE */
|
||||
@ -17,15 +22,28 @@
|
||||
#include "Recursor.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 */
|
||||
static const char *htmlDesc = "index.d";
|
||||
static const char *htmlContent = "content.d";
|
||||
static const char *separator = "/";
|
||||
static const char *picture = ".jpeg"; /* yeah, I hard coded this */
|
||||
static const size_t maxRead = 512;
|
||||
static const char *link = ".link";
|
||||
const char *desc = ".d"; /* used in multiple files */
|
||||
const char *news = ".news";
|
||||
static const char *dot_link = ".link";
|
||||
const char *dot_desc = ".d"; /* used in multiple files */
|
||||
const char *dot_news = ".news";
|
||||
extern const char *dirCurrent;
|
||||
extern const char *dirParent;
|
||||
extern const char *htmlIndex;
|
||||
@ -38,15 +56,17 @@ static char title[64] = "(no title)";
|
||||
static char filenews[64] = "(no file name)";
|
||||
|
||||
/* 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) {
|
||||
char *dot;
|
||||
int read, tLen;
|
||||
int read;
|
||||
size_t tLen;
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
/* save the fn, safe because we checked it, and strip off .news */
|
||||
@ -55,44 +75,56 @@ int WidgetSetNews(const char *fn) {
|
||||
/* open .news */
|
||||
if(!(fp = fopen(fn, "r"))) { perror(fn); return 0; }
|
||||
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");
|
||||
month = correctNo(month, 1, 12);
|
||||
day = correctNo(day, 1, 31);
|
||||
if(read < 3) fprintf(stderr, "Widget::setNews: error parsing ISO 8601 "
|
||||
"date, <YYYY-MM-DD>.\n");
|
||||
month = clip(month, 1, 12);
|
||||
day = clip(day, 1, 31);
|
||||
/* fgets reads a newline at the end (annoying) so we strip that off */
|
||||
if(!fgets(title, sizeof(title), fp)) { perror(fn); *title = '\0'; }
|
||||
else if((tLen = strlen(title)) > 0 && title[tLen - 1] == '\n') title[tLen - 1] = '\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';
|
||||
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;
|
||||
}
|
||||
|
||||
/* the widget handlers */
|
||||
|
||||
/** @implements ParserWidget */
|
||||
int WidgetContent(const struct Files *f, FILE *fp) {
|
||||
char buf[81], *bufpos;
|
||||
int i;
|
||||
size_t i;
|
||||
FILE *in;
|
||||
|
||||
UNUSED(f);
|
||||
/* it's a nightmare to test if this is text (which most is,) in which case
|
||||
we should insert <p>...</p> after every paragraph, <>& -> <>&,
|
||||
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
|
||||
plain-text */
|
||||
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);
|
||||
}
|
||||
if(fclose(in)) perror(htmlDesc);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/** @implements ParserWidget */
|
||||
int WidgetDate(const struct Files *f, FILE *fp) {
|
||||
UNUSED(f);
|
||||
/* ISO 8601 - YYYY-MM-DD */
|
||||
fprintf(fp, "%4.4d-%2.2d-%2.2d", year, month, day);
|
||||
return 0;
|
||||
}
|
||||
/** @implements ParserWidget */
|
||||
int WidgetFilealt(const struct Files *f, FILE *fp) {
|
||||
fprintf(fp, "%s", FilesIsDir(f) ? "Dir" : "File");
|
||||
return 0;
|
||||
}
|
||||
/** @implements ParserWidget */
|
||||
int WidgetFiledesc(const struct Files *f, FILE *fp) {
|
||||
char buf[256], *name;
|
||||
FILE *in;
|
||||
@ -100,29 +132,32 @@ int WidgetFiledesc(const struct Files *f, FILE *fp) {
|
||||
if(FilesIsDir(f)) {
|
||||
/* <file>/index.d */
|
||||
strncpy(buf, name, sizeof(buf) - 9);
|
||||
strncat(buf, separator, 1);
|
||||
strncat(buf, htmlDesc, 7);
|
||||
strncat(buf, separator, 1lu);
|
||||
strncat(buf, htmlDesc, 7lu);
|
||||
} else {
|
||||
/* <file>.d */
|
||||
strncpy(buf, name, sizeof(buf) - 6);
|
||||
strncat(buf, desc, 5);
|
||||
strncat(buf, dot_desc, 5lu);
|
||||
}
|
||||
if((in = fopen(buf, "r"))) {
|
||||
char *bufpos;
|
||||
int i;
|
||||
for(i = 0; (i < maxRead) && (bufpos = fgets(buf, sizeof(buf), in)); i++) {
|
||||
size_t i;
|
||||
for(i = 0; (i < maxRead)
|
||||
&& (bufpos = fgets(buf, (int)sizeof(buf), in)); i++) {
|
||||
fprintf(fp, "%s", bufpos);
|
||||
}
|
||||
if(fclose(in)) perror(buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/** @implements ParserWidget */
|
||||
int WidgetFilehref(const struct Files *f, FILE *fp) {
|
||||
char *str, *name;
|
||||
int ch;
|
||||
FILE *fhref;
|
||||
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 */
|
||||
for( ; ; ) {
|
||||
ch = fgetc(fhref);
|
||||
@ -135,14 +170,15 @@ int WidgetFilehref(const struct Files *f, FILE *fp) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/** @implements ParserWidget */
|
||||
int WidgetFileicon(const struct Files *f, FILE *fp) {
|
||||
char buf[256], *name;
|
||||
FILE *in;
|
||||
if(!(name = FilesName(f))) return 0;
|
||||
/* insert <file>.d.jpeg if available */
|
||||
strncpy(buf, name, sizeof(buf) - 12);
|
||||
strncat(buf, desc, 5);
|
||||
strncat(buf, picture, 6);
|
||||
strncat(buf, dot_desc,5lu);
|
||||
strncat(buf, picture, 6lu);
|
||||
if((in = fopen(buf, "r"))) {
|
||||
fprintf(fp, "%s", buf);
|
||||
if(fclose(in)) perror(buf);
|
||||
@ -158,44 +194,57 @@ int WidgetFileicon(const struct Files *f, FILE *fp) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/** @implements ParserWidget */
|
||||
int WidgetFilename(const struct Files *f, FILE *fp) {
|
||||
fprintf(fp, "%s", FilesName(f));
|
||||
return 0;
|
||||
}
|
||||
/** @implements ParserWidget */
|
||||
int WidgetFiles(const struct Files *f, FILE *fp) {
|
||||
while(0 && fp);
|
||||
return FilesAdvance((struct Files *)f) ? -1 : 0;
|
||||
}
|
||||
/** @implements ParserWidget */
|
||||
int WidgetFilesize(const struct Files *f, FILE *fp) { /* eww */
|
||||
if(!FilesIsDir(f)) fprintf(fp, " (%d KB)", FilesSize(f));
|
||||
return 0;
|
||||
}
|
||||
/** @implements ParserWidget */
|
||||
int WidgetNews(const struct Files *f, FILE *fp) {
|
||||
char buf[256], *bufpos;
|
||||
int i;
|
||||
size_t i;
|
||||
FILE *in;
|
||||
|
||||
UNUSED(f);
|
||||
if(!filenews[0]) 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);
|
||||
}
|
||||
if(fclose(in)) perror(filenews);
|
||||
return 0;
|
||||
}
|
||||
/** @implements ParserWidget */
|
||||
int WidgetNewsname(const struct Files *f, FILE *fp) {
|
||||
UNUSED(f);
|
||||
fprintf(fp, "%s", filenews);
|
||||
return 0;
|
||||
}
|
||||
/** @implements ParserWidget */
|
||||
int WidgetNow(const struct Files *f, FILE *fp) {
|
||||
char t[22];
|
||||
time_t currentTime;
|
||||
struct tm *formatedTime;
|
||||
|
||||
UNUSED(f);
|
||||
if((currentTime = time(0)) == (time_t)(-1)) { perror("@date"); return 0; }
|
||||
formatedTime = gmtime(¤tTime);
|
||||
/* 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);
|
||||
return 0;
|
||||
}
|
||||
/** @implements ParserWidget */
|
||||
int WidgetPwd(const struct Files *f, FILE *fp) {
|
||||
static int persistant = 0; /* ick, be very careful! */
|
||||
char *pwd;
|
||||
@ -205,6 +254,7 @@ int WidgetPwd(const struct Files *f, FILE *fp) {
|
||||
fprintf(fp, "%s", pwd);
|
||||
return -1;
|
||||
}
|
||||
/** @implements ParserWidget */
|
||||
int WidgetRoot(const struct Files *f, FILE *fp) {
|
||||
static int persistant = 0; /* ick, be very careful! */
|
||||
char *pwd;
|
||||
@ -214,12 +264,14 @@ int WidgetRoot(const struct Files *f, FILE *fp) {
|
||||
fprintf(fp, "%s", dirParent);
|
||||
return -1;
|
||||
}
|
||||
/** @implements ParserWidget */
|
||||
int WidgetTitle(const struct Files *f, FILE *fp) {
|
||||
UNUSED(f);
|
||||
fprintf(fp, "%s", title);
|
||||
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;
|
||||
else if(no > high) no = high;
|
||||
return no;
|
||||
|
Loading…
Reference in New Issue
Block a user