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:
kichik 2003-04-04 14:43:36 +00:00
parent e1bc9f0971
commit 0e30afb5d9
16 changed files with 6231 additions and 5689 deletions

View file

@ -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, &para->fpos, para->keyword);
} else if (kw->text) {
error(err_multiBR, &para->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, &para->fpos, para->keyword);
} else if (kw->text)
{
error(err_multiBR, &para->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

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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

View file

@ -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;
}
}
}
}

View file

@ -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);
}

View file

@ -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");
}
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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 */

View file

@ -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;
}