From 3e043306f1594f7528788a1c593995b391fc7a5a Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 25 Oct 2001 19:28:43 +0000 Subject: Enforce proper ordering of heading levels: specifically, ensure the user doesn't skip a heading level (\H before any \C or \A, or \S straight after \C with no intervening \H). The precise criterion is that when creating section a.b.c.d, sections a.b.c, a.b and a should already exist. This ensures the section tree really is a properly formed tree with no missing nodes. [originally from svn r1329] --- buttress.h | 3 ++- contents.c | 11 ++++++++++- error.c | 5 +++++ inputs/errors2.but | 5 +++++ keywords.c | 16 +++++++++++++++- main.c | 2 ++ 6 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 inputs/errors2.but diff --git a/buttress.h b/buttress.h index b07cf0a..8f8961a 100644 --- a/buttress.h +++ b/buttress.h @@ -199,6 +199,7 @@ enum { 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_whatever /* random error of another type */ }; @@ -374,7 +375,7 @@ void index_debug(index *); */ numberstate *number_init(void); void number_cfg(numberstate *, paragraph *); -word *number_mktext(numberstate *, int, int, int, word **); +word *number_mktext(numberstate *, int, int, int, word **, filepos); void number_free(numberstate *); /* diff --git a/contents.c b/contents.c index fee45d9..7688d75 100644 --- a/contents.c +++ b/contents.c @@ -13,6 +13,7 @@ struct numberstate_Tag { int appendixnum; int ischapter; int *sectionlevels; + int oklevel; int maxsectlevel; int listitem; wchar_t *chaptertext; /* the word for a chapter */ @@ -25,6 +26,7 @@ numberstate *number_init(void) { 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->listitem = -1; @@ -114,7 +116,7 @@ void number_cfg(numberstate *state, paragraph *source) { } word *number_mktext(numberstate *state, int para, int aux, int prev, - word **auxret) { + word **auxret, filepos fpos) { word *ret = NULL; word **ret2 = &ret; word **pret = &ret; @@ -130,10 +132,16 @@ word *number_mktext(numberstate *state, int para, int aux, int prev, ret2 = pret; donumber(&pret, state->chapternum); state->ischapter = 1; + state->oklevel = 0; break; case para_Heading: case para_Subsect: level = (para == para_Heading ? 0 : aux); + if (level > state->oklevel) { + error(err_sectjump, &fpos); + return NULL; + } + state->oklevel = level+1; if (state->maxsectlevel <= level) { state->maxsectlevel = level + 32; state->sectionlevels = resize(state->sectionlevels, @@ -165,6 +173,7 @@ word *number_mktext(numberstate *state, int para, int aux, int prev, ret2 = pret; doanumber(&pret, state->appendixnum); state->ischapter = 0; + state->oklevel = 0; break; case para_NumberedList: ret2 = pret; diff --git a/error.c b/error.c index b4a3898..c81aa8c 100644 --- a/error.c +++ b/error.c @@ -162,6 +162,11 @@ static void do_error(int code, va_list ap) { 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_whatever: sp = va_arg(ap, char *); vsprintf(error, sp, ap); diff --git a/inputs/errors2.but b/inputs/errors2.but new file mode 100644 index 0000000..b1a3303 --- /dev/null +++ b/inputs/errors2.but @@ -0,0 +1,5 @@ +\H{outofplace} Heading out of place. + +\C{chap} Chapter is fine + +\S{subsect} Subsection should have heading before it. diff --git a/keywords.c b/keywords.c index d0d0b4d..7dd35b1 100644 --- a/keywords.c +++ b/keywords.c @@ -86,6 +86,7 @@ keyword *kw_lookup(keywordlist *kl, wchar_t *str) { * finish). */ keywordlist *get_keywords(paragraph *source) { + int errors = FALSE; keywordlist *kl = mknew(keywordlist); numberstate *n = number_init(); int prevpara = para_NotParaType; @@ -102,7 +103,15 @@ keywordlist *get_keywords(paragraph *source) { * Number the chapter / section / list-item / whatever. */ source->kwtext = number_mktext(n, source->type, source->aux, - prevpara, &source->kwtext2); + prevpara, &source->kwtext2, + source->fpos); + if (!source->kwtext) { + /* There was an error collecting the section numbers. + * number_mktext has reported it; we record it and bail + * out at the end. */ + errors = TRUE; + continue; + } prevpara = source->type; if (source->keyword && *source->keyword) { @@ -128,6 +137,11 @@ keywordlist *get_keywords(paragraph *source) { number_free(n); + if (errors) { + free_keywords(kl); + return NULL; + } + heap_sort(kl); return kl; diff --git a/main.c b/main.c index 079aba8..b7be46f 100644 --- a/main.c +++ b/main.c @@ -197,6 +197,8 @@ int main(int argc, char **argv) { sfree(infiles); keywords = get_keywords(sourceform); + if (!keywords) + exit(EXIT_FAILURE); gen_citations(sourceform, keywords); subst_keywords(sourceform, keywords); -- cgit v1.1