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

Diff for /mandoc/mdoc_macro.c between version 1.209 and 1.230

version 1.209, 2016/08/20 17:59:34 version 1.230, 2018/12/31 04:55:46
Line 1 
Line 1 
 /*      $Id$ */  /*      $Id$ */
 /*  /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>   * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010, 2012-2016 Ingo Schwarze <schwarze@openbsd.org>   * Copyright (c) 2010, 2012-2018 Ingo Schwarze <schwarze@openbsd.org>
  *   *
  * 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 46  static void  phrase_ta(MACRO_PROT_ARGS);
Line 46  static void  phrase_ta(MACRO_PROT_ARGS);
 static  void            append_delims(struct roff_man *, int, int *, char *);  static  void            append_delims(struct roff_man *, int, int *, char *);
 static  void            dword(struct roff_man *, int, int, const char *,  static  void            dword(struct roff_man *, int, int, const char *,
                                 enum mdelim, int);                                  enum mdelim, int);
 static  int             find_pending(struct roff_man *, int, int, int,  static  int             find_pending(struct roff_man *, enum roff_tok,
                                 struct roff_node *);                                  int, int, struct roff_node *);
 static  int             lookup(struct roff_man *, int, int, int, const char *);  static  int             lookup(struct roff_man *, int, int, int, const char *);
 static  int             macro_or_word(MACRO_PROT_ARGS, int);  static  int             macro_or_word(MACRO_PROT_ARGS, char *, int);
 static  int             parse_rest(struct roff_man *, int, int, int *, char *);  static  void            break_intermediate(struct roff_node *,
 static  int             rew_alt(int);                                  struct roff_node *);
 static  void            rew_elem(struct roff_man *, int);  static  int             parse_rest(struct roff_man *, enum roff_tok,
                                   int, int *, char *);
   static  enum roff_tok   rew_alt(enum roff_tok);
   static  void            rew_elem(struct roff_man *, enum roff_tok);
 static  void            rew_last(struct roff_man *, const struct roff_node *);  static  void            rew_last(struct roff_man *, const struct roff_node *);
 static  void            rew_pending(struct roff_man *,  static  void            rew_pending(struct roff_man *,
                                 const struct roff_node *);                                  const struct roff_node *);
   
 const   struct mdoc_macro __mdoc_macros[MDOC_MAX] = {  static const struct mdoc_macro mdoc_macros[MDOC_MAX - MDOC_Dd] = {
         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ap */  
         { in_line_eoln, MDOC_PROLOGUE }, /* Dd */          { in_line_eoln, MDOC_PROLOGUE }, /* Dd */
         { in_line_eoln, MDOC_PROLOGUE }, /* Dt */          { in_line_eoln, MDOC_PROLOGUE }, /* Dt */
         { in_line_eoln, MDOC_PROLOGUE }, /* Os */          { in_line_eoln, MDOC_PROLOGUE }, /* Os */
Line 74  const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
Line 76  const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
         { blk_full, MDOC_PARSED | MDOC_JOIN }, /* It */          { blk_full, MDOC_PARSED | MDOC_JOIN }, /* It */
         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */          { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
         { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* An */          { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* An */
           { in_line_argn, MDOC_CALLABLE | MDOC_PARSED |
                           MDOC_IGNDELIM | MDOC_JOIN }, /* Ap */
         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */          { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
         { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Cd */          { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Cd */
         { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */          { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
Line 194  const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
Line 198  const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
         { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* En */          { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* En */
         { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */          { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */
         { in_line_eoln, MDOC_JOIN }, /* %Q */          { in_line_eoln, MDOC_JOIN }, /* %Q */
         { in_line_eoln, 0 }, /* br */  
         { in_line_eoln, 0 }, /* sp */  
         { in_line_eoln, 0 }, /* %U */          { in_line_eoln, 0 }, /* %U */
         { phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */          { phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */
         { in_line_eoln, MDOC_PROLOGUE }, /* ll */  
 };  };
   
 const   struct mdoc_macro * const mdoc_macros = __mdoc_macros;  
   
   const struct mdoc_macro *
   mdoc_macro(enum roff_tok tok)
   {
           assert(tok >= MDOC_Dd && tok < MDOC_MAX);
           return mdoc_macros + (tok - MDOC_Dd);
   }
   
 /*  /*
  * This is called at the end of parsing.  It must traverse up the tree,   * This is called at the end of parsing.  It must traverse up the tree,
Line 216  mdoc_endparse(struct roff_man *mdoc)
Line 222  mdoc_endparse(struct roff_man *mdoc)
   
         /* Scan for open explicit scopes. */          /* Scan for open explicit scopes. */
   
         n = mdoc->last->flags & MDOC_VALID ?          n = mdoc->last->flags & NODE_VALID ?
             mdoc->last->parent : mdoc->last;              mdoc->last->parent : mdoc->last;
   
         for ( ; n; n = n->parent)          for ( ; n; n = n->parent)
                 if (n->type == ROFFT_BLOCK &&                  if (n->type == ROFFT_BLOCK &&
                     mdoc_macros[n->tok].flags & MDOC_EXPLICIT)                      mdoc_macro(n->tok)->flags & MDOC_EXPLICIT)
                         mandoc_msg(MANDOCERR_BLK_NOEND, mdoc->parse,                          mandoc_msg(MANDOCERR_BLK_NOEND,
                             n->line, n->pos, mdoc_macronames[n->tok]);                              n->line, n->pos, "%s", roff_name[n->tok]);
   
         /* Rewind to the first. */          /* Rewind to the first. */
   
         rew_last(mdoc, mdoc->first);          rew_last(mdoc, mdoc->meta.first);
         mdoc_state_reset(mdoc);  
 }  }
   
 /*  /*
Line 238  mdoc_endparse(struct roff_man *mdoc)
Line 243  mdoc_endparse(struct roff_man *mdoc)
 static int  static int
 lookup(struct roff_man *mdoc, int from, int line, int ppos, const char *p)  lookup(struct roff_man *mdoc, int from, int line, int ppos, const char *p)
 {  {
         int      res;          enum roff_tok    res;
   
         if (mdoc->flags & MDOC_PHRASEQF) {          if (mdoc->flags & MDOC_PHRASEQF) {
                 mdoc->flags &= ~MDOC_PHRASEQF;                  mdoc->flags &= ~MDOC_PHRASEQF;
                 return TOKEN_NONE;                  return TOKEN_NONE;
         }          }
         if (from == TOKEN_NONE || mdoc_macros[from].flags & MDOC_PARSED) {          if (from == TOKEN_NONE || mdoc_macro(from)->flags & MDOC_PARSED) {
                 res = mdoc_hash_find(p);                  res = roffhash_find(mdoc->mdocmac, p, 0);
                 if (res != TOKEN_NONE) {                  if (res != TOKEN_NONE) {
                         if (mdoc_macros[res].flags & MDOC_CALLABLE)                          if (mdoc_macro(res)->flags & MDOC_CALLABLE)
                                 return res;                                  return res;
                         if (res != MDOC_br && res != MDOC_sp && res != MDOC_ll)                          mandoc_msg(MANDOCERR_MACRO_CALL, line, ppos, "%s", p);
                                 mandoc_msg(MANDOCERR_MACRO_CALL,  
                                     mdoc->parse, line, ppos, p);  
                 }                  }
         }          }
         return TOKEN_NONE;          return TOKEN_NONE;
Line 264  static void
Line 267  static void
 rew_last(struct roff_man *mdoc, const struct roff_node *to)  rew_last(struct roff_man *mdoc, const struct roff_node *to)
 {  {
   
         if (to->flags & MDOC_VALID)          if (to->flags & NODE_VALID)
                 return;                  return;
   
         while (mdoc->last != to) {          while (mdoc->last != to) {
                 mdoc_state(mdoc, mdoc->last);                  mdoc_state(mdoc, mdoc->last);
                 mdoc->last->flags |= MDOC_VALID | MDOC_ENDED;                  mdoc->last->flags |= NODE_VALID | NODE_ENDED;
                 mdoc->last = mdoc->last->parent;                  mdoc->last = mdoc->last->parent;
         }          }
         mdoc_state(mdoc, mdoc->last);          mdoc_state(mdoc, mdoc->last);
         mdoc->last->flags |= MDOC_VALID | MDOC_ENDED;          mdoc->last->flags |= NODE_VALID | NODE_ENDED;
         mdoc->next = ROFF_NEXT_SIBLING;          mdoc->next = ROFF_NEXT_SIBLING;
 }  }
   
Line 298  rew_pending(struct roff_man *mdoc, const struct roff_n
Line 301  rew_pending(struct roff_man *mdoc, const struct roff_n
                         default:                          default:
                                 return;                                  return;
                         }                          }
                         if ( ! (n->flags & MDOC_BROKEN))                          if ( ! (n->flags & NODE_BROKEN))
                                 return;                                  return;
                 } else                  } else
                         n = mdoc->last;                          n = mdoc->last;
Line 309  rew_pending(struct roff_man *mdoc, const struct roff_n
Line 312  rew_pending(struct roff_man *mdoc, const struct roff_n
   
                         if (n->type == ROFFT_BLOCK ||                          if (n->type == ROFFT_BLOCK ||
                             n->type == ROFFT_HEAD) {                              n->type == ROFFT_HEAD) {
                                 if (n->flags & MDOC_ENDED)                                  if (n->flags & NODE_ENDED)
                                         break;                                          break;
                                 else                                  else
                                         return;                                          return;
Line 322  rew_pending(struct roff_man *mdoc, const struct roff_n
Line 325  rew_pending(struct roff_man *mdoc, const struct roff_n
  * For a block closing macro, return the corresponding opening one.   * For a block closing macro, return the corresponding opening one.
  * Otherwise, return the macro itself.   * Otherwise, return the macro itself.
  */   */
 static int  static enum roff_tok
 rew_alt(int tok)  rew_alt(enum roff_tok tok)
 {  {
         switch (tok) {          switch (tok) {
         case MDOC_Ac:          case MDOC_Ac:
Line 364  rew_alt(int tok)
Line 367  rew_alt(int tok)
 }  }
   
 static void  static void
 rew_elem(struct roff_man *mdoc, int tok)  rew_elem(struct roff_man *mdoc, enum roff_tok tok)
 {  {
         struct roff_node *n;          struct roff_node *n;
   
Line 376  rew_elem(struct roff_man *mdoc, int tok)
Line 379  rew_elem(struct roff_man *mdoc, int tok)
         rew_last(mdoc, n);          rew_last(mdoc, n);
 }  }
   
   static void
   break_intermediate(struct roff_node *n, struct roff_node *breaker)
   {
           if (n != breaker &&
               n->type != ROFFT_BLOCK && n->type != ROFFT_HEAD &&
               (n->type != ROFFT_BODY || n->end != ENDBODY_NOT))
                   n = n->parent;
           while (n != breaker) {
                   if ( ! (n->flags & NODE_VALID))
                           n->flags |= NODE_BROKEN;
                   n = n->parent;
           }
   }
   
 /*  /*
  * If there is an open sub-block of the target requiring   * If there is an open sub-block of the target requiring
  * explicit close-out, postpone closing out the target until   * explicit close-out, postpone closing out the target until
  * the rew_pending() call closing out the sub-block.   * the rew_pending() call closing out the sub-block.
  */   */
 static int  static int
 find_pending(struct roff_man *mdoc, int tok, int line, int ppos,  find_pending(struct roff_man *mdoc, enum roff_tok tok, int line, int ppos,
         struct roff_node *target)          struct roff_node *target)
 {  {
         struct roff_node        *n;          struct roff_node        *n;
         int                      irc;          int                      irc;
   
           if (target->flags & NODE_VALID)
                   return 0;
   
         irc = 0;          irc = 0;
         for (n = mdoc->last; n != NULL && n != target; n = n->parent) {          for (n = mdoc->last; n != NULL && n != target; n = n->parent) {
                 if (n->flags & MDOC_ENDED) {                  if (n->flags & NODE_ENDED)
                         if ( ! (n->flags & MDOC_VALID))  
                                 n->flags |= MDOC_BROKEN;  
                         continue;                          continue;
                 }  
                 if (n->type == ROFFT_BLOCK &&                  if (n->type == ROFFT_BLOCK &&
                     mdoc_macros[n->tok].flags & MDOC_EXPLICIT) {                      mdoc_macro(n->tok)->flags & MDOC_EXPLICIT) {
                         irc = 1;                          irc = 1;
                         n->flags = MDOC_BROKEN;                          break_intermediate(mdoc->last, target);
                         if (target->type == ROFFT_HEAD)                          if (target->type == ROFFT_HEAD)
                                 target->flags = MDOC_ENDED;                                  target->flags |= NODE_ENDED;
                         else if ( ! (target->flags & MDOC_ENDED)) {                          else if ( ! (target->flags & NODE_ENDED)) {
                                 mandoc_vmsg(MANDOCERR_BLK_NEST,                                  mandoc_msg(MANDOCERR_BLK_NEST,
                                     mdoc->parse, line, ppos,                                      line, ppos, "%s breaks %s",
                                     "%s breaks %s", mdoc_macronames[tok],                                      roff_name[tok], roff_name[n->tok]);
                                     mdoc_macronames[n->tok]);  
                                 mdoc_endbody_alloc(mdoc, line, ppos,                                  mdoc_endbody_alloc(mdoc, line, ppos,
                                     tok, target, ENDBODY_NOSPACE);                                      tok, target);
                         }                          }
                 }                  }
         }          }
Line 444  dword(struct roff_man *mdoc, int line, int col, const 
Line 460  dword(struct roff_man *mdoc, int line, int col, const 
          */           */
   
         if (d == DELIM_OPEN)          if (d == DELIM_OPEN)
                 mdoc->last->flags |= MDOC_DELIMO;                  mdoc->last->flags |= NODE_DELIMO;
         else if (d == DELIM_CLOSE &&          else if (d == DELIM_CLOSE &&
             ! (mdoc->flags & MDOC_NODELIMC) &&              ! (mdoc->flags & MDOC_NODELIMC) &&
             mdoc->last->parent->tok != MDOC_Fd)              mdoc->last->parent->tok != MDOC_Fd)
                 mdoc->last->flags |= MDOC_DELIMC;                  mdoc->last->flags |= NODE_DELIMC;
         mdoc->flags &= ~MDOC_NODELIMC;          mdoc->flags &= ~MDOC_NODELIMC;
 }  }
   
Line 457  append_delims(struct roff_man *mdoc, int line, int *po
Line 473  append_delims(struct roff_man *mdoc, int line, int *po
 {  {
         char            *p;          char            *p;
         int              la;          int              la;
           enum margserr    ac;
   
         if (buf[*pos] == '\0')          if (buf[*pos] == '\0')
                 return;                  return;
   
         for (;;) {          for (;;) {
                 la = *pos;                  la = *pos;
                 if (mdoc_args(mdoc, line, pos, buf, TOKEN_NONE, &p) ==                  ac = mdoc_args(mdoc, line, pos, buf, TOKEN_NONE, &p);
                     ARGS_EOLN)                  if (ac == ARGS_EOLN)
                         break;                          break;
                 dword(mdoc, line, la, p, DELIM_MAX, 1);                  dword(mdoc, line, la, p, DELIM_MAX, 1);
   
Line 481  append_delims(struct roff_man *mdoc, int line, int *po
Line 498  append_delims(struct roff_man *mdoc, int line, int *po
                  */                   */
   
                 if (mandoc_eos(p, strlen(p)))                  if (mandoc_eos(p, strlen(p)))
                         mdoc->last->flags |= MDOC_EOS;                          mdoc->last->flags |= NODE_EOS;
                   if (ac == ARGS_ALLOC)
                           free(p);
         }          }
 }  }
   
Line 491  append_delims(struct roff_man *mdoc, int line, int *po
Line 510  append_delims(struct roff_man *mdoc, int line, int *po
  * Otherwise, allocate it and return 0.   * Otherwise, allocate it and return 0.
  */   */
 static int  static int
 macro_or_word(MACRO_PROT_ARGS, int parsed)  macro_or_word(MACRO_PROT_ARGS, char *p, int parsed)
 {  {
         char            *p;  
         int              ntok;          int              ntok;
   
         p = buf + ppos;          ntok = buf[ppos] == '"' || parsed == 0 ||
         ntok = TOKEN_NONE;              mdoc->flags & MDOC_PHRASELIT ? TOKEN_NONE :
         if (*p == '"')              lookup(mdoc, tok, line, ppos, p);
                 p++;  
         else if (parsed && ! (mdoc->flags & MDOC_PHRASELIT))  
                 ntok = lookup(mdoc, tok, line, ppos, p);  
   
         if (ntok == TOKEN_NONE) {          if (ntok == TOKEN_NONE) {
                 dword(mdoc, line, ppos, p, DELIM_MAX, tok == TOKEN_NONE ||                  dword(mdoc, line, ppos, p, DELIM_MAX, tok == TOKEN_NONE ||
                     mdoc_macros[tok].flags & MDOC_JOIN);                      mdoc_macro(tok)->flags & MDOC_JOIN);
                 return 0;                  return 0;
         } else {          } else {
                 if (mdoc_macros[tok].fp == in_line_eoln)                  if (tok != TOKEN_NONE &&
                       mdoc_macro(tok)->fp == in_line_eoln)
                         rew_elem(mdoc, tok);                          rew_elem(mdoc, tok);
                 mdoc_macro(mdoc, ntok, line, ppos, pos, buf);                  (*mdoc_macro(ntok)->fp)(mdoc, ntok, line, ppos, pos, buf);
                 if (tok == TOKEN_NONE)                  if (tok == TOKEN_NONE)
                         append_delims(mdoc, line, pos, buf);                          append_delims(mdoc, line, pos, buf);
                 return 1;                  return 1;
Line 532  blk_exp_close(MACRO_PROT_ARGS)
Line 548  blk_exp_close(MACRO_PROT_ARGS)
   
         int              j, lastarg, maxargs, nl, pending;          int              j, lastarg, maxargs, nl, pending;
         enum margserr    ac;          enum margserr    ac;
         int              atok, ntok;          enum roff_tok    atok, ntok;
         char            *p;          char            *p;
   
         nl = MDOC_NEWLINE & mdoc->flags;          nl = MDOC_NEWLINE & mdoc->flags;
Line 554  blk_exp_close(MACRO_PROT_ARGS)
Line 570  blk_exp_close(MACRO_PROT_ARGS)
         atok = rew_alt(tok);          atok = rew_alt(tok);
         body = NULL;          body = NULL;
         for (n = mdoc->last; n; n = n->parent) {          for (n = mdoc->last; n; n = n->parent) {
                 if (n->flags & MDOC_ENDED || n->tok != atok ||                  if (n->flags & NODE_ENDED || n->tok != atok ||
                     n->type != ROFFT_BODY || n->end != ENDBODY_NOT)                      n->type != ROFFT_BODY || n->end != ENDBODY_NOT)
                         continue;                          continue;
                 body = n;                  body = n;
Line 568  blk_exp_close(MACRO_PROT_ARGS)
Line 584  blk_exp_close(MACRO_PROT_ARGS)
   
         endbody = itblk = later = NULL;          endbody = itblk = later = NULL;
         for (n = mdoc->last; n; n = n->parent) {          for (n = mdoc->last; n; n = n->parent) {
                 if (n->flags & MDOC_ENDED) {                  if (n->flags & NODE_ENDED)
                         if ( ! (n->flags & MDOC_VALID))  
                                 n->flags |= MDOC_BROKEN;  
                         continue;                          continue;
                 }  
   
                 /*                  /*
                  * Mismatching end macros can never break anything,                   * Mismatching end macros can never break anything
                  * SYNOPSIS name blocks can never be broken,  
                  * and we only care about the breaking of BLOCKs.                   * and we only care about the breaking of BLOCKs.
                  */                   */
   
                 if (body == NULL ||                  if (body == NULL || n->type != ROFFT_BLOCK)
                     n->tok == MDOC_Nm ||  
                     n->type != ROFFT_BLOCK)  
                         continue;                          continue;
   
                   /*
                    * SYNOPSIS name blocks can not be broken themselves,
                    * but they do get broken together with a broken child.
                    */
   
                   if (n->tok == MDOC_Nm) {
                           if (later != NULL)
                                   n->flags |= NODE_BROKEN | NODE_ENDED;
                           continue;
                   }
   
                 if (n->tok == MDOC_It) {                  if (n->tok == MDOC_It) {
                         itblk = n;                          itblk = n;
                         continue;                          continue;
                 }                  }
   
                 if (atok == n->tok) {                  if (atok == n->tok) {
                         assert(body);  
   
                         /*                          /*
                          * Found the start of our own block.                           * Found the start of our own block.
Line 611  blk_exp_close(MACRO_PROT_ARGS)
Line 631  blk_exp_close(MACRO_PROT_ARGS)
                          * the scope - of the current block ends.                           * the scope - of the current block ends.
                          */                           */
   
                         mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse,                          mandoc_msg(MANDOCERR_BLK_NEST,
                             line, ppos, "%s breaks %s",                              line, ppos, "%s breaks %s",
                             mdoc_macronames[atok],                              roff_name[atok], roff_name[later->tok]);
                             mdoc_macronames[later->tok]);  
   
                         endbody = mdoc_endbody_alloc(mdoc, line, ppos,                          endbody = mdoc_endbody_alloc(mdoc, line, ppos,
                             atok, body, ENDBODY_SPACE);                              atok, body);
   
                         if (tok == MDOC_El)                          if (tok == MDOC_El)
                                 itblk->flags |= MDOC_ENDED | MDOC_BROKEN;                                  itblk->flags |= NODE_ENDED | NODE_BROKEN;
   
                         /*                          /*
                          * If a block closing macro taking arguments                           * If a block closing macro taking arguments
Line 633  blk_exp_close(MACRO_PROT_ARGS)
Line 652  blk_exp_close(MACRO_PROT_ARGS)
                         break;                          break;
                 }                  }
   
                 /* Explicit blocks close out description lines. */                  /*
                    * Explicit blocks close out description lines, but
                    * even those can get broken together with a child.
                    */
   
                 if (n->tok == MDOC_Nd) {                  if (n->tok == MDOC_Nd) {
                         rew_last(mdoc, n);                          if (later != NULL)
                                   n->flags |= NODE_BROKEN | NODE_ENDED;
                           else
                                   rew_last(mdoc, n);
                         continue;                          continue;
                 }                  }
   
                 /* Breaking an open sub block. */                  /* Breaking an open sub block. */
   
                 n->flags |= MDOC_BROKEN;                  break_intermediate(mdoc->last, body);
                   n->flags |= NODE_BROKEN;
                 if (later == NULL)                  if (later == NULL)
                         later = n;                          later = n;
         }          }
   
         if (body == NULL) {          if (body == NULL) {
                 mandoc_msg(MANDOCERR_BLK_NOTOPEN, mdoc->parse,                  mandoc_msg(MANDOCERR_BLK_NOTOPEN, line, ppos,
                     line, ppos, mdoc_macronames[tok]);                      "%s", roff_name[tok]);
                 if (maxargs && endbody == NULL) {                  if (maxargs && endbody == NULL) {
                         /*                          /*
                          * Stray .Ec without previous .Eo:                           * Stray .Ec without previous .Eo:
                          * Break the output line, keep the arguments.                           * Break the output line, keep the arguments.
                          */                           */
                         roff_elem_alloc(mdoc, line, ppos, MDOC_br);                          roff_elem_alloc(mdoc, line, ppos, ROFF_br);
                         rew_elem(mdoc, MDOC_br);                          rew_elem(mdoc, ROFF_br);
                 }                  }
         } else if (endbody == NULL) {          } else if (endbody == NULL) {
                 rew_last(mdoc, body);                  rew_last(mdoc, body);
Line 664  blk_exp_close(MACRO_PROT_ARGS)
Line 690  blk_exp_close(MACRO_PROT_ARGS)
                         mdoc_tail_alloc(mdoc, line, ppos, atok);                          mdoc_tail_alloc(mdoc, line, ppos, atok);
         }          }
   
         if ( ! (mdoc_macros[tok].flags & MDOC_PARSED)) {          if ((mdoc_macro(tok)->flags & MDOC_PARSED) == 0) {
                 if (buf[*pos] != '\0')                  if (buf[*pos] != '\0')
                         mandoc_vmsg(MANDOCERR_ARG_SKIP,                          mandoc_msg(MANDOCERR_ARG_SKIP, line, ppos,
                             mdoc->parse, line, ppos,                              "%s %s", roff_name[tok], buf + *pos);
                             "%s %s", mdoc_macronames[tok],  
                             buf + *pos);  
                 if (endbody == NULL && n != NULL)                  if (endbody == NULL && n != NULL)
                         rew_pending(mdoc, n);                          rew_pending(mdoc, n);
                 return;                  return;
Line 689  blk_exp_close(MACRO_PROT_ARGS)
Line 713  blk_exp_close(MACRO_PROT_ARGS)
                 if (ac == ARGS_PUNCT || ac == ARGS_EOLN)                  if (ac == ARGS_PUNCT || ac == ARGS_EOLN)
                         break;                          break;
   
                 ntok = ac == ARGS_QWORD ? TOKEN_NONE :                  ntok = lookup(mdoc, tok, line, lastarg, p);
                     lookup(mdoc, tok, line, lastarg, p);  
   
                 if (ntok == TOKEN_NONE) {                  if (ntok == TOKEN_NONE) {
                         dword(mdoc, line, lastarg, p, DELIM_MAX,                          dword(mdoc, line, lastarg, p, DELIM_MAX,
                             MDOC_JOIN & mdoc_macros[tok].flags);                              mdoc_macro(tok)->flags & MDOC_JOIN);
                           if (ac == ARGS_ALLOC)
                                   free(p);
                         continue;                          continue;
                 }                  }
                   if (ac == ARGS_ALLOC)
                           free(p);
   
                 if (n != NULL)                  if (n != NULL)
                         rew_last(mdoc, n);                          rew_last(mdoc, n);
                 mdoc->flags &= ~MDOC_NEWLINE;                  mdoc->flags &= ~MDOC_NEWLINE;
                 mdoc_macro(mdoc, ntok, line, lastarg, pos, buf);                  (*mdoc_macro(ntok)->fp)(mdoc, ntok, line, lastarg, pos, buf);
                 break;                  break;
         }          }
   
         if (n != NULL) {          if (n != NULL) {
                 if (ntok != TOKEN_NONE && n->flags & MDOC_BROKEN) {                  pending = 0;
                   if (ntok != TOKEN_NONE && n->flags & NODE_BROKEN) {
                         target = n;                          target = n;
                         do                          do
                                 target = target->parent;                                  target = target->parent;
                         while ( ! (target->flags & MDOC_ENDED));                          while ( ! (target->flags & NODE_ENDED));
                         pending = find_pending(mdoc, ntok, line, ppos,                          pending = find_pending(mdoc, ntok, line, ppos, target);
                             target);                  }
                 } else  
                         pending = 0;  
                 if ( ! pending)                  if ( ! pending)
                         rew_pending(mdoc, n);                          rew_pending(mdoc, n);
         }          }
Line 726  static void
Line 752  static void
 in_line(MACRO_PROT_ARGS)  in_line(MACRO_PROT_ARGS)
 {  {
         int              la, scope, cnt, firstarg, mayopen, nc, nl;          int              la, scope, cnt, firstarg, mayopen, nc, nl;
         int              ntok;          enum roff_tok    ntok;
         enum margserr    ac;          enum margserr    ac;
         enum mdelim      d;          enum mdelim      d;
         struct mdoc_arg *arg;          struct mdoc_arg *arg;
Line 769  in_line(MACRO_PROT_ARGS)
Line 795  in_line(MACRO_PROT_ARGS)
   
                 if (ac == ARGS_EOLN) {                  if (ac == ARGS_EOLN) {
                         if (d == DELIM_OPEN)                          if (d == DELIM_OPEN)
                                 mdoc->last->flags &= ~MDOC_DELIMO;                                  mdoc->last->flags &= ~NODE_DELIMO;
                         break;                          break;
                 }                  }
   
Line 787  in_line(MACRO_PROT_ARGS)
Line 813  in_line(MACRO_PROT_ARGS)
                         break;                          break;
                 }                  }
   
                 ntok = (ac == ARGS_QWORD || (tok == MDOC_Fn && !cnt)) ?                  ntok = (tok == MDOC_Fn && !cnt) ?
                     TOKEN_NONE : lookup(mdoc, tok, line, la, p);                      TOKEN_NONE : lookup(mdoc, tok, line, la, p);
   
                 /*                  /*
Line 806  in_line(MACRO_PROT_ARGS)
Line 832  in_line(MACRO_PROT_ARGS)
                         } else if ( ! nc && ! cnt) {                          } else if ( ! nc && ! cnt) {
                                 mdoc_argv_free(arg);                                  mdoc_argv_free(arg);
                                 mandoc_msg(MANDOCERR_MACRO_EMPTY,                                  mandoc_msg(MANDOCERR_MACRO_EMPTY,
                                     mdoc->parse, line, ppos,                                      line, ppos, "%s", roff_name[tok]);
                                     mdoc_macronames[tok]);  
                         }                          }
                         mdoc_macro(mdoc, ntok, line, la, pos, buf);                          (*mdoc_macro(ntok)->fp)(mdoc, ntok,
                               line, la, pos, buf);
                         if (nl)                          if (nl)
                                 append_delims(mdoc, line, pos, buf);                                  append_delims(mdoc, line, pos, buf);
                           if (ac == ARGS_ALLOC)
                                   free(p);
                         return;                          return;
                 }                  }
   
                 /*                  /*
                  * Non-quote-enclosed punctuation.  Set up our scope, if                   * Handle punctuation.  Set up our scope, if a word;
                  * a word; rewind the scope, if a delimiter; then append                   * rewind the scope, if a delimiter; then append the word.
                  * the word.  
                  */                   */
   
                 d = ac == ARGS_QWORD ? DELIM_NONE : mdoc_isdelim(p);                  if ((d = mdoc_isdelim(p)) != DELIM_NONE) {
   
                 if (DELIM_NONE != d) {  
                         /*                          /*
                          * If we encounter closing punctuation, no word                           * If we encounter closing punctuation, no word
                          * has been emitted, no scope is open, and we're                           * has been emitted, no scope is open, and we're
Line 843  in_line(MACRO_PROT_ARGS)
Line 868  in_line(MACRO_PROT_ARGS)
                          * Close out our scope, if one is open, before                           * Close out our scope, if one is open, before
                          * any punctuation.                           * any punctuation.
                          */                           */
                         if (scope)                          if (scope && tok != MDOC_Lk) {
                                 rew_elem(mdoc, tok);                                  rew_elem(mdoc, tok);
                         scope = 0;                                  scope = 0;
                         if (tok == MDOC_Fn)                                  if (tok == MDOC_Fn)
                                 mayopen = 0;                                          mayopen = 0;
                           }
                 } else if (mayopen && !scope) {                  } else if (mayopen && !scope) {
                         mdoc_elem_alloc(mdoc, line, ppos, tok, arg);                          mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
                         scope = 1;                          scope = 1;
Line 855  in_line(MACRO_PROT_ARGS)
Line 881  in_line(MACRO_PROT_ARGS)
                 }                  }
   
                 dword(mdoc, line, la, p, d,                  dword(mdoc, line, la, p, d,
                     MDOC_JOIN & mdoc_macros[tok].flags);                      mdoc_macro(tok)->flags & MDOC_JOIN);
   
                   if (ac == ARGS_ALLOC)
                           free(p);
   
                 /*                  /*
                  * If the first argument is a closing delimiter,                   * If the first argument is a closing delimiter,
                  * do not suppress spacing before it.                   * do not suppress spacing before it.
                  */                   */
   
                 if (firstarg && d == DELIM_CLOSE && !nc)                  if (firstarg && d == DELIM_CLOSE && !nc)
                         mdoc->last->flags &= ~MDOC_DELIMC;                          mdoc->last->flags &= ~NODE_DELIMC;
                 firstarg = 0;                  firstarg = 0;
   
                 /*                  /*
Line 877  in_line(MACRO_PROT_ARGS)
Line 906  in_line(MACRO_PROT_ARGS)
                 }                  }
         }          }
   
         if (scope)          if (scope && tok != MDOC_Lk) {
                 rew_elem(mdoc, tok);                  rew_elem(mdoc, tok);
                   scope = 0;
           }
   
         /*          /*
          * If no elements have been collected and we're allowed to have           * If no elements have been collected and we're allowed to have
Line 892  in_line(MACRO_PROT_ARGS)
Line 923  in_line(MACRO_PROT_ARGS)
                         rew_last(mdoc, mdoc->last);                          rew_last(mdoc, mdoc->last);
                 } else {                  } else {
                         mdoc_argv_free(arg);                          mdoc_argv_free(arg);
                         mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,                          mandoc_msg(MANDOCERR_MACRO_EMPTY,
                             line, ppos, mdoc_macronames[tok]);                              line, ppos, "%s", roff_name[tok]);
                 }                  }
         }          }
         if (nl)          if (nl)
                 append_delims(mdoc, line, pos, buf);                  append_delims(mdoc, line, pos, buf);
           if (scope)
                   rew_elem(mdoc, tok);
 }  }
   
 static void  static void
 blk_full(MACRO_PROT_ARGS)  blk_full(MACRO_PROT_ARGS)
 {  {
         int               la, nl, parsed;          int               done, la, nl, parsed;
         struct mdoc_arg  *arg;          struct mdoc_arg  *arg;
         struct roff_node *blk; /* Our own or a broken block. */          struct roff_node *blk; /* Our own or a broken block. */
         struct roff_node *head; /* Our own head. */          struct roff_node *head; /* Our own head. */
Line 915  blk_full(MACRO_PROT_ARGS)
Line 948  blk_full(MACRO_PROT_ARGS)
         nl = MDOC_NEWLINE & mdoc->flags;          nl = MDOC_NEWLINE & mdoc->flags;
   
         if (buf[*pos] == '\0' && (tok == MDOC_Sh || tok == MDOC_Ss)) {          if (buf[*pos] == '\0' && (tok == MDOC_Sh || tok == MDOC_Ss)) {
                 mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,                  mandoc_msg(MANDOCERR_MACRO_EMPTY,
                     line, ppos, mdoc_macronames[tok]);                      line, ppos, "%s", roff_name[tok]);
                 return;                  return;
         }          }
   
         if ( ! (mdoc_macros[tok].flags & MDOC_EXPLICIT)) {          if ((mdoc_macro(tok)->flags & MDOC_EXPLICIT) == 0) {
   
                 /* Here, tok is one of Sh Ss Nm Nd It. */                  /* Here, tok is one of Sh Ss Nm Nd It. */
   
                 blk = NULL;                  blk = NULL;
                 for (n = mdoc->last; n != NULL; n = n->parent) {                  for (n = mdoc->last; n != NULL; n = n->parent) {
                         if (n->flags & MDOC_ENDED) {                          if (n->flags & NODE_ENDED) {
                                 if ( ! (n->flags & MDOC_VALID))                                  if ( ! (n->flags & NODE_VALID))
                                         n->flags |= MDOC_BROKEN;                                          n->flags |= NODE_BROKEN;
                                 continue;                                  continue;
                         }                          }
                         if (n->type != ROFFT_BLOCK)                          if (n->type != ROFFT_BLOCK)
Line 936  blk_full(MACRO_PROT_ARGS)
Line 969  blk_full(MACRO_PROT_ARGS)
   
                         if (tok == MDOC_It && n->tok == MDOC_Bl) {                          if (tok == MDOC_It && n->tok == MDOC_Bl) {
                                 if (blk != NULL) {                                  if (blk != NULL) {
                                         mandoc_vmsg(MANDOCERR_BLK_BROKEN,                                          mandoc_msg(MANDOCERR_BLK_BROKEN,
                                             mdoc->parse, line, ppos,                                              line, ppos, "It breaks %s",
                                             "It breaks %s",                                              roff_name[blk->tok]);
                                             mdoc_macronames[blk->tok]);  
                                         rew_pending(mdoc, blk);                                          rew_pending(mdoc, blk);
                                 }                                  }
                                 break;                                  break;
                         }                          }
   
                         if (mdoc_macros[n->tok].flags & MDOC_EXPLICIT) {                          if (mdoc_macro(n->tok)->flags & MDOC_EXPLICIT) {
                                 switch (tok) {                                  switch (tok) {
                                 case MDOC_Sh:                                  case MDOC_Sh:
                                 case MDOC_Ss:                                  case MDOC_Ss:
                                         mandoc_vmsg(MANDOCERR_BLK_BROKEN,                                          mandoc_msg(MANDOCERR_BLK_BROKEN,
                                             mdoc->parse, line, ppos,                                              line, ppos,
                                             "%s breaks %s",                                              "%s breaks %s", roff_name[tok],
                                             mdoc_macronames[tok],                                              roff_name[n->tok]);
                                             mdoc_macronames[n->tok]);  
                                         rew_pending(mdoc, n);                                          rew_pending(mdoc, n);
                                         n = mdoc->last;                                          n = mdoc->last;
                                         continue;                                          continue;
Line 977  blk_full(MACRO_PROT_ARGS)
Line 1008  blk_full(MACRO_PROT_ARGS)
                         /* Item breaking an explicit block. */                          /* Item breaking an explicit block. */
   
                         if (blk != NULL) {                          if (blk != NULL) {
                                 mandoc_vmsg(MANDOCERR_BLK_BROKEN,                                  mandoc_msg(MANDOCERR_BLK_BROKEN, line, ppos,
                                     mdoc->parse, line, ppos,                                      "It breaks %s", roff_name[blk->tok]);
                                     "It breaks %s",  
                                     mdoc_macronames[blk->tok]);  
                                 rew_pending(mdoc, blk);                                  rew_pending(mdoc, blk);
                                 blk = NULL;                                  blk = NULL;
                         }                          }
   
                         /* Close out prior implicit scopes. */                          /* Close out prior implicit scopes. */
   
                         rew_last(mdoc, n);                          rew_pending(mdoc, n);
                 }                  }
   
                 /* Skip items outside lists. */                  /* Skip items outside lists. */
   
                 if (tok == MDOC_It && (n == NULL || n->tok != MDOC_Bl)) {                  if (tok == MDOC_It && (n == NULL || n->tok != MDOC_Bl)) {
                         mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse,                          mandoc_msg(MANDOCERR_IT_STRAY,
                             line, ppos, "It %s", buf + *pos);                              line, ppos, "It %s", buf + *pos);
                         roff_elem_alloc(mdoc, line, ppos, MDOC_br);                          roff_elem_alloc(mdoc, line, ppos, ROFF_br);
                         rew_elem(mdoc, MDOC_br);                          rew_elem(mdoc, ROFF_br);
                         return;                          return;
                 }                  }
         }          }
Line 1071  blk_full(MACRO_PROT_ARGS)
Line 1100  blk_full(MACRO_PROT_ARGS)
                 }                  }
   
                 if (tok == MDOC_Bd || tok == MDOC_Bk) {                  if (tok == MDOC_Bd || tok == MDOC_Bk) {
                         mandoc_vmsg(MANDOCERR_ARG_EXCESS,                          mandoc_msg(MANDOCERR_ARG_EXCESS, line, la,
                             mdoc->parse, line, la, "%s ... %s",                              "%s ... %s", roff_name[tok], buf + la);
                             mdoc_macronames[tok], buf + la);                          if (ac == ARGS_ALLOC)
                                   free(p);
                         break;                          break;
                 }                  }
                 if (tok == MDOC_Rs) {                  if (tok == MDOC_Rs) {
                         mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse,                          mandoc_msg(MANDOCERR_ARG_SKIP,
                             line, la, "Rs %s", buf + la);                              line, la, "Rs %s", buf + la);
                           if (ac == ARGS_ALLOC)
                                   free(p);
                         break;                          break;
                 }                  }
                 if (ac == ARGS_PUNCT)                  if (ac == ARGS_PUNCT)
Line 1091  blk_full(MACRO_PROT_ARGS)
Line 1123  blk_full(MACRO_PROT_ARGS)
   
                 if (head == NULL &&                  if (head == NULL &&
                     ac != ARGS_PHRASE &&                      ac != ARGS_PHRASE &&
                     ac != ARGS_QWORD &&  
                     mdoc_isdelim(p) == DELIM_OPEN) {                      mdoc_isdelim(p) == DELIM_OPEN) {
                         dword(mdoc, line, la, p, DELIM_OPEN, 0);                          dword(mdoc, line, la, p, DELIM_OPEN, 0);
                           if (ac == ARGS_ALLOC)
                                   free(p);
                         continue;                          continue;
                 }                  }
   
Line 1125  blk_full(MACRO_PROT_ARGS)
Line 1158  blk_full(MACRO_PROT_ARGS)
                         continue;                          continue;
                 }                  }
   
                 if (macro_or_word(mdoc, tok, line, la, pos, buf, parsed))                  done = macro_or_word(mdoc, tok, line, la, pos, buf, p, parsed);
                   if (ac == ARGS_ALLOC)
                           free(p);
                   if (done)
                         break;                          break;
         }          }
   
         if (blk->flags & MDOC_VALID)          if (blk->flags & NODE_VALID)
                 return;                  return;
         if (head == NULL)          if (head == NULL)
                 head = roff_head_alloc(mdoc, line, ppos, tok);                  head = roff_head_alloc(mdoc, line, ppos, tok);
Line 1155  out:
Line 1191  out:
 static void  static void
 blk_part_imp(MACRO_PROT_ARGS)  blk_part_imp(MACRO_PROT_ARGS)
 {  {
         int               la, nl;          int               done, la, nl;
         enum margserr     ac;          enum margserr     ac;
         char             *p;          char             *p;
         struct roff_node *blk; /* saved block context */          struct roff_node *blk; /* saved block context */
Line 1188  blk_part_imp(MACRO_PROT_ARGS)
Line 1224  blk_part_imp(MACRO_PROT_ARGS)
                 if (ac == ARGS_EOLN || ac == ARGS_PUNCT)                  if (ac == ARGS_EOLN || ac == ARGS_PUNCT)
                         break;                          break;
   
                 if (body == NULL && ac != ARGS_QWORD &&                  if (body == NULL && mdoc_isdelim(p) == DELIM_OPEN) {
                     mdoc_isdelim(p) == DELIM_OPEN) {  
                         dword(mdoc, line, la, p, DELIM_OPEN, 0);                          dword(mdoc, line, la, p, DELIM_OPEN, 0);
                           if (ac == ARGS_ALLOC)
                                   free(p);
                         continue;                          continue;
                 }                  }
   
                 if (body == NULL)                  if (body == NULL)
                         body = roff_body_alloc(mdoc, line, ppos, tok);                          body = roff_body_alloc(mdoc, line, ppos, tok);
   
                 if (macro_or_word(mdoc, tok, line, la, pos, buf, 1))                  done = macro_or_word(mdoc, tok, line, la, pos, buf, p, 1);
                   if (ac == ARGS_ALLOC)
                           free(p);
                   if (done)
                         break;                          break;
         }          }
         if (body == NULL)          if (body == NULL)
Line 1216  blk_part_imp(MACRO_PROT_ARGS)
Line 1256  blk_part_imp(MACRO_PROT_ARGS)
         for (n = body->child; n && n->next; n = n->next)          for (n = body->child; n && n->next; n = n->next)
                 /* Do nothing. */ ;                  /* Do nothing. */ ;
         if (n && n->tok == MDOC_Ns)          if (n && n->tok == MDOC_Ns)
                 mdoc_node_relink(mdoc, n);                  roff_node_relink(mdoc, n);
 }  }
   
 static void  static void
 blk_part_exp(MACRO_PROT_ARGS)  blk_part_exp(MACRO_PROT_ARGS)
 {  {
         int               la, nl;          int               done, la, nl;
         enum margserr     ac;          enum margserr     ac;
         struct roff_node *head; /* keep track of head */          struct roff_node *head; /* keep track of head */
         char             *p;          char             *p;
Line 1245  blk_part_exp(MACRO_PROT_ARGS)
Line 1285  blk_part_exp(MACRO_PROT_ARGS)
   
                 /* Flush out leading punctuation. */                  /* Flush out leading punctuation. */
   
                 if (head == NULL && ac != ARGS_QWORD &&                  if (head == NULL && mdoc_isdelim(p) == DELIM_OPEN) {
                     mdoc_isdelim(p) == DELIM_OPEN) {  
                         dword(mdoc, line, la, p, DELIM_OPEN, 0);                          dword(mdoc, line, la, p, DELIM_OPEN, 0);
                           if (ac == ARGS_ALLOC)
                                   free(p);
                         continue;                          continue;
                 }                  }
   
Line 1257  blk_part_exp(MACRO_PROT_ARGS)
Line 1298  blk_part_exp(MACRO_PROT_ARGS)
                                 dword(mdoc, line, la, p, DELIM_MAX, 0);                                  dword(mdoc, line, la, p, DELIM_MAX, 0);
                         rew_last(mdoc, head);                          rew_last(mdoc, head);
                         roff_body_alloc(mdoc, line, ppos, tok);                          roff_body_alloc(mdoc, line, ppos, tok);
                         if (tok == MDOC_Eo)                          if (tok == MDOC_Eo) {
                                   if (ac == ARGS_ALLOC)
                                           free(p);
                                 continue;                                  continue;
                           }
                 }                  }
   
                 if (macro_or_word(mdoc, tok, line, la, pos, buf, 1))                  done = macro_or_word(mdoc, tok, line, la, pos, buf, p, 1);
                   if (ac == ARGS_ALLOC)
                           free(p);
                   if (done)
                         break;                          break;
         }          }
   
Line 1281  in_line_argn(MACRO_PROT_ARGS)
Line 1328  in_line_argn(MACRO_PROT_ARGS)
         struct mdoc_arg *arg;          struct mdoc_arg *arg;
         char            *p;          char            *p;
         enum margserr    ac;          enum margserr    ac;
         int              ntok;          enum roff_tok    ntok;
         int              state; /* arg#; -1: not yet open; -2: closed */          int              state; /* arg#; -1: not yet open; -2: closed */
         int              la, maxargs, nl;          int              la, maxargs, nl;
   
Line 1319  in_line_argn(MACRO_PROT_ARGS)
Line 1366  in_line_argn(MACRO_PROT_ARGS)
                 la = *pos;                  la = *pos;
                 ac = mdoc_args(mdoc, line, pos, buf, tok, &p);                  ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
   
                 if (ac == ARGS_WORD && state == -1 &&                  if ((ac == ARGS_WORD || ac == ARGS_ALLOC) && state == -1 &&
                     ! (mdoc_macros[tok].flags & MDOC_IGNDELIM) &&                      (mdoc_macro(tok)->flags & MDOC_IGNDELIM) == 0 &&
                     mdoc_isdelim(p) == DELIM_OPEN) {                      mdoc_isdelim(p) == DELIM_OPEN) {
                         dword(mdoc, line, la, p, DELIM_OPEN, 0);                          dword(mdoc, line, la, p, DELIM_OPEN, 0);
                           if (ac == ARGS_ALLOC)
                                   free(p);
                         continue;                          continue;
                 }                  }
   
Line 1334  in_line_argn(MACRO_PROT_ARGS)
Line 1383  in_line_argn(MACRO_PROT_ARGS)
   
                 if (ac == ARGS_PUNCT || ac == ARGS_EOLN) {                  if (ac == ARGS_PUNCT || ac == ARGS_EOLN) {
                         if (abs(state) < 2 && tok == MDOC_Pf)                          if (abs(state) < 2 && tok == MDOC_Pf)
                                 mandoc_vmsg(MANDOCERR_PF_SKIP,                                  mandoc_msg(MANDOCERR_PF_SKIP,
                                     mdoc->parse, line, ppos, "Pf %s",                                      line, ppos, "Pf %s",
                                     p == NULL ? "at eol" : p);                                      p == NULL ? "at eol" : p);
                         break;                          break;
                 }                  }
Line 1345  in_line_argn(MACRO_PROT_ARGS)
Line 1394  in_line_argn(MACRO_PROT_ARGS)
                         state = -2;                          state = -2;
                 }                  }
   
                 ntok = (ac == ARGS_QWORD || (tok == MDOC_Pf && state == 0)) ?                  ntok = (tok == MDOC_Pf && state == 0) ?
                     TOKEN_NONE : lookup(mdoc, tok, line, la, p);                      TOKEN_NONE : lookup(mdoc, tok, line, la, p);
   
                 if (ntok != TOKEN_NONE) {                  if (ntok != TOKEN_NONE) {
Line 1353  in_line_argn(MACRO_PROT_ARGS)
Line 1402  in_line_argn(MACRO_PROT_ARGS)
                                 rew_elem(mdoc, tok);                                  rew_elem(mdoc, tok);
                                 state = -2;                                  state = -2;
                         }                          }
                         mdoc_macro(mdoc, ntok, line, la, pos, buf);                          (*mdoc_macro(ntok)->fp)(mdoc, ntok,
                               line, la, pos, buf);
                           if (ac == ARGS_ALLOC)
                                   free(p);
                         break;                          break;
                 }                  }
   
                 if (ac == ARGS_QWORD ||                  if (mdoc_macro(tok)->flags & MDOC_IGNDELIM ||
                     mdoc_macros[tok].flags & MDOC_IGNDELIM ||  
                     mdoc_isdelim(p) == DELIM_NONE) {                      mdoc_isdelim(p) == DELIM_NONE) {
                         if (state == -1) {                          if (state == -1) {
                                 mdoc_elem_alloc(mdoc, line, ppos, tok, arg);                                  mdoc_elem_alloc(mdoc, line, ppos, tok, arg);
Line 1371  in_line_argn(MACRO_PROT_ARGS)
Line 1422  in_line_argn(MACRO_PROT_ARGS)
                 }                  }
   
                 dword(mdoc, line, la, p, DELIM_MAX,                  dword(mdoc, line, la, p, DELIM_MAX,
                     MDOC_JOIN & mdoc_macros[tok].flags);                      mdoc_macro(tok)->flags & MDOC_JOIN);
                   if (ac == ARGS_ALLOC)
                           free(p);
                   p = mdoc->last->string;
         }          }
   
         if (state == -1) {          if (state == -1) {
                 mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,                  mandoc_msg(MANDOCERR_MACRO_EMPTY,
                     line, ppos, mdoc_macronames[tok]);                      line, ppos, "%s", roff_name[tok]);
                 return;                  return;
         }          }
   
Line 1404  in_line_eoln(MACRO_PROT_ARGS)
Line 1458  in_line_eoln(MACRO_PROT_ARGS)
         }          }
   
         if (buf[*pos] == '\0' &&          if (buf[*pos] == '\0' &&
             (tok == MDOC_Fd || mdoc_macronames[tok][0] == '%')) {              (tok == MDOC_Fd || *roff_name[tok] == '%')) {
                 mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,                  mandoc_msg(MANDOCERR_MACRO_EMPTY,
                     line, ppos, mdoc_macronames[tok]);                      line, ppos, "%s", roff_name[tok]);
                 return;                  return;
         }          }
   
Line 1423  in_line_eoln(MACRO_PROT_ARGS)
Line 1477  in_line_eoln(MACRO_PROT_ARGS)
  * or until the next macro, call that macro, and return 1.   * or until the next macro, call that macro, and return 1.
  */   */
 static int  static int
 parse_rest(struct roff_man *mdoc, int tok, int line, int *pos, char *buf)  parse_rest(struct roff_man *mdoc, enum roff_tok tok,
       int line, int *pos, char *buf)
 {  {
         int              la;          char            *p;
           int              done, la;
           enum margserr    ac;
   
         for (;;) {          for (;;) {
                 la = *pos;                  la = *pos;
                 if (mdoc_args(mdoc, line, pos, buf, tok, NULL) == ARGS_EOLN)                  ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
                   if (ac == ARGS_EOLN)
                         return 0;                          return 0;
                 if (macro_or_word(mdoc, tok, line, la, pos, buf, 1))                  done = macro_or_word(mdoc, tok, line, la, pos, buf, p, 1);
                   if (ac == ARGS_ALLOC)
                           free(p);
                   if (done)
                         return 1;                          return 1;
         }          }
 }  }
Line 1464  phrase_ta(MACRO_PROT_ARGS)
Line 1525  phrase_ta(MACRO_PROT_ARGS)
   
         body = NULL;          body = NULL;
         for (n = mdoc->last; n != NULL; n = n->parent) {          for (n = mdoc->last; n != NULL; n = n->parent) {
                 if (n->flags & MDOC_ENDED)                  if (n->flags & NODE_ENDED)
                         continue;                          continue;
                 if (n->tok == MDOC_It && n->type == ROFFT_BODY)                  if (n->tok == MDOC_It && n->type == ROFFT_BODY)
                         body = n;                          body = n;
Line 1473  phrase_ta(MACRO_PROT_ARGS)
Line 1534  phrase_ta(MACRO_PROT_ARGS)
         }          }
   
         if (n == NULL || n->norm->Bl.type != LIST_column) {          if (n == NULL || n->norm->Bl.type != LIST_column) {
                 mandoc_msg(MANDOCERR_TA_STRAY, mdoc->parse,                  mandoc_msg(MANDOCERR_TA_STRAY, line, ppos, "Ta");
                     line, ppos, "Ta");  
                 return;                  return;
         }          }
   

Legend:
Removed from v.1.209  
changed lines
  Added in v.1.230

CVSweb