[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.19 and 1.23

version 1.19, 2004/01/06 01:18:52 version 1.23, 2004/04/13 16:06:23
Line 114  __RCSID("$NetBSD$");
Line 114  __RCSID("$NetBSD$");
  *      T -> $(varspec) op value   *      T -> $(varspec) op value
  *      T -> $(varspec) == "string"   *      T -> $(varspec) == "string"
  *      T -> $(varspec) != "string"   *      T -> $(varspec) != "string"
    *      T -> "string"
  *      T -> ( E )   *      T -> ( E )
  *      T -> ! T   *      T -> ! T
  *      op -> == | != | > | < | >= | <=   *      op -> == | != | > | < | >= | <=
Line 171  static char    *condExpr;      /* The ex
Line 172  static char    *condExpr;      /* The ex
 static Token      condPushBack=None;    /* Single push-back token used in  static Token      condPushBack=None;    /* Single push-back token used in
                                          * parsing */                                           * parsing */
   
 #define MAXIF           30        /* greatest depth of #if'ing */  #define MAXIF           64        /* greatest depth of #if'ing */
   
   static Boolean    finalElse[MAXIF+1][MAXIF+1]; /* Seen final else (stack) */
 static Boolean    condStack[MAXIF];     /* Stack of conditionals's values */  static Boolean    condStack[MAXIF];     /* Stack of conditionals's values */
 static int        condTop = MAXIF;      /* Top-most conditional */  static int        condTop = MAXIF;      /* Top-most conditional */
 static int        skipIfLevel=0;        /* Depth of skipped conditionals */  static int        skipIfLevel=0;        /* Depth of skipped conditionals */
Line 527  CondCvtArg(char *str, double *value)
Line 529  CondCvtArg(char *str, double *value)
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
    * CondGetString --
    *      Get a string from a variable reference or an optionally quoted
    *      string.  This is called for the lhs and rhs of string compares.
    *
    * Results:
    *      Sets doFree if needed,
    *      Sets quoted if string was quoted,
    *      Returns NULL on error,
    *      else returns string - absent any quotes.
    *
    * Side Effects:
    *      Moves condExpr to end of this token.
    *
    *
    *-----------------------------------------------------------------------
    */
   static char *
   CondGetString(Boolean doEval, Boolean *quoted, Boolean *doFree)
   {
       Buffer buf;
       char *cp;
       char *str;
       int len;
       int qt;
       char *start;
   
       buf = Buf_Init(0);
       str = NULL;
       *quoted = qt = *condExpr == '"' ? 1 : 0;
       if (qt)
           condExpr++;
       for (start = condExpr; *condExpr && str == NULL; condExpr++) {
           switch (*condExpr) {
           case '\\':
               if (condExpr[1] != '\0') {
                   condExpr++;
                   Buf_AddByte(buf, (Byte)*condExpr);
               }
               break;
           case '"':
               if (qt) {
                   condExpr++;             /* we don't want the quotes */
                   goto got_str;
               } else
                   Buf_AddByte(buf, (Byte)*condExpr); /* likely? */
               break;
           case ')':
           case '!':
           case '=':
           case '>':
           case '<':
           case ' ':
           case '\t':
               if (!qt)
                   goto got_str;
               else
                   Buf_AddByte(buf, (Byte)*condExpr);
               break;
           case '$':
               /* if we are in quotes, then an undefined variable is ok */
               str = Var_Parse(condExpr, VAR_CMD, (qt ? 0 : doEval),
                               &len, doFree);
               if (str == var_Error) {
                   /*
                    * Even if !doEval, we still report syntax errors, which
                    * is what getting var_Error back with !doEval means.
                    */
                   str = NULL;
                   goto cleanup;
               }
               condExpr += len;
               /*
                * If the '$' was first char (no quotes), and we are
                * followed by space, the operator or end of expression,
                * we are done.
                */
               if ((condExpr == start + len) &&
                   (*condExpr == '\0' ||
                    isspace((unsigned char) *condExpr) ||
                    strchr("!=><)", *condExpr))) {
                   goto cleanup;
               }
               /*
                * Nope, we better copy str to buf
                */
               for (cp = str; *cp; cp++) {
                   Buf_AddByte(buf, (Byte)*cp);
               }
               if (*doFree)
                   free(str);
               *doFree = FALSE;
               str = NULL;                 /* not finished yet */
               condExpr--;                 /* don't skip over next char */
               break;
           default:
               Buf_AddByte(buf, (Byte)*condExpr);
               break;
           }
       }
    got_str:
       Buf_AddByte(buf, (Byte)'\0');
       str = (char *)Buf_GetAll(buf, NULL);
       *doFree = TRUE;
    cleanup:
       Buf_Destroy(buf, FALSE);
       return str;
   }
   
   /*-
    *-----------------------------------------------------------------------
  * CondToken --   * CondToken --
  *      Return the next token from the input.   *      Return the next token from the input.
  *   *
Line 579  CondToken(Boolean doEval)
Line 691  CondToken(Boolean doEval)
             case '\0':              case '\0':
                 t = EndOfFile;                  t = EndOfFile;
                 break;                  break;
               case '"':
             case '$': {              case '$': {
                 char    *lhs;                  char    *lhs;
                 char    *rhs;                  char    *rhs;
                 char    *op;                  char    *op;
                 int     varSpecLen;                  Boolean lhsFree;
                 Boolean doFree;                  Boolean rhsFree;
                   Boolean lhsQuoted;
                   Boolean rhsQuoted;
   
                   lhsFree = rhsFree = FALSE;
                   lhsQuoted = rhsQuoted = FALSE;
   
                 /*                  /*
                  * Parse the variable spec and skip over it, saving its                   * Parse the variable spec and skip over it, saving its
                  * value in lhs.                   * value in lhs.
                  */                   */
                 t = Err;                  t = Err;
                 lhs = Var_Parse(condExpr, VAR_CMD, doEval,&varSpecLen,&doFree);                  lhs = CondGetString(doEval, &lhsQuoted, &lhsFree);
                 if (lhs == var_Error) {                  if (!lhs)
                     /*                      return Err;
                      * Even if !doEval, we still report syntax errors, which  
                      * is what getting var_Error back with !doEval means.  
                      */  
                     return(Err);  
                 }  
                 condExpr += varSpecLen;  
   
                 if (!isspace((unsigned char) *condExpr) &&  
                     strchr("!=><", *condExpr) == NULL) {  
                     Buffer buf;  
                     char *cp;  
   
                     buf = Buf_Init(0);  
   
                     for (cp = lhs; *cp; cp++)  
                         Buf_AddByte(buf, (Byte)*cp);  
   
                     if (doFree)  
                         free(lhs);  
   
                     for (;*condExpr && !isspace((unsigned char) *condExpr);  
                          condExpr++)  
                         Buf_AddByte(buf, (Byte)*condExpr);  
   
                     Buf_AddByte(buf, (Byte)'\0');  
                     lhs = (char *)Buf_GetAll(buf, &varSpecLen);  
                     Buf_Destroy(buf, FALSE);  
   
                     doFree = TRUE;  
                 }  
   
                 /*                  /*
                  * Skip whitespace to get to the operator                   * Skip whitespace to get to the operator
                  */                   */
Line 650  CondToken(Boolean doEval)
Line 737  CondToken(Boolean doEval)
                         break;                          break;
                     default:                      default:
                         op = UNCONST("!=");                          op = UNCONST("!=");
                         rhs = UNCONST("0");                          if (lhsQuoted)
                               rhs = UNCONST("");
                           else
                               rhs = UNCONST("0");
   
                         goto do_compare;                          goto do_compare;
                 }                  }
Line 662  CondToken(Boolean doEval)
Line 752  CondToken(Boolean doEval)
                                 "Missing right-hand-side of operator");                                  "Missing right-hand-side of operator");
                     goto error;                      goto error;
                 }                  }
                 rhs = condExpr;                  rhs = CondGetString(doEval, &rhsQuoted, &rhsFree);
                   if (!rhs)
                       return Err;
 do_compare:  do_compare:
                 if (*rhs == '"') {                  if (rhsQuoted || lhsQuoted) {
                     /*  
                      * Doing a string comparison. Only allow == and != for  
                      * operators.  
                      */  
                     char    *string;  
                     char    *cp, *cp2;  
                     int     qt;  
                     Buffer  buf;  
   
 do_string_compare:  do_string_compare:
                     if (((*op != '!') && (*op != '=')) || (op[1] != '=')) {                      if (((*op != '!') && (*op != '=')) || (op[1] != '=')) {
                         Parse_Error(PARSE_WARNING,                          Parse_Error(PARSE_WARNING,
Line 681  do_string_compare:
Line 764  do_string_compare:
                         goto error;                          goto error;
                     }                      }
   
                     buf = Buf_Init(0);  
                     qt = *rhs == '"' ? 1 : 0;  
   
                     for (cp = &rhs[qt];  
                          ((qt && (*cp != '"')) ||  
                           (!qt && strchr(" \t)", *cp) == NULL)) &&  
                          (*cp != '\0'); cp++) {  
                         if ((*cp == '\\') && (cp[1] != '\0')) {  
                             /*  
                              * Backslash escapes things -- skip over next  
                              * character, if it exists.  
                              */  
                             cp++;  
                             Buf_AddByte(buf, (Byte)*cp);  
                         } else if (*cp == '$') {  
                             int len;  
                             Boolean freeIt;  
   
                             cp2 = Var_Parse(cp, VAR_CMD, doEval,&len, &freeIt);  
                             if (cp2 != var_Error) {  
                                 Buf_AddBytes(buf, strlen(cp2), (Byte *)cp2);  
                                 if (freeIt) {  
                                     free(cp2);  
                                 }  
                                 cp += len - 1;  
                             } else {  
                                 Buf_AddByte(buf, (Byte)*cp);  
                             }  
                         } else {  
                             Buf_AddByte(buf, (Byte)*cp);  
                         }  
                     }  
   
                     Buf_AddByte(buf, (Byte)0);  
   
                     string = (char *)Buf_GetAll(buf, (int *)0);  
                     Buf_Destroy(buf, FALSE);  
   
                     if (DEBUG(COND)) {                      if (DEBUG(COND)) {
                         printf("lhs = \"%s\", rhs = \"%s\", op = %.2s\n",                          printf("lhs = \"%s\", rhs = \"%s\", op = %.2s\n",
                                lhs, string, op);                                 lhs, rhs, op);
                     }                      }
                     /*                      /*
                      * Null-terminate rhs and perform the comparison.                       * Null-terminate rhs and perform the comparison.
                      * t is set to the result.                       * t is set to the result.
                      */                       */
                     if (*op == '=') {                      if (*op == '=') {
                         t = strcmp(lhs, string) ? False : True;                          t = strcmp(lhs, rhs) ? False : True;
                     } else {                      } else {
                         t = strcmp(lhs, string) ? True : False;                          t = strcmp(lhs, rhs) ? True : False;
                     }  
                     free(string);  
                     if (rhs == condExpr) {  
                         if (!qt && *cp == ')')  
                             condExpr = cp;  
                         else  
                             condExpr = cp + 1;  
                     }                      }
                 } else {                  } else {
                     /*                      /*
Line 745  do_string_compare:
Line 783  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        *string;                      char        *cp;
   
                     if (CondCvtArg(lhs, &left))                      if (CondCvtArg(lhs, &left))
                         goto do_string_compare;                          goto do_string_compare;
                     if (*rhs == '$') {                      if ((cp = CondCvtArg(rhs, &right)) &&
                         int     len;  
                         Boolean freeIt;  
   
                         string = Var_Parse(rhs, VAR_CMD, doEval,&len,&freeIt);  
                         if (string == var_Error) {  
                             right = 0.0;  
                         } else {  
                             if (CondCvtArg(string, &right)) {  
                                 if (freeIt)  
                                     free(string);  
                                 goto do_string_compare;  
                             }  
                             if (freeIt)  
                                 free(string);  
                             if (rhs == condExpr)  
                                 condExpr += len;  
                         }  
                     } else {  
                         char *cp;  
   
                         if ((cp = CondCvtArg(rhs, &right)) &&  
                             cp == rhs)                              cp == rhs)
                             goto do_string_compare;                          goto do_string_compare;
                         if (rhs == condExpr) {  
                             /*  
                              * Skip over the right-hand side  
                              */  
                             if (cp)  
                                 condExpr = cp;  
                             else  
                                 condExpr = strchr(rhs, '\0');  
                         }  
                     }  
   
                     if (DEBUG(COND)) {                      if (DEBUG(COND)) {
                         printf("left = %f, right = %f, op = %.2s\n", left,                          printf("left = %f, right = %f, op = %.2s\n", left,
Line 822  do_string_compare:
Line 829  do_string_compare:
                     }                      }
                 }                  }
 error:  error:
                 if (doFree)                  if (lhsFree)
                     free(lhs);                      free(lhs);
                   if (rhsFree)
                       free(rhs);
                 break;                  break;
             }              }
             default: {              default: {
Line 1232  Cond_Eval(char *line)
Line 1241  Cond_Eval(char *line)
          * so we return COND_PARSE, unless this endif isn't paired with           * so we return COND_PARSE, unless this endif isn't paired with
          * a decent if.           * a decent if.
          */           */
           finalElse[condTop][skipIfLevel] = FALSE;
         if (skipIfLevel != 0) {          if (skipIfLevel != 0) {
             skipIfLevel -= 1;              skipIfLevel -= 1;
             return (COND_SKIP);              return (COND_SKIP);
Line 1266  Cond_Eval(char *line)
Line 1276  Cond_Eval(char *line)
          * of the previous if we parsed.           * of the previous if we parsed.
          */           */
         if (isElse && (line[0] == 's') && (line[1] == 'e')) {          if (isElse && (line[0] == 's') && (line[1] == 'e')) {
               if (finalElse[condTop][skipIfLevel]) {
                   Parse_Error (PARSE_WARNING, "extra else");
               } else {
                   finalElse[condTop][skipIfLevel] = TRUE;
               }
             if (condTop == MAXIF) {              if (condTop == MAXIF) {
                 Parse_Error (level, "if-less else");                  Parse_Error (level, "if-less else");
                 return (COND_INVALID);                  return (COND_INVALID);
Line 1300  Cond_Eval(char *line)
Line 1315  Cond_Eval(char *line)
              * we're skipping things...               * we're skipping things...
              */               */
             skipIfLevel += 1;              skipIfLevel += 1;
               if (skipIfLevel >= MAXIF) {
                   Parse_Error (PARSE_FATAL, "Too many nested if's. %d max.", MAXIF);
                   return (COND_INVALID);
               }
               finalElse[condTop][skipIfLevel] = FALSE;
             return(COND_SKIP);              return(COND_SKIP);
         }          }
   
Line 1315  Cond_Eval(char *line)
Line 1335  Cond_Eval(char *line)
     }      }
     if (!isElse) {      if (!isElse) {
         condTop -= 1;          condTop -= 1;
           finalElse[condTop][skipIfLevel] = FALSE;
     } else if ((skipIfLevel != 0) || condStack[condTop]) {      } else if ((skipIfLevel != 0) || condStack[condTop]) {
         /*          /*
          * If this is an else-type conditional, it should only take effect           * If this is an else-type conditional, it should only take effect

Legend:
Removed from v.1.19  
changed lines
  Added in v.1.23

CVSweb <webmaster@jp.NetBSD.org>