=================================================================== RCS file: /cvs/mandoc/roff.c,v retrieving revision 1.365 retrieving revision 1.373 diff -u -p -r1.365 -r1.373 --- mandoc/roff.c 2019/04/21 23:51:21 1.365 +++ mandoc/roff.c 2020/04/06 10:16:17 1.373 @@ -1,7 +1,7 @@ -/* $Id: roff.c,v 1.365 2019/04/21 23:51:21 schwarze Exp $ */ +/* $Id: roff.c,v 1.373 2020/04/06 10:16:17 schwarze Exp $ */ /* + * Copyright (c) 2010-2015, 2017-2020 Ingo Schwarze * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons - * Copyright (c) 2010-2015, 2017-2019 Ingo Schwarze * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,6 +14,8 @@ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Implementation of the roff(7) parser for mandoc(1). */ #include "config.h" @@ -196,7 +198,7 @@ static int roff_ds(ROFF_ARGS); static int roff_ec(ROFF_ARGS); static int roff_eo(ROFF_ARGS); static int roff_eqndelim(struct roff *, struct buf *, int); -static int roff_evalcond(struct roff *r, int, char *, int *); +static int roff_evalcond(struct roff *, int, char *, int *); static int roff_evalnum(struct roff *, int, const char *, int *, int *, int); static int roff_evalpar(struct roff *, int, @@ -355,7 +357,7 @@ const char *__roff_name[MAN_MAX + 1] = { "Lk", "Mt", "Brq", "Bro", "Brc", "%C", "Es", "En", "Dx", "%Q", "%U", "Ta", - NULL, + "Tg", NULL, "TH", "SH", "SS", "TP", "TQ", "LP", "PP", "P", "IP", @@ -771,6 +773,7 @@ void roff_reset(struct roff *r) { roff_free1(r); + r->options |= MPARSE_COMMENT; r->format = r->options & (MPARSE_MDOC | MPARSE_MAN); r->control = '\0'; r->escape = '\\'; @@ -783,7 +786,7 @@ roff_reset(struct roff *r) void roff_free(struct roff *r) { - int i; + int i; roff_free1(r); for (i = 0; i < r->mstacksz; i++) @@ -800,7 +803,7 @@ roff_alloc(int options) r = mandoc_calloc(1, sizeof(struct roff)); r->reqtab = roffhash_alloc(0, ROFF_RENAMED); - r->options = options; + r->options = options | MPARSE_COMMENT; r->format = options & (MPARSE_MDOC | MPARSE_MAN); r->mstackpos = -1; r->rstackpos = -1; @@ -1113,13 +1116,72 @@ roff_node_delete(struct roff_man *man, struct roff_nod roff_node_free(n); } +int +roff_node_transparent(struct roff_node *n) +{ + if (n == NULL) + return 0; + if (n->type == ROFFT_COMMENT || n->flags & NODE_NOPRT) + return 1; + return roff_tok_transparent(n->tok); +} + +int +roff_tok_transparent(enum roff_tok tok) +{ + switch (tok) { + case ROFF_ft: + case ROFF_ll: + case ROFF_mc: + case ROFF_po: + case ROFF_ta: + case MDOC_Db: + case MDOC_Es: + case MDOC_Sm: + case MDOC_Tg: + case MAN_DT: + case MAN_UC: + case MAN_PD: + case MAN_AT: + return 1; + default: + return 0; + } +} + +struct roff_node * +roff_node_child(struct roff_node *n) +{ + for (n = n->child; roff_node_transparent(n); n = n->next) + continue; + return n; +} + +struct roff_node * +roff_node_prev(struct roff_node *n) +{ + do { + n = n->prev; + } while (roff_node_transparent(n)); + return n; +} + +struct roff_node * +roff_node_next(struct roff_node *n) +{ + do { + n = n->next; + } while (roff_node_transparent(n)); + return n; +} + void deroff(char **dest, const struct roff_node *n) { char *cp; size_t sz; - if (n->type != ROFFT_TEXT) { + if (n->string == NULL) { for (n = n->child; n != NULL; n = n->next) deroff(dest, n); return; @@ -1246,7 +1308,7 @@ roff_expand(struct roff *r, struct buf *buf, int ln, i * in the syntax tree. */ - if (newesc != ASCII_ESC && r->format == 0) { + if (newesc != ASCII_ESC && r->options & MPARSE_COMMENT) { while (*ep == ' ' || *ep == '\t') ep--; ep[1] = '\0'; @@ -1590,7 +1652,7 @@ char * roff_getarg(struct roff *r, char **cpp, int ln, int *pos) { struct buf buf; - char *cp, *start; + char *cp, *start; int newesc, pairs, quoted, white; /* Quoting can only start with a new word. */ @@ -1815,8 +1877,10 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, roff_addtbl(r->man, ln, r->tbl); return e; } - if ( ! ctl) + if ( ! ctl) { + r->options &= ~MPARSE_COMMENT; return roff_parsetext(r, buf, pos, offs) | e; + } /* Skip empty request lines. */ @@ -1839,6 +1903,7 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, /* No scope is open. This is a new request or macro. */ + r->options &= ~MPARSE_COMMENT; spos = pos; t = roff_parse(r, buf->buf, &pos, ln, ppos); @@ -2290,12 +2355,24 @@ roff_cond_sub(ROFF_ARGS) } } + t = roff_parse(r, buf->buf, &pos, ln, ppos); + + /* For now, let high level macros abort .ce mode. */ + + if (roffce_node != NULL && + (t == TOKEN_NONE || t == ROFF_Dd || t == ROFF_EQ || + t == ROFF_TH || t == ROFF_TS)) { + r->man->last = roffce_node; + r->man->next = ROFF_NEXT_SIBLING; + roffce_lines = 0; + roffce_node = NULL; + } + /* * Fully handle known macros when they are structurally * required or when the conditional evaluated to true. */ - t = roff_parse(r, buf->buf, &pos, ln, ppos); if (t == ROFF_break) { if (irc & ROFF_LOOPMASK) irc = ROFF_IGN | ROFF_LOOPEXIT;