=================================================================== RCS file: /cvs/mandoc/roff.c,v retrieving revision 1.315 retrieving revision 1.324 diff -u -p -r1.315 -r1.324 --- mandoc/roff.c 2017/06/18 17:36:03 1.315 +++ mandoc/roff.c 2017/07/14 17:16:16 1.324 @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.315 2017/06/18 17:36:03 schwarze Exp $ */ +/* $Id: roff.c,v 1.324 2017/07/14 17:16:16 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons * Copyright (c) 2010-2015, 2017 Ingo Schwarze @@ -98,9 +98,8 @@ struct roff { struct tbl_node *first_tbl; /* first table parsed */ struct tbl_node *last_tbl; /* last table parsed */ struct tbl_node *tbl; /* current table being parsed */ - struct eqn_node *last_eqn; /* last equation parsed */ - struct eqn_node *first_eqn; /* first equation parsed */ - struct eqn_node *eqn; /* current equation being parsed */ + struct eqn_node *last_eqn; /* equation parser */ + struct eqn_node *eqn; /* active equation parser */ int eqn_inline; /* current equation is inline */ int options; /* parse options */ int rstacksz; /* current size limit of rstack */ @@ -154,6 +153,7 @@ static void roffnode_cleanscope(struct roff *); static void roffnode_pop(struct roff *); static void roffnode_push(struct roff *, enum roff_tok, const char *, int, int); +static void roff_addtbl(struct roff_man *, struct tbl_node *); static enum rofferr roff_als(ROFF_ARGS); static enum rofferr roff_block(ROFF_ARGS); static enum rofferr roff_block_text(ROFF_ARGS); @@ -330,7 +330,7 @@ const char *__roff_name[MAN_MAX + 1] = { "RE", "RS", "DT", "UC", "PD", "AT", "in", "OP", "EX", "EE", "UR", - "UE", NULL + "UE", "MT", "ME", NULL }; const char *const *roff_name = __roff_name; @@ -695,7 +695,6 @@ static void roff_free1(struct roff *r) { struct tbl_node *tbl; - struct eqn_node *e; int i; while (NULL != (tbl = r->first_tbl)) { @@ -704,11 +703,9 @@ roff_free1(struct roff *r) } r->first_tbl = r->last_tbl = r->tbl = NULL; - while (NULL != (e = r->first_eqn)) { - r->first_eqn = e->next; - eqn_free(e); - } - r->first_eqn = r->last_eqn = r->eqn = NULL; + if (r->last_eqn != NULL) + eqn_free(r->last_eqn); + r->last_eqn = r->eqn = NULL; while (r->last) roffnode_pop(r); @@ -819,14 +816,14 @@ roff_man_free(struct roff_man *man) struct roff_man * roff_man_alloc(struct roff *roff, struct mparse *parse, - const char *defos, int quick) + const char *os_s, int quick) { struct roff_man *man; man = mandoc_calloc(1, sizeof(*man)); man->parse = parse; man->roff = roff; - man->defos = defos; + man->os_s = os_s; man->quick = quick; roff_man_alloc1(man); roff->man = man; @@ -983,31 +980,21 @@ roff_body_alloc(struct roff_man *man, int line, int po return n; } -void -roff_addeqn(struct roff_man *man, const struct eqn *eqn) +static void +roff_addtbl(struct roff_man *man, struct tbl_node *tbl) { struct roff_node *n; + const struct tbl_span *span; - n = roff_node_alloc(man, eqn->ln, eqn->pos, ROFFT_EQN, TOKEN_NONE); - n->eqn = eqn; - if (eqn->ln > man->last->line) - n->flags |= NODE_LINE; - roff_node_append(man, n); - man->next = ROFF_NEXT_SIBLING; -} - -void -roff_addtbl(struct roff_man *man, const struct tbl_span *tbl) -{ - struct roff_node *n; - if (man->macroset == MACROSET_MAN) man_breakscope(man, ROFF_TS); - n = roff_node_alloc(man, tbl->line, 0, ROFFT_TBL, TOKEN_NONE); - n->span = tbl; - roff_node_append(man, n); - n->flags |= NODE_VALID | NODE_ENDED; - man->next = ROFF_NEXT_SIBLING; + while ((span = tbl_span(tbl)) != NULL) { + n = roff_node_alloc(man, tbl->line, 0, ROFFT_TBL, TOKEN_NONE); + n->span = span; + roff_node_append(man, n); + n->flags |= NODE_VALID | NODE_ENDED; + man->next = ROFF_NEXT_SIBLING; + } } void @@ -1055,6 +1042,8 @@ roff_node_free(struct roff_node *n) mdoc_argv_free(n->args); if (n->type == ROFFT_BLOCK || n->type == ROFFT_ELEM) free(n->norm); + if (n->eqn != NULL) + eqn_box_free(n->eqn); free(n->string); free(n); } @@ -1138,13 +1127,13 @@ roff_res(struct roff *r, struct buf *buf, int ln, int size_t maxl; /* expected length of the escape name */ size_t naml; /* actual length of the escape name */ enum mandoc_esc esc; /* type of the escape sequence */ - enum mdoc_os os_e; /* kind of RCS id seen */ int inaml; /* length returned from mandoc_escape() */ int expand_count; /* to avoid infinite loops */ int npos; /* position in numeric expression */ int arg_complete; /* argument not interrupted by eol */ int done; /* no more input available */ int deftype; /* type of definition to paste */ + int rcsid; /* kind of RCS id seen */ char term; /* character terminating the escape */ /* Search forward for comments. */ @@ -1160,20 +1149,21 @@ roff_res(struct roff *r, struct buf *buf, int ln, int /* Comment found, look for RCS id. */ + rcsid = 0; if ((cp = strstr(stesc, "$" "OpenBSD")) != NULL) { - os_e = MDOC_OS_OPENBSD; + rcsid = 1 << MANDOC_OS_OPENBSD; cp += 8; } else if ((cp = strstr(stesc, "$" "NetBSD")) != NULL) { - os_e = MDOC_OS_NETBSD; + rcsid = 1 << MANDOC_OS_NETBSD; cp += 7; } if (cp != NULL && isalnum((unsigned char)*cp) == 0 && strchr(cp, '$') != NULL) { - if (r->man->meta.rcsids & (1 << os_e)) + if (r->man->meta.rcsids & rcsid) mandoc_msg(MANDOCERR_RCS_REP, r->parse, ln, stesc + 1 - buf->buf, stesc + 1); - r->man->meta.rcsids |= 1 << os_e; + r->man->meta.rcsids |= rcsid; } /* Handle trailing whitespace. */ @@ -1512,10 +1502,15 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, return e; assert(e == ROFF_CONT); } - if (r->eqn != NULL) - return eqn_read(&r->eqn, ln, buf->buf, ppos, offs); - if (r->tbl != NULL && ( ! ctl || buf->buf[pos] == '\0')) - return tbl_read(r->tbl, ln, buf->buf, ppos); + if (r->eqn != NULL && strncmp(buf->buf + ppos, ".EN", 3)) { + eqn_read(r->eqn, buf->buf + ppos); + return ROFF_IGN; + } + if (r->tbl != NULL && (ctl == 0 || buf->buf[pos] == '\0')) { + tbl_read(r->tbl, ln, buf->buf, ppos); + roff_addtbl(r->man, r->tbl); + return ROFF_IGN; + } if ( ! ctl) return roff_parsetext(r, buf, pos, offs); @@ -1556,13 +1551,16 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, pos++; while (buf->buf[pos] == ' ') pos++; - return tbl_read(r->tbl, ln, buf->buf, pos); + tbl_read(r->tbl, ln, buf->buf, pos); + roff_addtbl(r->man, r->tbl); + return ROFF_IGN; } /* For now, let high level macros abort .ce mode. */ if (ctl && roffce_node != NULL && - (t == TOKEN_NONE || t == ROFF_EQ || t == ROFF_TS)) { + (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; @@ -1585,22 +1583,23 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, void roff_endparse(struct roff *r) { - - if (r->last) + if (r->last != NULL) mandoc_msg(MANDOCERR_BLK_NOEND, r->parse, r->last->line, r->last->col, roff_name[r->last->tok]); - if (r->eqn) { + if (r->eqn != NULL) { mandoc_msg(MANDOCERR_BLK_NOEND, r->parse, - r->eqn->eqn.ln, r->eqn->eqn.pos, "EQ"); - eqn_end(&r->eqn); + r->eqn->node->line, r->eqn->node->pos, "EQ"); + eqn_parse(r->eqn); + r->eqn = NULL; } - if (r->tbl) { + if (r->tbl != NULL) { mandoc_msg(MANDOCERR_BLK_NOEND, r->parse, r->tbl->line, r->tbl->pos, "TS"); - tbl_end(&r->tbl); + tbl_end(r->tbl); + r->tbl = NULL; } } @@ -1926,17 +1925,8 @@ roff_cond_sub(ROFF_ARGS) rr = r->last->rule; roffnode_cleanscope(r); - t = roff_parse(r, buf->buf, &pos, ln, ppos); /* - * Fully handle known macros when they are structurally - * required or when the conditional evaluated to true. - */ - - if (t != TOKEN_NONE && (rr || roffs[t].flags & ROFFMAC_STRUCT)) - return (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs); - - /* * If `\}' occurs on a macro line without a preceding macro, * drop the line completely. */ @@ -1948,14 +1938,29 @@ roff_cond_sub(ROFF_ARGS) /* Always check for the closing delimiter `\}'. */ while ((ep = strchr(ep, '\\')) != NULL) { - if (*(++ep) == '}') { - *ep = '&'; - roff_ccond(r, ln, ep - buf->buf - 1); - } - if (*ep != '\0') + switch (ep[1]) { + case '}': + memmove(ep, ep + 2, strlen(ep + 2) + 1); + roff_ccond(r, ln, ep - buf->buf); + break; + case '\0': ++ep; + break; + default: + ep += 2; + break; + } } - return rr ? ROFF_CONT : ROFF_IGN; + + /* + * 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); + return t != TOKEN_NONE && (rr || roffs[t].flags & ROFFMAC_STRUCT) + ? (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs) : rr + ? ROFF_CONT : ROFF_IGN; } static enum rofferr @@ -2776,16 +2781,19 @@ roff_Dd(ROFF_ARGS) static enum rofferr roff_TE(ROFF_ARGS) { - - if (NULL == r->tbl) + if (r->tbl == NULL) { mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse, ln, ppos, "TE"); - else if ( ! tbl_end(&r->tbl)) { + return ROFF_IGN; + } + if (tbl_end(r->tbl) == 0) { + r->tbl = NULL; free(buf->buf); buf->buf = mandoc_strdup(".sp"); buf->sz = 4; return ROFF_REPARSE; } + r->tbl = NULL; return ROFF_IGN; } @@ -2871,21 +2879,26 @@ roff_eqndelim(struct roff *r, struct buf *buf, int pos static enum rofferr roff_EQ(ROFF_ARGS) { - struct eqn_node *e; + struct roff_node *n; + if (r->man->macroset == MACROSET_MAN) + man_breakscope(r->man, ROFF_EQ); + n = roff_node_alloc(r->man, ln, ppos, ROFFT_EQN, TOKEN_NONE); + if (ln > r->man->last->line) + n->flags |= NODE_LINE; + n->eqn = mandoc_calloc(1, sizeof(*n->eqn)); + n->eqn->expectargs = UINT_MAX; + roff_node_append(r->man, n); + r->man->next = ROFF_NEXT_SIBLING; + assert(r->eqn == NULL); - e = eqn_alloc(ppos, ln, r->parse); + if (r->last_eqn == NULL) + r->last_eqn = eqn_alloc(r->parse); + else + eqn_reset(r->last_eqn); + r->eqn = r->last_eqn; + r->eqn->node = n; - if (r->last_eqn) { - r->last_eqn->next = e; - e->delim = r->last_eqn->delim; - e->odelim = r->last_eqn->odelim; - e->cdelim = r->last_eqn->cdelim; - } else - r->first_eqn = r->last_eqn = e; - - r->eqn = r->last_eqn = e; - if (buf->buf[pos] != '\0') mandoc_vmsg(MANDOCERR_ARG_SKIP, r->parse, ln, pos, ".EQ %s", buf->buf + pos); @@ -2896,30 +2909,31 @@ roff_EQ(ROFF_ARGS) static enum rofferr roff_EN(ROFF_ARGS) { - - mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse, ln, ppos, "EN"); + if (r->eqn != NULL) { + eqn_parse(r->eqn); + r->eqn = NULL; + } else + mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse, ln, ppos, "EN"); + if (buf->buf[pos] != '\0') + mandoc_vmsg(MANDOCERR_ARG_SKIP, r->parse, ln, pos, + "EN %s", buf->buf + pos); return ROFF_IGN; } static enum rofferr roff_TS(ROFF_ARGS) { - struct tbl_node *tbl; - - if (r->tbl) { + if (r->tbl != NULL) { mandoc_msg(MANDOCERR_BLK_BROKEN, r->parse, ln, ppos, "TS breaks TS"); - tbl_end(&r->tbl); + tbl_end(r->tbl); } - - tbl = tbl_alloc(ppos, ln, r->parse); - + r->tbl = tbl_alloc(ppos, ln, r->parse); if (r->last_tbl) - r->last_tbl->next = tbl; + r->last_tbl->next = r->tbl; else - r->first_tbl = r->last_tbl = tbl; - - r->tbl = r->last_tbl = tbl; + r->first_tbl = r->tbl; + r->last_tbl = r->tbl; return ROFF_IGN; } @@ -2931,7 +2945,8 @@ roff_onearg(ROFF_ARGS) int npos; if (r->man->flags & (MAN_BLINE | MAN_ELINE) && - (tok == ROFF_sp || tok == ROFF_ti)) + (tok == ROFF_ce || tok == ROFF_rj || tok == ROFF_sp || + tok == ROFF_ti)) man_breakscope(r->man, tok); if (roffce_node != NULL && (tok == ROFF_ce || tok == ROFF_rj)) { @@ -3596,20 +3611,6 @@ roff_freestr(struct roffkv *r) } /* --- accessors and utility functions ------------------------------------ */ - -const struct tbl_span * -roff_span(const struct roff *r) -{ - - return r->tbl ? tbl_span(r->tbl) : NULL; -} - -const struct eqn * -roff_eqn(const struct roff *r) -{ - - return r->last_eqn ? &r->last_eqn->eqn : NULL; -} /* * Duplicate an input string, making the appropriate character