]> git.cameronkatri.com Git - mandoc.git/blobdiff - roff.c
Don't let .Ta creep into an already-closed list; same as for .It.
[mandoc.git] / roff.c
diff --git a/roff.c b/roff.c
index f2ee39a3e9ea6cad1692f39275a030b86540291d..992d9772a3e0990f0eaf091e94ea9621fd10b8e7 100644 (file)
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/*     $Id: roff.c,v 1.238 2014/11/01 06:03:13 schwarze Exp $ */
+/*     $Id: roff.c,v 1.244 2014/12/18 17:43:41 schwarze Exp $ */
 /*
  * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -730,6 +730,7 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs)
        enum rofft       t;
        enum rofferr     e;
        int              pos;   /* parse point */
+       int              spos;  /* saved parse point for messages */
        int              ppos;  /* original offset in buf->buf */
        int              ctl;   /* macro line (boolean) */
 
@@ -800,15 +801,29 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs)
                return((*roffs[t].sub)(r, t, buf, ln, ppos, pos, offs));
        }
 
+       /* No scope is open.  This is a new request or macro. */
+
+       spos = pos;
+       t = roff_parse(r, buf->buf, &pos, ln, ppos);
+
+       /* Tables ignore most macros. */
+
+       if (r->tbl != NULL && (t == ROFF_MAX || t == ROFF_TS)) {
+               mandoc_msg(MANDOCERR_TBLMACRO, r->parse,
+                   ln, pos, buf->buf + spos);
+               return(ROFF_IGN);
+       }
+
        /*
-        * Lastly, as we've no scope open, try to look up and execute
-        * the new macro.  If no macro is found, simply return and let
-        * the compilers handle it.
+        * This is neither a roff request nor a user-defined macro.
+        * Let the standard macro set parsers handle it.
         */
 
-       if ((t = roff_parse(r, buf->buf, &pos, ln, ppos)) == ROFF_MAX)
+       if (t == ROFF_MAX)
                return(ROFF_CONT);
 
+       /* Execute a roff request or a user defined macro. */
+
        assert(roffs[t].proc);
        return((*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs));
 }
@@ -1236,7 +1251,7 @@ roff_evalstrcond(const char *v, int *pos)
 out:
        if (NULL == s3)
                s3 = strchr(s2, '\0');
-       else
+       else if (*s3 != '\0')
                s3++;
        *pos = s3 - v;
        return(match);
@@ -1249,7 +1264,7 @@ out:
 static int
 roff_evalcond(struct roff *r, int ln, const char *v, int *pos)
 {
-       int      wanttrue, number;
+       int      number, savepos, wanttrue;
 
        if ('!' == v[*pos]) {
                wanttrue = 0;
@@ -1258,6 +1273,8 @@ roff_evalcond(struct roff *r, int ln, const char *v, int *pos)
                wanttrue = 1;
 
        switch (v[*pos]) {
+       case '\0':
+               return(0);
        case 'n':
                /* FALLTHROUGH */
        case 'o':
@@ -1272,16 +1289,21 @@ roff_evalcond(struct roff *r, int ln, const char *v, int *pos)
        case 'r':
                /* FALLTHROUGH */
        case 't':
+               /* FALLTHROUGH */
+       case 'v':
                (*pos)++;
                return(!wanttrue);
        default:
                break;
        }
 
+       savepos = *pos;
        if (roff_evalnum(r, ln, v, pos, &number, 0))
                return((number > 0) == wanttrue);
-       else
+       else if (*pos == savepos)
                return(roff_evalstrcond(v, pos) == wanttrue);
+       else
+               return (0);
 }
 
 static enum rofferr
@@ -1554,7 +1576,7 @@ roff_evalnum(struct roff *r, int ln, const char *v,
                        *res *= operand2;
                        break;
                case '/':
-                       if (0 == operand2) {
+                       if (operand2 == 0) {
                                mandoc_msg(MANDOCERR_DIVZERO,
                                        r->parse, ln, *pos, v);
                                *res = 0;
@@ -1563,6 +1585,12 @@ roff_evalnum(struct roff *r, int ln, const char *v,
                        *res /= operand2;
                        break;
                case '%':
+                       if (operand2 == 0) {
+                               mandoc_msg(MANDOCERR_DIVZERO,
+                                       r->parse, ln, *pos, v);
+                               *res = 0;
+                               break;
+                       }
                        *res %= operand2;
                        break;
                case '<':