[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.15 and 1.25

version 1.15, 2003/04/17 15:57:52 version 1.25, 2005/02/16 15:11:52
Line 2 
Line 2 
   
 /*  /*
  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.   * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
    * All rights reserved.
    *
    * This code is derived from software contributed to Berkeley by
    * Adam de Boor.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    * 1. Redistributions of source code must retain the above copyright
    *    notice, this list of conditions and the following disclaimer.
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in the
    *    documentation and/or other materials provided with the distribution.
    * 3. Neither the name of the University nor the names of its contributors
    *    may be used to endorse or promote products derived from this software
    *    without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    * SUCH DAMAGE.
    */
   
   /*
  * Copyright (c) 1988, 1989 by Adam de Boor   * Copyright (c) 1988, 1989 by Adam de Boor
  * Copyright (c) 1989 by Berkeley Softworks   * Copyright (c) 1989 by Berkeley Softworks
  * All rights reserved.   * All rights reserved.
Line 38 
Line 69 
  * SUCH DAMAGE.   * SUCH DAMAGE.
  */   */
   
 #ifdef MAKE_BOOTSTRAP  #ifndef MAKE_NATIVE
 static char rcsid[] = "$NetBSD$";  static char rcsid[] = "$NetBSD$";
 #else  #else
 #include <sys/cdefs.h>  #include <sys/cdefs.h>
Line 83  __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 107  typedef enum {
Line 139  typedef enum {
  * last two fields are stored in condInvert and condDefProc, respectively.   * last two fields are stored in condInvert and condDefProc, respectively.
  */   */
 static void CondPushBack(Token);  static void CondPushBack(Token);
 static int CondGetArg(char **, char **, char *, Boolean);  static int CondGetArg(char **, char **, const char *, Boolean);
 static Boolean CondDoDefined(int, char *);  static Boolean CondDoDefined(int, char *);
 static int CondStrMatch(ClientData, ClientData);  static int CondStrMatch(ClientData, ClientData);
 static Boolean CondDoMake(int, char *);  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 Boolean CondCvtArg(char *, double *);  static char * 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);
 static Token CondE(Boolean);  static Token CondE(Boolean);
   
 static struct If {  static struct If {
     char        *form;        /* Form of if */      const char  *form;        /* Form of if */
     int         formlen;      /* Length of form */      int         formlen;      /* Length of form */
     Boolean     doNot;        /* TRUE if default function should be negated */      Boolean     doNot;        /* TRUE if default function should be negated */
     Boolean     (*defProc)(int, char *); /* Default function to apply */      Boolean     (*defProc)(int, char *); /* Default function to apply */
Line 140  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 189  CondPushBack(Token t)
Line 222  CondPushBack(Token t)
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static int  static int
 CondGetArg(char **linePtr, char **argPtr, char *func, Boolean parens)  CondGetArg(char **linePtr, char **argPtr, const char *func, Boolean parens)
 {  {
     char          *cp;      char          *cp;
     int           argLen;      int           argLen;
Line 259  CondGetArg(char **linePtr, char **argPtr
Line 292  CondGetArg(char **linePtr, char **argPtr
         cp++;          cp++;
     }      }
     if (parens && *cp != ')') {      if (parens && *cp != ')') {
         Parse_Error (PARSE_WARNING, "Missing closing parenthesis for %s()",          Parse_Error(PARSE_WARNING, "Missing closing parenthesis for %s()",
                      func);                       func);
         return (0);          return (0);
     } else if (parens) {      } else if (parens) {
Line 294  CondDoDefined(int argLen, char *arg)
Line 327  CondDoDefined(int argLen, char *arg)
     Boolean result;      Boolean result;
   
     arg[argLen] = '\0';      arg[argLen] = '\0';
     if (Var_Value (arg, VAR_CMD, &p1) != (char *)NULL) {      if (Var_Value(arg, VAR_CMD, &p1) != (char *)NULL) {
         result = TRUE;          result = TRUE;
     } else {      } else {
         result = FALSE;          result = FALSE;
Line 345  CondDoMake(int argLen, char *arg)
Line 378  CondDoMake(int argLen, char *arg)
     Boolean result;      Boolean result;
   
     arg[argLen] = '\0';      arg[argLen] = '\0';
     if (Lst_Find (create, (ClientData)arg, CondStrMatch) == NILLNODE) {      if (Lst_Find(create, (ClientData)arg, CondStrMatch) == NILLNODE) {
         result = FALSE;          result = FALSE;
     } else {      } else {
         result = TRUE;          result = TRUE;
Line 460  CondDoCommands(int argLen, char *arg)
Line 493  CondDoCommands(int argLen, char *arg)
  *   *
  * Results:   * Results:
  *      Sets 'value' to double value of string.   *      Sets 'value' to double value of string.
  *      Returns true if the string was a valid number, false o.w.   *      Returns NULL if string was fully consumed,
    *      else returns remaining input.
  *   *
  * Side Effects:   * Side Effects:
  *      Can change 'value' even if string is not a valid number.   *      Can change 'value' even if string is not a valid number.
Line 468  CondDoCommands(int argLen, char *arg)
Line 502  CondDoCommands(int argLen, char *arg)
  *   *
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static Boolean  static char *
 CondCvtArg(char *str, double *value)  CondCvtArg(char *str, double *value)
 {  {
     if ((*str == '0') && (str[1] == 'x')) {      if ((*str == '0') && (str[1] == 'x')) {
Line 481  CondCvtArg(char *str, double *value)
Line 515  CondCvtArg(char *str, double *value)
             else if (isxdigit((unsigned char) *str))              else if (isxdigit((unsigned char) *str))
                 x = 10 + *str - isupper((unsigned char) *str) ? 'A' : 'a';                  x = 10 + *str - isupper((unsigned char) *str) ? 'A' : 'a';
             else              else
                 return FALSE;                  break;
             i = (i << 4) + x;              i = (i << 4) + x;
         }          }
         *value = (double) i;          *value = (double) i;
         return TRUE;          return *str ? str : NULL;
     }      } else {
     else {  
         char *eptr;          char *eptr;
         *value = strtod(str, &eptr);          *value = strtod(str, &eptr);
         return *eptr == '\0';          return *eptr ? eptr : NULL;
       }
   }
   
   /*-
    *-----------------------------------------------------------------------
    * 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;
 }  }
   
 /*-  /*-
Line 548  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 618  CondToken(Boolean doEval)
Line 736  CondToken(Boolean doEval)
                         }                          }
                         break;                          break;
                     default:                      default:
                         op = "!=";                          op = UNCONST("!=");
                         rhs = "0";                          if (lhsQuoted)
                               rhs = UNCONST("");
                           else
                               rhs = UNCONST("0");
   
                         goto do_compare;                          goto do_compare;
                 }                  }
Line 631  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 650  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 714  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;
                       if ((cp = CondCvtArg(rhs, &right)) &&
                               cp == rhs)
                         goto do_string_compare;                          goto do_string_compare;
                     if (*rhs == '$') {  
                         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 {  
                         if (!CondCvtArg(rhs, &right))  
                             goto do_string_compare;  
                         if (rhs == condExpr) {  
                             /*  
                              * Skip over the right-hand side  
                              */  
                             while(!isspace((unsigned char) *condExpr) &&  
                                   (*condExpr != '\0')) {  
                                 condExpr++;  
                             }  
                         }  
                     }  
   
                     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 788  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 806  error:
Line 849  error:
                      */                       */
                     evalProc = CondDoDefined;                      evalProc = CondDoDefined;
                     condExpr += 7;                      condExpr += 7;
                     arglen = CondGetArg (&condExpr, &arg, "defined", TRUE);                      arglen = CondGetArg(&condExpr, &arg, "defined", TRUE);
                     if (arglen == 0) {                      if (arglen == 0) {
                         condExpr -= 7;                          condExpr -= 7;
                         goto use_default;                          goto use_default;
Line 819  error:
Line 862  error:
                      */                       */
                     evalProc = CondDoMake;                      evalProc = CondDoMake;
                     condExpr += 4;                      condExpr += 4;
                     arglen = CondGetArg (&condExpr, &arg, "make", TRUE);                      arglen = CondGetArg(&condExpr, &arg, "make", TRUE);
                     if (arglen == 0) {                      if (arglen == 0) {
                         condExpr -= 4;                          condExpr -= 4;
                         goto use_default;                          goto use_default;
Line 855  error:
Line 898  error:
   
                     if (condExpr[arglen] != '\0') {                      if (condExpr[arglen] != '\0') {
                         val = Var_Parse(&condExpr[arglen - 1], VAR_CMD,                          val = Var_Parse(&condExpr[arglen - 1], VAR_CMD,
                                         doEval, &length, &doFree);                                          FALSE, &length, &doFree);
                         if (val == var_Error) {                          if (val == var_Error) {
                             t = Err;                              t = Err;
                         } else {                          } else {
Line 1031  CondF(Boolean doEval)
Line 1074  CondF(Boolean doEval)
             /*              /*
              * F -> T               * F -> T
              */               */
             CondPushBack (o);              CondPushBack(o);
         }          }
     }      }
     return (l);      return (l);
Line 1078  CondE(Boolean doEval)
Line 1121  CondE(Boolean doEval)
             /*              /*
              * E -> F               * E -> F
              */               */
             CondPushBack (o);              CondPushBack(o);
         }          }
     }      }
     return (l);      return (l);
Line 1133  Cond_EvalExpression(int dosetup, char *l
Line 1176  Cond_EvalExpression(int dosetup, char *l
     case Err:      case Err:
 err:  err:
         if (eprint)          if (eprint)
             Parse_Error (PARSE_FATAL, "Malformed conditional (%s)",              Parse_Error(PARSE_FATAL, "Malformed conditional (%s)",
                          line);                           line);
         return (COND_INVALID);          return (COND_INVALID);
     default:      default:
Line 1198  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);
         } else {          } else {
             if (condTop == MAXIF) {              if (condTop == MAXIF) {
                 Parse_Error (level, "if-less endif");                  Parse_Error(level, "if-less endif");
                 return (COND_INVALID);                  return (COND_INVALID);
             } else {              } else {
                 skipLine = FALSE;                  skipLine = FALSE;
Line 1232  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);
             } else if (skipIfLevel == 0) {              } else if (skipIfLevel == 0) {
                 value = !condStack[condTop];                  value = !condStack[condTop];
Line 1249  Cond_Eval(char *line)
Line 1298  Cond_Eval(char *line)
     } else {      } else {
         if (isElse) {          if (isElse) {
             if (condTop == MAXIF) {              if (condTop == MAXIF) {
                 Parse_Error (level, "if-less elif");                  Parse_Error(level, "if-less elif");
                 return (COND_INVALID);                  return (COND_INVALID);
             } else if (skipIfLevel != 0) {              } else if (skipIfLevel != 0) {
                 /*                  /*
Line 1266  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 1281  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
Line 1298  Cond_Eval(char *line)
Line 1353  Cond_Eval(char *line)
          * This is the one case where we can definitely proclaim a fatal           * This is the one case where we can definitely proclaim a fatal
          * error. If we don't, we're hosed.           * error. If we don't, we're hosed.
          */           */
         Parse_Error (PARSE_FATAL, "Too many nested if's. %d max.", MAXIF);          Parse_Error(PARSE_FATAL, "Too many nested if's. %d max.", MAXIF);
         return (COND_INVALID);          return (COND_INVALID);
     } else {      } else {
         condStack[condTop] = value;          condStack[condTop] = value;

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.25

CVSweb <webmaster@jp.NetBSD.org>