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

Diff for /mandoc/roff.c between version 1.197 and 1.198

version 1.197, 2014/03/07 18:37:37 version 1.198, 2014/03/08 04:43:54
Line 76  enum rofft {
Line 76  enum rofft {
         ROFF_MAX          ROFF_MAX
 };  };
   
 enum    roffrule {  
         ROFFRULE_DENY,  
         ROFFRULE_ALLOW  
 };  
   
 /*  /*
  * An incredibly-simple string buffer.   * An incredibly-simple string buffer.
  */   */
Line 112  struct roff {
Line 107  struct roff {
         struct mparse   *parse; /* parse point */          struct mparse   *parse; /* parse point */
         int              quick; /* skip standard macro deletion */          int              quick; /* skip standard macro deletion */
         struct roffnode *last; /* leaf of stack */          struct roffnode *last; /* leaf of stack */
         enum roffrule    rstack[RSTACK_MAX]; /* stack of !`ie' rules */          int              rstack[RSTACK_MAX]; /* stack of !`ie' rules */
         char             control; /* control character */          char             control; /* control character */
         int              rstackpos; /* position in rstack */          int              rstackpos; /* position in rstack */
         struct roffreg  *regtab; /* number registers */          struct roffreg  *regtab; /* number registers */
Line 136  struct roffnode {
Line 131  struct roffnode {
         char            *name; /* node name, e.g. macro name */          char            *name; /* node name, e.g. macro name */
         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; /* current evaluation rule */          int              rule; /* current evaluation rule */
 };  };
   
 #define ROFF_ARGS        struct roff *r, /* parse ctx */ \  #define ROFF_ARGS        struct roff *r, /* parse ctx */ \
Line 184  static enum rofferr  roff_cond(ROFF_ARGS);
Line 179  static enum rofferr  roff_cond(ROFF_ARGS);
 static  enum rofferr     roff_cond_text(ROFF_ARGS);  static  enum rofferr     roff_cond_text(ROFF_ARGS);
 static  enum rofferr     roff_cond_sub(ROFF_ARGS);  static  enum rofferr     roff_cond_sub(ROFF_ARGS);
 static  enum rofferr     roff_ds(ROFF_ARGS);  static  enum rofferr     roff_ds(ROFF_ARGS);
 static  enum roffrule    roff_evalcond(const char *, int *);  static  int              roff_evalcond(const char *, int *);
   static  int              roff_evalstrcond(const char *, int *);
 static  void             roff_free1(struct roff *);  static  void             roff_free1(struct roff *);
 static  void             roff_freereg(struct roffreg *);  static  void             roff_freereg(struct roffreg *);
 static  void             roff_freestr(struct roffkv *);  static  void             roff_freestr(struct roffkv *);
Line 401  roffnode_push(struct roff *r, enum rofft tok, const ch
Line 397  roffnode_push(struct roff *r, enum rofft tok, const ch
         p->parent = r->last;          p->parent = r->last;
         p->line = line;          p->line = line;
         p->col = col;          p->col = col;
         p->rule = p->parent ? p->parent->rule : ROFFRULE_DENY;          p->rule = p->parent ? p->parent->rule : 0;
   
         r->last = p;          r->last = p;
 }  }
Line 1050  static enum rofferr
Line 1046  static enum rofferr
 roff_cond_sub(ROFF_ARGS)  roff_cond_sub(ROFF_ARGS)
 {  {
         enum rofft       t;          enum rofft       t;
         enum roffrule    rr;  
         char            *ep;          char            *ep;
           int              rr;
   
         rr = r->last->rule;          rr = r->last->rule;
         roffnode_cleanscope(r);          roffnode_cleanscope(r);
Line 1063  roff_cond_sub(ROFF_ARGS)
Line 1059  roff_cond_sub(ROFF_ARGS)
          */           */
   
         if ((ROFF_MAX != t) &&          if ((ROFF_MAX != t) &&
             (ROFFRULE_ALLOW == rr ||              (rr || ROFFMAC_STRUCT & roffs[t].flags)) {
              ROFFMAC_STRUCT & roffs[t].flags)) {  
                 assert(roffs[t].proc);                  assert(roffs[t].proc);
                 return((*roffs[t].proc)(r, t, bufp, szp,                  return((*roffs[t].proc)(r, t, bufp, szp,
                                         ln, ppos, pos, offs));                                          ln, ppos, pos, offs));
Line 1077  roff_cond_sub(ROFF_ARGS)
Line 1072  roff_cond_sub(ROFF_ARGS)
   
         ep = *bufp + pos;          ep = *bufp + pos;
         if ('\\' == ep[0] && '}' == ep[1])          if ('\\' == ep[0] && '}' == ep[1])
                 rr = ROFFRULE_DENY;                  rr = 0;
   
         /* Always check for the closing delimiter `\}'. */          /* Always check for the closing delimiter `\}'. */
   
Line 1088  roff_cond_sub(ROFF_ARGS)
Line 1083  roff_cond_sub(ROFF_ARGS)
                 }                  }
                 ++ep;                  ++ep;
         }          }
         return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);          return(rr ? ROFF_CONT : ROFF_IGN);
 }  }
   
 /* ARGSUSED */  /* ARGSUSED */
Line 1096  static enum rofferr
Line 1091  static enum rofferr
 roff_cond_text(ROFF_ARGS)  roff_cond_text(ROFF_ARGS)
 {  {
         char            *ep;          char            *ep;
         enum roffrule    rr;          int              rr;
   
         rr = r->last->rule;          rr = r->last->rule;
         roffnode_cleanscope(r);          roffnode_cleanscope(r);
Line 1109  roff_cond_text(ROFF_ARGS)
Line 1104  roff_cond_text(ROFF_ARGS)
                 }                  }
                 ++ep;                  ++ep;
         }          }
         return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);          return(rr ? ROFF_CONT : ROFF_IGN);
 }  }
   
 static int  static int
Line 1162  roff_getop(const char *v, int *pos, char *res)
Line 1157  roff_getop(const char *v, int *pos, char *res)
         return(*res);          return(*res);
 }  }
   
 static enum roffrule  /*
    * Evaluate a string comparison condition.
    * The first character is the delimiter.
    * Succeed if the string up to its second occurrence
    * matches the string up to its third occurence.
    * Advance the cursor after the third occurrence
    * or lacking that, to the end of the line.
    */
   static int
   roff_evalstrcond(const char *v, int *pos)
   {
           const char      *s1, *s2, *s3;
           int              match;
   
           match = 0;
           s1 = v + *pos;          /* initial delimiter */
           s2 = s1 + 1;            /* for scanning the first string */
           s3 = strchr(s2, *s1);   /* for scanning the second string */
   
           if (NULL == s3)         /* found no middle delimiter */
                   goto out;
   
           while ('\0' != *++s3) {
                   if (*s2 != *s3) {  /* mismatch */
                           s3 = strchr(s3, *s1);
                           break;
                   }
                   if (*s3 == *s1) {  /* found the final delimiter */
                           match = 1;
                           break;
                   }
                   s2++;
           }
   
   out:
           if (NULL == s3)
                   s3 = strchr(s2, '\0');
           else
                   s3++;
           *pos = s3 - v;
           return(match);
   }
   
   static int
 roff_evalcond(const char *v, int *pos)  roff_evalcond(const char *v, int *pos)
 {  {
         int      not, lh, rh;          int      wanttrue, lh, rh;
         char     op;          char     op;
   
           if ('!' == v[*pos]) {
                   wanttrue = 0;
                   (*pos)++;
           } else
                   wanttrue = 1;
   
         switch (v[*pos]) {          switch (v[*pos]) {
         case ('n'):          case ('n'):
                   /* FALLTHROUGH */
           case ('o'):
                 (*pos)++;                  (*pos)++;
                 return(ROFFRULE_ALLOW);                  return(wanttrue);
           case ('c'):
                   /* FALLTHROUGH */
           case ('d'):
                   /* FALLTHROUGH */
         case ('e'):          case ('e'):
                 /* FALLTHROUGH */                  /* FALLTHROUGH */
         case ('o'):          case ('r'):
                 /* FALLTHROUGH */                  /* FALLTHROUGH */
         case ('t'):          case ('t'):
                 (*pos)++;                  (*pos)++;
                 return(ROFFRULE_DENY);                  return(!wanttrue);
         case ('!'):  
                 (*pos)++;  
                 not = 1;  
                 break;  
         default:          default:
                 not = 0;  
                 break;                  break;
         }          }
   
         if (!roff_getnum(v, pos, &lh))          if (!roff_getnum(v, pos, &lh))
                 return ROFFRULE_DENY;                  return(roff_evalstrcond(v, pos) == wanttrue);
         if (!roff_getop(v, pos, &op)) {          if (!roff_getop(v, pos, &op))
                 if (lh < 0)                  return((lh > 0) == wanttrue);
                         lh = 0;  
                 goto out;  
         }  
         if (!roff_getnum(v, pos, &rh))          if (!roff_getnum(v, pos, &rh))
                 return ROFFRULE_DENY;                  return(0);
   
         switch (op) {          switch (op) {
         case 'g':          case 'g':
                 lh = lh >= rh;                  return((lh >= rh) == wanttrue);
                 break;  
         case 'l':          case 'l':
                 lh = lh <= rh;                  return((lh <= rh) == wanttrue);
                 break;  
         case '=':          case '=':
                 lh = lh == rh;                  return((lh == rh) == wanttrue);
                 break;  
         case '>':          case '>':
                 lh = lh > rh;                  return((lh > rh) == wanttrue);
                 break;  
         case '<':          case '<':
                 lh = lh < rh;                  return((lh < rh) == wanttrue);
                 break;  
         default:          default:
                 return ROFFRULE_DENY;                  return(0);
         }          }
 out:  
         if (not)  
                 lh = !lh;  
         return lh ? ROFFRULE_ALLOW : ROFFRULE_DENY;  
 }  }
   
 /* ARGSUSED */  /* ARGSUSED */
Line 1246  roff_cond(ROFF_ARGS)
Line 1280  roff_cond(ROFF_ARGS)
          */           */
   
         r->last->rule = ROFF_el == tok ?          r->last->rule = ROFF_el == tok ?
                 (r->rstackpos < 0 ?                  (r->rstackpos < 0 ? 0 : r->rstack[r->rstackpos--]) :
                  ROFFRULE_DENY : r->rstack[r->rstackpos--]) :  
                 roff_evalcond(*bufp, &pos);                  roff_evalcond(*bufp, &pos);
   
         /*          /*
Line 1261  roff_cond(ROFF_ARGS)
Line 1294  roff_cond(ROFF_ARGS)
                                 r->parse, ln, ppos, NULL);                                  r->parse, ln, ppos, NULL);
                         return(ROFF_ERR);                          return(ROFF_ERR);
                 }                  }
                 r->rstack[++r->rstackpos] =                  r->rstack[++r->rstackpos] = !r->last->rule;
                         ROFFRULE_DENY == r->last->rule ?  
                         ROFFRULE_ALLOW : 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. */
   
         if (r->last->parent && ROFFRULE_DENY == r->last->parent->rule)          if (r->last->parent && !r->last->parent->rule)
                 r->last->rule = ROFFRULE_DENY;                  r->last->rule = 0;
   
         /*          /*
          * Determine scope.           * Determine scope.

Legend:
Removed from v.1.197  
changed lines
  Added in v.1.198

CVSweb