summaryrefslogtreecommitdiffstats
path: root/roff.c
diff options
context:
space:
mode:
Diffstat (limited to 'roff.c')
-rw-r--r--roff.c33
1 files changed, 30 insertions, 3 deletions
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: