-/* $Id: roff.c,v 1.326 2018/04/09 22:27:04 schwarze Exp $ */
+/* $Id: roff.c,v 1.328 2018/04/11 17:11:13 schwarze Exp $ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015, 2017, 2018 Ingo Schwarze <schwarze@openbsd.org>
struct roffreg {
struct roffstr key;
int val;
+ int step;
struct roffreg *next;
};
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 *,
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 *,
r = mandoc_calloc(1, sizeof(struct roff));
r->parse = parse;
- r->reqtab = roffhash_alloc(0, ROFF_USERDEF);
+ r->reqtab = roffhash_alloc(0, ROFF_RENAMED);
r->options = options;
r->format = options & (MPARSE_MDOC | MPARSE_MAN);
r->rstackpos = -1;
roff_res(struct roff *r, struct buf *buf, int ln, int pos)
{
char ubuf[24]; /* buffer to print the number */
+ struct roff_node *n; /* used for header comments */
const char *start; /* start of the string to process */
char *stesc; /* start of an escape sequence ('\\') */
+ char *ep; /* end of comment string */
const char *stnam; /* start of the name, after "[(*" */
const char *cp; /* end of the name, e.g. before ']' */
const char *res; /* the string to be substituted */
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. */
/* Handle trailing whitespace. */
- cp = strchr(stesc--, '\0') - 1;
- if (*cp == '\n') {
+ ep = strchr(stesc--, '\0') - 1;
+ if (*ep == '\n') {
done = 1;
- cp--;
+ ep--;
}
- if (*cp == ' ' || *cp == '\t')
+ if (*ep == ' ' || *ep == '\t')
mandoc_msg(MANDOCERR_SPACE_EOL, r->parse,
- ln, cp - buf->buf, NULL);
+ ln, ep - buf->buf, NULL);
+
+ /*
+ * Save comments preceding the title macro
+ * in the syntax tree.
+ */
+
+ if (r->format == 0) {
+ while (*ep == ' ' || *ep == '\t')
+ ep--;
+ ep[1] = '\0';
+ n = roff_node_alloc(r->man,
+ ln, stesc + 1 - buf->buf,
+ ROFFT_COMMENT, TOKEN_NONE);
+ n->string = mandoc_strdup(stesc + 2);
+ roff_node_append(r->man, n);
+ n->flags |= NODE_VALID | NODE_ENDED;
+ r->man->next = ROFF_NEXT_SIBLING;
+ }
+
+ /* Discard comments. */
+
while (stesc > start && stesc[-1] == ' ')
stesc--;
*stesc = '\0';
term = cp[1];
/* FALLTHROUGH */
case 'n':
+ sign = cp[1];
+ if (sign == '+' || sign == '-')
+ cp++;
res = ubuf;
break;
default:
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;
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;
reg->key.p = mandoc_strndup(name, len);
reg->key.sz = len;
reg->val = 0;
+ reg->step = 0;
reg->next = r->regtab;
r->regtab = reg;
}
reg->val -= val;
else
reg->val = val;
+ if (step != INT_MIN)
+ reg->step = step;
}
/*
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;
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;
}
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;
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;
}