aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2022-04-27 13:41:13 +0000
committerIngo Schwarze <schwarze@openbsd.org>2022-04-27 13:41:13 +0000
commit3d43838424a8548b9c4ffe76ae65e482bfa44346 (patch)
tree6e718c32997b4afdae752d4a10d744c384214be6
parent506fdd1d59c80ebc68d0b51075f7a5b1a812663a (diff)
downloadmandoc-3d43838424a8548b9c4ffe76ae65e482bfa44346.tar.gz
mandoc-3d43838424a8548b9c4ffe76ae65e482bfa44346.tar.zst
mandoc-3d43838424a8548b9c4ffe76ae65e482bfa44346.zip
Fix three bugs regarding the interaction of \z and \h:
1. The combination \z\h is a no-op whatever the argument may be. In the past, the \z only affected the first space character generated by the \h, which was wrong. 2. For the conbination \zX\h with a positive argument, the first space resulting from the \h is not printed but consumed by the \z. 3. For the combination \zX\h with a negative argument, application of the \z needs to be completed before the \h can be started. In the past, if this combination occurred at the beginning of an output line, the \h backed up to the beginning of the line and after that, the \z attempted to back up even further, triggering an assertion. Bugs found during an audit of assignments to termp->col that i started after the bugfix tbl_term.c rev. 1.65. The assertion triggered by bug 3 was *not* yet found by afl(1).
-rw-r--r--regress/roff/esc/Makefile11
-rw-r--r--regress/roff/esc/hneg.in11
-rw-r--r--regress/roff/esc/hneg.out_ascii10
-rw-r--r--regress/roff/esc/z.in10
-rw-r--r--regress/roff/esc/z.out_ascii5
-rw-r--r--term.c22
6 files changed, 60 insertions, 9 deletions
diff --git a/regress/roff/esc/Makefile b/regress/roff/esc/Makefile
index 4c152fc4..f00aa4d3 100644
--- a/regress/roff/esc/Makefile
+++ b/regress/roff/esc/Makefile
@@ -1,8 +1,15 @@
-# $OpenBSD: Makefile,v 1.18 2022/04/13 13:11:33 schwarze Exp $
+# $OpenBSD: Makefile,v 1.19 2022/04/27 13:30:19 schwarze Exp $
-REGRESS_TARGETS = one two multi B bs_man bs_mdoc c c_man E1 e f h l O1 o p w z
+REGRESS_TARGETS = one two multi
+REGRESS_TARGETS += B bs_man bs_mdoc c c_man E1 e f h hneg l O1 o p w z
REGRESS_TARGETS += ignore invalid unsupp
HTML_TARGETS = f
LINT_TARGETS = B h l O1 w ignore invalid unsupp
+# mandoc defect:
+# - \h with a negative argument replaces output characters
+# instead of overstriking them
+
+SKIP_GROFF = hneg
+
.include <bsd.regress.mk>
diff --git a/regress/roff/esc/hneg.in b/regress/roff/esc/hneg.in
new file mode 100644
index 00000000..cd085af3
--- /dev/null
+++ b/regress/roff/esc/hneg.in
@@ -0,0 +1,11 @@
+.\" $OpenBSD: hneg.in,v 1.1 2022/04/27 13:30:19 schwarze Exp $
+.Dd $Mdocdate: April 27 2022 $
+.Dt ESC-HNEG 1
+.Os
+.Sh NAME
+.Nm esc-hneg
+.Nd the roff escape h sequence with a negative argument
+.Sh DESCRIPTION
+simple: >abc\h'-3'd<
+.br
+after z escape: >ab\zc\h'-2'd<
diff --git a/regress/roff/esc/hneg.out_ascii b/regress/roff/esc/hneg.out_ascii
new file mode 100644
index 00000000..000082f9
--- /dev/null
+++ b/regress/roff/esc/hneg.out_ascii
@@ -0,0 +1,10 @@
+ESC-HNEG(1) General Commands Manual ESC-HNEG(1)
+
+NNAAMMEE
+ eesscc--hhnneegg - the roff escape h sequence with a negative argument
+
+DDEESSCCRRIIPPTTIIOONN
+ simple: >d<c
+ after z escape: >d<c
+
+OpenBSD April 27, 2022 OpenBSD
diff --git a/regress/roff/esc/z.in b/regress/roff/esc/z.in
index ab4c5ab3..252cfc0b 100644
--- a/regress/roff/esc/z.in
+++ b/regress/roff/esc/z.in
@@ -1,5 +1,5 @@
-.\" $OpenBSD: z.in,v 1.3 2017/07/04 14:53:27 schwarze Exp $
-.Dd $Mdocdate: July 4 2017 $
+.\" $OpenBSD: z.in,v 1.4 2022/04/27 13:30:19 schwarze Exp $
+.Dd $Mdocdate: April 27 2022 $
.Dt ESC-Z 1
.Os
.Sh NAME
@@ -20,6 +20,12 @@ new line<
.br
single z with overstrike: >\z\o'ab'c<
.br
+single z with h escape: >\z\h'3'm\z\h'-3'<
+.br
+single z with char and h with positive argument: >\za\h'3'b<
+.br
+single z with char and h with zero argument: >\za\h'0'b<
+.br
single z near the end of the line: >\z<
.br
double z: >\z\zx<
diff --git a/regress/roff/esc/z.out_ascii b/regress/roff/esc/z.out_ascii
index da268176..0566c7a6 100644
--- a/regress/roff/esc/z.out_ascii
+++ b/regress/roff/esc/z.out_ascii
@@ -10,7 +10,10 @@ DDEESSCCRRIIPPTTIIOONN
single z with font escape: >xxbboolldd<
single z with nospace escape: > new line<
single z with overstrike: >abc<
+ single z with h escape: >m<
+ single z with char and h with positive argument: >a b<
+ single z with char and h with zero argument: >ab<
single z near the end of the line: ><
double z: >x<
-OpenBSD July 4, 2017 OpenBSD
+OpenBSD April 27, 2022 OpenBSD
diff --git a/term.c b/term.c
index 70ca20c4..b7c2363f 100644
--- a/term.c
+++ b/term.c
@@ -1,4 +1,4 @@
-/* $Id: term.c,v 1.285 2022/01/10 18:01:35 schwarze Exp $ */
+/* $Id: term.c,v 1.286 2022/04/27 13:41:13 schwarze Exp $ */
/*
* Copyright (c) 2010-2022 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -628,6 +628,10 @@ term_word(struct termp *p, const char *word)
encode(p, "utf8", 4);
continue;
case ESCAPE_HORIZ:
+ if (p->flags & TERMP_BACKAFTER) {
+ p->flags &= ~TERMP_BACKAFTER;
+ continue;
+ }
if (*seq == '|') {
seq++;
uc = -p->col;
@@ -636,12 +640,22 @@ term_word(struct termp *p, const char *word)
if (a2roffsu(seq, &su, SCALE_EM) == NULL)
continue;
uc += term_hen(p, &su);
- if (uc > 0) {
+ if (uc >= 0) {
while (uc > 0) {
- bufferc(p, ASCII_NBRSP);
uc -= term_len(p, 1);
+ if (p->flags & TERMP_BACKBEFORE)
+ p->flags &= ~TERMP_BACKBEFORE;
+ else
+ bufferc(p, ASCII_NBRSP);
}
- } else if (p->col > (size_t)(-uc)) {
+ continue;
+ }
+ if (p->flags & TERMP_BACKBEFORE) {
+ p->flags &= ~TERMP_BACKBEFORE;
+ assert(p->col > 0);
+ p->col--;
+ }
+ if (p->col >= (size_t)(-uc)) {
p->col += uc;
} else {
uc += p->col;