diff --git a/Docs/src/bin/halibut/bk_xhtml.c b/Docs/src/bin/halibut/bk_xhtml.c
index de874fcb..6f71f5a5 100644
--- a/Docs/src/bin/halibut/bk_xhtml.c
+++ b/Docs/src/bin/halibut/bk_xhtml.c
@@ -864,6 +864,7 @@ xhtml_backend(paragraph * sourceform, keywordlist * in_keywords,
sfree(conf.fsect[i].number_suffix);
sfree(conf.fsect);
}
+ free_ustr_slist(conf.meta_append);
}
static int xhtml_para_level(paragraph * p)
diff --git a/Docs/src/bin/halibut/halibut.h b/Docs/src/bin/halibut/halibut.h
index a0ab4c33..07abf19c 100644
--- a/Docs/src/bin/halibut/halibut.h
+++ b/Docs/src/bin/halibut/halibut.h
@@ -1,6 +1,10 @@
#ifndef HALIBUT_HALIBUT_H
#define HALIBUT_HALIBUT_H
+#ifdef _WIN32
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
#include
#include
#include
@@ -92,6 +96,7 @@ struct paragraph_Tag {
void *private_data; /* for temp use in backends */
};
+#define initpara(p) ( (p).type = para_NotParaType, (p).keyword = NULL, (p).words = NULL )
enum {
para_IM, /* index merge */
para_BR, /* bibliography rewrite */
@@ -232,6 +237,7 @@ void *smalloc(int size);
void *srealloc(void *p, int size);
void sfree(void *p);
#endif
+void free_list(void*p);
void free_word_list(word * w);
void free_para_list(paragraph * p);
word *dup_word_list(word * w);
@@ -256,11 +262,13 @@ wchar_t *ustrcpy(wchar_t * dest, const wchar_t * source);
wchar_t utolower(wchar_t);
int ustrcmp(const wchar_t * lhs, const wchar_t * rhs);
int ustricmp(const wchar_t * lhs, const wchar_t * rhs);
+void ultou(unsigned long v, wchar_t *o);
int utoi(const wchar_t *);
int utob(const wchar_t *);
int uisdigit(wchar_t);
wchar_t *ustrlow(wchar_t * s);
wchar_t *ustrftime(wchar_t * fmt, struct tm *timespec);
+#define free_ustr_slist free_list
ustr_slist* ustr_slist_append(ustr_slist**headaddr, const wchar_t*str);
/*
@@ -321,6 +329,7 @@ struct tagWrappedLine {
};
wrappedline *wrap_para(word *, int, int, int (*)(word *));
void wrap_free(wrappedline *);
+unsigned long getutcunixtime();
/*
* input.c
diff --git a/Docs/src/bin/halibut/input.c b/Docs/src/bin/halibut/input.c
index cca822e6..a4d1a149 100644
--- a/Docs/src/bin/halibut/input.c
+++ b/Docs/src/bin/halibut/input.c
@@ -175,12 +175,16 @@ enum {
tok_rbrace /* } */
};
+#define tokiscmd(t,c) ( (t).type == tok_cmd && (t).cmd == (c) )
+
/* Halibut command keywords. */
enum {
c__invalid, /* invalid command */
c__comment, /* comment command (\#) */
c__escaped, /* escaped character */
+ c__nop, /* no-op */
c__nbsp, /* nonbreaking space */
+ c__midparacmd_unixnow,
c_A, /* appendix heading */
c_B, /* bibliography entry */
c_BR, /* bibliography rewrite */
@@ -215,6 +219,13 @@ enum {
c_versionid /* document RCS id */
};
+#define getcmdstyle(c) \
+ (c) == c_c ? word_Code : \
+ (c) == c_cw ? word_WeakCode : \
+ (c) == c_e ? word_Emph : \
+ word_Normal
+
+
/* Perhaps whitespace should be defined in a more Unicode-friendly way? */
#define iswhite(c) ( (c)==32 || (c)==9 || (c)==13 || (c)==10 )
#define isnl(c) ( (c)==10 )
@@ -260,6 +271,7 @@ static void match_kw(token * tok)
{
"-", c__escaped}
, /* nonbreaking hyphen */
+ { ".", c__nop },
{
"A", c_A}
, /* appendix heading */
@@ -326,6 +338,7 @@ static void match_kw(token * tok)
{
"e", c_e}
, /* emphasis */
+ { "hackunixnow", c__midparacmd_unixnow },
{
"i", c_i}
, /* visible index mark */
@@ -474,7 +487,7 @@ token get_token(input * in)
{ /* tok_cmd */
c = get(in, &cpos);
if (c == '-' || c == '\\' || c == '_' ||
- c == '#' || c == '{' || c == '}')
+ c == '#' || c == '{' || c == '}' || c == '.')
{
/* single-char command */
rdadd(&rs, (wchar_t)c);
@@ -635,6 +648,36 @@ static paragraph *addpara(paragraph newpara, paragraph *** hptrptr)
*/
#define dtor(t) ( sfree(t.text) )
+static int is_special_midpara_cmd(token*t)
+{
+ return tokiscmd(*t, c__midparacmd_unixnow);
+}
+
+static int handle_special_midpara_cmd(token*t, rdstring*rs, paragraph ***hptrptr)
+{
+ wchar_t wbuf[100];
+ paragraph par;
+
+ if (t->type != tok_cmd) return 0;
+ initpara(par);
+ par.fpos = t->pos;
+ switch(t->cmd)
+ {
+ case c__midparacmd_unixnow:
+ ultou(getutcunixtime(), wbuf);
+ rdadds(rs, wbuf);
+ return 1;
+ }
+ return 0;
+}
+
+#define stack_item_push(stck__, sitype__) do { \
+ struct stack_item *si__ = mknew(struct stack_item); \
+ si__->type = sitype__; \
+ stk_push((stck__), si__); \
+ } while(!__LINE__)
+
+
/*
* Reads a single file (ie until get() returns EOF)
*/
@@ -644,7 +687,7 @@ static void read_file(paragraph *** ret, input * in, indexdata * idx, tree234 *m
paragraph par;
word wd, **whptr, **idximplicit;
wchar_t utext[2], *wdtext;
- int style, spcstyle;
+ int style, spcstyle, tmpstyle;
int already;
int iswhite, seenwhite;
int type;
@@ -883,12 +926,14 @@ static void read_file(paragraph *** ret, input * in, indexdata * idx, tree234 *m
t.type == tok_word ||
t.type == tok_white ||
(t.type == tok_cmd && t.cmd == c__nbsp) ||
- (t.type == tok_cmd && t.cmd == c__escaped))
+ (t.type == tok_cmd && t.cmd == c__escaped) ||
+ /* TODO: Merge from upstream?: (t.type == tok_cmd && t.cmd == c_u) || */
+ is_special_midpara_cmd(&t))
{
if (t.type == tok_white ||
(t.type == tok_cmd && t.cmd == c__nbsp))
rdadd(&rs, ' ');
- else
+ else if (!handle_special_midpara_cmd(&t, &rs, ret))
rdadds(&rs, t.text);
}
if (t.type != tok_rbrace)
@@ -994,6 +1039,10 @@ static void read_file(paragraph *** ret, input * in, indexdata * idx, tree234 *m
break;
}
+ if (t.type == tok_cmd && t.cmd == c__nop) {
+ dtor(t), t = get_token(in);
+ continue; /* do nothing! */
+ }
if (t.type == tok_cmd && t.cmd == c__escaped)
{
t.type = tok_word; /* nice and simple */
@@ -1283,15 +1332,13 @@ static void read_file(paragraph *** ret, input * in, indexdata * idx, tree234 *m
*/
sitem = mknew(struct stack_item);
sitem->type = stack_hyper;
- if (t.type == tok_cmd &&
- (t.cmd == c_e || t.cmd == c_c || t.cmd == c_cw))
+ if (t.type == tok_cmd && (tmpstyle = getcmdstyle(t.cmd)))
{
if (style != word_Normal)
error(err_nestedstyles, &t.pos);
else
{
- style = (t.cmd == c_c ? word_Code :
- t.cmd == c_cw ? word_WeakCode : word_Emph);
+ style = tmpstyle;
spcstyle = tospacestyle(style);
sitem->type |= stack_style;
}
@@ -1326,8 +1373,7 @@ static void read_file(paragraph *** ret, input * in, indexdata * idx, tree234 *m
error(err_explbr, &t.pos);
} else
{
- style = (type == c_c ? word_Code :
- type == c_cw ? word_WeakCode : word_Emph);
+ style = getcmdstyle(type);
spcstyle = tospacestyle(style);
sitem = mknew(struct stack_item);
sitem->type = stack_style;
@@ -1354,15 +1400,13 @@ static void read_file(paragraph *** ret, input * in, indexdata * idx, tree234 *m
* Special cases: \i\c, \i\e, \i\cw
*/
wd.fpos = t.pos;
- if (t.type == tok_cmd &&
- (t.cmd == c_e || t.cmd == c_c || t.cmd == c_cw))
+ if (t.type == tok_cmd && (tmpstyle = getcmdstyle(t.cmd)))
{
if (style != word_Normal)
error(err_nestedstyles, &t.pos);
else
{
- style = (t.cmd == c_c ? word_Code :
- t.cmd == c_cw ? word_WeakCode : word_Emph);
+ style = tmpstyle;
spcstyle = tospacestyle(style);
sitem->type |= stack_style;
}
diff --git a/Docs/src/bin/halibut/main.c b/Docs/src/bin/halibut/main.c
index 2b413d9e..a80c0417 100644
--- a/Docs/src/bin/halibut/main.c
+++ b/Docs/src/bin/halibut/main.c
@@ -20,6 +20,9 @@ int main(int argc, char **argv)
int errs;
int reportcols;
int debug;
+#ifdef C_ASSERT
+ { C_ASSERT(!word_Normal); /* For getcmdstyle */ }
+#endif
initversionstring();
diff --git a/Docs/src/bin/halibut/malloc.c b/Docs/src/bin/halibut/malloc.c
index 24cb6765..90ee658d 100644
--- a/Docs/src/bin/halibut/malloc.c
+++ b/Docs/src/bin/halibut/malloc.c
@@ -129,6 +129,20 @@ word *dup_word_list(word * w)
return head;
}
+/*
+ * Free a generic linked list
+ */
+void free_list(void*p)
+{
+ void *s = p, *n;
+ for (; p; p = n)
+ {
+ n = *(void**) p; /* Assmumes next pointer is the first member! */
+ if (n == s) n = NULL; /* Around the ring? */
+ sfree(p);
+ }
+}
+
/*
* Free a linked list of words
*/
diff --git a/Docs/src/bin/halibut/misc.c b/Docs/src/bin/halibut/misc.c
index 5fad528d..83d4ba78 100644
--- a/Docs/src/bin/halibut/misc.c
+++ b/Docs/src/bin/halibut/misc.c
@@ -2,6 +2,7 @@
* misc.c: miscellaneous useful items
*/
#include
+#include
#include "halibut.h"
struct stackTag {
@@ -355,3 +356,21 @@ void wrap_free(wrappedline * w)
w = t;
}
}
+
+unsigned long getutcunixtime()
+{
+#ifndef _WIN32
+ struct timespec ts;
+ ts.tv_sec = 0;
+ /* gettimeofday()? */
+#if (_XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 199309L)
+ if (0 == clock_gettime(CLOCK_REALTIME, &ts))
+ return ts.tv_sec;
+#endif
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+ if (timespec_get(&ts, TIME_UTC)) /* implementation defined epoch :( */
+ return ts.tv_sec;
+#endif
+#endif /*~ _WIN32 */
+ return (unsigned long) time(NULL);
+}
diff --git a/Docs/src/bin/halibut/ustring.c b/Docs/src/bin/halibut/ustring.c
index b4e0a050..63c68dbd 100644
--- a/Docs/src/bin/halibut/ustring.c
+++ b/Docs/src/bin/halibut/ustring.c
@@ -2,9 +2,17 @@
* ustring.c: Unicode string routines
*/
+#include "halibut.h"
#include
#include
-#include "halibut.h"
+#include
+
+static void asciitou(wchar_t *dest, const char *src)
+{
+ for (;;)
+ if (!(*dest++ = *src++))
+ break;
+}
wchar_t *ustrdup(const wchar_t * s)
{
@@ -119,6 +127,13 @@ wchar_t *ustrlow(wchar_t * s)
return s;
}
+void ultou(unsigned long v, wchar_t *o)
+{
+ char buf[42];
+ sprintf(buf, "%lu", v);
+ asciitou(o, buf);
+}
+
int utoi(const wchar_t *s)
{
int sign = +1;
diff --git a/Docs/src/config_web.but b/Docs/src/config_web.but
index c9d7555f..bed94434 100644
--- a/Docs/src/config_web.but
+++ b/Docs/src/config_web.but
@@ -11,6 +11,6 @@
\cfg{xhtml-contents-depth-0}{3}
-\cfg{xhtml-head-end}{}
+\cfg{xhtml-head-end}{}
\cfg{xhtml-body-end}{
}
diff --git a/Docs/unreleased.png b/Docs/unreleased.png
index f3d4a719..3e61a975 100644
Binary files a/Docs/unreleased.png and b/Docs/unreleased.png differ