summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--regress/roff/esc/w.in16
-rw-r--r--regress/roff/esc/w.out_ascii9
-rw-r--r--regress/roff/esc/w.out_lint9
-rw-r--r--roff.75
-rw-r--r--roff.c33
5 files changed, 61 insertions, 11 deletions
diff --git a/regress/roff/esc/w.in b/regress/roff/esc/w.in
index c30a31ac..59a9bdb5 100644
--- a/regress/roff/esc/w.in
+++ b/regress/roff/esc/w.in
@@ -1,4 +1,4 @@
-.\" $OpenBSD: w.in,v 1.4 2022/06/08 13:08:00 schwarze Exp $
+.\" $OpenBSD: w.in,v 1.5 2023/10/23 20:07:19 schwarze Exp $
.Dd $Mdocdate$
.Dt ESC-W 1
.Os
@@ -13,6 +13,20 @@ character: \w'n'
blank: \w' '
.br
text: \w'text'
+.br
+special: \w'\(bu'
+.br
+numbered: \w'\N'100''
+.br
+Unicode: \w'\[u2013]'
+.br
+overstrike: \w'\o'ab''
+.br
+undefined: \w'\G'
+.br
+zero-width: \w'\fB\&\fP'
+.br
+skipchar: \w'a\zb\z\(buc'
.Ss Argument delimiters
unsupported \er: \w\rM\ru
.br
diff --git a/regress/roff/esc/w.out_ascii b/regress/roff/esc/w.out_ascii
index 7ed32ece..a8fdce54 100644
--- a/regress/roff/esc/w.out_ascii
+++ b/regress/roff/esc/w.out_ascii
@@ -8,6 +8,13 @@ DDEESSCCRRIIPPTTIIOONN
character: 24
blank: 24
text: 96
+ special: 24
+ numbered: 24
+ Unicode: 24
+ overstrike: 24
+ undefined: 24
+ zero-width: 0
+ skipchar: 48
AArrgguummeenntt ddeelliimmiitteerrss
unsupported \r: 24u
@@ -27,4 +34,4 @@ DDEESSCCRRIIPPTTIIOONN
overstrike: 24u
unterminated: 72
-OpenBSD June 8, 2022 OpenBSD
+OpenBSD October 23, 2023 OpenBSD
diff --git a/regress/roff/esc/w.out_lint b/regress/roff/esc/w.out_lint
index fd2a0948..9c6417c5 100644
--- a/regress/roff/esc/w.out_lint
+++ b/regress/roff/esc/w.out_lint
@@ -1,4 +1,5 @@
-mandoc: w.in:17:20: UNSUPP: unsupported escape sequence: \r
-mandoc: w.in:17:23: UNSUPP: unsupported escape sequence: \r
-mandoc: w.in:23:16: WARNING: undefined escape, printing literally: \G
-mandoc: w.in:51:15: ERROR: incomplete escape sequence: \w'foo
+mandoc: w.in:25:15: WARNING: undefined escape, printing literally: \G
+mandoc: w.in:31:20: UNSUPP: unsupported escape sequence: \r
+mandoc: w.in:31:23: UNSUPP: unsupported escape sequence: \r
+mandoc: w.in:37:16: WARNING: undefined escape, printing literally: \G
+mandoc: w.in:65:15: ERROR: incomplete escape sequence: \w'foo
diff --git a/roff.7 b/roff.7
index 597d4aa7..22459a9c 100644
--- a/roff.7
+++ b/roff.7
@@ -1,6 +1,6 @@
.\" $Id$
.\"
-.\" Copyright (c) 2010-2019, 2022 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2010-2019, 2022-2023 Ingo Schwarze <schwarze@openbsd.org>
.\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
@@ -2224,7 +2224,8 @@ The
.Xr mandoc 1
implementation assumes that after expansion of user-defined strings, the
.Ar string
-only contains normal characters, no escape sequences, and that each
+only contains normal characters, characters expressed as escape sequences,
+and zero-width escape sequences, and that each
character has a width of 24 basic units.
.It Ic \eX\(aq Ns Ar string Ns Ic \(aq
Output
diff --git a/roff.c b/roff.c
index 0005b999..53f9df46 100644
--- a/roff.c
+++ b/roff.c
@@ -1,6 +1,6 @@
/* $Id$ */
/*
- * Copyright (c) 2010-2015, 2017-2022 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2015, 2017-2023 Ingo Schwarze <schwarze@openbsd.org>
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -1362,6 +1362,7 @@ roff_expand(struct roff *r, struct buf *buf, int ln, int pos, char ec)
const char *res; /* the string to be pasted */
const char *src; /* source for copying */
char *dst; /* destination for copying */
+ enum mandoc_esc subtype; /* return value from roff_escape */
int iesc; /* index of leading escape char */
int inam; /* index of the escape name */
int iarg; /* index beginning the argument */
@@ -1551,8 +1552,34 @@ roff_expand(struct roff *r, struct buf *buf, int ln, int pos, char ec)
res = ubuf;
break;
case 'w':
- (void)snprintf(ubuf, sizeof(ubuf),
- "%d", (iendarg - iarg) * 24);
+ rsz = 0;
+ subtype = ESCAPE_UNDEF;
+ while (iarg < iendarg) {
+ asz = subtype == ESCAPE_SKIPCHAR ? 0 : 1;
+ if (buf->buf[iarg] != '\\') {
+ rsz += asz;
+ iarg++;
+ continue;
+ }
+ switch ((subtype = roff_escape(buf->buf, 0,
+ iarg, NULL, NULL, NULL, NULL, &iarg))) {
+ case ESCAPE_SPECIAL:
+ case ESCAPE_NUMBERED:
+ case ESCAPE_UNICODE:
+ case ESCAPE_OVERSTRIKE:
+ case ESCAPE_UNDEF:
+ break;
+ case ESCAPE_DEVICE:
+ asz *= 8;
+ break;
+ case ESCAPE_EXPAND:
+ abort();
+ default:
+ continue;
+ }
+ rsz += asz;
+ }
+ (void)snprintf(ubuf, sizeof(ubuf), "%d", rsz * 24);
res = ubuf;
break;
default: