[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.1 and 1.13

version 1.1, 2009/03/25 15:17:49 version 1.13, 2009/06/17 11:02:06
Line 1 
Line 1 
 /* $Id$ */  /*      $Id$ */
 /*  /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@openbsd.org>   * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *   *
  * Permission to use, copy, modify, and distribute this software for any   * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the   * purpose with or without fee is hereby granted, provided that the above
  * above copyright notice and this permission notice appear in all   * copyright notice and this permission notice appear in all copies.
  * copies.  
  *   *
  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  * PERFORMANCE OF THIS SOFTWARE.  
  */   */
 #include <sys/types.h>  #include <sys/types.h>
   
Line 22 
Line 20 
 #include <ctype.h>  #include <ctype.h>
 #include <stdarg.h>  #include <stdarg.h>
 #include <stdlib.h>  #include <stdlib.h>
   #include <string.h>
   
 #include "libmdoc.h"  #include "libmdoc.h"
   
 /* FIXME: .Bl -diag can't have non-text children in HEAD. */  /* FIXME: .Bl -diag can't have non-text children in HEAD. */
 /* TODO: ignoring Pp (it's superfluous in some invocations). */  /* TODO: ignoring Pp (it's superfluous in some invocations). */
   
 /*  
  * Pre- and post-validate macros as they're parsed.  Pre-validation  
  * occurs when the macro has been detected and its arguments parsed.  
  * Post-validation occurs when all child macros have also been parsed.  
  * In the ELEMENT case, this is simply the parameters of the macro; in  
  * the BLOCK case, this is the HEAD, BODY, TAIL and so on.  
  */  
   
 #define PRE_ARGS        struct mdoc *mdoc, const struct mdoc_node *n  #define PRE_ARGS        struct mdoc *mdoc, const struct mdoc_node *n
 #define POST_ARGS       struct mdoc *mdoc  #define POST_ARGS       struct mdoc *mdoc
   
 enum    merr {  enum    merr {
           ETOOLONG,
         EESCAPE,          EESCAPE,
         EPRINT,          EPRINT,
         ENODATA,          ENODATA,
Line 50  enum merr {
Line 42  enum merr {
         ELISTTYPE,          ELISTTYPE,
         EDISPTYPE,          EDISPTYPE,
         EMULTIDISP,          EMULTIDISP,
           ESECNAME,
         EMULTILIST,          EMULTILIST,
         EARGREP,          EARGREP,
         EBOOL,          EBOOL,
Line 57  enum merr {
Line 50  enum merr {
 };  };
   
 enum    mwarn {  enum    mwarn {
           WPRINT,
           WNOWIDTH,
           WMISSWIDTH,
         WESCAPE,          WESCAPE,
           WDEPESC,
           WDEPCOL,
         WWRONGMSEC,          WWRONGMSEC,
         WSECOOO,          WSECOOO,
         WSECREP,          WSECREP,
Line 82  struct valids {
Line 80  struct valids {
         v_post  *post;          v_post  *post;
 };  };
   
 /* Utility checks. */  
   
 static  int     pwarn(struct mdoc *, int, int, enum mwarn);  static  int     pwarn(struct mdoc *, int, int, enum mwarn);
 static  int     perr(struct mdoc *, int, int, enum merr);  static  int     perr(struct mdoc *, int, int, enum merr);
 static  int     check_parent(PRE_ARGS, int, enum mdoc_type);  static  int     check_parent(PRE_ARGS, int, enum mdoc_type);
Line 102  static int err_child_gt(struct mdoc *, const char *, i
Line 98  static int err_child_gt(struct mdoc *, const char *, i
 static  int     warn_child_gt(struct mdoc *, const char *, int);  static  int     warn_child_gt(struct mdoc *, const char *, int);
 static  int     err_child_eq(struct mdoc *, const char *, int);  static  int     err_child_eq(struct mdoc *, const char *, int);
 static  int     warn_child_eq(struct mdoc *, const char *, int);  static  int     warn_child_eq(struct mdoc *, const char *, int);
 static  inline int count_child(struct mdoc *);  static  int     count_child(struct mdoc *);
 static  inline int warn_count(struct mdoc *, const char *,  static  int     warn_print(struct mdoc *, int, int);
   static  int     warn_count(struct mdoc *, const char *,
                         int, const char *, int);                          int, const char *, int);
 static  inline int err_count(struct mdoc *, const char *,  static  int     err_count(struct mdoc *, const char *,
                         int, const char *, int);                          int, const char *, int);
 static  int     pre_an(PRE_ARGS);  static  int     pre_an(PRE_ARGS);
 static  int     pre_bd(PRE_ARGS);  static  int     pre_bd(PRE_ARGS);
Line 120  static int pre_fd(PRE_ARGS);
Line 117  static int pre_fd(PRE_ARGS);
 static  int     pre_it(PRE_ARGS);  static  int     pre_it(PRE_ARGS);
 static  int     pre_lb(PRE_ARGS);  static  int     pre_lb(PRE_ARGS);
 static  int     pre_os(PRE_ARGS);  static  int     pre_os(PRE_ARGS);
 static  int     pre_prologue(PRE_ARGS);  
 static  int     pre_rv(PRE_ARGS);  static  int     pre_rv(PRE_ARGS);
 static  int     pre_sh(PRE_ARGS);  static  int     pre_sh(PRE_ARGS);
 static  int     pre_ss(PRE_ARGS);  static  int     pre_ss(PRE_ARGS);
Line 137  static int bwarn_ge1(POST_ARGS);
Line 133  static int bwarn_ge1(POST_ARGS);
 static  int     hwarn_eq1(POST_ARGS);  static  int     hwarn_eq1(POST_ARGS);
 static  int     ewarn_ge1(POST_ARGS);  static  int     ewarn_ge1(POST_ARGS);
 static  int     ebool(POST_ARGS);  static  int     ebool(POST_ARGS);
   
 static  int     post_an(POST_ARGS);  static  int     post_an(POST_ARGS);
 static  int     post_args(POST_ARGS);  static  int     post_args(POST_ARGS);
 static  int     post_at(POST_ARGS);  static  int     post_at(POST_ARGS);
Line 151  static int post_sh_body(POST_ARGS);
Line 146  static int post_sh_body(POST_ARGS);
 static  int     post_sh_head(POST_ARGS);  static  int     post_sh_head(POST_ARGS);
 static  int     post_st(POST_ARGS);  static  int     post_st(POST_ARGS);
   
 #define mwarn(m, t) nwarn((m), (m)->last, (t))  #define vwarn(m, t) nwarn((m), (m)->last, (t))
 #define merr(m, t) nerr((m), (m)->last, (t))  #define verr(m, t) nerr((m), (m)->last, (t))
 #define nwarn(m, n, t) pwarn((m), (n)->line, (n)->pos, (t))  #define nwarn(m, n, t) pwarn((m), (n)->line, (n)->pos, (t))
 #define nerr(m, n, t) perr((m), (n)->line, (n)->pos, (t))  #define nerr(m, n, t) perr((m), (n)->line, (n)->pos, (t))
   
Line 160  static v_pre pres_an[] = { pre_an, NULL };
Line 155  static v_pre pres_an[] = { pre_an, NULL };
 static  v_pre   pres_bd[] = { pre_display, pre_bd, NULL };  static  v_pre   pres_bd[] = { pre_display, pre_bd, NULL };
 static  v_pre   pres_bl[] = { pre_bl, NULL };  static  v_pre   pres_bl[] = { pre_bl, NULL };
 static  v_pre   pres_cd[] = { pre_cd, NULL };  static  v_pre   pres_cd[] = { pre_cd, NULL };
 static  v_pre   pres_dd[] = { pre_prologue, pre_dd, NULL };  static  v_pre   pres_dd[] = { pre_dd, NULL };
 static  v_pre   pres_d1[] = { pre_display, NULL };  static  v_pre   pres_d1[] = { pre_display, NULL };
 static  v_pre   pres_dt[] = { pre_prologue, pre_dt, NULL };  static  v_pre   pres_dt[] = { pre_dt, NULL };
 static  v_pre   pres_er[] = { pre_er, NULL };  static  v_pre   pres_er[] = { pre_er, NULL };
 static  v_pre   pres_ex[] = { pre_ex, NULL };  static  v_pre   pres_ex[] = { pre_ex, NULL };
 static  v_pre   pres_fd[] = { pre_fd, NULL };  static  v_pre   pres_fd[] = { pre_fd, NULL };
 static  v_pre   pres_it[] = { pre_it, NULL };  static  v_pre   pres_it[] = { pre_it, NULL };
 static  v_pre   pres_lb[] = { pre_lb, NULL };  static  v_pre   pres_lb[] = { pre_lb, NULL };
 static  v_pre   pres_os[] = { pre_prologue, pre_os, NULL };  static  v_pre   pres_os[] = { pre_os, NULL };
 static  v_pre   pres_rv[] = { pre_rv, NULL };  static  v_pre   pres_rv[] = { pre_rv, NULL };
 static  v_pre   pres_sh[] = { pre_sh, NULL };  static  v_pre   pres_sh[] = { pre_sh, NULL };
 static  v_pre   pres_ss[] = { pre_ss, NULL };  static  v_pre   pres_ss[] = { pre_ss, NULL };
Line 197  static v_post posts_bf[] = { hwarn_le1, post_bf, NULL 
Line 192  static v_post posts_bf[] = { hwarn_le1, post_bf, NULL 
 static  v_post  posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL };  static  v_post  posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL };
   
 const   struct valids mdoc_valids[MDOC_MAX] = {  const   struct valids mdoc_valids[MDOC_MAX] = {
         { NULL, NULL },                         /* \" */          { NULL, NULL },                         /* Ap */
         { pres_dd, posts_text },                /* Dd */          { pres_dd, posts_text },                /* Dd */
         { pres_dt, NULL },                      /* Dt */          { pres_dt, NULL },                      /* Dt */
         { pres_os, NULL },                      /* Os */          { pres_os, NULL },                      /* Os */
Line 304  const struct valids mdoc_valids[MDOC_MAX] = {
Line 299  const struct valids mdoc_valids[MDOC_MAX] = {
         { NULL, NULL },                         /* Fr */          { NULL, NULL },                         /* Fr */
         { NULL, posts_notext },                 /* Ud */          { NULL, posts_notext },                 /* Ud */
         { pres_lb, posts_lb },                  /* Lb */          { pres_lb, posts_lb },                  /* Lb */
         { NULL, NULL },                         /* Ap */  
         { NULL, posts_pp },                     /* Lp */          { NULL, posts_pp },                     /* Lp */
         { NULL, posts_text },                   /* Lk */          { NULL, NULL },                         /* Lk */
         { NULL, posts_text },                   /* Mt */          { NULL, posts_text },                   /* Mt */
         { NULL, posts_wline },                  /* Brq */          { NULL, posts_wline },                  /* Brq */
         { NULL, NULL },                         /* Bro */          { NULL, NULL },                         /* Bro */
Line 319  const struct valids mdoc_valids[MDOC_MAX] = {
Line 313  const struct valids mdoc_valids[MDOC_MAX] = {
 };  };
   
   
   #ifdef __linux__
   extern  size_t  strlcat(char *, const char *, size_t);
   #endif
   
   
 int  int
 mdoc_valid_pre(struct mdoc *mdoc,  mdoc_valid_pre(struct mdoc *mdoc,
                 const struct mdoc_node *n)                  const struct mdoc_node *n)
Line 384  perr(struct mdoc *m, int line, int pos, enum merr type
Line 383  perr(struct mdoc *m, int line, int pos, enum merr type
   
         p = NULL;          p = NULL;
         switch (type) {          switch (type) {
           case (ETOOLONG):
                   p = "text argument too long";
                   break;
         case (EESCAPE):          case (EESCAPE):
                 p = "invalid escape sequence";                  p = "invalid escape sequence";
                 break;                  break;
Line 411  perr(struct mdoc *m, int line, int pos, enum merr type
Line 413  perr(struct mdoc *m, int line, int pos, enum merr type
         case (EDISPTYPE):          case (EDISPTYPE):
                 p = "missing display type";                  p = "missing display type";
                 break;                  break;
           case (ESECNAME):
                   p = "the NAME section must come first";
                   break;
         case (ELINE):          case (ELINE):
                 p = "expected line arguments";                  p = "expected line arguments";
                 break;                  break;
Line 461  pwarn(struct mdoc *m, int line, int pos, enum mwarn ty
Line 466  pwarn(struct mdoc *m, int line, int pos, enum mwarn ty
                 p = "prologue macros out-of-order";                  p = "prologue macros out-of-order";
                 c = WARN_COMPAT;                  c = WARN_COMPAT;
                 break;                  break;
           case (WDEPCOL):
                   p = "deprecated column argument syntax";
                   c = WARN_COMPAT;
                   break;
           case (WNOWIDTH):
                   p = "superfluous width argument";
                   break;
           case (WMISSWIDTH):
                   p = "missing width argument";
                   break;
           case (WPRINT):
                   p = "invalid character";
                   break;
         case (WESCAPE):          case (WESCAPE):
                 p = "invalid escape sequence";                  p = "invalid escape sequence";
                 break;                  break;
           case (WDEPESC):
                   p = "deprecated special-character escape";
                   break;
         case (WNOLINE):          case (WNOLINE):
                 p = "suggested no line arguments";                  p = "suggested no line arguments";
                 break;                  break;
Line 498  pwarn(struct mdoc *m, int line, int pos, enum mwarn ty
Line 519  pwarn(struct mdoc *m, int line, int pos, enum mwarn ty
 }  }
   
   
   static int
   warn_print(struct mdoc *m, int ln, int pos)
   {
           if (MDOC_IGN_CHARS & m->pflags)
                   return(pwarn(m, ln, pos, WPRINT));
           return(perr(m, ln, pos, EPRINT));
   }
   
   
 static inline int  static inline int
 warn_count(struct mdoc *m, const char *k,  warn_count(struct mdoc *m, const char *k,
                 int want, const char *v, int has)                  int want, const char *v, int has)
Line 695  check_text(struct mdoc *mdoc, int line, int pos, const
Line 724  check_text(struct mdoc *mdoc, int line, int pos, const
 {  {
         size_t           c;          size_t           c;
   
         /* FIXME: indicate deprecated escapes \*(xx and \*x. */  
   
         for ( ; *p; p++) {          for ( ; *p; p++) {
                 if ('\t' == *p) {                  if ('\t' == *p) {
                         if ( ! (MDOC_LITERAL & mdoc->flags))                          if ( ! (MDOC_LITERAL & mdoc->flags))
                                 return(perr(mdoc, line, pos, EPRINT));                                  if ( ! warn_print(mdoc, line, pos))
                                           return(0);
                 } else if ( ! isprint((u_char)*p))                  } else if ( ! isprint((u_char)*p))
                         return(perr(mdoc, line, pos, EPRINT));                          if ( ! warn_print(mdoc, line, pos))
                                   return(0);
   
                 if ('\\' != *p)                  if ('\\' != *p)
                         continue;                          continue;
   
                 c = mdoc_isescape(p);                  c = mdoc_isescape(p);
                 if (c) {                  if (c) {
                           /* See if form is deprecated. */
                           if ('*' == p[1])
                                   if ( ! pwarn(mdoc, line, pos, WDEPESC))
                                           return(0);
                         p += (int)c - 1;                          p += (int)c - 1;
                         continue;                          continue;
                 }                  }
Line 764  pre_display(PRE_ARGS)
Line 797  pre_display(PRE_ARGS)
 static int  static int
 pre_bl(PRE_ARGS)  pre_bl(PRE_ARGS)
 {  {
         int              i, type, width, offset;          int              pos, col, type, width, offset;
   
         if (MDOC_BLOCK != n->type)          if (MDOC_BLOCK != n->type)
                 return(1);                  return(1);
Line 773  pre_bl(PRE_ARGS)
Line 806  pre_bl(PRE_ARGS)
   
         /* Make sure that only one type of list is specified.  */          /* Make sure that only one type of list is specified.  */
   
         type = offset = width = -1;          type = offset = width = col = -1;
   
         /* LINTED */          /* LINTED */
         for (i = 0; i < (int)n->args->argc; i++)          for (pos = 0; pos < (int)n->args->argc; pos++)
                 switch (n->args->argv[i].arg) {                  switch (n->args->argv[pos].arg) {
                 case (MDOC_Bullet):                  case (MDOC_Bullet):
                         /* FALLTHROUGH */                          /* FALLTHROUGH */
                 case (MDOC_Dash):                  case (MDOC_Dash):
Line 799  pre_bl(PRE_ARGS)
Line 832  pre_bl(PRE_ARGS)
                 case (MDOC_Inset):                  case (MDOC_Inset):
                         /* FALLTHROUGH */                          /* FALLTHROUGH */
                 case (MDOC_Column):                  case (MDOC_Column):
                         if (-1 == type) {                          if (-1 != type)
                                 type = n->args->argv[i].arg;                                  return(nerr(mdoc, n, EMULTILIST));
                                 break;                          type = n->args->argv[pos].arg;
                         }                          col = pos;
                         return(nerr(mdoc, n, EMULTILIST));                          break;
                 case (MDOC_Width):                  case (MDOC_Width):
                         if (-1 == width) {                          if (-1 != width)
                                 width = n->args->argv[i].arg;                                  return(nerr(mdoc, n, EARGREP));
                                 break;                          width = n->args->argv[pos].arg;
                         }                          break;
                         return(nerr(mdoc, n, EARGREP));  
                 case (MDOC_Offset):                  case (MDOC_Offset):
                         if (-1 == offset) {                          if (-1 != offset)
                                 offset = n->args->argv[i].arg;                                  return(nerr(mdoc, n, EARGREP));
                                 break;                          offset = n->args->argv[pos].arg;
                         }                          break;
                         return(nerr(mdoc, n, EARGREP));  
                 default:                  default:
                         break;                          break;
                 }                  }
Line 823  pre_bl(PRE_ARGS)
Line 854  pre_bl(PRE_ARGS)
         if (-1 == type)          if (-1 == type)
                 return(nerr(mdoc, n, ELISTTYPE));                  return(nerr(mdoc, n, ELISTTYPE));
   
           /*
            * Validate the width field.  Some list types don't need width
            * types and should be warned about them.  Others should have it
            * and must also be warned.
            */
   
         switch (type) {          switch (type) {
           case (MDOC_Tag):
                   if (-1 == width && ! nwarn(mdoc, n, WMISSWIDTH))
                           return(0);
                   break;
         case (MDOC_Column):          case (MDOC_Column):
                 /* FALLTHROUGH */                  /* FALLTHROUGH */
         case (MDOC_Diag):          case (MDOC_Diag):
Line 831  pre_bl(PRE_ARGS)
Line 872  pre_bl(PRE_ARGS)
         case (MDOC_Inset):          case (MDOC_Inset):
                 /* FALLTHROUGH */                  /* FALLTHROUGH */
         case (MDOC_Item):          case (MDOC_Item):
                 if (-1 == width)                  if (-1 != width && ! nwarn(mdoc, n, WNOWIDTH))
                           return(0);
                   break;
           default:
                   break;
           }
   
           /*
            * General validation of fields.
            */
   
           switch (type) {
           case (MDOC_Column):
                   assert(col >= 0);
                   if (0 == n->args->argv[col].sz)
                         break;                          break;
                 return(mdoc_nwarn(mdoc, n, WARN_SYNTAX,                  if ( ! nwarn(mdoc, n, WDEPCOL))
                                 "superfluous %s argument",                          return(0);
                                 mdoc_argnames[MDOC_Width]));                  break;
         case (MDOC_Tag):  
                 if (-1 != width)  
                         break;  
                 return(mdoc_nwarn(mdoc, n, WARN_SYNTAX,  
                                 "suggest %s argument",  
                                 mdoc_argnames[MDOC_Width]));  
         default:          default:
                 break;                  break;
         }          }
Line 960  static int
Line 1009  static int
 pre_er(PRE_ARGS)  pre_er(PRE_ARGS)
 {  {
   
         return(check_msec(mdoc, n, 2, 0));          return(check_msec(mdoc, n, 2, 3, 9, 0));
 }  }
   
   
Line 973  pre_cd(PRE_ARGS)
Line 1022  pre_cd(PRE_ARGS)
   
   
 static int  static int
 pre_prologue(PRE_ARGS)  
 {  
   
         return(check_sec(mdoc, n, SEC_PROLOGUE, SEC_CUSTOM));  
 }  
   
   
 static int  
 pre_dt(PRE_ARGS)  pre_dt(PRE_ARGS)
 {  {
   
Line 1033  post_bf(POST_ARGS)
Line 1074  post_bf(POST_ARGS)
   
         head = mdoc->last->head;          head = mdoc->last->head;
   
         if (NULL == mdoc->last->args) {          if (mdoc->last->args && head->child)
                 if (NULL == head->child ||                  return(mdoc_err(mdoc, "one argument expected"));
                                 MDOC_TEXT != head->child->type)          else if (mdoc->last->args)
                         return(mdoc_err(mdoc, "text argument expected"));                  return(1);
   
                 p = head->child->string;          if (NULL == head->child || MDOC_TEXT != head->child->type)
                 if (xstrcmp(p, "Em"))                  return(mdoc_err(mdoc, "text argument expected"));
                         return(1);  
                 else if (xstrcmp(p, "Li"))  
                         return(1);  
                 else if (xstrcmp(p, "Sm"))  
                         return(1);  
                 return(mdoc_nerr(mdoc, head->child, "invalid font"));  
         }  
   
         if (head->child)          p = head->child->string;
                 return(mdoc_err(mdoc, "one argument expected"));  
   
         return(1);          if (0 == strcmp(p, "Em"))
                   return(1);
           else if (0 == strcmp(p, "Li"))
                   return(1);
           else if (0 == strcmp(p, "Sm"))
                   return(1);
   
           return(mdoc_nerr(mdoc, head->child, "invalid font mode"));
 }  }
   
   
Line 1063  post_nm(POST_ARGS)
Line 1103  post_nm(POST_ARGS)
                 return(1);                  return(1);
         if (mdoc->meta.name)          if (mdoc->meta.name)
                 return(1);                  return(1);
         return(merr(mdoc, ENAME));          return(verr(mdoc, ENAME));
 }  }
   
   
Line 1074  post_at(POST_ARGS)
Line 1114  post_at(POST_ARGS)
         if (NULL == mdoc->last->child)          if (NULL == mdoc->last->child)
                 return(1);                  return(1);
         if (MDOC_TEXT != mdoc->last->child->type)          if (MDOC_TEXT != mdoc->last->child->type)
                 return(merr(mdoc, EATT));                  return(verr(mdoc, EATT));
         if (mdoc_a2att(mdoc->last->child->string))          if (mdoc_a2att(mdoc->last->child->string))
                 return(1);                  return(1);
         return(merr(mdoc, EATT));          return(verr(mdoc, EATT));
 }  }
   
   
Line 1088  post_an(POST_ARGS)
Line 1128  post_an(POST_ARGS)
         if (mdoc->last->args) {          if (mdoc->last->args) {
                 if (NULL == mdoc->last->child)                  if (NULL == mdoc->last->child)
                         return(1);                          return(1);
                 return(merr(mdoc, ELINE));                  return(verr(mdoc, ELINE));
         }          }
   
         if (mdoc->last->child)          if (mdoc->last->child)
                 return(1);                  return(1);
         return(merr(mdoc, ELINE));          return(verr(mdoc, ELINE));
 }  }
   
   
Line 1103  post_args(POST_ARGS)
Line 1143  post_args(POST_ARGS)
   
         if (mdoc->last->args)          if (mdoc->last->args)
                 return(1);                  return(1);
         return(merr(mdoc, ELINE));          return(verr(mdoc, ELINE));
 }  }
   
   
Line 1118  post_it(POST_ARGS)
Line 1158  post_it(POST_ARGS)
   
         n = mdoc->last->parent->parent;          n = mdoc->last->parent->parent;
         if (NULL == n->args)          if (NULL == n->args)
                 return(merr(mdoc, ELISTTYPE));                  return(verr(mdoc, ELISTTYPE));
   
         /* Some types require block-head, some not. */          /* Some types require block-head, some not. */
   
Line 1156  post_it(POST_ARGS)
Line 1196  post_it(POST_ARGS)
                 }                  }
   
         if (-1 == type)          if (-1 == type)
                 return(merr(mdoc, ELISTTYPE));                  return(verr(mdoc, ELISTTYPE));
   
         switch (type) {          switch (type) {
         case (MDOC_Tag):          case (MDOC_Tag):
                 if (NULL == mdoc->last->head->child)                  if (NULL == mdoc->last->head->child)
                         if ( ! mwarn(mdoc, WLINE))                          if ( ! vwarn(mdoc, WLINE))
                                 return(0);                                  return(0);
                 break;                  break;
         case (MDOC_Hang):          case (MDOC_Hang):
Line 1172  post_it(POST_ARGS)
Line 1212  post_it(POST_ARGS)
                 /* FALLTHROUGH */                  /* FALLTHROUGH */
         case (MDOC_Diag):          case (MDOC_Diag):
                 if (NULL == mdoc->last->head->child)                  if (NULL == mdoc->last->head->child)
                         if ( ! mwarn(mdoc, WLINE))                          if ( ! vwarn(mdoc, WLINE))
                                 return(0);                                  return(0);
                 if (NULL == mdoc->last->body->child)                  if (NULL == mdoc->last->body->child)
                         if ( ! mwarn(mdoc, WMULTILINE))                          if ( ! vwarn(mdoc, WMULTILINE))
                                 return(0);                                  return(0);
                 break;                  break;
         case (MDOC_Bullet):          case (MDOC_Bullet):
Line 1188  post_it(POST_ARGS)
Line 1228  post_it(POST_ARGS)
                 /* FALLTHROUGH */                  /* FALLTHROUGH */
         case (MDOC_Item):          case (MDOC_Item):
                 if (mdoc->last->head->child)                  if (mdoc->last->head->child)
                         if ( ! mwarn(mdoc, WNOLINE))                          if ( ! vwarn(mdoc, WNOLINE))
                                 return(0);                                  return(0);
                 if (NULL == mdoc->last->body->child)                  if (NULL == mdoc->last->body->child)
                         if ( ! mwarn(mdoc, WMULTILINE))                          if ( ! vwarn(mdoc, WMULTILINE))
                                 return(0);                                  return(0);
                 break;                  break;
         case (MDOC_Column):          case (MDOC_Column):
                 if (NULL == mdoc->last->head->child)                  if (NULL == mdoc->last->head->child)
                         if ( ! mwarn(mdoc, WLINE))                          if ( ! vwarn(mdoc, WLINE))
                                 return(0);                                  return(0);
                 if (mdoc->last->body->child)                  if (mdoc->last->body->child)
                         if ( ! mwarn(mdoc, WNOMULTILINE))                          if ( ! vwarn(mdoc, WNOMULTILINE))
                                 return(0);                                  return(0);
                 c = mdoc->last->child;                  c = mdoc->last->child;
                 for (i = 0; c && MDOC_HEAD == c->type; c = c->next)                  for (i = 0; c && MDOC_HEAD == c->type; c = c->next)
Line 1248  ebool(struct mdoc *mdoc)
Line 1288  ebool(struct mdoc *mdoc)
         for (n = mdoc->last->child; n; n = n->next) {          for (n = mdoc->last->child; n; n = n->next) {
                 if (MDOC_TEXT != n->type)                  if (MDOC_TEXT != n->type)
                         break;                          break;
                 if (xstrcmp(n->string, "on"))                  if (0 == strcmp(n->string, "on"))
                         continue;                          continue;
                 if (xstrcmp(n->string, "off"))                  if (0 == strcmp(n->string, "off"))
                         continue;                          continue;
                 break;                  break;
         }          }
Line 1266  post_root(POST_ARGS)
Line 1306  post_root(POST_ARGS)
 {  {
   
         if (NULL == mdoc->first->child)          if (NULL == mdoc->first->child)
                 return(merr(mdoc, ENODATA));                  return(verr(mdoc, ENODATA));
         if (SEC_PROLOGUE == mdoc->lastnamed)          if ( ! (MDOC_PBODY & mdoc->flags))
                 return(merr(mdoc, ENOPROLOGUE));                  return(verr(mdoc, ENOPROLOGUE));
   
         if (MDOC_BLOCK != mdoc->first->child->type)          if (MDOC_BLOCK != mdoc->first->child->type)
                 return(merr(mdoc, ENODATA));                  return(verr(mdoc, ENODATA));
         if (MDOC_Sh != mdoc->first->child->tok)          if (MDOC_Sh != mdoc->first->child->tok)
                 return(merr(mdoc, ENODATA));                  return(verr(mdoc, ENODATA));
   
         return(1);          return(1);
 }  }
Line 1285  post_st(POST_ARGS)
Line 1325  post_st(POST_ARGS)
   
         if (mdoc_a2st(mdoc->last->child->string))          if (mdoc_a2st(mdoc->last->child->string))
                 return(1);                  return(1);
         return(mwarn(mdoc, WBADSTAND));          return(vwarn(mdoc, WBADSTAND));
 }  }
   
   
Line 1317  post_sh_body(POST_ARGS)
Line 1357  post_sh_body(POST_ARGS)
          */           */
   
         if (NULL == (n = mdoc->last->child))          if (NULL == (n = mdoc->last->child))
                 return(mwarn(mdoc, WNAMESECINC));                  return(vwarn(mdoc, WNAMESECINC));
   
         for ( ; n && n->next; n = n->next) {          for ( ; n && n->next; n = n->next) {
                 if (MDOC_ELEM == n->type && MDOC_Nm == n->tok)                  if (MDOC_ELEM == n->type && MDOC_Nm == n->tok)
                         continue;                          continue;
                 if (MDOC_TEXT == n->type)                  if (MDOC_TEXT == n->type)
                         continue;                          continue;
                 if ( ! mwarn(mdoc, WNAMESECINC))                  if ( ! vwarn(mdoc, WNAMESECINC))
                         return(0);                          return(0);
         }          }
   
         if (MDOC_ELEM == n->type && MDOC_Nd == n->tok)          if (MDOC_ELEM == n->type && MDOC_Nd == n->tok)
                 return(1);                  return(1);
         return(mwarn(mdoc, WNAMESECINC));          return(vwarn(mdoc, WNAMESECINC));
 }  }
   
   
 static int  static int
 post_sh_head(POST_ARGS)  post_sh_head(POST_ARGS)
 {  {
         char              buf[64];          char                    buf[64];
         enum mdoc_sec     sec;          enum mdoc_sec           sec;
           const struct mdoc_node *n;
   
         /*          /*
          * Process a new section.  Sections are either "named" or           * Process a new section.  Sections are either "named" or
Line 1347  post_sh_head(POST_ARGS)
Line 1388  post_sh_head(POST_ARGS)
          * certain manual sections.           * certain manual sections.
          */           */
   
         assert(MDOC_Sh == mdoc->last->tok);          buf[0] = 0;
   
         (void)xstrlcpys(buf, mdoc->last->child, sizeof(buf));          for (n = mdoc->last->child; n; n = n->next) {
                   /* XXX - copied from compact(). */
                   assert(MDOC_TEXT == n->type);
   
                   if (strlcat(buf, n->string, 64) >= 64)
                           return(nerr(mdoc, n, ETOOLONG));
                   if (NULL == n->next)
                           continue;
                   if (strlcat(buf, " ", 64) >= 64)
                           return(nerr(mdoc, n, ETOOLONG));
           }
   
         sec = mdoc_atosec(buf);          sec = mdoc_atosec(buf);
   
         /* The NAME section should always be first. */          /*
            * Check: NAME should always be first, CUSTOM has no roles,
            * non-CUSTOM has a conventional order to be followed.
            */
   
         if (SEC_BODY == mdoc->lastnamed && SEC_NAME != sec)          if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed)
                 return(mwarn(mdoc, WSECOOO));                  return(verr(mdoc, ESECNAME));
         if (SEC_CUSTOM == sec)          if (SEC_CUSTOM == sec)
                 return(1);                  return(1);
   
         /* Check for repeated or out-of-order sections. */  
   
         if (sec == mdoc->lastnamed)          if (sec == mdoc->lastnamed)
                 return(mwarn(mdoc, WSECREP));                  return(vwarn(mdoc, WSECREP));
         if (sec < mdoc->lastnamed)          if (sec < mdoc->lastnamed)
                 return(mwarn(mdoc, WSECOOO));                  return(vwarn(mdoc, WSECOOO));
   
         /* Check particular section/manual section conventions. */          /*
            * Check particular section/manual conventions.  LIBRARY can
            * only occur in msec 2, 3 (TODO: are there more of these?).
            */
   
         switch (sec) {          switch (sec) {
         case (SEC_LIBRARY):          case (SEC_LIBRARY):
Line 1377  post_sh_head(POST_ARGS)
Line 1431  post_sh_head(POST_ARGS)
                 case (3):                  case (3):
                         break;                          break;
                 default:                  default:
                         return(mwarn(mdoc, WWRONGMSEC));                          return(vwarn(mdoc, WWRONGMSEC));
                 }                  }
                 break;                  break;
         default:          default:

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.13

CVSweb