Info backend now takes care to avoid magic characters in node names
[sgt/halibut] / input.c
diff --git a/input.c b/input.c
index db862dd..cb6cf9c 100644 (file)
--- a/input.c
+++ b/input.c
@@ -162,6 +162,7 @@ enum {
     c__invalid,                               /* invalid command */
     c__comment,                               /* comment command (\#) */
     c__escaped,                               /* escaped character */
+    c__nop,                           /* no-op */
     c__nbsp,                          /* nonbreaking space */
     c_A,                              /* appendix heading */
     c_B,                              /* bibliography entry */
@@ -190,7 +191,7 @@ enum {
     c_lcont,                          /* continuation para(s) for list item */
     c_n,                              /* numbered list */
     c_nocite,                         /* bibliography trickery */
-    c_preamble,                               /* document preamble text */
+    c_preamble,                               /* (obsolete) preamble text */
     c_q,                              /* quote marks */
     c_quote,                          /* block-quoted paragraphs */
     c_rule,                           /* horizontal rule */
@@ -231,6 +232,7 @@ static void match_kw(token *tok) {
     static const struct { char const *name; int id; } keywords[] = {
        {"#", c__comment},             /* comment command (\#) */
        {"-", c__escaped},             /* nonbreaking hyphen */
+       {".", c__nop},                 /* no-op */
        {"A", c_A},                    /* appendix heading */
        {"B", c_B},                    /* bibliography entry */
        {"BR", c_BR},                  /* bibliography rewrite */
@@ -259,7 +261,7 @@ static void match_kw(token *tok) {
        {"lcont", c_lcont},            /* continuation para(s) for list item */
        {"n", c_n},                    /* numbered list */
        {"nocite", c_nocite},          /* bibliography trickery */
-       {"preamble", c_preamble},      /* document preamble text */
+       {"preamble", c_preamble},      /* (obsolete) preamble text */
        {"q", c_q},                    /* quote marks */
        {"quote", c_quote},            /* block-quoted paragraphs */
        {"rule", c_rule},              /* horizontal rule */
@@ -360,7 +362,7 @@ token get_token(input *in) {
     } else if (c == '\\') {           /* tok_cmd */
        c = get(in, &cpos);
        if (c == '-' || c == '\\' || c == '_' ||
-           c == '#' || c == '{' || c == '}') {
+           c == '#' || c == '{' || c == '}' || c == '.') {
            /* single-char command */
            rdadd(&rs, c);
        } else if (c == 'u') {
@@ -526,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 {
@@ -590,14 +593,17 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) {
                     */
                    dtor(t), t = get_token(in);
                }
-               if (t.type == tok_eop || t.type == tok_eof)
+               if (t.type == tok_eop || t.type == tok_eof ||
+                   t.type == tok_rbrace) { /* might be } terminating \lcont */
+                   if (t.type == tok_rbrace)
+                       already = TRUE;
                    break;
-               else if (t.type == tok_cmd && t.cmd == c_c)
+               } else if (t.type == tok_cmd && t.cmd == c_c) {
                    wtype = word_WeakCode;
-               else if (t.type == tok_cmd && t.cmd == c_e &&
-                        wtype == word_WeakCode)
+               else if (t.type == tok_cmd && t.cmd == c_e &&
+                          wtype == word_WeakCode) {
                    wtype = word_Emph;
-               else {
+               else {
                    error(err_brokencodepara, &t.pos);
                    prev_para_type = par.type;
                    addpara(par, ret);
@@ -631,6 +637,16 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) {
                continue;
            }
 
+           /*
+            * Also expect, and swallow, any whitespace after that
+            * (a newline before a code paragraph wouldn't be
+            * surprising).
+            */
+           do {
+               dtor(t), t = get_token(in);
+           } while (t.type == tok_white);
+           already = TRUE;
+
            if (cmd == c_lcont) {
                /*
                 * \lcont causes a continuation of a list item into
@@ -766,7 +782,7 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) {
              case c_define: is_macro = TRUE; needkw = 1; break;
                /* For \nocite the keyword is _everything_ */
              case c_nocite: needkw = 8; par.type = para_NoCite; break;
-             case c_preamble: needkw = 32; par.type = para_Preamble; break;
+             case c_preamble: needkw = 32; par.type = para_Normal; break;
              case c_rule: needkw = 16; par.type = para_Rule; break;
              case c_title: needkw = 32; par.type = para_Title; break;
              case c_versionid: needkw = 32; par.type = para_VersionID; break;
@@ -905,6 +921,11 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) {
                break;
            }
 
+           if (t.type == tok_cmd && t.cmd == c__nop) {
+               dtor(t), t = get_token(in);
+               continue;              /* do nothing! */
+           }
+
            if (t.type == tok_cmd && t.cmd == c__escaped) {
                t.type = tok_word;     /* nice and simple */
                t.aux = 0;             /* even if `\-' - nonbreaking! */
@@ -968,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:
@@ -992,11 +1014,20 @@ static void read_file(paragraph ***ret, input *in, indexdata *idx) {
                    }
                    if (sitem->type & stack_idx) {
                        indexword->text = ustrdup(indexstr.text);
-                       if (index_downcase)
+                       if (index_downcase) {
+                           word *w;
+
                            ustrlow(indexword->text);
+                           ustrlow(indexstr.text);
+
+                           for (w = idxwordlist; w; w = w->next)
+                               if (w->text)
+                                   ustrlow(w->text);
+                       }
                        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) {
@@ -1082,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);
                    }
@@ -1161,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)) {
@@ -1192,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);
                    }
@@ -1204,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);
                    }
@@ -1217,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);
                    /*
@@ -1290,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;