From: schwarze Date: Sat, 20 Aug 2016 14:43:39 +0000 (+0000) Subject: If a column list starts with implicit rows (that is, rows without .It) X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=ad7fa6e5733c8a528a9c220b6e810b4e8d68855c;p=openbsd If a column list starts with implicit rows (that is, rows without .It) and roff-level nodes (e.g. tbl or eqn) follow, don't run into an assertion. Instead, wrap the roff-level nodes in their own row. Issue found by tb@ with afl(1). --- diff --git a/regress/usr.bin/mandoc/mdoc/Bl/Makefile b/regress/usr.bin/mandoc/mdoc/Bl/Makefile index 9c740556d88..a40a2828d99 100644 --- a/regress/usr.bin/mandoc/mdoc/Bl/Makefile +++ b/regress/usr.bin/mandoc/mdoc/Bl/Makefile @@ -1,7 +1,7 @@ -# $OpenBSD: Makefile,v 1.29 2015/10/12 15:27:53 schwarze Exp $ +# $OpenBSD: Makefile,v 1.30 2016/08/20 14:43:39 schwarze Exp $ REGRESS_TARGETS = item inset diag ohang bullet dash enum hang tag -REGRESS_TARGETS += column extend nested offset secstart +REGRESS_TARGETS += column colNoIt extend nested offset secstart REGRESS_TARGETS += notype multitype badargs REGRESS_TARGETS += empty noIt emptyhead emptytag emptyitem multitag @@ -23,7 +23,7 @@ LINT_TARGETS += bareIt bareTa break breakingIt broken SKIP_GROFF ?= notype empty break breakingIt broken emptytag -SKIP_TMAN ?= column multitype multitag bareTa break broken +SKIP_TMAN ?= column colNoIt multitype multitag bareTa break broken # Fixing the indentation in long .IP and .TP tags in -man -Tascii # caused a minor regression in -Tman that is not trivial to fix, diff --git a/regress/usr.bin/mandoc/mdoc/Bl/colNoIt.in b/regress/usr.bin/mandoc/mdoc/Bl/colNoIt.in new file mode 100644 index 00000000000..7c80cf9320d --- /dev/null +++ b/regress/usr.bin/mandoc/mdoc/Bl/colNoIt.in @@ -0,0 +1,15 @@ +.Dd August 20, 2016 +.Dt BL-COLNOIT 1 +.Os OpenBSD +.Sh NAME +.Nm Bl-colNoIt +.Nd column lists without item macros +.Sh DESCRIPTION +.Bl -column "a" "b" +.Sy a Ta b +.Em c Ta d +.El +.Bl -column "a" "b" +a b +c d +.El diff --git a/regress/usr.bin/mandoc/mdoc/Bl/colNoIt.out_ascii b/regress/usr.bin/mandoc/mdoc/Bl/colNoIt.out_ascii new file mode 100644 index 00000000000..e61c33343ff --- /dev/null +++ b/regress/usr.bin/mandoc/mdoc/Bl/colNoIt.out_ascii @@ -0,0 +1,13 @@ +BL-COLNOIT(1) General Commands Manual BL-COLNOIT(1) + +NNAAMMEE + BBll--ccoollNNooIItt - column lists without item macros + +DDEESSCCRRIIPPTTIIOONN + aa b + _c d + + a b + c d + +OpenBSD August 20, 2016 OpenBSD diff --git a/regress/usr.bin/mandoc/tbl/macro/Makefile b/regress/usr.bin/mandoc/tbl/macro/Makefile index 25e415f92c0..70ec1b332c1 100644 --- a/regress/usr.bin/mandoc/tbl/macro/Makefile +++ b/regress/usr.bin/mandoc/tbl/macro/Makefile @@ -1,11 +1,12 @@ -# $OpenBSD: Makefile,v 1.1.1.1 2015/01/29 23:24:24 schwarze Exp $ +# $OpenBSD: Makefile,v 1.2 2016/08/20 14:43:40 schwarze Exp $ -REGRESS_TARGETS = man nested +REGRESS_TARGETS = man nested column LINT_TARGETS = man nested -# trivial difference to groff-1.22.3: +# trivial differences to groff-1.22.3: # .TS in a table causes a blank table line in GNU tbl(1), but not in mandoc. +# .TS in a column list causes a blank line in mandoc, but not in GNU tbl(1). -SKIP_GROFF = nested +SKIP_GROFF = nested column .include diff --git a/regress/usr.bin/mandoc/tbl/macro/column.in b/regress/usr.bin/mandoc/tbl/macro/column.in new file mode 100644 index 00000000000..511025eaf6d --- /dev/null +++ b/regress/usr.bin/mandoc/tbl/macro/column.in @@ -0,0 +1,16 @@ +.Dd August 20, 2016 +.Dt TBL-COLUMN 1 +.Os OpenBSD +.Sh NAME +.Nm TBL-column +.Nd tables inside column lists +.Sh DESCRIPTION +.Bl -column "a" "b" +.Sy a Ta b +.TS +lll. +1 2 3 +4 5 6 +.TE +.Em c Ta d +.El diff --git a/regress/usr.bin/mandoc/tbl/macro/column.out_ascii b/regress/usr.bin/mandoc/tbl/macro/column.out_ascii new file mode 100644 index 00000000000..b4428aa649d --- /dev/null +++ b/regress/usr.bin/mandoc/tbl/macro/column.out_ascii @@ -0,0 +1,13 @@ +TBL-COLUMN(1) General Commands Manual TBL-COLUMN(1) + +NNAAMMEE + TTBBLL--ccoolluummnn - tables inside column lists + +DDEESSCCRRIIPPTTIIOONN + aa b + 1 2 3 + 4 5 6 + + _c d + +OpenBSD August 20, 2016 OpenBSD diff --git a/usr.bin/mandoc/mdoc.c b/usr.bin/mandoc/mdoc.c index 56ae0c9acd5..407f6bb3240 100644 --- a/usr.bin/mandoc/mdoc.c +++ b/usr.bin/mandoc/mdoc.c @@ -1,7 +1,7 @@ -/* $OpenBSD: mdoc.c,v 1.145 2015/10/30 19:03:36 schwarze Exp $ */ +/* $OpenBSD: mdoc.c,v 1.146 2016/08/20 14:43:39 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons - * Copyright (c) 2010, 2012-2015 Ingo Schwarze + * Copyright (c) 2010, 2012-2016 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 @@ -217,29 +217,19 @@ mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs) struct roff_node *n; char *c, *ws, *end; - assert(mdoc->last); n = mdoc->last; /* - * Divert directly to list processing if we're encountering a - * columnar ROFFT_BLOCK with or without a prior ROFFT_BLOCK entry - * (a ROFFT_BODY means it's already open, in which case we should - * process within its context in the normal way). + * If a column list contains plain text, assume an implicit item + * macro. This can happen one or more times at the beginning + * of such a list, intermixed with non-It mdoc macros and with + * nodes generated on the roff level, for example by tbl. */ - if (n->tok == MDOC_Bl && n->type == ROFFT_BODY && - n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) { - /* `Bl' is open without any children. */ - mdoc->flags |= MDOC_FREECOL; - mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf); - return 1; - } - - if (n->tok == MDOC_It && n->type == ROFFT_BLOCK && - NULL != n->parent && - MDOC_Bl == n->parent->tok && - LIST_column == n->parent->norm->Bl.type) { - /* `Bl' has block-level `It' children. */ + if ((n->tok == MDOC_Bl && n->type == ROFFT_BODY && + n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) || + (n->parent != NULL && n->parent->tok == MDOC_Bl && + n->parent->norm->Bl.type == LIST_column)) { mdoc->flags |= MDOC_FREECOL; mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf); return 1; @@ -391,36 +381,23 @@ mdoc_pmacro(struct roff_man *mdoc, int ln, char *buf, int offs) * into macro processing. */ - if (NULL == mdoc->last || MDOC_It == tok || MDOC_El == tok) { - mdoc_macro(mdoc, tok, ln, sv, &offs, buf); - return 1; - } - n = mdoc->last; - assert(mdoc->last); - - /* - * If the first macro of a `Bl -column', open an `It' block - * context around the parsed macro. - */ - - if (n->tok == MDOC_Bl && n->type == ROFFT_BODY && - n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) { - mdoc->flags |= MDOC_FREECOL; - mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf); + if (n == NULL || tok == MDOC_It || tok == MDOC_El) { + mdoc_macro(mdoc, tok, ln, sv, &offs, buf); return 1; } /* - * If we're following a block-level `It' within a `Bl -column' - * context (perhaps opened in the above block or in ptext()), - * then open an `It' block context around the parsed macro. + * If a column list contains a non-It macro, assume an implicit + * item macro. This can happen one or more times at the + * beginning of such a list, intermixed with text lines and + * with nodes generated on the roff level, for example by tbl. */ - if (n->tok == MDOC_It && n->type == ROFFT_BLOCK && - NULL != n->parent && - MDOC_Bl == n->parent->tok && - LIST_column == n->parent->norm->Bl.type) { + if ((n->tok == MDOC_Bl && n->type == ROFFT_BODY && + n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) || + (n->parent != NULL && n->parent->tok == MDOC_Bl && + n->parent->norm->Bl.type == LIST_column)) { mdoc->flags |= MDOC_FREECOL; mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf); return 1; diff --git a/usr.bin/mandoc/mdoc_validate.c b/usr.bin/mandoc/mdoc_validate.c index 9d69b6faf11..d1d9bb4d7e2 100644 --- a/usr.bin/mandoc/mdoc_validate.c +++ b/usr.bin/mandoc/mdoc_validate.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mdoc_validate.c,v 1.223 2016/08/11 11:39:19 schwarze Exp $ */ +/* $OpenBSD: mdoc_validate.c,v 1.224 2016/08/20 14:43:39 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons * Copyright (c) 2010-2016 Ingo Schwarze @@ -1320,11 +1320,41 @@ post_bl(POST_ARGS) return; } while (nchild != NULL) { + nnext = nchild->next; if (nchild->tok == MDOC_It || (nchild->tok == MDOC_Sm && - nchild->next != NULL && - nchild->next->tok == MDOC_It)) { - nchild = nchild->next; + nnext != NULL && nnext->tok == MDOC_It)) { + nchild = nnext; + continue; + } + + /* + * In .Bl -column, the first rows may be implicit, + * that is, they may not start with .It macros. + * Such rows may be followed by nodes generated on the + * roff level, for example .TS, which cannot be moved + * out of the list. In that case, wrap such roff nodes + * into an implicit row. + */ + + if (nchild->prev != NULL) { + mdoc->last = nchild; + mdoc->next = ROFF_NEXT_SIBLING; + roff_block_alloc(mdoc, nchild->line, + nchild->pos, MDOC_It); + roff_head_alloc(mdoc, nchild->line, + nchild->pos, MDOC_It); + mdoc->next = ROFF_NEXT_SIBLING; + roff_body_alloc(mdoc, nchild->line, + nchild->pos, MDOC_It); + while (nchild->tok != MDOC_It) { + mdoc_node_relink(mdoc, nchild); + if ((nchild = nnext) == NULL) + break; + nnext = nchild->next; + mdoc->next = ROFF_NEXT_SIBLING; + } + mdoc->last = nbody; continue; } @@ -1340,13 +1370,11 @@ post_bl(POST_ARGS) nblock = nbody->parent; nprev = nblock->prev; nparent = nblock->parent; - nnext = nchild->next; /* * Unlink this child. */ - assert(nchild->prev == NULL); nbody->child = nnext; if (nnext == NULL) nbody->last = NULL;