Print this page
9718 update mandoc to 1.14.4

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/mandoc/mdoc_validate.c
          +++ new/usr/src/cmd/mandoc/mdoc_validate.c
   1      -/*      $Id: mdoc_validate.c,v 1.352 2017/08/02 13:29:04 schwarze Exp $ */
        1 +/*      $Id: mdoc_validate.c,v 1.360 2018/08/01 16:00:58 schwarze Exp $ */
   2    2  /*
   3    3   * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
   4      - * Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
        4 + * Copyright (c) 2010-2018 Ingo Schwarze <schwarze@openbsd.org>
   5    5   * Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
   6    6   *
   7    7   * Permission to use, copy, modify, and distribute this software for any
   8    8   * purpose with or without fee is hereby granted, provided that the above
   9    9   * copyright notice and this permission notice appear in all copies.
  10   10   *
  11   11   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
  12   12   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  13   13   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
  14   14   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
↓ open down ↓ 31 lines elided ↑ open up ↑
  46   46  
  47   47  enum    check_ineq {
  48   48          CHECK_LT,
  49   49          CHECK_GT,
  50   50          CHECK_EQ
  51   51  };
  52   52  
  53   53  typedef void    (*v_post)(POST_ARGS);
  54   54  
  55   55  static  int      build_list(struct roff_man *, int);
  56      -static  void     check_text(struct roff_man *, int, int, char *);
  57   56  static  void     check_argv(struct roff_man *,
  58   57                          struct roff_node *, struct mdoc_argv *);
  59   58  static  void     check_args(struct roff_man *, struct roff_node *);
       59 +static  void     check_text(struct roff_man *, int, int, char *);
       60 +static  void     check_text_em(struct roff_man *, int, int, char *);
  60   61  static  void     check_toptext(struct roff_man *, int, int, const char *);
  61   62  static  int      child_an(const struct roff_node *);
  62   63  static  size_t          macro2len(enum roff_tok);
  63   64  static  void     rewrite_macro2len(struct roff_man *, char **);
  64   65  static  int      similar(const char *, const char *);
  65   66  
  66   67  static  void     post_an(POST_ARGS);
  67   68  static  void     post_an_norm(POST_ARGS);
  68   69  static  void     post_at(POST_ARGS);
  69   70  static  void     post_bd(POST_ARGS);
↓ open down ↓ 92 lines elided ↑ open up ↑
 162  163          NULL,           /* %D */
 163  164          NULL,           /* %I */
 164  165          NULL,           /* %J */
 165  166          post_hyph,      /* %N */
 166  167          post_hyph,      /* %O */
 167  168          NULL,           /* %P */
 168  169          post_hyph,      /* %R */
 169  170          post_hyph,      /* %T */ /* FIXME: can be used outside Rs/Re. */
 170  171          NULL,           /* %V */
 171  172          NULL,           /* Ac */
 172      -        post_delim_nb,  /* Ao */
      173 +        NULL,           /* Ao */
 173  174          post_delim_nb,  /* Aq */
 174  175          post_at,        /* At */
 175  176          NULL,           /* Bc */
 176  177          post_bf,        /* Bf */
 177      -        post_delim_nb,  /* Bo */
      178 +        NULL,           /* Bo */
 178  179          NULL,           /* Bq */
 179  180          post_xx,        /* Bsx */
 180  181          post_bx,        /* Bx */
 181  182          post_obsolete,  /* Db */
 182  183          NULL,           /* Dc */
 183  184          NULL,           /* Do */
 184  185          NULL,           /* Dq */
 185  186          NULL,           /* Ec */
 186  187          NULL,           /* Ef */
 187  188          post_delim_nb,  /* Em */
 188  189          NULL,           /* Eo */
 189  190          post_xx,        /* Fx */
 190  191          post_delim_nb,  /* Ms */
 191  192          NULL,           /* No */
 192  193          post_ns,        /* Ns */
 193  194          post_xx,        /* Nx */
 194  195          post_xx,        /* Ox */
 195  196          NULL,           /* Pc */
 196  197          NULL,           /* Pf */
 197      -        post_delim_nb,  /* Po */
      198 +        NULL,           /* Po */
 198  199          post_delim_nb,  /* Pq */
 199  200          NULL,           /* Qc */
 200  201          post_delim_nb,  /* Ql */
 201      -        post_delim_nb,  /* Qo */
      202 +        NULL,           /* Qo */
 202  203          post_delim_nb,  /* Qq */
 203  204          NULL,           /* Re */
 204  205          post_rs,        /* Rs */
 205  206          NULL,           /* Sc */
 206      -        post_delim_nb,  /* So */
      207 +        NULL,           /* So */
 207  208          post_delim_nb,  /* Sq */
 208  209          post_sm,        /* Sm */
 209  210          post_sx,        /* Sx */
 210  211          post_delim_nb,  /* Sy */
 211  212          post_useless,   /* Tn */
 212  213          post_xx,        /* Ux */
 213  214          NULL,           /* Xc */
 214  215          NULL,           /* Xo */
 215  216          post_fo,        /* Fo */
 216  217          NULL,           /* Fc */
 217      -        post_delim_nb,  /* Oo */
      218 +        NULL,           /* Oo */
 218  219          NULL,           /* Oc */
 219  220          post_bk,        /* Bk */
 220  221          NULL,           /* Ek */
 221  222          post_eoln,      /* Bt */
 222  223          post_obsolete,  /* Hf */
 223  224          post_obsolete,  /* Fr */
 224  225          post_eoln,      /* Ud */
 225  226          post_lb,        /* Lb */
 226  227          post_par,       /* Lp */
 227  228          post_delim_nb,  /* Lk */
 228  229          post_defaults,  /* Mt */
 229  230          post_delim_nb,  /* Brq */
 230      -        post_delim_nb,  /* Bro */
      231 +        NULL,           /* Bro */
 231  232          NULL,           /* Brc */
 232  233          NULL,           /* %C */
 233  234          post_es,        /* Es */
 234  235          post_en,        /* En */
 235  236          post_xx,        /* Dx */
 236  237          NULL,           /* %Q */
 237  238          NULL,           /* %U */
 238  239          NULL,           /* Ta */
 239  240  };
 240  241  static  const v_post *const mdoc_valids = __mdoc_valids - MDOC_Dd;
↓ open down ↓ 40 lines elided ↑ open up ↑
 281  282          "CAVEATS",
 282  283          "BUGS",
 283  284          "SECURITY CONSIDERATIONS",
 284  285          NULL
 285  286  };
 286  287  
 287  288  
 288  289  void
 289  290  mdoc_node_validate(struct roff_man *mdoc)
 290  291  {
 291      -        struct roff_node *n;
      292 +        struct roff_node *n, *np;
 292  293          const v_post *p;
 293  294  
 294  295          n = mdoc->last;
 295  296          mdoc->last = mdoc->last->child;
 296  297          while (mdoc->last != NULL) {
 297  298                  mdoc_node_validate(mdoc);
 298  299                  if (mdoc->last == n)
 299  300                          mdoc->last = mdoc->last->child;
 300  301                  else
 301  302                          mdoc->last = mdoc->last->next;
 302  303          }
 303  304  
 304  305          mdoc->last = n;
 305  306          mdoc->next = ROFF_NEXT_SIBLING;
 306  307          switch (n->type) {
 307  308          case ROFFT_TEXT:
      309 +                np = n->parent;
 308  310                  if (n->sec != SEC_SYNOPSIS ||
 309      -                    (n->parent->tok != MDOC_Cd && n->parent->tok != MDOC_Fd))
      311 +                    (np->tok != MDOC_Cd && np->tok != MDOC_Fd))
 310  312                          check_text(mdoc, n->line, n->pos, n->string);
 311      -                if (n->parent->tok == MDOC_It ||
 312      -                    (n->parent->type == ROFFT_BODY &&
 313      -                     (n->parent->tok == MDOC_Sh ||
 314      -                      n->parent->tok == MDOC_Ss)))
      313 +                if (np->tok != MDOC_Ql && np->tok != MDOC_Dl &&
      314 +                    (np->tok != MDOC_Bd ||
      315 +                     (mdoc->flags & MDOC_LITERAL) == 0) &&
      316 +                    (np->tok != MDOC_It || np->type != ROFFT_HEAD ||
      317 +                     np->parent->parent->norm->Bl.type != LIST_diag))
      318 +                        check_text_em(mdoc, n->line, n->pos, n->string);
      319 +                if (np->tok == MDOC_It || (np->type == ROFFT_BODY &&
      320 +                    (np->tok == MDOC_Sh || np->tok == MDOC_Ss)))
 315  321                          check_toptext(mdoc, n->line, n->pos, n->string);
 316  322                  break;
      323 +        case ROFFT_COMMENT:
 317  324          case ROFFT_EQN:
 318  325          case ROFFT_TBL:
 319  326                  break;
 320  327          case ROFFT_ROOT:
 321  328                  post_root(mdoc);
 322  329                  break;
 323  330          default:
 324  331                  check_args(mdoc, mdoc->last);
 325  332  
 326  333                  /*
↓ open down ↓ 61 lines elided ↑ open up ↑
 388  395  
 389  396          if (MDOC_LITERAL & mdoc->flags)
 390  397                  return;
 391  398  
 392  399          for (cp = p; NULL != (p = strchr(p, '\t')); p++)
 393  400                  mandoc_msg(MANDOCERR_FI_TAB, mdoc->parse,
 394  401                      ln, pos + (int)(p - cp), NULL);
 395  402  }
 396  403  
 397  404  static void
      405 +check_text_em(struct roff_man *mdoc, int ln, int pos, char *p)
      406 +{
      407 +        const struct roff_node  *np, *nn;
      408 +        char                    *cp;
      409 +
      410 +        np = mdoc->last->prev;
      411 +        nn = mdoc->last->next;
      412 +
      413 +        /* Look for em-dashes wrongly encoded as "--". */
      414 +
      415 +        for (cp = p; *cp != '\0'; cp++) {
      416 +                if (cp[0] != '-' || cp[1] != '-')
      417 +                        continue;
      418 +                cp++;
      419 +
      420 +                /* Skip input sequences of more than two '-'. */
      421 +
      422 +                if (cp[1] == '-') {
      423 +                        while (cp[1] == '-')
      424 +                                cp++;
      425 +                        continue;
      426 +                }
      427 +
      428 +                /* Skip "--" directly attached to something else. */
      429 +
      430 +                if ((cp - p > 1 && cp[-2] != ' ') ||
      431 +                    (cp[1] != '\0' && cp[1] != ' '))
      432 +                        continue;
      433 +
      434 +                /* Require a letter right before or right afterwards. */
      435 +
      436 +                if ((cp - p > 2 ?
      437 +                     isalpha((unsigned char)cp[-3]) :
      438 +                     np != NULL &&
      439 +                     np->type == ROFFT_TEXT &&
      440 +                     *np->string != '\0' &&
      441 +                     isalpha((unsigned char)np->string[
      442 +                       strlen(np->string) - 1])) ||
      443 +                    (cp[1] != '\0' && cp[2] != '\0' ?
      444 +                     isalpha((unsigned char)cp[2]) :
      445 +                     nn != NULL &&
      446 +                     nn->type == ROFFT_TEXT &&
      447 +                     isalpha((unsigned char)*nn->string))) {
      448 +                        mandoc_msg(MANDOCERR_DASHDASH, mdoc->parse,
      449 +                            ln, pos + (int)(cp - p) - 1, NULL);
      450 +                        break;
      451 +                }
      452 +        }
      453 +}
      454 +
      455 +static void
 398  456  check_toptext(struct roff_man *mdoc, int ln, int pos, const char *p)
 399  457  {
 400  458          const char      *cp, *cpr;
 401  459  
 402  460          if (*p == '\0')
 403  461                  return;
 404  462  
 405  463          if ((cp = strstr(p, "OpenBSD")) != NULL)
 406  464                  mandoc_msg(MANDOCERR_BX, mdoc->parse,
 407  465                      ln, pos + (cp - p), "Ox");
↓ open down ↓ 115 lines elided ↑ open up ↑
 523  581          default:
 524  582                  break;
 525  583          }
 526  584  
 527  585          /* Exactly two non-alphanumeric bytes. */
 528  586          if (lc == nch->string + 1 && !isalnum((unsigned char)lc[-1]))
 529  587                  return;
 530  588  
 531  589          /* At least three alphabetic words with a sentence ending. */
 532  590          if (strchr("!.:?", *lc) != NULL && (tok == MDOC_Em ||
 533      -            tok == MDOC_Li || tok == MDOC_Po || tok == MDOC_Pq ||
 534      -            tok == MDOC_Sy)) {
      591 +            tok == MDOC_Li || tok == MDOC_Pq || tok == MDOC_Sy)) {
 535  592                  nw = 0;
 536  593                  for (cp = lc - 1; cp >= nch->string; cp--) {
 537  594                          if (*cp == ' ') {
 538  595                                  nw++;
 539  596                                  if (cp > nch->string && cp[-1] == ',')
 540  597                                          cp--;
 541  598                          } else if (isalpha((unsigned int)*cp)) {
 542  599                                  if (nw > 1)
 543  600                                          return;
 544  601                          } else
↓ open down ↓ 395 lines elided ↑ open up ↑
 940  997                  mdoc->last->flags = NODE_NOSRC;
 941  998                  mdoc->last = n;
 942  999                  return;
 943 1000          }
 944 1001  
 945 1002          mandoc_vmsg(MANDOCERR_LB_BAD, mdoc->parse, n->child->line,
 946 1003              n->child->pos, "Lb %s", n->child->string);
 947 1004  
 948 1005          roff_word_alloc(mdoc, n->line, n->pos, "library");
 949 1006          mdoc->last->flags = NODE_NOSRC;
 950      -        roff_word_alloc(mdoc, n->line, n->pos, "\\(Lq");
     1007 +        roff_word_alloc(mdoc, n->line, n->pos, "\\(lq");
 951 1008          mdoc->last->flags = NODE_DELIMO | NODE_NOSRC;
 952 1009          mdoc->last = mdoc->last->next;
 953      -        roff_word_alloc(mdoc, n->line, n->pos, "\\(Rq");
     1010 +        roff_word_alloc(mdoc, n->line, n->pos, "\\(rq");
 954 1011          mdoc->last->flags = NODE_DELIMC | NODE_NOSRC;
 955 1012          mdoc->last = n;
 956 1013  }
 957 1014  
 958 1015  static void
 959 1016  post_rv(POST_ARGS)
 960 1017  {
 961 1018          struct roff_node        *n;
 962 1019          int                      ic;
 963 1020  
↓ open down ↓ 943 lines elided ↑ open up ↑
1907 1964                  mandoc_msg(MANDOCERR_RCS_MISSING, mdoc->parse, 0, 0,
1908 1965                      mdoc->meta.os_e == MANDOC_OS_OPENBSD ?
1909 1966                      "(OpenBSD)" : "(NetBSD)");
1910 1967  
1911 1968          if (mdoc->meta.arch != NULL &&
1912 1969              (arch = arches[mdoc->meta.os_e]) != NULL) {
1913 1970                  while (*arch != NULL && strcmp(*arch, mdoc->meta.arch))
1914 1971                          arch++;
1915 1972                  if (*arch == NULL) {
1916 1973                          n = mdoc->first->child;
1917      -                        while (n->tok != MDOC_Dt)
     1974 +                        while (n->tok != MDOC_Dt ||
     1975 +                            n->child == NULL ||
     1976 +                            n->child->next == NULL ||
     1977 +                            n->child->next->next == NULL)
1918 1978                                  n = n->next;
1919 1979                          n = n->child->next->next;
1920 1980                          mandoc_vmsg(MANDOCERR_ARCH_BAD,
1921 1981                              mdoc->parse, n->line, n->pos,
1922 1982                              "Dt ... %s %s", mdoc->meta.arch,
1923 1983                              mdoc->meta.os_e == MANDOC_OS_OPENBSD ?
1924 1984                              "(OpenBSD)" : "(NetBSD)");
1925 1985                  }
1926 1986          }
1927 1987  
1928 1988          /* Check that we begin with a proper `Sh'. */
1929 1989  
1930 1990          n = mdoc->first->child;
1931      -        while (n != NULL && n->tok >= MDOC_Dd &&
1932      -            mdoc_macros[n->tok].flags & MDOC_PROLOGUE)
     1991 +        while (n != NULL &&
     1992 +            (n->type == ROFFT_COMMENT ||
     1993 +             (n->tok >= MDOC_Dd &&
     1994 +              mdoc_macros[n->tok].flags & MDOC_PROLOGUE)))
1933 1995                  n = n->next;
1934 1996  
1935 1997          if (n == NULL)
1936 1998                  mandoc_msg(MANDOCERR_DOC_EMPTY, mdoc->parse, 0, 0, NULL);
1937 1999          else if (n->tok != MDOC_Sh)
1938 2000                  mandoc_msg(MANDOCERR_SEC_BEFORE, mdoc->parse,
1939 2001                      n->line, n->pos, roff_name[n->tok]);
1940 2002  }
1941 2003  
1942 2004  static void
↓ open down ↓ 964 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX