diff options
| -rw-r--r-- | bk_info.c | 41 | ||||
| -rw-r--r-- | error.c | 14 | ||||
| -rw-r--r-- | halibut.h | 7 | ||||
| -rw-r--r-- | index.c | 15 | ||||
| -rw-r--r-- | input.c | 12 | ||||
| -rw-r--r-- | inputs/errors.but | 8 | ||||
| -rw-r--r-- | main.c | 2 |
7 files changed, 88 insertions, 11 deletions
@@ -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; } @@ -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); @@ -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); @@ -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); @@ -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. @@ -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); |