From 71472a8560e814daaed28a4c8419af566b7da2a1 Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Sat, 29 Aug 2015 21:37:20 +0000 Subject: Implement the escape sequence \\$*, expanding to all arguments of the current user-defined macro. This is another missing feature required for ocserv(8). Problem reported by Kurt Jaeger . --- roff.7 | 6 ++++-- roff.c | 43 +++++++++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/roff.7 b/roff.7 index 127504f8..39003c09 100644 --- a/roff.7 +++ b/roff.7 @@ -1,4 +1,4 @@ -.\" $Id: roff.7,v 1.72 2015/05/31 23:13:22 schwarze Exp $ +.\" $Id: roff.7,v 1.73 2015/08/29 21:37:20 schwarze Exp $ .\" .\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons .\" Copyright (c) 2010, 2011, 2013, 2014 Ingo Schwarze @@ -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: May 31 2015 $ +.Dd $Mdocdate: August 29 2015 $ .Dt ROFF 7 .Os .Sh NAME @@ -665,6 +665,8 @@ produces .D1 \efI\e^XtFree\e^\efP. .Pp in the input stream, and thus in the output: \fI\^XtFree\^\fP. +Each occurrence of \e\e$* is replaced with all the arguments, +joined together with single blank characters. .Pp Since macros and user-defined strings share a common string table, defining a macro diff --git a/roff.c b/roff.c index d28cea9c..e72c965a 100644 --- a/roff.c +++ b/roff.c @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.273 2015/08/29 20:26:04 schwarze Exp $ */ +/* $Id: roff.c,v 1.274 2015/08/29 21:37:20 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons * Copyright (c) 2010-2015 Ingo Schwarze @@ -3080,7 +3080,7 @@ roff_userdef(ROFF_ARGS) { const char *arg[9], *ap; char *cp, *n1, *n2; - int i; + int i, ib, ie; size_t asz, rsz; /* @@ -3114,9 +3114,14 @@ roff_userdef(ROFF_ARGS) continue; if (*cp++ != '$') continue; - i = *cp - '1'; - if (0 > i || 8 < i) - continue; + if (*cp == '*') { /* \\$* inserts all arguments */ + ib = 0; + ie = r->argc - 1; + } else { /* \\$1 .. \\$9 insert one argument */ + ib = ie = *cp - '1'; + if (ib < 0 || ib > 8) + continue; + } cp -= 2; /* @@ -3124,11 +3129,13 @@ roff_userdef(ROFF_ARGS) * taking escaping of quotes into account. */ - asz = 0; - for (ap = arg[i]; *ap != '\0'; ap++) { - asz++; - if (*ap == '"') - asz += 3; + asz = ie > ib ? ie - ib : 0; /* for blanks */ + for (i = ib; i <= ie; i++) { + for (ap = arg[i]; *ap != '\0'; ap++) { + asz++; + if (*ap == '"') + asz += 3; + } } if (asz != 3) { @@ -3169,12 +3176,16 @@ roff_userdef(ROFF_ARGS) /* Copy the expanded argument, escaping quotes. */ n2 = cp; - for (ap = arg[i]; *ap != '\0'; ap++) { - if (*ap == '"') { - memcpy(n2, "\\(dq", 4); - n2 += 4; - } else - *n2++ = *ap; + for (i = ib; i <= ie; i++) { + for (ap = arg[i]; *ap != '\0'; ap++) { + if (*ap == '"') { + memcpy(n2, "\\(dq", 4); + n2 += 4; + } else + *n2++ = *ap; + } + if (i < ie) + *n2++ = ' '; } } -- cgit v1.2.3-56-ge451