Replace the kludge for the \z escape sequence by an actual
authorschwarze <schwarze@openbsd.org>
Wed, 29 Apr 2015 18:32:57 +0000 (18:32 +0000)
committerschwarze <schwarze@openbsd.org>
Wed, 29 Apr 2015 18:32:57 +0000 (18:32 +0000)
implementation.  As a side effect, minus ten lines of code.

As another side effect, this also fixes the assertion failure that
used to be triggered by "\z\o'ab'c" at the beginning of an output
line, found by jsg@ with afl (test case 022/Apr27).

regress/usr.bin/mandoc/roff/esc/Makefile
regress/usr.bin/mandoc/roff/esc/z.in
regress/usr.bin/mandoc/roff/esc/z.out_ascii
share/man/man7/roff.7
usr.bin/mandoc/term.c
usr.bin/mandoc/term.h

index ab2b01a..f086036 100644 (file)
@@ -1,16 +1,6 @@
-# $OpenBSD: Makefile,v 1.10 2015/01/21 20:20:49 schwarze Exp $
+# $OpenBSD: Makefile,v 1.11 2015/04/29 18:32:57 schwarze Exp $
 
 REGRESS_TARGETS = one two multi B c c_man e f h o w z ignore
 LINT_TARGETS   = B h w ignore
 
-# Postprocessing to remove "character backspace" sequences
-# unless they are followed by the same character again.
-# This removes underlining as well, so we mustn't use it.
-# Cannot use /g because matches progress backwards.
-
-z.out_ascii: z.in
-       ${NROFF} ${NOPTS} -Tascii ${.ALLSRC} | \
-               perl -pe 'while (s/(.)\010(?!\1)//) {}' \
-               > ${.TARGET}
-
 .include <bsd.regress.mk>
index 7076ebb..9d3ad1d 100644 (file)
@@ -1,4 +1,4 @@
-.Dd May 28, 2012
+.Dd April 29, 2015
 .Dt ESC-Z 1
 .Os OpenBSD
 .Sh NAME
@@ -17,6 +17,8 @@ single z with font escape: >\z\fBxbold\fP<
 single z with nospace escape: >\z\c
 new line<
 .br
-single z with undefined escape: >\z\a<
+single z with overstrike: >\z\o'ab'c<
+.br
+single z near the end of the line: >\z<
 .br
 double z: >\z\zx<
index 935ebe6..233a4aa 100644 (file)
@@ -4,12 +4,13 @@ N\bNA\bAM\bME\bE
      e\bes\bsc\bc-\b-z\bz - the roff escape z sequence
 
 D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
-     single z with ASCII char: ><
-     single z with escape char: ><
-     single z with defined string (mytext): >ytext<
-     single z with font escape: >b\bbo\bol\bld\bd<
+     single z with ASCII char: >x\b<
+     single z with escape char: >O\b<
+     single z with defined string (mytext): >m\bytext<
+     single z with font escape: >x\bx\bb\bbo\bol\bld\bd<
      single z with nospace escape: > new line<
-     single z with undefined escape: ><
-     double z: ><
+     single z with overstrike: >a\bb\bc<
+     single z near the end of the line: ><
+     double z: >x\b<
 
-OpenBSD                          May 28, 2012                          OpenBSD
+OpenBSD                         April 29, 2015                         OpenBSD
index 432ff03..13743c1 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: roff.7,v 1.50 2015/02/17 17:16:11 schwarze Exp $
+.\"    $OpenBSD: roff.7,v 1.51 2015/04/29 18:32:57 schwarze Exp $
 .\"
 .\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
 .\" Copyright (c) 2010, 2011, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -15,7 +15,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: February 17 2015 $
+.Dd $Mdocdate: April 29 2015 $
 .Dt ROFF 7
 .Os
 .Sh NAME
@@ -2026,10 +2026,7 @@ Print
 with zero width and height; ignored by
 .Xr mandoc 1 .
 .Ss \ez
-Output the next character without advancing the cursor position;
-approximated in
-.Xr mandoc 1
-by simply skipping the next character.
+Output the next character without advancing the cursor position.
 .Sh COMPATIBILITY
 The
 .Xr mandoc 1
index 9e6ee91..141f548 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: term.c,v 1.107 2015/04/04 17:46:58 schwarze Exp $ */
+/*     $OpenBSD: term.c,v 1.108 2015/04/29 18:32:57 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -263,6 +263,7 @@ term_flushln(struct termp *p)
 
        p->col = 0;
        p->overstep = 0;
+       p->flags &= ~(TERMP_BACKAFTER | TERMP_BACKBEFORE);
 
        if ( ! (TERMP_NOBREAK & p->flags)) {
                p->viscol = 0;
@@ -415,11 +416,6 @@ term_word(struct termp *p, const char *word)
 
        while ('\0' != *word) {
                if ('\\' != *word) {
-                       if (TERMP_SKIPCHAR & p->flags) {
-                               p->flags &= ~TERMP_SKIPCHAR;
-                               word++;
-                               continue;
-                       }
                        if (TERMP_NBRWORD & p->flags) {
                                if (' ' == *word) {
                                        encode(p, nbrsp, 1);
@@ -478,13 +474,13 @@ term_word(struct termp *p, const char *word)
                        term_fontlast(p);
                        continue;
                case ESCAPE_NOSPACE:
-                       if (TERMP_SKIPCHAR & p->flags)
-                               p->flags &= ~TERMP_SKIPCHAR;
-                       else if ('\0' == *word)
+                       if (p->flags & TERMP_BACKAFTER)
+                               p->flags &= ~TERMP_BACKAFTER;
+                       else if (*word == '\0')
                                p->flags |= (TERMP_NOSPACE | TERMP_NONEWLINE);
                        continue;
                case ESCAPE_SKIPCHAR:
-                       p->flags |= TERMP_SKIPCHAR;
+                       p->flags |= TERMP_BACKAFTER;
                        continue;
                case ESCAPE_OVERSTRIKE:
                        cp = seq + sz;
@@ -494,9 +490,14 @@ term_word(struct termp *p, const char *word)
                                        continue;
                                }
                                encode1(p, *seq++);
-                               if (seq < cp)
-                                       encode(p, "\b", 1);
+                               if (seq < cp) {
+                                       if (p->flags & TERMP_BACKBEFORE)
+                                               p->flags |= TERMP_BACKAFTER;
+                                       else
+                                               p->flags |= TERMP_BACKBEFORE;
+                               }
                        }
+                       continue;
                default:
                        continue;
                }
@@ -551,16 +552,16 @@ encode1(struct termp *p, int c)
 {
        enum termfont     f;
 
-       if (TERMP_SKIPCHAR & p->flags) {
-               p->flags &= ~TERMP_SKIPCHAR;
-               return;
-       }
+       if (p->col + 7 >= p->maxcols)
+               adjbuf(p, p->col + 7);
 
-       if (p->col + 6 >= p->maxcols)
-               adjbuf(p, p->col + 6);
-
-       f = p->fontq[p->fonti];
+       f = (c == ASCII_HYPH || isgraph(c)) ?
+           p->fontq[p->fonti] : TERMFONT_NONE;
 
+       if (p->flags & TERMP_BACKBEFORE) {
+               p->buf[p->col++] = 8;
+               p->flags &= ~TERMP_BACKBEFORE;
+       }
        if (TERMFONT_UNDER == f || TERMFONT_BI == f) {
                p->buf[p->col++] = '_';
                p->buf[p->col++] = 8;
@@ -573,6 +574,10 @@ encode1(struct termp *p, int c)
                p->buf[p->col++] = 8;
        }
        p->buf[p->col++] = c;
+       if (p->flags & TERMP_BACKAFTER) {
+               p->flags |= TERMP_BACKBEFORE;
+               p->flags &= ~TERMP_BACKAFTER;
+       }
 }
 
 static void
@@ -580,29 +585,8 @@ encode(struct termp *p, const char *word, size_t sz)
 {
        size_t            i;
 
-       if (TERMP_SKIPCHAR & p->flags) {
-               p->flags &= ~TERMP_SKIPCHAR;
-               return;
-       }
-
-       /*
-        * Encode and buffer a string of characters.  If the current
-        * font mode is unset, buffer directly, else encode then buffer
-        * character by character.
-        */
-
-       if (p->fontq[p->fonti] == TERMFONT_NONE) {
-               if (p->col + sz >= p->maxcols)
-                       adjbuf(p, p->col + sz);
-               for (i = 0; i < sz; i++)
-                       p->buf[p->col++] = word[i];
-               return;
-       }
-
-       /* Pre-buffer, assuming worst-case. */
-
-       if (p->col + 1 + (sz * 5) >= p->maxcols)
-               adjbuf(p, p->col + 1 + (sz * 5));
+       if (p->col + 2 + (sz * 5) >= p->maxcols)
+               adjbuf(p, p->col + 2 + (sz * 5));
 
        for (i = 0; i < sz; i++) {
                if (ASCII_HYPH == word[i] ||
index 9a677c7..47e14f8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: term.h,v 1.57 2015/04/04 17:46:58 schwarze Exp $ */
+/*     $OpenBSD: term.h,v 1.58 2015/04/29 18:32:57 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -67,13 +67,14 @@ struct      termp {
        int               overstep;     /* See termp_flushln(). */
        int               skipvsp;      /* Vertical space to skip. */
        int               flags;
-#define        TERMP_SENTENCE   (1 << 1)       /* Space before a sentence. */
-#define        TERMP_NOSPACE    (1 << 2)       /* No space before words. */
-#define        TERMP_NONOSPACE  (1 << 3)       /* No space (no autounset). */
-#define        TERMP_NBRWORD    (1 << 4)       /* Make next word nonbreaking. */
-#define        TERMP_KEEP       (1 << 5)       /* Keep words together. */
-#define        TERMP_PREKEEP    (1 << 6)       /* ...starting with the next one. */
-#define        TERMP_SKIPCHAR   (1 << 7)       /* Skip the next character. */
+#define        TERMP_SENTENCE   (1 << 0)       /* Space before a sentence. */
+#define        TERMP_NOSPACE    (1 << 1)       /* No space before words. */
+#define        TERMP_NONOSPACE  (1 << 2)       /* No space (no autounset). */
+#define        TERMP_NBRWORD    (1 << 3)       /* Make next word nonbreaking. */
+#define        TERMP_KEEP       (1 << 4)       /* Keep words together. */
+#define        TERMP_PREKEEP    (1 << 5)       /* ...starting with the next one. */
+#define        TERMP_BACKAFTER  (1 << 6)       /* Back up after next character. */
+#define        TERMP_BACKBEFORE (1 << 7)       /* Back up before next character. */
 #define        TERMP_NOBREAK    (1 << 8)       /* See term_flushln(). */
 #define        TERMP_BRIND      (1 << 9)       /* See term_flushln(). */
 #define        TERMP_DANGLE     (1 << 10)      /* See term_flushln(). */