]> git.cameronkatri.com Git - mandoc.git/commitdiff
Two new low-level roff(7) features:
authorIngo Schwarze <schwarze@openbsd.org>
Tue, 10 Apr 2018 00:52:30 +0000 (00:52 +0000)
committerIngo Schwarze <schwarze@openbsd.org>
Tue, 10 Apr 2018 00:52:30 +0000 (00:52 +0000)
* .nr optional third argument (auto-increment step size)
* \n+ and \n- numerical register auto-increment and -decrement
bentley@ reported on Dec 9, 2013 that lang/sbcl(1) uses these.

TODO
regress/roff/nr/Makefile
regress/roff/nr/incr.in [new file with mode: 0644]
regress/roff/nr/incr.out_ascii [new file with mode: 0644]
roff.7
roff.c

diff --git a/TODO b/TODO
index 4d74fd0605e94475e59cabaa1e0cfa8e5a346208..0e324d9c07621dba356ecc0d10030dcc5cc346f7 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,6 +1,6 @@
 ************************************************************************
 * Official mandoc TODO.
-* $Id: TODO,v 1.249 2018/04/09 02:31:42 schwarze Exp $
+* $Id: TODO,v 1.250 2018/04/10 00:52:30 schwarze Exp $
 ************************************************************************
 
 Many issues are annotated for difficulty as follows:
@@ -52,10 +52,6 @@ are mere guesses, and some may be wrong.
   found by naddy@ in xloadimage(1)
   loc **  exist ***  algo *  size *  imp *
 
-- .nr third argument (auto-increment step size, requires \n+)
-  found by bentley@ in sbcl(1)  Mon, 9 Dec 2013 18:36:57 -0700
-  loc *  exist *  algo *  size *  imp **
-
 - .ns (no-space mode) occurs in xine-config(1)
   when implementing this, also let .TH set it
   reported by brad@  Sat, 15 Jan 2011 15:45:23 -0500
@@ -65,10 +61,6 @@ are mere guesses, and some may be wrong.
   found by jca@ in ratpoison(1)  Sun, 30 Jun 2013 12:01:09 +0200
   loc *  exist **  algo **  size **  imp **
 
-- \n+ and \n- numerical register increment and decrement
-  found by bentley@ in sbcl(1)  Mon, 9 Dec 2013 18:36:57 -0700
-  loc *  exist *  algo *  size *  imp **
-
 - \w'' improve width measurements
   would not be very useful without an expression parser, see below
   needed for Tcl_NewStringObj(3) via wiz@  Wed, 5 Mar 2014 22:27:43 +0100
index b3ba8102a150c68b0fa8f77bc741f5fb17880589..562a5f30268596ecb16acfc7faa9637f8ba3d84b 100644 (file)
@@ -1,6 +1,6 @@
 # $OpenBSD: Makefile,v 1.9 2015/01/23 00:38:43 schwarze Exp $
 
-REGRESS_TARGETS = argc divzero escname eval int predef rr scale undef
+REGRESS_TARGETS = argc divzero escname eval incr int predef rr scale undef
 LINT_TARGETS   = divzero escname
 
 .include <bsd.regress.mk>
diff --git a/regress/roff/nr/incr.in b/regress/roff/nr/incr.in
new file mode 100644 (file)
index 0000000..a03493f
--- /dev/null
@@ -0,0 +1,30 @@
+.\" $OpenBSD: undef.in,v 1.1 2018/04/09 22:26:25 schwarze Exp $
+.TH NR-INCR 1 "April 10, 2018"
+.SH NAME
+nr-incr \- increment a number register by accessing it
+.SH DESCRIPTION
+.nr myr 0 1
+Roff can count by merely accessing a number register:
+\n+[myr]
+\n+[myr]
+\n+[myr]
+.PP
+.nr myr +0 1+1
+It can also change the step size:
+\n+[myr]
+\n+[myr]
+\n+[myr]
+.PP
+.nr myr +0 3
+It can also count down:
+\n-[myr]
+\n-[myr]
+\n-[myr]
+\n-[myr]
+.PP
+.nr myr -0 -2
+Down in negative steps is up:
+\n-[myr]
+\n-[myr]
+\n-[myr]
+\n-[myr]
diff --git a/regress/roff/nr/incr.out_ascii b/regress/roff/nr/incr.out_ascii
new file mode 100644 (file)
index 0000000..d039d5b
--- /dev/null
@@ -0,0 +1,19 @@
+NR-INCR(1)                  General Commands Manual                 NR-INCR(1)
+
+
+
+N\bNA\bAM\bME\bE
+       nr-incr - increment a number register by accessing it
+
+D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
+       Roff can count by merely accessing a number register: 1 2 3
+
+       It can also change the step size: 5 7 9
+
+       It can also count down: 6 3 0 -3
+
+       Down in negative steps is up: -1 1 3 5
+
+
+
+OpenBSD                         April 10, 2018                      NR-INCR(1)
diff --git a/roff.7 b/roff.7
index 58b5379e3c4ef3596a9fe2938361088b23a21b89..8cb922c70676dfe5d7619dadd947bfed0490121f 100644 (file)
--- a/roff.7
+++ b/roff.7
@@ -1,7 +1,7 @@
-.\"    $Id: roff.7,v 1.95 2017/12/15 23:39:07 schwarze Exp $
+.\"    $Id: roff.7,v 1.96 2018/04/10 00:52:30 schwarze Exp $
 .\"
 .\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2010,2011,2013-2015,2017 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2010-2018 Ingo Schwarze <schwarze@openbsd.org>
 .\"
 .\" Permission to use, copy, modify, and distribute this software for any
 .\" purpose with or without fee is hereby granted, provided that the above
@@ -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: December 15 2017 $
+.Dd $Mdocdate: April 10 2018 $
 .Dt ROFF 7
 .Os
 .Sh NAME
@@ -1348,7 +1348,7 @@ Currently unsupported.
 .It Ic \&nop Ar body
 Execute the rest of the input line as a request or macro line.
 Currently unsupported.
-.It Ic \&nr Ar register Oo Cm + Ns | Ns Cm - Oc Ns Ar expression
+.It Ic \&nr Ar register Oo Cm + Ns | Ns Cm - Oc Ns Ar expression Op Ar stepsize
 Define or change a register.
 A register is an arbitrary string value that defines some sort of state,
 which influences parsing and/or formatting.
@@ -1360,6 +1360,14 @@ below.
 If it is prefixed by a sign, the register will be
 incremented or decremented instead of assigned to.
 .Pp
+The
+.Ar stepsize
+is used by the
+.Ic \en+
+auto-increment feature.
+It remains unchanged when omitted while changing an existing register,
+and it defaults to 0 when defining a new register.
+.Pp
 The following
 .Ar register
 is handled specially:
@@ -1996,13 +2004,19 @@ and
 Character
 .Ar number
 on the current font.
-.Ss \en Ns Bq Ar name
+.Ss \en Ns Oo +|- Oc Ns Bq Ar name
 Interpolate the number register
 .Ar name .
 For short names, there are variants
 .No \en Ns Ar c
 and
 .No \en( Ns Ar cc .
+If the optional sign is specified,
+the register is first incremented or decremented by the
+.Ar stepsize
+that was specified in the relevant
+.Ic \&nr
+request, and the changed value is interpolated.
 .Ss \eo\(aq Ns Ar string Ns \(aq
 Overstrike, writing all the characters contained in the
 .Ar string
diff --git a/roff.c b/roff.c
index 08c0afc51419e621b4600576de86b560769f7dbb..d37a9fc718b948b19c6aabe0ec80fb457ce541a7 100644 (file)
--- a/roff.c
+++ b/roff.c
@@ -1,4 +1,4 @@
-/*     $Id: roff.c,v 1.326 2018/04/09 22:27:04 schwarze Exp $ */
+/*     $Id: roff.c,v 1.327 2018/04/10 00:52:30 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -73,6 +73,7 @@ struct        roffkv {
 struct roffreg {
        struct roffstr   key;
        int              val;
+       int              step;
        struct roffreg  *next;
 };
 
@@ -182,7 +183,8 @@ static      void             roff_freestr(struct roffkv *);
 static size_t           roff_getname(struct roff *, char **, int, int);
 static int              roff_getnum(const char *, int *, int *, int);
 static int              roff_getop(const char *, int *, char *);
-static int              roff_getregn(struct roff *, const char *, size_t);
+static int              roff_getregn(struct roff *,
+                               const char *, size_t, char);
 static int              roff_getregro(const struct roff *,
                                const char *name);
 static const char      *roff_getstrn(struct roff *,
@@ -207,7 +209,7 @@ static      enum rofferr     roff_rm(ROFF_ARGS);
 static enum rofferr     roff_rn(ROFF_ARGS);
 static enum rofferr     roff_rr(ROFF_ARGS);
 static void             roff_setregn(struct roff *, const char *,
-                               size_t, int, char);
+                               size_t, int, char, int);
 static void             roff_setstr(struct roff *,
                                const char *, const char *, int);
 static void             roff_setstrn(struct roffkv **, const char *,
@@ -1136,6 +1138,7 @@ roff_res(struct roff *r, struct buf *buf, int ln, int pos)
        int              done;  /* no more input available */
        int              deftype; /* type of definition to paste */
        int              rcsid; /* kind of RCS id seen */
+       char             sign;  /* increment number register */
        char             term;  /* character terminating the escape */
 
        /* Search forward for comments. */
@@ -1246,6 +1249,9 @@ roff_res(struct roff *r, struct buf *buf, int ln, int pos)
                        term = cp[1];
                        /* FALLTHROUGH */
                case 'n':
+                       sign = cp[1];
+                       if (sign == '+' || sign == '-')
+                               cp++;
                        res = ubuf;
                        break;
                default:
@@ -1350,7 +1356,7 @@ roff_res(struct roff *r, struct buf *buf, int ln, int pos)
                case 'n':
                        if (arg_complete)
                                (void)snprintf(ubuf, sizeof(ubuf), "%d",
-                                   roff_getregn(r, stnam, naml));
+                                   roff_getregn(r, stnam, naml, sign));
                        else
                                ubuf[0] = '\0';
                        break;
@@ -2522,12 +2528,12 @@ roff_evalnum(struct roff *r, int ln, const char *v,
 void
 roff_setreg(struct roff *r, const char *name, int val, char sign)
 {
-       roff_setregn(r, name, strlen(name), val, sign);
+       roff_setregn(r, name, strlen(name), val, sign, INT_MIN);
 }
 
 static void
 roff_setregn(struct roff *r, const char *name, size_t len,
-    int val, char sign)
+    int val, char sign, int step)
 {
        struct roffreg  *reg;
 
@@ -2544,6 +2550,7 @@ roff_setregn(struct roff *r, const char *name, size_t len,
                reg->key.p = mandoc_strndup(name, len);
                reg->key.sz = len;
                reg->val = 0;
+               reg->step = 0;
                reg->next = r->regtab;
                r->regtab = reg;
        }
@@ -2554,6 +2561,8 @@ roff_setregn(struct roff *r, const char *name, size_t len,
                reg->val -= val;
        else
                reg->val = val;
+       if (step != INT_MIN)
+               reg->step = step;
 }
 
 /*
@@ -2589,11 +2598,11 @@ roff_getregro(const struct roff *r, const char *name)
 int
 roff_getreg(struct roff *r, const char *name)
 {
-       return roff_getregn(r, name, strlen(name));
+       return roff_getregn(r, name, strlen(name), '\0');
 }
 
 static int
-roff_getregn(struct roff *r, const char *name, size_t len)
+roff_getregn(struct roff *r, const char *name, size_t len, char sign)
 {
        struct roffreg  *reg;
        int              val;
@@ -2604,12 +2613,24 @@ roff_getregn(struct roff *r, const char *name, size_t len)
                        return val;
        }
 
-       for (reg = r->regtab; reg; reg = reg->next)
+       for (reg = r->regtab; reg; reg = reg->next) {
                if (len == reg->key.sz &&
-                   0 == strncmp(name, reg->key.p, len))
+                   0 == strncmp(name, reg->key.p, len)) {
+                       switch (sign) {
+                       case '+':
+                               reg->val += reg->step;
+                               break;
+                       case '-':
+                               reg->val -= reg->step;
+                               break;
+                       default:
+                               break;
+                       }
                        return reg->val;
+               }
+       }
 
-       roff_setregn(r, name, len, 0, '\0');
+       roff_setregn(r, name, len, 0, '\0', INT_MIN);
        return 0;
 }
 
@@ -2649,9 +2670,9 @@ roff_freereg(struct roffreg *reg)
 static enum rofferr
 roff_nr(ROFF_ARGS)
 {
-       char            *key, *val;
+       char            *key, *val, *step;
        size_t           keysz;
-       int              iv;
+       int              iv, is, len;
        char             sign;
 
        key = val = buf->buf + pos;
@@ -2666,9 +2687,17 @@ roff_nr(ROFF_ARGS)
        if (sign == '+' || sign == '-')
                val++;
 
-       if (roff_evalnum(r, ln, val, NULL, &iv, ROFFNUM_SCALE))
-               roff_setregn(r, key, keysz, iv, sign);
+       len = 0;
+       if (roff_evalnum(r, ln, val, &len, &iv, ROFFNUM_SCALE) == 0)
+               return ROFF_IGN;
+
+       step = val + len;
+       while (isspace((unsigned char)*step))
+               step++;
+       if (roff_evalnum(r, ln, step, NULL, &is, 0) == 0)
+               is = INT_MIN;
 
+       roff_setregn(r, key, keysz, iv, sign, is);
        return ROFF_IGN;
 }