[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.128 and 1.131

version 1.128, 2010/11/29 15:45:15 version 1.131, 2010/11/30 12:35:10
Line 36 
Line 36 
 #define PRE_ARGS  struct mdoc *mdoc, struct mdoc_node *n  #define PRE_ARGS  struct mdoc *mdoc, struct mdoc_node *n
 #define POST_ARGS struct mdoc *mdoc  #define POST_ARGS struct mdoc *mdoc
   
   #define NUMSIZ    32
   #define DATESIZ   32
   
 enum    check_ineq {  enum    check_ineq {
         CHECK_LT,          CHECK_LT,
         CHECK_GT,          CHECK_GT,
Line 84  static int  post_an(POST_ARGS);
Line 87  static int  post_an(POST_ARGS);
 static  int      post_at(POST_ARGS);  static  int      post_at(POST_ARGS);
 static  int      post_bf(POST_ARGS);  static  int      post_bf(POST_ARGS);
 static  int      post_bl(POST_ARGS);  static  int      post_bl(POST_ARGS);
   static  int      post_bl_block(POST_ARGS);
   static  int      post_bl_block_width(POST_ARGS);
   static  int      post_bl_block_tag(POST_ARGS);
 static  int      post_bl_head(POST_ARGS);  static  int      post_bl_head(POST_ARGS);
 static  int      post_defaults(POST_ARGS);  static  int      post_defaults(POST_ARGS);
 static  int      post_literal(POST_ARGS);  static  int      post_literal(POST_ARGS);
Line 193  const struct valids mdoc_valids[MDOC_MAX] = {
Line 199  const struct valids mdoc_valids[MDOC_MAX] = {
         { NULL, posts_nm },                     /* Nm */          { NULL, posts_nm },                     /* Nm */
         { NULL, posts_wline },                  /* Op */          { NULL, posts_wline },                  /* Op */
         { NULL, NULL },                         /* Ot */          { NULL, NULL },                         /* Ot */
         { NULL, NULL },                         /* Pa */          { NULL, posts_defaults },               /* Pa */
         { pres_rv, NULL },                      /* Rv */          { pres_rv, NULL },                      /* Rv */
         { NULL, posts_st },                     /* St */          { NULL, posts_st },                     /* St */
         { NULL, NULL },                         /* Va */          { NULL, NULL },                         /* Va */
Line 1154  post_vt(POST_ARGS)
Line 1160  post_vt(POST_ARGS)
 static int  static int
 post_nm(POST_ARGS)  post_nm(POST_ARGS)
 {  {
           struct mdoc_node *nn;
           char              buf[BUFSIZ];
   
         if (mdoc->last->child)          /* If no child specified, make sure we have the meta name. */
   
           if (NULL == mdoc->last->child && NULL == mdoc->meta.name) {
                   mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NONAME);
                 return(1);                  return(1);
         if (mdoc->meta.name)          } else if (mdoc->meta.name)
                 return(1);                  return(1);
         return(mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NONAME));  
           /* If no meta name, set it from the child. */
   
           buf[0] = '\0';
   
           for (nn = mdoc->last->child; nn; nn = nn->next) {
                   /* XXX - copied from concat(). */
                   assert(MDOC_TEXT == nn->type);
   
                   if (strlcat(buf, nn->string, BUFSIZ) >= BUFSIZ) {
                           mdoc_nmsg(mdoc, nn, MANDOCERR_MEM);
                           return(0);
                   }
   
                   if (NULL == nn->next)
                           continue;
   
                   if (strlcat(buf, " ", BUFSIZ) >= BUFSIZ) {
                           mdoc_nmsg(mdoc, nn, MANDOCERR_MEM);
                           return(0);
                   }
           }
   
           mdoc->meta.name = mandoc_strdup(buf);
           return(1);
 }  }
   
 static int  static int
Line 1186  post_defaults(POST_ARGS)
Line 1221  post_defaults(POST_ARGS)
   
         /*          /*
          * The `Ar' defaults to "file ..." if no value is provided as an           * The `Ar' defaults to "file ..." if no value is provided as an
          * argument; the `Mt' macro uses "~"; the `Li' just gets an           * argument; the `Mt' and `Pa' macros use "~"; the `Li' just
          * empty string.           * gets an empty string.
          */           */
   
         if (mdoc->last->child)          if (mdoc->last->child)
Line 1213  post_defaults(POST_ARGS)
Line 1248  post_defaults(POST_ARGS)
                 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, ""))                  if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, ""))
                         return(0);                          return(0);
                 break;                  break;
           case (MDOC_Pa):
                   /* FALLTHROUGH */
         case (MDOC_Mt):          case (MDOC_Mt):
                 if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "~"))                  if ( ! mdoc_word_alloc(mdoc, nn->line, nn->pos, "~"))
                         return(0);                          return(0);
Line 1367  post_it(POST_ARGS)
Line 1404  post_it(POST_ARGS)
         return(1);          return(1);
 }  }
   
   
 static int  static int
 post_bl_head(POST_ARGS)  post_bl_block(POST_ARGS)
 {  {
         struct mdoc_node *n;          struct mdoc_node *n;
   
         assert(mdoc->last->parent);          /*
         n = mdoc->last->parent;           * These are fairly complicated, so we've broken them into two
            * functions.  post_bl_block_tag() is called when a -tag is
            * specified, but no -width (it must be guessed).  The second
            * when a -width is specified (macro indicators must be
            * rewritten into real lengths).
            */
   
         if (LIST_column == n->data.Bl->type) {          n = mdoc->last;
                 if (n->data.Bl->ncols && mdoc->last->nchild) {  
                         mdoc_nmsg(mdoc, n, MANDOCERR_COLUMNS);          if (LIST_tag == n->data.Bl->type &&
                           NULL == n->data.Bl->width) {
                   if ( ! post_bl_block_tag(mdoc))
                         return(0);                          return(0);
           } else if (NULL != n->data.Bl->width) {
                   if ( ! post_bl_block_width(mdoc))
                           return(0);
           } else
                   return(1);
   
           assert(n->data.Bl->width);
           return(1);
   }
   
   static int
   post_bl_block_width(POST_ARGS)
   {
           size_t            width;
           int               i;
           enum mdoct        tok;
           struct mdoc_node *n;
           char              buf[NUMSIZ];
   
           n = mdoc->last;
   
           /*
            * Calculate the real width of a list from the -width string,
            * which may contain a macro (with a known default width), a
            * literal string, or a scaling width.
            *
            * If the value to -width is a macro, then we re-write it to be
            * the macro's width as set in share/tmac/mdoc/doc-common.
            */
   
           if (0 == strcmp(n->data.Bl->width, "Ds"))
                   width = 6;
           else if (MDOC_MAX == (tok = mdoc_hash_find(n->data.Bl->width)))
                   return(1);
           else if (0 == (width = mdoc_macro2len(tok)))
                   return(mdoc_nmsg(mdoc, n, MANDOCERR_BADWIDTH));
   
           /* The value already exists: free and reallocate it. */
   
           assert(n->args);
   
           for (i = 0; i < (int)n->args->argc; i++)
                   if (MDOC_Width == n->args->argv[i].arg)
                           break;
   
           assert(i < (int)n->args->argc);
   
           snprintf(buf, NUMSIZ, "%zun", width);
           free(n->args->argv[i].value[0]);
           n->args->argv[i].value[0] = mandoc_strdup(buf);
   
           /* Set our width! */
           n->data.Bl->width = n->args->argv[i].value[0];
           return(1);
   }
   
   static int
   post_bl_block_tag(POST_ARGS)
   {
           struct mdoc_node *n, *nn;
           size_t            sz, ssz;
           int               i;
           char              buf[NUMSIZ];
   
           /*
            * Calculate the -width for a `Bl -tag' list if it hasn't been
            * provided.  Uses the first head macro.  NOTE AGAIN: this is
            * ONLY if the -width argument has NOT been provided.  See
            * post_bl_block_width() for converting the -width string.
            */
   
           sz = 10;
           n = mdoc->last;
   
           for (nn = n->body->child; nn; nn = nn->next) {
                   if (MDOC_It != nn->tok)
                           continue;
   
                   assert(MDOC_BLOCK == nn->type);
                   nn = nn->head->child;
   
                   if (nn == NULL) {
                           /* No -width for .Bl and first .It is emtpy */
                           if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG))
                                   return(0);
                           break;
                 }                  }
   
                   if (MDOC_TEXT == nn->type) {
                           sz = strlen(nn->string) + 1;
                           break;
                   }
   
                   if (0 != (ssz = mdoc_macro2len(nn->tok)))
                           sz = ssz;
                   else if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG))
                           return(0);
   
                   break;
           }
   
           /* Defaults to ten ens. */
   
           snprintf(buf, NUMSIZ, "%zun", sz);
   
           /*
            * We have to dynamically add this to the macro's argument list.
            * We're guaranteed that a MDOC_Width doesn't already exist.
            */
   
           assert(n->args);
           i = (int)(n->args->argc)++;
   
           n->args->argv = mandoc_realloc(n->args->argv,
                           n->args->argc * sizeof(struct mdoc_argv));
   
           n->args->argv[i].arg = MDOC_Width;
           n->args->argv[i].line = n->line;
           n->args->argv[i].pos = n->pos;
           n->args->argv[i].sz = 1;
           n->args->argv[i].value = mandoc_malloc(sizeof(char *));
           n->args->argv[i].value[0] = mandoc_strdup(buf);
   
           /* Set our width! */
           n->data.Bl->width = n->args->argv[i].value[0];
           return(1);
   }
   
   
   static int
   post_bl_head(POST_ARGS)
   {
           struct mdoc_node *np, *nn, *nnp;
           int               i, j;
   
           if (LIST_column != mdoc->last->data.Bl->type)
                   /* FIXME: this should be ERROR class... */
                   return(hwarn_eq0(mdoc));
   
           /*
            * Convert old-style lists, where the column width specifiers
            * trail as macro parameters, to the new-style ("normal-form")
            * lists where they're argument values following -column.
            */
   
           /* First, disallow both types and allow normal-form. */
   
           /*
            * TODO: technically, we can accept both and just merge the two
            * lists, but I'll leave that for another day.
            */
   
           if (mdoc->last->data.Bl->ncols && mdoc->last->nchild) {
                   mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_COLUMNS);
                   return(0);
           } else if (NULL == mdoc->last->child)
                 return(1);                  return(1);
   
           np = mdoc->last->parent;
           assert(np->args);
   
           for (j = 0; j < (int)np->args->argc; j++)
                   if (MDOC_Column == np->args->argv[j].arg)
                           break;
   
           assert(j < (int)np->args->argc);
           assert(0 == np->args->argv[j].sz);
   
           /*
            * Accomodate for new-style groff column syntax.  Shuffle the
            * child nodes, all of which must be TEXT, as arguments for the
            * column field.  Then, delete the head children.
            */
   
           np->args->argv[j].sz = (size_t)mdoc->last->nchild;
           np->args->argv[j].value = mandoc_malloc
                   ((size_t)mdoc->last->nchild * sizeof(char *));
   
           mdoc->last->data.Bl->ncols = np->args->argv[j].sz;
           mdoc->last->data.Bl->cols = (const char **)np->args->argv[j].value;
   
           for (i = 0, nn = mdoc->last->child; nn; i++) {
                   np->args->argv[j].value[i] = nn->string;
                   nn->string = NULL;
                   nnp = nn;
                   nn = nn->next;
                   mdoc_node_delete(NULL, nnp);
         }          }
   
         /* FIXME: should be ERROR class. */          mdoc->last->nchild = 0;
         return(hwarn_eq0(mdoc));          mdoc->last->child = NULL;
   
           return(1);
 }  }
   
   
 static int  static int
 post_bl(POST_ARGS)  post_bl(POST_ARGS)
 {  {
Line 1396  post_bl(POST_ARGS)
Line 1625  post_bl(POST_ARGS)
   
         if (MDOC_HEAD == mdoc->last->type)          if (MDOC_HEAD == mdoc->last->type)
                 return(post_bl_head(mdoc));                  return(post_bl_head(mdoc));
           if (MDOC_BLOCK == mdoc->last->type)
                   return(post_bl_block(mdoc));
         if (MDOC_BODY != mdoc->last->type)          if (MDOC_BODY != mdoc->last->type)
                 return(1);                  return(1);
         if (NULL == mdoc->last->child)          if (NULL == mdoc->last->child)

Legend:
Removed from v.1.128  
changed lines
  Added in v.1.131

CVSweb