]> git.cameronkatri.com Git - mandoc.git/blobdiff - roff.c
Three bugfixes related to the closing of conditional blocks:
[mandoc.git] / roff.c
diff --git a/roff.c b/roff.c
index a3e34186c8d1ec54d754cd0fed5ea642779909fa..0772d8ab9d28287cea7652ed40d8fbd7cfc4cda8 100644 (file)
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/*     $Id: roff.c,v 1.192 2014/02/14 22:27:41 schwarze Exp $ */
+/*     $Id: roff.c,v 1.195 2014/03/07 02:22:05 schwarze Exp $ */
 /*
  * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -40,7 +40,9 @@ enum  rofft {
        ROFF_am,
        ROFF_ami,
        ROFF_am1,
+       ROFF_as,
        ROFF_cc,
+       ROFF_ce,
        ROFF_de,
        ROFF_dei,
        ROFF_de1,
@@ -70,7 +72,6 @@ enum  rofft {
        ROFF_EQ,
        ROFF_EN,
        ROFF_cblock,
-       ROFF_ccond,
        ROFF_USERDEF,
        ROFF_MAX
 };
@@ -178,7 +179,7 @@ static      enum rofferr     roff_block_text(ROFF_ARGS);
 static enum rofferr     roff_block_sub(ROFF_ARGS);
 static enum rofferr     roff_cblock(ROFF_ARGS);
 static enum rofferr     roff_cc(ROFF_ARGS);
-static enum rofferr     roff_ccond(ROFF_ARGS);
+static void             roff_ccond(struct roff *, int, int);
 static enum rofferr     roff_cond(ROFF_ARGS);
 static enum rofferr     roff_cond_text(ROFF_ARGS);
 static enum rofferr     roff_cond_sub(ROFF_ARGS);
@@ -233,7 +234,9 @@ static      struct roffmac   roffs[ROFF_MAX] = {
        { "am", roff_block, roff_block_text, roff_block_sub, 0, NULL },
        { "ami", roff_block, roff_block_text, roff_block_sub, 0, NULL },
        { "am1", roff_block, roff_block_text, roff_block_sub, 0, NULL },
+       { "as", roff_ds, NULL, NULL, 0, NULL },
        { "cc", roff_cc, NULL, NULL, 0, NULL },
+       { "ce", roff_line_ignore, NULL, NULL, 0, NULL },
        { "de", roff_block, roff_block_text, roff_block_sub, 0, NULL },
        { "dei", roff_block, roff_block_text, roff_block_sub, 0, NULL },
        { "de1", roff_block, roff_block_text, roff_block_sub, 0, NULL },
@@ -263,7 +266,6 @@ static      struct roffmac   roffs[ROFF_MAX] = {
        { "EQ", roff_EQ, NULL, NULL, 0, NULL },
        { "EN", roff_EN, NULL, NULL, 0, NULL },
        { ".", roff_cblock, NULL, NULL, 0, NULL },
-       { "\\}", roff_ccond, NULL, NULL, 0, NULL },
        { NULL, roff_userdef, NULL, NULL, 0, NULL },
 };
 
@@ -786,14 +788,10 @@ roff_parse(struct roff *r, const char *buf, int *pos)
                        '\t' == buf[*pos] || ' ' == buf[*pos])
                return(ROFF_MAX);
 
-       /*
-        * We stop the macro parse at an escape, tab, space, or nil.
-        * However, `\}' is also a valid macro, so make sure we don't
-        * clobber it by seeing the `\' as the end of token.
-        */
+       /* We stop the macro parse at an escape, tab, space, or nil. */
 
        mac = buf + *pos;
-       maclen = strcspn(mac + 1, " \\\t\0") + 1;
+       maclen = strcspn(mac, " \\\t\0");
 
        t = (r->current_string = roff_getstrn(r, mac, maclen))
            ? ROFF_USERDEF : roffhash_find(mac, maclen);
@@ -862,14 +860,13 @@ roffnode_cleanscope(struct roff *r)
 }
 
 
-/* ARGSUSED */
-static enum rofferr
-roff_ccond(ROFF_ARGS)
+static void
+roff_ccond(struct roff *r, int ln, int ppos)
 {
 
        if (NULL == r->last) {
                mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
-               return(ROFF_IGN);
+               return;
        }
 
        switch (r->last->tok) {
@@ -881,20 +878,17 @@ roff_ccond(ROFF_ARGS)
                break;
        default:
                mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
-               return(ROFF_IGN);
+               return;
        }
 
        if (r->last->endspan > -1) {
                mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
-               return(ROFF_IGN);
+               return;
        }
 
-       if ((*bufp)[pos])
-               mandoc_msg(MANDOCERR_ARGSLOST, r->parse, ln, pos, NULL);
-
        roffnode_pop(r);
        roffnode_cleanscope(r);
-       return(ROFF_IGN);
+       return;
 }
 
 
@@ -939,7 +933,7 @@ roff_block(ROFF_ARGS)
        /*
         * At the beginning of a `de' macro, clear the existing string
         * with the same name, if there is one.  New content will be
-        * added from roff_block_text() in multiline mode.
+        * appended from roff_block_text() in multiline mode.
         */
 
        if (ROFF_de == tok)
@@ -1029,7 +1023,7 @@ roff_block_sub(ROFF_ARGS)
         */
        if (ROFF_cblock != t) {
                if (ROFF_de == tok)
-                       roff_setstr(r, r->last->name, *bufp + ppos, 1);
+                       roff_setstr(r, r->last->name, *bufp + ppos, 2);
                return(ROFF_IGN);
        }
 
@@ -1045,7 +1039,7 @@ roff_block_text(ROFF_ARGS)
 {
 
        if (ROFF_de == tok)
-               roff_setstr(r, r->last->name, *bufp + pos, 1);
+               roff_setstr(r, r->last->name, *bufp + pos, 2);
 
        return(ROFF_IGN);
 }
@@ -1069,7 +1063,7 @@ roff_cond_sub(ROFF_ARGS)
         */
 
        if ((ROFF_MAX != t) &&
-           (ROFF_ccond == t || ROFFRULE_ALLOW == rr ||
+           (ROFFRULE_ALLOW == rr ||
             ROFFMAC_STRUCT & roffs[t].flags)) {
                assert(roffs[t].proc);
                return((*roffs[t].proc)(r, t, bufp, szp,
@@ -1095,9 +1089,7 @@ roff_cond_sub(ROFF_ARGS)
                } else
                        *(ep - 1) = *ep = ' ';
 
-               roff_ccond(r, ROFF_ccond, bufp, szp, 
-                               ln, pos, pos + 2, offs);
-               break;
+               roff_ccond(r, ln, pos);
        }
        return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
 }
@@ -1118,8 +1110,7 @@ roff_cond_text(ROFF_ARGS)
                if ('}' != *ep)
                        continue;
                *ep = '&';
-               roff_ccond(r, ROFF_ccond, bufp, szp, 
-                               ln, pos, pos + 2, offs);
+               roff_ccond(r, ln, pos);
        }
        return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
 }
@@ -1348,7 +1339,7 @@ roff_ds(ROFF_ARGS)
                string++;
 
        /* The rest is the value. */
-       roff_setstr(r, name, string, 0);
+       roff_setstr(r, name, string, ROFF_as == tok);
        return(ROFF_IGN);
 }
 
@@ -1848,22 +1839,23 @@ roff_getname(struct roff *r, char **cpp, int ln, int pos)
 
 /*
  * Store *string into the user-defined string called *name.
- * In multiline mode, append to an existing entry and append '\n';
- * else replace the existing entry, if there is one.
  * To clear an existing entry, call with (*r, *name, NULL, 0).
+ * append == 0: replace mode
+ * append == 1: single-line append mode
+ * append == 2: multiline append mode, append '\n' after each call
  */
 static void
 roff_setstr(struct roff *r, const char *name, const char *string,
-       int multiline)
+       int append)
 {
 
        roff_setstrn(&r->strtab, name, strlen(name), string,
-                       string ? strlen(string) : 0, multiline);
+                       string ? strlen(string) : 0, append);
 }
 
 static void
 roff_setstrn(struct roffkv **r, const char *name, size_t namesz,
-               const char *string, size_t stringsz, int multiline)
+               const char *string, size_t stringsz, int append)
 {
        struct roffkv   *n;
        char            *c;
@@ -1885,8 +1877,7 @@ roff_setstrn(struct roffkv **r, const char *name, size_t namesz,
                n->val.sz = 0;
                n->next = *r;
                *r = n;
-       } else if (0 == multiline) {
-               /* In multiline mode, append; else replace. */
+       } else if (0 == append) {
                free(n->val.p);
                n->val.p = NULL;
                n->val.sz = 0;
@@ -1899,7 +1890,7 @@ roff_setstrn(struct roffkv **r, const char *name, size_t namesz,
         * One additional byte for the '\n' in multiline mode,
         * and one for the terminating '\0'.
         */
-       newch = stringsz + (multiline ? 2u : 1u);
+       newch = stringsz + (1 < append ? 2u : 1u);
 
        if (NULL == n->val.p) {
                n->val.p = mandoc_malloc(newch);
@@ -1926,7 +1917,7 @@ roff_setstrn(struct roffkv **r, const char *name, size_t namesz,
        }
 
        /* Append terminating bytes. */
-       if (multiline)
+       if (1 < append)
                *c++ = '\n';
 
        *c = '\0';