فهرست منبع

2003-07-30 Ben Maurer <[email protected]>

	* ManagedXslTransform.cs: Hold reference to CompiledStyle, not the
	XslTransformProcessor. Will help with thread safty.
	* Compiler.cs, XslTemplate.cs, XslTransformProcessor.cs: Store
	variable values in the XslTransformProcessor.
	* XsltCompiledContext.cs: If the scope is null, don't look there!
	* Debug.cs: New method Assert
	* XslApplyTemplates.cs, XslCallTemplate.cs, XslCompiledElement.cs,
	XslTemplateContent.cs, XslVariable.cs:
	Store variable values in the XslTransformProcessor

svn path=/trunk/mcs/; revision=16917
Ben Maurer 22 سال پیش
والد
کامیت
4e6296d44c

+ 7 - 0
mcs/class/System.XML/Mono.Xml.Xsl.Operations/ChangeLog

@@ -1,3 +1,10 @@
+2003-07-30 Ben Maurer  <[email protected]>
+
+	* XslApplyTemplates.cs, XslCallTemplate.cs, XslCompiledElement.cs,
+	XslTemplateContent.cs, XslVariable.cs:
+	Store variable values in the XslTransformProcessor
+
+
 2003-07-30 Ben Maurer  <[email protected]>
 
 	* XslAvt.cs, XslCopyOf.cs, XslIf.cs, XslText.cs, XslValueOf.cs,

+ 10 - 8
mcs/class/System.XML/Mono.Xml.Xsl.Operations/XslApplyTemplates.cs

@@ -37,7 +37,7 @@ namespace Mono.Xml.Xsl.Operations {
 					switch (c.Input.LocalName)
 					{
 						case "with-param":
-							withParams.Add (new XslWithParam (c));
+							withParams.Add (new XslVariableInformation (c));
 							break;
 							
 						case "sort":
@@ -55,16 +55,18 @@ namespace Mono.Xml.Xsl.Operations {
 		
 		public override void Evaluate (XslTransformProcessor p)
 		{
-			foreach (XslWithParam param in withParams)
-				param.Evaluate (p);
+			Hashtable passedParams = null;
+			
+			if (withParams.Count > 0) {
+				passedParams = new Hashtable ();
+				foreach (XslVariableInformation param in withParams)
+					passedParams [param.Name] = param.Evaluate (p);
+			}
 			
 			if (select == null)	
-				p.ApplyTemplates (p.CurrentNode.SelectChildren (XPathNodeType.All), mode, withParams);
+				p.ApplyTemplates (p.CurrentNode.SelectChildren (XPathNodeType.All), mode, passedParams);
 			else
-				p.ApplyTemplates (p.Select (select), mode, withParams);
-						
-			foreach (XslWithParam param in withParams)
-				param.Clear ();
+				p.ApplyTemplates (p.Select (select), mode, passedParams);
 		}
 	}
 }

+ 8 - 6
mcs/class/System.XML/Mono.Xml.Xsl.Operations/XslCallTemplate.cs

@@ -34,7 +34,7 @@ namespace Mono.Xml.Xsl.Operations {
 					switch (c.Input.LocalName)
 					{
 						case "with-param":
-							withParams.Add (new XslWithParam (c));
+							withParams.Add (new XslVariableInformation (c));
 							break;
 						default:
 							throw new Exception ("unexptected element"); // todo forwards compat
@@ -46,13 +46,15 @@ namespace Mono.Xml.Xsl.Operations {
 		
 		public override void Evaluate (XslTransformProcessor p)
 		{
-			foreach (XslWithParam param in withParams)
-				param.Evaluate (p);
+			Hashtable passedParams = null;
 			
-			p.CallTemplate (name, withParams);
+			if (withParams.Count > 0) {
+				passedParams = new Hashtable ();
+				foreach (XslVariableInformation param in withParams)
+					passedParams [param.Name] = param.Evaluate (p);
+			}
 			
-			foreach (XslWithParam param in withParams)
-				param.Clear ();
+			p.CallTemplate (name, passedParams);
 		}
 	}
 }

+ 3 - 2
mcs/class/System.XML/Mono.Xml.Xsl.Operations/XslCompiledElement.cs

@@ -20,11 +20,12 @@ using QName = System.Xml.XmlQualifiedName;
 namespace Mono.Xml.Xsl.Operations {
 
 	public abstract class XslCompiledElement : XslOperation {
+		bool hasStack;
+		int stackSize;
+		
 		public XslCompiledElement (Compiler c)
 		{
-			c.PushScope ();
 			this.Compile (c);
-			c.PopScope ();
 		}
 		
 		protected abstract void Compile (Compiler c);

+ 18 - 7
mcs/class/System.XML/Mono.Xml.Xsl.Operations/XslTemplateContent.cs

@@ -20,9 +20,14 @@ namespace Mono.Xml.Xsl.Operations {
 		ArrayList content = new ArrayList ();
 		ArrayList variables;
 		
+		bool hasStack;
+		int stackSize;
+		
 		public XslTemplateContent (Compiler c) : base (c) {}
 		protected override void Compile (Compiler c)
 		{
+			hasStack = (c.CurrentVariableScope == null);
+			c.PushScope ();
 			do {	
 				Debug.EnterNavigator (c);
 				XPathNavigator n = c.Input;			
@@ -82,10 +87,7 @@ namespace Mono.Xml.Xsl.Operations {
 							content.Add (new XslValueOf(c));
 							break;
 						case "variable":
-							XslLocalVariable v = new XslLocalVariable (c);
-							if (variables == null) variables = new ArrayList ();
-							variables.Add (v);
-							content.Add (v);
+							content.Add (new XslLocalVariable (c));
 							break;
 						default:
 							// TODO: handle fallback, like we should
@@ -109,16 +111,25 @@ namespace Mono.Xml.Xsl.Operations {
 				Debug.ExitNavigator (c);
 				
 			} while (c.Input.MoveToNext ());
+			
+			
+			if (hasStack) {
+				stackSize = c.PopScope ().VariableHighTide;
+				hasStack = stackSize > 0;
+			} else 
+				c.PopScope ();
 		}
 		
 		public override void Evaluate (XslTransformProcessor p)
 		{
+			if (hasStack)
+				p.PushStack (stackSize);
+			
 			foreach (XslOperation op in content)
 				op.Evaluate (p);
 			
-			if (this.variables != null)
-				foreach (XslLocalVariable v in this.variables)
-					v.Clear ();
+			if (hasStack)
+				p.PopStack ();
 		}
 	}
 }

+ 88 - 104
mcs/class/System.XML/Mono.Xml.Xsl.Operations/XslVariable.cs

@@ -18,17 +18,14 @@ using System.Xml.Xsl;
 using QName = System.Xml.XmlQualifiedName;
 
 namespace Mono.Xml.Xsl.Operations {
-	public abstract class XslGeneralVariable : XslCompiledElement, IXsltContextVariable {
-		protected QName name;
-		protected XPathExpression select;
-		protected XslOperation content;
-		protected object value;
-		protected bool busy, evaluated;
-		
-		
-		public XslGeneralVariable (Compiler c) : base (c) {}
+	
+	public class XslVariableInformation
+	{
+		QName name;
+		XPathExpression select;
+		XslOperation content;
 		
-		protected override void Compile (Compiler c)
+		public XslVariableInformation (Compiler c)
 		{
 			c.AssertAttribute ("name");
 			name = c.ParseQNameAttribute ("name");
@@ -43,69 +40,82 @@ namespace Mono.Xml.Xsl.Operations {
 			}
 		}
 		
-		public override void Evaluate (XslTransformProcessor p) {
-			Evaluate (p, false);
-		}
-		
-		protected virtual void Evaluate (XslTransformProcessor p, bool isFromXPath)
+		public object Evaluate (XslTransformProcessor p)
 		{
-			if (!evaluated) {
-				if (busy) throw new Exception ("Circular dependency");
-				busy = true;
-				
-				if (select != null) {
-					value = p.Evaluate (select);
-				} else if (content != null) {
-					XmlNodeWriter w = new XmlNodeWriter ();
-					p.PushOutput (w);
-					content.Evaluate (p);
-					p.PopOutput ();
-					value = w.Document.CreateNavigator ().SelectChildren (XPathNodeType.All);
-				} else {
-					value = "";
-				}
-				
-				evaluated = true;
-				busy = false;
+			if (select != null) {
+				return p.Evaluate (select);
+			} else if (content != null) {
+				XmlNodeWriter w = new XmlNodeWriter ();
+				p.PushOutput (w);
+				content.Evaluate (p);
+				p.PopOutput ();
+				return w.Document.CreateNavigator ().SelectChildren (XPathNodeType.All);
+			} else {
+				return "";
 			}
-			
 		}
 		
-		public QName Name {get {return this.name;}}
+		public QName Name { get { return name; }}
+	}
+	
+	public abstract class XslGeneralVariable : XslCompiledElement, IXsltContextVariable {
+		protected XslVariableInformation var;	
 		
-		public XPathResultType VariableType { 
-			get {
-				if (value != null) return Functions.XPFuncImpl.GetXPathType (value.GetType ());
-				return XPathResultType.Any;
-			}
+		public XslGeneralVariable (Compiler c) : base (c) {}
+		
+		protected override void Compile (Compiler c)
+		{
+			this.var = new XslVariableInformation (c);
 		}
 		
+		public override abstract void Evaluate (XslTransformProcessor p);
+		protected abstract object GetValue (XslTransformProcessor p);
+		
+		
 		public object Evaluate (XsltContext xsltContext)
 		{
-			if (!evaluated)
-				Evaluate (((XsltCompiledContext)xsltContext).Processor, true);
+			XslTransformProcessor p = ((XsltCompiledContext)xsltContext).Processor;
+			Evaluate (p);
+			
+			object value = GetValue (p);
 			
 			if (value is XPathNodeIterator)			
 				return ((XPathNodeIterator)value).Clone ();
 			
 			return value;
-			
-		}
-		
-				
-		public virtual void Clear ()
-		{
-			evaluated = false;
-			value = null;
 		}
-		
-		public bool Evaluated { get { return evaluated; }}
+
+		public QName Name {get {return  var.Name;}}
+		public XPathResultType VariableType { get {return XPathResultType.Any;}}
 		public abstract bool IsLocal { get; }
 		public abstract bool IsParam { get; }
 	}
 	
 	public class XslGlobalVariable : XslGeneralVariable {
 		public XslGlobalVariable (Compiler c) : base (c) {}
+		static object busyObject = new Object ();
+		
+			
+		public override void Evaluate (XslTransformProcessor p)
+		{
+			Hashtable varInfo = p.globalVariableTable;
+			
+			if (varInfo.Contains (this)) {
+				if (varInfo [this] == busyObject)
+					throw new Exception ("Circular Dependency");
+				return;
+			}
+			
+			varInfo [this] = busyObject;
+			varInfo [this] = var.Evaluate (p);
+			
+		}
+		
+		protected override object GetValue (XslTransformProcessor p)
+		{
+			return p.globalVariableTable [this];
+		}
+			
 		public override bool IsLocal { get { return false; }}
 		public override bool IsParam { get { return false; }}
 	}
@@ -116,49 +126,36 @@ namespace Mono.Xml.Xsl.Operations {
 		
 		public XslGlobalParam (Compiler c) : base (c) {}
 			
-		public void Override (object paramVal)
+		public void Override (XslTransformProcessor p, object paramVal)
 		{
-			if (evaluated)
-				throw new Exception ("why was i called again?");
-			evaluated = true;
+			Debug.Assert (!p.globalVariableTable.Contains (this), "Shouldn't have been evaluated by this point");
 			
-			this.value = paramVal;
+			p.globalVariableTable [this] = paramVal;
 		}
+		
 		public override bool IsParam { get { return true; }}
 	}
 	
 	public class XslLocalVariable : XslGeneralVariable {
-		protected Stack values;
-			
+		protected int slot;
+				
 		public XslLocalVariable (Compiler c) : base (c)
 		{
-			c.AddVariable (this);
+			slot = c.AddVariable (this);
 		}
-		public override bool IsLocal { get { return true; }}
-		public override bool IsParam { get { return false; }}
 		
-		protected override void Evaluate (XslTransformProcessor p, bool isFromXPath)
-		{
-			if (!evaluated && isFromXPath)
-				throw new Exception ("Variable used before decleration");
-			
-			if (evaluated && !isFromXPath) {
-				if (values == null)
-					values = new Stack ();
-				values.Push (value);
-			}
-			
-			base.Evaluate (p, isFromXPath);
+		public override void Evaluate (XslTransformProcessor p)
+		{	
+			p.SetStackItem (slot, var.Evaluate (p));
 		}
 		
-		public override void Clear ()
+		protected override object GetValue (XslTransformProcessor p)
 		{
-			base.Clear ();
-			if (values != null && values.Count != 0) {
-				value = values.Pop ();
-				evaluated = true;
-			}
+			return p.GetStackItem (slot);
 		}
+		
+		public override bool IsLocal { get { return true; }}
+		public override bool IsParam { get { return false; }}
 	}
 	
 	public class XslLocalParam : XslLocalVariable {
@@ -166,32 +163,19 @@ namespace Mono.Xml.Xsl.Operations {
 		object paramVal;
 		
 		public XslLocalParam (Compiler c) : base (c) {}
-			
-		public void Override (object paramVal)
-		{
-			if (evaluated) {
-				if (values == null)
-					values = new Stack ();
-				values.Push (value);
-			}
-			evaluated = true;
-			
-			this.value = paramVal;
+		
+		public override void Evaluate (XslTransformProcessor p)
+		{		
+			if (p.GetStackItem (slot) != null) return; // evaluated already
+				
+			base.Evaluate (p);
 		}
-		public override bool IsParam { get { return true; }}
-	}
-	
-	public class XslWithParam : XslGeneralVariable {
-		public XslWithParam (Compiler c) : base (c) {}
-		public override bool IsLocal { get { return false; }}
-		public override bool IsParam { get { return false; }}
 		
-		public object Value {
-			get {
-				if (!evaluated) throw new Exception ("why wasn't I evaluated");
-				if (value is XPathNodeIterator) return ((XPathNodeIterator)value).Clone ();
-				return value;
-			}
+		public void Override (XslTransformProcessor p, object paramVal)
+		{
+			p.SetStackItem (slot, paramVal);
 		}
+		
+		public override bool IsParam { get { return true; }}
 	}
 }

+ 7 - 0
mcs/class/System.XML/Mono.Xml.Xsl/ChangeLog

@@ -1,3 +1,10 @@
+2003-07-30 Ben Maurer  <[email protected]>
+
+	* Compiler.cs, XslTemplate.cs, XslTransformProcessor.cs: Store
+	variable values in the XslTransformProcessor.
+	* XsltCompiledContext.cs: If the scope is null, don't look there!
+	* Debug.cs: New method Assert
+
 2003-07-30 Ben Maurer  <[email protected]>
 
 	* Compiler.cs, XsltCompiledContext.cs: Remove verbose messages

+ 24 - 7
mcs/class/System.XML/Mono.Xml.Xsl/Compiler.cs

@@ -227,7 +227,6 @@ namespace Mono.Xml.Xsl {
 			return new XslTemplateContent (this);
 		}
 #endregion
-		
 
 		public void AddGlobalVariable (XslGlobalVariable var)
 		{
@@ -246,17 +245,20 @@ namespace Mono.Xml.Xsl {
 			curVarScope = new VariableScope (curVarScope);
 		}
 		
-		public void PopScope ()
+		public VariableScope PopScope ()
 		{
+			curVarScope.giveHighTideToParent ();
+			VariableScope cur = curVarScope;
 			curVarScope = curVarScope.Parent;
+			return cur;
 		}
 		
-		public void AddVariable (XslLocalVariable v)
+		public int AddVariable (XslLocalVariable v)
 		{
 			if (curVarScope == null)
 				throw new Exception ("not inited");
 			
-			curVarScope.AddVariable (v);
+			return curVarScope.AddVariable (v);
 		}
 		
 		public void AddSort (XPathExpression e, Sort s)
@@ -269,20 +271,33 @@ namespace Mono.Xml.Xsl {
 	public class VariableScope {
 		Hashtable variables;
 		VariableScope parent;
-			
+		int nextSlot = 0;
+		int highTide = 0; // this will be the size of the stack frame
+		
+		internal void giveHighTideToParent ()
+		{
+			if (parent != null)
+				parent.highTide = System.Math.Max (VariableHighTide, parent.VariableHighTide);
+		}
+
+		public int VariableHighTide { get { return  System.Math.Max (highTide, nextSlot); }}
+		
 		public VariableScope (VariableScope parent)
 		{
 			this.parent = parent;
+			if (parent != null)
+				this.nextSlot = parent.nextSlot;
 		}
 		
 		public VariableScope Parent { get { return parent; }}
 		
-		public void AddVariable (XslLocalVariable v)
+		public int AddVariable (XslLocalVariable v)
 		{
 			if (variables == null)
 				variables = new Hashtable ();
 			
 			variables [v.Name] = v;
+			return nextSlot++;
 		}
 		
 		public XslLocalVariable Resolve (QName name)
@@ -290,7 +305,9 @@ namespace Mono.Xml.Xsl {
 			for (VariableScope s = this; s != null; s = s.Parent)			
 				if (s.variables != null && s.variables.Contains (name)) {
 					XslLocalVariable v = (XslLocalVariable)s.variables [name];								
-					if (v.Evaluated) return v;
+					return v;
+					// TODO: replace this logic
+					//	if (v.Evaluated) return v;
 				}
 			
 			return null;

+ 18 - 4
mcs/class/System.XML/Mono.Xml.Xsl/Debug.cs

@@ -38,13 +38,28 @@ namespace Mono.Xml.Xsl {
 	
 			WriteLine(output);
 		}
-		
+
 		[System.Diagnostics.Conditional("DEBUG")]
-		internal static void WriteLine(string message) {
-			Console.Error.WriteLine(message);
+		internal static void Assert (bool condition, string message)
+		{
+			if (!condition)
+				throw new Exception (message);
+		}
+
+		[System.Diagnostics.Conditional("DEBUG")]
+		internal static void WriteLine (object value)
+		{
+			Console.Error.WriteLine (value);
+		}
+
+		[System.Diagnostics.Conditional("DEBUG")]
+		internal static void WriteLine (string message)
+		{
+			Console.Error.WriteLine (message);
 		}
 		
 		static Stack eleStack = new Stack ();
+		
 		[System.Diagnostics.Conditional("DEBUG")]
 		internal static void EnterNavigator (Compiler c)
 		{
@@ -59,6 +74,5 @@ namespace Mono.Xml.Xsl {
 				throw new Exception ("Position must be the same on enter/exit. Enter node: " + x.Name + " exit node " + c.Input.Name);
 			
 		}
-
 	}
 }

+ 22 - 17
mcs/class/System.XML/Mono.Xml.Xsl/XslTemplate.cs

@@ -147,6 +147,8 @@ namespace Mono.Xml.Xsl {
 		XslOperation content;
 
 		XslStylesheet style;
+		int stackSize;
+		
 		
 		public XslTemplate (Compiler c)
 		{
@@ -171,7 +173,7 @@ namespace Mono.Xml.Xsl {
 				Parse (c);
 			}
 			
-			c.PopScope ();
+			stackSize = c.PopScope ().VariableHighTide;
 			
 		}
 
@@ -228,26 +230,29 @@ namespace Mono.Xml.Xsl {
 			}
 		}
 		
-		public virtual void Evaluate (XslTransformProcessor p, ArrayList withParams)
+		public virtual void Evaluate (XslTransformProcessor p, Hashtable withParams)
 		{
+			p.PushStack (stackSize);
+
 			if (parameters != null) {
-				
-				if (withParams != null)
-					foreach (XslWithParam wp in withParams) {
-						if (parameters.Contains (wp.Name))
-							((XslLocalParam)parameters [wp.Name]).Override (wp.Value);
+				if (withParams == null) {
+					foreach (XslLocalParam param in parameters.Values)
+						param.Evaluate (p);
+				} else {
+					foreach (XslLocalParam param in parameters.Values)
+					{
+						if (withParams.Contains (param.Name))
+							param.Override (p, withParams [param.Name]);
+						else
+							param.Evaluate (p);
 					}
-				foreach (XslLocalParam param in parameters.Values)
-					param.Evaluate (p);
+				}
 			}
 			
 			if (content != null)
 				content.Evaluate (p);
-			
-			if (parameters != null) {
-				foreach (XslLocalParam param in parameters.Values)
-					param.Clear ();
-			}
+
+			p.PopStack ();
 		}
 		public void Evaluate (XslTransformProcessor p)
 		{
@@ -268,7 +273,7 @@ namespace Mono.Xml.Xsl {
 			get { return instance; }
 		}
 		
-		public override void Evaluate (XslTransformProcessor p, ArrayList withParams)
+		public override void Evaluate (XslTransformProcessor p, Hashtable withParams)
 		{
 			p.ApplyTemplates (p.CurrentNode.SelectChildren (XPathNodeType.All), mode, null);
 		}
@@ -283,7 +288,7 @@ namespace Mono.Xml.Xsl {
 			get { return instance; }
 		}
 		
-		public override void Evaluate (XslTransformProcessor p, ArrayList withParams)
+		public override void Evaluate (XslTransformProcessor p, Hashtable withParams)
 		{
 		}
 	}
@@ -297,7 +302,7 @@ namespace Mono.Xml.Xsl {
 			get { return instance; }
 		}
 		
-		public override void Evaluate (XslTransformProcessor p, ArrayList withParams)
+		public override void Evaluate (XslTransformProcessor p, Hashtable withParams)
 		{
 			p.Out.WriteString (p.CurrentNode.Value);
 		}

+ 60 - 17
mcs/class/System.XML/Mono.Xml.Xsl/XslTransformProcessor.cs

@@ -24,13 +24,14 @@ namespace Mono.Xml.Xsl {
 		
 		XslStylesheet style;
 		
-		Stack outputStack = new Stack ();
-		Stack nodesetStack = new Stack ();
 		Stack currentTemplateStack = new Stack ();
 		
 		XPathNavigator root;
 		XsltContext ctx;
 		XsltArgumentList args;
+
+		// Store the values of global params
+		internal Hashtable globalVariableTable = new Hashtable ();
 		
 		public XslTransformProcessor (CompiledStylesheet style)
 		{
@@ -44,7 +45,7 @@ namespace Mono.Xml.Xsl {
 				if (v is XslGlobalParam) {
 					object p = args.GetParam(v.Name.Name, v.Name.Namespace);
 					if (p != null)
-						((XslGlobalParam)v).Override (p);
+						((XslGlobalParam)v).Override (this, p);
 				}
 			}
 			
@@ -52,14 +53,15 @@ namespace Mono.Xml.Xsl {
 			this.root = root;
 			this.outputStack.Push (output);
 			this.ApplyTemplates (root.Select ("."), QName.Empty, null);
-			foreach (XslGlobalVariable v in CompiledStyle.Variables.Values)
-				v.Clear ();
 		}
 		
 		public XsltContext Context { get { return ctx; }}
 		public CompiledStylesheet CompiledStyle { get { return compiledStyle; }}
 		public XsltArgumentList Arguments {get{return args;}}
 		
+		#region Output
+		Stack outputStack = new Stack ();
+		
 		public XmlWriter Out { get { return (XmlWriter)outputStack.Peek(); }}
 		
 		public void PushOutput (XmlWriter newOutput)
@@ -71,8 +73,10 @@ namespace Mono.Xml.Xsl {
 		{
 			return (XmlWriter)this.outputStack.Pop ();
 		}
+		#endregion
 		
-		public void ApplyTemplates (XPathNodeIterator nodes, QName mode, ArrayList withParams)
+		#region Templates -- Apply/Call
+		public void ApplyTemplates (XPathNodeIterator nodes, QName mode, Hashtable withParams)
 		{
 			PushNodeset (nodes);
 			while (NodesetMoveNext ()) {
@@ -85,7 +89,7 @@ namespace Mono.Xml.Xsl {
 			PopNodeset ();
 		}
 		
-		public void CallTemplate (QName name, ArrayList withParams)
+		public void CallTemplate (QName name, Hashtable withParams)
 		{
 			XslTemplate t = FindTemplate (name);
 			currentTemplateStack.Push (null);
@@ -93,16 +97,6 @@ namespace Mono.Xml.Xsl {
 			currentTemplateStack.Pop ();
 		}
 		
-		public void PushForEachContext ()
-		{
-			currentTemplateStack.Push (null);
-		}
-		
-		public void PopForEachContext ()
-		{
-			currentTemplateStack.Pop ();
-		}
-		
 		public void ApplyImports ()
 		{	
 
@@ -187,7 +181,24 @@ namespace Mono.Xml.Xsl {
 				
 			throw new Exception ("Could not resolve named template " + name);
 		}
+		
+		#endregion
+		
+
+		public void PushForEachContext ()
+		{
+			currentTemplateStack.Push (null);
+		}
+		
+		public void PopForEachContext ()
+		{
+			currentTemplateStack.Pop ();
+		}
+		
 
+		#region Nodeset Context
+		Stack nodesetStack = new Stack ();
+		
 		public XPathNodeIterator CurrentNodeset {
 			get { return (XPathNodeIterator)nodesetStack.Peek (); }
 		}
@@ -210,7 +221,9 @@ namespace Mono.Xml.Xsl {
 		{
 			nodesetStack.Pop ();
 		}
+		#endregion
 		
+		#region Evaluate
 		public object Evaluate (XPathExpression expr)
 		{
 			expr = CompiledStyle.ExpressionStore.PrepForExecution (expr, this);
@@ -241,9 +254,39 @@ namespace Mono.Xml.Xsl {
 			return CurrentNodeset.Current.Select (expr);
 		}
 		
+		#endregion
+		
 		public XslAttributeSet ResolveAttributeSet (QName name)
 		{
 			return CompiledStyle.ResolveAttributeSet (name);
 		}
+		
+		#region Variable Stack
+		Stack variableStack = new Stack ();
+		object [] currentStack;
+		
+		public object GetStackItem (int slot)
+		{
+			return currentStack [slot];
+		}
+		
+		public void SetStackItem (int slot, object o)
+		{
+			currentStack [slot] = o;
+		}
+		
+		public void PushStack (int stackSize)
+		{
+			variableStack.Push (currentStack);
+			currentStack = new object [stackSize];
+		}
+		
+		public void PopStack ()
+		{
+			currentStack = (object[])variableStack.Pop();
+		}
+		
+		#endregion
+		
 	}
 }

+ 6 - 4
mcs/class/System.XML/Mono.Xml.Xsl/XsltCompiledContext.cs

@@ -140,10 +140,12 @@ namespace Mono.Xml.Xsl {
 
 		public override System.Xml.Xsl.IXsltContextVariable ResolveVariable(string prefix, string name)
 		{
-			XslGeneralVariable var = v.Resolve (new QName (name));
-
-			if (var != null)
-				return var;
+			if (v != null) {
+				XslGeneralVariable var = v.Resolve (new QName (name));
+	
+				if (var != null)
+					return var;
+			}
 			return p.CompiledStyle.ResolveVariable (new QName (name));
 		}
 

+ 5 - 0
mcs/class/System.XML/System.Xml.Xsl/ChangeLog

@@ -1,3 +1,8 @@
+2003-07-30 Ben Maurer  <[email protected]>
+
+	* ManagedXslTransform.cs: Hold reference to CompiledStyle, not the
+	XslTransformProcessor. Will help with thread safty.
+
 2003-07-30 Ben Maurer  <[email protected]>
 
 	* ManagedXslTransform.cs: remove verbose debugging messages

+ 4 - 4
mcs/class/System.XML/System.Xml.Xsl/ManagedXslTransform.cs

@@ -17,17 +17,17 @@ using Mono.Xml.Xsl;
 
 namespace System.Xml.Xsl {
 	internal class ManagedXslTransform : XslTransformImpl {
-		XslTransformProcessor p;
+		CompiledStylesheet s;
+		
 		
 		public override void Load (XPathNavigator stylesheet, XmlResolver resolver)
 		{
-			Compiler c = new Compiler ();
-			p = new XslTransformProcessor (c.Compile (stylesheet, resolver));
+			s = new Compiler ().Compile (stylesheet, resolver);
 		}
 
 		public override void Transform (XPathNavigator input, XsltArgumentList args, XmlWriter output, XmlResolver resolver)
 		{
-			p.Process (input, output, args); // todo use resolver
+			new XslTransformProcessor (s).Process (input, output, args); // todo use resolver
 		}
 	}
 }