]> git.cameronkatri.com Git - mandoc.git/blobdiff - mdoc_validate.c
Fixed re-adjustment of scope in exiting roff instructions (libman).
[mandoc.git] / mdoc_validate.c
index 779b71cb4af80af10c939ff09452e7e83d0df049..b92e89c583f2eb4440dd6717b05f7b2cbdb1cb24 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_validate.c,v 1.48 2009/10/19 09:40:23 kristaps Exp $ */
+/*     $Id: mdoc_validate.c,v 1.58 2010/02/17 19:28:11 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <sys/types.h>
 
 #include <assert.h>
 #include <ctype.h>
-#include <errno.h>
 #include <limits.h>
 #include <stdarg.h>
 #include <stdlib.h>
@@ -63,17 +66,12 @@ static      int      warn_count(struct mdoc *, const char *,
 static int      err_count(struct mdoc *, const char *, 
                        int, const char *, int);
 
-#ifdef __linux__
-extern size_t   strlcat(char *, const char *, size_t);
-#endif
-
 static int      berr_ge1(POST_ARGS);
 static int      bwarn_ge1(POST_ARGS);
 static int      ebool(POST_ARGS);
 static int      eerr_eq0(POST_ARGS);
 static int      eerr_eq1(POST_ARGS);
 static int      eerr_ge1(POST_ARGS);
-static int      eerr_le2(POST_ARGS);
 static int      eerr_le1(POST_ARGS);
 static int      ewarn_ge1(POST_ARGS);
 static int      herr_eq0(POST_ARGS);
@@ -95,6 +93,7 @@ static        int      post_sh(POST_ARGS);
 static int      post_sh_body(POST_ARGS);
 static int      post_sh_head(POST_ARGS);
 static int      post_st(POST_ARGS);
+static int      post_vt(POST_ARGS);
 static int      pre_an(PRE_ARGS);
 static int      pre_bd(PRE_ARGS);
 static int      pre_bl(PRE_ARGS);
@@ -119,22 +118,22 @@ static    v_post   posts_bf[] = { hwarn_le1, post_bf, NULL };
 static v_post   posts_bl[] = { bwarn_ge1, post_bl, NULL };
 static v_post   posts_bool[] = { eerr_eq1, ebool, NULL };
 static v_post   posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL };
-static v_post   posts_in[] = { eerr_eq1, NULL };
 static v_post   posts_it[] = { post_it, NULL };
 static v_post   posts_lb[] = { eerr_eq1, post_lb, NULL };
 static v_post   posts_nd[] = { berr_ge1, NULL };
 static v_post   posts_nm[] = { post_nm, NULL };
 static v_post   posts_notext[] = { eerr_eq0, NULL };
-static v_post   posts_pf[] = { eerr_eq1, NULL };
 static v_post   posts_rs[] = { berr_ge1, herr_eq0, post_rs, NULL };
 static v_post   posts_sh[] = { herr_ge1, bwarn_ge1, post_sh, NULL };
 static v_post   posts_sp[] = { eerr_le1, NULL };
 static v_post   posts_ss[] = { herr_ge1, NULL };
 static v_post   posts_st[] = { eerr_eq1, post_st, NULL };
 static v_post   posts_text[] = { eerr_ge1, NULL };
+static v_post   posts_text1[] = { eerr_eq1, NULL };
+static v_post   posts_vt[] = { post_vt, NULL };
 static v_post   posts_wline[] = { bwarn_ge1, herr_eq0, NULL };
 static v_post   posts_wtext[] = { ewarn_ge1, NULL };
-static v_post   posts_xr[] = { eerr_ge1, eerr_le2, NULL };
+static v_post   posts_xr[] = { eerr_ge1, NULL };
 static v_pre    pres_an[] = { pre_an, NULL };
 static v_pre    pres_bd[] = { pre_display, pre_bd, NULL };
 static v_pre    pres_bl[] = { pre_bl, NULL };
@@ -182,7 +181,7 @@ const       struct valids mdoc_valids[MDOC_MAX] = {
        { NULL, posts_text },                   /* Fn */ 
        { NULL, posts_wtext },                  /* Ft */ 
        { NULL, posts_text },                   /* Ic */ 
-       { NULL, posts_in },                     /* In */ 
+       { NULL, posts_text1 },                  /* In */ 
        { NULL, NULL },                         /* Li */
        { NULL, posts_nd },                     /* Nd */
        { NULL, posts_nm },                     /* Nm */
@@ -192,11 +191,11 @@ const     struct valids mdoc_valids[MDOC_MAX] = {
        { pres_rv, NULL },                      /* Rv */
        { NULL, posts_st },                     /* St */ 
        { NULL, NULL },                         /* Va */
-       { NULL, posts_text },                   /* Vt */ 
+       { NULL, posts_vt },                     /* Vt */ 
        { NULL, posts_xr },                     /* Xr */ 
        { NULL, posts_text },                   /* %A */
        { NULL, posts_text },                   /* %B */ /* FIXME: can be used outside Rs/Re. */
-       { NULL, posts_text },                   /* %D */
+       { NULL, posts_text },                   /* %D */ /* FIXME: check date with mandoc_a2time(). */
        { NULL, posts_text },                   /* %I */
        { NULL, posts_text },                   /* %J */
        { NULL, posts_text },                   /* %N */
@@ -230,7 +229,7 @@ const       struct valids mdoc_valids[MDOC_MAX] = {
        { NULL, NULL },                         /* Nx */
        { NULL, NULL },                         /* Ox */
        { NULL, NULL },                         /* Pc */
-       { NULL, posts_pf },                     /* Pf */
+       { NULL, posts_text1 },                  /* Pf */
        { NULL, NULL },                         /* Po */
        { NULL, posts_wline },                  /* Pq */
        { NULL, NULL },                         /* Qc */
@@ -261,7 +260,7 @@ const       struct valids mdoc_valids[MDOC_MAX] = {
        { NULL, posts_notext },                 /* Ud */
        { pres_lb, posts_lb },                  /* Lb */
        { NULL, posts_notext },                 /* Lp */ 
-       { NULL, NULL },                         /* Lk */ 
+       { NULL, posts_text },                   /* Lk */ 
        { NULL, posts_text },                   /* Mt */ 
        { NULL, posts_wline },                  /* Brq */ 
        { NULL, NULL },                         /* Bro */ 
@@ -273,6 +272,7 @@ const       struct valids mdoc_valids[MDOC_MAX] = {
        { NULL, posts_text },                   /* %Q */
        { NULL, posts_notext },                 /* br */
        { NULL, posts_sp },                     /* sp */
+       { NULL, posts_text1 },                  /* %U */
 };
 
 
@@ -407,7 +407,6 @@ CHECK_BODY_DEFN(ge1, warn, warn_child_gt, 0)        /* bwarn_ge1() */
 CHECK_BODY_DEFN(ge1, err, err_child_gt, 0)     /* berr_ge1() */
 CHECK_ELEM_DEFN(ge1, warn, warn_child_gt, 0)   /* ewarn_gt1() */
 CHECK_ELEM_DEFN(eq1, err, err_child_eq, 1)     /* eerr_eq1() */
-CHECK_ELEM_DEFN(le2, err, err_child_lt, 3)     /* eerr_le2() */
 CHECK_ELEM_DEFN(le1, err, err_child_lt, 2)     /* eerr_le1() */
 CHECK_ELEM_DEFN(eq0, err, err_child_eq, 0)     /* eerr_eq0() */
 CHECK_ELEM_DEFN(ge1, err, err_child_gt, 0)     /* eerr_ge1() */
@@ -666,6 +665,8 @@ pre_bl(PRE_ARGS)
                /* FALLTHROUGH */
        case (MDOC_Diag):
                /* FALLTHROUGH */
+       case (MDOC_Ohang):
+               /* FALLTHROUGH */
        case (MDOC_Inset):
                /* FALLTHROUGH */
        case (MDOC_Item):
@@ -696,6 +697,8 @@ pre_bd(PRE_ARGS)
        for (i = 0, err = type = 0; ! err && 
                        i < (int)n->args->argc; i++)
                switch (n->args->argv[i].arg) {
+               case (MDOC_Centred):
+                       /* FALLTHROUGH */
                case (MDOC_Ragged):
                        /* FALLTHROUGH */
                case (MDOC_Unfilled):
@@ -805,6 +808,8 @@ static int
 pre_dt(PRE_ARGS)
 {
 
+       /* FIXME: make sure is capitalised. */
+
        if (0 == mdoc->meta.date || mdoc->meta.os)
                if ( ! mdoc_nwarn(mdoc, n, EPROLOOO))
                        return(0);
@@ -885,6 +890,32 @@ post_lb(POST_ARGS)
 }
 
 
+static int
+post_vt(POST_ARGS)
+{
+       const struct mdoc_node *n;
+
+       /*
+        * The Vt macro comes in both ELEM and BLOCK form, both of which
+        * have different syntaxes (yet more context-sensitive
+        * behaviour).  ELEM types must have a child; BLOCK types,
+        * specifically the BODY, should only have TEXT children.
+        */
+
+       if (MDOC_ELEM == mdoc->last->type)
+               return(eerr_ge1(mdoc));
+       if (MDOC_BODY != mdoc->last->type)
+               return(1);
+       
+       for (n = mdoc->last->child; n; n = n->next)
+               if (MDOC_TEXT != n->type) 
+                       if ( ! mdoc_nwarn(mdoc, n, EBADCHILD))
+                               return(0);
+
+       return(1);
+}
+
+
 static int
 post_nm(POST_ARGS)
 {
@@ -1081,11 +1112,18 @@ post_bl(POST_ARGS)
        if (NULL == mdoc->last->child)
                return(1);
 
+       /*
+        * We only allow certain children of `Bl'.  This is usually on
+        * `It', but apparently `Sm' occurs here and there, so we let
+        * that one through, too.
+        */
+
        /* LINTED */
        for (n = mdoc->last->child; n; n = n->next) {
-               if (MDOC_BLOCK == n->type) 
-                       if (MDOC_It == n->tok)
-                               continue;
+               if (MDOC_BLOCK == n->type && MDOC_It == n->tok)
+                       continue;
+               if (MDOC_Sm == n->tok)
+                       continue;
                return(mdoc_nerr(mdoc, n, EBADCHILD));
        }
 
@@ -1153,6 +1191,8 @@ post_rs(POST_ARGS)
 
        for (nn = mdoc->last->child; nn; nn = nn->next)
                switch (nn->tok) {
+               case(MDOC__U):
+                       /* FALLTHROUGH */
                case(MDOC__Q):
                        /* FALLTHROUGH */
                case(MDOC__C):