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

Diff for /mandoc/roff.c between version 1.130 and 1.154

version 1.130, 2011/03/29 09:00:48 version 1.154, 2011/07/27 07:09:41
Line 20 
Line 20 
 #endif  #endif
   
 #include <assert.h>  #include <assert.h>
 #include <errno.h>  
 #include <ctype.h>  #include <ctype.h>
 #include <limits.h>  
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <stdio.h>  
   
 #include "mandoc.h"  #include "mandoc.h"
 #include "libroff.h"  #include "libroff.h"
 #include "libmandoc.h"  #include "libmandoc.h"
   
   /* Maximum number of nested if-else conditionals. */
 #define RSTACK_MAX      128  #define RSTACK_MAX      128
   
 enum    rofft {  enum    rofft {
Line 63  enum rofft {
Line 61  enum rofft {
         ROFF_EQ,          ROFF_EQ,
         ROFF_EN,          ROFF_EN,
         ROFF_cblock,          ROFF_cblock,
         ROFF_ccond, /* FIXME: remove this. */          ROFF_ccond,
         ROFF_USERDEF,          ROFF_USERDEF,
         ROFF_MAX          ROFF_MAX
 };  };
Line 73  enum roffrule {
Line 71  enum roffrule {
         ROFFRULE_DENY          ROFFRULE_DENY
 };  };
   
   /*
    * A single register entity.  If "set" is zero, the value of the
    * register should be the default one, which is per-register.
    * Registers are assumed to be unsigned ints for now.
    */
   struct  reg {
           int               set; /* whether set or not */
           unsigned int      u; /* unsigned integer */
   };
   
 struct  roffstr {  struct  roffstr {
         char            *name; /* key of symbol */          char            *name; /* key of symbol */
         char            *string; /* current value */          char            *string; /* current value */
Line 84  struct roff {
Line 92  struct roff {
         struct roffnode *last; /* leaf of stack */          struct roffnode *last; /* leaf of stack */
         enum roffrule    rstack[RSTACK_MAX]; /* stack of !`ie' rules */          enum roffrule    rstack[RSTACK_MAX]; /* stack of !`ie' rules */
         int              rstackpos; /* position in rstack */          int              rstackpos; /* position in rstack */
         struct regset   *regs; /* read/writable registers */          struct reg       regs[REG__MAX];
         struct roffstr  *first_string; /* user-defined strings & macros */          struct roffstr  *first_string; /* user-defined strings & macros */
         const char      *current_string; /* value of last called user macro */          const char      *current_string; /* value of last called user macro */
         struct tbl_node *first_tbl; /* first table parsed */          struct tbl_node *first_tbl; /* first table parsed */
Line 127  struct roffmac {
Line 135  struct roffmac {
         struct roffmac  *next;          struct roffmac  *next;
 };  };
   
   struct  predef {
           const char      *name; /* predefined input name */
           const char      *str; /* replacement symbol */
   };
   
   #define PREDEF(__name, __str) \
           { (__name), (__str) },
   
 static  enum rofferr     roff_block(ROFF_ARGS);  static  enum rofferr     roff_block(ROFF_ARGS);
 static  enum rofferr     roff_block_text(ROFF_ARGS);  static  enum rofferr     roff_block_text(ROFF_ARGS);
 static  enum rofferr     roff_block_sub(ROFF_ARGS);  static  enum rofferr     roff_block_sub(ROFF_ARGS);
Line 143  static const char *roff_getstrn(const struct roff *, 
Line 159  static const char *roff_getstrn(const struct roff *, 
                                 const char *, size_t);                                  const char *, size_t);
 static  enum rofferr     roff_line_ignore(ROFF_ARGS);  static  enum rofferr     roff_line_ignore(ROFF_ARGS);
 static  enum rofferr     roff_nr(ROFF_ARGS);  static  enum rofferr     roff_nr(ROFF_ARGS);
 static  int              roff_res(struct roff *,  static  void             roff_res(struct roff *,
                                 char **, size_t *, int);                                  char **, size_t *, int, int);
 static  enum rofferr     roff_rm(ROFF_ARGS);  static  enum rofferr     roff_rm(ROFF_ARGS);
 static  void             roff_setstr(struct roff *,  static  void             roff_setstr(struct roff *,
                                 const char *, const char *, int);                                  const char *, const char *, int);
Line 198  static struct roffmac  roffs[ROFF_MAX] = {
Line 214  static struct roffmac  roffs[ROFF_MAX] = {
         { NULL, roff_userdef, NULL, NULL, 0, NULL },          { NULL, roff_userdef, NULL, NULL, 0, NULL },
 };  };
   
   /* Array of injected predefined strings. */
   #define PREDEFS_MAX      38
   static  const struct predef predefs[PREDEFS_MAX] = {
   #include "predefs.in"
   };
   
 static  void             roff_free1(struct roff *);  static  void             roff_free1(struct roff *);
 static  enum rofft       roff_hash_find(const char *, size_t);  static  enum rofft       roff_hash_find(const char *, size_t);
 static  void             roff_hash_init(void);  static  void             roff_hash_init(void);
Line 206  static void   roffnode_push(struct roff *, enum rofft,
Line 228  static void   roffnode_push(struct roff *, enum rofft,
                                 const char *, int, int);                                  const char *, int, int);
 static  void             roffnode_pop(struct roff *);  static  void             roffnode_pop(struct roff *);
 static  enum rofft       roff_parse(struct roff *, const char *, int *);  static  enum rofft       roff_parse(struct roff *, const char *, int *);
 static  int              roff_parse_nat(const char *, unsigned int *);  
   
 /* See roff_hash_find() */  /* See roff_hash_find() */
 #define ROFF_HASH(p)    (p[0] - ASCII_LO)  #define ROFF_HASH(p)    (p[0] - ASCII_LO)
Line 232  roff_hash_init(void)
Line 253  roff_hash_init(void)
         }          }
 }  }
   
   
 /*  /*
  * Look up a roff token by its name.  Returns ROFF_MAX if no macro by   * Look up a roff token by its name.  Returns ROFF_MAX if no macro by
  * the nil-terminated string name could be found.   * the nil-terminated string name could be found.
Line 277  roffnode_pop(struct roff *r)
Line 297  roffnode_pop(struct roff *r)
         assert(r->last);          assert(r->last);
         p = r->last;          p = r->last;
   
         if (ROFF_el == p->tok)  
                 if (r->rstackpos > -1)  
                         r->rstackpos--;  
   
         r->last = r->last->parent;          r->last = r->last->parent;
         free(p->name);          free(p->name);
         free(p->end);          free(p->end);
Line 341  roff_free1(struct roff *r)
Line 357  roff_free1(struct roff *r)
 void  void
 roff_reset(struct roff *r)  roff_reset(struct roff *r)
 {  {
           int              i;
   
         roff_free1(r);          roff_free1(r);
   
           memset(&r->regs, 0, sizeof(struct reg) * REG__MAX);
   
           for (i = 0; i < PREDEFS_MAX; i++)
                   roff_setstr(r, predefs[i].name, predefs[i].str, 0);
 }  }
   
   
Line 356  roff_free(struct roff *r)
Line 378  roff_free(struct roff *r)
   
   
 struct roff *  struct roff *
 roff_alloc(struct regset *regs, struct mparse *parse)  roff_alloc(struct mparse *parse)
 {  {
         struct roff     *r;          struct roff     *r;
           int              i;
   
         r = mandoc_calloc(1, sizeof(struct roff));          r = mandoc_calloc(1, sizeof(struct roff));
         r->regs = regs;  
         r->parse = parse;          r->parse = parse;
         r->rstackpos = -1;          r->rstackpos = -1;
   
         roff_hash_init();          roff_hash_init();
   
           for (i = 0; i < PREDEFS_MAX; i++)
                   roff_setstr(r, predefs[i].name, predefs[i].str, 0);
   
         return(r);          return(r);
 }  }
   
   
 /*  /*
  * Pre-filter each and every line for reserved words (one beginning with   * Pre-filter each and every line for reserved words (one beginning with
  * `\*', e.g., `\*(ab').  These must be handled before the actual line   * `\*', e.g., `\*(ab').  These must be handled before the actual line
  * is processed.   * is processed.
    * This also checks the syntax of regular escapes.
  */   */
 static int  static void
 roff_res(struct roff *r, char **bufp, size_t *szp, int pos)  roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
 {  {
           enum mandoc_esc  esc;
         const char      *stesc; /* start of an escape sequence ('\\') */          const char      *stesc; /* start of an escape sequence ('\\') */
         const char      *stnam; /* start of the name, after "[(*" */          const char      *stnam; /* start of the name, after "[(*" */
         const char      *cp;    /* end of the name, e.g. before ']' */          const char      *cp;    /* end of the name, e.g. before ']' */
Line 386  roff_res(struct roff *r, char **bufp, size_t *szp, int
Line 413  roff_res(struct roff *r, char **bufp, size_t *szp, int
         size_t           nsz;          size_t           nsz;
         char            *n;          char            *n;
   
         /* Search for a leading backslash and save a pointer to it. */  again:
   
         cp = *bufp + pos;          cp = *bufp + pos;
         while (NULL != (cp = strchr(cp, '\\'))) {          while (NULL != (cp = strchr(cp, '\\'))) {
                 stesc = cp++;                  stesc = cp++;
Line 399  roff_res(struct roff *r, char **bufp, size_t *szp, int
Line 425  roff_res(struct roff *r, char **bufp, size_t *szp, int
                  */                   */
   
                 if ('\0' == *cp)                  if ('\0' == *cp)
                         return(1);                          return;
                 if ('*' != *cp++)  
                         continue;  
   
                   if ('*' != *cp) {
                           res = cp;
                           esc = mandoc_escape(&cp, NULL, NULL);
                           if (ESCAPE_ERROR != esc)
                                   continue;
                           cp = res;
                           mandoc_msg
                                   (MANDOCERR_BADESCAPE, r->parse,
                                    ln, (int)(stesc - *bufp), NULL);
                           return;
                   }
   
                   cp++;
   
                 /*                  /*
                  * The third character decides the length                   * The third character decides the length
                  * of the name of the string.                   * of the name of the string.
Line 411  roff_res(struct roff *r, char **bufp, size_t *szp, int
Line 449  roff_res(struct roff *r, char **bufp, size_t *szp, int
   
                 switch (*cp) {                  switch (*cp) {
                 case ('\0'):                  case ('\0'):
                         return(1);                          return;
                 case ('('):                  case ('('):
                         cp++;                          cp++;
                         maxl = 2;                          maxl = 2;
Line 429  roff_res(struct roff *r, char **bufp, size_t *szp, int
Line 467  roff_res(struct roff *r, char **bufp, size_t *szp, int
                 /* Advance to the end of the name. */                  /* Advance to the end of the name. */
   
                 for (i = 0; 0 == maxl || i < maxl; i++, cp++) {                  for (i = 0; 0 == maxl || i < maxl; i++, cp++) {
                         if ('\0' == *cp)                          if ('\0' == *cp) {
                                 return(1); /* Error. */                                  mandoc_msg
                                           (MANDOCERR_BADESCAPE,
                                            r->parse, ln,
                                            (int)(stesc - *bufp), NULL);
                                   return;
                           }
                         if (0 == maxl && ']' == *cp)                          if (0 == maxl && ']' == *cp)
                                 break;                                  break;
                 }                  }
Line 443  roff_res(struct roff *r, char **bufp, size_t *szp, int
Line 486  roff_res(struct roff *r, char **bufp, size_t *szp, int
                 res = roff_getstrn(r, stnam, (size_t)i);                  res = roff_getstrn(r, stnam, (size_t)i);
   
                 if (NULL == res) {                  if (NULL == res) {
                         cp -= maxl ? 1 : 0;                          mandoc_msg
                         continue;                                  (MANDOCERR_BADESCAPE, r->parse,
                                    ln, (int)(stesc - *bufp), NULL);
                           res = "";
                 }                  }
   
                 /* Replace the escape sequence by the string. */                  /* Replace the escape sequence by the string. */
   
                   pos += (stesc - *bufp);
   
                 nsz = *szp + strlen(res) + 1;                  nsz = *szp + strlen(res) + 1;
                 n = mandoc_malloc(nsz);                  n = mandoc_malloc(nsz);
   
Line 460  roff_res(struct roff *r, char **bufp, size_t *szp, int
Line 507  roff_res(struct roff *r, char **bufp, size_t *szp, int
   
                 *bufp = n;                  *bufp = n;
                 *szp = nsz;                  *szp = nsz;
                 return(0);                  goto again;
         }          }
   
         return(1);  
 }  }
   
   /*
    * Process text streams: convert all breakable hyphens into ASCII_HYPH.
    */
   static enum rofferr
   roff_parsetext(char *p)
   {
           size_t           sz;
           const char      *start;
           enum mandoc_esc  esc;
   
           start = p;
   
           while ('\0' != *p) {
                   sz = strcspn(p, "-\\");
                   p += sz;
   
                   if ('\\' == *p) {
                           /* Skip over escapes. */
                           p++;
                           esc = mandoc_escape
                                   ((const char **)&p, NULL, NULL);
                           if (ESCAPE_ERROR == esc)
                                   break;
                   } else if ('-' == *p) {
                           if (mandoc_hyph(start, p))
                                   *p = ASCII_HYPH;
                           p++;
                   }
           }
   
           return(ROFF_CONT);
   }
   
 enum rofferr  enum rofferr
 roff_parseln(struct roff *r, int ln, char **bufp,  roff_parseln(struct roff *r, int ln, char **bufp,
                 size_t *szp, int pos, int *offs)                  size_t *szp, int pos, int *offs)
Line 480  roff_parseln(struct roff *r, int ln, char **bufp, 
Line 557  roff_parseln(struct roff *r, int ln, char **bufp, 
          * words to fill in.           * words to fill in.
          */           */
   
         if (r->first_string && ! roff_res(r, bufp, szp, pos))          roff_res(r, bufp, szp, ln, pos);
                 return(ROFF_REPARSE);  
   
         ppos = pos;          ppos = pos;
         ctl = mandoc_getcontrol(*bufp, &pos);          ctl = mandoc_getcontrol(*bufp, &pos);
Line 503  roff_parseln(struct roff *r, int ln, char **bufp, 
Line 579  roff_parseln(struct roff *r, int ln, char **bufp, 
                 if (ROFF_CONT != e)                  if (ROFF_CONT != e)
                         return(e);                          return(e);
                 if (r->eqn)                  if (r->eqn)
                         return(eqn_read(&r->eqn, ln, *bufp, pos));                          return(eqn_read(&r->eqn, ln, *bufp, pos, offs));
                 if (r->tbl)                  if (r->tbl)
                         return(tbl_read(r->tbl, ln, *bufp, pos));                          return(tbl_read(r->tbl, ln, *bufp, pos));
                 return(ROFF_CONT);                  return(roff_parsetext(*bufp + pos));
         } else if ( ! ctl) {          } else if ( ! ctl) {
                 if (r->eqn)                  if (r->eqn)
                         return(eqn_read(&r->eqn, ln, *bufp, pos));                          return(eqn_read(&r->eqn, ln, *bufp, pos, offs));
                 if (r->tbl)                  if (r->tbl)
                         return(tbl_read(r->tbl, ln, *bufp, pos));                          return(tbl_read(r->tbl, ln, *bufp, pos));
                 return(ROFF_CONT);                  return(roff_parsetext(*bufp + pos));
         } else if (r->eqn)          } else if (r->eqn)
                 return(eqn_read(&r->eqn, ln, *bufp, ppos));                  return(eqn_read(&r->eqn, ln, *bufp, ppos, offs));
   
         /*          /*
          * If a scope is open, go to the child handler for that macro,           * If a scope is open, go to the child handler for that macro,
Line 556  roff_endparse(struct roff *r)
Line 632  roff_endparse(struct roff *r)
   
         if (r->eqn) {          if (r->eqn) {
                 mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse,                  mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse,
                                 r->eqn->eqn.line, r->eqn->eqn.pos, NULL);                                  r->eqn->eqn.ln, r->eqn->eqn.pos, NULL);
                 eqn_end(r->eqn);                  eqn_end(&r->eqn);
                 r->eqn = NULL;  
         }          }
   
         if (r->tbl) {          if (r->tbl) {
                 mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse,                  mandoc_msg(MANDOCERR_SCOPEEXIT, r->parse,
                                 r->tbl->line, r->tbl->pos, NULL);                                  r->tbl->line, r->tbl->pos, NULL);
                 tbl_end(r->tbl);                  tbl_end(&r->tbl);
                 r->tbl = NULL;  
         }          }
 }  }
   
Line 580  roff_parse(struct roff *r, const char *buf, int *pos)
Line 654  roff_parse(struct roff *r, const char *buf, int *pos)
         size_t           maclen;          size_t           maclen;
         enum rofft       t;          enum rofft       t;
   
         if ('\0' == buf[*pos] || '"' == buf[*pos])          if ('\0' == buf[*pos] || '"' == buf[*pos] ||
                           '\t' == buf[*pos] || ' ' == buf[*pos])
                 return(ROFF_MAX);                  return(ROFF_MAX);
   
           /*
            * We stop the macro parse at an escape, tab, space, or nil.
            * However, `\}' is also a valid macro, so make sure we don't
            * clobber it by seeing the `\' as the end of token.
            */
   
         mac = buf + *pos;          mac = buf + *pos;
         maclen = strcspn(mac, " \\\t\0");          maclen = strcspn(mac + 1, " \\\t\0") + 1;
   
         t = (r->current_string = roff_getstrn(r, mac, maclen))          t = (r->current_string = roff_getstrn(r, mac, maclen))
             ? ROFF_USERDEF : roff_hash_find(mac, maclen);              ? ROFF_USERDEF : roff_hash_find(mac, maclen);
Line 597  roff_parse(struct roff *r, const char *buf, int *pos)
Line 678  roff_parse(struct roff *r, const char *buf, int *pos)
         return(t);          return(t);
 }  }
   
   
 static int  
 roff_parse_nat(const char *buf, unsigned int *res)  
 {  
         char            *ep;  
         long             lval;  
   
         errno = 0;  
         lval = strtol(buf, &ep, 10);  
         if (buf[0] == '\0' || *ep != '\0')  
                 return(0);  
         if ((errno == ERANGE &&  
                         (lval == LONG_MAX || lval == LONG_MIN)) ||  
                         (lval > INT_MAX || lval < 0))  
                 return(0);  
   
         *res = (unsigned int)lval;  
         return(1);  
 }  
   
   
 /* ARGSUSED */  /* ARGSUSED */
 static enum rofferr  static enum rofferr
 roff_cblock(ROFF_ARGS)  roff_cblock(ROFF_ARGS)
Line 739  roff_block(ROFF_ARGS)
Line 799  roff_block(ROFF_ARGS)
                         mandoc_msg(MANDOCERR_REQUEST, r->parse, ln, ppos,                          mandoc_msg(MANDOCERR_REQUEST, r->parse, ln, ppos,
                             roffs[tok].name);                              roffs[tok].name);
   
                 while ((*bufp)[pos] && ' ' != (*bufp)[pos])                  while ((*bufp)[pos] && ! isspace((unsigned char)(*bufp)[pos]))
                         pos++;                          pos++;
   
                 while (' ' == (*bufp)[pos])                  while (isspace((unsigned char)(*bufp)[pos]))
                         (*bufp)[pos++] = '\0';                          (*bufp)[pos++] = '\0';
         }          }
   
Line 763  roff_block(ROFF_ARGS)
Line 823  roff_block(ROFF_ARGS)
         /* If present, process the custom end-of-line marker. */          /* If present, process the custom end-of-line marker. */
   
         sv = pos;          sv = pos;
         while ((*bufp)[pos] &&          while ((*bufp)[pos] && ! isspace((unsigned char)(*bufp)[pos]))
                         ' ' != (*bufp)[pos] &&  
                         '\t' != (*bufp)[pos])  
                 pos++;                  pos++;
   
         /*          /*
Line 835  roff_block_sub(ROFF_ARGS)
Line 893  roff_block_sub(ROFF_ARGS)
          * pulling it out of the hashtable.           * pulling it out of the hashtable.
          */           */
   
         if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos)))          t = roff_parse(r, *bufp, &pos);
                 return(ROFF_IGN);  
   
         /*          /*
          * Macros other than block-end are only significant           * Macros other than block-end are only significant
Line 872  roff_cond_sub(ROFF_ARGS)
Line 929  roff_cond_sub(ROFF_ARGS)
 {  {
         enum rofft       t;          enum rofft       t;
         enum roffrule    rr;          enum roffrule    rr;
           char            *ep;
   
         rr = r->last->rule;          rr = r->last->rule;
           roffnode_cleanscope(r);
   
         /*          /*
          * Clean out scope.  If we've closed ourselves, then don't           * If the macro is unknown, first check if it contains a closing
          * continue.           * delimiter `\}'.  If it does, close out our scope and return
            * the currently-scoped rule (ignore or continue).  Else, drop
            * into the currently-scoped rule.
          */           */
   
         roffnode_cleanscope(r);  
   
         if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos))) {          if (ROFF_MAX == (t = roff_parse(r, *bufp, &pos))) {
                 if ('\\' == (*bufp)[pos] && '}' == (*bufp)[pos + 1])                  ep = &(*bufp)[pos];
                         return(roff_ccond                  for ( ; NULL != (ep = strchr(ep, '\\')); ep++) {
                                 (r, ROFF_ccond, bufp, szp,                          ep++;
                                  ln, pos, pos + 2, offs));                          if ('}' != *ep)
                                   continue;
   
                           /*
                            * Make the \} go away.
                            * This is a little haphazard, as it's not quite
                            * clear how nroff does this.
                            * If we're at the end of line, then just chop
                            * off the \} and resize the buffer.
                            * If we aren't, then conver it to spaces.
                            */
   
                           if ('\0' == *(ep + 1)) {
                                   *--ep = '\0';
                                   *szp -= 2;
                           } else
                                   *(ep - 1) = *ep = ' ';
   
                           roff_ccond(r, ROFF_ccond, bufp, szp,
                                           ln, pos, pos + 2, offs);
                           break;
                   }
                 return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);                  return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
         }          }
   
Line 895  roff_cond_sub(ROFF_ARGS)
Line 975  roff_cond_sub(ROFF_ARGS)
          * if they're either structurally required (such as loops and           * if they're either structurally required (such as loops and
          * conditionals) or a closing macro.           * conditionals) or a closing macro.
          */           */
   
         if (ROFFRULE_DENY == rr)          if (ROFFRULE_DENY == rr)
                 if ( ! (ROFFMAC_STRUCT & roffs[t].flags))                  if ( ! (ROFFMAC_STRUCT & roffs[t].flags))
                         if (ROFF_ccond != t)                          if (ROFF_ccond != t)
Line 905  roff_cond_sub(ROFF_ARGS)
Line 986  roff_cond_sub(ROFF_ARGS)
                                 ln, ppos, pos, offs));                                  ln, ppos, pos, offs));
 }  }
   
   
 /* ARGSUSED */  /* ARGSUSED */
 static enum rofferr  static enum rofferr
 roff_cond_text(ROFF_ARGS)  roff_cond_text(ROFF_ARGS)
 {  {
         char            *ep, *st;          char            *ep;
         enum roffrule    rr;          enum roffrule    rr;
   
         rr = r->last->rule;          rr = r->last->rule;
           roffnode_cleanscope(r);
   
         /*          ep = &(*bufp)[pos];
          * We display the value of the text if out current evaluation          for ( ; NULL != (ep = strchr(ep, '\\')); ep++) {
          * scope permits us to do so.                  ep++;
          */                  if ('}' != *ep)
                           continue;
         /* FIXME: use roff_ccond? */                  *ep = '&';
                   roff_ccond(r, ROFF_ccond, bufp, szp,
         st = &(*bufp)[pos];                                  ln, pos, pos + 2, offs);
         if (NULL == (ep = strstr(st, "\\}"))) {  
                 roffnode_cleanscope(r);  
                 return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);  
         }          }
   
         if (ep == st || (ep > st && '\\' != *(ep - 1)))  
                 roffnode_pop(r);  
   
         roffnode_cleanscope(r);  
         return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);          return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
 }  }
   
   
 static enum roffrule  static enum roffrule
 roff_evalcond(const char *v, int *pos)  roff_evalcond(const char *v, int *pos)
 {  {
Line 978  roff_cond(ROFF_ARGS)
Line 1050  roff_cond(ROFF_ARGS)
         int              sv;          int              sv;
         enum roffrule    rule;          enum roffrule    rule;
   
         /* Stack overflow! */          /*
            * An `.el' has no conditional body: it will consume the value
            * of the current rstack entry set in prior `ie' calls or
            * defaults to DENY.
            *
            * If we're not an `el', however, then evaluate the conditional.
            */
   
         if (ROFF_ie == tok && r->rstackpos == RSTACK_MAX - 1) {          rule = ROFF_el == tok ?
                 mandoc_msg(MANDOCERR_MEM, r->parse, ln, ppos, NULL);                  (r->rstackpos < 0 ?
                 return(ROFF_ERR);                   ROFFRULE_DENY : r->rstack[r->rstackpos--]) :
         }                  roff_evalcond(*bufp, &pos);
   
         /* First, evaluate the conditional. */  
   
         if (ROFF_el == tok) {  
                 /*  
                  * An `.el' will get the value of the current rstack  
                  * entry set in prior `ie' calls or defaults to DENY.  
                  */  
                 if (r->rstackpos < 0)  
                         rule = ROFFRULE_DENY;  
                 else  
                         rule = r->rstack[r->rstackpos];  
         } else  
                 rule = roff_evalcond(*bufp, &pos);  
   
         sv = pos;          sv = pos;
   
         while (' ' == (*bufp)[pos])          while (' ' == (*bufp)[pos])
                 pos++;                  pos++;
   
Line 1020  roff_cond(ROFF_ARGS)
Line 1083  roff_cond(ROFF_ARGS)
   
         r->last->rule = rule;          r->last->rule = rule;
   
           /*
            * An if-else will put the NEGATION of the current evaluated
            * conditional into the stack of rules.
            */
   
         if (ROFF_ie == tok) {          if (ROFF_ie == tok) {
                 /*                  if (r->rstackpos == RSTACK_MAX - 1) {
                  * An if-else will put the NEGATION of the current                          mandoc_msg(MANDOCERR_MEM,
                  * evaluated conditional into the stack.                                  r->parse, ln, ppos, NULL);
                  */                          return(ROFF_ERR);
                 r->rstackpos++;                  }
                 if (ROFFRULE_DENY == r->last->rule)                  r->rstack[++r->rstackpos] =
                         r->rstack[r->rstackpos] = ROFFRULE_ALLOW;                          ROFFRULE_DENY == r->last->rule ?
                 else                          ROFFRULE_ALLOW : ROFFRULE_DENY;
                         r->rstack[r->rstackpos] = ROFFRULE_DENY;  
         }          }
   
         /* If the parent has false as its rule, then so do we. */          /* If the parent has false as its rule, then so do we. */
Line 1095  roff_ds(ROFF_ARGS)
Line 1162  roff_ds(ROFF_ARGS)
         return(ROFF_IGN);          return(ROFF_IGN);
 }  }
   
   int
   roff_regisset(const struct roff *r, enum regs reg)
   {
   
           return(r->regs[(int)reg].set);
   }
   
   unsigned int
   roff_regget(const struct roff *r, enum regs reg)
   {
   
           return(r->regs[(int)reg].u);
   }
   
   void
   roff_regunset(struct roff *r, enum regs reg)
   {
   
           r->regs[(int)reg].set = 0;
   }
   
 /* ARGSUSED */  /* ARGSUSED */
 static enum rofferr  static enum rofferr
 roff_nr(ROFF_ARGS)  roff_nr(ROFF_ARGS)
 {  {
         const char      *key;          const char      *key;
         char            *val;          char            *val;
         struct reg      *rg;          int              iv;
   
         val = *bufp + pos;          val = *bufp + pos;
         key = roff_getname(r, &val, ln, pos);          key = roff_getname(r, &val, ln, pos);
         rg = r->regs->regs;  
   
         if (0 == strcmp(key, "nS")) {          if (0 == strcmp(key, "nS")) {
                 rg[(int)REG_nS].set = 1;                  r->regs[(int)REG_nS].set = 1;
                 if ( ! roff_parse_nat(val, &rg[(int)REG_nS].v.u))                  if ((iv = mandoc_strntoi(val, strlen(val), 10)) >= 0)
                         rg[(int)REG_nS].v.u = 0;                          r->regs[(int)REG_nS].u = (unsigned)iv;
                   else
                           r->regs[(int)REG_nS].u = 0u;
         }          }
   
         return(ROFF_IGN);          return(ROFF_IGN);
Line 1141  roff_TE(ROFF_ARGS)
Line 1229  roff_TE(ROFF_ARGS)
         if (NULL == r->tbl)          if (NULL == r->tbl)
                 mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);                  mandoc_msg(MANDOCERR_NOSCOPE, r->parse, ln, ppos, NULL);
         else          else
                 tbl_end(r->tbl);                  tbl_end(&r->tbl);
   
         r->tbl = NULL;  
         return(ROFF_IGN);          return(ROFF_IGN);
 }  }
   
Line 1160  roff_T_(ROFF_ARGS)
Line 1247  roff_T_(ROFF_ARGS)
         return(ROFF_IGN);          return(ROFF_IGN);
 }  }
   
 /* ARGSUSED */  int
 static enum rofferr  roff_closeeqn(struct roff *r)
 roff_EQ(ROFF_ARGS)  
 {  {
         struct eqn_node *e;  
   
           return(r->eqn && ROFF_EQN == eqn_end(&r->eqn) ? 1 : 0);
   }
   
   void
   roff_openeqn(struct roff *r, const char *name, int line,
                   int offs, const char *buf)
   {
           struct eqn_node *e;
           int              poff;
   
         assert(NULL == r->eqn);          assert(NULL == r->eqn);
         e = eqn_alloc(ppos, ln);          e = eqn_alloc(name, offs, line, r->parse);
   
         if (r->last_eqn)          if (r->last_eqn)
                 r->last_eqn->next = e;                  r->last_eqn->next = e;
Line 1175  roff_EQ(ROFF_ARGS)
Line 1270  roff_EQ(ROFF_ARGS)
                 r->first_eqn = r->last_eqn = e;                  r->first_eqn = r->last_eqn = e;
   
         r->eqn = r->last_eqn = e;          r->eqn = r->last_eqn = e;
   
           if (buf) {
                   poff = 0;
                   eqn_read(&r->eqn, line, buf, offs, &poff);
           }
   }
   
   /* ARGSUSED */
   static enum rofferr
   roff_EQ(ROFF_ARGS)
   {
   
           roff_openeqn(r, *bufp + pos, ln, ppos, NULL);
         return(ROFF_IGN);          return(ROFF_IGN);
 }  }
   
Line 1195  roff_TS(ROFF_ARGS)
Line 1303  roff_TS(ROFF_ARGS)
   
         if (r->tbl) {          if (r->tbl) {
                 mandoc_msg(MANDOCERR_SCOPEBROKEN, r->parse, ln, ppos, NULL);                  mandoc_msg(MANDOCERR_SCOPEBROKEN, r->parse, ln, ppos, NULL);
                 tbl_end(r->tbl);                  tbl_end(&r->tbl);
         }          }
   
         t = tbl_alloc(ppos, ln, r->parse);          t = tbl_alloc(ppos, ln, r->parse);
Line 1430  roff_eqn(const struct roff *r)
Line 1538  roff_eqn(const struct roff *r)
 {  {
   
         return(r->last_eqn ? &r->last_eqn->eqn : NULL);          return(r->last_eqn ? &r->last_eqn->eqn : NULL);
   }
   
   char
   roff_eqndelim(const struct roff *r)
   {
   
           return('\0');
 }  }

Legend:
Removed from v.1.130  
changed lines
  Added in v.1.154

CVSweb