d7482997 |
1 | /* |
2 | * biblio.c: process the bibliography |
3 | */ |
4 | |
5 | #include <assert.h> |
6 | #include "halibut.h" |
7 | |
8 | static wchar_t *gentext(int num) { |
9 | wchar_t text[22]; |
6e969fcf |
10 | wchar_t *p = text + lenof(text); |
d7482997 |
11 | *--p = L'\0'; |
12 | *--p = L']'; |
13 | while (num != 0) { |
14 | assert(p > text); |
15 | *--p = L"0123456789"[num % 10]; |
16 | num /= 10; |
17 | } |
18 | assert(p > text); |
19 | *--p = L'['; |
20 | return ustrdup(p); |
21 | } |
22 | |
23 | static void cite_biblio(keywordlist *kl, wchar_t *key, filepos fpos) { |
24 | keyword *kw = kw_lookup(kl, key); |
25 | if (!kw) |
26 | error(err_nosuchkw, &fpos, key); |
27 | else { |
28 | /* |
29 | * We've found a \k reference. If it's a |
30 | * bibliography entry ... |
31 | */ |
32 | if (kw->para->type == para_Biblio) { |
33 | /* |
34 | * ... then mark the paragraph as cited. |
35 | */ |
36 | kw->para->type = para_BiblioCited; |
37 | } |
38 | } |
39 | } |
40 | |
41 | /* |
42 | * Make a pass through the source form, generating citation formats |
43 | * for bibliography entries and also marking which bibliography |
44 | * entries are actually cited (or \nocite-ed). |
45 | */ |
46 | |
47 | void gen_citations(paragraph *source, keywordlist *kl) { |
48 | paragraph *para; |
49 | int bibnum = 0; |
50 | |
51 | for (para = source; para; para = para->next) { |
52 | word *ptr; |
53 | |
54 | /* |
55 | * \BR and \nocite paragraphs get special processing here. |
56 | */ |
57 | if (para->type == para_BR) { |
58 | keyword *kw = kw_lookup(kl, para->keyword); |
59 | if (!kw) { |
60 | error(err_nosuchkw, ¶->fpos, para->keyword); |
61 | } else if (kw->text) { |
62 | error(err_multiBR, ¶->fpos, para->keyword); |
63 | } else { |
64 | kw->text = dup_word_list(para->words); |
65 | } |
66 | } else if (para->type == para_NoCite) { |
67 | wchar_t *wp = para->keyword; |
68 | while (*wp) { |
69 | cite_biblio(kl, wp, para->fpos); |
70 | wp = uadv(wp); |
71 | } |
72 | } |
73 | |
74 | /* |
75 | * Scan for keyword references. |
76 | */ |
77 | for (ptr = para->words; ptr; ptr = ptr->next) { |
78 | if (ptr->type == word_UpperXref || |
79 | ptr->type == word_LowerXref) |
80 | cite_biblio(kl, ptr->text, ptr->fpos); |
81 | } |
82 | } |
83 | |
84 | /* |
85 | * We're now almost done; all that remains is to scan through |
86 | * the cited bibliography entries and invent default citation |
87 | * texts for the ones that don't already have explicitly |
88 | * provided \BR text. |
89 | */ |
90 | for (para = source; para; para = para->next) { |
91 | if (para->type == para_BiblioCited) { |
92 | keyword *kw = kw_lookup(kl, para->keyword); |
93 | assert(kw != NULL); |
94 | if (!kw->text) { |
95 | word *wd = smalloc(sizeof(word)); |
96 | wd->text = gentext(++bibnum); |
97 | wd->type = word_Normal; |
98 | wd->alt = NULL; |
99 | wd->next = NULL; |
100 | kw->text = wd; |
101 | } |
102 | para->kwtext = kw->text; |
103 | } |
104 | } |
105 | } |