From 7e65590a55ba575d0086bdfc25addaf1051d799b Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Sat, 11 Sep 2010 01:13:08 +0100
Subject: Update Prebuild.exe with Prebuild r323 + an existing OpenSim specific
nant hack to correctly clean up chosen OpenSim exes and dlls in bin/ on a
"nant clean"
Source code is included for reference. This can go away again once Prebuild is updated with a more general mechanism for cleaning up files.
The Prebuild source code here can be built with nant, or regnerated for other tools using the prebuild at {root}/bin/Prebuild.exe
---
Prebuild/src/Core/Parse/.svn/all-wcprops | 17 +
Prebuild/src/Core/Parse/.svn/dir-prop-base | 5 +
Prebuild/src/Core/Parse/.svn/entries | 96 +++
.../Parse/.svn/prop-base/IfContext.cs.svn-base | 9 +
.../Parse/.svn/prop-base/Preprocessor.cs.svn-base | 9 +
.../Parse/.svn/text-base/IfContext.cs.svn-base | 154 +++++
.../Parse/.svn/text-base/Preprocessor.cs.svn-base | 652 +++++++++++++++++++++
Prebuild/src/Core/Parse/IfContext.cs | 154 +++++
Prebuild/src/Core/Parse/Preprocessor.cs | 652 +++++++++++++++++++++
9 files changed, 1748 insertions(+)
create mode 100644 Prebuild/src/Core/Parse/.svn/all-wcprops
create mode 100644 Prebuild/src/Core/Parse/.svn/dir-prop-base
create mode 100644 Prebuild/src/Core/Parse/.svn/entries
create mode 100644 Prebuild/src/Core/Parse/.svn/prop-base/IfContext.cs.svn-base
create mode 100644 Prebuild/src/Core/Parse/.svn/prop-base/Preprocessor.cs.svn-base
create mode 100644 Prebuild/src/Core/Parse/.svn/text-base/IfContext.cs.svn-base
create mode 100644 Prebuild/src/Core/Parse/.svn/text-base/Preprocessor.cs.svn-base
create mode 100644 Prebuild/src/Core/Parse/IfContext.cs
create mode 100644 Prebuild/src/Core/Parse/Preprocessor.cs
(limited to 'Prebuild/src/Core/Parse')
diff --git a/Prebuild/src/Core/Parse/.svn/all-wcprops b/Prebuild/src/Core/Parse/.svn/all-wcprops
new file mode 100644
index 0000000..c77d416
--- /dev/null
+++ b/Prebuild/src/Core/Parse/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 56
+/svnroot/dnpb/!svn/ver/323/trunk/Prebuild/src/Core/Parse
+END
+IfContext.cs
+K 25
+svn:wc:ra_dav:version-url
+V 69
+/svnroot/dnpb/!svn/ver/295/trunk/Prebuild/src/Core/Parse/IfContext.cs
+END
+Preprocessor.cs
+K 25
+svn:wc:ra_dav:version-url
+V 72
+/svnroot/dnpb/!svn/ver/323/trunk/Prebuild/src/Core/Parse/Preprocessor.cs
+END
diff --git a/Prebuild/src/Core/Parse/.svn/dir-prop-base b/Prebuild/src/Core/Parse/.svn/dir-prop-base
new file mode 100644
index 0000000..a1989a0
--- /dev/null
+++ b/Prebuild/src/Core/Parse/.svn/dir-prop-base
@@ -0,0 +1,5 @@
+K 10
+svn:ignore
+V 5
+*.swp
+END
diff --git a/Prebuild/src/Core/Parse/.svn/entries b/Prebuild/src/Core/Parse/.svn/entries
new file mode 100644
index 0000000..2aae711
--- /dev/null
+++ b/Prebuild/src/Core/Parse/.svn/entries
@@ -0,0 +1,96 @@
+10
+
+dir
+323
+https://dnpb.svn.sourceforge.net/svnroot/dnpb/trunk/Prebuild/src/Core/Parse
+https://dnpb.svn.sourceforge.net/svnroot/dnpb
+
+
+
+2010-09-10T17:51:36.189738Z
+323
+jhurliman
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+3355ff64-970d-0410-bbe8-d0fbd18be4fb
+
+IfContext.cs
+file
+
+
+
+
+2010-09-10T22:51:44.000000Z
+859fca08c6a39a48f179d5ffe3d19bd0
+2009-02-19T06:47:52.218324Z
+295
+kunnis
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3653
+
+Preprocessor.cs
+file
+
+
+
+
+2010-09-10T22:51:44.000000Z
+6ef27f33f41caca9d4ab6c82ead76902
+2010-09-10T17:51:36.189738Z
+323
+jhurliman
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+18590
+
diff --git a/Prebuild/src/Core/Parse/.svn/prop-base/IfContext.cs.svn-base b/Prebuild/src/Core/Parse/.svn/prop-base/IfContext.cs.svn-base
new file mode 100644
index 0000000..7b57b30
--- /dev/null
+++ b/Prebuild/src/Core/Parse/.svn/prop-base/IfContext.cs.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/Prebuild/src/Core/Parse/.svn/prop-base/Preprocessor.cs.svn-base b/Prebuild/src/Core/Parse/.svn/prop-base/Preprocessor.cs.svn-base
new file mode 100644
index 0000000..7b57b30
--- /dev/null
+++ b/Prebuild/src/Core/Parse/.svn/prop-base/Preprocessor.cs.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+Author Date Id Revision
+END
diff --git a/Prebuild/src/Core/Parse/.svn/text-base/IfContext.cs.svn-base b/Prebuild/src/Core/Parse/.svn/text-base/IfContext.cs.svn-base
new file mode 100644
index 0000000..3c79d38
--- /dev/null
+++ b/Prebuild/src/Core/Parse/.svn/text-base/IfContext.cs.svn-base
@@ -0,0 +1,154 @@
+#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
+
+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/.svn/text-base/Preprocessor.cs.svn-base b/Prebuild/src/Core/Parse/.svn/text-base/Preprocessor.cs.svn-base
new file mode 100644
index 0000000..0648fad
--- /dev/null
+++ b/Prebuild/src/Core/Parse/.svn/text-base/Preprocessor.cs.svn-base
@@ -0,0 +1,652 @@
+#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
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Xml;
+
+namespace Prebuild.Core.Parse
+{
+ ///
+ ///
+ ///
+ public enum OperatorSymbol
+ {
+ ///
+ ///
+ ///
+ None,
+ ///
+ ///
+ ///
+ Equal,
+ ///
+ ///
+ ///
+ NotEqual,
+ ///
+ ///
+ ///
+ LessThan,
+ ///
+ ///
+ ///
+ GreaterThan,
+ ///
+ ///
+ ///
+ LessThanEqual,
+ ///
+ ///
+ ///
+ GreaterThanEqual
+ }
+
+ ///
+ ///
+ ///
+ public class Preprocessor
+ {
+ #region Constants
+
+ ///
+ /// Includes the regex to look for file tags in the processing instruction.
+ ///
+ private static readonly Regex includeFileRegex = new Regex("file=\"(.+?)\"");
+
+ #endregion
+
+ #region Fields
+
+ readonly XmlDocument m_OutDoc = new XmlDocument();
+ readonly Stack m_IfStack = new Stack();
+ readonly Dictionary m_Variables = new Dictionary();
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Preprocessor()
+ {
+ 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";
+ }
+
+ if (File.Exists("/System/Library/Frameworks/Cocoa.framework/Cocoa"))
+ {
+ return "MACOSX";
+ }
+
+ /*
+ * .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;
+
+ for(int i = 0; i < exp.Length; i++)
+ {
+ char 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");
+ }
+ if(id.Length < 1)
+ {
+ throw new WarningException("Expected identifier in expression");
+ }
+ if(str.Length < 1)
+ {
+ throw new WarningException("Expected value in expression");
+ }
+
+ bool ret;
+ try
+ {
+ object val = m_Variables[id.ToLower()];
+ if(val == null)
+ {
+ throw new WarningException("Unknown identifier '{0}'", id);
+ }
+
+ Type t = val.GetType();
+ if(t.IsAssignableFrom(typeof(int)))
+ {
+ int numVal = (int)val;
+ int numVal2 = Int32.Parse(str);
+ ret = CompareNum(oper, numVal, numVal2);
+ }
+ else
+ {
+ string strVal = val.ToString();
+ string 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;
+ }
+
+ ///
+ /// Taken from current Prebuild included in OpenSim 0.7.x
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ private static void WildCardInclude (Stack readerStack, string include)
+ {
+ if (!include.Contains ("*")) {
+ return;
+ }
+
+ // Console.WriteLine("Processing {0}", include);
+
+ // Break up the include into pre and post wildcard sections
+ string preWildcard = include.Substring (0, include.IndexOf ("*"));
+ string postWildcard = include.Substring (include.IndexOf ("*") + 2);
+
+ // If preWildcard is a directory, recurse
+ if (Directory.Exists (preWildcard)) {
+ string[] directories = Directory.GetDirectories (preWildcard);
+ Array.Sort (directories);
+ Array.Reverse (directories);
+ foreach (string dirPath in directories) {
+ //Console.WriteLine ("Scanning : {0}", dirPath);
+
+ string includeFile = Path.Combine (dirPath, postWildcard);
+ if (includeFile.Contains ("*")) {
+ // postWildcard included another wildcard, recurse.
+ WildCardInclude (readerStack, includeFile);
+ } else {
+ FileInfo file = new FileInfo (includeFile);
+ if (file.Exists) {
+ //Console.WriteLine ("Including File: {0}", includeFile);
+ XmlReader newReader = new XmlTextReader (file.Open (FileMode.Open, FileAccess.Read, FileShare.Read));
+ readerStack.Push (newReader);
+ }
+ }
+ }
+ } else {
+ // preWildcard is not a path to a directory, so the wildcard is in the filename
+ string searchFilename = Path.GetFileName (preWildcard.Substring (preWildcard.IndexOf ("/") + 1) + "*" + postWildcard);
+ Console.WriteLine ("searchFilename: {0}", searchFilename);
+
+ string searchDirectory = Path.GetDirectoryName (preWildcard);
+ Console.WriteLine ("searchDirectory: {0}", searchDirectory);
+
+ string[] files = Directory.GetFiles (searchDirectory, searchFilename);
+ Array.Sort (files);
+ Array.Reverse (files);
+ foreach (string includeFile in files) {
+ FileInfo file = new FileInfo (includeFile);
+ if (file.Exists) {
+ // Console.WriteLine ("Including File: {0}", includeFile);
+ XmlReader newReader = new XmlTextReader (file.Open (FileMode.Open, FileAccess.Read, FileShare.Read));
+ readerStack.Push (newReader);
+ }
+ }
+ }
+ }
+
+ #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 initialReader)
+ {
+ if(initialReader == 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;
+
+ // Create a queue of XML readers and add the initial
+ // reader to it. Then we process until we run out of
+ // readers which lets the operation add more
+ // readers to generate a multi-file parser and not require
+ // XML fragments that a recursive version would use.
+ Stack readerStack = new Stack();
+ readerStack.Push(initialReader);
+
+ while(readerStack.Count > 0)
+ {
+ // Pop off the next reader.
+ XmlReader reader = readerStack.Pop();
+
+ // Process through this XML reader until it is
+ // completed (or it is replaced by the include
+ // operation).
+ while(reader.Read())
+ {
+ // The prebuild file has a series of processing
+ // instructions which allow for specific
+ // inclusions based on operating system or to
+ // include additional files.
+ if(reader.NodeType == XmlNodeType.ProcessingInstruction)
+ {
+ bool ignore = false;
+
+ switch(reader.LocalName)
+ {
+ case "include":
+ // use regular expressions to parse out the attributes.
+ MatchCollection matches = includeFileRegex.Matches(reader.Value);
+
+ // make sure there is only one file attribute.
+ if(matches.Count > 1)
+ {
+ throw new WarningException("An node was found, but it specified more than one file.");
+ }
+
+ if(matches.Count == 0)
+ {
+ throw new WarningException("An node was found, but it did not specify the file attribute.");
+ }
+
+ // ***** Adding for wildcard handling
+ // Push current reader back onto the stack.
+ readerStack.Push (reader);
+
+ // Pull the file out from the regex and make sure it is a valid file before using it.
+ string filename = matches[0].Groups[1].Value;
+
+ filename = String.Join (Path.DirectorySeparatorChar.ToString (), filename.Split (new char[] { '/', '\\' }));
+
+ if (!filename.Contains ("*")) {
+
+ FileInfo includeFile = new FileInfo (filename);
+ if (!includeFile.Exists) {
+ throw new WarningException ("Cannot include file: " + includeFile.FullName);
+ }
+
+ // Create a new reader object for this file. Then put the old reader back on the stack and start
+ // processing using this new XML reader.
+
+ XmlReader newReader = new XmlTextReader (includeFile.Open (FileMode.Open, FileAccess.Read, FileShare.Read));
+ reader = newReader;
+ readerStack.Push (reader);
+
+ } else {
+ WildCardInclude (readerStack, filename);
+ }
+
+ reader = (XmlReader)readerStack.Pop ();
+ ignore = true;
+ break;
+
+ 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'");
+ }
+ 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'");
+ }
+ 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 = 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
+ }
+}
diff --git a/Prebuild/src/Core/Parse/IfContext.cs b/Prebuild/src/Core/Parse/IfContext.cs
new file mode 100644
index 0000000..3c79d38
--- /dev/null
+++ b/Prebuild/src/Core/Parse/IfContext.cs
@@ -0,0 +1,154 @@
+#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
+
+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
new file mode 100644
index 0000000..0648fad
--- /dev/null
+++ b/Prebuild/src/Core/Parse/Preprocessor.cs
@@ -0,0 +1,652 @@
+#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
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Xml;
+
+namespace Prebuild.Core.Parse
+{
+ ///
+ ///
+ ///
+ public enum OperatorSymbol
+ {
+ ///
+ ///
+ ///
+ None,
+ ///
+ ///
+ ///
+ Equal,
+ ///
+ ///
+ ///
+ NotEqual,
+ ///
+ ///
+ ///
+ LessThan,
+ ///
+ ///
+ ///
+ GreaterThan,
+ ///
+ ///
+ ///
+ LessThanEqual,
+ ///
+ ///
+ ///
+ GreaterThanEqual
+ }
+
+ ///
+ ///
+ ///
+ public class Preprocessor
+ {
+ #region Constants
+
+ ///
+ /// Includes the regex to look for file tags in the processing instruction.
+ ///
+ private static readonly Regex includeFileRegex = new Regex("file=\"(.+?)\"");
+
+ #endregion
+
+ #region Fields
+
+ readonly XmlDocument m_OutDoc = new XmlDocument();
+ readonly Stack m_IfStack = new Stack();
+ readonly Dictionary m_Variables = new Dictionary();
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Preprocessor()
+ {
+ 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";
+ }
+
+ if (File.Exists("/System/Library/Frameworks/Cocoa.framework/Cocoa"))
+ {
+ return "MACOSX";
+ }
+
+ /*
+ * .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;
+
+ for(int i = 0; i < exp.Length; i++)
+ {
+ char 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");
+ }
+ if(id.Length < 1)
+ {
+ throw new WarningException("Expected identifier in expression");
+ }
+ if(str.Length < 1)
+ {
+ throw new WarningException("Expected value in expression");
+ }
+
+ bool ret;
+ try
+ {
+ object val = m_Variables[id.ToLower()];
+ if(val == null)
+ {
+ throw new WarningException("Unknown identifier '{0}'", id);
+ }
+
+ Type t = val.GetType();
+ if(t.IsAssignableFrom(typeof(int)))
+ {
+ int numVal = (int)val;
+ int numVal2 = Int32.Parse(str);
+ ret = CompareNum(oper, numVal, numVal2);
+ }
+ else
+ {
+ string strVal = val.ToString();
+ string 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;
+ }
+
+ ///
+ /// Taken from current Prebuild included in OpenSim 0.7.x
+ ///
+ ///
+ /// A
+ ///
+ ///
+ /// A
+ ///
+ private static void WildCardInclude (Stack readerStack, string include)
+ {
+ if (!include.Contains ("*")) {
+ return;
+ }
+
+ // Console.WriteLine("Processing {0}", include);
+
+ // Break up the include into pre and post wildcard sections
+ string preWildcard = include.Substring (0, include.IndexOf ("*"));
+ string postWildcard = include.Substring (include.IndexOf ("*") + 2);
+
+ // If preWildcard is a directory, recurse
+ if (Directory.Exists (preWildcard)) {
+ string[] directories = Directory.GetDirectories (preWildcard);
+ Array.Sort (directories);
+ Array.Reverse (directories);
+ foreach (string dirPath in directories) {
+ //Console.WriteLine ("Scanning : {0}", dirPath);
+
+ string includeFile = Path.Combine (dirPath, postWildcard);
+ if (includeFile.Contains ("*")) {
+ // postWildcard included another wildcard, recurse.
+ WildCardInclude (readerStack, includeFile);
+ } else {
+ FileInfo file = new FileInfo (includeFile);
+ if (file.Exists) {
+ //Console.WriteLine ("Including File: {0}", includeFile);
+ XmlReader newReader = new XmlTextReader (file.Open (FileMode.Open, FileAccess.Read, FileShare.Read));
+ readerStack.Push (newReader);
+ }
+ }
+ }
+ } else {
+ // preWildcard is not a path to a directory, so the wildcard is in the filename
+ string searchFilename = Path.GetFileName (preWildcard.Substring (preWildcard.IndexOf ("/") + 1) + "*" + postWildcard);
+ Console.WriteLine ("searchFilename: {0}", searchFilename);
+
+ string searchDirectory = Path.GetDirectoryName (preWildcard);
+ Console.WriteLine ("searchDirectory: {0}", searchDirectory);
+
+ string[] files = Directory.GetFiles (searchDirectory, searchFilename);
+ Array.Sort (files);
+ Array.Reverse (files);
+ foreach (string includeFile in files) {
+ FileInfo file = new FileInfo (includeFile);
+ if (file.Exists) {
+ // Console.WriteLine ("Including File: {0}", includeFile);
+ XmlReader newReader = new XmlTextReader (file.Open (FileMode.Open, FileAccess.Read, FileShare.Read));
+ readerStack.Push (newReader);
+ }
+ }
+ }
+ }
+
+ #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 initialReader)
+ {
+ if(initialReader == 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;
+
+ // Create a queue of XML readers and add the initial
+ // reader to it. Then we process until we run out of
+ // readers which lets the operation add more
+ // readers to generate a multi-file parser and not require
+ // XML fragments that a recursive version would use.
+ Stack readerStack = new Stack();
+ readerStack.Push(initialReader);
+
+ while(readerStack.Count > 0)
+ {
+ // Pop off the next reader.
+ XmlReader reader = readerStack.Pop();
+
+ // Process through this XML reader until it is
+ // completed (or it is replaced by the include
+ // operation).
+ while(reader.Read())
+ {
+ // The prebuild file has a series of processing
+ // instructions which allow for specific
+ // inclusions based on operating system or to
+ // include additional files.
+ if(reader.NodeType == XmlNodeType.ProcessingInstruction)
+ {
+ bool ignore = false;
+
+ switch(reader.LocalName)
+ {
+ case "include":
+ // use regular expressions to parse out the attributes.
+ MatchCollection matches = includeFileRegex.Matches(reader.Value);
+
+ // make sure there is only one file attribute.
+ if(matches.Count > 1)
+ {
+ throw new WarningException("An node was found, but it specified more than one file.");
+ }
+
+ if(matches.Count == 0)
+ {
+ throw new WarningException("An node was found, but it did not specify the file attribute.");
+ }
+
+ // ***** Adding for wildcard handling
+ // Push current reader back onto the stack.
+ readerStack.Push (reader);
+
+ // Pull the file out from the regex and make sure it is a valid file before using it.
+ string filename = matches[0].Groups[1].Value;
+
+ filename = String.Join (Path.DirectorySeparatorChar.ToString (), filename.Split (new char[] { '/', '\\' }));
+
+ if (!filename.Contains ("*")) {
+
+ FileInfo includeFile = new FileInfo (filename);
+ if (!includeFile.Exists) {
+ throw new WarningException ("Cannot include file: " + includeFile.FullName);
+ }
+
+ // Create a new reader object for this file. Then put the old reader back on the stack and start
+ // processing using this new XML reader.
+
+ XmlReader newReader = new XmlTextReader (includeFile.Open (FileMode.Open, FileAccess.Read, FileShare.Read));
+ reader = newReader;
+ readerStack.Push (reader);
+
+ } else {
+ WildCardInclude (readerStack, filename);
+ }
+
+ reader = (XmlReader)readerStack.Pop ();
+ ignore = true;
+ break;
+
+ 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'");
+ }
+ 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'");
+ }
+ 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 = 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