- /*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- package com.sun.org.apache.xpath.internal;
-
- import javax.xml.transform.TransformerException;
-
- import com.sun.org.apache.xalan.internal.res.XSLMessages;
- import com.sun.org.apache.xpath.internal.objects.XObject;
- import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
-
- /**
- * Defines a class to keep track of a stack for
- * template arguments and variables.
- *
- * <p>This has been changed from the previous incarnations of this
- * class to be fairly low level.</p>
- * @xsl.usage internal
- */
- public class VariableStack implements Cloneable
- {
- /**
- * limitation for 1K
- */
- public static final int CLEARLIMITATION= 1024;
-
- /**
- * Constructor for a variable stack.
- */
- public VariableStack()
- {
- reset();
- }
-
- /**
- * Returns a clone of this variable stack.
- *
- * @return a clone of this variable stack.
- *
- * @throws CloneNotSupportedException
- */
- public synchronized Object clone() throws CloneNotSupportedException
- {
-
- VariableStack vs = (VariableStack) super.clone();
-
- // I *think* I can get away with a shallow clone here?
- vs._stackFrames = (XObject[]) _stackFrames.clone();
- vs._links = (int[]) _links.clone();
-
- return vs;
- }
-
- /**
- * The stack frame where all variables and params will be kept.
- * @serial
- */
- XObject[] _stackFrames = new XObject[XPathContext.RECURSIONLIMIT * 2];
-
- /**
- * The top of the stack frame (<code>_stackFrames</code>).
- * @serial
- */
- int _frameTop;
-
- /**
- * The bottom index of the current frame (relative to <code>_stackFrames</code>).
- * @serial
- */
- private int _currentFrameBottom;
-
- /**
- * The stack of frame positions. I call 'em links because of distant
- * <a href="http://math.millikin.edu/mprogers/Courses/currentCourses/CS481-ComputerArchitecture/cs481.Motorola68000.html">
- * Motorola 68000 assembler</a> memories. :-)
- * @serial
- */
- int[] _links = new int[XPathContext.RECURSIONLIMIT];
-
- /**
- * The top of the links stack.
- */
- int _linksTop;
-
- /**
- * Get the element at the given index, regardless of stackframe.
- *
- * @param i index from zero.
- *
- * @return The item at the given index.
- */
- public XObject elementAt(final int i)
- {
- return _stackFrames[i];
- }
-
- /**
- * Get size of the stack.
- *
- * @return the total size of the execution stack.
- */
- public int size()
- {
- return _frameTop;
- }
-
- /**
- * Reset the stack to a start position.
- *
- * @return the total size of the execution stack.
- */
- public void reset()
- {
-
- _frameTop = 0;
- _linksTop = 0;
-
- // Adding one here to the stack of frame positions will allow us always
- // to look one under without having to check if we're at zero.
- // (As long as the caller doesn't screw up link/unlink.)
- _links[_linksTop++] = 0;
- _stackFrames = new XObject[_stackFrames.length];
- }
-
- /**
- * Set the current stack frame.
- *
- * @param sf The new stack frame position.
- */
- public void setStackFrame(int sf)
- {
- _currentFrameBottom = sf;
- }
-
- /**
- * Get the position from where the search should start,
- * which is either the searchStart property, or the top
- * of the stack if that value is -1.
- *
- * @return The current stack frame position.
- */
- public int getStackFrame()
- {
- return _currentFrameBottom;
- }
-
- /**
- * Allocates memory (called a stackframe) on the stack; used to store
- * local variables and parameter arguments.
- *
- * <p>I use the link/unlink concept because of distant
- * <a href="http://math.millikin.edu/mprogers/Courses/currentCourses/CS481-ComputerArchitecture/cs481.Motorola68000.html">
- * Motorola 68000 assembler</a> memories.</p>
- *
- * @param size The size of the stack frame allocation. This ammount should
- * normally be the maximum number of variables that you can have allocated
- * at one time in the new stack frame.
- *
- * @return The bottom of the stack frame, from where local variable addressing
- * should start from.
- */
- public int link(final int size)
- {
-
- _currentFrameBottom = _frameTop;
- _frameTop += size;
-
- if (_frameTop >= _stackFrames.length)
- {
- XObject newsf[] = new XObject[_stackFrames.length + XPathContext.RECURSIONLIMIT + size];
-
- System.arraycopy(_stackFrames, 0, newsf, 0, _stackFrames.length);
-
- _stackFrames = newsf;
- }
-
- if (_linksTop + 1 >= _links.length)
- {
- int newlinks[] = new int[_links.length + (CLEARLIMITATION * 2)];
-
- System.arraycopy(_links, 0, newlinks, 0, _links.length);
-
- _links = newlinks;
- }
-
- _links[_linksTop++] = _currentFrameBottom;
-
- return _currentFrameBottom;
- }
-
- /**
- * Free up the stack frame that was last allocated with
- * {@link link(int size)}.
- */
- public void unlink()
- {
- _frameTop = _links[--_linksTop];
- _currentFrameBottom = _links[_linksTop - 1];
- }
-
- /**
- * Free up the stack frame that was last allocated with
- * {@link link(int size)}.
- * @param currentFrame The current frame to set to
- * after the unlink.
- */
- public void unlink(int currentFrame)
- {
- _frameTop = _links[--_linksTop];
- _currentFrameBottom = currentFrame;
- }
-
- /**
- * Set a local variable or parameter in the current stack frame.
- *
- *
- * @param index Local variable index relative to the current stack
- * frame bottom.
- *
- * @param val The value of the variable that is being set.
- */
- public void setLocalVariable(int index, XObject val)
- {
- _stackFrames[index + _currentFrameBottom] = val;
- }
-
- /**
- * Set a local variable or parameter in the specified stack frame.
- *
- *
- * @param index Local variable index relative to the current stack
- * frame bottom.
- * NEEDSDOC @param stackFrame
- *
- * @param val The value of the variable that is being set.
- */
- public void setLocalVariable(int index, XObject val, int stackFrame)
- {
- _stackFrames[index + stackFrame] = val;
- }
-
- /**
- * Get a local variable or parameter in the current stack frame.
- *
- *
- * @param xctxt The XPath context, which must be passed in order to
- * lazy evaluate variables.
- *
- * @param index Local variable index relative to the current stack
- * frame bottom.
- *
- * @return The value of the variable.
- *
- * @throws TransformerException
- */
- public XObject getLocalVariable(XPathContext xctxt, int index)
- throws TransformerException
- {
-
- index += _currentFrameBottom;
-
- XObject val = _stackFrames[index];
-
- if(null == val)
- throw new TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VARIABLE_ACCESSED_BEFORE_BIND, null),
- xctxt.getSAXLocator());
- // "Variable accessed before it is bound!", xctxt.getSAXLocator());
-
- // Lazy execution of variables.
- if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
- return (_stackFrames[index] = val.execute(xctxt));
-
- return val;
- }
-
- /**
- * Get a local variable or parameter in the current stack frame.
- *
- *
- * @param index Local variable index relative to the given
- * frame bottom.
- * NEEDSDOC @param frame
- *
- * @return The value of the variable.
- *
- * @throws TransformerException
- */
- public XObject getLocalVariable(int index, int frame)
- throws TransformerException
- {
-
- index += frame;
-
- XObject val = _stackFrames[index];
-
- return val;
- }
-
- /**
- * Get a local variable or parameter in the current stack frame.
- *
- *
- * @param xctxt The XPath context, which must be passed in order to
- * lazy evaluate variables.
- *
- * @param index Local variable index relative to the current stack
- * frame bottom.
- *
- * @return The value of the variable.
- *
- * @throws TransformerException
- */
- public XObject getLocalVariable(XPathContext xctxt, int index, boolean destructiveOK)
- throws TransformerException
- {
-
- index += _currentFrameBottom;
-
- XObject val = _stackFrames[index];
-
- if(null == val)
- throw new TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VARIABLE_ACCESSED_BEFORE_BIND, null),
- xctxt.getSAXLocator());
- // "Variable accessed before it is bound!", xctxt.getSAXLocator());
-
- // Lazy execution of variables.
- if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
- return (_stackFrames[index] = val.execute(xctxt));
-
- return destructiveOK ? val : val.getFresh();
- }
-
- /**
- * Tell if a local variable has been set or not.
- *
- * @param index Local variable index relative to the current stack
- * frame bottom.
- *
- * @return true if the value at the index is not null.
- *
- * @throws TransformerException
- */
- public boolean isLocalSet(int index) throws TransformerException
- {
- return (_stackFrames[index + _currentFrameBottom] != null);
- }
-
- /** NEEDSDOC Field m_nulls */
- private static XObject[] m_nulls = new XObject[CLEARLIMITATION];
-
- /**
- * Use this to clear the variables in a section of the stack. This is
- * used to clear the parameter section of the stack, so that default param
- * values can tell if they've already been set. It is important to note that
- * this function has a 1K limitation.
- *
- * @param start The start position, relative to the current local stack frame.
- * @param len The number of slots to be cleared.
- */
- public void clearLocalSlots(int start, int len)
- {
-
- start += _currentFrameBottom;
-
- System.arraycopy(m_nulls, 0, _stackFrames, start, len);
- }
-
- /**
- * Set a global variable or parameter in the global stack frame.
- *
- *
- * @param index Local variable index relative to the global stack frame
- * bottom.
- *
- * @param val The value of the variable that is being set.
- */
- public void setGlobalVariable(final int index, final XObject val)
- {
- _stackFrames[index] = val;
- }
-
- /**
- * Get a global variable or parameter from the global stack frame.
- *
- *
- * @param xctxt The XPath context, which must be passed in order to
- * lazy evaluate variables.
- *
- * @param index Global variable index relative to the global stack
- * frame bottom.
- *
- * @return The value of the variable.
- *
- * @throws TransformerException
- */
- public XObject getGlobalVariable(XPathContext xctxt, final int index)
- throws TransformerException
- {
-
- XObject val = _stackFrames[index];
-
- // Lazy execution of variables.
- if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
- return (_stackFrames[index] = val.execute(xctxt));
-
- return val;
- }
-
- /**
- * Get a global variable or parameter from the global stack frame.
- *
- *
- * @param xctxt The XPath context, which must be passed in order to
- * lazy evaluate variables.
- *
- * @param index Global variable index relative to the global stack
- * frame bottom.
- *
- * @return The value of the variable.
- *
- * @throws TransformerException
- */
- public XObject getGlobalVariable(XPathContext xctxt, final int index, boolean destructiveOK)
- throws TransformerException
- {
-
- XObject val = _stackFrames[index];
-
- // Lazy execution of variables.
- if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
- return (_stackFrames[index] = val.execute(xctxt));
-
- return destructiveOK ? val : val.getFresh();
- }
-
- /**
- * Get a variable based on it's qualified name.
- * This is for external use only.
- *
- * @param xctxt The XPath context, which must be passed in order to
- * lazy evaluate variables.
- *
- * @param qname The qualified name of the variable.
- *
- * @return The evaluated value of the variable.
- *
- * @throws javax.xml.transform.TransformerException
- */
- public XObject getVariableOrParam(
- XPathContext xctxt, com.sun.org.apache.xml.internal.utils.QName qname)
- throws javax.xml.transform.TransformerException
- {
-
- // <<<<<<< TIGER SPECIFIC CHANGE >>>>>>>>>
- // As we are not supporting Xalan interpretive we are taking away the functionality
- // dependent on XSLT interpretive Transformer. Only way supported is to use XSLTC
- // and the execution path needed for supporting standard XPath API defined by
- // JAXP 1.3 . This method is overridden in XPath implementation to support
- // standard XPath functionality with xpath package of Xalan
-
- throw new javax.xml.transform.TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VAR_NOT_RESOLVABLE, new Object[]{qname.toString()})); //"Variable not resolvable: " + qname);
- }
- } // end VariableStack
-