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

Diff for /mandoc/man_macro.c between version 1.78 and 1.87

version 1.78, 2013/12/22 13:25:17 version 1.87, 2014/07/30 23:01:39
Line 2 
Line 2 
 /*  /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>   * Copyright (c) 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
    * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
  *   *
  * 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 above   * purpose with or without fee is hereby granted, provided that the above
Line 39  static int   blk_close(MACRO_PROT_ARGS);
Line 40  static int   blk_close(MACRO_PROT_ARGS);
 static  int              blk_exp(MACRO_PROT_ARGS);  static  int              blk_exp(MACRO_PROT_ARGS);
 static  int              blk_imp(MACRO_PROT_ARGS);  static  int              blk_imp(MACRO_PROT_ARGS);
 static  int              in_line_eoln(MACRO_PROT_ARGS);  static  int              in_line_eoln(MACRO_PROT_ARGS);
 static  int              man_args(struct man *, int,  static  int              man_args(struct man *, int,
                                 int *, char *, char **);                                  int *, char *, char **);
   
 static  int              rew_scope(enum man_type,  static  int              rew_scope(enum man_type,
                                 struct man *, enum mant);                                  struct man *, enum mant);
 static  enum rew         rew_dohalt(enum mant, enum man_type,  static  enum rew         rew_dohalt(enum mant, enum man_type,
                                 const struct man_node *);                                  const struct man_node *);
 static  enum rew         rew_block(enum mant, enum man_type,  static  enum rew         rew_block(enum mant, enum man_type,
                                 const struct man_node *);                                  const struct man_node *);
 static  void             rew_warn(struct man *,  
                                 struct man_node *, enum mandocerr);  
   
 const   struct man_macro __man_macros[MAN_MAX] = {  const   struct man_macro __man_macros[MAN_MAX] = {
         { in_line_eoln, MAN_NSCOPED }, /* br */          { in_line_eoln, MAN_NSCOPED }, /* br */
Line 90  const struct man_macro __man_macros[MAN_MAX] = {
Line 89  const struct man_macro __man_macros[MAN_MAX] = {
         { in_line_eoln, MAN_BSCOPE }, /* EE */          { in_line_eoln, MAN_BSCOPE }, /* EE */
         { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* UR */          { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* UR */
         { blk_close, 0 }, /* UE */          { blk_close, 0 }, /* UE */
           { in_line_eoln, 0 }, /* ll */
 };  };
   
 const   struct man_macro * const man_macros = __man_macros;  const   struct man_macro * const man_macros = __man_macros;
   
   
 /*  
  * Warn when "n" is an explicit non-roff macro.  
  */  
 static void  
 rew_warn(struct man *man, struct man_node *n, enum mandocerr er)  
 {  
   
         if (er == MANDOCERR_MAX || MAN_BLOCK != n->type)  
                 return;  
         if (MAN_VALID & n->flags)  
                 return;  
         if ( ! (MAN_EXPLICIT & man_macros[n->tok].flags))  
                 return;  
   
         assert(er < MANDOCERR_FATAL);  
         man_nmsg(man, n, er);  
 }  
   
   
 /*  
  * Rewind scope.  If a code "er" != MANDOCERR_MAX has been provided, it  
  * will be used if an explicit block scope is being closed out.  
  */  
 int  int
 man_unscope(struct man *man, const struct man_node *to,  man_unscope(struct man *man, const struct man_node *to)
                 enum mandocerr er)  
 {  {
         struct man_node *n;          struct man_node *n;
   
         assert(to);  
   
         man->next = MAN_NEXT_SIBLING;          man->next = MAN_NEXT_SIBLING;
           to = to->parent;
           n = man->last;
           while (n != to) {
   
         /* LINTED */                  /* Reached the end of the document? */
         while (man->last != to) {  
                   if (to == NULL && ! (n->flags & MAN_VALID)) {
                           if (man->flags & (MAN_BLINE | MAN_ELINE) &&
                               man_macros[n->tok].flags & MAN_SCOPED) {
                                   mandoc_vmsg(MANDOCERR_BLK_LINE,
                                       man->parse, n->line, n->pos,
                                       "EOF breaks %s",
                                       man_macronames[n->tok]);
                                   if (man->flags & MAN_ELINE)
                                           man->flags &= ~MAN_ELINE;
                                   else {
                                           assert(n->type == MAN_HEAD);
                                           n = n->parent;
                                           man->flags &= ~MAN_BLINE;
                                   }
                                   man->last = n;
                                   n = n->parent;
                                   man_node_delete(man, man->last);
                                   continue;
                           }
                           if (n->type == MAN_BLOCK &&
                               man_macros[n->tok].flags & MAN_EXPLICIT)
                                   mandoc_msg(MANDOCERR_BLK_NOEND,
                                       man->parse, n->line, n->pos,
                                       man_macronames[n->tok]);
                   }
   
                 /*                  /*
                  * Save the parent here, because we may delete the                   * We might delete the man->last node
                  * man->last node in the post-validation phase and reset                   * in the post-validation phase.
                  * it to man->last->parent, causing a step in the closing                   * Save a pointer to the parent such that
                  * out to be lost.                   * we know where to continue the iteration.
                  */                   */
                 n = man->last->parent;                  man->last = n;
                 rew_warn(man, man->last, er);                  n = n->parent;
                 if ( ! man_valid_post(man))                  if ( ! man_valid_post(man))
                         return(0);                          return(0);
                 man->last = n;  
                 assert(man->last);  
         }          }
   
         rew_warn(man, man->last, er);  
         if ( ! man_valid_post(man))  
                 return(0);  
   
         return(1);          return(1);
 }  }
   
   
 static enum rew  static enum rew
 rew_block(enum mant ntok, enum man_type type, const struct man_node *n)  rew_block(enum mant ntok, enum man_type type, const struct man_node *n)
 {  {
   
         if (MAN_BLOCK == type && ntok == n->parent->tok &&          if (MAN_BLOCK == type && ntok == n->parent->tok &&
                         MAN_BODY == n->parent->type)              MAN_BODY == n->parent->type)
                 return(REW_REWIND);                  return(REW_REWIND);
         return(ntok == n->tok ? REW_HALT : REW_NOHALT);          return(ntok == n->tok ? REW_HALT : REW_NOHALT);
 }  }
   
   
 /*  /*
  * There are three scope levels: scoped to the root (all), scoped to the   * There are three scope levels: scoped to the root (all), scoped to the
  * section (all less sections), and scoped to subsections (all less   * section (all less sections), and scoped to subsections (all less
  * sections and subsections).   * sections and subsections).
  */   */
 static enum rew  static enum rew
 rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n)  rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n)
 {  {
         enum rew         c;          enum rew         c;
Line 195  rew_dohalt(enum mant tok, enum man_type type, const st
Line 189  rew_dohalt(enum mant tok, enum man_type type, const st
                         return(REW_REWIND);                          return(REW_REWIND);
         }          }
   
         /*          /*
          * Next follow the implicit scope-smashings as defined by man.7:           * Next follow the implicit scope-smashings as defined by man.7:
          * section, sub-section, etc.           * section, sub-section, etc.
          */           */
   
         switch (tok) {          switch (tok) {
         case (MAN_SH):          case MAN_SH:
                 break;                  break;
         case (MAN_SS):          case MAN_SS:
                 /* Rewind to a section, if a block. */                  /* Rewind to a section, if a block. */
                 if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))                  if (REW_NOHALT != (c = rew_block(MAN_SH, type, n)))
                         return(c);                          return(c);
                 break;                  break;
         case (MAN_RS):          case MAN_RS:
                 /* Preserve empty paragraphs before RS. */                  /* Preserve empty paragraphs before RS. */
                 if (0 == n->nchild && (MAN_P == n->tok ||                  if (0 == n->nchild && (MAN_P == n->tok ||
                     MAN_PP == n->tok || MAN_LP == n->tok))                      MAN_PP == n->tok || MAN_LP == n->tok))
Line 236  rew_dohalt(enum mant tok, enum man_type type, const st
Line 230  rew_dohalt(enum mant tok, enum man_type type, const st
         return(REW_NOHALT);          return(REW_NOHALT);
 }  }
   
   
 /*  /*
  * Rewinding entails ascending the parse tree until a coherent point,   * Rewinding entails ascending the parse tree until a coherent point,
  * for example, the `SH' macro will close out any intervening `SS'   * for example, the `SH' macro will close out any intervening `SS'
Line 248  rew_scope(enum man_type type, struct man *man, enum ma
Line 241  rew_scope(enum man_type type, struct man *man, enum ma
         struct man_node *n;          struct man_node *n;
         enum rew         c;          enum rew         c;
   
         /* LINTED */  
         for (n = man->last; n; n = n->parent) {          for (n = man->last; n; n = n->parent) {
                 /*                  /*
                  * Whether we should stop immediately (REW_HALT), stop                   * Whether we should stop immediately (REW_HALT), stop
                  * and rewind until this point (REW_REWIND), or keep                   * and rewind until this point (REW_REWIND), or keep
                  * rewinding (REW_NOHALT).                   * rewinding (REW_NOHALT).
Line 262  rew_scope(enum man_type type, struct man *man, enum ma
Line 254  rew_scope(enum man_type type, struct man *man, enum ma
                         break;                          break;
         }          }
   
         /*          /*
          * Rewind until the current point.  Warn if we're a roff           * Rewind until the current point.  Warn if we're a roff
          * instruction that's mowing over explicit scopes.           * instruction that's mowing over explicit scopes.
          */           */
         assert(n);          assert(n);
   
         return(man_unscope(man, n, MANDOCERR_MAX));          return(man_unscope(man, n));
 }  }
   
   
 /*  /*
  * Close out a generic explicit macro.   * Close out a generic explicit macro.
  */   */
 /* ARGSUSED */  
 int  int
 blk_close(MACRO_PROT_ARGS)  blk_close(MACRO_PROT_ARGS)
 {  {
         enum mant                ntok;          enum mant                ntok;
         const struct man_node   *nn;          const struct man_node   *nn;
   
         switch (tok) {          switch (tok) {
         case (MAN_RE):          case MAN_RE:
                 ntok = MAN_RS;                  ntok = MAN_RS;
                 break;                  break;
         case (MAN_UE):          case MAN_UE:
                 ntok = MAN_UR;                  ntok = MAN_UR;
                 break;                  break;
         default:          default:
Line 299  blk_close(MACRO_PROT_ARGS)
Line 290  blk_close(MACRO_PROT_ARGS)
                         break;                          break;
   
         if (NULL == nn) {          if (NULL == nn) {
                 man_pmsg(man, line, ppos, MANDOCERR_NOSCOPE);                  mandoc_msg(MANDOCERR_BLK_NOTOPEN, man->parse,
                       line, ppos, man_macronames[tok]);
                 if ( ! rew_scope(MAN_BLOCK, man, MAN_PP))                  if ( ! rew_scope(MAN_BLOCK, man, MAN_PP))
                         return(0);                          return(0);
         } else          } else
                 man_unscope(man, nn, MANDOCERR_MAX);                  man_unscope(man, nn);
   
         return(1);          return(1);
 }  }
   
   
 /* ARGSUSED */  
 int  int
 blk_exp(MACRO_PROT_ARGS)  blk_exp(MACRO_PROT_ARGS)
 {  {
Line 342  blk_exp(MACRO_PROT_ARGS)
Line 332  blk_exp(MACRO_PROT_ARGS)
                 if (n->tok != tok)                  if (n->tok != tok)
                         continue;                          continue;
                 assert(MAN_HEAD == n->type);                  assert(MAN_HEAD == n->type);
                 man_unscope(man, n, MANDOCERR_MAX);                  man_unscope(man, n);
                 break;                  break;
         }          }
   
         return(man_body_alloc(man, line, ppos, tok));          return(man_body_alloc(man, line, ppos, tok));
 }  }
   
   
   
 /*  /*
  * Parse an implicit-block macro.  These contain a MAN_HEAD and a   * Parse an implicit-block macro.  These contain a MAN_HEAD and a
  * MAN_BODY contained within a MAN_BLOCK.  Rules for closing out other   * MAN_BODY contained within a MAN_BLOCK.  Rules for closing out other
  * scopes, such as `SH' closing out an `SS', are defined in the rew   * scopes, such as `SH' closing out an `SS', are defined in the rew
  * routines.   * routines.
  */   */
 /* ARGSUSED */  
 int  int
 blk_imp(MACRO_PROT_ARGS)  blk_imp(MACRO_PROT_ARGS)
 {  {
Line 409  blk_imp(MACRO_PROT_ARGS)
Line 396  blk_imp(MACRO_PROT_ARGS)
         return(man_body_alloc(man, line, ppos, tok));          return(man_body_alloc(man, line, ppos, tok));
 }  }
   
   
 /* ARGSUSED */  
 int  int
 in_line_eoln(MACRO_PROT_ARGS)  in_line_eoln(MACRO_PROT_ARGS)
 {  {
Line 437  in_line_eoln(MACRO_PROT_ARGS)
Line 422  in_line_eoln(MACRO_PROT_ARGS)
          */           */
   
         if (n != man->last &&          if (n != man->last &&
             mandoc_eos(man->last->string, strlen(man->last->string), 0))              mandoc_eos(man->last->string, strlen(man->last->string)))
                 man->last->flags |= MAN_EOS;                  man->last->flags |= MAN_EOS;
   
         /*          /*
Line 450  in_line_eoln(MACRO_PROT_ARGS)
Line 435  in_line_eoln(MACRO_PROT_ARGS)
                 assert( ! (MAN_NSCOPED & man_macros[tok].flags));                  assert( ! (MAN_NSCOPED & man_macros[tok].flags));
                 man->flags |= MAN_ELINE;                  man->flags |= MAN_ELINE;
                 return(1);                  return(1);
         }  
   
         /* Set ignorable context, if applicable. */  
   
         if (MAN_NSCOPED & man_macros[tok].flags) {  
                 assert( ! (MAN_SCOPED & man_macros[tok].flags));  
                 man->flags |= MAN_ILINE;  
         }          }
   
         assert(MAN_ROOT != man->last->type);          assert(MAN_ROOT != man->last->type);
         man->next = MAN_NEXT_SIBLING;          man->next = MAN_NEXT_SIBLING;
   
         /*          /*
          * Rewind our element scope.  Note that when TH is pruned, we'll           * Rewind our element scope.  Note that when TH is pruned, we'll
          * be back at the root, so make sure that we don't clobber as           * be back at the root, so make sure that we don't clobber as
Line 480  in_line_eoln(MACRO_PROT_ARGS)
Line 458  in_line_eoln(MACRO_PROT_ARGS)
         assert(man->last);          assert(man->last);
   
         /*          /*
          * Same here regarding whether we're back at the root.           * Same here regarding whether we're back at the root.
          */           */
   
         if (man->last->type != MAN_ROOT && ! man_valid_post(man))          if (man->last->type != MAN_ROOT && ! man_valid_post(man))
Line 494  int
Line 472  int
 man_macroend(struct man *man)  man_macroend(struct man *man)
 {  {
   
         return(man_unscope(man, man->first, MANDOCERR_SCOPEEXIT));          return(man_unscope(man, man->first));
 }  }
   
 static int  static int

Legend:
Removed from v.1.78  
changed lines
  Added in v.1.87

CVSweb