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

Diff for /mandoc/roff.c between version 1.203 and 1.204

version 1.203, 2014/04/05 20:34:57 version 1.204, 2014/04/07 15:07:13
Line 181  static enum rofferr  roff_cond_text(ROFF_ARGS);
Line 181  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  int              roff_evalcond(const char *, int *);  static  int              roff_evalcond(const char *, int *);
   static  int              roff_evalnum(const char *, int *, int *, int);
   static  int              roff_evalpar(const char *, int *, int *);
 static  int              roff_evalstrcond(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 *);
Line 1107  roff_cond_text(ROFF_ARGS)
Line 1109  roff_cond_text(ROFF_ARGS)
         return(rr ? ROFF_CONT : ROFF_IGN);          return(rr ? ROFF_CONT : ROFF_IGN);
 }  }
   
   /*
    * Parse a single signed integer number.  Stop at the first non-digit.
    * If there is at least one digit, return success and advance the
    * parse point, else return failure and let the parse point unchanged.
    * Ignore overflows, treat them just like the C language.
    */
 static int  static int
 roff_getnum(const char *v, int *pos, int *res)  roff_getnum(const char *v, int *pos, int *res)
 {  {
Line 1118  roff_getnum(const char *v, int *pos, int *res)
Line 1126  roff_getnum(const char *v, int *pos, int *res)
                 p++;                  p++;
   
         for (*res = 0; isdigit((unsigned char)v[p]); p++)          for (*res = 0; isdigit((unsigned char)v[p]); p++)
                 *res += 10 * *res + v[p] - '0';                  *res = 10 * *res + v[p] - '0';
         if (p == *pos + n)          if (p == *pos + n)
                 return 0;                  return 0;
   
Line 1129  roff_getnum(const char *v, int *pos, int *res)
Line 1137  roff_getnum(const char *v, int *pos, int *res)
         return 1;          return 1;
 }  }
   
 static int  
 roff_getop(const char *v, int *pos, char *res)  
 {  
         int e;  
   
         *res = v[*pos];  
         e = v[*pos + 1] == '=';  
   
         switch (*res) {  
         case '=':  
                 break;  
         case '>':  
                 if (e)  
                         *res = 'g';  
                 break;  
         case '<':  
                 if (e)  
                         *res = 'l';  
                 break;  
         default:  
                 return(0);  
         }  
   
         *pos += 1 + e;  
   
         return(*res);  
 }  
   
 /*  /*
  * Evaluate a string comparison condition.   * Evaluate a string comparison condition.
  * The first character is the delimiter.   * The first character is the delimiter.
Line 1200  out:
Line 1180  out:
         return(match);          return(match);
 }  }
   
   /*
    * Evaluate an optionally negated single character, numerical,
    * or string condition.
    */
 static int  static int
 roff_evalcond(const char *v, int *pos)  roff_evalcond(const char *v, int *pos)
 {  {
         int      wanttrue, lh, rh;          int      wanttrue, number;
         char     op;  
   
         if ('!' == v[*pos]) {          if ('!' == v[*pos]) {
                 wanttrue = 0;                  wanttrue = 0;
Line 1233  roff_evalcond(const char *v, int *pos)
Line 1216  roff_evalcond(const char *v, int *pos)
                 break;                  break;
         }          }
   
         if (!roff_getnum(v, pos, &lh))          if (roff_evalnum(v, pos, &number, 0))
                   return((number > 0) == wanttrue);
           else
                 return(roff_evalstrcond(v, pos) == wanttrue);                  return(roff_evalstrcond(v, pos) == wanttrue);
         if (!roff_getop(v, pos, &op))  
                 return((lh > 0) == wanttrue);  
         if (!roff_getnum(v, pos, &rh))  
                 return(0);  
   
         switch (op) {  
         case 'g':  
                 return((lh >= rh) == wanttrue);  
         case 'l':  
                 return((lh <= rh) == wanttrue);  
         case '=':  
                 return((lh == rh) == wanttrue);  
         case '>':  
                 return((lh > rh) == wanttrue);  
         case '<':  
                 return((lh < rh) == wanttrue);  
         default:  
                 return(0);  
         }  
 }  }
   
 /* ARGSUSED */  /* ARGSUSED */
Line 1371  roff_ds(ROFF_ARGS)
Line 1337  roff_ds(ROFF_ARGS)
         return(ROFF_IGN);          return(ROFF_IGN);
 }  }
   
   /*
    * Parse a single operator, one or two characters long.
    * If the operator is recognized, return success and advance the
    * parse point, else return failure and let the parse point unchanged.
    */
   static int
   roff_getop(const char *v, int *pos, char *res)
   {
   
           *res = v[*pos];
   
           switch (*res) {
           case ('+'):
                   /* FALLTHROUGH */
           case ('-'):
                   /* FALLTHROUGH */
           case ('*'):
                   /* FALLTHROUGH */
           case ('/'):
                   /* FALLTHROUGH */
           case ('%'):
                   /* FALLTHROUGH */
           case ('&'):
                   /* FALLTHROUGH */
           case (':'):
                   break;
           case '<':
                   switch (v[*pos + 1]) {
                   case ('='):
                           *res = 'l';
                           (*pos)++;
                           break;
                   case ('>'):
                           *res = '!';
                           (*pos)++;
                           break;
                   case ('?'):
                           *res = 'i';
                           (*pos)++;
                           break;
                   default:
                           break;
                   }
                   break;
           case '>':
                   switch (v[*pos + 1]) {
                   case ('='):
                           *res = 'g';
                           (*pos)++;
                           break;
                   case ('?'):
                           *res = 'a';
                           (*pos)++;
                           break;
                   default:
                           break;
                   }
                   break;
           case '=':
                   if ('=' == v[*pos + 1])
                           (*pos)++;
                   break;
           default:
                   return(0);
           }
           (*pos)++;
   
           return(*res);
   }
   
   /*
    * Evaluate either a parenthesized numeric expression
    * or a single signed integer number.
    */
   static int
   roff_evalpar(const char *v, int *pos, int *res)
   {
   
           if ('(' != v[*pos])
                   return(roff_getnum(v, pos, res));
   
           (*pos)++;
           if ( ! roff_evalnum(v, pos, res, 1))
                   return(0);
   
           /* If the trailing parenthesis is missing, ignore the error. */
           if (')' == v[*pos])
                   (*pos)++;
   
           return(1);
   }
   
   /*
    * Evaluate a complete numeric expression.
    * Proceed left to right, there is no concept of precedence.
    */
   static int
   roff_evalnum(const char *v, int *pos, int *res, int skipwhite)
   {
           int              mypos, operand2;
           char             operator;
   
           if (NULL == pos) {
                   mypos = 0;
                   pos = &mypos;
           }
   
           if (skipwhite)
                   while (isspace((unsigned char)v[*pos]))
                           (*pos)++;
   
           if ( ! roff_evalpar(v, pos, res))
                   return(0);
   
           while (1) {
                   if (skipwhite)
                           while (isspace((unsigned char)v[*pos]))
                                   (*pos)++;
   
                   if ( ! roff_getop(v, pos, &operator))
                           break;
   
                   if (skipwhite)
                           while (isspace((unsigned char)v[*pos]))
                                   (*pos)++;
   
                   if ( ! roff_evalpar(v, pos, &operand2))
                           return(0);
   
                   if (skipwhite)
                           while (isspace((unsigned char)v[*pos]))
                                   (*pos)++;
   
                   switch (operator) {
                   case ('+'):
                           *res += operand2;
                           break;
                   case ('-'):
                           *res -= operand2;
                           break;
                   case ('*'):
                           *res *= operand2;
                           break;
                   case ('/'):
                           *res /= operand2;
                           break;
                   case ('%'):
                           *res %= operand2;
                           break;
                   case ('<'):
                           *res = *res < operand2;
                           break;
                   case ('>'):
                           *res = *res > operand2;
                           break;
                   case ('l'):
                           *res = *res <= operand2;
                           break;
                   case ('g'):
                           *res = *res >= operand2;
                           break;
                   case ('='):
                           *res = *res == operand2;
                           break;
                   case ('!'):
                           *res = *res != operand2;
                           break;
                   case ('&'):
                           *res = *res && operand2;
                           break;
                   case (':'):
                           *res = *res || operand2;
                           break;
                   case ('i'):
                           if (operand2 < *res)
                                   *res = operand2;
                           break;
                   case ('a'):
                           if (operand2 > *res)
                                   *res = operand2;
                           break;
                   default:
                           abort();
                   }
           }
           return(1);
   }
   
 void  void
 roff_setreg(struct roff *r, const char *name, int val, char sign)  roff_setreg(struct roff *r, const char *name, int val, char sign)
 {  {
Line 1480  roff_freereg(struct roffreg *reg)
Line 1634  roff_freereg(struct roffreg *reg)
         }          }
 }  }
   
 /* 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;
         size_t           sz;  
         int              iv;          int              iv;
         char             sign;          char             sign;
   
Line 1497  roff_nr(ROFF_ARGS)
Line 1649  roff_nr(ROFF_ARGS)
         if ('+' == sign || '-' == sign)          if ('+' == sign || '-' == sign)
                 val++;                  val++;
   
         sz = strspn(val, "0123456789");          if (roff_evalnum(val, NULL, &iv, 0))
         iv = sz ? mandoc_strntoi(val, sz, 10) : 0;                  roff_setreg(r, key, iv, sign);
   
         roff_setreg(r, key, iv, sign);  
   
         return(ROFF_IGN);          return(ROFF_IGN);
 }  }

Legend:
Removed from v.1.203  
changed lines
  Added in v.1.204

CVSweb