summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bk_info.c41
-rw-r--r--error.c14
-rw-r--r--halibut.h7
-rw-r--r--index.c15
-rw-r--r--input.c12
-rw-r--r--inputs/errors.but8
-rw-r--r--main.c2
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);