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

Diff for /src/usr.bin/make/cond.c between version 1.27 and 1.28

version 1.27, 2002/04/17 16:45:02 version 1.28, 2002/06/11 21:12:11
Line 50 
Line 50 
 #include "dir.h"  #include "dir.h"
 #include "buf.h"  #include "buf.h"
 #include "cond.h"  #include "cond.h"
   #include "cond_int.h"
   #include "condhashconsts.h"
 #include "error.h"  #include "error.h"
 #include "var.h"  #include "var.h"
 #include "varname.h"  #include "varname.h"
Line 59 
Line 61 
 #include "main.h"  #include "main.h"
 #include "gnode.h"  #include "gnode.h"
 #include "lst.h"  #include "lst.h"
   #include "ohash.h"
   
   
 /* The parsing of conditional expressions is based on this grammar:  /* The parsing of conditional expressions is based on this grammar:
Line 113 
Line 116 
 static const char *find_cond(const char *);  static const char *find_cond(const char *);
   
   
 static struct If {  struct If {
     char        *form;          /* Form of if */      bool        isElse;         /* true for else forms */
     int         formlen;        /* Length of form */      bool        doNot;          /* true for embedded negation */
     bool        doNot;          /* true if default function should be negated */  
     bool        (*defProc)(struct Name *);      bool        (*defProc)(struct Name *);
                                 /* Default function to apply */                                  /* function to apply */
 } ifs[] = {  
     { "ifdef",    5,      false,  CondDoDefined },  
     { "ifndef",   6,      true,   CondDoDefined },  
     { "ifmake",   6,      false,  CondDoMake },  
     { "ifnmake",  7,      true,   CondDoMake },  
     { "if",       2,      false,  CondDoDefined },  
     { NULL,       0,      false,  NULL }  
 };  };
   
   static struct If ifs[] = {
       { false,    false,  CondDoDefined },        /* if, ifdef */
       { false,    true,   CondDoDefined },        /* ifndef */
       { false,    false,  CondDoMake },           /* ifmake */
       { false,    true,   CondDoMake },           /* ifnmake */
       { true,     false,  CondDoDefined },        /* elif, elifdef */
       { true,     true,   CondDoDefined },        /* elifndef */
       { true,     false,  CondDoMake },           /* elifmake */
       { true,     true,   CondDoMake },           /* elifnmake */
       { true,     false,  NULL }
   };
   
   #define COND_IF_INDEX           0
   #define COND_IFDEF_INDEX        0
   #define COND_IFNDEF_INDEX       1
   #define COND_IFMAKE_INDEX       2
   #define COND_IFNMAKE_INDEX      3
   #define COND_ELIF_INDEX         4
   #define COND_ELIFDEF_INDEX      4
   #define COND_ELIFNDEF_INDEX     5
   #define COND_ELIFMAKE_INDEX     6
   #define COND_ELIFNMAKE_INDEX    7
   #define COND_ELSE_INDEX         8
   
 static bool       condInvert;           /* Invert the default function */  static bool       condInvert;           /* Invert the default function */
 static bool       (*condDefProc)        /* Default function to apply */  static bool       (*condDefProc)        /* Default function to apply */
                    (struct Name *);                     (struct Name *);
Line 836 
Line 855 
     return l;      return l;
 }  }
   
 /* A conditional line looks like this:  /* Evaluate conditional in line.
  *          <cond-type> <expr>   * returns COND_SKIP, COND_PARSE, COND_INVALID, COND_ISFOR, COND_ISINCLUDE,
    * COND_ISUNDEF.
    * A conditional line looks like this:
    *      <cond-type> <expr>
  *      where <cond-type> is any of if, ifmake, ifnmake, ifdef,   *      where <cond-type> is any of if, ifmake, ifnmake, ifdef,
  *      ifndef, elif, elifmake, elifnmake, elifdef, elifndef   *      ifndef, elif, elifmake, elifnmake, elifdef, elifndef
  *      and <expr> consists of &&, ||, !, make(target), defined(variable)   *      and <expr> consists of &&, ||, !, make(target), defined(variable)
  *      and parenthetical groupings thereof.   *      and parenthetical groupings thereof.
  */   */
 int  int
 Cond_Eval(line)  Cond_Eval(const char *line)
     const char      *line;    /* Line to parse */  
 {  {
     struct If       *ifp;      /* find end of keyword */
     bool            isElse;      const char  *end;
     bool            value = false;      u_int32_t   k;
     int             level;      /* Level at which to report errors. */      size_t      len;
       struct If   *ifp;
       bool        value = false;
       int         level;  /* Level at which to report errors. */
   
     level = PARSE_FATAL;      level = PARSE_FATAL;
   
     /* Stuff we are looking for can be if*, elif*, else, or endif.      for (end = line; islower(*end); end++)
      * otherwise, this is not our turf.  */          ;
       /* quick path: recognize special targets early on */
     /* Find what type of if we're dealing with. The result is left      if (*end == '.' || *end == ':')
      * in ifp and isElse is set true if it's an elif line.  */          return COND_INVALID;
     if (line[0] == 'e' && line[1] == 'l') {      len = end - line;
         line += 2;      k = ohash_interval(line, &end);
         isElse = true;      switch(k % MAGICSLOTS2) {
     } else if (strncmp(line, "endif", 5) == 0) {      case K_COND_IF % MAGICSLOTS2:
           if (k == K_COND_IF && len == strlen(COND_IF) &&
               strncmp(line, COND_IF, len) == 0) {
               ifp = ifs + COND_IF_INDEX;
           } else
               return COND_INVALID;
           break;
       case K_COND_IFDEF % MAGICSLOTS2:
           if (k == K_COND_IFDEF && len == strlen(COND_IFDEF) &&
               strncmp(line, COND_IFDEF, len) == 0) {
               ifp = ifs + COND_IFDEF_INDEX;
           } else
               return COND_INVALID;
           break;
       case K_COND_IFNDEF % MAGICSLOTS2:
           if (k == K_COND_IFNDEF && len == strlen(COND_IFNDEF) &&
               strncmp(line, COND_IFNDEF, len) == 0) {
               ifp = ifs + COND_IFNDEF_INDEX;
           } else
               return COND_INVALID;
           break;
       case K_COND_IFMAKE % MAGICSLOTS2:
           if (k == K_COND_IFMAKE && len == strlen(COND_IFMAKE) &&
               strncmp(line, COND_IFMAKE, len) == 0) {
               ifp = ifs + COND_IFMAKE_INDEX;
           } else
               return COND_INVALID;
           break;
       case K_COND_IFNMAKE % MAGICSLOTS2:
           if (k == K_COND_IFNMAKE && len == strlen(COND_IFNMAKE) &&
               strncmp(line, COND_IFNMAKE, len) == 0) {
               ifp = ifs + COND_IFNMAKE_INDEX;
           } else
               return COND_INVALID;
           break;
       case K_COND_ELIF % MAGICSLOTS2:
           if (k == K_COND_ELIF && len == strlen(COND_ELIF) &&
               strncmp(line, COND_ELIF, len) == 0) {
               ifp = ifs + COND_ELIF_INDEX;
           } else
               return COND_INVALID;
           break;
       case K_COND_ELIFDEF % MAGICSLOTS2:
           if (k == K_COND_ELIFDEF && len == strlen(COND_ELIFDEF) &&
               strncmp(line, COND_ELIFDEF, len) == 0) {
               ifp = ifs + COND_ELIFDEF_INDEX;
           } else
               return COND_INVALID;
           break;
       case K_COND_ELIFNDEF % MAGICSLOTS2:
           if (k == K_COND_ELIFNDEF && len == strlen(COND_ELIFNDEF) &&
               strncmp(line, COND_ELIFNDEF, len) == 0) {
               ifp = ifs + COND_ELIFNDEF_INDEX;
           } else
               return COND_INVALID;
           break;
       case K_COND_ELIFMAKE % MAGICSLOTS2:
           if (k == K_COND_ELIFMAKE && len == strlen(COND_ELIFMAKE) &&
               strncmp(line, COND_ELIFMAKE, len) == 0) {
               ifp = ifs + COND_ELIFMAKE_INDEX;
           } else
               return COND_INVALID;
           break;
       case K_COND_ELIFNMAKE % MAGICSLOTS2:
           if (k == K_COND_ELIFNMAKE && len == strlen(COND_ELIFNMAKE) &&
               strncmp(line, COND_ELIFNMAKE, len) == 0) {
               ifp = ifs + COND_ELIFNMAKE_INDEX;
           } else
               return COND_INVALID;
           break;
       case K_COND_ELSE % MAGICSLOTS2:
           /* valid conditional whose value is the inverse
            * of the previous if we parsed.  */
           if (k == K_COND_ELSE && len == strlen(COND_ELSE) &&
               strncmp(line, COND_ELSE, len) == 0) {
               if (condTop == MAXIF) {
                   Parse_Error(level, "if-less else");
                   return COND_INVALID;
               } else if (skipIfLevel == 0) {
                   value = !condStack[condTop].value;
                   ifp = ifs + COND_ELSE_INDEX;
               } else
                   return COND_SKIP;
           } else
               return COND_INVALID;
           break;
       case K_COND_ENDIF % MAGICSLOTS2:
           if (k == K_COND_ENDIF && len == strlen(COND_ENDIF) &&
               strncmp(line, COND_ENDIF, len) == 0) {
         /* End of a conditional section. If skipIfLevel is non-zero, that          /* End of a conditional section. If skipIfLevel is non-zero, that
          * conditional was skipped, so lines following it should also be           * conditional was skipped, so lines following it should also be
          * skipped. Hence, we return COND_SKIP. Otherwise, the conditional           * skipped. Hence, we return COND_SKIP. Otherwise, the conditional
          * was read so succeeding lines should be parsed (think about it...)           * was read so succeeding lines should be parsed (think about it...)
          * 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.  */
         if (skipIfLevel != 0) {              if (skipIfLevel != 0) {
             skipIfLevel -= 1;                  skipIfLevel -= 1;
             return COND_SKIP;                  return COND_SKIP;
         } else {  
             if (condTop == MAXIF) {  
                 Parse_Error(level, "if-less endif");  
                 return COND_INVALID;  
             } else {              } else {
                 skipLine = false;                  if (condTop == MAXIF) {
                 condTop += 1;                      Parse_Error(level, "if-less endif");
                 return COND_PARSE;                      return COND_INVALID;
                   } else {
                       skipLine = false;
                       condTop += 1;
                       return COND_PARSE;
                   }
             }              }
         }          } else
     } else              return COND_INVALID;
         isElse = false;          break;
           /* Recognize other keywords there, to simplify parser's task */
     /* Figure out what sort of conditional it is -- what its default      case K_COND_FOR % MAGICSLOTS2:
      * function is, etc. -- by looking in the table of valid "ifs" */          if (k == K_COND_FOR && len == strlen(COND_FOR) &&
     for (ifp = ifs; ifp->form != NULL; ifp++) {              strncmp(line, COND_FOR, len) == 0)
         if (strncmp(ifp->form, line, ifp->formlen) == 0)              return COND_ISFOR;
             break;          else
               return COND_INVALID;
       case K_COND_UNDEF % MAGICSLOTS2:
           if (k == K_COND_UNDEF && len == strlen(COND_UNDEF) &&
               strncmp(line, COND_UNDEF, len) == 0)
               return COND_ISUNDEF;
           else
               return COND_INVALID;
       case K_COND_INCLUDE % MAGICSLOTS2:
           if (k == K_COND_INCLUDE && len == strlen(COND_INCLUDE) &&
               strncmp(line, COND_INCLUDE, len) == 0)
               return COND_ISINCLUDE;
           else
               return COND_INVALID;
       default:
           /* Not a valid conditional type. No error...  */
           return COND_INVALID;
     }      }
   
     if (ifp->form == NULL) {      if (ifp->isElse) {
         /* Nothing fits. If the first word on the line is actually          if (condTop == MAXIF) {
          * "else", it's a valid conditional whose value is the inverse              Parse_Error(level, "if-less elif");
          * of the previous if we parsed.  */  
         if (isElse && line[0] == 's' && line[1] == 'e') {  
             if (condTop == MAXIF) {  
                 Parse_Error(level, "if-less else");  
                 return COND_INVALID;  
             } else if (skipIfLevel == 0)  
                 value = !condStack[condTop].value;  
             else  
                 return COND_SKIP;  
         } else  
             /* Not a valid conditional type. No error...  */  
             return COND_INVALID;              return COND_INVALID;
     } else {          } else if (skipIfLevel != 0) {
         if (isElse) {              /* If skipping this conditional, just ignore the whole thing.
             if (condTop == MAXIF) {               * If we don't, the user might be employing a variable that's
                 Parse_Error(level, "if-less elif");               * undefined, for which there's an enclosing ifdef that
                 return COND_INVALID;               * we're skipping...  */
             } else if (skipIfLevel != 0) {  
                 /* If skipping this conditional, just ignore the whole thing.  
                  * If we don't, the user might be employing a variable that's  
                  * undefined, for which there's an enclosing ifdef that  
                  * we're skipping...  */  
                 return COND_SKIP;  
             }  
         } else if (skipLine) {  
             /* Don't even try to evaluate a conditional that's not an else if  
              * we're skipping things...  */  
             skipIfLevel += 1;  
             return COND_SKIP;              return COND_SKIP;
         }          }
       } else if (skipLine) {
           /* Don't even try to evaluate a conditional that's not an else if
            * we're skipping things...  */
           skipIfLevel += 1;
           return COND_SKIP;
       }
   
       if (ifp->defProc) {
         /* Initialize file-global variables for parsing.  */          /* Initialize file-global variables for parsing.  */
         condDefProc = ifp->defProc;          condDefProc = ifp->defProc;
         condInvert = ifp->doNot;          condInvert = ifp->doNot;
   
         line += ifp->formlen;          line += len;
   
         while (*line == ' ' || *line == '\t')          while (*line == ' ' || *line == '\t')
             line++;              line++;
Line 960 
Line 1074 
                 break;                  break;
         }          }
     }      }
     if (!isElse)  
       if (!ifp->isElse)
         condTop -= 1;          condTop -= 1;
     else if (skipIfLevel != 0 || condStack[condTop].value) {      else if (skipIfLevel != 0 || condStack[condTop].value) {
         /* 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.27  
changed lines
  Added in v.1.28