diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2018-04-10 00:52:30 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2018-04-10 00:52:30 +0000 |
commit | 37f94bbdf74663ed1f212a4a0aa87e4faf4ca885 (patch) | |
tree | 2fa8495fcc4d028ad7c5b27d0950eb9637149e7f | |
parent | 272b0bdc5c87bfffd9b9864eac579487de6636ea (diff) | |
download | mandoc-37f94bbdf74663ed1f212a4a0aa87e4faf4ca885.tar.gz |
Two new low-level roff(7) features:
* .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.
-rw-r--r-- | TODO | 8 | ||||
-rw-r--r-- | regress/roff/nr/Makefile | 2 | ||||
-rw-r--r-- | regress/roff/nr/incr.in | 30 | ||||
-rw-r--r-- | regress/roff/nr/incr.out_ascii | 19 | ||||
-rw-r--r-- | roff.7 | 20 | ||||
-rw-r--r-- | roff.c | 57 |
6 files changed, 110 insertions, 26 deletions
@@ -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 diff --git a/regress/roff/nr/Makefile b/regress/roff/nr/Makefile index b3ba8102..562a5f30 100644 --- a/regress/roff/nr/Makefile +++ b/regress/roff/nr/Makefile @@ -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 index 00000000..a03493ff --- /dev/null +++ b/regress/roff/nr/incr.in @@ -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 index 00000000..d039d5b1 --- /dev/null +++ b/regress/roff/nr/incr.out_ascii @@ -0,0 +1,19 @@ +NR-INCR(1) General Commands Manual NR-INCR(1) + + + +NNAAMMEE + nr-incr - increment a number register by accessing it + +DDEESSCCRRIIPPTTIIOONN + 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) @@ -1,7 +1,7 @@ .\" $Id$ .\" .\" 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 @@ -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 @@ -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; } |