Fix for Bugzilla entries
	6833
	7023
	7123
	7410

Basic summary of logic error: It is possible for multiple RTF DTMs
to be pushed onto the stack between the start of a template and
return from it. I hadn't anticipated that, so my pop logic was
inadequate.

I'm still not 110% sure I understand the case where this situation
arises... I have a general intuition that it makes sense, but also a
suspicion that there might be a way to avoid creating one of these
DTMs. We should review that someday.

Meanwhile, this fixes a whole batch of related bugs.


git-svn-id: https://svn.apache.org/repos/asf/xalan/java/trunk@336321 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/org/apache/xpath/XPathContext.java b/src/org/apache/xpath/XPathContext.java
index ffe4fdb..d6070e3 100644
--- a/src/org/apache/xpath/XPathContext.java
+++ b/src/org/apache/xpath/XPathContext.java
@@ -110,6 +110,7 @@
 import org.apache.xml.utils.SAXSourceLocator;
 import org.apache.xml.utils.XMLString;
 import org.apache.xml.utils.XMLStringFactory;
+import org.apache.xml.utils.IntStack;
 
 import org.apache.xpath.axes.DescendantIterator;
 
@@ -124,6 +125,7 @@
  */
 public class XPathContext extends DTMManager // implements ExpressionContext
 {
+	IntStack m_last_pushed_rtfdtm=new IntStack();	
   /**
    * Stack of cached "reusable" DTMs for Result Tree Fragments.
    * This is a kluge to handle the problem of starting an RTF before
@@ -1270,6 +1272,10 @@
     m_rtfdtm_stack.addElement(rtfdtm);
 		++m_which_rtfdtm;
 	}
+	else if(m_which_rtfdtm<0)
+	{
+		rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(++m_which_rtfdtm);
+	}
 	else
 	{
 		rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(m_which_rtfdtm);
@@ -1277,8 +1283,9 @@
 	  	// It might already be under construction -- the classic example would be
  	 	// an xsl:variable which uses xsl:call-template as part of its value. To
   		// handle this recursion, we have to start a new RTF DTM, pushing the old
-  		// one onto a stack so we can return to it. It is hoped that
-	  	// this is an uncommon case!
+  		// one onto a stack so we can return to it. This is not as uncommon a case
+  		// as we might wish, unfortunately, as some folks insist on coding XSLT
+  		// as if it were a procedural language...
   		if(rtfdtm.isTreeIncomplete())
 	  	{
 	  		if(++m_which_rtfdtm < m_rtfdtm_stack.size())
@@ -1290,6 +1297,7 @@
 	  		}
  	 	}
 	}
+		
     return rtfdtm;
   }
   
@@ -1299,6 +1307,7 @@
    * */
   public void pushRTFContext()
   {
+  	m_last_pushed_rtfdtm.push(m_which_rtfdtm);
   	if(null!=m_rtfdtm_stack)
 	  	((SAX2RTFDTM)(getRTFDTM())).pushRewindMark();
   }
@@ -1321,11 +1330,22 @@
   {
   	if(null==m_rtfdtm_stack)
   		return;
-  		
-	boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.elementAt(m_which_rtfdtm))).popRewindMark();
-	if(isEmpty && m_which_rtfdtm>0)
-	{
-		--m_which_rtfdtm;
-	}
+  
+  	int previous=m_last_pushed_rtfdtm.pop();
+  	if(m_which_rtfdtm==previous)
+  	{
+  		if(previous>=0) // guard against none-active
+  		{
+	  		boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.elementAt(previous))).popRewindMark();
+  		}
+  	}
+  	else while(m_which_rtfdtm!=previous)
+  	{
+  		// Empty each DTM before popping, so it's ready for reuse
+  		// _DON'T_ pop the previous, since it's still open (which is why we
+  		// stacked up more of these) and did not receive a mark.
+  		boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.elementAt(m_which_rtfdtm))).popRewindMark();
+  		--m_which_rtfdtm; 
+  	}
   }
 }