]> git.cameronkatri.com Git - mandoc.git/blobdiff - mdoc_validate.c
do not break the line between Bsx/Bx/Fx/Nx/Ox/Dx and its arguments
[mandoc.git] / mdoc_validate.c
index 38283674da3e7c79210206516c91c5ec93ee3729..9bf1efb3d784ac19467e9790bd6d0fd399ecd591 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_validate.c,v 1.322 2017/04/29 12:45:42 schwarze Exp $ */
+/*     $Id: mdoc_validate.c,v 1.332 2017/06/08 00:23:30 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -53,6 +53,7 @@ typedef       void    (*v_post)(POST_ARGS);
 
 static int      build_list(struct roff_man *, int);
 static void     check_text(struct roff_man *, int, int, char *);
+static void     check_bsd(struct roff_man *, int, int, char *);
 static void     check_argv(struct roff_man *,
                        struct roff_node *, struct mdoc_argv *);
 static void     check_args(struct roff_man *, struct roff_node *);
@@ -105,6 +106,7 @@ static      void     post_sh_authors(POST_ARGS);
 static void     post_sm(POST_ARGS);
 static void     post_st(POST_ARGS);
 static void     post_std(POST_ARGS);
+static void     post_useless(POST_ARGS);
 static void     post_xr(POST_ARGS);
 static void     post_xx(POST_ARGS);
 
@@ -201,7 +203,7 @@ static      const v_post __mdoc_valids[MDOC_MAX - MDOC_Dd] = {
        post_sm,        /* Sm */
        post_hyph,      /* Sx */
        NULL,           /* Sy */
-       NULL,           /* Tn */
+       post_useless,   /* Tn */
        post_xx,        /* Ux */
        NULL,           /* Xc */
        NULL,           /* Xo */
@@ -227,11 +229,8 @@ static     const v_post __mdoc_valids[MDOC_MAX - MDOC_Dd] = {
        post_en,        /* En */
        post_xx,        /* Dx */
        NULL,           /* %Q */
-       post_par,       /* br */
-       post_par,       /* sp */
        NULL,           /* %U */
        NULL,           /* Ta */
-       NULL,           /* ll */
 };
 static const v_post *const mdoc_valids = __mdoc_valids - MDOC_Dd;
 
@@ -304,6 +303,10 @@ mdoc_node_validate(struct roff_man *mdoc)
                if (n->sec != SEC_SYNOPSIS ||
                    (n->parent->tok != MDOC_Cd && n->parent->tok != MDOC_Fd))
                        check_text(mdoc, n->line, n->pos, n->string);
+               if (n->parent->tok == MDOC_Sh ||
+                   n->parent->tok == MDOC_Ss ||
+                   n->parent->tok == MDOC_It)
+                       check_bsd(mdoc, n->line, n->pos, n->string);
                break;
        case ROFFT_EQN:
        case ROFFT_TBL:
@@ -327,6 +330,20 @@ mdoc_node_validate(struct roff_man *mdoc)
 
                /* Call the macro's postprocessor. */
 
+               if (n->tok < ROFF_MAX) {
+                       switch(n->tok) {
+                       case ROFF_br:
+                       case ROFF_sp:
+                               post_par(mdoc);
+                               break;
+                       default:
+                               roff_validate(mdoc);
+                               break;
+                       }
+                       break;
+               }
+
+               assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
                p = mdoc_valids + n->tok;
                if (*p)
                        (*p)(mdoc);
@@ -371,6 +388,25 @@ check_text(struct roff_man *mdoc, int ln, int pos, char *p)
                    ln, pos + (int)(p - cp), NULL);
 }
 
+static void
+check_bsd(struct roff_man *mdoc, int ln, int pos, char *p)
+{
+       const char      *cp;
+
+       if ((cp = strstr(p, "OpenBSD")) != NULL)
+               mandoc_msg(MANDOCERR_BX, mdoc->parse,
+                   ln, pos + (cp - p), "Ox");
+       if ((cp = strstr(p, "NetBSD")) != NULL)
+               mandoc_msg(MANDOCERR_BX, mdoc->parse,
+                   ln, pos + (cp - p), "Nx");
+       if ((cp = strstr(p, "FreeBSD")) != NULL)
+               mandoc_msg(MANDOCERR_BX, mdoc->parse,
+                   ln, pos + (cp - p), "Fx");
+       if ((cp = strstr(p, "DragonFly")) != NULL)
+               mandoc_msg(MANDOCERR_BX, mdoc->parse,
+                   ln, pos + (cp - p), "Dx");
+}
+
 static void
 post_bl_norm(POST_ARGS)
 {
@@ -660,6 +696,7 @@ post_eoln(POST_ARGS)
 {
        struct roff_node        *n;
 
+       post_useless(mdoc);
        n = mdoc->last;
        if (n->child != NULL)
                mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse, n->line,
@@ -757,6 +794,9 @@ post_lb(POST_ARGS)
                return;
        }
 
+       mandoc_vmsg(MANDOCERR_LB_BAD, mdoc->parse, n->child->line,
+           n->child->pos, "Lb %s", n->child->string);
+
        roff_word_alloc(mdoc, n->line, n->pos, "library");
        mdoc->last->flags = NODE_NOSRC;
        roff_word_alloc(mdoc, n->line, n->pos, "\\(Lq");
@@ -855,6 +895,16 @@ post_obsolete(POST_ARGS)
                    n->line, n->pos, roff_name[n->tok]);
 }
 
+static void
+post_useless(POST_ARGS)
+{
+       struct roff_node *n;
+
+       n = mdoc->last;
+       mandoc_msg(MANDOCERR_MACRO_USELESS, mdoc->parse,
+           n->line, n->pos, roff_name[n->tok]);
+}
+
 /*
  * Block macros.
  */
@@ -1029,6 +1079,7 @@ static void
 post_nd(POST_ARGS)
 {
        struct roff_node        *n;
+       size_t                   sz;
 
        n = mdoc->last;
 
@@ -1042,6 +1093,11 @@ post_nd(POST_ARGS)
        if (n->child == NULL)
                mandoc_msg(MANDOCERR_ND_EMPTY, mdoc->parse,
                    n->line, n->pos, "Nd");
+       else if (n->last->type == ROFFT_TEXT &&
+           (sz = strlen(n->last->string)) != 0 &&
+           n->last->string[sz - 1] == '.')
+               mandoc_msg(MANDOCERR_ND_DOT, mdoc->parse,
+                   n->last->line, n->last->pos + sz - 1, NULL);
 
        post_hyph(mdoc);
 }
@@ -1310,7 +1366,7 @@ post_bl_block(POST_ARGS)
                        switch (nc->tok) {
                        case MDOC_Pp:
                        case MDOC_Lp:
-                       case MDOC_br:
+                       case ROFF_br:
                                break;
                        default:
                                nc = NULL;
@@ -1426,6 +1482,8 @@ post_bl(POST_ARGS)
        struct roff_node        *nparent, *nprev; /* of the Bl block */
        struct roff_node        *nblock, *nbody;  /* of the Bl */
        struct roff_node        *nchild, *nnext;  /* of the Bl body */
+       const char              *prev_Er;
+       int                      order;
 
        nbody = mdoc->last;
        switch (nbody->type) {
@@ -1526,6 +1584,34 @@ post_bl(POST_ARGS)
 
                nchild = nnext;
        }
+
+       if (mdoc->meta.os_e != MDOC_OS_NETBSD)
+               return;
+
+       prev_Er = NULL;
+       for (nchild = nbody->child; nchild != NULL; nchild = nchild->next) {
+               if (nchild->tok != MDOC_It)
+                       continue;
+               if ((nnext = nchild->head->child) == NULL)
+                       continue;
+               if (nnext->type == ROFFT_BLOCK)
+                       nnext = nnext->body->child;
+               if (nnext == NULL || nnext->tok != MDOC_Er)
+                       continue;
+               nnext = nnext->child;
+               if (prev_Er != NULL) {
+                       order = strcmp(prev_Er, nnext->string);
+                       if (order > 0)
+                               mandoc_vmsg(MANDOCERR_ER_ORDER,
+                                   mdoc->parse, nnext->line, nnext->pos,
+                                   "Er %s %s", prev_Er, nnext->string);
+                       else if (order == 0)
+                               mandoc_vmsg(MANDOCERR_ER_REP,
+                                   mdoc->parse, nnext->line, nnext->pos,
+                                   "Er %s", prev_Er);
+               }
+               prev_Er = nnext->string;
+       }
 }
 
 static void
@@ -1868,7 +1954,7 @@ post_sh_see_also(POST_ARGS)
                        if (isalpha((const unsigned char)*name))
                                return;
                lastpunct = n->string;
-               if (n->next == NULL)
+               if (n->next == NULL || n->next->tok == MDOC_Rs)
                        mandoc_vmsg(MANDOCERR_XR_PUNCT, mdoc->parse,
                            n->line, n->pos, "%s after %s(%s)",
                            lastpunct, lastname, lastsec);
@@ -2064,7 +2150,7 @@ post_prevpar(POST_ARGS)
 
        if (n->prev->tok != MDOC_Pp &&
            n->prev->tok != MDOC_Lp &&
-           n->prev->tok != MDOC_br)
+           n->prev->tok != ROFF_br)
                return;
        if (n->tok == MDOC_Bl && n->norm->Bl.comp)
                return;
@@ -2085,10 +2171,10 @@ post_par(POST_ARGS)
        struct roff_node *np;
 
        np = mdoc->last;
-       if (np->tok != MDOC_br && np->tok != MDOC_sp)
+       if (np->tok != ROFF_br && np->tok != ROFF_sp)
                post_prevpar(mdoc);
 
-       if (np->tok == MDOC_sp) {
+       if (np->tok == ROFF_sp) {
                if (np->child != NULL && np->child->next != NULL)
                        mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse,
                            np->child->next->line, np->child->next->pos,
@@ -2103,8 +2189,8 @@ post_par(POST_ARGS)
                if (np->tok != MDOC_Sh && np->tok != MDOC_Ss)
                        return;
        } else if (np->tok != MDOC_Pp && np->tok != MDOC_Lp &&
-           (mdoc->last->tok != MDOC_br ||
-            (np->tok != MDOC_sp && np->tok != MDOC_br)))
+           (mdoc->last->tok != ROFF_br ||
+            (np->tok != ROFF_sp && np->tok != ROFF_br)))
                return;
 
        mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
@@ -2253,11 +2339,19 @@ static void
 post_bx(POST_ARGS)
 {
        struct roff_node        *n, *nch;
+       const char              *macro;
 
        n = mdoc->last;
        nch = n->child;
 
        if (nch != NULL) {
+               macro = !strcmp(nch->string, "Open") ? "Ox" :
+                   !strcmp(nch->string, "Net") ? "Nx" :
+                   !strcmp(nch->string, "Free") ? "Fx" :
+                   !strcmp(nch->string, "DragonFly") ? "Dx" : NULL;
+               if (macro != NULL)
+                       mandoc_msg(MANDOCERR_BX, mdoc->parse,
+                           n->line, n->pos, macro);
                mdoc->last = nch;
                nch = nch->next;
                mdoc->next = ROFF_NEXT_SIBLING;
@@ -2324,11 +2418,11 @@ post_os(POST_ARGS)
        mdoc->meta.os = NULL;
        deroff(&mdoc->meta.os, n);
        if (mdoc->meta.os)
-               return;
+               goto out;
 
        if (mdoc->defos) {
                mdoc->meta.os = mandoc_strdup(mdoc->defos);
-               return;
+               goto out;
        }
 
 #ifdef OSNAME
@@ -2345,6 +2439,10 @@ post_os(POST_ARGS)
        }
        mdoc->meta.os = mandoc_strdup(defbuf);
 #endif /*!OSNAME*/
+
+out:   mdoc->meta.os_e = strstr(mdoc->meta.os, "OpenBSD") != NULL ?
+           MDOC_OS_OPENBSD : strstr(mdoc->meta.os, "NetBSD") != NULL ?
+           MDOC_OS_NETBSD : MDOC_OS_OTHER;
 }
 
 enum roff_sec