diff options
author | 2018-04-10 00:52:21 +0000 | |
---|---|---|
committer | 2018-04-10 00:52:21 +0000 | |
commit | dcd9eb04fac3fc0204c41a5cde01d05348c2f357 (patch) | |
tree | 316158f0ed23ef0a1a7e8d7ce819ea4fbcd72eae /usr.bin/mandoc/roff.c | |
parent | more typos spotted by Karsten Weiss using codespell (diff) | |
download | wireguard-openbsd-dcd9eb04fac3fc0204c41a5cde01d05348c2f357.tar.xz wireguard-openbsd-dcd9eb04fac3fc0204c41a5cde01d05348c2f357.zip |
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.
Diffstat (limited to 'usr.bin/mandoc/roff.c')
-rw-r--r-- | usr.bin/mandoc/roff.c | 59 |
1 files changed, 44 insertions, 15 deletions
diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c index a191d34a49c..47507154239 100644 --- a/usr.bin/mandoc/roff.c +++ b/usr.bin/mandoc/roff.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roff.c,v 1.198 2018/04/09 22:26:25 schwarze Exp $ */ +/* $OpenBSD: roff.c,v 1.199 2018/04/10 00:52:21 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org> @@ -71,6 +71,7 @@ struct roffkv { struct roffreg { struct roffstr key; int val; + int step; struct roffreg *next; }; @@ -180,7 +181,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 *, @@ -205,7 +207,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 *, @@ -1134,6 +1136,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. */ @@ -1244,6 +1247,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: @@ -1348,7 +1354,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; @@ -2520,12 +2526,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; @@ -2542,6 +2548,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; } @@ -2552,6 +2559,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; } /* @@ -2587,11 +2596,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; @@ -2602,12 +2611,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; } @@ -2647,9 +2668,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; @@ -2664,9 +2685,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; } |