[BACK]Return to mdoc_validate.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/mdoc_validate.c between version 1.379 and 1.380

version 1.379, 2020/02/27 21:43:44 version 1.380, 2020/03/13 15:32:28
Line 1 
Line 1 
 /*      $Id$ */  /* $Id$ */
 /*  /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>  
  * Copyright (c) 2010-2020 Ingo Schwarze <schwarze@openbsd.org>   * Copyright (c) 2010-2020 Ingo Schwarze <schwarze@openbsd.org>
    * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>   * Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
Line 15 
Line 15 
  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    *
    * Validation module for mdoc(7) syntax trees used by mandoc(1).
  */   */
 #include "config.h"  #include "config.h"
   
Line 35 
Line 37 
 #include "mandoc.h"  #include "mandoc.h"
 #include "mandoc_xr.h"  #include "mandoc_xr.h"
 #include "roff.h"  #include "roff.h"
   #include "tag.h"
 #include "mdoc.h"  #include "mdoc.h"
 #include "libmandoc.h"  #include "libmandoc.h"
 #include "roff_int.h"  #include "roff_int.h"
Line 82  static void  post_dd(POST_ARGS);
Line 85  static void  post_dd(POST_ARGS);
 static  void     post_delim(POST_ARGS);  static  void     post_delim(POST_ARGS);
 static  void     post_delim_nb(POST_ARGS);  static  void     post_delim_nb(POST_ARGS);
 static  void     post_dt(POST_ARGS);  static  void     post_dt(POST_ARGS);
   static  void     post_em(POST_ARGS);
 static  void     post_en(POST_ARGS);  static  void     post_en(POST_ARGS);
   static  void     post_er(POST_ARGS);
 static  void     post_es(POST_ARGS);  static  void     post_es(POST_ARGS);
 static  void     post_eoln(POST_ARGS);  static  void     post_eoln(POST_ARGS);
 static  void     post_ex(POST_ARGS);  static  void     post_ex(POST_ARGS);
Line 113  static void  post_sm(POST_ARGS);
Line 118  static void  post_sm(POST_ARGS);
 static  void     post_st(POST_ARGS);  static  void     post_st(POST_ARGS);
 static  void     post_std(POST_ARGS);  static  void     post_std(POST_ARGS);
 static  void     post_sx(POST_ARGS);  static  void     post_sx(POST_ARGS);
   static  void     post_tag(POST_ARGS);
 static  void     post_tg(POST_ARGS);  static  void     post_tg(POST_ARGS);
 static  void     post_useless(POST_ARGS);  static  void     post_useless(POST_ARGS);
 static  void     post_xr(POST_ARGS);  static  void     post_xr(POST_ARGS);
Line 137  static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = 
Line 143  static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = 
         NULL,           /* Ap */          NULL,           /* Ap */
         post_defaults,  /* Ar */          post_defaults,  /* Ar */
         NULL,           /* Cd */          NULL,           /* Cd */
         post_delim_nb,  /* Cm */          post_tag,       /* Cm */
         post_delim_nb,  /* Dv */          post_tag,       /* Dv */
         post_delim_nb,  /* Er */          post_er,        /* Er */
         post_delim_nb,  /* Ev */          post_tag,       /* Ev */
         post_ex,        /* Ex */          post_ex,        /* Ex */
         post_fa,        /* Fa */          post_fa,        /* Fa */
         NULL,           /* Fd */          NULL,           /* Fd */
         post_delim_nb,  /* Fl */          post_tag,       /* Fl */
         post_fn,        /* Fn */          post_fn,        /* Fn */
         post_delim_nb,  /* Ft */          post_delim_nb,  /* Ft */
         post_delim_nb,  /* Ic */          post_tag,       /* Ic */
         post_delim_nb,  /* In */          post_delim_nb,  /* In */
         post_defaults,  /* Li */          post_tag,       /* Li */
         post_nd,        /* Nd */          post_nd,        /* Nd */
         post_nm,        /* Nm */          post_nm,        /* Nm */
         post_delim_nb,  /* Op */          post_delim_nb,  /* Op */
Line 187  static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = 
Line 193  static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = 
         NULL,           /* Dq */          NULL,           /* Dq */
         NULL,           /* Ec */          NULL,           /* Ec */
         NULL,           /* Ef */          NULL,           /* Ef */
         post_delim_nb,  /* Em */          post_em,        /* Em */
         NULL,           /* Eo */          NULL,           /* Eo */
         post_xx,        /* Fx */          post_xx,        /* Fx */
         post_delim_nb,  /* Ms */          post_tag,       /* Ms */
         NULL,           /* No */          post_tag,       /* No */
         post_ns,        /* Ns */          post_ns,        /* Ns */
         post_xx,        /* Nx */          post_xx,        /* Nx */
         post_xx,        /* Ox */          post_xx,        /* Ox */
Line 210  static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = 
Line 216  static const v_post mdoc_valids[MDOC_MAX - MDOC_Dd] = 
         post_delim_nb,  /* Sq */          post_delim_nb,  /* Sq */
         post_sm,        /* Sm */          post_sm,        /* Sm */
         post_sx,        /* Sx */          post_sx,        /* Sx */
         post_delim_nb,  /* Sy */          post_em,        /* Sy */
         post_useless,   /* Tn */          post_useless,   /* Tn */
         post_xx,        /* Ux */          post_xx,        /* Ux */
         NULL,           /* Xc */          NULL,           /* Xc */
Line 287  static const char * const secnames[SEC__MAX] = {
Line 293  static const char * const secnames[SEC__MAX] = {
         NULL          NULL
 };  };
   
   static  int       fn_prio = TAG_STRONG;
   
   
 /* Validate the subtree rooted at mdoc->last. */  /* Validate the subtree rooted at mdoc->last. */
 void  void
 mdoc_validate(struct roff_man *mdoc)  mdoc_validate(struct roff_man *mdoc)
Line 1094  post_st(POST_ARGS)
Line 1102  post_st(POST_ARGS)
 static void  static void
 post_tg(POST_ARGS)  post_tg(POST_ARGS)
 {  {
         struct roff_node        *n, *nch, *nn;          struct roff_node *n;    /* The .Tg node. */
         size_t                  len;          struct roff_node *nch;  /* The first child of the .Tg node. */
           struct roff_node *nn;   /* The next node after the .Tg node. */
           struct roff_node *nt;   /* The TEXT node containing the tag. */
           size_t            len;  /* The number of bytes in the tag. */
   
         /* Find the next node. */          /* Find the next node. */
         n = mdoc->last;          n = mdoc->last;
Line 1106  post_tg(POST_ARGS)
Line 1117  post_tg(POST_ARGS)
                 }                  }
         }          }
   
         /* Add the default argument, if needed. */          /* Find the tag. */
         nch = n->child;          nt = nch = n->child;
         if (nch == NULL && nn != NULL && nn->child->type == ROFFT_TEXT) {          if (nch == NULL && nn != NULL && nn->child != NULL &&
                 mdoc->next = ROFF_NEXT_CHILD;              nn->child->type == ROFFT_TEXT)
                 roff_word_alloc(mdoc, n->line, n->pos, n->next->child->string);                  nt = nn->child;
                 nch = mdoc->last;  
                 nch->flags |= NODE_NOSRC;  
                 mdoc->last = n;  
         }  
   
         /* Validate the first argument. */          /* Validate the tag. */
         if (nch == NULL || *nch->string == '\0')          if (nt == NULL || *nt->string == '\0')
                 mandoc_msg(MANDOCERR_MACRO_EMPTY, n->line, n->pos, "Tg");                  mandoc_msg(MANDOCERR_MACRO_EMPTY, n->line, n->pos, "Tg");
         if (nch == NULL) {          if (nt == NULL) {
                 roff_node_delete(mdoc, n);                  roff_node_delete(mdoc, n);
                 return;                  return;
         }          }
         len = strcspn(nch->string, " \t");          len = strcspn(nt->string, " \t\\");
         if (nch->string[len] != '\0')          if (nt->string[len] != '\0')
                 mandoc_msg(MANDOCERR_TG_SPC, nch->line, nch->pos + len + 1,                  mandoc_msg(MANDOCERR_TG_SPC, nt->line,
                     "Tg %s", nch->string);                      nt->pos + len, "Tg %s", nt->string);
   
         /* Keep only the first argument. */          /* Keep only the first argument. */
         if (nch->next != NULL) {          if (nch != NULL && nch->next != NULL) {
                 mandoc_msg(MANDOCERR_ARG_EXCESS, nch->next->line,                  mandoc_msg(MANDOCERR_ARG_EXCESS, nch->next->line,
                     nch->next->pos, "Tg ... %s", nch->next->string);                      nch->next->pos, "Tg ... %s", nch->next->string);
                 while (nch->next != NULL)                  while (nch->next != NULL)
Line 1137  post_tg(POST_ARGS)
Line 1144  post_tg(POST_ARGS)
         }          }
   
         /* Drop the macro if the first argument is invalid. */          /* Drop the macro if the first argument is invalid. */
         if (len == 0 || nch->string[len] != '\0') {          if (len == 0 || nt->string[len] != '\0') {
                 roff_node_delete(mdoc, n);                  roff_node_delete(mdoc, n);
                 return;                  return;
         }          }
   
         /* By default, write a <mark> element. */          /* By default, tag the .Tg node itself. */
         n->flags |= NODE_ID;  
         if (nn == NULL)          if (nn == NULL)
                 return;                  nn = n;
   
         /* Explicit tagging of specific macros. */          /* Explicit tagging of specific macros. */
         switch (nn->tok) {          switch (nn->tok) {
         case MDOC_Sh:          case MDOC_Sh:
         case MDOC_Ss:          case MDOC_Ss:
                 if (nn->head->flags & NODE_ID || nn->head->child == NULL)          case MDOC_Fo:
                   nn = nn->head;
                   /* FALLTHROUGH */
           case MDOC_Cm:
           case MDOC_Dv:
           case MDOC_Em:
           case MDOC_Er:
           case MDOC_Ev:
           case MDOC_Fl:
           case MDOC_Fn:
           case MDOC_Ic:
           case MDOC_Li:
           case MDOC_Ms:
           case MDOC_No:
           case MDOC_Sy:
                   if (nn->child != NULL && (nn->flags & NODE_ID) == 0)
                         break;                          break;
                 n->flags |= NODE_NOPRT;                  /* FALLTHROUGH */
                 nn->head->flags |= NODE_ID | NODE_HREF;  
                 assert(nn->head->string == NULL);  
                 nn->head->string = mandoc_strdup(nch->string);  
                 break;  
         default:          default:
                   nn = n;
                 break;                  break;
         }          }
         if (n->flags & NODE_NOPRT)          tag_put(nt->string, TAG_MANUAL, nn);
                 n->flags &= ~NODE_ID;          if (nn != n)
                   n->flags |= NODE_NOPRT;
 }  }
   
 static void  static void
Line 1257  post_bf(POST_ARGS)
Line 1276  post_bf(POST_ARGS)
 static void  static void
 post_fname(POST_ARGS)  post_fname(POST_ARGS)
 {  {
         const struct roff_node  *n;          struct roff_node        *n, *nch;
         const char              *cp;          const char              *cp;
         size_t                   pos;          size_t                   pos;
   
         n = mdoc->last->child;          n = mdoc->last;
         cp = n->string;          nch = n->child;
           cp = nch->string;
         if (*cp == '(') {          if (*cp == '(') {
                 if (cp[strlen(cp + 1)] == ')')                  if (cp[strlen(cp + 1)] == ')')
                         return;                          return;
                 pos = 0;                  pos = 0;
         } else {          } else {
                 pos = strcspn(cp, "()");                  pos = strcspn(cp, "()");
                 if (cp[pos] == '\0')                  if (cp[pos] == '\0') {
                           if (n->sec == SEC_DESCRIPTION ||
                               n->sec == SEC_CUSTOM)
                                   tag_put(NULL, fn_prio++, n);
                         return;                          return;
                   }
         }          }
         mandoc_msg(MANDOCERR_FN_PAREN, n->line, n->pos + pos, "%s", cp);          mandoc_msg(MANDOCERR_FN_PAREN, nch->line, nch->pos + pos, "%s", cp);
 }  }
   
 static void  static void
 post_fn(POST_ARGS)  post_fn(POST_ARGS)
 {  {
   
         post_fname(mdoc);          post_fname(mdoc);
         post_fa(mdoc);          post_fa(mdoc);
 }  }
Line 1442  post_display(POST_ARGS)
Line 1465  post_display(POST_ARGS)
 static void  static void
 post_defaults(POST_ARGS)  post_defaults(POST_ARGS)
 {  {
         struct roff_node *nn;          struct roff_node *n;
   
         if (mdoc->last->child != NULL) {          n = mdoc->last;
           if (n->child != NULL) {
                 post_delim_nb(mdoc);                  post_delim_nb(mdoc);
                 return;                  return;
         }          }
           mdoc->next = ROFF_NEXT_CHILD;
         /*          switch (n->tok) {
          * The `Ar' defaults to "file ..." if no value is provided as an  
          * argument; the `Mt' and `Pa' macros use "~"; the `Li' just  
          * gets an empty string.  
          */  
   
         nn = mdoc->last;  
         switch (nn->tok) {  
         case MDOC_Ar:          case MDOC_Ar:
                 mdoc->next = ROFF_NEXT_CHILD;                  roff_word_alloc(mdoc, n->line, n->pos, "file");
                 roff_word_alloc(mdoc, nn->line, nn->pos, "file");  
                 mdoc->last->flags |= NODE_NOSRC;                  mdoc->last->flags |= NODE_NOSRC;
                 roff_word_alloc(mdoc, nn->line, nn->pos, "...");                  roff_word_alloc(mdoc, n->line, n->pos, "...");
                 mdoc->last->flags |= NODE_NOSRC;  
                 break;                  break;
         case MDOC_Pa:          case MDOC_Pa:
         case MDOC_Mt:          case MDOC_Mt:
                 mdoc->next = ROFF_NEXT_CHILD;                  roff_word_alloc(mdoc, n->line, n->pos, "~");
                 roff_word_alloc(mdoc, nn->line, nn->pos, "~");  
                 mdoc->last->flags |= NODE_NOSRC;  
                 break;                  break;
         default:          default:
                 abort();                  abort();
         }          }
         mdoc->last = nn;          mdoc->last->flags |= NODE_NOSRC;
           mdoc->last = n;
 }  }
   
 static void  static void
Line 1527  post_an(POST_ARGS)
Line 1541  post_an(POST_ARGS)
 }  }
   
 static void  static void
 post_en(POST_ARGS)  post_em(POST_ARGS)
 {  {
           post_tag(mdoc);
           tag_put(NULL, TAG_FALLBACK, mdoc->last);
   }
   
   static void
   post_en(POST_ARGS)
   {
         post_obsolete(mdoc);          post_obsolete(mdoc);
         if (mdoc->last->type == ROFFT_BLOCK)          if (mdoc->last->type == ROFFT_BLOCK)
                 mdoc->last->norm->Es = mdoc->last_es;                  mdoc->last->norm->Es = mdoc->last_es;
 }  }
   
 static void  static void
 post_es(POST_ARGS)  post_er(POST_ARGS)
 {  {
           struct roff_node *n;
   
           n = mdoc->last;
           if (n->sec == SEC_ERRORS &&
               (n->parent->tok == MDOC_It ||
                (n->parent->tok == MDOC_Bq &&
                 n->parent->parent->parent->tok == MDOC_It)))
                   tag_put(NULL, TAG_STRONG, n);
           post_delim_nb(mdoc);
   }
   
   static void
   post_tag(POST_ARGS)
   {
           struct roff_node *n;
   
           n = mdoc->last;
           if ((n->prev == NULL ||
                (n->prev->type == ROFFT_TEXT &&
                 strcmp(n->prev->string, "|") == 0)) &&
               (n->parent->tok == MDOC_It ||
                (n->parent->tok == MDOC_Xo &&
                 n->parent->parent->prev == NULL &&
                 n->parent->parent->parent->tok == MDOC_It)))
                   tag_put(NULL, TAG_STRONG, n);
           post_delim_nb(mdoc);
   }
   
   static void
   post_es(POST_ARGS)
   {
         post_obsolete(mdoc);          post_obsolete(mdoc);
         mdoc->last_es = mdoc->last;          mdoc->last_es = mdoc->last;
 }  }
Line 1635  post_it(POST_ARGS)
Line 1685  post_it(POST_ARGS)
                 if ((nch = nit->head->child) != NULL)                  if ((nch = nit->head->child) != NULL)
                         mandoc_msg(MANDOCERR_ARG_SKIP,                          mandoc_msg(MANDOCERR_ARG_SKIP,
                             nit->line, nit->pos, "It %s",                              nit->line, nit->pos, "It %s",
                             nch->string == NULL ? roff_name[nch->tok] :                              nch->type == ROFFT_TEXT ? nch->string :
                             nch->string);                              roff_name[nch->tok]);
                 break;                  break;
         case LIST_column:          case LIST_column:
                 cols = (int)nbl->norm->Bl.ncols;                  cols = (int)nbl->norm->Bl.ncols;
Line 2152  post_sx(POST_ARGS)
Line 2202  post_sx(POST_ARGS)
 static void  static void
 post_sh(POST_ARGS)  post_sh(POST_ARGS)
 {  {
   
         post_ignpar(mdoc);          post_ignpar(mdoc);
   
         switch (mdoc->last->type) {          switch (mdoc->last->type) {
Line 2384  post_sh_head(POST_ARGS)
Line 2433  post_sh_head(POST_ARGS)
                 roff_setreg(mdoc->roff, "nS", 0, '=');                  roff_setreg(mdoc->roff, "nS", 0, '=');
                 mdoc->flags &= ~MDOC_SYNOPSIS;                  mdoc->flags &= ~MDOC_SYNOPSIS;
         }          }
           if (sec == SEC_DESCRIPTION)
                   fn_prio = TAG_STRONG;
   
         /* Mark our last section. */          /* Mark our last section. */
   
Line 2555  post_par(POST_ARGS)
Line 2606  post_par(POST_ARGS)
 {  {
         struct roff_node *np;          struct roff_node *np;
   
           fn_prio = TAG_STRONG;
         post_prevpar(mdoc);          post_prevpar(mdoc);
   
         np = mdoc->last;          np = mdoc->last;

Legend:
Removed from v.1.379  
changed lines
  Added in v.1.380

CVSweb