From dd9640cda82bca8125289f292238ea6b447cc6e9 Mon Sep 17 00:00:00 2001
From: lbsa71
Date: Thu, 19 Feb 2009 12:48:38 +0000
Subject: === PREBUILD UPSTREAMS UPDATE : POTENTIAL BREAKAGE ===
* Applied upstreams changes to allow for auditing and debugging in our various environments.
* This should, in theory, bring back 'multiple ref dirs'.
* Temporarily Removed xmlns because prebuild-1.7 schema does not allow for multiple solutions per prebuild node (This will be a moot issue once the Prebuild node is moved out of prebuild.xml)
* Autotools target: Various minor fixes
* MonoDevelop Target : No changes.
* Nant Target: Various minor fixes, support for net-3.5 and mono-2.0/3.5 targets
* Sharpdevelop targets: No changes.
* VS Targets: Refactored into using VSGenericTarget, and supports 2.0-3.5
* XCode Target: No changes.
--- Regressions and outstanding issues ---
* The Solution is assigned a random Guid - will lead to unnecessary reloads and loss of user settings.
--- New features of Prebuild 2.0.4 ---
* (Better) support for Web, WinForms and Database Projects and build actions
* Conditional Framework Version compilation support (1.1, 2.0-3.5)
* ArrayList -> List<>, ICollection -> IList
(this means Prebuild can generate 1.1 solutions, but can't itself be built under 1.1 - how very meta)
* Added preprocessor directive.
---
Prebuild/src/Core/Parse/Preprocessor.cs | 272 +++++++++++++++++++-------------
1 file changed, 165 insertions(+), 107 deletions(-)
(limited to 'Prebuild/src/Core/Parse/Preprocessor.cs')
diff --git a/Prebuild/src/Core/Parse/Preprocessor.cs b/Prebuild/src/Core/Parse/Preprocessor.cs
index eea5c30..013f8e1 100644
--- a/Prebuild/src/Core/Parse/Preprocessor.cs
+++ b/Prebuild/src/Core/Parse/Preprocessor.cs
@@ -23,18 +23,10 @@ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY O
*/
#endregion
-#region CVS Information
-/*
- * $Source$
- * $Author: jendave $
- * $Date: 2007-04-26 17:10:27 +0900 (Thu, 26 Apr 2007) $
- * $Revision: 236 $
- */
-#endregion
-
using System;
using System.Collections;
using System.IO;
+using System.Text.RegularExpressions;
using System.Xml;
namespace Prebuild.Core.Parse
@@ -79,6 +71,16 @@ namespace Prebuild.Core.Parse
///
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
XmlDocument m_OutDoc;
@@ -138,10 +140,10 @@ namespace Prebuild.Core.Parse
return "Win32";
}
- if (File.Exists("/System/Library/Frameworks/Cocoa.framework/Cocoa"))
- {
- return "MACOSX";
- }
+ if (File.Exists("/System/Library/Frameworks/Cocoa.framework/Cocoa"))
+ {
+ return "MACOSX";
+ }
/*
* .NET 1.x, under Mono, the UNIX code is 128. Under
@@ -236,7 +238,7 @@ namespace Prebuild.Core.Parse
OperatorSymbol oper = OperatorSymbol.None;
bool inStr = false;
char c;
-
+
for(int i = 0; i < exp.Length; i++)
{
c = exp[i];
@@ -283,7 +285,7 @@ namespace Prebuild.Core.Parse
{
oper = OperatorSymbol.NotEqual;
}
-
+
break;
case '<':
@@ -295,7 +297,7 @@ namespace Prebuild.Core.Parse
{
oper = OperatorSymbol.LessThan;
}
-
+
break;
case '>':
@@ -314,7 +316,7 @@ namespace Prebuild.Core.Parse
}
}
-
+
if(inStr)
{
throw new WarningException("Expected end of string in expression");
@@ -392,9 +394,9 @@ namespace Prebuild.Core.Parse
/// 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)
+ public string Process(XmlReader initialReader)
{
- if(reader == null)
+ if(initialReader == null)
{
throw new ArgumentException("Invalid XML reader to pre-process");
}
@@ -403,119 +405,175 @@ namespace Prebuild.Core.Parse
StringWriter xmlText = new StringWriter();
XmlTextWriter writer = new XmlTextWriter(xmlText);
writer.Formatting = Formatting.Indented;
- while(reader.Read())
+
+ // 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)
{
- if(reader.NodeType == XmlNodeType.ProcessingInstruction)
+ // Pop off the next reader.
+ XmlReader reader = (XmlReader) readerStack.Pop();
+
+ // Process through this XML reader until it is
+ // completed (or it is replaced by the include
+ // operation).
+ while(reader.Read())
{
- bool ignore = false;
- switch(reader.LocalName)
+ // 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)
{
- case "if":
- m_IfStack.Push(context);
- context = new IfContext(context.Keep & context.Active, ParseExpression(reader.Value), IfState.If);
- ignore = true;
- break;
+ bool ignore = false;
- 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'");
- }
+ 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.");
+ }
- context.State = IfState.ElseIf;
- if(!context.EverKept)
- {
- context.Keep = ParseExpression(reader.Value);
- }
- else
- {
- context.Keep = false;
- }
+ if(matches.Count == 0)
+ {
+ throw new WarningException("An node was found, but it did not specify the file attribute.");
+ }
+
+ // 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;
+ FileInfo includeFile = new FileInfo(filename);
- ignore = true;
- break;
+ if(!includeFile.Exists)
+ {
+ throw new WarningException("Cannot include file: " + includeFile.FullName);
+ }
- 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'");
- }
+ // 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));
- context.State = IfState.Else;
- context.Keep = !context.EverKept;
- ignore = true;
- break;
+ readerStack.Push(reader);
+ reader = newReader;
+ ignore = true;
+ break;
- case "endif":
- if(m_IfStack.Count == 0)
- {
- throw new WarningException("Unexpected 'endif' outside of 'if'");
- }
+ case "if":
+ m_IfStack.Push(context);
+ context = new IfContext(context.Keep & context.Active, ParseExpression(reader.Value), IfState.If);
+ ignore = true;
+ break;
- context = (IfContext)m_IfStack.Pop();
- 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'");
+ }
- if(ignore)
- {
- continue;
- }
- }//end pre-proc instruction
+ context.State = IfState.ElseIf;
+ if(!context.EverKept)
+ {
+ context.Keep = ParseExpression(reader.Value);
+ }
+ else
+ {
+ context.Keep = false;
+ }
- if(!context.Active || !context.Keep)
- {
- continue;
- }
+ ignore = true;
+ break;
- switch(reader.NodeType)
- {
- case XmlNodeType.Element:
- bool empty = reader.IsEmptyElement;
- writer.WriteStartElement(reader.Name);
+ 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'");
+ }
- while (reader.MoveToNextAttribute())
- {
- writer.WriteAttributeString(reader.Name, reader.Value);
+ 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(empty)
+ if(ignore)
{
- writer.WriteEndElement();
+ continue;
}
-
- break;
+ }//end pre-proc instruction
- case XmlNodeType.EndElement:
- writer.WriteEndElement();
- break;
+ if(!context.Active || !context.Keep)
+ {
+ continue;
+ }
- case XmlNodeType.Text:
- writer.WriteString(reader.Value);
- break;
+ switch(reader.NodeType)
+ {
+ case XmlNodeType.Element:
+ bool empty = reader.IsEmptyElement;
+ writer.WriteStartElement(reader.Name);
+
+ while (reader.MoveToNextAttribute())
+ {
+ writer.WriteAttributeString(reader.Name, reader.Value);
+ }
- case XmlNodeType.CDATA:
- writer.WriteCData(reader.Value);
- break;
+ if(empty)
+ {
+ writer.WriteEndElement();
+ }
+
+ break;
- default:
- 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");
+ if(m_IfStack.Count != 0)
+ {
+ throw new WarningException("Mismatched 'if', 'endif' pair");
+ }
}
-
+
return xmlText.ToString();
}
--
cgit v1.1