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

Diff for /mandoc/roff.c between version 1.81 and 1.82

version 1.81, 2010/05/17 00:46:35 version 1.82, 2010/05/17 02:01:05
Line 26 
Line 26 
 #include "mandoc.h"  #include "mandoc.h"
 #include "roff.h"  #include "roff.h"
   
   #define RSTACK_MAX      128
   
 #define ROFF_CTL(c) \  #define ROFF_CTL(c) \
         ('.' == (c) || '\'' == (c))          ('.' == (c) || '\'' == (c))
   
Line 36  enum rofft {
Line 38  enum rofft {
         ROFF_de,          ROFF_de,
         ROFF_dei,          ROFF_dei,
         ROFF_de1,          ROFF_de1,
           ROFF_el,
           ROFF_ie,
         ROFF_if,          ROFF_if,
         ROFF_ig,          ROFF_ig,
         ROFF_cblock,          ROFF_cblock,
         ROFF_ccond,          ROFF_ccond,
 #if 0  
         ROFF_ie,  
         ROFF_el,  
 #endif  
         ROFF_MAX          ROFF_MAX
 };  };
   
   enum    roffrule {
           ROFFRULE_ALLOW,
           ROFFRULE_DENY
   };
   
 struct  roff {  struct  roff {
         struct roffnode *last; /* leaf of stack */          struct roffnode *last; /* leaf of stack */
         mandocmsg        msg; /* err/warn/fatal messages */          mandocmsg        msg; /* err/warn/fatal messages */
         void            *data; /* privdata for messages */          void            *data; /* privdata for messages */
           enum roffrule    rstack[RSTACK_MAX]; /* stack of !`ie' rules */
           int              rstackpos; /* position in rstack */
 };  };
   
 enum    roffrule {  
         ROFFRULE_ALLOW,  
         ROFFRULE_DENY  
 };  
   
 struct  roffnode {  struct  roffnode {
         enum rofft       tok; /* type of node */          enum rofft       tok; /* type of node */
         struct roffnode *parent; /* up one in stack */          struct roffnode *parent; /* up one in stack */
Line 65  struct roffnode {
Line 67  struct roffnode {
         int              col; /* parse col */          int              col; /* parse col */
         char            *end; /* end-rules: custom token */          char            *end; /* end-rules: custom token */
         int              endspan; /* end-rules: next-line or infty */          int              endspan; /* end-rules: next-line or infty */
         enum roffrule    rule;          enum roffrule    rule; /* current evaluation rule */
 };  };
   
 #define ROFF_ARGS        struct roff *r, /* parse ctx */ \  #define ROFF_ARGS        struct roff *r, /* parse ctx */ \
Line 93  static enum rofferr  roff_block_text(ROFF_ARGS);
Line 95  static enum rofferr  roff_block_text(ROFF_ARGS);
 static  enum rofferr     roff_block_sub(ROFF_ARGS);  static  enum rofferr     roff_block_sub(ROFF_ARGS);
 static  enum rofferr     roff_cblock(ROFF_ARGS);  static  enum rofferr     roff_cblock(ROFF_ARGS);
 static  enum rofferr     roff_ccond(ROFF_ARGS);  static  enum rofferr     roff_ccond(ROFF_ARGS);
 static  enum rofferr     roff_if(ROFF_ARGS);  static  enum rofferr     roff_cond(ROFF_ARGS);
 static  enum rofferr     roff_if_text(ROFF_ARGS);  static  enum rofferr     roff_cond_text(ROFF_ARGS);
 static  enum rofferr     roff_if_sub(ROFF_ARGS);  static  enum rofferr     roff_cond_sub(ROFF_ARGS);
   
 const   struct roffmac   roffs[ROFF_MAX] = {  const   struct roffmac   roffs[ROFF_MAX] = {
         { "am", roff_block, roff_block_text, roff_block_sub, 0 },          { "am", roff_block, roff_block_text, roff_block_sub, 0 },
Line 104  const struct roffmac  roffs[ROFF_MAX] = {
Line 106  const struct roffmac  roffs[ROFF_MAX] = {
         { "de", roff_block, roff_block_text, roff_block_sub, 0 },          { "de", roff_block, roff_block_text, roff_block_sub, 0 },
         { "dei", roff_block, roff_block_text, roff_block_sub, 0 },          { "dei", roff_block, roff_block_text, roff_block_sub, 0 },
         { "de1", roff_block, roff_block_text, roff_block_sub, 0 },          { "de1", roff_block, roff_block_text, roff_block_sub, 0 },
         { "if", roff_if, roff_if_text, roff_if_sub, ROFFMAC_STRUCT },          { "el", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT },
           { "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT },
           { "if", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT },
         { "ig", roff_block, roff_block_text, roff_block_sub, 0 },          { "ig", roff_block, roff_block_text, roff_block_sub, 0 },
         { ".", roff_cblock, NULL, NULL, 0 },          { ".", roff_cblock, NULL, NULL, 0 },
         { "\\}", roff_ccond, NULL, NULL, 0 },          { "\\}", roff_ccond, NULL, NULL, 0 },
Line 149  roffnode_pop(struct roff *r)
Line 153  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;
         if (p->end)          if (p->end)
                 free(p->end);                  free(p->end);
Line 219  roff_alloc(const mandocmsg msg, void *data)
Line 228  roff_alloc(const mandocmsg msg, void *data)
   
         r->msg = msg;          r->msg = msg;
         r->data = data;          r->data = data;
           r->rstackpos = -1;
         return(r);          return(r);
 }  }
   
Line 306  roff_parse(const char *buf, int *pos)
Line 316  roff_parse(const char *buf, int *pos)
         for (j = 0; j < 4; j++, (*pos)++)          for (j = 0; j < 4; j++, (*pos)++)
                 if ('\0' == (mac[j] = buf[*pos]))                  if ('\0' == (mac[j] = buf[*pos]))
                         break;                          break;
                 else if (' ' == buf[*pos])                  else if (' ' == buf[*pos] || (j && '\\' == buf[*pos]))
                         break;                          break;
   
         if (j == 4 || j < 1)          if (j == 4 || j < 1)
Line 395  roff_ccond(ROFF_ARGS)
Line 405  roff_ccond(ROFF_ARGS)
                 return(ROFF_IGN);                  return(ROFF_IGN);
         }          }
   
         if (ROFF_if != r->last->tok) {          switch (r->last->tok) {
           case (ROFF_el):
                   /* FALLTHROUGH */
           case (ROFF_ie):
                   /* FALLTHROUGH */
           case (ROFF_if):
                   break;
           default:
                 if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL))                  if ( ! (*r->msg)(MANDOCERR_NOSCOPE, r->data, ln, ppos, NULL))
                         return(ROFF_ERR);                          return(ROFF_ERR);
                 return(ROFF_IGN);                  return(ROFF_IGN);
Line 478  roff_block(ROFF_ARGS)
Line 495  roff_block(ROFF_ARGS)
   
 /* ARGSUSED */  /* ARGSUSED */
 static enum rofferr  static enum rofferr
 roff_if_sub(ROFF_ARGS)  
 {  
         enum rofft       t;  
         enum roffrule    rr;  
   
         ppos = pos;  
         rr = r->last->rule;  
         roffnode_cleanscope(r);  
   
         if (ROFF_MAX == (t = roff_parse(*bufp, &pos)))  
                 return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);  
   
         /*  
          * A denied conditional must evaluate its children if and only  
          * if they're either structurally required (such as loops and  
          * conditionals) or a closing macro.  
          */  
         if (ROFFRULE_DENY == rr)  
                 if ( ! (ROFFMAC_STRUCT & roffs[t].flags))  
                         if (ROFF_ccond != t)  
                                 return(ROFF_IGN);  
   
         assert(roffs[t].proc);  
         return((*roffs[t].proc)  
                         (r, t, bufp, szp, ln, ppos, pos, offs));  
 }  
   
   
 /* ARGSUSED */  
 static enum rofferr  
 roff_block_sub(ROFF_ARGS)  roff_block_sub(ROFF_ARGS)
 {  {
         enum rofft      t;          enum rofft      t;
Line 573  roff_block_text(ROFF_ARGS)
Line 560  roff_block_text(ROFF_ARGS)
   
 /* ARGSUSED */  /* ARGSUSED */
 static enum rofferr  static enum rofferr
 roff_if_text(ROFF_ARGS)  roff_cond_sub(ROFF_ARGS)
 {  {
           enum rofft       t;
           enum roffrule    rr;
   
           ppos = pos;
           rr = r->last->rule;
   
           roffnode_cleanscope(r);
   
           if (ROFF_MAX == (t = roff_parse(*bufp, &pos)))
                   return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
   
           /*
            * A denied conditional must evaluate its children if and only
            * if they're either structurally required (such as loops and
            * conditionals) or a closing macro.
            */
           if (ROFFRULE_DENY == rr)
                   if ( ! (ROFFMAC_STRUCT & roffs[t].flags))
                           if (ROFF_ccond != t)
                                   return(ROFF_IGN);
   
           assert(roffs[t].proc);
           return((*roffs[t].proc)
                           (r, t, bufp, szp, ln, ppos, pos, offs));
   }
   
   
   /* ARGSUSED */
   static enum rofferr
   roff_cond_text(ROFF_ARGS)
   {
         char            *ep, *st;          char            *ep, *st;
           enum roffrule    rr;
   
           rr = r->last->rule;
   
           /*
            * We display the value of the text if out current evaluation
            * scope permits us to do so.
            */
   
         st = &(*bufp)[pos];          st = &(*bufp)[pos];
         if (NULL == (ep = strstr(st, "\\}"))) {          if (NULL == (ep = strstr(st, "\\}"))) {
                 roffnode_cleanscope(r);                  roffnode_cleanscope(r);
                 return(ROFF_IGN);                  return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
         }          }
   
         if (ep > st && '\\' != *(ep - 1))          if (ep > st && '\\' != *(ep - 1))
                 roffnode_pop(r);                  roffnode_pop(r);
   
         roffnode_cleanscope(r);          roffnode_cleanscope(r);
         return(ROFF_IGN);          return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
 }  }
   
   
 /* ARGSUSED */  /* ARGSUSED */
 static enum rofferr  static enum rofferr
 roff_if(ROFF_ARGS)  roff_cond(ROFF_ARGS)
 {  {
         int              sv;          int              sv;
   
         /*          /* Stack overflow! */
          * Read ahead past the conditional.  
          * FIXME: this does not work, as conditionals don't end on  
          * whitespace, but are parsed according to a formal grammar.  
          * It's good enough for now, however.  
          */  
   
         while ((*bufp)[pos] && ' ' != (*bufp)[pos])          if (ROFF_ie == tok && r->rstackpos == RSTACK_MAX - 1) {
                 pos++;                  (*r->msg)(MANDOCERR_MEM, r->data, ln, ppos, NULL);
                   return(ROFF_ERR);
           }
   
           if (ROFF_if == tok || ROFF_ie == tok) {
                   /*
                    * Read ahead past the conditional.  FIXME: this does
                    * not work, as conditionals don't end on whitespace,
                    * but are parsed according to a formal grammar.  It's
                    * good enough for now, however.
                    */
                   while ((*bufp)[pos] && ' ' != (*bufp)[pos])
                           pos++;
           }
   
         sv = pos;          sv = pos;
         while (' ' == (*bufp)[pos])          while (' ' == (*bufp)[pos])
                 pos++;                  pos++;
Line 617  roff_if(ROFF_ARGS)
Line 651  roff_if(ROFF_ARGS)
          * really doing anything.  Warn about this.  It's probably           * really doing anything.  Warn about this.  It's probably
          * wrong.           * wrong.
          */           */
   
         if ('\0' == (*bufp)[pos] && sv != pos) {          if ('\0' == (*bufp)[pos] && sv != pos) {
                 if ( ! (*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL))                  if ( ! (*r->msg)(MANDOCERR_NOARGS, r->data, ln, ppos, NULL))
                         return(ROFF_ERR);                          return(ROFF_ERR);
Line 627  roff_if(ROFF_ARGS)
Line 660  roff_if(ROFF_ARGS)
         if ( ! roffnode_push(r, tok, ln, ppos))          if ( ! roffnode_push(r, tok, ln, ppos))
                 return(ROFF_ERR);                  return(ROFF_ERR);
   
         /* Don't evaluate: just assume NO. */          /* TODO: here we would 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)
                           r->last->rule = ROFFRULE_DENY;
                   else
                           r->last->rule = r->rstack[r->rstackpos];
           } else if (ROFF_ie == tok) {
                   /*
                    * An if-else will put the NEGATION of the current
                    * evaluated conditional into the stack.
                    */
                   r->rstackpos++;
                   if (ROFFRULE_DENY == r->last->rule)
                           r->rstack[r->rstackpos] = ROFFRULE_ALLOW;
                   else
                           r->rstack[r->rstackpos] = ROFFRULE_DENY;
           }
   
         r->last->endspan = 1;          r->last->endspan = 1;
   

Legend:
Removed from v.1.81  
changed lines
  Added in v.1.82

CVSweb