diff options
-rw-r--r-- | share/man/man7/roff.7 | 12 | ||||
-rw-r--r-- | usr.bin/mandoc/read.c | 74 | ||||
-rw-r--r-- | usr.bin/mandoc/roff.c | 114 |
3 files changed, 111 insertions, 89 deletions
diff --git a/share/man/man7/roff.7 b/share/man/man7/roff.7 index c3e710dfc28..39b81055ab5 100644 --- a/share/man/man7/roff.7 +++ b/share/man/man7/roff.7 @@ -1,4 +1,4 @@ -.\" $OpenBSD: roff.7,v 1.62 2017/06/02 19:21:03 schwarze Exp $ +.\" $OpenBSD: roff.7,v 1.63 2017/06/04 00:08:56 schwarze Exp $ .\" .\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> .\" Copyright (c) 2010,2011,2013-2015,2017 Ingo Schwarze <schwarze@openbsd.org> @@ -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: June 2 2017 $ +.Dd $Mdocdate: June 4 2017 $ .Dt ROFF 7 .Os .Sh NAME @@ -806,8 +806,11 @@ This is a Heirloom extension and currently unsupported. Set a trap within a diversion. Currently unsupported. .It Ic \&ec Op Ar char -Change the escape character. -Currently unsupported. +Enable the escape mechanism and change the escape character. +The +.Ar char +argument defaults to the backslash +.Pq Sq \e . .It Ic \&ecr Restore the escape character. Currently unsupported. @@ -837,7 +840,6 @@ See .Ic \&EQ . .It Ic \&eo Disable the escape mechanism completely. -Currently unsupported. .It Ic \&EP End a picture started by .Ic \&BP . diff --git a/usr.bin/mandoc/read.c b/usr.bin/mandoc/read.c index 6909bda9e3b..21538c2050f 100644 --- a/usr.bin/mandoc/read.c +++ b/usr.bin/mandoc/read.c @@ -1,4 +1,4 @@ -/* $OpenBSD: read.c,v 1.141 2017/06/03 15:54:09 schwarze Exp $ */ +/* $OpenBSD: read.c,v 1.142 2017/06/04 00:08:56 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org> @@ -322,7 +322,6 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start) const char *save_file; char *cp; size_t pos; /* byte number in the ln buffer */ - size_t j; /* auxiliary byte number in the blk buffer */ enum rofferr rr; int of; int lnn; /* line number in the real file */ @@ -404,79 +403,14 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start) continue; } - /* Trailing backslash = a plain char. */ - - if (blk.buf[i] != '\\' || i + 1 == blk.sz) { - ln.buf[pos++] = blk.buf[i++]; - continue; - } - - /* - * Found escape and at least one other character. - * When it's a newline character, skip it. - * When there is a carriage return in between, - * skip that one as well. - */ - - if ('\r' == blk.buf[i + 1] && i + 2 < blk.sz && - '\n' == blk.buf[i + 2]) - ++i; - if ('\n' == blk.buf[i + 1]) { - i += 2; - ++lnn; - continue; - } - - if ('"' == blk.buf[i + 1] || '#' == blk.buf[i + 1]) { - j = i; - i += 2; - /* Comment, skip to end of line */ - for (; i < blk.sz; ++i) { - if (blk.buf[i] != '\n') - continue; - if (blk.buf[i - 1] == ' ' || - blk.buf[i - 1] == '\t') - mandoc_msg( - MANDOCERR_SPACE_EOL, - curp, curp->line, - pos + i-1 - j, NULL); - ++i; - ++lnn; - break; - } - - /* Backout trailing whitespaces */ - for (; pos > 0; --pos) { - if (ln.buf[pos - 1] != ' ') - break; - if (pos > 2 && ln.buf[pos - 2] == '\\') - break; - } - break; - } - - /* Catch escaped bogus characters. */ - - c = (unsigned char) blk.buf[i+1]; - - if ( ! (isascii(c) && - (isgraph(c) || isblank(c)))) { - mandoc_vmsg(MANDOCERR_CHAR_BAD, curp, - curp->line, pos, "0x%x", c); - i += 2; - ln.buf[pos++] = '?'; - continue; - } - - /* Some other escape sequence, copy & cont. */ - - ln.buf[pos++] = blk.buf[i++]; ln.buf[pos++] = blk.buf[i++]; } - if (pos >= ln.sz) + if (pos + 1 >= ln.sz) resize_buf(&ln, 256); + if (i == blk.sz || blk.buf[i] == '\0') + ln.buf[pos++] = '\n'; ln.buf[pos] = '\0'; /* diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c index 9893599c0eb..07a2d227350 100644 --- a/usr.bin/mandoc/roff.c +++ b/usr.bin/mandoc/roff.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roff.c,v 1.174 2017/05/08 20:33:40 schwarze Exp $ */ +/* $OpenBSD: roff.c,v 1.175 2017/06/04 00:08:56 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2015, 2017 Ingo Schwarze <schwarze@openbsd.org> @@ -97,6 +97,7 @@ struct roff { int format; /* current file in mdoc or man format */ int argc; /* number of args of the last macro */ char control; /* control character */ + char escape; /* escape character */ }; struct roffnode { @@ -153,6 +154,8 @@ static enum rofferr roff_cond(ROFF_ARGS); static enum rofferr roff_cond_text(ROFF_ARGS); static enum rofferr roff_cond_sub(ROFF_ARGS); static enum rofferr roff_ds(ROFF_ARGS); +static enum rofferr roff_ec(ROFF_ARGS); +static enum rofferr roff_eo(ROFF_ARGS); static enum rofferr roff_eqndelim(struct roff *, struct buf *, int); static int roff_evalcond(struct roff *r, int, char *, int *); static int roff_evalnum(struct roff *, int, @@ -383,13 +386,13 @@ static struct roffmac roffs[TOKEN_NONE] = { { roff_ds, NULL, NULL, 0 }, /* ds1 */ { roff_unsupp, NULL, NULL, 0 }, /* dwh */ { roff_unsupp, NULL, NULL, 0 }, /* dt */ - { roff_unsupp, NULL, NULL, 0 }, /* ec */ + { roff_ec, NULL, NULL, 0 }, /* ec */ { roff_unsupp, NULL, NULL, 0 }, /* ecr */ { roff_unsupp, NULL, NULL, 0 }, /* ecs */ { roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT }, /* el */ { roff_unsupp, NULL, NULL, 0 }, /* em */ { roff_EN, NULL, NULL, 0 }, /* EN */ - { roff_unsupp, NULL, NULL, 0 }, /* eo */ + { roff_eo, NULL, NULL, 0 }, /* eo */ { roff_unsupp, NULL, NULL, 0 }, /* EP */ { roff_EQ, NULL, NULL, 0 }, /* EQ */ { roff_line_ignore, NULL, NULL, 0 }, /* errprint */ @@ -749,7 +752,8 @@ roff_reset(struct roff *r) { roff_free1(r); r->format = r->options & (MPARSE_MDOC | MPARSE_MAN); - r->control = 0; + r->control = '\0'; + r->escape = '\\'; } void @@ -771,6 +775,7 @@ roff_alloc(struct mparse *parse, int options) r->options = options; r->format = options & (MPARSE_MDOC | MPARSE_MAN); r->rstackpos = -1; + r->escape = '\\'; return r; } @@ -1147,27 +1152,80 @@ roff_res(struct roff *r, struct buf *buf, int ln, int pos) int expand_count; /* to avoid infinite loops */ int npos; /* position in numeric expression */ int arg_complete; /* argument not interrupted by eol */ + int done; /* no more input available */ char term; /* character terminating the escape */ - expand_count = 0; + /* Search forward for comments. */ + + done = 0; start = buf->buf + pos; - stesc = strchr(start, '\0') - 1; - while (stesc-- > start) { + for (stesc = buf->buf + pos; *stesc != '\0'; stesc++) { + if (stesc[0] != r->escape || stesc[1] == '\0') + continue; + stesc++; + if (*stesc != '"' && *stesc != '#') + continue; + cp = strchr(stesc--, '\0') - 1; + if (*cp == '\n') { + done = 1; + cp--; + } + if (*cp == ' ' || *cp == '\t') + mandoc_msg(MANDOCERR_SPACE_EOL, r->parse, + ln, cp - buf->buf, NULL); + while (stesc > start && stesc[-1] == ' ') + stesc--; + *stesc = '\0'; + break; + } + if (stesc == start) + return ROFF_CONT; + stesc--; + + /* Notice the end of the input. */ + + if (*stesc == '\n') { + *stesc-- = '\0'; + done = 1; + } + + expand_count = 0; + while (stesc >= start) { /* Search backwards for the next backslash. */ - if (*stesc != '\\') + if (*stesc != r->escape) { + if (*stesc == '\\') { + *stesc = '\0'; + buf->sz = mandoc_asprintf(&nbuf, "%s\\e%s", + buf->buf, stesc + 1) + 1; + start = nbuf + pos; + stesc = nbuf + (stesc - buf->buf); + free(buf->buf); + buf->buf = nbuf; + } + stesc--; continue; + } /* If it is escaped, skip it. */ for (cp = stesc - 1; cp >= start; cp--) - if (*cp != '\\') + if (*cp != r->escape) break; if ((stesc - cp) % 2 == 0) { - stesc = (char *)cp; + while (stesc > cp) + *stesc-- = '\\'; continue; + } else if (stesc[1] != '\0') { + *stesc = '\\'; + } else { + *stesc-- = '\0'; + if (done) + continue; + else + return ROFF_APPEND; } /* Decide whether to expand or to check only. */ @@ -1193,6 +1251,7 @@ roff_res(struct roff *r, struct buf *buf, int ln, int pos) mandoc_vmsg(MANDOCERR_ESC_BAD, r->parse, ln, (int)(stesc - buf->buf), "%.*s", (int)(cp - stesc), stesc); + stesc--; continue; } @@ -1407,7 +1466,7 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs) /* Expand some escape sequences. */ e = roff_res(r, buf, ln, pos); - if (e == ROFF_IGN) + if (e == ROFF_IGN || e == ROFF_APPEND) return e; assert(e == ROFF_CONT); @@ -2847,7 +2906,7 @@ roff_cc(ROFF_ARGS) p = buf->buf + pos; if (*p == '\0' || (r->control = *p++) == '.') - r->control = 0; + r->control = '\0'; if (*p != '\0') mandoc_vmsg(MANDOCERR_ARG_EXCESS, r->parse, @@ -2857,6 +2916,33 @@ roff_cc(ROFF_ARGS) } static enum rofferr +roff_ec(ROFF_ARGS) +{ + const char *p; + + p = buf->buf + pos; + if (*p == '\0') + r->escape = '\\'; + else { + r->escape = *p; + if (*++p != '\0') + mandoc_vmsg(MANDOCERR_ARG_EXCESS, r->parse, + ln, p - buf->buf, "ec ... %s", p); + } + return ROFF_IGN; +} + +static enum rofferr +roff_eo(ROFF_ARGS) +{ + r->escape = '\0'; + if (buf->buf[pos] != '\0') + mandoc_vmsg(MANDOCERR_ARG_SKIP, r->parse, + ln, pos, "eo %s", buf->buf + pos); + return ROFF_IGN; +} + +static enum rofferr roff_tr(ROFF_ARGS) { const char *p, *first, *second; @@ -3383,9 +3469,9 @@ roff_getcontrol(const struct roff *r, const char *cp, int *ppos) pos = *ppos; - if (0 != r->control && cp[pos] == r->control) + if (r->control != '\0' && cp[pos] == r->control) pos++; - else if (0 != r->control) + else if (r->control != '\0') return 0; else if ('\\' == cp[pos] && '.' == cp[pos + 1]) pos += 2; |