diff options
Diffstat (limited to 'app/tools/halibut/biblio.c')
-rw-r--r-- | app/tools/halibut/biblio.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/app/tools/halibut/biblio.c b/app/tools/halibut/biblio.c new file mode 100644 index 0000000..7ce163d --- /dev/null +++ b/app/tools/halibut/biblio.c @@ -0,0 +1,105 @@ +/* + * biblio.c: process the bibliography + */ + +#include <assert.h> +#include "halibut.h" + +static wchar_t *gentext(int num) { + wchar_t text[22]; + wchar_t *p = text + lenof(text); + *--p = L'\0'; + *--p = L']'; + while (num != 0) { + assert(p > text); + *--p = L"0123456789"[num % 10]; + num /= 10; + } + assert(p > text); + *--p = L'['; + return ustrdup(p); +} + +static void cite_biblio(keywordlist *kl, wchar_t *key, filepos fpos) { + keyword *kw = kw_lookup(kl, key); + if (!kw) + error(err_nosuchkw, &fpos, key); + else { + /* + * We've found a \k reference. If it's a + * bibliography entry ... + */ + if (kw->para->type == para_Biblio) { + /* + * ... then mark the paragraph as cited. + */ + kw->para->type = para_BiblioCited; + } + } +} + +/* + * Make a pass through the source form, generating citation formats + * for bibliography entries and also marking which bibliography + * entries are actually cited (or \nocite-ed). + */ + +void gen_citations(paragraph *source, keywordlist *kl) { + paragraph *para; + int bibnum = 0; + + for (para = source; para; para = para->next) { + word *ptr; + + /* + * \BR and \nocite paragraphs get special processing here. + */ + if (para->type == para_BR) { + keyword *kw = kw_lookup(kl, para->keyword); + if (!kw) { + error(err_nosuchkw, ¶->fpos, para->keyword); + } else if (kw->text) { + error(err_multiBR, ¶->fpos, para->keyword); + } else { + kw->text = dup_word_list(para->words); + } + } else if (para->type == para_NoCite) { + wchar_t *wp = para->keyword; + while (*wp) { + cite_biblio(kl, wp, para->fpos); + wp = uadv(wp); + } + } + + /* + * Scan for keyword references. + */ + for (ptr = para->words; ptr; ptr = ptr->next) { + if (ptr->type == word_UpperXref || + ptr->type == word_LowerXref) + cite_biblio(kl, ptr->text, ptr->fpos); + } + } + + /* + * We're now almost done; all that remains is to scan through + * the cited bibliography entries and invent default citation + * texts for the ones that don't already have explicitly + * provided \BR text. + */ + for (para = source; para; para = para->next) { + if (para->type == para_BiblioCited) { + keyword *kw = kw_lookup(kl, para->keyword); + assert(kw != NULL); + if (!kw->text) { + word *wd = smalloc(sizeof(word)); + wd->text = gentext(++bibnum); + wd->type = word_Normal; + wd->alt = NULL; + wd->next = NULL; + kw->text = wd; + } + para->kwtext = kw->text; + } + } +} |