Пример #1
0
        private static bool StartsWithKeyword(string expression, PreprocessorOperation operation)
        {
            expression = expression.ToUpper(CultureInfo.InvariantCulture);
            switch (operation)
            {
            case PreprocessorOperation.Not:
                if (expression.StartsWith("NOT ", StringComparison.Ordinal) || expression.StartsWith("NOT(", StringComparison.Ordinal))
                {
                    return(true);
                }
                break;

            case PreprocessorOperation.And:
                if (expression.StartsWith("AND ", StringComparison.Ordinal) || expression.StartsWith("AND(", StringComparison.Ordinal))
                {
                    return(true);
                }
                break;

            case PreprocessorOperation.Or:
                if (expression.StartsWith("OR ", StringComparison.Ordinal) || expression.StartsWith("OR(", StringComparison.Ordinal))
                {
                    return(true);
                }
                break;

            default:
                break;
            }
            return(false);
        }
Пример #2
0
        private void UpdateExpressionValue(ref bool currentValue, PreprocessorOperation operation, bool prevResult)
        {
            switch (operation)
            {
            case PreprocessorOperation.And:
                currentValue = currentValue && prevResult;
                break;

            case PreprocessorOperation.Or:
                currentValue = currentValue || prevResult;
                break;

            case PreprocessorOperation.Not:
                currentValue = !currentValue;
                break;

            default:
                throw new Exception("Unexpected Preprocessor Operator: " + operation.ToString());
            }
        }
Пример #3
0
 /// <summary>
 /// Tests expression to see if it starts with a keyword.
 /// </summary>
 /// <param name="expression">Expression to test.</param>
 /// <param name="operation">Operation to test for.</param>
 /// <returns>true if expression starts with a keyword.</returns>
 private static bool StartsWithKeyword(string expression, PreprocessorOperation operation)
 {
     expression = expression.ToUpper(CultureInfo.InvariantCulture);
     switch (operation)
     {
         case PreprocessorOperation.Not:
             if (expression.StartsWith("NOT ", StringComparison.Ordinal) || expression.StartsWith("NOT(", StringComparison.Ordinal))
             {
                 return true;
             }
             break;
         case PreprocessorOperation.And:
             if (expression.StartsWith("AND ", StringComparison.Ordinal) || expression.StartsWith("AND(", StringComparison.Ordinal))
             {
                 return true;
             }
             break;
         case PreprocessorOperation.Or:
             if (expression.StartsWith("OR ", StringComparison.Ordinal) || expression.StartsWith("OR(", StringComparison.Ordinal))
             {
                 return true;
             }
             break;
         default:
             break;
     }
     return false;
 }
Пример #4
0
        /// <summary>
        /// Recurse through the expression to evaluate if it is true or false.
        /// The expression is evaluated left to right. 
        /// The expression is case-sensitive (converted to upper case) with the
        /// following exceptions: variable names and keywords (and, not, or).
        /// Comparisons with = and != are string comparisons.  
        /// Comparisons with inequality operators must be done on valid integers.
        /// 
        /// The operator precedence is:
        ///    ""
        ///    ()
        ///    &lt;, &gt;, &lt;=, &gt;=, =, !=
        ///    Not
        ///    And, Or
        ///    
        /// Valid expressions include:
        ///   not $(var.B) or not $(var.C)
        ///   (($(var.A))and $(var.B) ="2")or Not((($(var.C))) and $(var.A))
        ///   (($(var.A)) and $(var.B) = " 3 ") or $(var.C)
        ///   $(var.A) and $(var.C) = "3" or $(var.C) and $(var.D) = $(env.windir)
        ///   $(var.A) and $(var.B)>2 or $(var.B) &lt;= 2
        ///   $(var.A) != "2" 
        /// </summary>
        /// <param name="originalExpression">The original expression</param>
        /// <param name="expression">The expression currently being evaluated</param>
        /// <param name="prevResultOperation">The operation to apply to this result</param>
        /// <param name="prevResult">The previous result to apply to this result</param>
        /// <returns>Boolean to indicate if the expression is true or false</returns>
        private bool EvaluateExpressionRecurse(string originalExpression,  ref string expression,  PreprocessorOperation prevResultOperation,  bool prevResult)
        {
            bool expressionValue = false;
            expression = expression.Trim();
            if (expression.Length == 0)
            {
                throw new WixException(WixErrors.UnexpectedEmptySubexpression(this.GetCurrentSourceLineNumbers(), originalExpression));
            }

            // If the expression starts with parenthesis, evaluate it
            if (expression.IndexOf('(') == 0)
            {
                int endSubExpressionIndex;
                string subExpression = this.GetParenthesisExpression(originalExpression, expression, out endSubExpressionIndex);
                expressionValue = this.EvaluateExpressionRecurse(originalExpression, ref subExpression, PreprocessorOperation.And, true);

                // Now get the rest of the expression that hasn't been evaluated
                expression = expression.Substring(endSubExpressionIndex).Trim();
            }
            else
            {
                // Check for NOT
                if (StartsWithKeyword(expression, PreprocessorOperation.Not))
                {
                    expression = expression.Substring(3).Trim();
                    if (expression.Length == 0)
                    {
                        throw new WixException(WixErrors.ExpectedExpressionAfterNot(this.GetCurrentSourceLineNumbers(), originalExpression));
                    }

                    expressionValue = this.EvaluateExpressionRecurse(originalExpression, ref expression, PreprocessorOperation.Not, true);
                }
                else // Expect a literal
                {
                    expressionValue = this.EvaluateAtomicExpression(originalExpression, ref expression);

                    // Expect the literal that was just evaluated to already be cut off
                }
            }
            this.UpdateExpressionValue(ref expressionValue, prevResultOperation, prevResult);

            // If there's still an expression left, it must start with AND or OR.
            if (expression.Trim().Length > 0)
            {
                if (StartsWithKeyword(expression, PreprocessorOperation.And))
                {
                    expression = expression.Substring(3);
                    return this.EvaluateExpressionRecurse(originalExpression, ref expression, PreprocessorOperation.And, expressionValue);
                }
                else if (StartsWithKeyword(expression, PreprocessorOperation.Or))
                {
                    expression = expression.Substring(2);
                    return this.EvaluateExpressionRecurse(originalExpression, ref expression, PreprocessorOperation.Or, expressionValue);
                }
                else
                {
                    throw new WixException(WixErrors.InvalidSubExpression(this.GetCurrentSourceLineNumbers(), expression, originalExpression));
                }
            }

            return expressionValue;
        }
Пример #5
0
 /// <summary>
 /// Updates expression based on operation.
 /// </summary>
 /// <param name="currentValue">State to update.</param>
 /// <param name="operation">Operation to apply to current value.</param>
 /// <param name="prevResult">Previous result.</param>
 private void UpdateExpressionValue(ref bool currentValue, PreprocessorOperation operation, bool prevResult)
 {
     switch (operation)
     {
         case PreprocessorOperation.And:
             currentValue = currentValue && prevResult;
             break;
         case PreprocessorOperation.Or:
             currentValue = currentValue || prevResult;
             break;
         case PreprocessorOperation.Not:
             currentValue = !currentValue;
             break;
         default:
             throw new WixException(WixErrors.UnexpectedPreprocessorOperator(this.GetCurrentSourceLineNumbers(), operation.ToString()));
     }
 }
Пример #6
0
        private bool EvaluateExpressionRecurse(string originalExpression, ref string expression, PreprocessorOperation prevResultOperation, bool prevResult)
        {
            bool expressionValue = false;

            expression = expression.Trim();
            if (expression.Length == 0)
            {
                throw new Exception("Unexpected Empty Subexpression: " + originalExpression);
            }

            // If the expression starts with parenthesis, evaluate it
            if (expression.IndexOf('(') == 0)
            {
                int    endSubExpressionIndex;
                string subExpression = this.GetParenthesisExpression(originalExpression, expression, out endSubExpressionIndex);
                expressionValue = this.EvaluateExpressionRecurse(originalExpression, ref subExpression, PreprocessorOperation.And, true);

                // Now get the rest of the expression that hasn't been evaluated
                expression = expression.Substring(endSubExpressionIndex).Trim();
            }
            else
            {
                // Check for NOT
                if (StartsWithKeyword(expression, PreprocessorOperation.Not))
                {
                    expression = expression.Substring(3).Trim();
                    if (expression.Length == 0)
                    {
                        throw new Exception("Expected Expression After Not: " + originalExpression);
                    }

                    expressionValue = this.EvaluateExpressionRecurse(originalExpression, ref expression, PreprocessorOperation.Not, true);
                }
                else // Expect a literal
                {
                    expressionValue = this.EvaluateAtomicExpression(originalExpression, ref expression);

                    // Expect the literal that was just evaluated to already be cut off
                }
            }
            this.UpdateExpressionValue(ref expressionValue, prevResultOperation, prevResult);

            // If there's still an expression left, it must start with AND or OR.
            if (expression.Trim().Length > 0)
            {
                if (StartsWithKeyword(expression, PreprocessorOperation.And))
                {
                    expression = expression.Substring(3);
                    return(this.EvaluateExpressionRecurse(originalExpression, ref expression, PreprocessorOperation.And, expressionValue));
                }
                else if (StartsWithKeyword(expression, PreprocessorOperation.Or))
                {
                    expression = expression.Substring(2);
                    return(this.EvaluateExpressionRecurse(originalExpression, ref expression, PreprocessorOperation.Or, expressionValue));
                }
                else
                {
                    throw new Exception("Invalid Sub Expression: " + expression);
                }
            }

            return(expressionValue);
        }
Пример #7
0
 /// <summary>
 /// Tests expression to see if it starts with a keyword.
 /// </summary>
 /// <param name="expression">Expression to test.</param>
 /// <param name="operation">Operation to test for.</param>
 /// <returns>true if expression starts with a keyword.</returns>
 private bool StartsWithKeyword(string expression, PreprocessorOperation operation)
 {
     expression = expression.ToUpper();
     switch (operation)
     {
         case PreprocessorOperation.Not:
             if (expression.StartsWith("NOT ") || expression.StartsWith("NOT("))
             {
                 return true;
             }
             break;
         case PreprocessorOperation.And:
             if (expression.StartsWith("AND ") || expression.StartsWith("AND("))
             {
                 return true;
             }
             break;
         case PreprocessorOperation.Or:
             if (expression.StartsWith("OR ") || expression.StartsWith("OR("))
             {
                 return true;
             }
             break;
         default:
             break;
     }
     return false;
 }