roff-like markup to HTML with additional niceties.
git clone git://git.skec.site/pub/broff.git
log | files | refs | readme | license

commit 4bc4351c04a8771e402bdeae198a09a393e248e0
parent d8917c8a1ec08fa4149be14ff53255c29112f5f6
Author: Michael Skec
Date:   Wed, 22 Nov 2023 17:44:42 +1100

footnotes: some cleanup

Diffstat:
Mbroff.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;