From 2a3c79df83e800d5dfe75a1a3b140ed81da2b1d6 Mon Sep 17 00:00:00 2001
From: Sean Dague
Date: Mon, 16 Jul 2007 15:40:11 +0000
Subject: changed to native line ending encoding
---
Prebuild/src/Core/Parse/IfContext.cs | 326 +++++-----
Prebuild/src/Core/Parse/Preprocessor.cs | 1038 +++++++++++++++----------------
2 files changed, 682 insertions(+), 682 deletions(-)
(limited to 'Prebuild/src/Core/Parse')
diff --git a/Prebuild/src/Core/Parse/IfContext.cs b/Prebuild/src/Core/Parse/IfContext.cs
index 383049d..6311f47 100644
--- a/Prebuild/src/Core/Parse/IfContext.cs
+++ b/Prebuild/src/Core/Parse/IfContext.cs
@@ -1,163 +1,163 @@
-#region BSD License
-/*
-Copyright (c) 2004-2005 Matthew Holmes (matthew@wildfiregames.com), Dan Moorehead (dan05a@gmail.com)
-
-Redistribution and use in source and binary forms, with or without modification, are permitted
-provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this list of conditions
- and the following disclaimer.
-* 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.
-* The name of the author may not be used to endorse or promote products derived from this software
- without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-*/
-#endregion
-
-#region CVS Information
-/*
- * $Source$
- * $Author: jendave $
- * $Date: 2006-01-28 01:49:58 +0100 (lö, 28 jan 2006) $
- * $Revision: 71 $
- */
-#endregion
-
-using System;
-
-namespace Prebuild.Core.Parse
-{
- ///
- ///
- ///
- public enum IfState
- {
- ///
- ///
- ///
- None,
- ///
- ///
- ///
- If,
- ///
- ///
- ///
- ElseIf,
- ///
- ///
- ///
- Else
- }
-
- ///
- /// Summary description for IfContext.
- ///
- // Inspired by the equivalent WiX class (see www.sourceforge.net/projects/wix/)
- public class IfContext
- {
- #region Properties
-
- bool m_Active;
- bool m_Keep;
- bool m_EverKept;
- IfState m_State = IfState.None;
-
- #endregion
-
- #region Constructors
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// if set to true [active].
- /// if set to true [keep].
- /// The state.
- public IfContext(bool active, bool keep, IfState state)
- {
- m_Active = active;
- m_Keep = keep;
- m_EverKept = keep;
- m_State = state;
- }
-
- #endregion
-
- #region Properties
-
- ///
- /// Gets or sets a value indicating whether this is active.
- ///
- /// true if active; otherwise, false.
- public bool Active
- {
- get
- {
- return m_Active;
- }
- set
- {
- m_Active = value;
- }
- }
-
- ///
- /// Gets or sets a value indicating whether this is keep.
- ///
- /// true if keep; otherwise, false.
- public bool Keep
- {
- get
- {
- return m_Keep;
- }
- set
- {
- m_Keep = value;
- if(m_Keep)
- {
- m_EverKept = true;
- }
- }
- }
-
- ///
- /// Gets a value indicating whether [ever kept].
- ///
- /// true if [ever kept]; otherwise, false.
- public bool EverKept
- {
- get
- {
- return m_EverKept;
- }
- }
-
- ///
- /// Gets or sets the state.
- ///
- /// The state.
- public IfState State
- {
- get
- {
- return m_State;
- }
- set
- {
- m_State = value;
- }
- }
-
- #endregion
- }
-}
+#region BSD License
+/*
+Copyright (c) 2004-2005 Matthew Holmes (matthew@wildfiregames.com), Dan Moorehead (dan05a@gmail.com)
+
+Redistribution and use in source and binary forms, with or without modification, are permitted
+provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions
+ and the following disclaimer.
+* 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.
+* The name of the author may not be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+*/
+#endregion
+
+#region CVS Information
+/*
+ * $Source$
+ * $Author: jendave $
+ * $Date: 2006-01-28 01:49:58 +0100 (lö, 28 jan 2006) $
+ * $Revision: 71 $
+ */
+#endregion
+
+using System;
+
+namespace Prebuild.Core.Parse
+{
+ ///
+ ///
+ ///
+ public enum IfState
+ {
+ ///
+ ///
+ ///
+ None,
+ ///
+ ///
+ ///
+ If,
+ ///
+ ///
+ ///
+ ElseIf,
+ ///
+ ///
+ ///
+ Else
+ }
+
+ ///
+ /// Summary description for IfContext.
+ ///
+ // Inspired by the equivalent WiX class (see www.sourceforge.net/projects/wix/)
+ public class IfContext
+ {
+ #region Properties
+
+ bool m_Active;
+ bool m_Keep;
+ bool m_EverKept;
+ IfState m_State = IfState.None;
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// if set to true [active].
+ /// if set to true [keep].
+ /// The state.
+ public IfContext(bool active, bool keep, IfState state)
+ {
+ m_Active = active;
+ m_Keep = keep;
+ m_EverKept = keep;
+ m_State = state;
+ }
+
+ #endregion
+
+ #region Properties
+
+ ///
+ /// Gets or sets a value indicating whether this is active.
+ ///
+ /// true if active; otherwise, false.
+ public bool Active
+ {
+ get
+ {
+ return m_Active;
+ }
+ set
+ {
+ m_Active = value;
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether this is keep.
+ ///
+ /// true if keep; otherwise, false.
+ public bool Keep
+ {
+ get
+ {
+ return m_Keep;
+ }
+ set
+ {
+ m_Keep = value;
+ if(m_Keep)
+ {
+ m_EverKept = true;
+ }
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether [ever kept].
+ ///
+ /// true if [ever kept]; otherwise, false.
+ public bool EverKept
+ {
+ get
+ {
+ return m_EverKept;
+ }
+ }
+
+ ///
+ /// Gets or sets the state.
+ ///
+ /// The state.
+ public IfState State
+ {
+ get
+ {
+ return m_State;
+ }
+ set
+ {
+ m_State = value;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Prebuild/src/Core/Parse/Preprocessor.cs b/Prebuild/src/Core/Parse/Preprocessor.cs
index 85e92c3..c4e1e61 100644
--- a/Prebuild/src/Core/Parse/Preprocessor.cs
+++ b/Prebuild/src/Core/Parse/Preprocessor.cs
@@ -1,519 +1,519 @@
-#region BSD License
-/*
-Copyright (c) 2004-2005 Matthew Holmes (matthew@wildfiregames.com), Dan Moorehead (dan05a@gmail.com)
-
-Redistribution and use in source and binary forms, with or without modification, are permitted
-provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this list of conditions
- and the following disclaimer.
-* 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.
-* The name of the author may not be used to endorse or promote products derived from this software
- without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-*/
-#endregion
-
-#region CVS Information
-/*
- * $Source$
- * $Author: jendave $
- * $Date: 2006-09-01 19:55:06 +0200 (fr, 01 sep 2006) $
- * $Revision: 147 $
- */
-#endregion
-
-using System;
-using System.Collections;
-using System.IO;
-using System.Xml;
-
-namespace Prebuild.Core.Parse
-{
- ///
- ///
- ///
- public enum OperatorSymbol
- {
- ///
- ///
- ///
- None,
- ///
- ///
- ///
- Equal,
- ///
- ///
- ///
- NotEqual,
- ///
- ///
- ///
- LessThan,
- ///
- ///
- ///
- GreaterThan,
- ///
- ///
- ///
- LessThanEqual,
- ///
- ///
- ///
- GreaterThanEqual
- }
-
- ///
- ///
- ///
- public class Preprocessor
- {
- #region Fields
-
- XmlDocument m_OutDoc;
- Stack m_IfStack;
- Hashtable m_Variables;
-
- #endregion
-
- #region Constructors
-
- ///
- /// Initializes a new instance of the class.
- ///
- public Preprocessor()
- {
- m_OutDoc = new XmlDocument();
- m_IfStack = new Stack();
- m_Variables = new Hashtable();
-
- RegisterVariable("OS", GetOS());
- RegisterVariable("RuntimeVersion", Environment.Version.Major);
- RegisterVariable("RuntimeMajor", Environment.Version.Major);
- RegisterVariable("RuntimeMinor", Environment.Version.Minor);
- RegisterVariable("RuntimeRevision", Environment.Version.Revision);
- }
-
- #endregion
-
- #region Properties
-
- ///
- /// Gets the processed doc.
- ///
- /// The processed doc.
- public XmlDocument ProcessedDoc
- {
- get
- {
- return m_OutDoc;
- }
- }
-
- #endregion
-
- #region Private Methods
-
- ///
- /// Parts of this code were taken from NAnt and is subject to the GPL
- /// as per NAnt's license. Thanks to the NAnt guys for this little gem.
- ///
- ///
- public static string GetOS()
- {
- PlatformID platId = Environment.OSVersion.Platform;
- if(platId == PlatformID.Win32NT || platId == PlatformID.Win32Windows)
- {
- return "Win32";
- }
-
- /*
- * .NET 1.x, under Mono, the UNIX code is 128. Under
- * .NET 2.x, Mono or MS, the UNIX code is 4
- */
- if(Environment.Version.Major == 1)
- {
- if((int)platId == 128)
- {
- return "UNIX";
- }
- }
- else if((int)platId == 4)
- {
- return "UNIX";
- }
-
- return "Unknown";
- }
-
- private static bool CompareNum(OperatorSymbol oper, int val1, int val2)
- {
- switch(oper)
- {
- case OperatorSymbol.Equal:
- return (val1 == val2);
- case OperatorSymbol.NotEqual:
- return (val1 != val2);
- case OperatorSymbol.LessThan:
- return (val1 < val2);
- case OperatorSymbol.LessThanEqual:
- return (val1 <= val2);
- case OperatorSymbol.GreaterThan:
- return (val1 > val2);
- case OperatorSymbol.GreaterThanEqual:
- return (val1 >= val2);
- }
-
- throw new WarningException("Unknown operator type");
- }
-
- private static bool CompareStr(OperatorSymbol oper, string val1, string val2)
- {
- switch(oper)
- {
- case OperatorSymbol.Equal:
- return (val1 == val2);
- case OperatorSymbol.NotEqual:
- return (val1 != val2);
- case OperatorSymbol.LessThan:
- return (val1.CompareTo(val2) < 0);
- case OperatorSymbol.LessThanEqual:
- return (val1.CompareTo(val2) <= 0);
- case OperatorSymbol.GreaterThan:
- return (val1.CompareTo(val2) > 0);
- case OperatorSymbol.GreaterThanEqual:
- return (val1.CompareTo(val2) >= 0);
- }
-
- throw new WarningException("Unknown operator type");
- }
-
- private static char NextChar(int idx, string str)
- {
- if((idx + 1) >= str.Length)
- {
- return Char.MaxValue;
- }
-
- return str[idx + 1];
- }
- // Very very simple expression parser. Can only match expressions of the form
- // :
- // OS = Windows
- // OS != Linux
- // RuntimeMinor > 0
- private bool ParseExpression(string exp)
- {
- if(exp == null)
- {
- throw new ArgumentException("Invalid expression, cannot be null");
- }
-
- exp = exp.Trim();
- if(exp.Length < 1)
- {
- throw new ArgumentException("Invalid expression, cannot be 0 length");
- }
-
- string id = "";
- string str = "";
- OperatorSymbol oper = OperatorSymbol.None;
- bool inStr = false;
- char c;
-
- for(int i = 0; i < exp.Length; i++)
- {
- c = exp[i];
- if(Char.IsWhiteSpace(c))
- {
- continue;
- }
-
- if(Char.IsLetterOrDigit(c) || c == '_')
- {
- if(inStr)
- {
- str += c;
- }
- else
- {
- id += c;
- }
- }
- else if(c == '\"')
- {
- inStr = !inStr;
- if(inStr)
- {
- str = "";
- }
- }
- else
- {
- if(inStr)
- {
- str += c;
- }
- else
- {
- switch(c)
- {
- case '=':
- oper = OperatorSymbol.Equal;
- break;
-
- case '!':
- if(NextChar(i, exp) == '=')
- {
- oper = OperatorSymbol.NotEqual;
- }
-
- break;
-
- case '<':
- if(NextChar(i, exp) == '=')
- {
- oper = OperatorSymbol.LessThanEqual;
- }
- else
- {
- oper = OperatorSymbol.LessThan;
- }
-
- break;
-
- case '>':
- if(NextChar(i, exp) == '=')
- {
- oper = OperatorSymbol.GreaterThanEqual;
- }
- else
- {
- oper = OperatorSymbol.GreaterThan;
- }
-
- break;
- }
- }
- }
- }
-
-
- if(inStr)
- {
- throw new WarningException("Expected end of string in expression");
- }
-
- if(oper == OperatorSymbol.None)
- {
- throw new WarningException("Expected operator in expression");
- }
- else if(id.Length < 1)
- {
- throw new WarningException("Expected identifier in expression");
- }
- else if(str.Length < 1)
- {
- throw new WarningException("Expected value in expression");
- }
-
- bool ret = false;
- try
- {
- object val = m_Variables[id.ToLower()];
- if(val == null)
- {
- throw new WarningException("Unknown identifier '{0}'", id);
- }
-
- int numVal, numVal2;
- string strVal, strVal2;
- Type t = val.GetType();
- if(t.IsAssignableFrom(typeof(int)))
- {
- numVal = (int)val;
- numVal2 = Int32.Parse(str);
- ret = CompareNum(oper, numVal, numVal2);
- }
- else
- {
- strVal = val.ToString();
- strVal2 = str;
- ret = CompareStr(oper, strVal, strVal2);
- }
- }
- catch(ArgumentException ex)
- {
- ex.ToString();
- throw new WarningException("Invalid value type for system variable '{0}', expected int", id);
- }
-
- return ret;
- }
-
- #endregion
-
- #region Public Methods
-
- ///
- ///
- ///
- ///
- ///
- public void RegisterVariable(string name, object variableValue)
- {
- if(name == null || variableValue == null)
- {
- return;
- }
-
- m_Variables[name.ToLower()] = variableValue;
- }
-
- ///
- /// Performs validation on the xml source as well as evaluates conditional and flow expresions
- ///
- /// For invalid use of conditional expressions or for invalid XML syntax. If a XmlValidatingReader is passed, then will also throw exceptions for non-schema-conforming xml
- ///
- /// the output xml
- public string Process(XmlReader reader)
- {
- if(reader == null)
- {
- throw new ArgumentException("Invalid XML reader to pre-process");
- }
-
- IfContext context = new IfContext(true, true, IfState.None);
- StringWriter xmlText = new StringWriter();
- XmlTextWriter writer = new XmlTextWriter(xmlText);
- writer.Formatting = Formatting.Indented;
- while(reader.Read())
- {
- if(reader.NodeType == XmlNodeType.ProcessingInstruction)
- {
- bool ignore = false;
- switch(reader.LocalName)
- {
- case "if":
- m_IfStack.Push(context);
- context = new IfContext(context.Keep & context.Active, ParseExpression(reader.Value), IfState.If);
- ignore = true;
- break;
-
- case "elseif":
- if(m_IfStack.Count == 0)
- {
- throw new WarningException("Unexpected 'elseif' outside of 'if'");
- }
- else if(context.State != IfState.If && context.State != IfState.ElseIf)
- {
- throw new WarningException("Unexpected 'elseif' outside of 'if'");
- }
-
- context.State = IfState.ElseIf;
- if(!context.EverKept)
- {
- context.Keep = ParseExpression(reader.Value);
- }
- else
- {
- context.Keep = false;
- }
-
- ignore = true;
- break;
-
- case "else":
- if(m_IfStack.Count == 0)
- {
- throw new WarningException("Unexpected 'else' outside of 'if'");
- }
- else if(context.State != IfState.If && context.State != IfState.ElseIf)
- {
- throw new WarningException("Unexpected 'else' outside of 'if'");
- }
-
- context.State = IfState.Else;
- context.Keep = !context.EverKept;
- ignore = true;
- break;
-
- case "endif":
- if(m_IfStack.Count == 0)
- {
- throw new WarningException("Unexpected 'endif' outside of 'if'");
- }
-
- context = (IfContext)m_IfStack.Pop();
- ignore = true;
- break;
- }
-
- if(ignore)
- {
- continue;
- }
- }//end pre-proc instruction
-
- if(!context.Active || !context.Keep)
- {
- continue;
- }
-
- switch(reader.NodeType)
- {
- case XmlNodeType.Element:
- bool empty = reader.IsEmptyElement;
- writer.WriteStartElement(reader.Name);
-
- while (reader.MoveToNextAttribute())
- {
- writer.WriteAttributeString(reader.Name, reader.Value);
- }
-
- if(empty)
- {
- writer.WriteEndElement();
- }
-
- break;
-
- case XmlNodeType.EndElement:
- writer.WriteEndElement();
- break;
-
- case XmlNodeType.Text:
- writer.WriteString(reader.Value);
- break;
-
- case XmlNodeType.CDATA:
- writer.WriteCData(reader.Value);
- break;
-
- default:
- break;
- }
- }
-
- if(m_IfStack.Count != 0)
- {
- throw new WarningException("Mismatched 'if', 'endif' pair");
- }
-
- return xmlText.ToString();
- }
-
- #endregion
- }
-}
+#region BSD License
+/*
+Copyright (c) 2004-2005 Matthew Holmes (matthew@wildfiregames.com), Dan Moorehead (dan05a@gmail.com)
+
+Redistribution and use in source and binary forms, with or without modification, are permitted
+provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions
+ and the following disclaimer.
+* 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.
+* The name of the author may not be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+*/
+#endregion
+
+#region CVS Information
+/*
+ * $Source$
+ * $Author: jendave $
+ * $Date: 2006-09-01 19:55:06 +0200 (fr, 01 sep 2006) $
+ * $Revision: 147 $
+ */
+#endregion
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Xml;
+
+namespace Prebuild.Core.Parse
+{
+ ///
+ ///
+ ///
+ public enum OperatorSymbol
+ {
+ ///
+ ///
+ ///
+ None,
+ ///
+ ///
+ ///
+ Equal,
+ ///
+ ///
+ ///
+ NotEqual,
+ ///
+ ///
+ ///
+ LessThan,
+ ///
+ ///
+ ///
+ GreaterThan,
+ ///
+ ///
+ ///
+ LessThanEqual,
+ ///
+ ///
+ ///
+ GreaterThanEqual
+ }
+
+ ///
+ ///
+ ///
+ public class Preprocessor
+ {
+ #region Fields
+
+ XmlDocument m_OutDoc;
+ Stack m_IfStack;
+ Hashtable m_Variables;
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Preprocessor()
+ {
+ m_OutDoc = new XmlDocument();
+ m_IfStack = new Stack();
+ m_Variables = new Hashtable();
+
+ RegisterVariable("OS", GetOS());
+ RegisterVariable("RuntimeVersion", Environment.Version.Major);
+ RegisterVariable("RuntimeMajor", Environment.Version.Major);
+ RegisterVariable("RuntimeMinor", Environment.Version.Minor);
+ RegisterVariable("RuntimeRevision", Environment.Version.Revision);
+ }
+
+ #endregion
+
+ #region Properties
+
+ ///
+ /// Gets the processed doc.
+ ///
+ /// The processed doc.
+ public XmlDocument ProcessedDoc
+ {
+ get
+ {
+ return m_OutDoc;
+ }
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ ///
+ /// Parts of this code were taken from NAnt and is subject to the GPL
+ /// as per NAnt's license. Thanks to the NAnt guys for this little gem.
+ ///
+ ///
+ public static string GetOS()
+ {
+ PlatformID platId = Environment.OSVersion.Platform;
+ if(platId == PlatformID.Win32NT || platId == PlatformID.Win32Windows)
+ {
+ return "Win32";
+ }
+
+ /*
+ * .NET 1.x, under Mono, the UNIX code is 128. Under
+ * .NET 2.x, Mono or MS, the UNIX code is 4
+ */
+ if(Environment.Version.Major == 1)
+ {
+ if((int)platId == 128)
+ {
+ return "UNIX";
+ }
+ }
+ else if((int)platId == 4)
+ {
+ return "UNIX";
+ }
+
+ return "Unknown";
+ }
+
+ private static bool CompareNum(OperatorSymbol oper, int val1, int val2)
+ {
+ switch(oper)
+ {
+ case OperatorSymbol.Equal:
+ return (val1 == val2);
+ case OperatorSymbol.NotEqual:
+ return (val1 != val2);
+ case OperatorSymbol.LessThan:
+ return (val1 < val2);
+ case OperatorSymbol.LessThanEqual:
+ return (val1 <= val2);
+ case OperatorSymbol.GreaterThan:
+ return (val1 > val2);
+ case OperatorSymbol.GreaterThanEqual:
+ return (val1 >= val2);
+ }
+
+ throw new WarningException("Unknown operator type");
+ }
+
+ private static bool CompareStr(OperatorSymbol oper, string val1, string val2)
+ {
+ switch(oper)
+ {
+ case OperatorSymbol.Equal:
+ return (val1 == val2);
+ case OperatorSymbol.NotEqual:
+ return (val1 != val2);
+ case OperatorSymbol.LessThan:
+ return (val1.CompareTo(val2) < 0);
+ case OperatorSymbol.LessThanEqual:
+ return (val1.CompareTo(val2) <= 0);
+ case OperatorSymbol.GreaterThan:
+ return (val1.CompareTo(val2) > 0);
+ case OperatorSymbol.GreaterThanEqual:
+ return (val1.CompareTo(val2) >= 0);
+ }
+
+ throw new WarningException("Unknown operator type");
+ }
+
+ private static char NextChar(int idx, string str)
+ {
+ if((idx + 1) >= str.Length)
+ {
+ return Char.MaxValue;
+ }
+
+ return str[idx + 1];
+ }
+ // Very very simple expression parser. Can only match expressions of the form
+ // :
+ // OS = Windows
+ // OS != Linux
+ // RuntimeMinor > 0
+ private bool ParseExpression(string exp)
+ {
+ if(exp == null)
+ {
+ throw new ArgumentException("Invalid expression, cannot be null");
+ }
+
+ exp = exp.Trim();
+ if(exp.Length < 1)
+ {
+ throw new ArgumentException("Invalid expression, cannot be 0 length");
+ }
+
+ string id = "";
+ string str = "";
+ OperatorSymbol oper = OperatorSymbol.None;
+ bool inStr = false;
+ char c;
+
+ for(int i = 0; i < exp.Length; i++)
+ {
+ c = exp[i];
+ if(Char.IsWhiteSpace(c))
+ {
+ continue;
+ }
+
+ if(Char.IsLetterOrDigit(c) || c == '_')
+ {
+ if(inStr)
+ {
+ str += c;
+ }
+ else
+ {
+ id += c;
+ }
+ }
+ else if(c == '\"')
+ {
+ inStr = !inStr;
+ if(inStr)
+ {
+ str = "";
+ }
+ }
+ else
+ {
+ if(inStr)
+ {
+ str += c;
+ }
+ else
+ {
+ switch(c)
+ {
+ case '=':
+ oper = OperatorSymbol.Equal;
+ break;
+
+ case '!':
+ if(NextChar(i, exp) == '=')
+ {
+ oper = OperatorSymbol.NotEqual;
+ }
+
+ break;
+
+ case '<':
+ if(NextChar(i, exp) == '=')
+ {
+ oper = OperatorSymbol.LessThanEqual;
+ }
+ else
+ {
+ oper = OperatorSymbol.LessThan;
+ }
+
+ break;
+
+ case '>':
+ if(NextChar(i, exp) == '=')
+ {
+ oper = OperatorSymbol.GreaterThanEqual;
+ }
+ else
+ {
+ oper = OperatorSymbol.GreaterThan;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+
+ if(inStr)
+ {
+ throw new WarningException("Expected end of string in expression");
+ }
+
+ if(oper == OperatorSymbol.None)
+ {
+ throw new WarningException("Expected operator in expression");
+ }
+ else if(id.Length < 1)
+ {
+ throw new WarningException("Expected identifier in expression");
+ }
+ else if(str.Length < 1)
+ {
+ throw new WarningException("Expected value in expression");
+ }
+
+ bool ret = false;
+ try
+ {
+ object val = m_Variables[id.ToLower()];
+ if(val == null)
+ {
+ throw new WarningException("Unknown identifier '{0}'", id);
+ }
+
+ int numVal, numVal2;
+ string strVal, strVal2;
+ Type t = val.GetType();
+ if(t.IsAssignableFrom(typeof(int)))
+ {
+ numVal = (int)val;
+ numVal2 = Int32.Parse(str);
+ ret = CompareNum(oper, numVal, numVal2);
+ }
+ else
+ {
+ strVal = val.ToString();
+ strVal2 = str;
+ ret = CompareStr(oper, strVal, strVal2);
+ }
+ }
+ catch(ArgumentException ex)
+ {
+ ex.ToString();
+ throw new WarningException("Invalid value type for system variable '{0}', expected int", id);
+ }
+
+ return ret;
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void RegisterVariable(string name, object variableValue)
+ {
+ if(name == null || variableValue == null)
+ {
+ return;
+ }
+
+ m_Variables[name.ToLower()] = variableValue;
+ }
+
+ ///
+ /// Performs validation on the xml source as well as evaluates conditional and flow expresions
+ ///
+ /// For invalid use of conditional expressions or for invalid XML syntax. If a XmlValidatingReader is passed, then will also throw exceptions for non-schema-conforming xml
+ ///
+ /// the output xml
+ public string Process(XmlReader reader)
+ {
+ if(reader == null)
+ {
+ throw new ArgumentException("Invalid XML reader to pre-process");
+ }
+
+ IfContext context = new IfContext(true, true, IfState.None);
+ StringWriter xmlText = new StringWriter();
+ XmlTextWriter writer = new XmlTextWriter(xmlText);
+ writer.Formatting = Formatting.Indented;
+ while(reader.Read())
+ {
+ if(reader.NodeType == XmlNodeType.ProcessingInstruction)
+ {
+ bool ignore = false;
+ switch(reader.LocalName)
+ {
+ case "if":
+ m_IfStack.Push(context);
+ context = new IfContext(context.Keep & context.Active, ParseExpression(reader.Value), IfState.If);
+ ignore = true;
+ break;
+
+ case "elseif":
+ if(m_IfStack.Count == 0)
+ {
+ throw new WarningException("Unexpected 'elseif' outside of 'if'");
+ }
+ else if(context.State != IfState.If && context.State != IfState.ElseIf)
+ {
+ throw new WarningException("Unexpected 'elseif' outside of 'if'");
+ }
+
+ context.State = IfState.ElseIf;
+ if(!context.EverKept)
+ {
+ context.Keep = ParseExpression(reader.Value);
+ }
+ else
+ {
+ context.Keep = false;
+ }
+
+ ignore = true;
+ break;
+
+ case "else":
+ if(m_IfStack.Count == 0)
+ {
+ throw new WarningException("Unexpected 'else' outside of 'if'");
+ }
+ else if(context.State != IfState.If && context.State != IfState.ElseIf)
+ {
+ throw new WarningException("Unexpected 'else' outside of 'if'");
+ }
+
+ context.State = IfState.Else;
+ context.Keep = !context.EverKept;
+ ignore = true;
+ break;
+
+ case "endif":
+ if(m_IfStack.Count == 0)
+ {
+ throw new WarningException("Unexpected 'endif' outside of 'if'");
+ }
+
+ context = (IfContext)m_IfStack.Pop();
+ ignore = true;
+ break;
+ }
+
+ if(ignore)
+ {
+ continue;
+ }
+ }//end pre-proc instruction
+
+ if(!context.Active || !context.Keep)
+ {
+ continue;
+ }
+
+ switch(reader.NodeType)
+ {
+ case XmlNodeType.Element:
+ bool empty = reader.IsEmptyElement;
+ writer.WriteStartElement(reader.Name);
+
+ while (reader.MoveToNextAttribute())
+ {
+ writer.WriteAttributeString(reader.Name, reader.Value);
+ }
+
+ if(empty)
+ {
+ writer.WriteEndElement();
+ }
+
+ break;
+
+ case XmlNodeType.EndElement:
+ writer.WriteEndElement();
+ break;
+
+ case XmlNodeType.Text:
+ writer.WriteString(reader.Value);
+ break;
+
+ case XmlNodeType.CDATA:
+ writer.WriteCData(reader.Value);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if(m_IfStack.Count != 0)
+ {
+ throw new WarningException("Mismatched 'if', 'endif' pair");
+ }
+
+ return xmlText.ToString();
+ }
+
+ #endregion
+ }
+}
--
cgit v1.1