From 24ab75f2dd3fed4d32b30c3fdd01554d16f0bfd1 Mon Sep 17 00:00:00 2001 From: schwarze Date: Sun, 31 May 2015 23:12:16 +0000 Subject: [PATCH] Implement the roff(7) `r' (register exists) conditional. Missing feature found by Markus in Debian's bash(1) manual page. --- regress/usr.bin/mandoc/roff/cond/Makefile | 4 +- regress/usr.bin/mandoc/roff/cond/register.in | 11 ++++++ .../mandoc/roff/cond/register.out_ascii | 14 +++++++ share/man/man7/roff.7 | 11 ++++-- usr.bin/mandoc/roff.c | 38 ++++++++++++++++--- 5 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 regress/usr.bin/mandoc/roff/cond/register.in create mode 100644 regress/usr.bin/mandoc/roff/cond/register.out_ascii diff --git a/regress/usr.bin/mandoc/roff/cond/Makefile b/regress/usr.bin/mandoc/roff/cond/Makefile index 9c847081525..68a88694a01 100644 --- a/regress/usr.bin/mandoc/roff/cond/Makefile +++ b/regress/usr.bin/mandoc/roff/cond/Makefile @@ -1,6 +1,6 @@ -# $OpenBSD: Makefile,v 1.7 2014/07/07 21:35:42 schwarze Exp $ +# $OpenBSD: Makefile,v 1.8 2015/05/31 23:12:17 schwarze Exp $ -REGRESS_TARGETS = if ie close numeric strcmp before-Dd +REGRESS_TARGETS = if ie close numeric register strcmp before-Dd LINT_TARGETS = if close .include diff --git a/regress/usr.bin/mandoc/roff/cond/register.in b/regress/usr.bin/mandoc/roff/cond/register.in new file mode 100644 index 00000000000..d8c9629bee5 --- /dev/null +++ b/regress/usr.bin/mandoc/roff/cond/register.in @@ -0,0 +1,11 @@ +.TH REGISTER 1 "May 31, 2015" OpenBSD +.SH NAME +register \- conditional testing whether a register is defined +.SH DESCRIPTION +.ie rmyreg OOPS +.el not yet defined +.br +.nr myreg 0 +.ie rmyreg now defined +.el OOPS +.if !rmyreg OOPS diff --git a/regress/usr.bin/mandoc/roff/cond/register.out_ascii b/regress/usr.bin/mandoc/roff/cond/register.out_ascii new file mode 100644 index 00000000000..acd0f724126 --- /dev/null +++ b/regress/usr.bin/mandoc/roff/cond/register.out_ascii @@ -0,0 +1,14 @@ +REGISTER(1) General Commands Manual REGISTER(1) + + + +NNAAMMEE + register - conditional testing whether a register is defined + +DDEESSCCRRIIPPTTIIOONN + not yet defined + now defined + + + +OpenBSD May 31, 2015 REGISTER(1) diff --git a/share/man/man7/roff.7 b/share/man/man7/roff.7 index 13743c13fc1..5426baf5f7d 100644 --- a/share/man/man7/roff.7 +++ b/share/man/man7/roff.7 @@ -1,4 +1,4 @@ -.\" $OpenBSD: roff.7,v 1.51 2015/04/29 18:32:57 schwarze Exp $ +.\" $OpenBSD: roff.7,v 1.52 2015/05/31 23:12:16 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: April 29 2015 $ +.Dd $Mdocdate: May 31 2015 $ .Dt ROFF 7 .Os .Sh NAME @@ -1055,8 +1055,6 @@ If the first character of COND is .Pq string defined , .Sq e .Pq even page , -.Sq r -.Pq register accessed , .Sq t .Pq troff mode , or @@ -1064,6 +1062,11 @@ or .Pq vroff mode , COND evaluates to false. .It +If the first character of COND is +.Sq r , +it evalutes to true if the rest of COND is the name of an existing +number register; otherwise, it evaluates to false. +.It If COND starts with a parenthesis or with an optionally signed integer number, it is evaluated according to the rules of .Sx Numerical expressions diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c index f99246a7686..62f524f3976 100644 --- a/usr.bin/mandoc/roff.c +++ b/usr.bin/mandoc/roff.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roff.c,v 1.142 2015/05/01 16:01:53 schwarze Exp $ */ +/* $OpenBSD: roff.c,v 1.143 2015/05/31 23:12:16 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons * Copyright (c) 2010-2015 Ingo Schwarze @@ -395,8 +395,7 @@ 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_eqndelim(struct roff *, struct buf *, int); -static int roff_evalcond(struct roff *r, int, - const char *, int *); +static int roff_evalcond(struct roff *r, int, char *, int *); static int roff_evalnum(struct roff *, int, const char *, int *, int *, int); static int roff_evalpar(struct roff *, int, @@ -413,6 +412,8 @@ static int roff_getregn(const struct roff *, static int roff_getregro(const char *name); static const char *roff_getstrn(const struct roff *, const char *, size_t); +static int roff_hasregn(const struct roff *, + const char *, size_t); static enum rofferr roff_insec(ROFF_ARGS); static enum rofferr roff_it(ROFF_ARGS); static enum rofferr roff_line_ignore(ROFF_ARGS); @@ -2132,8 +2133,10 @@ out: * or string condition. */ static int -roff_evalcond(struct roff *r, int ln, const char *v, int *pos) +roff_evalcond(struct roff *r, int ln, char *v, int *pos) { + char *cp, *name; + size_t sz; int number, savepos, wanttrue; if ('!' == v[*pos]) { @@ -2156,13 +2159,16 @@ roff_evalcond(struct roff *r, int ln, const char *v, int *pos) /* FALLTHROUGH */ case 'e': /* FALLTHROUGH */ - case 'r': - /* FALLTHROUGH */ case 't': /* FALLTHROUGH */ case 'v': (*pos)++; return(!wanttrue); + case 'r': + cp = name = v + ++*pos; + sz = roff_getname(r, &cp, ln, *pos); + *pos = cp - v; + return((sz && roff_hasregn(r, name, sz)) == wanttrue); default: break; } @@ -2625,6 +2631,26 @@ roff_getregn(const struct roff *r, const char *name, size_t len) return(0); } +static int +roff_hasregn(const struct roff *r, const char *name, size_t len) +{ + struct roffreg *reg; + int val; + + if ('.' == name[0] && 2 == len) { + val = roff_getregro(name + 1); + if (-1 != val) + return(1); + } + + for (reg = r->regtab; reg; reg = reg->next) + if (len == reg->key.sz && + 0 == strncmp(name, reg->key.p, len)) + return(1); + + return(0); +} + static void roff_freereg(struct roffreg *reg) { -- 2.20.1