Hopefully readable now: indent -nut -kr -bl -bli0 -i2 *
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@2423 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
e1bc9f0971
commit
0e30afb5d9
16 changed files with 6231 additions and 5689 deletions
|
@ -7,37 +7,40 @@
|
|||
|
||||
static wchar_t *gentext(int num)
|
||||
{
|
||||
wchar_t text[22];
|
||||
wchar_t *p = text + sizeof(text);
|
||||
*--p = L'\0';
|
||||
*--p = L']';
|
||||
while (num != 0) {
|
||||
assert(p > text);
|
||||
*--p = L"0123456789"[num % 10];
|
||||
num /= 10;
|
||||
}
|
||||
wchar_t text[22];
|
||||
wchar_t *p = text + sizeof(text);
|
||||
*--p = L'\0';
|
||||
*--p = L']';
|
||||
while (num != 0)
|
||||
{
|
||||
assert(p > text);
|
||||
*--p = L'[';
|
||||
return ustrdup(p);
|
||||
*--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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -48,60 +51,72 @@ static void cite_biblio(keywordlist * kl, wchar_t * key, filepos fpos)
|
|||
|
||||
void gen_citations(paragraph * source, keywordlist * kl)
|
||||
{
|
||||
paragraph *para;
|
||||
int bibnum = 0;
|
||||
paragraph *para;
|
||||
int bibnum = 0;
|
||||
|
||||
for (para = source; para; para = para->next) {
|
||||
word *ptr;
|
||||
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 || ptr->type == word_FreeTextXref)
|
||||
cite_biblio(kl, ptr->text, ptr->fpos);
|
||||
}
|
||||
/*
|
||||
* \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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* Scan for keyword references.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
for (ptr = para->words; ptr; ptr = ptr->next)
|
||||
{
|
||||
if (ptr->type == word_UpperXref || ptr->type == word_LowerXref
|
||||
|| ptr->type == word_FreeTextXref)
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,223 +9,238 @@
|
|||
#include "halibut.h"
|
||||
|
||||
struct numberstate_Tag {
|
||||
int chapternum;
|
||||
int appendixnum;
|
||||
int ischapter;
|
||||
int *sectionlevels;
|
||||
paragraph **currentsects;
|
||||
paragraph *lastsect;
|
||||
int oklevel;
|
||||
int maxsectlevel;
|
||||
int listitem;
|
||||
wchar_t *chaptertext; /* the word for a chapter */
|
||||
wchar_t *sectiontext; /* the word for a section */
|
||||
wchar_t *apptext; /* the word for an appendix */
|
||||
int chapternum;
|
||||
int appendixnum;
|
||||
int ischapter;
|
||||
int *sectionlevels;
|
||||
paragraph **currentsects;
|
||||
paragraph *lastsect;
|
||||
int oklevel;
|
||||
int maxsectlevel;
|
||||
int listitem;
|
||||
wchar_t *chaptertext; /* the word for a chapter */
|
||||
wchar_t *sectiontext; /* the word for a section */
|
||||
wchar_t *apptext; /* the word for an appendix */
|
||||
};
|
||||
|
||||
numberstate *number_init(void)
|
||||
{
|
||||
numberstate *ret = mknew(numberstate);
|
||||
ret->chapternum = 0;
|
||||
ret->appendixnum = -1;
|
||||
ret->ischapter = 1;
|
||||
ret->oklevel = -1; /* not even in a chapter yet */
|
||||
ret->maxsectlevel = 32;
|
||||
ret->sectionlevels = mknewa(int, ret->maxsectlevel);
|
||||
ret->currentsects = mknewa(paragraph *, ret->maxsectlevel + 1);
|
||||
memset(ret->currentsects, 0,
|
||||
(ret->maxsectlevel + 1) * sizeof(paragraph *));
|
||||
ret->lastsect = NULL;
|
||||
ret->listitem = -1;
|
||||
return ret;
|
||||
numberstate *ret = mknew(numberstate);
|
||||
ret->chapternum = 0;
|
||||
ret->appendixnum = -1;
|
||||
ret->ischapter = 1;
|
||||
ret->oklevel = -1; /* not even in a chapter yet */
|
||||
ret->maxsectlevel = 32;
|
||||
ret->sectionlevels = mknewa(int, ret->maxsectlevel);
|
||||
ret->currentsects = mknewa(paragraph *, ret->maxsectlevel + 1);
|
||||
memset(ret->currentsects, 0,
|
||||
(ret->maxsectlevel + 1) * sizeof(paragraph *));
|
||||
ret->lastsect = NULL;
|
||||
ret->listitem = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void number_free(numberstate * state)
|
||||
{
|
||||
sfree(state->sectionlevels);
|
||||
sfree(state->currentsects);
|
||||
sfree(state);
|
||||
sfree(state->sectionlevels);
|
||||
sfree(state->currentsects);
|
||||
sfree(state);
|
||||
}
|
||||
|
||||
static void dotext(word *** wret, wchar_t * text)
|
||||
{
|
||||
word *mnewword = mknew(word);
|
||||
mnewword->text = ustrdup(text);
|
||||
mnewword->type = word_Normal;
|
||||
mnewword->alt = NULL;
|
||||
mnewword->next = NULL;
|
||||
**wret = mnewword;
|
||||
*wret = &mnewword->next;
|
||||
word *mnewword = mknew(word);
|
||||
mnewword->text = ustrdup(text);
|
||||
mnewword->type = word_Normal;
|
||||
mnewword->alt = NULL;
|
||||
mnewword->next = NULL;
|
||||
**wret = mnewword;
|
||||
*wret = &mnewword->next;
|
||||
}
|
||||
|
||||
static void dospace(word *** wret)
|
||||
{
|
||||
word *mnewword = mknew(word);
|
||||
mnewword->text = NULL;
|
||||
mnewword->type = word_WhiteSpace;
|
||||
mnewword->alt = NULL;
|
||||
mnewword->next = NULL;
|
||||
**wret = mnewword;
|
||||
*wret = &mnewword->next;
|
||||
word *mnewword = mknew(word);
|
||||
mnewword->text = NULL;
|
||||
mnewword->type = word_WhiteSpace;
|
||||
mnewword->alt = NULL;
|
||||
mnewword->next = NULL;
|
||||
**wret = mnewword;
|
||||
*wret = &mnewword->next;
|
||||
}
|
||||
|
||||
static void donumber(word *** wret, int num)
|
||||
{
|
||||
wchar_t text[20];
|
||||
wchar_t *p = text + sizeof(text);
|
||||
*--p = L'\0';
|
||||
while (num != 0) {
|
||||
assert(p > text);
|
||||
*--p = L"0123456789"[num % 10];
|
||||
num /= 10;
|
||||
}
|
||||
dotext(wret, p);
|
||||
wchar_t text[20];
|
||||
wchar_t *p = text + sizeof(text);
|
||||
*--p = L'\0';
|
||||
while (num != 0)
|
||||
{
|
||||
assert(p > text);
|
||||
*--p = L"0123456789"[num % 10];
|
||||
num /= 10;
|
||||
}
|
||||
dotext(wret, p);
|
||||
}
|
||||
|
||||
static void doanumber(word *** wret, int num)
|
||||
{
|
||||
wchar_t text[20];
|
||||
wchar_t *p;
|
||||
int nletters, aton;
|
||||
nletters = 1;
|
||||
aton = 25;
|
||||
while (num > aton) {
|
||||
nletters++;
|
||||
num -= aton + 1;
|
||||
if (aton < INT_MAX / 26)
|
||||
aton = (aton + 1) * 26 - 1;
|
||||
else
|
||||
aton = INT_MAX;
|
||||
}
|
||||
p = text + sizeof(text);
|
||||
*--p = L'\0';
|
||||
while (nletters--) {
|
||||
assert(p > text);
|
||||
*--p = L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[num % 26];
|
||||
num /= 26;
|
||||
}
|
||||
dotext(wret, p);
|
||||
wchar_t text[20];
|
||||
wchar_t *p;
|
||||
int nletters, aton;
|
||||
nletters = 1;
|
||||
aton = 25;
|
||||
while (num > aton)
|
||||
{
|
||||
nletters++;
|
||||
num -= aton + 1;
|
||||
if (aton < INT_MAX / 26)
|
||||
aton = (aton + 1) * 26 - 1;
|
||||
else
|
||||
aton = INT_MAX;
|
||||
}
|
||||
p = text + sizeof(text);
|
||||
*--p = L'\0';
|
||||
while (nletters--)
|
||||
{
|
||||
assert(p > text);
|
||||
*--p = L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[num % 26];
|
||||
num /= 26;
|
||||
}
|
||||
dotext(wret, p);
|
||||
}
|
||||
|
||||
void number_cfg(numberstate * state, paragraph * source)
|
||||
{
|
||||
/*
|
||||
* Defaults
|
||||
*/
|
||||
state->chaptertext = L"Chapter";
|
||||
state->sectiontext = L"Section";
|
||||
state->apptext = L"Appendix";
|
||||
/*
|
||||
* Defaults
|
||||
*/
|
||||
state->chaptertext = L"Chapter";
|
||||
state->sectiontext = L"Section";
|
||||
state->apptext = L"Appendix";
|
||||
|
||||
for (; source; source = source->next) {
|
||||
if (source->type == para_Config) {
|
||||
if (!ustricmp(source->keyword, L"chapter")) {
|
||||
state->chaptertext = uadv(source->keyword);
|
||||
} else if (!ustricmp(source->keyword, L"section")) {
|
||||
state->sectiontext = uadv(source->keyword);
|
||||
} else if (!ustricmp(source->keyword, L"appendix")) {
|
||||
state->apptext = uadv(source->keyword);
|
||||
}
|
||||
}
|
||||
for (; source; source = source->next)
|
||||
{
|
||||
if (source->type == para_Config)
|
||||
{
|
||||
if (!ustricmp(source->keyword, L"chapter"))
|
||||
{
|
||||
state->chaptertext = uadv(source->keyword);
|
||||
} else if (!ustricmp(source->keyword, L"section"))
|
||||
{
|
||||
state->sectiontext = uadv(source->keyword);
|
||||
} else if (!ustricmp(source->keyword, L"appendix"))
|
||||
{
|
||||
state->apptext = uadv(source->keyword);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
word *number_mktext(numberstate * state, paragraph * p, wchar_t * category,
|
||||
int prev, int *errflag)
|
||||
int prev, int *errflag)
|
||||
{
|
||||
word *ret = NULL;
|
||||
word **ret2 = &ret;
|
||||
word **pret = &ret;
|
||||
int i, level;
|
||||
word *ret = NULL;
|
||||
word **ret2 = &ret;
|
||||
word **pret = &ret;
|
||||
int i, level;
|
||||
|
||||
level = -2; /* default for non-section-heading */
|
||||
switch (p->type) {
|
||||
case para_Chapter:
|
||||
state->chapternum++;
|
||||
for (i = 0; i < state->maxsectlevel; i++)
|
||||
state->sectionlevels[i] = 0;
|
||||
dotext(&pret, category ? category : state->chaptertext);
|
||||
dospace(&pret);
|
||||
ret2 = pret;
|
||||
donumber(&pret, state->chapternum);
|
||||
state->ischapter = 1;
|
||||
state->oklevel = 0;
|
||||
level = -1;
|
||||
break;
|
||||
case para_Heading:
|
||||
case para_Subsect:
|
||||
level = (p->type == para_Heading ? 0 : p->aux);
|
||||
if (level > state->oklevel) {
|
||||
error(err_sectjump, &p->fpos);
|
||||
*errflag = TRUE;
|
||||
ret = NULL;
|
||||
break;
|
||||
}
|
||||
state->oklevel = level + 1;
|
||||
if (state->maxsectlevel <= level) {
|
||||
state->maxsectlevel = level + 32;
|
||||
state->sectionlevels = resize(state->sectionlevels,
|
||||
state->maxsectlevel);
|
||||
}
|
||||
state->sectionlevels[level]++;
|
||||
for (i = level + 1; i < state->maxsectlevel; i++)
|
||||
state->sectionlevels[i] = 0;
|
||||
dotext(&pret, category ? category : state->sectiontext);
|
||||
dospace(&pret);
|
||||
ret2 = pret;
|
||||
if (state->ischapter)
|
||||
donumber(&pret, state->chapternum);
|
||||
else
|
||||
doanumber(&pret, state->appendixnum);
|
||||
for (i = 0; i <= level; i++) {
|
||||
dotext(&pret, L".");
|
||||
if (state->sectionlevels[i] == 0)
|
||||
state->sectionlevels[i] = 1;
|
||||
donumber(&pret, state->sectionlevels[i]);
|
||||
}
|
||||
break;
|
||||
case para_Appendix:
|
||||
state->appendixnum++;
|
||||
for (i = 0; i < state->maxsectlevel; i++)
|
||||
state->sectionlevels[i] = 0;
|
||||
dotext(&pret, category ? category : state->apptext);
|
||||
dospace(&pret);
|
||||
ret2 = pret;
|
||||
doanumber(&pret, state->appendixnum);
|
||||
state->ischapter = 0;
|
||||
state->oklevel = 0;
|
||||
level = -1;
|
||||
break;
|
||||
case para_UnnumberedChapter:
|
||||
level = -1;
|
||||
break;
|
||||
case para_NumberedList:
|
||||
ret2 = pret;
|
||||
if (prev != para_NumberedList)
|
||||
state->listitem = 0;
|
||||
state->listitem++;
|
||||
donumber(&pret, state->listitem);
|
||||
break;
|
||||
level = -2; /* default for non-section-heading */
|
||||
switch (p->type)
|
||||
{
|
||||
case para_Chapter:
|
||||
state->chapternum++;
|
||||
for (i = 0; i < state->maxsectlevel; i++)
|
||||
state->sectionlevels[i] = 0;
|
||||
dotext(&pret, category ? category : state->chaptertext);
|
||||
dospace(&pret);
|
||||
ret2 = pret;
|
||||
donumber(&pret, state->chapternum);
|
||||
state->ischapter = 1;
|
||||
state->oklevel = 0;
|
||||
level = -1;
|
||||
break;
|
||||
case para_Heading:
|
||||
case para_Subsect:
|
||||
level = (p->type == para_Heading ? 0 : p->aux);
|
||||
if (level > state->oklevel)
|
||||
{
|
||||
error(err_sectjump, &p->fpos);
|
||||
*errflag = TRUE;
|
||||
ret = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now set up parent, child and sibling links.
|
||||
*/
|
||||
p->parent = p->child = p->sibling = NULL;
|
||||
if (level != -2) {
|
||||
if (state->currentsects[level + 1])
|
||||
state->currentsects[level + 1]->sibling = p;
|
||||
if (level >= 0 && state->currentsects[level]) {
|
||||
p->parent = state->currentsects[level];
|
||||
if (!state->currentsects[level]->child)
|
||||
state->currentsects[level]->child = p;
|
||||
}
|
||||
state->currentsects[level + 1] = state->lastsect = p;
|
||||
for (i = level + 2; i < state->maxsectlevel + 1; i++)
|
||||
state->currentsects[i] = NULL;
|
||||
} else {
|
||||
p->parent = state->lastsect;
|
||||
state->oklevel = level + 1;
|
||||
if (state->maxsectlevel <= level)
|
||||
{
|
||||
state->maxsectlevel = level + 32;
|
||||
state->sectionlevels = resize(state->sectionlevels,
|
||||
state->maxsectlevel);
|
||||
}
|
||||
state->sectionlevels[level]++;
|
||||
for (i = level + 1; i < state->maxsectlevel; i++)
|
||||
state->sectionlevels[i] = 0;
|
||||
dotext(&pret, category ? category : state->sectiontext);
|
||||
dospace(&pret);
|
||||
ret2 = pret;
|
||||
if (state->ischapter)
|
||||
donumber(&pret, state->chapternum);
|
||||
else
|
||||
doanumber(&pret, state->appendixnum);
|
||||
for (i = 0; i <= level; i++)
|
||||
{
|
||||
dotext(&pret, L".");
|
||||
if (state->sectionlevels[i] == 0)
|
||||
state->sectionlevels[i] = 1;
|
||||
donumber(&pret, state->sectionlevels[i]);
|
||||
}
|
||||
break;
|
||||
case para_Appendix:
|
||||
state->appendixnum++;
|
||||
for (i = 0; i < state->maxsectlevel; i++)
|
||||
state->sectionlevels[i] = 0;
|
||||
dotext(&pret, category ? category : state->apptext);
|
||||
dospace(&pret);
|
||||
ret2 = pret;
|
||||
doanumber(&pret, state->appendixnum);
|
||||
state->ischapter = 0;
|
||||
state->oklevel = 0;
|
||||
level = -1;
|
||||
break;
|
||||
case para_UnnumberedChapter:
|
||||
level = -1;
|
||||
break;
|
||||
case para_NumberedList:
|
||||
ret2 = pret;
|
||||
if (prev != para_NumberedList)
|
||||
state->listitem = 0;
|
||||
state->listitem++;
|
||||
donumber(&pret, state->listitem);
|
||||
break;
|
||||
}
|
||||
|
||||
p->kwtext2 = *ret2;
|
||||
return ret;
|
||||
/*
|
||||
* Now set up parent, child and sibling links.
|
||||
*/
|
||||
p->parent = p->child = p->sibling = NULL;
|
||||
if (level != -2)
|
||||
{
|
||||
if (state->currentsects[level + 1])
|
||||
state->currentsects[level + 1]->sibling = p;
|
||||
if (level >= 0 && state->currentsects[level])
|
||||
{
|
||||
p->parent = state->currentsects[level];
|
||||
if (!state->currentsects[level]->child)
|
||||
state->currentsects[level]->child = p;
|
||||
}
|
||||
state->currentsects[level + 1] = state->lastsect = p;
|
||||
for (i = level + 2; i < state->maxsectlevel + 1; i++)
|
||||
state->currentsects[i] = NULL;
|
||||
} else
|
||||
{
|
||||
p->parent = state->lastsect;
|
||||
}
|
||||
|
||||
p->kwtext2 = *ret2;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -10,217 +10,215 @@
|
|||
/*
|
||||
* Error flags
|
||||
*/
|
||||
#define PREFIX 0x0001 /* give `halibut:' prefix */
|
||||
#define FILEPOS 0x0002 /* give file position prefix */
|
||||
#define PREFIX 0x0001 /* give `halibut:' prefix */
|
||||
#define FILEPOS 0x0002 /* give file position prefix */
|
||||
|
||||
static void do_error(int code, va_list ap)
|
||||
{
|
||||
char error[1024];
|
||||
char auxbuf[256];
|
||||
char *sp, *sp2;
|
||||
wchar_t *wsp;
|
||||
filepos fpos, fpos2;
|
||||
int flags;
|
||||
char error[1024];
|
||||
char auxbuf[256];
|
||||
char *sp, *sp2;
|
||||
wchar_t *wsp;
|
||||
filepos fpos, fpos2;
|
||||
int flags;
|
||||
|
||||
switch (code) {
|
||||
case err_nomemory: /* no arguments */
|
||||
sprintf(error, "out of memory");
|
||||
flags = PREFIX;
|
||||
break;
|
||||
case err_optnoarg:
|
||||
sp = va_arg(ap, char *);
|
||||
sprintf(error, "option `-%.200s' requires an argument", sp);
|
||||
flags = PREFIX;
|
||||
break;
|
||||
case err_nosuchopt:
|
||||
sp = va_arg(ap, char *);
|
||||
sprintf(error, "unrecognised option `-%.200s'", sp);
|
||||
flags = PREFIX;
|
||||
break;
|
||||
case err_noinput: /* no arguments */
|
||||
sprintf(error, "no input files");
|
||||
flags = PREFIX;
|
||||
break;
|
||||
case err_cantopen:
|
||||
sp = va_arg(ap, char *);
|
||||
sprintf(error, "unable to open input file `%.200s'", sp);
|
||||
flags = PREFIX;
|
||||
break;
|
||||
case err_nodata: /* no arguments */
|
||||
sprintf(error, "no data in input files");
|
||||
flags = PREFIX;
|
||||
break;
|
||||
case err_brokencodepara:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error,
|
||||
"every line of a code paragraph should begin `\\c'");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_kwunclosed:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected `}' after paragraph keyword");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_kwexpected:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected a paragraph keyword");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_kwillegal:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected no paragraph keyword");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_kwtoomany:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected only one paragraph keyword");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_bodyillegal:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected no text after paragraph keyword");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_badparatype:
|
||||
wsp = va_arg(ap, wchar_t *);
|
||||
sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "command `%.200s' unrecognised at start of"
|
||||
" paragraph", sp);
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_badmidcmd:
|
||||
wsp = va_arg(ap, wchar_t *);
|
||||
sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "command `%.200s' unexpected in mid-paragraph", sp);
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_unexbrace:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "brace character unexpected in mid-paragraph");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_explbr:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected `{' after command");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_commenteof:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "end of file unexpected inside `\\#{...}' comment");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_kwexprbr:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected `}' after cross-reference");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_missingrbrace:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "unclosed braces at end of paragraph");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_nestedstyles:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "unable to nest text styles");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_nestedindex:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "unable to nest index markings");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_nosuchkw:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
wsp = va_arg(ap, wchar_t *);
|
||||
sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
|
||||
sprintf(error, "unable to resolve cross-reference to `%.200s'",
|
||||
sp);
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_multiBR:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
wsp = va_arg(ap, wchar_t *);
|
||||
sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
|
||||
sprintf(error, "multiple `\\BR' entries given for `%.200s'", sp);
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_nosuchidxtag:
|
||||
wsp = va_arg(ap, wchar_t *);
|
||||
sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
|
||||
sprintf(error, "`\\IM' on unknown index tag `%.200s'", sp);
|
||||
flags = 0;
|
||||
/* FIXME: need to get a filepos to here somehow */
|
||||
break;
|
||||
case err_cantopenw:
|
||||
sp = va_arg(ap, char *);
|
||||
sprintf(error, "unable to open output file `%.200s'", sp);
|
||||
flags = PREFIX;
|
||||
break;
|
||||
case err_macroexists:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
wsp = va_arg(ap, wchar_t *);
|
||||
sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
|
||||
sprintf(error, "macro `%.200s' already defined", sp);
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_sectjump:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected higher heading levels before this one");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_winhelp_ctxclash:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sp = va_arg(ap, char *);
|
||||
sp2 = va_arg(ap, char *);
|
||||
sprintf(error, "Windows Help context id `%.200s' clashes with "
|
||||
"previously defined `%.200s'", sp, sp2);
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_multikw:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
fpos2 = *va_arg(ap, filepos *);
|
||||
wsp = va_arg(ap, wchar_t *);
|
||||
sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
|
||||
sprintf(error, "paragraph keyword `%.200s' already defined at ",
|
||||
sp);
|
||||
sprintf(error + strlen(error), "%s:%d", fpos2.filename,
|
||||
fpos2.line);
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_whatever:
|
||||
sp = va_arg(ap, char *);
|
||||
vsprintf(error, sp, ap);
|
||||
flags = PREFIX;
|
||||
break;
|
||||
}
|
||||
switch (code)
|
||||
{
|
||||
case err_nomemory: /* no arguments */
|
||||
sprintf(error, "out of memory");
|
||||
flags = PREFIX;
|
||||
break;
|
||||
case err_optnoarg:
|
||||
sp = va_arg(ap, char *);
|
||||
sprintf(error, "option `-%.200s' requires an argument", sp);
|
||||
flags = PREFIX;
|
||||
break;
|
||||
case err_nosuchopt:
|
||||
sp = va_arg(ap, char *);
|
||||
sprintf(error, "unrecognised option `-%.200s'", sp);
|
||||
flags = PREFIX;
|
||||
break;
|
||||
case err_noinput: /* no arguments */
|
||||
sprintf(error, "no input files");
|
||||
flags = PREFIX;
|
||||
break;
|
||||
case err_cantopen:
|
||||
sp = va_arg(ap, char *);
|
||||
sprintf(error, "unable to open input file `%.200s'", sp);
|
||||
flags = PREFIX;
|
||||
break;
|
||||
case err_nodata: /* no arguments */
|
||||
sprintf(error, "no data in input files");
|
||||
flags = PREFIX;
|
||||
break;
|
||||
case err_brokencodepara:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "every line of a code paragraph should begin `\\c'");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_kwunclosed:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected `}' after paragraph keyword");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_kwexpected:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected a paragraph keyword");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_kwillegal:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected no paragraph keyword");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_kwtoomany:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected only one paragraph keyword");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_bodyillegal:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected no text after paragraph keyword");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_badparatype:
|
||||
wsp = va_arg(ap, wchar_t *);
|
||||
sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "command `%.200s' unrecognised at start of"
|
||||
" paragraph", sp);
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_badmidcmd:
|
||||
wsp = va_arg(ap, wchar_t *);
|
||||
sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "command `%.200s' unexpected in mid-paragraph", sp);
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_unexbrace:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "brace character unexpected in mid-paragraph");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_explbr:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected `{' after command");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_commenteof:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "end of file unexpected inside `\\#{...}' comment");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_kwexprbr:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected `}' after cross-reference");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_missingrbrace:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "unclosed braces at end of paragraph");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_nestedstyles:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "unable to nest text styles");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_nestedindex:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "unable to nest index markings");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_nosuchkw:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
wsp = va_arg(ap, wchar_t *);
|
||||
sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
|
||||
sprintf(error, "unable to resolve cross-reference to `%.200s'", sp);
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_multiBR:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
wsp = va_arg(ap, wchar_t *);
|
||||
sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
|
||||
sprintf(error, "multiple `\\BR' entries given for `%.200s'", sp);
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_nosuchidxtag:
|
||||
wsp = va_arg(ap, wchar_t *);
|
||||
sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
|
||||
sprintf(error, "`\\IM' on unknown index tag `%.200s'", sp);
|
||||
flags = 0;
|
||||
/* FIXME: need to get a filepos to here somehow */
|
||||
break;
|
||||
case err_cantopenw:
|
||||
sp = va_arg(ap, char *);
|
||||
sprintf(error, "unable to open output file `%.200s'", sp);
|
||||
flags = PREFIX;
|
||||
break;
|
||||
case err_macroexists:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
wsp = va_arg(ap, wchar_t *);
|
||||
sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
|
||||
sprintf(error, "macro `%.200s' already defined", sp);
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_sectjump:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sprintf(error, "expected higher heading levels before this one");
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_winhelp_ctxclash:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
sp = va_arg(ap, char *);
|
||||
sp2 = va_arg(ap, char *);
|
||||
sprintf(error, "Windows Help context id `%.200s' clashes with "
|
||||
"previously defined `%.200s'", sp, sp2);
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_multikw:
|
||||
fpos = *va_arg(ap, filepos *);
|
||||
fpos2 = *va_arg(ap, filepos *);
|
||||
wsp = va_arg(ap, wchar_t *);
|
||||
sp = ustrtoa(wsp, auxbuf, sizeof(auxbuf));
|
||||
sprintf(error, "paragraph keyword `%.200s' already defined at ", sp);
|
||||
sprintf(error + strlen(error), "%s:%d", fpos2.filename, fpos2.line);
|
||||
flags = FILEPOS;
|
||||
break;
|
||||
case err_whatever:
|
||||
sp = va_arg(ap, char *);
|
||||
vsprintf(error, sp, ap);
|
||||
flags = PREFIX;
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & PREFIX)
|
||||
fputs("halibut: ", stderr);
|
||||
if (flags & FILEPOS) {
|
||||
fprintf(stderr, "%s:%d:", fpos.filename, fpos.line);
|
||||
if (fpos.col > 0)
|
||||
fprintf(stderr, "%d:", fpos.col);
|
||||
fputc(' ', stderr);
|
||||
}
|
||||
fputs(error, stderr);
|
||||
fputc('\n', stderr);
|
||||
if (flags & PREFIX)
|
||||
fputs("halibut: ", stderr);
|
||||
if (flags & FILEPOS)
|
||||
{
|
||||
fprintf(stderr, "%s:%d:", fpos.filename, fpos.line);
|
||||
if (fpos.col > 0)
|
||||
fprintf(stderr, "%d:", fpos.col);
|
||||
fputc(' ', stderr);
|
||||
}
|
||||
fputs(error, stderr);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
void fatal(int code, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, code);
|
||||
do_error(code, ap);
|
||||
va_end(ap);
|
||||
exit(EXIT_FAILURE);
|
||||
va_list ap;
|
||||
va_start(ap, code);
|
||||
do_error(code, ap);
|
||||
va_end(ap);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void error(int code, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, code);
|
||||
do_error(code, ap);
|
||||
va_end(ap);
|
||||
va_list ap;
|
||||
va_start(ap, code);
|
||||
do_error(code, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#ifdef __GNUC__
|
||||
#define NORETURN __attribute__((__noreturn__))
|
||||
#else
|
||||
#define NORETURN /* nothing */
|
||||
#define NORETURN /* nothing */
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
|
@ -44,27 +44,27 @@ typedef struct macrostack_Tag macrostack;
|
|||
* column number, for reporting errors
|
||||
*/
|
||||
struct filepos_Tag {
|
||||
char *filename;
|
||||
int line, col;
|
||||
char *filename;
|
||||
int line, col;
|
||||
};
|
||||
|
||||
/*
|
||||
* Data structure to hold all the file names etc for input
|
||||
*/
|
||||
typedef struct pushback_Tag {
|
||||
int chr;
|
||||
filepos pos;
|
||||
int chr;
|
||||
filepos pos;
|
||||
} pushback;
|
||||
struct input_Tag {
|
||||
char **filenames; /* complete list of input files */
|
||||
int nfiles; /* how many in the list */
|
||||
FILE *currfp; /* the currently open one */
|
||||
int currindex; /* which one is that in the list */
|
||||
pushback *pushback; /* pushed-back input characters */
|
||||
int npushback, pushbacksize;
|
||||
filepos pos;
|
||||
int reportcols; /* report column numbers in errors */
|
||||
macrostack *stack; /* macro expansions in force */
|
||||
char **filenames; /* complete list of input files */
|
||||
int nfiles; /* how many in the list */
|
||||
FILE *currfp; /* the currently open one */
|
||||
int currindex; /* which one is that in the list */
|
||||
pushback *pushback; /* pushed-back input characters */
|
||||
int npushback, pushbacksize;
|
||||
filepos pos;
|
||||
int reportcols; /* report column numbers in errors */
|
||||
macrostack *stack; /* macro expansions in force */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -72,95 +72,95 @@ struct input_Tag {
|
|||
* list of paragraphs
|
||||
*/
|
||||
struct paragraph_Tag {
|
||||
paragraph *next;
|
||||
int type;
|
||||
wchar_t *keyword; /* for most special paragraphs */
|
||||
word *words; /* list of words in paragraph */
|
||||
int aux; /* number, in a numbered paragraph
|
||||
* or subsection level
|
||||
*/
|
||||
word *kwtext; /* chapter/section indication */
|
||||
word *kwtext2; /* numeric-only form of kwtext */
|
||||
filepos fpos;
|
||||
paragraph *next;
|
||||
int type;
|
||||
wchar_t *keyword; /* for most special paragraphs */
|
||||
word *words; /* list of words in paragraph */
|
||||
int aux; /* number, in a numbered paragraph
|
||||
* or subsection level
|
||||
*/
|
||||
word *kwtext; /* chapter/section indication */
|
||||
word *kwtext2; /* numeric-only form of kwtext */
|
||||
filepos fpos;
|
||||
|
||||
paragraph *parent, *child, *sibling; /* for hierarchy navigation */
|
||||
paragraph *parent, *child, *sibling; /* for hierarchy navigation */
|
||||
|
||||
void *private_data; /* for temp use in backends */
|
||||
void *private_data; /* for temp use in backends */
|
||||
};
|
||||
enum {
|
||||
para_IM, /* index merge */
|
||||
para_BR, /* bibliography rewrite */
|
||||
para_Rule, /* random horizontal rule */
|
||||
para_Chapter,
|
||||
para_Appendix,
|
||||
para_UnnumberedChapter,
|
||||
para_Heading,
|
||||
para_Subsect,
|
||||
para_Normal,
|
||||
para_Biblio, /* causes no output unless turned ... */
|
||||
para_BiblioCited, /* ... into this paragraph type */
|
||||
para_Bullet,
|
||||
para_NumberedList,
|
||||
para_Code,
|
||||
para_Copyright,
|
||||
para_Preamble,
|
||||
para_NoCite,
|
||||
para_Title,
|
||||
para_VersionID,
|
||||
para_Config, /* configuration directive */
|
||||
para_NotParaType /* placeholder value */
|
||||
para_IM, /* index merge */
|
||||
para_BR, /* bibliography rewrite */
|
||||
para_Rule, /* random horizontal rule */
|
||||
para_Chapter,
|
||||
para_Appendix,
|
||||
para_UnnumberedChapter,
|
||||
para_Heading,
|
||||
para_Subsect,
|
||||
para_Normal,
|
||||
para_Biblio, /* causes no output unless turned ... */
|
||||
para_BiblioCited, /* ... into this paragraph type */
|
||||
para_Bullet,
|
||||
para_NumberedList,
|
||||
para_Code,
|
||||
para_Copyright,
|
||||
para_Preamble,
|
||||
para_NoCite,
|
||||
para_Title,
|
||||
para_VersionID,
|
||||
para_Config, /* configuration directive */
|
||||
para_NotParaType /* placeholder value */
|
||||
};
|
||||
|
||||
/*
|
||||
* Data structure to hold an individual word
|
||||
*/
|
||||
struct word_Tag {
|
||||
word *next, *alt;
|
||||
int type;
|
||||
int aux;
|
||||
int breaks; /* can a line break after it? */
|
||||
wchar_t *text;
|
||||
filepos fpos;
|
||||
word *next, *alt;
|
||||
int type;
|
||||
int aux;
|
||||
int breaks; /* can a line break after it? */
|
||||
wchar_t *text;
|
||||
filepos fpos;
|
||||
};
|
||||
enum {
|
||||
/* ORDERING CONSTRAINT: these normal-word types ... */
|
||||
word_Normal,
|
||||
word_Emph,
|
||||
word_Code, /* monospaced; `quoted' in text */
|
||||
word_WeakCode, /* monospaced, normal in text */
|
||||
/* ... must be in the same order as these space types ... */
|
||||
word_WhiteSpace, /* text is NULL or ignorable */
|
||||
word_EmphSpace, /* WhiteSpace when emphasised */
|
||||
word_CodeSpace, /* WhiteSpace when code */
|
||||
word_WkCodeSpace, /* WhiteSpace when weak code */
|
||||
/* ... and must be in the same order as these quote types ... */
|
||||
word_Quote, /* text is NULL or ignorable */
|
||||
word_EmphQuote, /* Quote when emphasised */
|
||||
word_CodeQuote, /* (can't happen) */
|
||||
word_WkCodeQuote, /* (can't happen) */
|
||||
/* END ORDERING CONSTRAINT */
|
||||
word_internal_endattrs,
|
||||
word_UpperXref, /* \K */
|
||||
word_LowerXref, /* \k */
|
||||
word_XrefEnd, /* (invisible; no text) */
|
||||
word_IndexRef, /* (always an invisible one) */
|
||||
word_HyperLink, /* (invisible) */
|
||||
word_HyperEnd, /* (also invisible; no text) */
|
||||
word_FreeTextXref /* \R */
|
||||
/* ORDERING CONSTRAINT: these normal-word types ... */
|
||||
word_Normal,
|
||||
word_Emph,
|
||||
word_Code, /* monospaced; `quoted' in text */
|
||||
word_WeakCode, /* monospaced, normal in text */
|
||||
/* ... must be in the same order as these space types ... */
|
||||
word_WhiteSpace, /* text is NULL or ignorable */
|
||||
word_EmphSpace, /* WhiteSpace when emphasised */
|
||||
word_CodeSpace, /* WhiteSpace when code */
|
||||
word_WkCodeSpace, /* WhiteSpace when weak code */
|
||||
/* ... and must be in the same order as these quote types ... */
|
||||
word_Quote, /* text is NULL or ignorable */
|
||||
word_EmphQuote, /* Quote when emphasised */
|
||||
word_CodeQuote, /* (can't happen) */
|
||||
word_WkCodeQuote, /* (can't happen) */
|
||||
/* END ORDERING CONSTRAINT */
|
||||
word_internal_endattrs,
|
||||
word_UpperXref, /* \K */
|
||||
word_LowerXref, /* \k */
|
||||
word_XrefEnd, /* (invisible; no text) */
|
||||
word_IndexRef, /* (always an invisible one) */
|
||||
word_HyperLink, /* (invisible) */
|
||||
word_HyperEnd, /* (also invisible; no text) */
|
||||
word_FreeTextXref /* \R */
|
||||
};
|
||||
/* aux values for attributed words */
|
||||
enum {
|
||||
attr_Only = 0x0000, /* a lone word with the attribute */
|
||||
attr_First = 0x0001, /* the first of a series */
|
||||
attr_Last = 0x0002, /* the last of a series */
|
||||
attr_Always = 0x0003, /* any other part of a series */
|
||||
attr_mask = 0x0003,
|
||||
attr_Only = 0x0000, /* a lone word with the attribute */
|
||||
attr_First = 0x0001, /* the first of a series */
|
||||
attr_Last = 0x0002, /* the last of a series */
|
||||
attr_Always = 0x0003, /* any other part of a series */
|
||||
attr_mask = 0x0003,
|
||||
};
|
||||
/* aux values for quote-type words */
|
||||
enum {
|
||||
quote_Open = 0x0010,
|
||||
quote_Close = 0x0020,
|
||||
quote_mask = 0x0030,
|
||||
quote_Open = 0x0010,
|
||||
quote_Close = 0x0020,
|
||||
quote_mask = 0x0030,
|
||||
};
|
||||
#define isattr(x) ( ( (x) > word_Normal && (x) < word_WhiteSpace ) || \
|
||||
( (x) > word_WhiteSpace && (x) < word_internal_endattrs ) )
|
||||
|
@ -179,36 +179,36 @@ enum {
|
|||
void fatal(int code, ...) NORETURN;
|
||||
void error(int code, ...);
|
||||
enum {
|
||||
err_nomemory, /* out of memory */
|
||||
err_optnoarg, /* option `-%s' requires an argument */
|
||||
err_nosuchopt, /* unrecognised option `-%s' */
|
||||
err_noinput, /* no input files */
|
||||
err_cantopen, /* unable to open input file `%s' */
|
||||
err_nodata, /* no data in input files */
|
||||
err_brokencodepara, /* line in codepara didn't begin `\c' */
|
||||
err_kwunclosed, /* expected `}' after keyword */
|
||||
err_kwillegal, /* paragraph type expects no keyword */
|
||||
err_kwexpected, /* paragraph type expects a keyword */
|
||||
err_kwtoomany, /* paragraph type expects only 1 */
|
||||
err_bodyillegal, /* paragraph type expects only kws! */
|
||||
err_badparatype, /* invalid command at start of para */
|
||||
err_badmidcmd, /* invalid command in mid-para */
|
||||
err_unexbrace, /* unexpected brace */
|
||||
err_explbr, /* expected `{' after command */
|
||||
err_commenteof, /* EOF inside braced comment */
|
||||
err_kwexprbr, /* expected `}' after cross-ref */
|
||||
err_missingrbrace, /* unclosed braces at end of para */
|
||||
err_nestedstyles, /* unable to nest text styles */
|
||||
err_nestedindex, /* unable to nest `\i' thingys */
|
||||
err_nosuchkw, /* unresolved cross-reference */
|
||||
err_multiBR, /* multiple \BRs on same keyword */
|
||||
err_nosuchidxtag, /* \IM on unknown index tag (warning) */
|
||||
err_cantopenw, /* can't open output file for write */
|
||||
err_macroexists, /* this macro already exists */
|
||||
err_sectjump, /* jump a heading level, eg \C -> \S */
|
||||
err_winhelp_ctxclash, /* WinHelp context ID hash clash */
|
||||
err_multikw, /* keyword clash in sections */
|
||||
err_whatever /* random error of another type */
|
||||
err_nomemory, /* out of memory */
|
||||
err_optnoarg, /* option `-%s' requires an argument */
|
||||
err_nosuchopt, /* unrecognised option `-%s' */
|
||||
err_noinput, /* no input files */
|
||||
err_cantopen, /* unable to open input file `%s' */
|
||||
err_nodata, /* no data in input files */
|
||||
err_brokencodepara, /* line in codepara didn't begin `\c' */
|
||||
err_kwunclosed, /* expected `}' after keyword */
|
||||
err_kwillegal, /* paragraph type expects no keyword */
|
||||
err_kwexpected, /* paragraph type expects a keyword */
|
||||
err_kwtoomany, /* paragraph type expects only 1 */
|
||||
err_bodyillegal, /* paragraph type expects only kws! */
|
||||
err_badparatype, /* invalid command at start of para */
|
||||
err_badmidcmd, /* invalid command in mid-para */
|
||||
err_unexbrace, /* unexpected brace */
|
||||
err_explbr, /* expected `{' after command */
|
||||
err_commenteof, /* EOF inside braced comment */
|
||||
err_kwexprbr, /* expected `}' after cross-ref */
|
||||
err_missingrbrace, /* unclosed braces at end of para */
|
||||
err_nestedstyles, /* unable to nest text styles */
|
||||
err_nestedindex, /* unable to nest `\i' thingys */
|
||||
err_nosuchkw, /* unresolved cross-reference */
|
||||
err_multiBR, /* multiple \BRs on same keyword */
|
||||
err_nosuchidxtag, /* \IM on unknown index tag (warning) */
|
||||
err_cantopenw, /* can't open output file for write */
|
||||
err_macroexists, /* this macro already exists */
|
||||
err_sectjump, /* jump a heading level, eg \C -> \S */
|
||||
err_winhelp_ctxclash, /* WinHelp context ID hash clash */
|
||||
err_multikw, /* keyword clash in sections */
|
||||
err_whatever /* random error of another type */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -280,13 +280,13 @@ void *stk_pop(stack);
|
|||
|
||||
typedef struct tagRdstring rdstring;
|
||||
struct tagRdstring {
|
||||
int pos, size;
|
||||
wchar_t *text;
|
||||
int pos, size;
|
||||
wchar_t *text;
|
||||
};
|
||||
typedef struct tagRdstringc rdstringc;
|
||||
struct tagRdstringc {
|
||||
int pos, size;
|
||||
char *text;
|
||||
int pos, size;
|
||||
char *text;
|
||||
};
|
||||
extern const rdstring empty_rdstring;
|
||||
extern const rdstringc empty_rdstringc;
|
||||
|
@ -303,10 +303,10 @@ void mark_attr_ends(paragraph * sourceform);
|
|||
|
||||
typedef struct tagWrappedLine wrappedline;
|
||||
struct tagWrappedLine {
|
||||
wrappedline *next;
|
||||
word *begin, *end; /* first & last words of line */
|
||||
int nspaces; /* number of whitespaces in line */
|
||||
int shortfall; /* how much shorter than max width */
|
||||
wrappedline *next;
|
||||
word *begin, *end; /* first & last words of line */
|
||||
int nspaces; /* number of whitespaces in line */
|
||||
int shortfall; /* how much shorter than max width */
|
||||
};
|
||||
wrappedline *wrap_para(word *, int, int, int (*)(word *));
|
||||
void wrap_free(wrappedline *);
|
||||
|
@ -320,18 +320,18 @@ paragraph *read_input(input * in, indexdata * idx);
|
|||
* keywords.c
|
||||
*/
|
||||
struct keywordlist_Tag {
|
||||
int nkeywords;
|
||||
int size;
|
||||
tree234 *keys; /* sorted by `key' field */
|
||||
word **looseends; /* non-keyword list element numbers */
|
||||
int nlooseends;
|
||||
int looseendssize;
|
||||
int nkeywords;
|
||||
int size;
|
||||
tree234 *keys; /* sorted by `key' field */
|
||||
word **looseends; /* non-keyword list element numbers */
|
||||
int nlooseends;
|
||||
int looseendssize;
|
||||
};
|
||||
struct keyword_Tag {
|
||||
wchar_t *key; /* the keyword itself */
|
||||
word *text; /* "Chapter 2", "Appendix Q"... */
|
||||
/* (NB: filepos are not set) */
|
||||
paragraph *para; /* the paragraph referenced */
|
||||
wchar_t *key; /* the keyword itself */
|
||||
word *text; /* "Chapter 2", "Appendix Q"... */
|
||||
/* (NB: filepos are not set) */
|
||||
paragraph *para; /* the paragraph referenced */
|
||||
};
|
||||
keyword *kw_lookup(keywordlist *, wchar_t *);
|
||||
keywordlist *get_keywords(paragraph *);
|
||||
|
@ -346,28 +346,28 @@ void subst_keywords(paragraph *, keywordlist *);
|
|||
* Data structure to hold both sides of the index.
|
||||
*/
|
||||
struct indexdata_Tag {
|
||||
tree234 *tags; /* holds type `indextag' */
|
||||
tree234 *entries; /* holds type `indexentry' */
|
||||
tree234 *tags; /* holds type `indextag' */
|
||||
tree234 *entries; /* holds type `indexentry' */
|
||||
};
|
||||
|
||||
/*
|
||||
* Data structure to hold an index tag (LHS of index).
|
||||
*/
|
||||
struct indextag_Tag {
|
||||
wchar_t *name;
|
||||
word *implicit_text;
|
||||
word **explicit_texts;
|
||||
int nexplicit, explicit_size;
|
||||
int nrefs;
|
||||
indexentry **refs; /* array of entries referenced by tag */
|
||||
wchar_t *name;
|
||||
word *implicit_text;
|
||||
word **explicit_texts;
|
||||
int nexplicit, explicit_size;
|
||||
int nrefs;
|
||||
indexentry **refs; /* array of entries referenced by tag */
|
||||
};
|
||||
|
||||
/*
|
||||
* Data structure to hold an index entry (RHS of index).
|
||||
*/
|
||||
struct indexentry_Tag {
|
||||
word *text;
|
||||
void *backend_data; /* private to back end */
|
||||
word *text;
|
||||
void *backend_data; /* private to back end */
|
||||
};
|
||||
|
||||
indexdata *make_index(void);
|
||||
|
|
|
@ -6,18 +6,18 @@
|
|||
#include "halibut.h"
|
||||
|
||||
static char *usagetext[] = {
|
||||
"halibut.exe file1 [file2 ...]",
|
||||
NULL
|
||||
"halibut.exe file1 [file2 ...]",
|
||||
NULL
|
||||
};
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
char **p;
|
||||
for (p = usagetext; *p; p++)
|
||||
puts(*p);
|
||||
char **p;
|
||||
for (p = usagetext; *p; p++)
|
||||
puts(*p);
|
||||
}
|
||||
|
||||
void showversion(void)
|
||||
{
|
||||
printf("Halibut, %s\n", version);
|
||||
printf("Halibut, %s\n", version);
|
||||
}
|
||||
|
|
|
@ -11,40 +11,40 @@ static int compare_entries(void *av, void *bv);
|
|||
|
||||
indexdata *make_index(void)
|
||||
{
|
||||
indexdata *ret = mknew(indexdata);
|
||||
ret->tags = newtree234(compare_tags);
|
||||
ret->entries = newtree234(compare_entries);
|
||||
return ret;
|
||||
indexdata *ret = mknew(indexdata);
|
||||
ret->tags = newtree234(compare_tags);
|
||||
ret->entries = newtree234(compare_entries);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static indextag *make_indextag(void)
|
||||
{
|
||||
indextag *ret = mknew(indextag);
|
||||
ret->name = NULL;
|
||||
ret->implicit_text = NULL;
|
||||
ret->explicit_texts = NULL;
|
||||
ret->nexplicit = ret->explicit_size = ret->nrefs = 0;
|
||||
ret->refs = NULL;
|
||||
return ret;
|
||||
indextag *ret = mknew(indextag);
|
||||
ret->name = NULL;
|
||||
ret->implicit_text = NULL;
|
||||
ret->explicit_texts = NULL;
|
||||
ret->nexplicit = ret->explicit_size = ret->nrefs = 0;
|
||||
ret->refs = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int compare_tags(void *av, void *bv)
|
||||
{
|
||||
indextag *a = (indextag *) av, *b = (indextag *) bv;
|
||||
return ustricmp(a->name, b->name);
|
||||
indextag *a = (indextag *) av, *b = (indextag *) bv;
|
||||
return ustricmp(a->name, b->name);
|
||||
}
|
||||
|
||||
static int compare_to_find_tag(void *av, void *bv)
|
||||
{
|
||||
wchar_t *a = (wchar_t *) av;
|
||||
indextag *b = (indextag *) bv;
|
||||
return ustricmp(a, b->name);
|
||||
wchar_t *a = (wchar_t *) av;
|
||||
indextag *b = (indextag *) bv;
|
||||
return ustricmp(a, b->name);
|
||||
}
|
||||
|
||||
static int compare_entries(void *av, void *bv)
|
||||
{
|
||||
indexentry *a = (indexentry *) av, *b = (indexentry *) bv;
|
||||
return compare_wordlists(a->text, b->text);
|
||||
indexentry *a = (indexentry *) av, *b = (indexentry *) bv;
|
||||
return compare_wordlists(a->text, b->text);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -52,7 +52,7 @@ static int compare_entries(void *av, void *bv)
|
|||
*/
|
||||
indextag *index_findtag(indexdata * idx, wchar_t * name)
|
||||
{
|
||||
return find234(idx->tags, name, compare_to_find_tag);
|
||||
return find234(idx->tags, name, compare_to_find_tag);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -66,65 +66,72 @@ indextag *index_findtag(indexdata * idx, wchar_t * name)
|
|||
void
|
||||
index_merge(indexdata * idx, int is_explicit, wchar_t * tags, word * text)
|
||||
{
|
||||
indextag *t, *existing;
|
||||
indextag *t, *existing;
|
||||
|
||||
/*
|
||||
* FIXME: want to warn on overlapping source sets.
|
||||
*/
|
||||
for (; *tags; tags = uadv(tags)) {
|
||||
t = make_indextag();
|
||||
t->name = tags;
|
||||
existing = add234(idx->tags, t);
|
||||
if (existing == t) {
|
||||
/*
|
||||
* Duplicate this so we can free it independently.
|
||||
*/
|
||||
t->name = ustrdup(tags);
|
||||
/*
|
||||
* FIXME: want to warn on overlapping source sets.
|
||||
*/
|
||||
for (; *tags; tags = uadv(tags))
|
||||
{
|
||||
t = make_indextag();
|
||||
t->name = tags;
|
||||
existing = add234(idx->tags, t);
|
||||
if (existing == t)
|
||||
{
|
||||
/*
|
||||
* Duplicate this so we can free it independently.
|
||||
*/
|
||||
t->name = ustrdup(tags);
|
||||
|
||||
/*
|
||||
* Every tag has an implicit \IM. So if this tag
|
||||
* doesn't exist and we're explicit, then we should
|
||||
* warn (and drop it, since it won't be referenced).
|
||||
*/
|
||||
if (is_explicit) {
|
||||
error(err_nosuchidxtag, tags);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Every tag has an implicit \IM. So if this tag
|
||||
* doesn't exist and we're explicit, then we should
|
||||
* warn (and drop it, since it won't be referenced).
|
||||
*/
|
||||
if (is_explicit)
|
||||
{
|
||||
error(err_nosuchidxtag, tags);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise, this is a new tag with an implicit \IM.
|
||||
*/
|
||||
t->implicit_text = text;
|
||||
} else {
|
||||
sfree(t);
|
||||
t = existing;
|
||||
if (!is_explicit) {
|
||||
/*
|
||||
* An implicit \IM for a tag that's had an implicit
|
||||
* \IM before. FIXME: we should check the text
|
||||
* against the existing text and warn on
|
||||
* differences. And check the tag for case match
|
||||
* against the existing tag, likewise.
|
||||
*/
|
||||
} else {
|
||||
/*
|
||||
* An explicit \IM added to a valid tag. In
|
||||
* particular, this removes the implicit \IM if
|
||||
* present.
|
||||
*/
|
||||
if (t->implicit_text) {
|
||||
free_word_list(t->implicit_text);
|
||||
t->implicit_text = NULL;
|
||||
}
|
||||
if (t->nexplicit >= t->explicit_size) {
|
||||
t->explicit_size = t->nexplicit + 8;
|
||||
t->explicit_texts = resize(t->explicit_texts,
|
||||
t->explicit_size);
|
||||
}
|
||||
t->explicit_texts[t->nexplicit++] = text;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Otherwise, this is a new tag with an implicit \IM.
|
||||
*/
|
||||
t->implicit_text = text;
|
||||
} else
|
||||
{
|
||||
sfree(t);
|
||||
t = existing;
|
||||
if (!is_explicit)
|
||||
{
|
||||
/*
|
||||
* An implicit \IM for a tag that's had an implicit
|
||||
* \IM before. FIXME: we should check the text
|
||||
* against the existing text and warn on
|
||||
* differences. And check the tag for case match
|
||||
* against the existing tag, likewise.
|
||||
*/
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* An explicit \IM added to a valid tag. In
|
||||
* particular, this removes the implicit \IM if
|
||||
* present.
|
||||
*/
|
||||
if (t->implicit_text)
|
||||
{
|
||||
free_word_list(t->implicit_text);
|
||||
t->implicit_text = NULL;
|
||||
}
|
||||
if (t->nexplicit >= t->explicit_size)
|
||||
{
|
||||
t->explicit_size = t->nexplicit + 8;
|
||||
t->explicit_texts = resize(t->explicit_texts, t->explicit_size);
|
||||
}
|
||||
t->explicit_texts[t->nexplicit++] = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -136,52 +143,59 @@ index_merge(indexdata * idx, int is_explicit, wchar_t * tags, word * text)
|
|||
*/
|
||||
void build_index(indexdata * i)
|
||||
{
|
||||
indextag *t;
|
||||
word **ta;
|
||||
int ti;
|
||||
int j;
|
||||
indextag *t;
|
||||
word **ta;
|
||||
int ti;
|
||||
int j;
|
||||
|
||||
for (ti = 0; (t = (indextag *) index234(i->tags, ti)) != NULL; ti++) {
|
||||
if (t->implicit_text) {
|
||||
t->nrefs = 1;
|
||||
ta = &t->implicit_text;
|
||||
} else {
|
||||
t->nrefs = t->nexplicit;
|
||||
ta = t->explicit_texts;
|
||||
}
|
||||
if (t->nrefs) {
|
||||
t->refs = mknewa(indexentry *, t->nrefs);
|
||||
for (j = 0; j < t->nrefs; j++) {
|
||||
indexentry *ent = mknew(indexentry);
|
||||
ent->text = *ta++;
|
||||
t->refs[j] = add234(i->entries, ent);
|
||||
if (t->refs[j] != ent) /* duplicate */
|
||||
sfree(ent);
|
||||
}
|
||||
}
|
||||
for (ti = 0; (t = (indextag *) index234(i->tags, ti)) != NULL; ti++)
|
||||
{
|
||||
if (t->implicit_text)
|
||||
{
|
||||
t->nrefs = 1;
|
||||
ta = &t->implicit_text;
|
||||
} else
|
||||
{
|
||||
t->nrefs = t->nexplicit;
|
||||
ta = t->explicit_texts;
|
||||
}
|
||||
if (t->nrefs)
|
||||
{
|
||||
t->refs = mknewa(indexentry *, t->nrefs);
|
||||
for (j = 0; j < t->nrefs; j++)
|
||||
{
|
||||
indexentry *ent = mknew(indexentry);
|
||||
ent->text = *ta++;
|
||||
t->refs[j] = add234(i->entries, ent);
|
||||
if (t->refs[j] != ent) /* duplicate */
|
||||
sfree(ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup_index(indexdata * i)
|
||||
{
|
||||
indextag *t;
|
||||
indexentry *ent;
|
||||
int ti;
|
||||
indextag *t;
|
||||
indexentry *ent;
|
||||
int ti;
|
||||
|
||||
for (ti = 0; (t = (indextag *) index234(i->tags, ti)) != NULL; ti++) {
|
||||
sfree(t->name);
|
||||
free_word_list(t->implicit_text);
|
||||
sfree(t->explicit_texts);
|
||||
sfree(t->refs);
|
||||
sfree(t);
|
||||
}
|
||||
freetree234(i->tags);
|
||||
for (ti = 0; (ent = (indexentry *) index234(i->entries, ti)) != NULL;
|
||||
ti++) {
|
||||
sfree(ent);
|
||||
}
|
||||
freetree234(i->entries);
|
||||
sfree(i);
|
||||
for (ti = 0; (t = (indextag *) index234(i->tags, ti)) != NULL; ti++)
|
||||
{
|
||||
sfree(t->name);
|
||||
free_word_list(t->implicit_text);
|
||||
sfree(t->explicit_texts);
|
||||
sfree(t->refs);
|
||||
sfree(t);
|
||||
}
|
||||
freetree234(i->tags);
|
||||
for (ti = 0; (ent = (indexentry *) index234(i->entries, ti)) != NULL;
|
||||
ti++)
|
||||
{
|
||||
sfree(ent);
|
||||
}
|
||||
freetree234(i->entries);
|
||||
sfree(i);
|
||||
}
|
||||
|
||||
static void dbg_prtwordlist(int level, word * w);
|
||||
|
@ -189,57 +203,61 @@ static void dbg_prtmerge(int is_explicit, wchar_t * tag, word * text);
|
|||
|
||||
void index_debug(indexdata * i)
|
||||
{
|
||||
indextag *t;
|
||||
indexentry *y;
|
||||
int ti;
|
||||
int j;
|
||||
indextag *t;
|
||||
indexentry *y;
|
||||
int ti;
|
||||
int j;
|
||||
|
||||
printf("\nINDEX TAGS\n==========\n\n");
|
||||
for (ti = 0; (t = (indextag *) index234(i->tags, ti)) != NULL; ti++) {
|
||||
printf("\n");
|
||||
if (t->implicit_text)
|
||||
dbg_prtmerge(0, t->name, t->implicit_text);
|
||||
for (j = 0; j < t->nexplicit; j++)
|
||||
dbg_prtmerge(1, t->name, t->explicit_texts[j]);
|
||||
}
|
||||
printf("\nINDEX TAGS\n==========\n\n");
|
||||
for (ti = 0; (t = (indextag *) index234(i->tags, ti)) != NULL; ti++)
|
||||
{
|
||||
printf("\n");
|
||||
if (t->implicit_text)
|
||||
dbg_prtmerge(0, t->name, t->implicit_text);
|
||||
for (j = 0; j < t->nexplicit; j++)
|
||||
dbg_prtmerge(1, t->name, t->explicit_texts[j]);
|
||||
}
|
||||
|
||||
printf("\nINDEX ENTRIES\n=============\n\n");
|
||||
for (ti = 0; (y = (indexentry *) index234(i->entries, ti)) != NULL;
|
||||
ti++) {
|
||||
printf("\n");
|
||||
printf("{\n");
|
||||
dbg_prtwordlist(1, y->text);
|
||||
printf("}\n");
|
||||
}
|
||||
printf("\nINDEX ENTRIES\n=============\n\n");
|
||||
for (ti = 0; (y = (indexentry *) index234(i->entries, ti)) != NULL; ti++)
|
||||
{
|
||||
printf("\n");
|
||||
printf("{\n");
|
||||
dbg_prtwordlist(1, y->text);
|
||||
printf("}\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void dbg_prtmerge(int is_explicit, wchar_t * tag, word * text)
|
||||
{
|
||||
printf("\\IM: %splicit: \"", is_explicit ? "ex" : "im");
|
||||
for (; *tag; tag++)
|
||||
putchar(*tag);
|
||||
printf("\" {\n");
|
||||
dbg_prtwordlist(1, text);
|
||||
printf("}\n");
|
||||
printf("\\IM: %splicit: \"", is_explicit ? "ex" : "im");
|
||||
for (; *tag; tag++)
|
||||
putchar(*tag);
|
||||
printf("\" {\n");
|
||||
dbg_prtwordlist(1, text);
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
static void dbg_prtwordlist(int level, word * w)
|
||||
{
|
||||
for (; w; w = w->next) {
|
||||
wchar_t *wp;
|
||||
printf("%*sword %d ", level * 4, "", w->type);
|
||||
if (w->text) {
|
||||
printf("\"");
|
||||
for (wp = w->text; *wp; wp++)
|
||||
putchar(*wp);
|
||||
printf("\"");
|
||||
} else
|
||||
printf("(no text)");
|
||||
if (w->alt) {
|
||||
printf(" alt = {\n");
|
||||
dbg_prtwordlist(level + 1, w->alt);
|
||||
printf("%*s}", level * 4, "");
|
||||
}
|
||||
printf("\n");
|
||||
for (; w; w = w->next)
|
||||
{
|
||||
wchar_t *wp;
|
||||
printf("%*sword %d ", level * 4, "", w->type);
|
||||
if (w->text)
|
||||
{
|
||||
printf("\"");
|
||||
for (wp = w->text; *wp; wp++)
|
||||
putchar(*wp);
|
||||
printf("\"");
|
||||
} else
|
||||
printf("(no text)");
|
||||
if (w->alt)
|
||||
{
|
||||
printf(" alt = {\n");
|
||||
dbg_prtwordlist(level + 1, w->alt);
|
||||
printf("%*s}", level * 4, "");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -9,21 +9,21 @@
|
|||
|
||||
static int kwcmp(void *av, void *bv)
|
||||
{
|
||||
const keyword *a = (const keyword *) av;
|
||||
const keyword *b = (const keyword *) bv;
|
||||
return ustrcmp(a->key, b->key);
|
||||
const keyword *a = (const keyword *) av;
|
||||
const keyword *b = (const keyword *) bv;
|
||||
return ustrcmp(a->key, b->key);
|
||||
}
|
||||
|
||||
static int kwfind(void *av, void *bv)
|
||||
{
|
||||
wchar_t *a = (wchar_t *) av;
|
||||
const keyword *b = (const keyword *) bv;
|
||||
return ustrcmp(a, b->key);
|
||||
wchar_t *a = (wchar_t *) av;
|
||||
const keyword *b = (const keyword *) bv;
|
||||
return ustrcmp(a, b->key);
|
||||
}
|
||||
|
||||
keyword *kw_lookup(keywordlist * kl, wchar_t * str)
|
||||
{
|
||||
return find234(kl->keys, str, kwfind);
|
||||
return find234(kl->keys, str, kwfind);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -34,126 +34,138 @@ keyword *kw_lookup(keywordlist * kl, wchar_t * str)
|
|||
*/
|
||||
keywordlist *get_keywords(paragraph * source)
|
||||
{
|
||||
int errors = FALSE;
|
||||
keywordlist *kl = mknew(keywordlist);
|
||||
numberstate *n = number_init();
|
||||
int prevpara = para_NotParaType;
|
||||
int errors = FALSE;
|
||||
keywordlist *kl = mknew(keywordlist);
|
||||
numberstate *n = number_init();
|
||||
int prevpara = para_NotParaType;
|
||||
|
||||
number_cfg(n, source);
|
||||
number_cfg(n, source);
|
||||
|
||||
kl->size = 0;
|
||||
kl->keys = newtree234(kwcmp);
|
||||
kl->nlooseends = kl->looseendssize = 0;
|
||||
kl->looseends = NULL;
|
||||
for (; source; source = source->next) {
|
||||
wchar_t *p, *q;
|
||||
p = q = source->keyword;
|
||||
kl->size = 0;
|
||||
kl->keys = newtree234(kwcmp);
|
||||
kl->nlooseends = kl->looseendssize = 0;
|
||||
kl->looseends = NULL;
|
||||
for (; source; source = source->next)
|
||||
{
|
||||
wchar_t *p, *q;
|
||||
p = q = source->keyword;
|
||||
|
||||
/*
|
||||
* Look for the section type override (`example',
|
||||
* `question' or whatever - to replace `chapter' or
|
||||
* `section' on a per-section basis).
|
||||
*/
|
||||
if (q) {
|
||||
q = uadv(q); /* point q at the word beyond */
|
||||
if (!*q)
|
||||
q = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Number the chapter / section / list-item / whatever.
|
||||
* This also sets up the `parent', `child' and `sibling'
|
||||
* links.
|
||||
*/
|
||||
source->kwtext = number_mktext(n, source, q, prevpara, &errors);
|
||||
prevpara = source->type;
|
||||
|
||||
if (p && *p) {
|
||||
if (source->kwtext || source->type == para_Biblio) {
|
||||
keyword *kw, *ret;
|
||||
|
||||
kw = mknew(keyword);
|
||||
kw->key = p;
|
||||
kw->text = source->kwtext;
|
||||
kw->para = source;
|
||||
ret = add234(kl->keys, kw);
|
||||
if (ret != kw) {
|
||||
error(err_multikw, &source->fpos, &ret->para->fpos, p);
|
||||
sfree(kw);
|
||||
/* FIXME: what happens to kw->text? Does it leak? */
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (kl->nlooseends >= kl->looseendssize) {
|
||||
kl->looseendssize = kl->nlooseends + 32;
|
||||
kl->looseends = resize(kl->looseends, kl->looseendssize);
|
||||
}
|
||||
kl->looseends[kl->nlooseends++] = source->kwtext;
|
||||
}
|
||||
/*
|
||||
* Look for the section type override (`example',
|
||||
* `question' or whatever - to replace `chapter' or
|
||||
* `section' on a per-section basis).
|
||||
*/
|
||||
if (q)
|
||||
{
|
||||
q = uadv(q); /* point q at the word beyond */
|
||||
if (!*q)
|
||||
q = NULL;
|
||||
}
|
||||
|
||||
number_free(n);
|
||||
/*
|
||||
* Number the chapter / section / list-item / whatever.
|
||||
* This also sets up the `parent', `child' and `sibling'
|
||||
* links.
|
||||
*/
|
||||
source->kwtext = number_mktext(n, source, q, prevpara, &errors);
|
||||
prevpara = source->type;
|
||||
|
||||
if (errors) {
|
||||
free_keywords(kl);
|
||||
return NULL;
|
||||
if (p && *p)
|
||||
{
|
||||
if (source->kwtext || source->type == para_Biblio)
|
||||
{
|
||||
keyword *kw, *ret;
|
||||
|
||||
kw = mknew(keyword);
|
||||
kw->key = p;
|
||||
kw->text = source->kwtext;
|
||||
kw->para = source;
|
||||
ret = add234(kl->keys, kw);
|
||||
if (ret != kw)
|
||||
{
|
||||
error(err_multikw, &source->fpos, &ret->para->fpos, p);
|
||||
sfree(kw);
|
||||
/* FIXME: what happens to kw->text? Does it leak? */
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
if (kl->nlooseends >= kl->looseendssize)
|
||||
{
|
||||
kl->looseendssize = kl->nlooseends + 32;
|
||||
kl->looseends = resize(kl->looseends, kl->looseendssize);
|
||||
}
|
||||
kl->looseends[kl->nlooseends++] = source->kwtext;
|
||||
}
|
||||
}
|
||||
|
||||
return kl;
|
||||
number_free(n);
|
||||
|
||||
if (errors)
|
||||
{
|
||||
free_keywords(kl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return kl;
|
||||
}
|
||||
|
||||
void free_keywords(keywordlist * kl)
|
||||
{
|
||||
keyword *kw;
|
||||
while (kl->nlooseends)
|
||||
free_word_list(kl->looseends[--kl->nlooseends]);
|
||||
sfree(kl->looseends);
|
||||
while ((kw = index234(kl->keys, 0)) != NULL) {
|
||||
delpos234(kl->keys, 0);
|
||||
free_word_list(kw->text);
|
||||
sfree(kw);
|
||||
}
|
||||
freetree234(kl->keys);
|
||||
sfree(kl);
|
||||
keyword *kw;
|
||||
while (kl->nlooseends)
|
||||
free_word_list(kl->looseends[--kl->nlooseends]);
|
||||
sfree(kl->looseends);
|
||||
while ((kw = index234(kl->keys, 0)) != NULL)
|
||||
{
|
||||
delpos234(kl->keys, 0);
|
||||
free_word_list(kw->text);
|
||||
sfree(kw);
|
||||
}
|
||||
freetree234(kl->keys);
|
||||
sfree(kl);
|
||||
}
|
||||
|
||||
void subst_keywords(paragraph * source, keywordlist * kl)
|
||||
{
|
||||
for (; source; source = source->next) {
|
||||
word *ptr;
|
||||
for (ptr = source->words; ptr; ptr = ptr->next) {
|
||||
if (ptr->type == word_UpperXref || ptr->type == word_LowerXref) {
|
||||
keyword *kw;
|
||||
word **endptr, *close, *subst;
|
||||
for (; source; source = source->next)
|
||||
{
|
||||
word *ptr;
|
||||
for (ptr = source->words; ptr; ptr = ptr->next)
|
||||
{
|
||||
if (ptr->type == word_UpperXref || ptr->type == word_LowerXref)
|
||||
{
|
||||
keyword *kw;
|
||||
word **endptr, *close, *subst;
|
||||
|
||||
kw = kw_lookup(kl, ptr->text);
|
||||
if (!kw) {
|
||||
error(err_nosuchkw, &ptr->fpos, ptr->text);
|
||||
subst = NULL;
|
||||
} else
|
||||
subst = dup_word_list(kw->text);
|
||||
kw = kw_lookup(kl, ptr->text);
|
||||
if (!kw)
|
||||
{
|
||||
error(err_nosuchkw, &ptr->fpos, ptr->text);
|
||||
subst = NULL;
|
||||
} else
|
||||
subst = dup_word_list(kw->text);
|
||||
|
||||
if (subst && ptr->type == word_LowerXref &&
|
||||
kw->para->type != para_Biblio &&
|
||||
kw->para->type != para_BiblioCited)
|
||||
ustrlow(subst->text);
|
||||
if (subst && ptr->type == word_LowerXref &&
|
||||
kw->para->type != para_Biblio &&
|
||||
kw->para->type != para_BiblioCited)
|
||||
ustrlow(subst->text);
|
||||
|
||||
close = mknew(word);
|
||||
close->text = NULL;
|
||||
close->alt = NULL;
|
||||
close->type = word_XrefEnd;
|
||||
close->fpos = ptr->fpos;
|
||||
close = mknew(word);
|
||||
close->text = NULL;
|
||||
close->alt = NULL;
|
||||
close->type = word_XrefEnd;
|
||||
close->fpos = ptr->fpos;
|
||||
|
||||
close->next = ptr->next;
|
||||
ptr->next = subst;
|
||||
close->next = ptr->next;
|
||||
ptr->next = subst;
|
||||
|
||||
for (endptr = &ptr->next; *endptr;
|
||||
endptr = &(*endptr)->next)
|
||||
(*endptr)->fpos = ptr->fpos;
|
||||
for (endptr = &ptr->next; *endptr; endptr = &(*endptr)->next)
|
||||
(*endptr)->fpos = ptr->fpos;
|
||||
|
||||
*endptr = close;
|
||||
ptr = close;
|
||||
}
|
||||
}
|
||||
*endptr = close;
|
||||
ptr = close;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
#include <stdio.h>
|
||||
|
||||
static char *licencetext[] = {
|
||||
"FIXME: licence text goes here",
|
||||
NULL
|
||||
"FIXME: licence text goes here",
|
||||
NULL
|
||||
};
|
||||
|
||||
void licence(void)
|
||||
{
|
||||
char **p;
|
||||
for (p = licencetext; *p; p++)
|
||||
puts(*p);
|
||||
char **p;
|
||||
for (p = licencetext; *p; p++)
|
||||
puts(*p);
|
||||
}
|
||||
|
|
|
@ -12,283 +12,308 @@ static void dbg_prtkws(keywordlist * kws);
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char **infiles;
|
||||
char *outfile;
|
||||
int nfiles;
|
||||
int nogo;
|
||||
int errs;
|
||||
int reportcols;
|
||||
int debug;
|
||||
char **infiles;
|
||||
char *outfile;
|
||||
int nfiles;
|
||||
int nogo;
|
||||
int errs;
|
||||
int reportcols;
|
||||
int debug;
|
||||
|
||||
/*
|
||||
* Set up initial (default) parameters.
|
||||
*/
|
||||
infiles = mknewa(char *, argc);
|
||||
outfile = NULL;
|
||||
nfiles = 0;
|
||||
nogo = errs = FALSE;
|
||||
reportcols = 0;
|
||||
debug = 0;
|
||||
/*
|
||||
* Set up initial (default) parameters.
|
||||
*/
|
||||
infiles = mknewa(char *, argc);
|
||||
outfile = NULL;
|
||||
nfiles = 0;
|
||||
nogo = errs = FALSE;
|
||||
reportcols = 0;
|
||||
debug = 0;
|
||||
|
||||
if (argc == 1) {
|
||||
usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse command line arguments.
|
||||
*/
|
||||
while (--argc) {
|
||||
char *p = *++argv;
|
||||
if (*p == '-') {
|
||||
/*
|
||||
* An option.
|
||||
*/
|
||||
while (p && *++p) {
|
||||
char c = *p;
|
||||
switch (c) {
|
||||
case '-':
|
||||
/*
|
||||
* Long option.
|
||||
*/
|
||||
{
|
||||
char *opt, *val;
|
||||
opt = p++; /* opt will have _one_ leading - */
|
||||
while (*p && *p != '=')
|
||||
p++; /* find end of option */
|
||||
if (*p == '=') {
|
||||
*p++ = '\0';
|
||||
val = p;
|
||||
} else
|
||||
val = NULL;
|
||||
if (!strcmp(opt, "-version")) {
|
||||
showversion();
|
||||
nogo = TRUE;
|
||||
} else if (!strcmp(opt, "-licence") ||
|
||||
!strcmp(opt, "-license")) {
|
||||
licence();
|
||||
nogo = TRUE;
|
||||
} else if (!strcmp(opt, "-output")) {
|
||||
if (!val)
|
||||
errs = TRUE, error(err_optnoarg, opt);
|
||||
else
|
||||
outfile = val;
|
||||
} else if (!strcmp(opt, "-precise")) {
|
||||
reportcols = 1;
|
||||
} else {
|
||||
errs = TRUE, error(err_nosuchopt, opt);
|
||||
}
|
||||
}
|
||||
p = NULL;
|
||||
break;
|
||||
case 'V':
|
||||
case 'L':
|
||||
case 'P':
|
||||
case 'd':
|
||||
/*
|
||||
* Option requiring no parameter.
|
||||
*/
|
||||
switch (c) {
|
||||
case 'V':
|
||||
showversion();
|
||||
nogo = TRUE;
|
||||
break;
|
||||
case 'L':
|
||||
licence();
|
||||
nogo = TRUE;
|
||||
break;
|
||||
case 'P':
|
||||
reportcols = 1;
|
||||
break;
|
||||
case 'd':
|
||||
debug = TRUE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
/*
|
||||
* Option requiring parameter.
|
||||
*/
|
||||
p++;
|
||||
if (!*p && argc > 1)
|
||||
--argc, p = *++argv;
|
||||
else if (!*p) {
|
||||
char opt[2];
|
||||
opt[0] = c;
|
||||
opt[1] = '\0';
|
||||
errs = TRUE, error(err_optnoarg, opt);
|
||||
}
|
||||
/*
|
||||
* Now c is the option and p is the parameter.
|
||||
*/
|
||||
switch (c) {
|
||||
case 'o':
|
||||
outfile = p;
|
||||
break;
|
||||
}
|
||||
p = NULL; /* prevent continued processing */
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Unrecognised option.
|
||||
*/
|
||||
{
|
||||
char opt[2];
|
||||
opt[0] = c;
|
||||
opt[1] = '\0';
|
||||
errs = TRUE, error(err_nosuchopt, opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* A non-option argument.
|
||||
*/
|
||||
infiles[nfiles++] = p;
|
||||
}
|
||||
}
|
||||
|
||||
if (errs)
|
||||
exit(EXIT_FAILURE);
|
||||
if (nogo)
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
/*
|
||||
* Do the work.
|
||||
*/
|
||||
if (nfiles == 0) {
|
||||
error(err_noinput);
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (argc == 1)
|
||||
{
|
||||
usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse command line arguments.
|
||||
*/
|
||||
while (--argc)
|
||||
{
|
||||
char *p = *++argv;
|
||||
if (*p == '-')
|
||||
{
|
||||
input in;
|
||||
paragraph *sourceform, *p;
|
||||
indexdata *idx;
|
||||
keywordlist *keywords;
|
||||
/*
|
||||
* An option.
|
||||
*/
|
||||
while (p && *++p)
|
||||
{
|
||||
char c = *p;
|
||||
switch (c)
|
||||
{
|
||||
case '-':
|
||||
/*
|
||||
* Long option.
|
||||
*/
|
||||
{
|
||||
char *opt, *val;
|
||||
opt = p++; /* opt will have _one_ leading - */
|
||||
while (*p && *p != '=')
|
||||
p++; /* find end of option */
|
||||
if (*p == '=')
|
||||
{
|
||||
*p++ = '\0';
|
||||
val = p;
|
||||
} else
|
||||
val = NULL;
|
||||
if (!strcmp(opt, "-version"))
|
||||
{
|
||||
showversion();
|
||||
nogo = TRUE;
|
||||
} else if (!strcmp(opt, "-licence") ||
|
||||
!strcmp(opt, "-license"))
|
||||
{
|
||||
licence();
|
||||
nogo = TRUE;
|
||||
} else if (!strcmp(opt, "-output"))
|
||||
{
|
||||
if (!val)
|
||||
errs = TRUE, error(err_optnoarg, opt);
|
||||
else
|
||||
outfile = val;
|
||||
} else if (!strcmp(opt, "-precise"))
|
||||
{
|
||||
reportcols = 1;
|
||||
} else
|
||||
{
|
||||
errs = TRUE, error(err_nosuchopt, opt);
|
||||
}
|
||||
}
|
||||
p = NULL;
|
||||
break;
|
||||
case 'V':
|
||||
case 'L':
|
||||
case 'P':
|
||||
case 'd':
|
||||
/*
|
||||
* Option requiring no parameter.
|
||||
*/
|
||||
switch (c)
|
||||
{
|
||||
case 'V':
|
||||
showversion();
|
||||
nogo = TRUE;
|
||||
break;
|
||||
case 'L':
|
||||
licence();
|
||||
nogo = TRUE;
|
||||
break;
|
||||
case 'P':
|
||||
reportcols = 1;
|
||||
break;
|
||||
case 'd':
|
||||
debug = TRUE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
/*
|
||||
* Option requiring parameter.
|
||||
*/
|
||||
p++;
|
||||
if (!*p && argc > 1)
|
||||
--argc, p = *++argv;
|
||||
else if (!*p)
|
||||
{
|
||||
char opt[2];
|
||||
opt[0] = c;
|
||||
opt[1] = '\0';
|
||||
errs = TRUE, error(err_optnoarg, opt);
|
||||
}
|
||||
/*
|
||||
* Now c is the option and p is the parameter.
|
||||
*/
|
||||
switch (c)
|
||||
{
|
||||
case 'o':
|
||||
outfile = p;
|
||||
break;
|
||||
}
|
||||
p = NULL; /* prevent continued processing */
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Unrecognised option.
|
||||
*/
|
||||
{
|
||||
char opt[2];
|
||||
opt[0] = c;
|
||||
opt[1] = '\0';
|
||||
errs = TRUE, error(err_nosuchopt, opt);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* A non-option argument.
|
||||
*/
|
||||
infiles[nfiles++] = p;
|
||||
}
|
||||
}
|
||||
|
||||
in.filenames = infiles;
|
||||
in.nfiles = nfiles;
|
||||
in.currfp = NULL;
|
||||
in.currindex = 0;
|
||||
in.npushback = in.pushbacksize = 0;
|
||||
in.pushback = NULL;
|
||||
in.reportcols = reportcols;
|
||||
in.stack = NULL;
|
||||
if (errs)
|
||||
exit(EXIT_FAILURE);
|
||||
if (nogo)
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
idx = make_index();
|
||||
/*
|
||||
* Do the work.
|
||||
*/
|
||||
if (nfiles == 0)
|
||||
{
|
||||
error(err_noinput);
|
||||
usage();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sourceform = read_input(&in, idx);
|
||||
if (!sourceform)
|
||||
exit(EXIT_FAILURE);
|
||||
{
|
||||
input in;
|
||||
paragraph *sourceform, *p;
|
||||
indexdata *idx;
|
||||
keywordlist *keywords;
|
||||
|
||||
sfree(in.pushback);
|
||||
in.filenames = infiles;
|
||||
in.nfiles = nfiles;
|
||||
in.currfp = NULL;
|
||||
in.currindex = 0;
|
||||
in.npushback = in.pushbacksize = 0;
|
||||
in.pushback = NULL;
|
||||
in.reportcols = reportcols;
|
||||
in.stack = NULL;
|
||||
|
||||
mark_attr_ends(sourceform);
|
||||
idx = make_index();
|
||||
|
||||
sfree(infiles);
|
||||
sourceform = read_input(&in, idx);
|
||||
if (!sourceform)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
keywords = get_keywords(sourceform);
|
||||
if (!keywords)
|
||||
exit(EXIT_FAILURE);
|
||||
gen_citations(sourceform, keywords);
|
||||
subst_keywords(sourceform, keywords);
|
||||
sfree(in.pushback);
|
||||
|
||||
for (p = sourceform; p; p = p->next)
|
||||
if (p->type == para_IM)
|
||||
index_merge(idx, TRUE, p->keyword, p->words);
|
||||
mark_attr_ends(sourceform);
|
||||
|
||||
build_index(idx);
|
||||
sfree(infiles);
|
||||
|
||||
if (debug) {
|
||||
index_debug(idx);
|
||||
dbg_prtkws(keywords);
|
||||
dbg_prtsource(sourceform);
|
||||
}
|
||||
keywords = get_keywords(sourceform);
|
||||
if (!keywords)
|
||||
exit(EXIT_FAILURE);
|
||||
gen_citations(sourceform, keywords);
|
||||
subst_keywords(sourceform, keywords);
|
||||
|
||||
xhtml_backend(sourceform, keywords, idx);
|
||||
for (p = sourceform; p; p = p->next)
|
||||
if (p->type == para_IM)
|
||||
index_merge(idx, TRUE, p->keyword, p->words);
|
||||
|
||||
free_para_list(sourceform);
|
||||
free_keywords(keywords);
|
||||
cleanup_index(idx);
|
||||
build_index(idx);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
index_debug(idx);
|
||||
dbg_prtkws(keywords);
|
||||
dbg_prtsource(sourceform);
|
||||
}
|
||||
|
||||
return 0;
|
||||
xhtml_backend(sourceform, keywords, idx);
|
||||
|
||||
free_para_list(sourceform);
|
||||
free_keywords(keywords);
|
||||
cleanup_index(idx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dbg_prtsource(paragraph * sourceform)
|
||||
{
|
||||
/*
|
||||
* Output source form in debugging format.
|
||||
*/
|
||||
/*
|
||||
* Output source form in debugging format.
|
||||
*/
|
||||
|
||||
paragraph *p;
|
||||
for (p = sourceform; p; p = p->next) {
|
||||
wchar_t *wp;
|
||||
printf("para %d ", p->type);
|
||||
if (p->keyword) {
|
||||
wp = p->keyword;
|
||||
while (*wp) {
|
||||
putchar('\"');
|
||||
for (; *wp; wp++)
|
||||
putchar(*wp);
|
||||
putchar('\"');
|
||||
if (*++wp)
|
||||
printf(", ");
|
||||
}
|
||||
} else
|
||||
printf("(no keyword)");
|
||||
printf(" {\n");
|
||||
dbg_prtwordlist(1, p->words);
|
||||
printf("}\n");
|
||||
}
|
||||
paragraph *p;
|
||||
for (p = sourceform; p; p = p->next)
|
||||
{
|
||||
wchar_t *wp;
|
||||
printf("para %d ", p->type);
|
||||
if (p->keyword)
|
||||
{
|
||||
wp = p->keyword;
|
||||
while (*wp)
|
||||
{
|
||||
putchar('\"');
|
||||
for (; *wp; wp++)
|
||||
putchar(*wp);
|
||||
putchar('\"');
|
||||
if (*++wp)
|
||||
printf(", ");
|
||||
}
|
||||
} else
|
||||
printf("(no keyword)");
|
||||
printf(" {\n");
|
||||
dbg_prtwordlist(1, p->words);
|
||||
printf("}\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void dbg_prtkws(keywordlist * kws)
|
||||
{
|
||||
/*
|
||||
* Output keywords in debugging format.
|
||||
*/
|
||||
/*
|
||||
* Output keywords in debugging format.
|
||||
*/
|
||||
|
||||
int i;
|
||||
keyword *kw;
|
||||
int i;
|
||||
keyword *kw;
|
||||
|
||||
for (i = 0; (kw = index234(kws->keys, i)) != NULL; i++) {
|
||||
wchar_t *wp;
|
||||
printf("keyword ");
|
||||
wp = kw->key;
|
||||
while (*wp) {
|
||||
putchar('\"');
|
||||
for (; *wp; wp++)
|
||||
putchar(*wp);
|
||||
putchar('\"');
|
||||
if (*++wp)
|
||||
printf(", ");
|
||||
}
|
||||
printf(" {\n");
|
||||
dbg_prtwordlist(1, kw->text);
|
||||
printf("}\n");
|
||||
for (i = 0; (kw = index234(kws->keys, i)) != NULL; i++)
|
||||
{
|
||||
wchar_t *wp;
|
||||
printf("keyword ");
|
||||
wp = kw->key;
|
||||
while (*wp)
|
||||
{
|
||||
putchar('\"');
|
||||
for (; *wp; wp++)
|
||||
putchar(*wp);
|
||||
putchar('\"');
|
||||
if (*++wp)
|
||||
printf(", ");
|
||||
}
|
||||
printf(" {\n");
|
||||
dbg_prtwordlist(1, kw->text);
|
||||
printf("}\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void dbg_prtwordlist(int level, word * w)
|
||||
{
|
||||
for (; w; w = w->next) {
|
||||
wchar_t *wp;
|
||||
printf("%*sword %d ", level * 4, "", w->type);
|
||||
if (w->text) {
|
||||
printf("\"");
|
||||
for (wp = w->text; *wp; wp++)
|
||||
putchar(*wp);
|
||||
printf("\"");
|
||||
} else
|
||||
printf("(no text)");
|
||||
if (w->alt) {
|
||||
printf(" alt = {\n");
|
||||
dbg_prtwordlist(level + 1, w->alt);
|
||||
printf("%*s}", level * 4, "");
|
||||
}
|
||||
printf("\n");
|
||||
for (; w; w = w->next)
|
||||
{
|
||||
wchar_t *wp;
|
||||
printf("%*sword %d ", level * 4, "", w->type);
|
||||
if (w->text)
|
||||
{
|
||||
printf("\"");
|
||||
for (wp = w->text; *wp; wp++)
|
||||
putchar(*wp);
|
||||
printf("\"");
|
||||
} else
|
||||
printf("(no text)");
|
||||
if (w->alt)
|
||||
{
|
||||
printf(" alt = {\n");
|
||||
dbg_prtwordlist(level + 1, w->alt);
|
||||
printf("%*s}", level * 4, "");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,28 +9,30 @@
|
|||
#ifdef LOGALLOC
|
||||
#define LOGPARAMS char *file, int line,
|
||||
static FILE *logallocfp = NULL;
|
||||
static int logline = 2; /* off by 1: `null pointer is' */
|
||||
static int logline = 2; /* off by 1: `null pointer is' */
|
||||
static void loginc(void)
|
||||
{
|
||||
}
|
||||
static void logallocinit(void)
|
||||
{
|
||||
if (!logallocfp) {
|
||||
logallocfp = fopen("malloc.log", "w");
|
||||
if (!logallocfp) {
|
||||
fprintf(stderr, "panic: unable to open malloc.log\n");
|
||||
exit(10);
|
||||
}
|
||||
setvbuf(logallocfp, NULL, _IOLBF, BUFSIZ);
|
||||
fprintf(logallocfp, "null pointer is %p\n", NULL);
|
||||
if (!logallocfp)
|
||||
{
|
||||
logallocfp = fopen("malloc.log", "w");
|
||||
if (!logallocfp)
|
||||
{
|
||||
fprintf(stderr, "panic: unable to open malloc.log\n");
|
||||
exit(10);
|
||||
}
|
||||
setvbuf(logallocfp, NULL, _IOLBF, BUFSIZ);
|
||||
fprintf(logallocfp, "null pointer is %p\n", NULL);
|
||||
}
|
||||
}
|
||||
static void logprintf(char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(logallocfp, fmt, ap);
|
||||
va_end(ap);
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(logallocfp, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#define LOGPRINT(x) ( logallocinit(), logprintf x )
|
||||
|
@ -46,46 +48,49 @@ static void logprintf(char *fmt, ...)
|
|||
* can do nothing except die when it's out of memory anyway.
|
||||
*/
|
||||
void *(smalloc) (LOGPARAMS int size) {
|
||||
void *p;
|
||||
LOGINC;
|
||||
LOGPRINT(("%s %d malloc(%ld)", file, line, (long) size));
|
||||
p = malloc(size);
|
||||
if (!p)
|
||||
fatal(err_nomemory);
|
||||
LOGPRINT((" returns %p\n", p));
|
||||
return p;
|
||||
void *p;
|
||||
LOGINC;
|
||||
LOGPRINT(("%s %d malloc(%ld)", file, line, (long) size));
|
||||
p = malloc(size);
|
||||
if (!p)
|
||||
fatal(err_nomemory);
|
||||
LOGPRINT((" returns %p\n", p));
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* sfree should guaranteeably deal gracefully with freeing NULL
|
||||
*/
|
||||
void (sfree) (LOGPARAMS void *p) {
|
||||
if (p) {
|
||||
LOGINC;
|
||||
LOGPRINT(("%s %d free(%p)\n", file, line, p));
|
||||
free(p);
|
||||
}
|
||||
if (p)
|
||||
{
|
||||
LOGINC;
|
||||
LOGPRINT(("%s %d free(%p)\n", file, line, p));
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* srealloc should guaranteeably be able to realloc NULL
|
||||
*/
|
||||
void *(srealloc) (LOGPARAMS void *p, int size) {
|
||||
void *q;
|
||||
if (p) {
|
||||
LOGINC;
|
||||
LOGPRINT(("%s %d realloc(%p,%ld)", file, line, p, (long) size));
|
||||
q = realloc(p, size);
|
||||
LOGPRINT((" returns %p\n", q));
|
||||
} else {
|
||||
LOGINC;
|
||||
LOGPRINT(("%s %d malloc(%ld)", file, line, (long) size));
|
||||
q = malloc(size);
|
||||
LOGPRINT((" returns %p\n", q));
|
||||
}
|
||||
if (!q)
|
||||
fatal(err_nomemory);
|
||||
return q;
|
||||
void *q;
|
||||
if (p)
|
||||
{
|
||||
LOGINC;
|
||||
LOGPRINT(("%s %d realloc(%p,%ld)", file, line, p, (long) size));
|
||||
q = realloc(p, size);
|
||||
LOGPRINT((" returns %p\n", q));
|
||||
} else
|
||||
{
|
||||
LOGINC;
|
||||
LOGPRINT(("%s %d malloc(%ld)", file, line, (long) size));
|
||||
q = malloc(size);
|
||||
LOGPRINT((" returns %p\n", q));
|
||||
}
|
||||
if (!q)
|
||||
fatal(err_nomemory);
|
||||
return q;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -94,9 +99,9 @@ void *(srealloc) (LOGPARAMS void *p, int size) {
|
|||
*/
|
||||
char *dupstr(char *s)
|
||||
{
|
||||
char *r = smalloc(1 + strlen(s));
|
||||
strcpy(r, s);
|
||||
return r;
|
||||
char *r = smalloc(1 + strlen(s));
|
||||
strcpy(r, s);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -104,22 +109,23 @@ char *dupstr(char *s)
|
|||
*/
|
||||
word *dup_word_list(word * w)
|
||||
{
|
||||
word *head, **eptr = &head;
|
||||
word *head, **eptr = &head;
|
||||
|
||||
while (w) {
|
||||
word *newwd = mknew(word);
|
||||
*newwd = *w; /* structure copy */
|
||||
newwd->text = ustrdup(w->text);
|
||||
if (w->alt)
|
||||
newwd->alt = dup_word_list(w->alt);
|
||||
*eptr = newwd;
|
||||
newwd->next = NULL;
|
||||
eptr = &newwd->next;
|
||||
while (w)
|
||||
{
|
||||
word *newwd = mknew(word);
|
||||
*newwd = *w; /* structure copy */
|
||||
newwd->text = ustrdup(w->text);
|
||||
if (w->alt)
|
||||
newwd->alt = dup_word_list(w->alt);
|
||||
*eptr = newwd;
|
||||
newwd->next = NULL;
|
||||
eptr = &newwd->next;
|
||||
|
||||
w = w->next;
|
||||
}
|
||||
w = w->next;
|
||||
}
|
||||
|
||||
return head;
|
||||
return head;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -127,15 +133,16 @@ word *dup_word_list(word * w)
|
|||
*/
|
||||
void free_word_list(word * w)
|
||||
{
|
||||
word *t;
|
||||
while (w) {
|
||||
t = w;
|
||||
w = w->next;
|
||||
sfree(t->text);
|
||||
if (t->alt)
|
||||
free_word_list(t->alt);
|
||||
sfree(t);
|
||||
}
|
||||
word *t;
|
||||
while (w)
|
||||
{
|
||||
t = w;
|
||||
w = w->next;
|
||||
sfree(t->text);
|
||||
if (t->alt)
|
||||
free_word_list(t->alt);
|
||||
sfree(t);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -143,12 +150,13 @@ void free_word_list(word * w)
|
|||
*/
|
||||
void free_para_list(paragraph * p)
|
||||
{
|
||||
paragraph *t;
|
||||
while (p) {
|
||||
t = p;
|
||||
p = p->next;
|
||||
sfree(t->keyword);
|
||||
free_word_list(t->words);
|
||||
sfree(t);
|
||||
}
|
||||
paragraph *t;
|
||||
while (p)
|
||||
{
|
||||
t = p;
|
||||
p = p->next;
|
||||
sfree(t->keyword);
|
||||
free_word_list(t->words);
|
||||
sfree(t);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,44 +5,45 @@
|
|||
#include "halibut.h"
|
||||
|
||||
struct stackTag {
|
||||
void **data;
|
||||
int sp;
|
||||
int size;
|
||||
void **data;
|
||||
int sp;
|
||||
int size;
|
||||
};
|
||||
|
||||
stack stk_new(void)
|
||||
{
|
||||
stack s;
|
||||
stack s;
|
||||
|
||||
s = mknew(struct stackTag);
|
||||
s->sp = 0;
|
||||
s->size = 0;
|
||||
s->data = NULL;
|
||||
s = mknew(struct stackTag);
|
||||
s->sp = 0;
|
||||
s->size = 0;
|
||||
s->data = NULL;
|
||||
|
||||
return s;
|
||||
return s;
|
||||
}
|
||||
|
||||
void stk_free(stack s)
|
||||
{
|
||||
sfree(s->data);
|
||||
sfree(s);
|
||||
sfree(s->data);
|
||||
sfree(s);
|
||||
}
|
||||
|
||||
void stk_push(stack s, void *item)
|
||||
{
|
||||
if (s->size <= s->sp) {
|
||||
s->size = s->sp + 32;
|
||||
s->data = resize(s->data, s->size);
|
||||
}
|
||||
s->data[s->sp++] = item;
|
||||
if (s->size <= s->sp)
|
||||
{
|
||||
s->size = s->sp + 32;
|
||||
s->data = resize(s->data, s->size);
|
||||
}
|
||||
s->data[s->sp++] = item;
|
||||
}
|
||||
|
||||
void *stk_pop(stack s)
|
||||
{
|
||||
if (s->sp > 0)
|
||||
return s->data[--s->sp];
|
||||
else
|
||||
return NULL;
|
||||
if (s->sp > 0)
|
||||
return s->data[--s->sp];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -53,279 +54,304 @@ const rdstringc empty_rdstringc = { 0, 0, NULL };
|
|||
|
||||
void rdadd(rdstring * rs, wchar_t c)
|
||||
{
|
||||
if (rs->pos >= rs->size - 1) {
|
||||
rs->size = rs->pos + 128;
|
||||
rs->text = resize(rs->text, rs->size);
|
||||
}
|
||||
rs->text[rs->pos++] = c;
|
||||
rs->text[rs->pos] = 0;
|
||||
if (rs->pos >= rs->size - 1)
|
||||
{
|
||||
rs->size = rs->pos + 128;
|
||||
rs->text = resize(rs->text, rs->size);
|
||||
}
|
||||
rs->text[rs->pos++] = c;
|
||||
rs->text[rs->pos] = 0;
|
||||
}
|
||||
|
||||
void rdadds(rdstring * rs, wchar_t * p)
|
||||
{
|
||||
int len = ustrlen(p);
|
||||
if (rs->pos >= rs->size - len) {
|
||||
rs->size = rs->pos + len + 128;
|
||||
rs->text = resize(rs->text, rs->size);
|
||||
}
|
||||
ustrcpy(rs->text + rs->pos, p);
|
||||
rs->pos += len;
|
||||
int len = ustrlen(p);
|
||||
if (rs->pos >= rs->size - len)
|
||||
{
|
||||
rs->size = rs->pos + len + 128;
|
||||
rs->text = resize(rs->text, rs->size);
|
||||
}
|
||||
ustrcpy(rs->text + rs->pos, p);
|
||||
rs->pos += len;
|
||||
}
|
||||
|
||||
wchar_t *rdtrim(rdstring * rs)
|
||||
{
|
||||
rs->text = resize(rs->text, rs->pos + 1);
|
||||
return rs->text;
|
||||
rs->text = resize(rs->text, rs->pos + 1);
|
||||
return rs->text;
|
||||
}
|
||||
|
||||
void rdaddc(rdstringc * rs, char c)
|
||||
{
|
||||
if (rs->pos >= rs->size - 1) {
|
||||
rs->size = rs->pos + 128;
|
||||
rs->text = resize(rs->text, rs->size);
|
||||
}
|
||||
rs->text[rs->pos++] = c;
|
||||
rs->text[rs->pos] = 0;
|
||||
if (rs->pos >= rs->size - 1)
|
||||
{
|
||||
rs->size = rs->pos + 128;
|
||||
rs->text = resize(rs->text, rs->size);
|
||||
}
|
||||
rs->text[rs->pos++] = c;
|
||||
rs->text[rs->pos] = 0;
|
||||
}
|
||||
|
||||
void rdaddsc(rdstringc * rs, char *p)
|
||||
{
|
||||
int len = strlen(p);
|
||||
if (rs->pos >= rs->size - len) {
|
||||
rs->size = rs->pos + len + 128;
|
||||
rs->text = resize(rs->text, rs->size);
|
||||
}
|
||||
strcpy(rs->text + rs->pos, p);
|
||||
rs->pos += len;
|
||||
int len = strlen(p);
|
||||
if (rs->pos >= rs->size - len)
|
||||
{
|
||||
rs->size = rs->pos + len + 128;
|
||||
rs->text = resize(rs->text, rs->size);
|
||||
}
|
||||
strcpy(rs->text + rs->pos, p);
|
||||
rs->pos += len;
|
||||
}
|
||||
|
||||
char *rdtrimc(rdstringc * rs)
|
||||
{
|
||||
rs->text = resize(rs->text, rs->pos + 1);
|
||||
return rs->text;
|
||||
rs->text = resize(rs->text, rs->pos + 1);
|
||||
return rs->text;
|
||||
}
|
||||
|
||||
int compare_wordlists(word * a, word * b)
|
||||
{
|
||||
int t;
|
||||
while (a && b) {
|
||||
if (a->type != b->type)
|
||||
return (a->type < b->type ? -1 : +1); /* FIXME? */
|
||||
t = a->type;
|
||||
if ((t != word_Normal && t != word_Code &&
|
||||
t != word_WeakCode && t != word_Emph) || a->alt || b->alt) {
|
||||
int c;
|
||||
if (a->text && b->text) {
|
||||
c = ustricmp(a->text, b->text);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
c = compare_wordlists(a->alt, b->alt);
|
||||
if (c)
|
||||
return c;
|
||||
a = a->next;
|
||||
b = b->next;
|
||||
} else {
|
||||
wchar_t *ap = a->text, *bp = b->text;
|
||||
while (*ap && *bp) {
|
||||
wchar_t ac = utolower(*ap), bc = utolower(*bp);
|
||||
if (ac != bc)
|
||||
return (ac < bc ? -1 : +1);
|
||||
if (!*++ap && a->next && a->next->type == t
|
||||
&& !a->next->alt)
|
||||
a = a->next, ap = a->text;
|
||||
if (!*++bp && b->next && b->next->type == t
|
||||
&& !b->next->alt)
|
||||
b = b->next, bp = b->text;
|
||||
}
|
||||
if (*ap || *bp)
|
||||
return (*ap ? +1 : -1);
|
||||
a = a->next;
|
||||
b = b->next;
|
||||
}
|
||||
int t;
|
||||
while (a && b)
|
||||
{
|
||||
if (a->type != b->type)
|
||||
return (a->type < b->type ? -1 : +1); /* FIXME? */
|
||||
t = a->type;
|
||||
if ((t != word_Normal && t != word_Code &&
|
||||
t != word_WeakCode && t != word_Emph) || a->alt || b->alt)
|
||||
{
|
||||
int c;
|
||||
if (a->text && b->text)
|
||||
{
|
||||
c = ustricmp(a->text, b->text);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
c = compare_wordlists(a->alt, b->alt);
|
||||
if (c)
|
||||
return c;
|
||||
a = a->next;
|
||||
b = b->next;
|
||||
} else
|
||||
{
|
||||
wchar_t *ap = a->text, *bp = b->text;
|
||||
while (*ap && *bp)
|
||||
{
|
||||
wchar_t ac = utolower(*ap), bc = utolower(*bp);
|
||||
if (ac != bc)
|
||||
return (ac < bc ? -1 : +1);
|
||||
if (!*++ap && a->next && a->next->type == t && !a->next->alt)
|
||||
a = a->next, ap = a->text;
|
||||
if (!*++bp && b->next && b->next->type == t && !b->next->alt)
|
||||
b = b->next, bp = b->text;
|
||||
}
|
||||
if (*ap || *bp)
|
||||
return (*ap ? +1 : -1);
|
||||
a = a->next;
|
||||
b = b->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (a || b)
|
||||
return (a ? +1 : -1);
|
||||
else
|
||||
return 0;
|
||||
if (a || b)
|
||||
return (a ? +1 : -1);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mark_attr_ends(paragraph * sourceform)
|
||||
{
|
||||
paragraph *p;
|
||||
word *w, *wp;
|
||||
for (p = sourceform; p; p = p->next) {
|
||||
wp = NULL;
|
||||
for (w = p->words; w; w = w->next) {
|
||||
if (isattr(w->type)) {
|
||||
int before = (wp && isattr(wp->type) &&
|
||||
sameattr(wp->type, w->type));
|
||||
int after = (w->next && isattr(w->next->type) &&
|
||||
sameattr(w->next->type, w->type));
|
||||
w->aux |= (before ?
|
||||
(after ? attr_Always : attr_Last) :
|
||||
(after ? attr_First : attr_Only));
|
||||
}
|
||||
wp = w;
|
||||
}
|
||||
paragraph *p;
|
||||
word *w, *wp;
|
||||
for (p = sourceform; p; p = p->next)
|
||||
{
|
||||
wp = NULL;
|
||||
for (w = p->words; w; w = w->next)
|
||||
{
|
||||
if (isattr(w->type))
|
||||
{
|
||||
int before = (wp && isattr(wp->type) &&
|
||||
sameattr(wp->type, w->type));
|
||||
int after = (w->next && isattr(w->next->type) &&
|
||||
sameattr(w->next->type, w->type));
|
||||
w->aux |= (before ?
|
||||
(after ? attr_Always : attr_Last) :
|
||||
(after ? attr_First : attr_Only));
|
||||
}
|
||||
wp = w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wrappedline *wrap_para(word * text, int width, int subsequentwidth,
|
||||
int (*widthfn) (word *))
|
||||
int (*widthfn) (word *))
|
||||
{
|
||||
wrappedline *head = NULL, **ptr = &head;
|
||||
int nwords, wordsize;
|
||||
struct wrapword {
|
||||
word *begin, *end;
|
||||
int width;
|
||||
int spacewidth;
|
||||
int cost;
|
||||
int nwords;
|
||||
} *wrapwords;
|
||||
int i, j, n;
|
||||
wrappedline *head = NULL, **ptr = &head;
|
||||
int nwords, wordsize;
|
||||
struct wrapword {
|
||||
word *begin, *end;
|
||||
int width;
|
||||
int spacewidth;
|
||||
int cost;
|
||||
int nwords;
|
||||
} *wrapwords;
|
||||
int i, j, n;
|
||||
|
||||
/*
|
||||
* Break the line up into wrappable components.
|
||||
*/
|
||||
nwords = wordsize = 0;
|
||||
wrapwords = NULL;
|
||||
while (text)
|
||||
{
|
||||
if (nwords >= wordsize)
|
||||
{
|
||||
wordsize = nwords + 64;
|
||||
wrapwords = srealloc(wrapwords, wordsize * sizeof(*wrapwords));
|
||||
}
|
||||
wrapwords[nwords].width = 0;
|
||||
wrapwords[nwords].begin = text;
|
||||
while (text)
|
||||
{
|
||||
wrapwords[nwords].width += widthfn(text);
|
||||
wrapwords[nwords].end = text->next;
|
||||
if (text->next && (text->next->type == word_WhiteSpace ||
|
||||
text->next->type == word_EmphSpace ||
|
||||
text->breaks))
|
||||
break;
|
||||
text = text->next;
|
||||
}
|
||||
if (text && text->next && (text->next->type == word_WhiteSpace ||
|
||||
text->next->type == word_EmphSpace))
|
||||
{
|
||||
wrapwords[nwords].spacewidth = widthfn(text->next);
|
||||
text = text->next;
|
||||
} else
|
||||
{
|
||||
wrapwords[nwords].spacewidth = 0;
|
||||
}
|
||||
nwords++;
|
||||
if (text)
|
||||
text = text->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the dynamic wrapping algorithm: work backwards from
|
||||
* nwords-1, determining the optimal wrapping for each terminal
|
||||
* subsequence of the paragraph.
|
||||
*/
|
||||
for (i = nwords; i--;)
|
||||
{
|
||||
int best = -1;
|
||||
int bestcost = 0;
|
||||
int cost;
|
||||
int linelen = 0, spacewidth = 0;
|
||||
int seenspace;
|
||||
int thiswidth = (i == 0 ? width : subsequentwidth);
|
||||
|
||||
j = 0;
|
||||
seenspace = 0;
|
||||
while (i + j < nwords)
|
||||
{
|
||||
/*
|
||||
* See what happens if we put j+1 words on this line.
|
||||
*/
|
||||
if (spacewidth)
|
||||
seenspace = 1;
|
||||
linelen += spacewidth + wrapwords[i + j].width;
|
||||
spacewidth = wrapwords[i + j].spacewidth;
|
||||
j++;
|
||||
if (linelen > thiswidth)
|
||||
{
|
||||
/*
|
||||
* If we're over the width limit, abandon ship,
|
||||
* _unless_ there is no best-effort yet (which will
|
||||
* only happen if the first word is too long all by
|
||||
* itself).
|
||||
*/
|
||||
if (best > 0)
|
||||
break;
|
||||
}
|
||||
if (i + j == nwords)
|
||||
{
|
||||
/*
|
||||
* Special case: if we're at the very end of the
|
||||
* paragraph, we don't score penalty points for the
|
||||
* white space left on the line.
|
||||
*/
|
||||
cost = 0;
|
||||
} else
|
||||
{
|
||||
cost = (thiswidth - linelen) * (thiswidth - linelen);
|
||||
cost += wrapwords[i + j].cost;
|
||||
}
|
||||
/*
|
||||
* We compare bestcost >= cost, not bestcost > cost,
|
||||
* because in cases where the costs are identical we
|
||||
* want to try to look like the greedy algorithm,
|
||||
* because readers are likely to have spent a lot of
|
||||
* time looking at greedy-wrapped paragraphs and
|
||||
* there's no point violating the Principle of Least
|
||||
* Surprise if it doesn't actually gain anything.
|
||||
*/
|
||||
if (best < 0 || bestcost >= cost)
|
||||
{
|
||||
bestcost = cost;
|
||||
best = j;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Now we know the optimal answer for this terminal
|
||||
* subsequence, so put it in wrapwords.
|
||||
*/
|
||||
wrapwords[i].cost = bestcost;
|
||||
wrapwords[i].nwords = best;
|
||||
}
|
||||
|
||||
/*
|
||||
* We've wrapped the paragraph. Now build the output
|
||||
* `wrappedline' list.
|
||||
*/
|
||||
i = 0;
|
||||
while (i < nwords)
|
||||
{
|
||||
wrappedline *w = mknew(wrappedline);
|
||||
*ptr = w;
|
||||
ptr = &w->next;
|
||||
w->next = NULL;
|
||||
|
||||
n = wrapwords[i].nwords;
|
||||
w->begin = wrapwords[i].begin;
|
||||
w->end = wrapwords[i + n - 1].end;
|
||||
|
||||
/*
|
||||
* Break the line up into wrappable components.
|
||||
* Count along the words to find nspaces and shortfall.
|
||||
*/
|
||||
nwords = wordsize = 0;
|
||||
wrapwords = NULL;
|
||||
while (text) {
|
||||
if (nwords >= wordsize) {
|
||||
wordsize = nwords + 64;
|
||||
wrapwords = srealloc(wrapwords, wordsize * sizeof(*wrapwords));
|
||||
}
|
||||
wrapwords[nwords].width = 0;
|
||||
wrapwords[nwords].begin = text;
|
||||
while (text) {
|
||||
wrapwords[nwords].width += widthfn(text);
|
||||
wrapwords[nwords].end = text->next;
|
||||
if (text->next && (text->next->type == word_WhiteSpace ||
|
||||
text->next->type == word_EmphSpace ||
|
||||
text->breaks))
|
||||
break;
|
||||
text = text->next;
|
||||
}
|
||||
if (text && text->next && (text->next->type == word_WhiteSpace ||
|
||||
text->next->type == word_EmphSpace)) {
|
||||
wrapwords[nwords].spacewidth = widthfn(text->next);
|
||||
text = text->next;
|
||||
} else {
|
||||
wrapwords[nwords].spacewidth = 0;
|
||||
}
|
||||
nwords++;
|
||||
if (text)
|
||||
text = text->next;
|
||||
w->nspaces = 0;
|
||||
w->shortfall = width;
|
||||
for (j = 0; j < n; j++)
|
||||
{
|
||||
w->shortfall -= wrapwords[i + j].width;
|
||||
if (j < n - 1 && wrapwords[i + j].spacewidth)
|
||||
{
|
||||
w->nspaces++;
|
||||
w->shortfall -= wrapwords[i + j].spacewidth;
|
||||
}
|
||||
}
|
||||
i += n;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the dynamic wrapping algorithm: work backwards from
|
||||
* nwords-1, determining the optimal wrapping for each terminal
|
||||
* subsequence of the paragraph.
|
||||
*/
|
||||
for (i = nwords; i--;) {
|
||||
int best = -1;
|
||||
int bestcost = 0;
|
||||
int cost;
|
||||
int linelen = 0, spacewidth = 0;
|
||||
int seenspace;
|
||||
int thiswidth = (i == 0 ? width : subsequentwidth);
|
||||
sfree(wrapwords);
|
||||
|
||||
j = 0;
|
||||
seenspace = 0;
|
||||
while (i + j < nwords) {
|
||||
/*
|
||||
* See what happens if we put j+1 words on this line.
|
||||
*/
|
||||
if (spacewidth)
|
||||
seenspace = 1;
|
||||
linelen += spacewidth + wrapwords[i + j].width;
|
||||
spacewidth = wrapwords[i + j].spacewidth;
|
||||
j++;
|
||||
if (linelen > thiswidth) {
|
||||
/*
|
||||
* If we're over the width limit, abandon ship,
|
||||
* _unless_ there is no best-effort yet (which will
|
||||
* only happen if the first word is too long all by
|
||||
* itself).
|
||||
*/
|
||||
if (best > 0)
|
||||
break;
|
||||
}
|
||||
if (i + j == nwords) {
|
||||
/*
|
||||
* Special case: if we're at the very end of the
|
||||
* paragraph, we don't score penalty points for the
|
||||
* white space left on the line.
|
||||
*/
|
||||
cost = 0;
|
||||
} else {
|
||||
cost = (thiswidth - linelen) * (thiswidth - linelen);
|
||||
cost += wrapwords[i + j].cost;
|
||||
}
|
||||
/*
|
||||
* We compare bestcost >= cost, not bestcost > cost,
|
||||
* because in cases where the costs are identical we
|
||||
* want to try to look like the greedy algorithm,
|
||||
* because readers are likely to have spent a lot of
|
||||
* time looking at greedy-wrapped paragraphs and
|
||||
* there's no point violating the Principle of Least
|
||||
* Surprise if it doesn't actually gain anything.
|
||||
*/
|
||||
if (best < 0 || bestcost >= cost) {
|
||||
bestcost = cost;
|
||||
best = j;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Now we know the optimal answer for this terminal
|
||||
* subsequence, so put it in wrapwords.
|
||||
*/
|
||||
wrapwords[i].cost = bestcost;
|
||||
wrapwords[i].nwords = best;
|
||||
}
|
||||
|
||||
/*
|
||||
* We've wrapped the paragraph. Now build the output
|
||||
* `wrappedline' list.
|
||||
*/
|
||||
i = 0;
|
||||
while (i < nwords) {
|
||||
wrappedline *w = mknew(wrappedline);
|
||||
*ptr = w;
|
||||
ptr = &w->next;
|
||||
w->next = NULL;
|
||||
|
||||
n = wrapwords[i].nwords;
|
||||
w->begin = wrapwords[i].begin;
|
||||
w->end = wrapwords[i + n - 1].end;
|
||||
|
||||
/*
|
||||
* Count along the words to find nspaces and shortfall.
|
||||
*/
|
||||
w->nspaces = 0;
|
||||
w->shortfall = width;
|
||||
for (j = 0; j < n; j++) {
|
||||
w->shortfall -= wrapwords[i + j].width;
|
||||
if (j < n - 1 && wrapwords[i + j].spacewidth) {
|
||||
w->nspaces++;
|
||||
w->shortfall -= wrapwords[i + j].spacewidth;
|
||||
}
|
||||
}
|
||||
i += n;
|
||||
}
|
||||
|
||||
sfree(wrapwords);
|
||||
|
||||
return head;
|
||||
return head;
|
||||
}
|
||||
|
||||
void wrap_free(wrappedline * w)
|
||||
{
|
||||
while (w) {
|
||||
wrappedline *t = w->next;
|
||||
sfree(w);
|
||||
w = t;
|
||||
}
|
||||
while (w)
|
||||
{
|
||||
wrappedline *t = w->next;
|
||||
sfree(w);
|
||||
w = t;
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -126,13 +126,13 @@ void *index234(tree234 * t, int index);
|
|||
* consume(p);
|
||||
*/
|
||||
enum {
|
||||
REL234_EQ, REL234_LT, REL234_LE, REL234_GT, REL234_GE
|
||||
REL234_EQ, REL234_LT, REL234_LE, REL234_GT, REL234_GE
|
||||
};
|
||||
void *find234(tree234 * t, void *e, cmpfn234 cmp);
|
||||
void *findrel234(tree234 * t, void *e, cmpfn234 cmp, int relation);
|
||||
void *findpos234(tree234 * t, void *e, cmpfn234 cmp, int *index);
|
||||
void *findrelpos234(tree234 * t, void *e, cmpfn234 cmp, int relation,
|
||||
int *index);
|
||||
int *index);
|
||||
|
||||
/*
|
||||
* Delete an element e in a 2-3-4 tree. Does not free the element,
|
||||
|
@ -199,4 +199,4 @@ tree234 *join234r(tree234 * t1, tree234 * t2);
|
|||
*/
|
||||
tree234 *copytree234(tree234 * t, copyfn234 copyfn, void *copyfnstate);
|
||||
|
||||
#endif /* TREE234_H */
|
||||
#endif /* TREE234_H */
|
||||
|
|
|
@ -8,185 +8,194 @@
|
|||
|
||||
wchar_t *ustrdup(wchar_t * s)
|
||||
{
|
||||
wchar_t *r;
|
||||
if (s) {
|
||||
r = mknewa(wchar_t, 1 + ustrlen(s));
|
||||
ustrcpy(r, s);
|
||||
} else {
|
||||
r = mknew(wchar_t);
|
||||
*r = 0;
|
||||
}
|
||||
return r;
|
||||
wchar_t *r;
|
||||
if (s)
|
||||
{
|
||||
r = mknewa(wchar_t, 1 + ustrlen(s));
|
||||
ustrcpy(r, s);
|
||||
} else
|
||||
{
|
||||
r = mknew(wchar_t);
|
||||
*r = 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
char *ustrtoa(wchar_t * s, char *outbuf, int size)
|
||||
{
|
||||
char *p;
|
||||
if (!s) {
|
||||
*outbuf = '\0';
|
||||
return outbuf;
|
||||
}
|
||||
for (p = outbuf; *s && p < outbuf + size; p++, s++)
|
||||
*p = *s;
|
||||
if (p < outbuf + size)
|
||||
*p = '\0';
|
||||
else
|
||||
outbuf[size - 1] = '\0';
|
||||
char *p;
|
||||
if (!s)
|
||||
{
|
||||
*outbuf = '\0';
|
||||
return outbuf;
|
||||
}
|
||||
for (p = outbuf; *s && p < outbuf + size; p++, s++)
|
||||
*p = *s;
|
||||
if (p < outbuf + size)
|
||||
*p = '\0';
|
||||
else
|
||||
outbuf[size - 1] = '\0';
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
int ustrlen(wchar_t * s)
|
||||
{
|
||||
int len = 0;
|
||||
while (*s++)
|
||||
len++;
|
||||
return len;
|
||||
int len = 0;
|
||||
while (*s++)
|
||||
len++;
|
||||
return len;
|
||||
}
|
||||
|
||||
wchar_t *uadv(wchar_t * s)
|
||||
{
|
||||
return s + 1 + ustrlen(s);
|
||||
return s + 1 + ustrlen(s);
|
||||
}
|
||||
|
||||
wchar_t *ustrcpy(wchar_t * dest, wchar_t * source)
|
||||
{
|
||||
wchar_t *ret = dest;
|
||||
do {
|
||||
*dest++ = *source;
|
||||
}
|
||||
while (*source++);
|
||||
return ret;
|
||||
wchar_t *ret = dest;
|
||||
do
|
||||
{
|
||||
*dest++ = *source;
|
||||
}
|
||||
while (*source++);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ustrcmp(wchar_t * lhs, wchar_t * rhs)
|
||||
{
|
||||
if (!lhs && !rhs)
|
||||
return 0;
|
||||
if (!lhs)
|
||||
return -1;
|
||||
if (!rhs)
|
||||
return +1;
|
||||
while (*lhs && *rhs && *lhs == *rhs)
|
||||
lhs++, rhs++;
|
||||
if (*lhs < *rhs)
|
||||
return -1;
|
||||
else if (*lhs > *rhs)
|
||||
return 1;
|
||||
if (!lhs && !rhs)
|
||||
return 0;
|
||||
if (!lhs)
|
||||
return -1;
|
||||
if (!rhs)
|
||||
return +1;
|
||||
while (*lhs && *rhs && *lhs == *rhs)
|
||||
lhs++, rhs++;
|
||||
if (*lhs < *rhs)
|
||||
return -1;
|
||||
else if (*lhs > *rhs)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
wchar_t utolower(wchar_t c)
|
||||
{
|
||||
if (c == L'\0')
|
||||
return c; /* this property needed by ustricmp */
|
||||
/* FIXME: this doesn't even come close */
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
c += 'a' - 'A';
|
||||
return c;
|
||||
if (c == L'\0')
|
||||
return c; /* this property needed by ustricmp */
|
||||
/* FIXME: this doesn't even come close */
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
c += 'a' - 'A';
|
||||
return c;
|
||||
}
|
||||
|
||||
int ustricmp(wchar_t * lhs, wchar_t * rhs)
|
||||
{
|
||||
wchar_t lc, rc;
|
||||
while ((lc = utolower(*lhs)) == (rc = utolower(*rhs)) && lc && rc)
|
||||
lhs++, rhs++;
|
||||
if (!lc && !rc)
|
||||
return 0;
|
||||
if (lc < rc)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
wchar_t lc, rc;
|
||||
while ((lc = utolower(*lhs)) == (rc = utolower(*rhs)) && lc && rc)
|
||||
lhs++, rhs++;
|
||||
if (!lc && !rc)
|
||||
return 0;
|
||||
if (lc < rc)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
wchar_t *ustrlow(wchar_t * s)
|
||||
{
|
||||
wchar_t *p = s;
|
||||
while (*p) {
|
||||
*p = utolower(*p);
|
||||
p++;
|
||||
}
|
||||
return s;
|
||||
wchar_t *p = s;
|
||||
while (*p)
|
||||
{
|
||||
*p = utolower(*p);
|
||||
p++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int utoi(wchar_t * s)
|
||||
{
|
||||
int sign = +1;
|
||||
int n;
|
||||
int sign = +1;
|
||||
int n;
|
||||
|
||||
if (*s == L'-') {
|
||||
s++;
|
||||
sign = -1;
|
||||
}
|
||||
if (*s == L'-')
|
||||
{
|
||||
s++;
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
while (*s && *s >= L'0' && *s <= L'9') {
|
||||
n *= 10;
|
||||
n += (*s - '0');
|
||||
s++;
|
||||
}
|
||||
n = 0;
|
||||
while (*s && *s >= L'0' && *s <= L'9')
|
||||
{
|
||||
n *= 10;
|
||||
n += (*s - '0');
|
||||
s++;
|
||||
}
|
||||
|
||||
return n;
|
||||
return n;
|
||||
}
|
||||
|
||||
int utob(wchar_t * s)
|
||||
{
|
||||
if (!ustricmp(s, L"yes") || !ustricmp(s, L"y") ||
|
||||
!ustricmp(s, L"true") || !ustricmp(s, L"t"))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
if (!ustricmp(s, L"yes") || !ustricmp(s, L"y") ||
|
||||
!ustricmp(s, L"true") || !ustricmp(s, L"t"))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int uisdigit(wchar_t c)
|
||||
{
|
||||
return c >= L'0' && c <= L'9';
|
||||
return c >= L'0' && c <= L'9';
|
||||
}
|
||||
|
||||
#define USTRFTIME_DELTA 128
|
||||
wchar_t *ustrftime(wchar_t * wfmt, struct tm * timespec)
|
||||
{
|
||||
void *blk = NULL;
|
||||
wchar_t *wblk, *wp;
|
||||
char *fmt, *text, *p;
|
||||
size_t size = 0;
|
||||
size_t len;
|
||||
void *blk = NULL;
|
||||
wchar_t *wblk, *wp;
|
||||
char *fmt, *text, *p;
|
||||
size_t size = 0;
|
||||
size_t len;
|
||||
|
||||
/*
|
||||
* strftime has the entertaining property that it returns 0
|
||||
* _either_ on out-of-space _or_ on successful generation of
|
||||
* the empty string. Hence we must ensure our format can never
|
||||
* generate the empty string. Somebody throw a custard pie at
|
||||
* whoever was responsible for that. Please?
|
||||
*/
|
||||
if (wfmt) {
|
||||
len = ustrlen(wfmt);
|
||||
fmt = mknewa(char, 2 + len);
|
||||
ustrtoa(wfmt, fmt + 1, len + 1);
|
||||
fmt[0] = ' ';
|
||||
} else
|
||||
fmt = " %c";
|
||||
/*
|
||||
* strftime has the entertaining property that it returns 0
|
||||
* _either_ on out-of-space _or_ on successful generation of
|
||||
* the empty string. Hence we must ensure our format can never
|
||||
* generate the empty string. Somebody throw a custard pie at
|
||||
* whoever was responsible for that. Please?
|
||||
*/
|
||||
if (wfmt)
|
||||
{
|
||||
len = ustrlen(wfmt);
|
||||
fmt = mknewa(char, 2 + len);
|
||||
ustrtoa(wfmt, fmt + 1, len + 1);
|
||||
fmt[0] = ' ';
|
||||
} else
|
||||
fmt = " %c";
|
||||
|
||||
while (1) {
|
||||
size += USTRFTIME_DELTA;
|
||||
blk = resize((char *) blk, size);
|
||||
len = strftime((char *) blk, size - 1, fmt, timespec);
|
||||
if (len > 0)
|
||||
break;
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
size += USTRFTIME_DELTA;
|
||||
blk = resize((char *) blk, size);
|
||||
len = strftime((char *) blk, size - 1, fmt, timespec);
|
||||
if (len > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Note: +1 for the terminating 0, -1 for the initial space in fmt */
|
||||
wblk = resize((wchar_t *) blk, len);
|
||||
text = mknewa(char, len);
|
||||
strftime(text, len, fmt + 1, timespec);
|
||||
/*
|
||||
* We operate in the C locale, so this all ought to be kosher
|
||||
* ASCII. If we ever move outside ASCII machines, we may need
|
||||
* to make this more portable...
|
||||
*/
|
||||
for (wp = wblk, p = text; *p; p++, wp++)
|
||||
*wp = *p;
|
||||
*wp = 0;
|
||||
if (wfmt)
|
||||
sfree(fmt);
|
||||
sfree(text);
|
||||
return wblk;
|
||||
/* Note: +1 for the terminating 0, -1 for the initial space in fmt */
|
||||
wblk = resize((wchar_t *) blk, len);
|
||||
text = mknewa(char, len);
|
||||
strftime(text, len, fmt + 1, timespec);
|
||||
/*
|
||||
* We operate in the C locale, so this all ought to be kosher
|
||||
* ASCII. If we ever move outside ASCII machines, we may need
|
||||
* to make this more portable...
|
||||
*/
|
||||
for (wp = wblk, p = text; *p; p++, wp++)
|
||||
*wp = *p;
|
||||
*wp = 0;
|
||||
if (wfmt)
|
||||
sfree(fmt);
|
||||
sfree(text);
|
||||
return wblk;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue