Info backend now takes care to avoid magic characters in node names
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 10 Apr 2004 08:59:19 +0000 (08:59 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Sat, 10 Apr 2004 08:59:19 +0000 (08:59 +0000)
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
error.c
halibut.h
index.c
input.c
inputs/errors.but
main.c

index 9834610..d4179f2 100644 (file)
--- 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 (file)
--- 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);
index 66bb333..24ad3a5 100644 (file)
--- 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 (file)
--- 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 (file)
--- 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;
index 1befc74..758660a 100644 (file)
@@ -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 (file)
--- 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);