From f4551933f1b39e3d017ce964cd3284193fb34cbe Mon Sep 17 00:00:00 2001 From: simon Date: Sat, 10 Apr 2004 08:59:19 +0000 Subject: [PATCH] Info backend now takes care to avoid magic characters in node names and index terms (the Info format doesn't like them). In the course of this I've had to introduce some infrastructure for carrying a filepos forward from the definition of every RHS index term so that a particular backend can provide a usefully localised report of which index term had a problem. git-svn-id: svn://svn.tartarus.org/sgt/halibut@4051 cda61777-01e9-0310-a592-d414129be87e --- bk_info.c | 41 +++++++++++++++++++++++++++++++++++------ error.c | 14 ++++++++++++++ halibut.h | 7 ++++++- index.c | 15 +++++++++++++-- input.c | 12 +++++++++++- inputs/errors.but | 8 ++++++++ main.c | 2 +- 7 files changed, 88 insertions(+), 11 deletions(-) diff --git a/bk_info.c b/bk_info.c index 9834610..d4179f2 100644 --- a/bk_info.c +++ b/bk_info.c @@ -4,9 +4,7 @@ * TODO: * * - configurable choice of how to allocate node names - * - escape, warn or simply remove commas and colons in node - * names; also test colons in index terms. - * - might be helpful to diagnose duplicate node names too! + * - might be helpful to diagnose duplicate node names! * - test everything in info(1), and probably jed too * * Later: @@ -184,14 +182,28 @@ void info_backend(paragraph *sourceform, keywordlist *keywords, for (i = 0; (entry = index234(idx->entries, i)) != NULL; i++) { info_idx *ii = mknew(info_idx); rdstringc rs = { 0, 0, NULL }; + char *p, *q; ii->nnodes = ii->nodesize = 0; ii->nodes = NULL; info_rdaddwc(&rs, entry->text, NULL, FALSE); + /* - * FIXME: splatter colons. + * We cannot have colons in index terms, since they + * disrupt the structure of the index menu. Remove any + * that we find, with a warning. */ + p = q = rs.text; + while (*p) { + if (*p == ':') { + error(err_infoindexcolon, &entry->fpos); + } else { + *q++ = *p; + } + p++; + } + ii->text = rs.text; entry->backend_data = ii; @@ -976,10 +988,27 @@ static node *info_node_new(char *name) return n; } -static char *info_node_name(paragraph *p) +static char *info_node_name(paragraph *par) { rdstringc rsc = { 0, 0, NULL }; - info_rdaddwc(&rsc, p->kwtext ? p->kwtext : p->words, NULL, FALSE); + char *p, *q; + info_rdaddwc(&rsc, par->kwtext ? par->kwtext : par->words, NULL, FALSE); + + /* + * We cannot have commas or colons in a node name. Remove any + * that we find, with a warning. + */ + p = q = rsc.text; + while (*p) { + if (*p == ':' || *p == ',') { + error(err_infonodechar, &par->fpos, *p); + } else { + *q++ = *p; + } + p++; + } + *p = '\0'; + return rsc.text; } diff --git a/error.c b/error.c index efa0eb8..3bfa78b 100644 --- a/error.c +++ b/error.c @@ -16,6 +16,7 @@ static void do_error(int code, va_list ap) { char error[1024]; char auxbuf[256]; + char c; char *sp, *sp2; wchar_t *wsp; filepos fpos, fpos2; @@ -207,6 +208,19 @@ static void do_error(int code, va_list ap) { " parameters"); flags = FILEPOS; break; + case err_infoindexcolon: + fpos = *va_arg(ap, filepos *); + sprintf(error, "info output format does not support colons in" + " index terms; removing"); + flags = FILEPOS; + break; + case err_infonodechar: + fpos = *va_arg(ap, filepos *); + c = (char)va_arg(ap, int); + sprintf(error, "info output format does not support '%c' in" + " node names; removing", c); + flags = FILEPOS; + break; case err_whatever: sp = va_arg(ap, char *); vsprintf(error, sp, ap); diff --git a/halibut.h b/halibut.h index 66bb333..24ad3a5 100644 --- a/halibut.h +++ b/halibut.h @@ -219,6 +219,8 @@ enum { err_misplacedlcont, /* \lcont not after a list item */ err_sectmarkerinblock, /* section marker appeared in block */ err_infodirentry, /* \cfg{info-dir-entry} missing param */ + err_infoindexcolon, /* colon in index term in info */ + err_infonodechar, /* colon/comma in node name in info */ err_whatever /* random error of another type */ }; @@ -373,7 +375,9 @@ struct indexdata_Tag { struct indextag_Tag { wchar_t *name; word *implicit_text; + filepos implicit_fpos; word **explicit_texts; + filepos *explicit_fpos; int nexplicit, explicit_size; int nrefs; indexentry **refs; /* array of entries referenced by tag */ @@ -385,13 +389,14 @@ struct indextag_Tag { struct indexentry_Tag { word *text; void *backend_data; /* private to back end */ + filepos fpos; }; indexdata *make_index(void); void cleanup_index(indexdata *); /* index_merge takes responsibility for freeing arg 3 iff implicit; never * takes responsibility for arg 2 */ -void index_merge(indexdata *, int is_explicit, wchar_t *, word *); +void index_merge(indexdata *, int is_explicit, wchar_t *, word *, filepos *); void build_index(indexdata *); void index_debug(indexdata *); indextag *index_findtag(indexdata *idx, wchar_t *name); diff --git a/index.c b/index.c index c312f07..9850750 100644 --- a/index.c +++ b/index.c @@ -21,6 +21,7 @@ static indextag *make_indextag(void) { ret->name = NULL; ret->implicit_text = NULL; ret->explicit_texts = NULL; + ret->explicit_fpos = NULL; ret->nexplicit = ret->explicit_size = ret->nrefs = 0; ret->refs = NULL; return ret; @@ -57,7 +58,8 @@ indextag *index_findtag(indexdata *idx, wchar_t *name) { * Guarantee on calling sequence: all implicit merges are given * before the explicit ones. */ -void index_merge(indexdata *idx, int is_explicit, wchar_t *tags, word *text) { +void index_merge(indexdata *idx, int is_explicit, wchar_t *tags, word *text, + filepos *fpos) { indextag *t, *existing; /* @@ -105,6 +107,7 @@ void index_merge(indexdata *idx, int is_explicit, wchar_t *tags, word *text) { * Otherwise, this is a new tag with an implicit \IM. */ t->implicit_text = text; + t->implicit_fpos = *fpos; } else { sfree(t); t = existing; @@ -130,8 +133,12 @@ void index_merge(indexdata *idx, int is_explicit, wchar_t *tags, word *text) { t->explicit_size = t->nexplicit + 8; t->explicit_texts = resize(t->explicit_texts, t->explicit_size); + t->explicit_fpos = resize(t->explicit_fpos, + t->explicit_size); } - t->explicit_texts[t->nexplicit++] = text; + t->explicit_texts[t->nexplicit] = text; + t->explicit_fpos[t->nexplicit] = *fpos; + t->nexplicit++; } } } @@ -147,6 +154,7 @@ void index_merge(indexdata *idx, int is_explicit, wchar_t *tags, word *text) { void build_index(indexdata *i) { indextag *t; word **ta; + filepos *fa; int ti; int j; @@ -154,15 +162,18 @@ void build_index(indexdata *i) { if (t->implicit_text) { t->nrefs = 1; ta = &t->implicit_text; + fa = &t->implicit_fpos; } else { t->nrefs = t->nexplicit; ta = t->explicit_texts; + fa = t->explicit_fpos; } if (t->nrefs) { t->refs = mknewa(indexentry *, t->nrefs); for (j = 0; j < t->nrefs; j++) { indexentry *ent = mknew(indexentry); ent->text = *ta++; + ent->fpos = *fa++; t->refs[j] = add234(i->entries, ent); if (t->refs[j] != ent) /* duplicate */ sfree(ent); diff --git a/input.c b/input.c index 429b4d5..cb6cf9c 100644 --- a/input.c +++ b/input.c @@ -528,6 +528,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { } type; word **whptr; /* to restore from \u alternatives */ word **idximplicit; /* to restore from \u alternatives */ + filepos fpos; } *sitem; stack parsestk; struct crossparaitem { @@ -988,6 +989,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { /* Error recovery: push nop */ sitem = mknew(struct stack_item); sitem->type = stack_nop; + sitem->fpos = t.pos; stk_push(parsestk, sitem); break; case tok_rbrace: @@ -1024,7 +1026,8 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { } indexing = FALSE; rdadd(&indexstr, L'\0'); - index_merge(idx, FALSE, indexstr.text, idxwordlist); + index_merge(idx, FALSE, indexstr.text, + idxwordlist, &sitem->fpos); sfree(indexstr.text); } if (sitem->type & stack_hyper) { @@ -1110,6 +1113,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { addword(wd, &idximplicit); } sitem = mknew(struct stack_item); + sitem->fpos = t.pos; sitem->type = stack_quote; stk_push(parsestk, sitem); } @@ -1189,6 +1193,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { * Special cases: \W{}\c, \W{}\e, \W{}\cw */ sitem = mknew(struct stack_item); + sitem->fpos = wd.fpos; sitem->type = stack_hyper; if (t.type == tok_cmd && (t.cmd == c_e || t.cmd == c_c || t.cmd == c_cw)) { @@ -1220,6 +1225,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { /* Error recovery: eat lbrace, push nop. */ dtor(t), t = get_token(in); sitem = mknew(struct stack_item); + sitem->fpos = t.pos; sitem->type = stack_nop; stk_push(parsestk, sitem); } @@ -1232,6 +1238,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { word_Emph); spcstyle = tospacestyle(style); sitem = mknew(struct stack_item); + sitem->fpos = t.pos; sitem->type = stack_style; stk_push(parsestk, sitem); } @@ -1245,10 +1252,12 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { /* Error recovery: eat lbrace, push nop. */ dtor(t), t = get_token(in); sitem = mknew(struct stack_item); + sitem->fpos = t.pos; sitem->type = stack_nop; stk_push(parsestk, sitem); } sitem = mknew(struct stack_item); + sitem->fpos = t.pos; sitem->type = stack_idx; dtor(t), t = get_token(in); /* @@ -1318,6 +1327,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) { * paragraph. */ sitem = mknew(struct stack_item); + sitem->fpos = t.pos; sitem->type = stack_ualt; sitem->whptr = whptr; sitem->idximplicit = idximplicit; diff --git a/inputs/errors.but b/inputs/errors.but index 1befc74..758660a 100644 --- a/inputs/errors.but +++ b/inputs/errors.but @@ -8,6 +8,12 @@ Bogus keyword: \k{nonexist} \IM{nonexist3} Logical impossibilities +Fingly \i{eep}. + +\IM{eep} Thing: with a colon + +Flongly \i{eep:sping}. + \define{macro} macro definition \define{macro} same macro again @@ -48,4 +54,6 @@ Complete twaddle: \twaddle. Unclosed brace: \c{foo. +\U Spong, wimble: flomp. + Comment to EOF: \#{ and here we go. diff --git a/main.c b/main.c index ecb2d37..4dec663 100644 --- a/main.c +++ b/main.c @@ -296,7 +296,7 @@ int main(int argc, char **argv) { for (p = sourceform; p; p = p->next) if (p->type == para_IM) - index_merge(idx, TRUE, p->keyword, p->words); + index_merge(idx, TRUE, p->keyword, p->words, &p->fpos); build_index(idx); -- 2.11.0