=================================================================== RCS file: /cvs/mandoc/roff.c,v retrieving revision 1.326 retrieving revision 1.330 diff -u -p -r1.326 -r1.330 --- mandoc/roff.c 2018/04/09 22:27:04 1.326 +++ mandoc/roff.c 2018/08/10 04:41:25 1.330 @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.326 2018/04/09 22:27:04 schwarze Exp $ */ +/* $Id: roff.c,v 1.330 2018/08/10 04:41:25 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons * Copyright (c) 2010-2015, 2017, 2018 Ingo Schwarze @@ -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 *, @@ -195,6 +197,7 @@ static enum rofferr roff_line_ignore(ROFF_ARGS); static void roff_man_alloc1(struct roff_man *); static void roff_man_free1(struct roff_man *); static enum rofferr roff_manyarg(ROFF_ARGS); +static enum rofferr roff_nop(ROFF_ARGS); static enum rofferr roff_nr(ROFF_ARGS); static enum rofferr roff_onearg(ROFF_ARGS); static enum roff_tok roff_parse(struct roff *, char *, int *, @@ -207,7 +210,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 *, @@ -488,7 +491,7 @@ static struct roffmac roffs[TOKEN_NONE] = { { roff_line_ignore, NULL, NULL, 0 }, /* nhychar */ { roff_unsupp, NULL, NULL, 0 }, /* nm */ { roff_unsupp, NULL, NULL, 0 }, /* nn */ - { roff_unsupp, NULL, NULL, 0 }, /* nop */ + { roff_nop, NULL, NULL, 0 }, /* nop */ { roff_nr, NULL, NULL, 0 }, /* nr */ { roff_unsupp, NULL, NULL, 0 }, /* nrf */ { roff_line_ignore, NULL, NULL, 0 }, /* nroff */ @@ -760,7 +763,7 @@ roff_alloc(struct mparse *parse, int options) 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; @@ -1120,8 +1123,10 @@ static enum rofferr 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 */ @@ -1136,6 +1141,7 @@ roff_res(struct roff *r, struct buf *buf, int ln, int 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. */ @@ -1170,14 +1176,35 @@ roff_res(struct roff *r, struct buf *buf, int ln, int /* 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'; @@ -1246,6 +1273,9 @@ roff_res(struct roff *r, struct buf *buf, int ln, int term = cp[1]; /* FALLTHROUGH */ case 'n': + sign = cp[1]; + if (sign == '+' || sign == '-') + cp++; res = ubuf; break; default: @@ -1350,7 +1380,7 @@ roff_res(struct roff *r, struct buf *buf, int ln, int 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 +2552,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 +2574,7 @@ roff_setregn(struct roff *r, const char *name, size_t 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 +2585,8 @@ roff_setregn(struct roff *r, const char *name, size_t reg->val -= val; else reg->val = val; + if (step != INT_MIN) + reg->step = step; } /* @@ -2589,11 +2622,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 +2637,24 @@ roff_getregn(struct roff *r, const char *name, size_t 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 +2694,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 +2711,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; } @@ -2793,6 +2846,7 @@ roff_TE(ROFF_ARGS) free(buf->buf); buf->buf = mandoc_strdup(".sp"); buf->sz = 4; + *offs = 0; return ROFF_REPARSE; } r->tbl = NULL; @@ -3108,6 +3162,15 @@ roff_eo(ROFF_ARGS) } static enum rofferr +roff_nop(ROFF_ARGS) +{ + while (buf->buf[pos] == ' ') + pos++; + *offs = pos; + return ROFF_RERUN; +} + +static enum rofferr roff_tr(ROFF_ARGS) { const char *p, *first, *second; @@ -3312,6 +3375,7 @@ roff_userdef(ROFF_ARGS) ln, (int)(cp - n1), NULL); free(buf->buf); buf->buf = n1; + *offs = 0; return ROFF_IGN; } @@ -3406,6 +3470,7 @@ roff_renamed(ROFF_ARGS) buf->buf[pos] == '\0' ? "" : " ", buf->buf + pos) + 1; free(buf->buf); buf->buf = nbuf; + *offs = 0; return ROFF_CONT; }