commit 4bc4351c04a8771e402bdeae198a09a393e248e0
parent d8917c8a1ec08fa4149be14ff53255c29112f5f6
Author: Michael Skec
Date: Wed, 22 Nov 2023 17:44:42 +1100
footnotes: some cleanup
Diffstat:
M | broff.c | | | 116 | ++++++++++++++++++++++++++++++++++++++++++++++--------------------------------- |
1 file changed, 67 insertions(+), 49 deletions(-)
diff --git a/broff.c b/broff.c
@@ -53,6 +53,47 @@ static bool check_font(
static bool check_link(void);
static bool check_img(void);
+/* Create footnote node */
+static struct footnote *
+new_footnote(int capacity)
+{
+ struct footnote *fn = calloc(1, sizeof(*fn));
+ fn->content_cap = capacity;
+ fn->content = malloc(fn->content_cap);
+ fn->content[0] = '\0';
+ fn->content_length = 0;
+ fn->next = NULL;
+
+ /* Update list head/tail */
+ if (!fn_tail)
+ {
+ fn_tail = fn_head = fn;
+ }
+ else
+ {
+ fn_tail->next = fn;
+ fn_tail = fn;
+ }
+
+ return fn;
+}
+
+static void
+footnote_grow(struct footnote *fn, int capacity)
+{
+ if (capacity < fn->content_cap)
+ return;
+
+ fn->content_cap = (capacity * 3) / 2;
+ fn->content = realloc(fn->content, fn->content_cap);
+
+ if (!fn->content)
+ {
+ assert(0 && "out of memory");
+ exit(-1);
+ }
+}
+
static int
stream_printf(const char *restrict format, ...)
{
@@ -62,23 +103,18 @@ stream_printf(const char *restrict format, ...)
if (is_footnote)
{
- int needed;
- struct footnote *fn = fn_tail;
- assert(fn && "no footnotes generated yet");
+ struct footnote *fn;
va_start(args, format);
n = vsnprintf(NULL, 0, format, args);
va_end(args);
- needed = n + fn->content_length + 1;
+ if (fn_tail)
+ fn = fn_tail;
+ else
+ fn = new_footnote(n + 1);
- if (needed >= fn->content_cap)
- {
- /* grow */
- fn->content_cap = (needed * 3) / 2;
- fn->content = realloc(fn->content, fn->content_cap);
- assert(fn->content);
- }
+ footnote_grow(fn, n + fn->content_length + 1);
va_start(args, format);
n = vsnprintf(fn->content + fn->content_length,
@@ -104,21 +140,17 @@ stream_puts(const char *s)
/* If we are currently writing a footnote */
if (is_footnote)
{
- int n, needed;
- struct footnote *fn = fn_tail;
- assert(fn && "no footnotes generated yet");
+ int n;
+ struct footnote *fn;
n = strlen(s);
- needed = n + fn->content_length + 1;
+ if (fn_tail)
+ fn = fn_tail;
+ else
+ fn = new_footnote(n + 1);
- if (needed >= fn->content_cap)
- {
- /* grow */
- fn->content_cap = (needed * 3) / 2;
- fn->content = realloc(fn->content, fn->content_cap);
- assert(fn->content);
- }
+ footnote_grow(fn, n + fn->content_length + 1);
strncpy(fn->content + fn->content_length,
s,
@@ -261,13 +293,13 @@ print_escaped(const char *line, int l)
continue;
}
- /* roff supports auto-numbered footnotes via the \*[*] escape sequence,
- * which states where the footnote is to be placed, and will refer to
- * the "nearest" (i.e. subsequent) footnote written between .FS and
- * .FE. We don't care about manual numbering and hence don't currently
- * support it.
+ /* roff ms supports auto-numbered footnotes via the \** escape
+ * sequence, which states where the footnote is to be placed, and will
+ * refer to the "nearest" (i.e. subsequent) footnote written between
+ * .FS and .FE. We don't care about manual numbering and hence don't
+ * currently support it in any way.
*/
- static const char *const FOOTNOTE_ESC = "\\*[*]";
+ static const char *const FOOTNOTE_ESC = "\\**";
if (len_remain >= strlen(FOOTNOTE_ESC) &&
strncmp(c, FOOTNOTE_ESC, strlen(FOOTNOTE_ESC)) == 0)
{
@@ -632,37 +664,23 @@ main(int argc, char *argv[])
if (len >= strlen(".FS") &&
strncmp(line, ".FS", strlen(".FS")) == 0)
{
- // end_last_cmd(); /* don't end commands */
+ /* don't end any current commands as we return back to them after
+ * the footnote's .FE */
- /* store state before the footnote */
+ /* store the current state before the footnote */
cmd_fn = cmd;
is_sentence_fn = is_sentence;
+ /* We are now writing to footnote */
is_footnote = true;
- /* Create the footnote node */
- struct footnote *fn = calloc(1, sizeof(*fn));
- fn->content_cap = 512;
- fn->content = malloc(fn->content_cap);
- fn->content[0] = '\0';
- fn->content_length = 0;
- fn->next = NULL;
-
- /* Update list head/tail */
- if (!fn_tail)
- {
- fn_tail = fn_head = fn;
- }
- else
- {
- fn_tail->next = fn;
- fn_tail = fn;
- }
+ /* Create a new footnote */
+ new_footnote(256);
/* All output will now be written to the footnote tail's content
* until .FE is encountered. */
- /* Start a new paragraph in the footnote. */
+ /* Start a new sentence (and "paragraph"?) in the footnote. */
is_sentence = false;
continue;