If there is random stuff inside a .Bl block body before the first .It,
authorIngo Schwarze <schwarze@openbsd.org>
Sun, 6 Oct 2013 13:32:46 +0000 (13:32 +0000)
committerIngo Schwarze <schwarze@openbsd.org>
Sun, 6 Oct 2013 13:32:46 +0000 (13:32 +0000)
do not throw a FATAL error and do not die, but just throw a WARNING
and move the stuff out of the .Bl block.

This bug felt completely 2008-ish; meanwhile, such bugs from the
Kristaps-doesnt-like-syntax-errors-so-lets-just-give-up--Era
are becoming rare, but this was one of the last survivors.

Thanks to bentley@ for reminding me to finally fix this.

TODO
mdoc_validate.c

diff --git a/TODO b/TODO
index 0aebbd38b423534bafeddc3ae5d11c08b41fef54..961306c884ba26ced587ff38d135f9a75af12416 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,19 +1,13 @@
 ************************************************************************
 * Official mandoc TODO.
-* $Id: TODO,v 1.157 2013/09/27 21:12:34 schwarze Exp $
+* $Id: TODO,v 1.158 2013/10/06 13:32:46 schwarze Exp $
 ************************************************************************
 
 ************************************************************************
 * crashes
 ************************************************************************
 
-- .Bl -tag followed by a text node preceding the first .It should not
-  throw a FATAL error, but only a normal ERROR.  Putting this into the
-  HEAD of an implicit .It might be cleanest, inserting an implicit .Pp
-  or just dumping the orphan stuff directly into the BODY of the .Bl
-  might be easier to implement, and all options can no doubt be made
-  to yield correct (i.e. groff bug-compatible) rendering.
-  Anthony J. Bentley on discuss@  Sun, 22 Sep 2013 16:33:21 -0600
+None known.
 
 ************************************************************************
 * missing features
index b4d60315540866927a494001171ea58f4f8d8d5c..c13422f23b45bc3571faf73ca46ec367baed1d63 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_validate.c,v 1.194 2013/10/05 22:08:12 schwarze Exp $ */
+/*     $Id: mdoc_validate.c,v 1.195 2013/10/06 13:32:46 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
@@ -1590,32 +1590,71 @@ post_bl_head(POST_ARGS)
 static int
 post_bl(POST_ARGS)
 {
-       struct mdoc_node        *n;
+       struct mdoc_node        *nparent, *nprev; /* of the Bl block */
+       struct mdoc_node        *nblock, *nbody;  /* of the Bl */
+       struct mdoc_node        *nchild, *nnext;  /* of the Bl body */
 
-       if (MDOC_HEAD == mdoc->last->type) 
-               return(post_bl_head(mdoc));
-       if (MDOC_BLOCK == mdoc->last->type)
+       nbody = mdoc->last;
+       switch (nbody->type) {
+       case (MDOC_BLOCK):
                return(post_bl_block(mdoc));
-       if (MDOC_BODY != mdoc->last->type)
+       case (MDOC_HEAD):
+               return(post_bl_head(mdoc));
+       case (MDOC_BODY):
+               break;
+       default:
                return(1);
+       }
 
-       for (n = mdoc->last->child; n; n = n->next) {
-               switch (n->tok) {
-               case (MDOC_Lp):
-                       /* FALLTHROUGH */
-               case (MDOC_Pp):
-                       mdoc_nmsg(mdoc, n, MANDOCERR_CHILD);
-                       /* FALLTHROUGH */
-               case (MDOC_It):
-                       /* FALLTHROUGH */
-               case (MDOC_Sm):
+       nchild = nbody->child;
+       while (NULL != nchild) {
+               if (MDOC_It == nchild->tok || MDOC_Sm == nchild->tok) {
+                       nchild = nchild->next;
                        continue;
-               default:
-                       break;
                }
 
-               mdoc_nmsg(mdoc, n, MANDOCERR_SYNTCHILD);
-               return(0);
+               mdoc_nmsg(mdoc, nchild, MANDOCERR_CHILD);
+
+               /*
+                * Move the node out of the Bl block.
+                * First, collect all required node pointers.
+                */
+
+               nblock  = nbody->parent;
+               nprev   = nblock->prev;
+               nparent = nblock->parent;
+               nnext   = nchild->next;
+
+               /*
+                * Unlink this child.
+                */
+
+               assert(NULL == nchild->prev);
+               if (0 == --nbody->nchild) {
+                       nbody->child = NULL;
+                       nbody->last  = NULL;
+                       assert(NULL == nnext);
+               } else {
+                       nbody->child = nnext;
+                       nnext->prev = NULL;
+               }
+
+               /*
+                * Relink this child.
+                */
+
+               nchild->parent = nparent;
+               nchild->prev   = nprev;
+               nchild->next   = nblock;
+
+               nblock->prev = nchild;
+               nparent->nchild++;
+               if (NULL == nprev)
+                       nparent->child = nchild;
+               else
+                       nprev->next = nchild;
+
+               nchild = nnext;
        }
 
        return(1);