[BACK]Return to cond.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.bin / make

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/usr.bin/make/cond.c between version 1.44 and 1.48

version 1.44, 2008/11/22 18:47:47 version 1.48, 2008/11/29 14:42:21
Line 92  __RCSID("$NetBSD$");
Line 92  __RCSID("$NetBSD$");
  */   */
   
 #include    <ctype.h>  #include    <ctype.h>
   #include    <errno.h>    /* For strtoul() error checking */
   
 #include    "make.h"  #include    "make.h"
 #include    "hash.h"  #include    "hash.h"
Line 146  static Boolean CondDoMake(int, char *);
Line 147  static Boolean CondDoMake(int, char *);
 static Boolean CondDoExists(int, char *);  static Boolean CondDoExists(int, char *);
 static Boolean CondDoTarget(int, char *);  static Boolean CondDoTarget(int, char *);
 static Boolean CondDoCommands(int, char *);  static Boolean CondDoCommands(int, char *);
 static char * CondCvtArg(char *, double *);  static Boolean CondCvtArg(char *, double *);
 static Token CondToken(Boolean);  static Token CondToken(Boolean);
 static Token CondT(Boolean);  static Token CondT(Boolean);
 static Token CondF(Boolean);  static Token CondF(Boolean);
Line 488  CondDoCommands(int argLen, char *arg)
Line 489  CondDoCommands(int argLen, char *arg)
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * CondCvtArg --   * CondCvtArg --
  *      Convert the given number into a double. If the number begins   *      Convert the given number into a double.
  *      with 0x, it is interpreted as a hexadecimal integer   *      We try a base 10 or 16 integer conversion first, if that fails
  *      and converted to a double from there. All other strings just have   *      then we try a floating point conversion instead.
  *      strtod called on them.  
  *   *
  * Results:   * Results:
  *      Sets 'value' to double value of string.   *      Sets 'value' to double value of string.
  *      Returns NULL if string was fully consumed,   *      Returns 'true' if the convertion suceeded
  *      else returns remaining input.  
  *  
  * Side Effects:  
  *      Can change 'value' even if string is not a valid number.  
  *  
  *   *
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static char *  static Boolean
 CondCvtArg(char *str, double *value)  CondCvtArg(char *str, double *value)
 {  {
     if ((*str == '0') && (str[1] == 'x')) {      char *eptr, ech;
         long i;      unsigned long l_val;
       double d_val;
         for (str += 2, i = 0; *str; str++) {  
             int x;      errno = 0;
             if (isdigit((unsigned char) *str))      l_val = strtoul(str, &eptr, str[1] == 'x' ? 16 : 10);
                 x  = *str - '0';      ech = *eptr;
             else if (isxdigit((unsigned char) *str))      if (ech == 0 && errno != ERANGE) {
                 x = 10 + *str - isupper((unsigned char) *str) ? 'A' : 'a';          d_val = str[0] == '-' ? -(double)-l_val : (double)l_val;
             else  
                 break;  
             i = (i << 4) + x;  
         }  
         *value = (double) i;  
         return *str ? str : NULL;  
     } else {      } else {
         char *eptr;          if (ech != 0 && ech != '.' && ech != 'e' && ech != 'E')
         *value = strtod(str, &eptr);              return FALSE;
         return *eptr ? eptr : NULL;          d_val = strtod(str, &eptr);
           if (*eptr)
               return FALSE;
     }      }
   
       *value = d_val;
       return TRUE;
 }  }
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * CondGetString --   * CondGetString --
Line 762  do_string_compare:
Line 756  do_string_compare:
          * lhs and the rhs to a double and compare the two.           * lhs and the rhs to a double and compare the two.
          */           */
         double          left, right;          double          left, right;
         char    *cp;  
   
         if (CondCvtArg(lhs, &left))          if (!CondCvtArg(lhs, &left) || !CondCvtArg(rhs, &right))
             goto do_string_compare;  
         if ((cp = CondCvtArg(rhs, &right)) &&  
                 cp == rhs)  
             goto do_string_compare;              goto do_string_compare;
   
         if (DEBUG(COND)) {          if (DEBUG(COND)) {
Line 815  error:
Line 805  error:
     return t;      return t;
 }  }
   
   static int
   get_mpt_arg(char **linePtr, char **argPtr, const char *func, Boolean parens)
   {
       /*
        * Use Var_Parse to parse the spec in parens and return
        * True if the resulting string is empty.
        */
       int     length;
       void    *freeIt;
       char    *val;
       char    *cp = *linePtr;
   
       /* We do all the work here and return the result as the length */
       *argPtr = NULL;
   
       val = Var_Parse(cp - 1, VAR_CMD, FALSE, &length, &freeIt);
       /*
        * Advance *linePtr to beyond the closing ). Note that
        * we subtract one because 'length' is calculated from 'cp - 1'.
        */
       *linePtr = cp - 1 + length;
   
       if (val == var_Error) {
           free(freeIt);
           return -1;
       }
   
       /* A variable is empty when it just contains spaces... 4/15/92, christos */
       while (isspace(*(unsigned char *)val))
           val++;
   
       /*
        * For consistency with the other functions we can't generate the
        * true/false here.
        */
       length = *val ? 2 : 1;
       if (freeIt)
           free(freeIt);
       return length;
   }
   
   static Boolean
   CondDoEmpty(int arglen, char *arg)
   {
       return arglen == 1;
   }
   
 static Token  static Token
 compare_function(Boolean doEval)  compare_function(Boolean doEval)
 {  {
       static const struct fn_def {
           const char  *fn_name;
           int         fn_name_len;
           int         (*fn_getarg)(char **, char **, const char *, Boolean);
           Boolean     (*fn_proc)(int, char *);
       } fn_defs[] = {
           { "defined",   7, CondGetArg, CondDoDefined },
           { "make",      4, CondGetArg, CondDoMake },
           { "exists",    6, CondGetArg, CondDoExists },
           { "empty",     5, get_mpt_arg, CondDoEmpty },
           { "target",    6, CondGetArg, CondDoTarget },
           { "commands",  8, CondGetArg, CondDoCommands },
           { NULL,        0, NULL, NULL },
       };
       const struct fn_def *fn_def;
     Token       t;      Token       t;
     Boolean (*evalProc)(int, char *);  
     Boolean invert = FALSE;  
     char        *arg = NULL;      char        *arg = NULL;
     int arglen = 0;      int arglen;
       char *cp = condExpr;
     if (istoken(condExpr, "defined", 7)) {      char *cp1;
         /*  
          * Use CondDoDefined to evaluate the argument and      for (fn_def = fn_defs; fn_def->fn_name != NULL; fn_def++) {
          * CondGetArg to extract the argument from the 'function          if (!istoken(cp, fn_def->fn_name, fn_def->fn_name_len))
          * call'.              continue;
          */          cp += fn_def->fn_name_len;
         evalProc = CondDoDefined;          /* There can only be whitespace before the '(' */
         condExpr += 7;          while (isspace(*(unsigned char *)cp))
         arglen = CondGetArg(&condExpr, &arg, "defined", TRUE);              cp++;
         if (arglen == 0) {          if (*cp != '(')
             condExpr -= 7;              break;
             goto use_default;  
         }  
     } else if (istoken(condExpr, "make", 4)) {  
         /*  
          * Use CondDoMake to evaluate the argument and  
          * CondGetArg to extract the argument from the 'function  
          * call'.  
          */  
         evalProc = CondDoMake;  
         condExpr += 4;  
         arglen = CondGetArg(&condExpr, &arg, "make", TRUE);  
         if (arglen == 0) {  
             condExpr -= 4;  
             goto use_default;  
         }  
     } else if (istoken(condExpr, "exists", 6)) {  
         /*  
          * Use CondDoExists to evaluate the argument and  
          * CondGetArg to extract the argument from the  
          * 'function call'.  
          */  
         evalProc = CondDoExists;  
         condExpr += 6;  
         arglen = CondGetArg(&condExpr, &arg, "exists", TRUE);  
         if (arglen == 0) {  
             condExpr -= 6;  
             goto use_default;  
         }  
     } else if (istoken(condExpr, "empty", 5)) {  
         /*  
          * Use Var_Parse to parse the spec in parens and return  
          * True if the resulting string is empty.  
          */  
         int         did_warn, length;  
         void    *freeIt;  
         char    *val;  
   
         condExpr += 5;  
   
         did_warn = 0;  
         for (arglen = 0; condExpr[arglen] != '\0'; arglen += 1) {  
             if (condExpr[arglen] == '(')  
                 break;  
             if (!isspace((unsigned char)condExpr[arglen]) &&  
                 !did_warn) {  
   
                 Parse_Error(PARSE_WARNING,          arglen = fn_def->fn_getarg(&cp, &arg, fn_def->fn_name, TRUE);
                     "Extra characters after \"empty\"");          if (arglen <= 0) {
                 did_warn = 1;              if (arglen < 0) {
                   condExpr = cp;
                   return Err;
             }              }
               break;
         }          }
           /* Evaluate the argument using the required function. */
         if (condExpr[arglen] != '\0') {          t = !doEval || fn_def->fn_proc(arglen, arg) ? True : False;
             val = Var_Parse(&condExpr[arglen - 1], VAR_CMD,          if (arg)
                             FALSE, &length, &freeIt);              free(arg);
             if (val == var_Error) {          condExpr = cp;
                 t = Err;  
             } else {  
                 /*  
                  * A variable is empty when it just contains  
                  * spaces... 4/15/92, christos  
                  */  
                 char *p;  
                 for (p = val; *p && isspace((unsigned char)*p); p++)  
                     continue;  
                 t = (*p == '\0') ? True : False;  
             }  
             if (freeIt) {  
                 free(freeIt);  
             }  
             /*  
              * Advance condExpr to beyond the closing ). Note that  
              * we subtract one from arglen + length b/c length  
              * is calculated from condExpr[arglen - 1].  
              */  
             condExpr += arglen + length - 1;  
         } else {  
             condExpr -= 5;  
             goto use_default;  
         }  
         return t;          return t;
     } else if (istoken(condExpr, "target", 6)) {  
         /*  
          * Use CondDoTarget to evaluate the argument and  
          * CondGetArg to extract the argument from the  
          * 'function call'.  
          */  
         evalProc = CondDoTarget;  
         condExpr += 6;  
         arglen = CondGetArg(&condExpr, &arg, "target", TRUE);  
         if (arglen == 0) {  
             condExpr -= 6;  
             goto use_default;  
         }  
     } else if (istoken(condExpr, "commands", 8)) {  
         /*  
          * Use CondDoCommands to evaluate the argument and  
          * CondGetArg to extract the argument from the  
          * 'function call'.  
          */  
         evalProc = CondDoCommands;  
         condExpr += 8;  
         arglen = CondGetArg(&condExpr, &arg, "commands", TRUE);  
         if (arglen == 0) {  
             condExpr -= 8;  
             goto use_default;  
         }  
     } else {  
         /*  
          * The symbol is itself the argument to the default  
          * function. We advance condExpr to the end of the symbol  
          * by hand (the next whitespace, closing paren or  
          * binary operator) and set to invert the evaluation  
          * function if condInvert is TRUE.  
          */  
         if (isdigit((unsigned char)condExpr[0])) {  
             /*  
              * Variables may already be substituted  
              * by the time we get here.  
              */  
             return compare_expression(doEval);  
         }  
     use_default:  
         invert = condInvert;  
         evalProc = condDefProc;  
         arglen = CondGetArg(&condExpr, &arg, "", FALSE);  
     }      }
   
       /* Push anything numeric through the compare expression */
       cp = condExpr;
       if (isdigit((unsigned char)cp[0]) || strchr("+-", cp[0]))
           return compare_expression(doEval);
   
     /*      /*
      * Evaluate the argument using the set function. If invert       * Most likely we have a naked token to apply the default function to.
      * is TRUE, we invert the sense of the function.       * However ".if a == b" gets here when the "a" is unquoted and doesn't
        * start with a '$'. This surprises people - especially given the way
        * that for loops get expanded.
        * If what follows the function argument is a '=' or '!' then the syntax
        * would be invalid if we did "defined(a)" - so instead treat as an
        * expression.
      */       */
     t = (!doEval || (* evalProc) (arglen, arg) ?      arglen = CondGetArg(&cp, &arg, "", FALSE);
          (invert ? False : True) :      for (cp1 = cp; isspace(*(unsigned char *)cp1); cp1++)
          (invert ? True : False));          continue;
       if (*cp1 == '=' || *cp1 == '!')
           return compare_expression(doEval);
       condExpr = cp;
   
       /*
        * Evaluate the argument using the default function. If invert
        * is TRUE, we invert the sense of the result.
        */
       t = !doEval || (* condDefProc)(arglen, arg) != condInvert ? True : False;
     if (arg)      if (arg)
         free(arg);          free(arg);
     return t;      return t;
Line 978  compare_function(Boolean doEval)
Line 936  compare_function(Boolean doEval)
 static Token  static Token
 CondToken(Boolean doEval)  CondToken(Boolean doEval)
 {  {
     Token         t;      Token t;
   
       t = condPushBack;
       if (t != None) {
           condPushBack = None;
           return t;
       }
   
     if (condPushBack == None) {      while (*condExpr == ' ' || *condExpr == '\t') {
         while (*condExpr == ' ' || *condExpr == '\t') {          condExpr++;
       }
   
       switch (*condExpr) {
   
       case '(':
           condExpr++;
           return LParen;
   
       case ')':
           condExpr++;
           return RParen;
   
       case '|':
           if (condExpr[1] == '|') {
             condExpr++;              condExpr++;
         }          }
         switch (*condExpr) {          condExpr++;
             case '(':          return Or;
                 t = LParen;  
                 condExpr++;  
                 break;  
             case ')':  
                 t = RParen;  
                 condExpr++;  
                 break;  
             case '|':  
                 if (condExpr[1] == '|') {  
                     condExpr++;  
                 }  
                 condExpr++;  
                 t = Or;  
                 break;  
             case '&':  
                 if (condExpr[1] == '&') {  
                     condExpr++;  
                 }  
                 condExpr++;  
                 t = And;  
                 break;  
             case '!':  
                 t = Not;  
                 condExpr++;  
                 break;  
             case '#':  
             case '\n':  
             case '\0':  
                 t = EndOfFile;  
                 break;  
             case '"':  
             case '$':  
                 return compare_expression(doEval);  
   
             default:  
                 return compare_function(doEval);  
   
       case '&':
           if (condExpr[1] == '&') {
               condExpr++;
         }          }
     } else {          condExpr++;
         t = condPushBack;          return And;
         condPushBack = None;  
       case '!':
           condExpr++;
           return Not;
   
       case '#':
       case '\n':
       case '\0':
           return EndOfFile;
   
       case '"':
       case '$':
           return compare_expression(doEval);
   
       default:
           return compare_function(doEval);
     }      }
     return (t);  
 }  }
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * CondT --   * CondT --

Legend:
Removed from v.1.44  
changed lines
  Added in v.1.48

CVSweb <webmaster@jp.NetBSD.org>