diff options
-rw-r--r-- | regress/usr.bin/mandoc/roff/args/roff.in | 8 | ||||
-rw-r--r-- | regress/usr.bin/mandoc/roff/args/roff.out_ascii | 3 | ||||
-rw-r--r-- | regress/usr.bin/mandoc/roff/args/roff.out_lint | 20 | ||||
-rw-r--r-- | usr.bin/mandoc/roff.c | 94 |
4 files changed, 96 insertions, 29 deletions
diff --git a/regress/usr.bin/mandoc/roff/args/roff.in b/regress/usr.bin/mandoc/roff/args/roff.in index ff9a5781cc5..a305d00ba6a 100644 --- a/regress/usr.bin/mandoc/roff/args/roff.in +++ b/regress/usr.bin/mandoc/roff/args/roff.in @@ -1,8 +1,14 @@ -.TH ARGS-ROFF 1 "January 1, 2011" +.TH ARGS-ROFF 1 "February 21, 2015" .SH NAME args-roff - arguments to roff macros .SH DESCRIPTION .de test +.BI (\\$1) "(\\$2)" +.br +.. +arguments containing quotes: +.test a"b a"b +.de test (\\$1) (\\$2) .br .. diff --git a/regress/usr.bin/mandoc/roff/args/roff.out_ascii b/regress/usr.bin/mandoc/roff/args/roff.out_ascii index c5566de2746..52385a4196e 100644 --- a/regress/usr.bin/mandoc/roff/args/roff.out_ascii +++ b/regress/usr.bin/mandoc/roff/args/roff.out_ascii @@ -6,6 +6,7 @@ NNAAMMEE args-roff - arguments to roff macros DDEESSCCRRIIPPTTIIOONN + arguments containing quotes: ((aa""bb))_(_a_"_b_) standard unquoted: (one) (two) escaped blanks: (one one) (two two) escaped 'e' character: (one\one) (two) @@ -36,4 +37,4 @@ DDEESSCCRRIIPPTTIIOONN - January 1, 2011 ARGS-ROFF(1) + February 21, 2015 ARGS-ROFF(1) diff --git a/regress/usr.bin/mandoc/roff/args/roff.out_lint b/regress/usr.bin/mandoc/roff/args/roff.out_lint index 0a57316606a..7c20a0488bc 100644 --- a/regress/usr.bin/mandoc/roff/args/roff.out_lint +++ b/regress/usr.bin/mandoc/roff/args/roff.out_lint @@ -1,11 +1,11 @@ -mandoc: roff.in:24:15: WARNING: whitespace at end of input line -mandoc: roff.in:26:16: WARNING: whitespace at end of input line -mandoc: roff.in:28:17: WARNING: whitespace at end of input line -mandoc: roff.in:48:27: WARNING: whitespace at end of input line -mandoc: roff.in:50:28: WARNING: whitespace at end of input line -mandoc: roff.in:52:29: WARNING: whitespace at end of input line -mandoc: roff.in:57:11: WARNING: unterminated quoted argument -mandoc: roff.in:60:11: WARNING: unterminated quoted argument -mandoc: roff.in:60:16: WARNING: whitespace at end of input line +mandoc: roff.in:30:15: WARNING: whitespace at end of input line +mandoc: roff.in:32:16: WARNING: whitespace at end of input line +mandoc: roff.in:34:17: WARNING: whitespace at end of input line +mandoc: roff.in:54:27: WARNING: whitespace at end of input line +mandoc: roff.in:56:28: WARNING: whitespace at end of input line +mandoc: roff.in:58:29: WARNING: whitespace at end of input line mandoc: roff.in:63:11: WARNING: unterminated quoted argument -mandoc: roff.in:63:17: WARNING: whitespace at end of input line +mandoc: roff.in:66:11: WARNING: unterminated quoted argument +mandoc: roff.in:66:16: WARNING: whitespace at end of input line +mandoc: roff.in:69:11: WARNING: unterminated quoted argument +mandoc: roff.in:69:17: WARNING: whitespace at end of input line diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c index 7f294e2ed4b..3835f1adbfa 100644 --- a/usr.bin/mandoc/roff.c +++ b/usr.bin/mandoc/roff.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roff.c,v 1.134 2015/02/17 17:55:12 schwarze Exp $ */ +/* $OpenBSD: roff.c,v 1.135 2015/02/21 14:46:33 schwarze Exp $ */ /* * Copyright (c) 2010, 2011, 2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> @@ -2651,14 +2651,16 @@ roff_so(ROFF_ARGS) static enum rofferr roff_userdef(ROFF_ARGS) { - const char *arg[9]; + const char *arg[9], *ap; char *cp, *n1, *n2; int i; + size_t asz, rsz; /* * Collect pointers to macro argument strings * and NUL-terminate them. */ + cp = buf->buf + pos; for (i = 0; i < 9; i++) arg[i] = *cp == '\0' ? "" : @@ -2667,31 +2669,89 @@ roff_userdef(ROFF_ARGS) /* * Expand macro arguments. */ - buf->sz = 0; - n1 = cp = mandoc_strdup(r->current_string); - while ((cp = strstr(cp, "\\$")) != NULL) { - i = cp[2] - '1'; - if (0 > i || 8 < i) { - /* Not an argument invocation. */ - cp += 2; + + buf->sz = strlen(r->current_string) + 1; + n1 = cp = mandoc_malloc(buf->sz); + memcpy(n1, r->current_string, buf->sz); + while (*cp != '\0') { + + /* Scan ahead for the next argument invocation. */ + + if (*cp++ != '\\') + continue; + if (*cp++ != '$') continue; + i = *cp - '1'; + if (0 > i || 8 < i) + continue; + cp -= 2; + + /* + * Determine the size of the expanded argument, + * taking escaping of quotes into account. + */ + + asz = 0; + for (ap = arg[i]; *ap != '\0'; ap++) { + asz++; + if (*ap == '"') + asz += 3; + } + if (asz != 3) { + + /* + * Determine the size of the rest of the + * unexpanded macro, including the NUL. + */ + + rsz = buf->sz - (cp - n1) - 3; + + /* + * When shrinking, move before + * releasing the storage. + */ + + if (asz < 3) + memmove(cp + asz, cp + 3, rsz); + + /* + * Resize the storage for the macro + * and readjust the parse pointer. + */ + + buf->sz += asz - 3; + n2 = mandoc_realloc(n1, buf->sz); + cp = n2 + (cp - n1); + n1 = n2; + + /* + * When growing, make room + * for the expanded argument. + */ + + if (asz > 3) + memmove(cp + asz, cp + 3, rsz); + } + + /* 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; } - *cp = '\0'; - buf->sz = mandoc_asprintf(&n2, "%s%s%s", - n1, arg[i], cp + 3) + 1; - cp = n2 + (cp - n1); - free(n1); - n1 = n2; } /* * Replace the macro invocation * by the expanded macro. */ + free(buf->buf); buf->buf = n1; - if (buf->sz == 0) - buf->sz = strlen(buf->buf) + 1; *offs = 0; return(buf->sz > 1 && buf->buf[buf->sz - 2] == '\n' ? |