1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
/*
* 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,
errorstate *es) {
keyword *kw = kw_lookup(kl, key);
if (!kw)
err_nosuchkw(es, &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, errorstate *es) {
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) {
err_nosuchkw(es, ¶->fpos, para->keyword);
} else if (kw->text) {
err_multiBR(es, ¶->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, es);
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, es);
}
}
/*
* 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->breaks = false;
wd->alt = NULL;
wd->next = NULL;
wd->aux = 0;
kw->text = wd;
}
para->kwtext = kw->text;
}
}
}
|