Print this page
9718 update mandoc to 1.14.4

@@ -1,9 +1,9 @@
-/*      $Id: mdoc_validate.c,v 1.352 2017/08/02 13:29:04 schwarze Exp $ */
+/*      $Id: mdoc_validate.c,v 1.360 2018/08/01 16:00:58 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010-2018 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * copyright notice and this permission notice appear in all copies.

@@ -51,14 +51,15 @@
 };
 
 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_argv(struct roff_man *,
                         struct roff_node *, struct mdoc_argv *);
 static  void     check_args(struct roff_man *, struct roff_node *);
+static  void     check_text(struct roff_man *, int, int, char *);
+static  void     check_text_em(struct roff_man *, int, int, char *);
 static  void     check_toptext(struct roff_man *, int, int, const char *);
 static  int      child_an(const struct roff_node *);
 static  size_t          macro2len(enum roff_tok);
 static  void     rewrite_macro2len(struct roff_man *, char **);
 static  int      similar(const char *, const char *);

@@ -167,16 +168,16 @@
         NULL,           /* %P */
         post_hyph,      /* %R */
         post_hyph,      /* %T */ /* FIXME: can be used outside Rs/Re. */
         NULL,           /* %V */
         NULL,           /* Ac */
-        post_delim_nb,  /* Ao */
+        NULL,           /* Ao */
         post_delim_nb,  /* Aq */
         post_at,        /* At */
         NULL,           /* Bc */
         post_bf,        /* Bf */
-        post_delim_nb,  /* Bo */
+        NULL,           /* Bo */
         NULL,           /* Bq */
         post_xx,        /* Bsx */
         post_bx,        /* Bx */
         post_obsolete,  /* Db */
         NULL,           /* Dc */

@@ -192,20 +193,20 @@
         post_ns,        /* Ns */
         post_xx,        /* Nx */
         post_xx,        /* Ox */
         NULL,           /* Pc */
         NULL,           /* Pf */
-        post_delim_nb,  /* Po */
+        NULL,           /* Po */
         post_delim_nb,  /* Pq */
         NULL,           /* Qc */
         post_delim_nb,  /* Ql */
-        post_delim_nb,  /* Qo */
+        NULL,           /* Qo */
         post_delim_nb,  /* Qq */
         NULL,           /* Re */
         post_rs,        /* Rs */
         NULL,           /* Sc */
-        post_delim_nb,  /* So */
+        NULL,           /* So */
         post_delim_nb,  /* Sq */
         post_sm,        /* Sm */
         post_sx,        /* Sx */
         post_delim_nb,  /* Sy */
         post_useless,   /* Tn */

@@ -212,11 +213,11 @@
         post_xx,        /* Ux */
         NULL,           /* Xc */
         NULL,           /* Xo */
         post_fo,        /* Fo */
         NULL,           /* Fc */
-        post_delim_nb,  /* Oo */
+        NULL,           /* Oo */
         NULL,           /* Oc */
         post_bk,        /* Bk */
         NULL,           /* Ek */
         post_eoln,      /* Bt */
         post_obsolete,  /* Hf */

@@ -225,11 +226,11 @@
         post_lb,        /* Lb */
         post_par,       /* Lp */
         post_delim_nb,  /* Lk */
         post_defaults,  /* Mt */
         post_delim_nb,  /* Brq */
-        post_delim_nb,  /* Bro */
+        NULL,           /* Bro */
         NULL,           /* Brc */
         NULL,           /* %C */
         post_es,        /* Es */
         post_en,        /* En */
         post_xx,        /* Dx */

@@ -286,11 +287,11 @@
 
 
 void
 mdoc_node_validate(struct roff_man *mdoc)
 {
-        struct roff_node *n;
+        struct roff_node *n, *np;
         const v_post *p;
 
         n = mdoc->last;
         mdoc->last = mdoc->last->child;
         while (mdoc->last != NULL) {

@@ -303,19 +304,25 @@
 
         mdoc->last = n;
         mdoc->next = ROFF_NEXT_SIBLING;
         switch (n->type) {
         case ROFFT_TEXT:
+                np = n->parent;
                 if (n->sec != SEC_SYNOPSIS ||
-                    (n->parent->tok != MDOC_Cd && n->parent->tok != MDOC_Fd))
+                    (np->tok != MDOC_Cd && np->tok != MDOC_Fd))
                         check_text(mdoc, n->line, n->pos, n->string);
-                if (n->parent->tok == MDOC_It ||
-                    (n->parent->type == ROFFT_BODY &&
-                     (n->parent->tok == MDOC_Sh ||
-                      n->parent->tok == MDOC_Ss)))
+                if (np->tok != MDOC_Ql && np->tok != MDOC_Dl &&
+                    (np->tok != MDOC_Bd ||
+                     (mdoc->flags & MDOC_LITERAL) == 0) &&
+                    (np->tok != MDOC_It || np->type != ROFFT_HEAD ||
+                     np->parent->parent->norm->Bl.type != LIST_diag))
+                        check_text_em(mdoc, n->line, n->pos, n->string);
+                if (np->tok == MDOC_It || (np->type == ROFFT_BODY &&
+                    (np->tok == MDOC_Sh || np->tok == MDOC_Ss)))
                         check_toptext(mdoc, n->line, n->pos, n->string);
                 break;
+        case ROFFT_COMMENT:
         case ROFFT_EQN:
         case ROFFT_TBL:
                 break;
         case ROFFT_ROOT:
                 post_root(mdoc);

@@ -393,10 +400,61 @@
                 mandoc_msg(MANDOCERR_FI_TAB, mdoc->parse,
                     ln, pos + (int)(p - cp), NULL);
 }
 
 static void
+check_text_em(struct roff_man *mdoc, int ln, int pos, char *p)
+{
+        const struct roff_node  *np, *nn;
+        char                    *cp;
+
+        np = mdoc->last->prev;
+        nn = mdoc->last->next;
+
+        /* Look for em-dashes wrongly encoded as "--". */
+
+        for (cp = p; *cp != '\0'; cp++) {
+                if (cp[0] != '-' || cp[1] != '-')
+                        continue;
+                cp++;
+
+                /* Skip input sequences of more than two '-'. */
+
+                if (cp[1] == '-') {
+                        while (cp[1] == '-')
+                                cp++;
+                        continue;
+                }
+
+                /* Skip "--" directly attached to something else. */
+
+                if ((cp - p > 1 && cp[-2] != ' ') ||
+                    (cp[1] != '\0' && cp[1] != ' '))
+                        continue;
+
+                /* Require a letter right before or right afterwards. */
+
+                if ((cp - p > 2 ?
+                     isalpha((unsigned char)cp[-3]) :
+                     np != NULL &&
+                     np->type == ROFFT_TEXT &&
+                     *np->string != '\0' &&
+                     isalpha((unsigned char)np->string[
+                       strlen(np->string) - 1])) ||
+                    (cp[1] != '\0' && cp[2] != '\0' ?
+                     isalpha((unsigned char)cp[2]) :
+                     nn != NULL &&
+                     nn->type == ROFFT_TEXT &&
+                     isalpha((unsigned char)*nn->string))) {
+                        mandoc_msg(MANDOCERR_DASHDASH, mdoc->parse,
+                            ln, pos + (int)(cp - p) - 1, NULL);
+                        break;
+                }
+        }
+}
+
+static void
 check_toptext(struct roff_man *mdoc, int ln, int pos, const char *p)
 {
         const char      *cp, *cpr;
 
         if (*p == '\0')

@@ -528,12 +586,11 @@
         if (lc == nch->string + 1 && !isalnum((unsigned char)lc[-1]))
                 return;
 
         /* At least three alphabetic words with a sentence ending. */
         if (strchr("!.:?", *lc) != NULL && (tok == MDOC_Em ||
-            tok == MDOC_Li || tok == MDOC_Po || tok == MDOC_Pq ||
-            tok == MDOC_Sy)) {
+            tok == MDOC_Li || tok == MDOC_Pq || tok == MDOC_Sy)) {
                 nw = 0;
                 for (cp = lc - 1; cp >= nch->string; cp--) {
                         if (*cp == ' ') {
                                 nw++;
                                 if (cp > nch->string && cp[-1] == ',')

@@ -945,14 +1002,14 @@
         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");
+        roff_word_alloc(mdoc, n->line, n->pos, "\\(lq");
         mdoc->last->flags = NODE_DELIMO | NODE_NOSRC;
         mdoc->last = mdoc->last->next;
-        roff_word_alloc(mdoc, n->line, n->pos, "\\(Rq");
+        roff_word_alloc(mdoc, n->line, n->pos, "\\(rq");
         mdoc->last->flags = NODE_DELIMC | NODE_NOSRC;
         mdoc->last = n;
 }
 
 static void

@@ -1912,11 +1969,14 @@
             (arch = arches[mdoc->meta.os_e]) != NULL) {
                 while (*arch != NULL && strcmp(*arch, mdoc->meta.arch))
                         arch++;
                 if (*arch == NULL) {
                         n = mdoc->first->child;
-                        while (n->tok != MDOC_Dt)
+                        while (n->tok != MDOC_Dt ||
+                            n->child == NULL ||
+                            n->child->next == NULL ||
+                            n->child->next->next == NULL)
                                 n = n->next;
                         n = n->child->next->next;
                         mandoc_vmsg(MANDOCERR_ARCH_BAD,
                             mdoc->parse, n->line, n->pos,
                             "Dt ... %s %s", mdoc->meta.arch,

@@ -1926,12 +1986,14 @@
         }
 
         /* Check that we begin with a proper `Sh'. */
 
         n = mdoc->first->child;
-        while (n != NULL && n->tok >= MDOC_Dd &&
-            mdoc_macros[n->tok].flags & MDOC_PROLOGUE)
+        while (n != NULL &&
+            (n->type == ROFFT_COMMENT ||
+             (n->tok >= MDOC_Dd &&
+              mdoc_macros[n->tok].flags & MDOC_PROLOGUE)))
                 n = n->next;
 
         if (n == NULL)
                 mandoc_msg(MANDOCERR_DOC_EMPTY, mdoc->parse, 0, 0, NULL);
         else if (n->tok != MDOC_Sh)