19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one
39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * or more contributor license agreements. See the NOTICE file
49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed with this work for additional information
59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * regarding copyright ownership. The ASF licenses this file
69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * to you under the Apache License, Version 2.0 (the  "License");
79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * you may not use this file except in compliance with the License.
89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * You may obtain a copy of the License at
99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *     http://www.apache.org/licenses/LICENSE-2.0
119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Unless required by applicable law or agreed to in writing, software
139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * See the License for the specific language governing permissions and
169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * limitations under the License.
179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/*
199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * $Id: VariableStack.java 524812 2007-04-02 15:52:03Z zongaro $
209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpackage org.apache.xpath;
229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport javax.xml.transform.TransformerException;
249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xalan.res.XSLMessages;
269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.objects.XObject;
279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport org.apache.xpath.res.XPATHErrorResources;
289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/**
309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Defines a class to keep track of a stack for
319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * template arguments and variables.
329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson *
339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <p>This has been changed from the previous incarnations of this
349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * class to be fairly low level.</p>
359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @xsl.usage internal
369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */
379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpublic class VariableStack implements Cloneable
389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson{
399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * limitation for 1K
419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public static final int CLEARLIMITATION= 1024;
439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Constructor for a variable stack.
469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public VariableStack()
489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    reset();
509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Constructor for a variable stack.
549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param initStackSize The initial stack size.  Must be at least one.  The
559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *                      stack can grow if needed.
569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public VariableStack(int initStackSize)
589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Allow for twice as many variables as stack link entries
609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    reset(initStackSize, initStackSize*2);
619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Returns a clone of this variable stack.
659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return  a clone of this variable stack.
679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws CloneNotSupportedException
699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public synchronized Object clone() throws CloneNotSupportedException
719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    VariableStack vs = (VariableStack) super.clone();
749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // I *think* I can get away with a shallow clone here?
769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    vs._stackFrames = (XObject[]) _stackFrames.clone();
779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    vs._links = (int[]) _links.clone();
789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return vs;
809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The stack frame where all variables and params will be kept.
849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @serial
859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  XObject[] _stackFrames;
879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The top of the stack frame (<code>_stackFrames</code>).
909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @serial
919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  int _frameTop;
939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The bottom index of the current frame (relative to <code>_stackFrames</code>).
969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @serial
979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private int _currentFrameBottom;
999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The stack of frame positions.  I call 'em links because of distant
1029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <a href="http://math.millikin.edu/mprogers/Courses/currentCourses/CS481-ComputerArchitecture/cs481.Motorola68000.html">
1039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Motorola 68000 assembler</a> memories.  :-)
1049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @serial
1059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  int[] _links;
1079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * The top of the links stack.
1109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  int _linksTop;
1129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get the element at the given index, regardless of stackframe.
1159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param i index from zero.
1179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The item at the given index.
1199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public XObject elementAt(final int i)
1219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return _stackFrames[i];
1239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get size of the stack.
1279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return the total size of the execution stack.
1299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public int size()
1319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return _frameTop;
1339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Reset the stack to a start position.
1379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void reset()
1399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // If the stack was previously allocated, assume that about the same
1419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // amount of stack space will be needed again; otherwise, use a very
1429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // large stack size.
1439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int linksSize = (_links == null) ? XPathContext.RECURSIONLIMIT
1449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                     : _links.length;
1459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    int varArraySize = (_stackFrames == null) ? XPathContext.RECURSIONLIMIT * 2
1469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                                              : _stackFrames.length;
1479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    reset(linksSize, varArraySize);
1489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Reset the stack to a start position.
1529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param linksSize Initial stack size to use
1539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param varArraySize Initial variable array size to use
1549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  protected void reset(int linksSize, int varArraySize) {
1569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _frameTop = 0;
1579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _linksTop = 0;
1589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Don't bother reallocating _links array if it exists already
1609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (_links == null) {
1619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      _links = new int[linksSize];
1629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
1639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Adding one here to the stack of frame positions will allow us always
1659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // to look one under without having to check if we're at zero.
1669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // (As long as the caller doesn't screw up link/unlink.)
1679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _links[_linksTop++] = 0;
1689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Get a clean _stackFrames array and discard the old one.
1709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _stackFrames = new XObject[varArraySize];
1719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Set the current stack frame.
1759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param sf The new stack frame position.
1779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void setStackFrame(int sf)
1799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _currentFrameBottom = sf;
1819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get the position from where the search should start,
1859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * which is either the searchStart property, or the top
1869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * of the stack if that value is -1.
1879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The current stack frame position.
1899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
1909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public int getStackFrame()
1919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
1929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return _currentFrameBottom;
1939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
1949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
1959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
1969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Allocates memory (called a stackframe) on the stack; used to store
1979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * local variables and parameter arguments.
1989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
1999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <p>I use the link/unlink concept because of distant
2009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * <a href="http://math.millikin.edu/mprogers/Courses/currentCourses/CS481-ComputerArchitecture/cs481.Motorola68000.html">
2019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Motorola 68000 assembler</a> memories.</p>
2029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param size The size of the stack frame allocation.  This ammount should
2049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * normally be the maximum number of variables that you can have allocated
2059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * at one time in the new stack frame.
2069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The bottom of the stack frame, from where local variable addressing
2089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * should start from.
2099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public int link(final int size)
2119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _currentFrameBottom = _frameTop;
2149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _frameTop += size;
2159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (_frameTop >= _stackFrames.length)
2179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      XObject newsf[] = new XObject[_stackFrames.length + XPathContext.RECURSIONLIMIT + size];
2199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      System.arraycopy(_stackFrames, 0, newsf, 0, _stackFrames.length);
2219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      _stackFrames = newsf;
2239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (_linksTop + 1 >= _links.length)
2269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
2279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      int newlinks[] = new int[_links.length + (CLEARLIMITATION * 2)];
2289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      System.arraycopy(_links, 0, newlinks, 0, _links.length);
2309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      _links = newlinks;
2329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
2339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _links[_linksTop++] = _currentFrameBottom;
2359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return _currentFrameBottom;
2379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Free up the stack frame that was last allocated with
2419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * {@link #link(int size)}.
2429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public  void unlink()
2449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _frameTop = _links[--_linksTop];
2469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _currentFrameBottom = _links[_linksTop - 1];
2479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Free up the stack frame that was last allocated with
2519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * {@link #link(int size)}.
2529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param currentFrame The current frame to set to
2539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * after the unlink.
2549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public  void unlink(int currentFrame)
2569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _frameTop = _links[--_linksTop];
2589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _currentFrameBottom = currentFrame;
2599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Set a local variable or parameter in the current stack frame.
2639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param index Local variable index relative to the current stack
2669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * frame bottom.
2679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param val The value of the variable that is being set.
2699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void setLocalVariable(int index, XObject val)
2719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _stackFrames[index + _currentFrameBottom] = val;
2739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Set a local variable or parameter in the specified stack frame.
2779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param index Local variable index relative to the current stack
2809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * frame bottom.
2819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * NEEDSDOC @param stackFrame
2829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param val The value of the variable that is being set.
2849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
2859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void setLocalVariable(int index, XObject val, int stackFrame)
2869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
2879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _stackFrames[index + stackFrame] = val;
2889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
2899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
2909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
2919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get a local variable or parameter in the current stack frame.
2929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param xctxt The XPath context, which must be passed in order to
2959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * lazy evaluate variables.
2969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
2979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param index Local variable index relative to the current stack
2989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * frame bottom.
2999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The value of the variable.
3019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
3039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
3049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public XObject getLocalVariable(XPathContext xctxt, int index)
3059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws TransformerException
3069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
3079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    index += _currentFrameBottom;
3099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    XObject val = _stackFrames[index];
3119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(null == val)
3139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      throw new TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VARIABLE_ACCESSED_BEFORE_BIND, null),
3149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     xctxt.getSAXLocator());
3159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // "Variable accessed before it is bound!", xctxt.getSAXLocator());
3169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Lazy execution of variables.
3189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
3199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return (_stackFrames[index] = val.execute(xctxt));
3209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return val;
3229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
3239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
3259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get a local variable or parameter in the current stack frame.
3269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param index Local variable index relative to the given
3299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * frame bottom.
3309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * NEEDSDOC @param frame
3319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The value of the variable.
3339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
3359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
3369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public XObject getLocalVariable(int index, int frame)
3379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws TransformerException
3389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
3399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    index += frame;
3419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    XObject val = _stackFrames[index];
3439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return val;
3459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
3469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
3489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get a local variable or parameter in the current stack frame.
3499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param xctxt The XPath context, which must be passed in order to
3529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * lazy evaluate variables.
3539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param index Local variable index relative to the current stack
3559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * frame bottom.
3569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The value of the variable.
3589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
3609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
3619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public XObject getLocalVariable(XPathContext xctxt, int index, boolean destructiveOK)
3629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws TransformerException
3639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
3649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    index += _currentFrameBottom;
3669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    XObject val = _stackFrames[index];
3689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if(null == val)
3709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      throw new TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VARIABLE_ACCESSED_BEFORE_BIND, null),
3719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                     xctxt.getSAXLocator());
3729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      // "Variable accessed before it is bound!", xctxt.getSAXLocator());
3739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Lazy execution of variables.
3759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
3769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return (_stackFrames[index] = val.execute(xctxt));
3779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return destructiveOK ? val : val.getFresh();
3799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
3809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
3829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Tell if a local variable has been set or not.
3839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param index Local variable index relative to the current stack
3859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * frame bottom.
3869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return true if the value at the index is not null.
3889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
3899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
3909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
3919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public boolean isLocalSet(int index) throws TransformerException
3929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
3939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return (_stackFrames[index + _currentFrameBottom] != null);
3949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
3959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /** NEEDSDOC Field m_nulls          */
3979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  private static XObject[] m_nulls = new XObject[CLEARLIMITATION];
3989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
3999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
4009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Use this to clear the variables in a section of the stack.  This is
4019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * used to clear the parameter section of the stack, so that default param
4029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * values can tell if they've already been set.  It is important to note that
4039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * this function has a 1K limitation.
4049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param start The start position, relative to the current local stack frame.
4069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param len The number of slots to be cleared.
4079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
4089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void clearLocalSlots(int start, int len)
4099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
4109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    start += _currentFrameBottom;
4129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    System.arraycopy(m_nulls, 0, _stackFrames, start, len);
4149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
4159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
4179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Set a global variable or parameter in the global stack frame.
4189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param index Local variable index relative to the global stack frame
4219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * bottom.
4229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param val The value of the variable that is being set.
4249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
4259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public void setGlobalVariable(final int index, final XObject val)
4269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
4279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    _stackFrames[index] = val;
4289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
4299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
4319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get a global variable or parameter from the global stack frame.
4329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param xctxt The XPath context, which must be passed in order to
4359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * lazy evaluate variables.
4369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param index Global variable index relative to the global stack
4389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * frame bottom.
4399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The value of the variable.
4419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
4439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
4449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public XObject getGlobalVariable(XPathContext xctxt, final int index)
4459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws TransformerException
4469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
4479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    XObject val = _stackFrames[index];
4499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Lazy execution of variables.
4519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
4529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return (_stackFrames[index] = val.execute(xctxt));
4539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return val;
4559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
4569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
4589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get a global variable or parameter from the global stack frame.
4599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param xctxt The XPath context, which must be passed in order to
4629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * lazy evaluate variables.
4639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param index Global variable index relative to the global stack
4659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * frame bottom.
4669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The value of the variable.
4689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws TransformerException
4709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
4719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public XObject getGlobalVariable(XPathContext xctxt, final int index, boolean destructiveOK)
4729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          throws TransformerException
4739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
4749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    XObject val = _stackFrames[index];
4769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Lazy execution of variables.
4789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (val.getType() == XObject.CLASS_UNRESOLVEDVARIABLE)
4799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      return (_stackFrames[index] = val.execute(xctxt));
4809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    return destructiveOK ? val : val.getFresh();
4829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
4839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
4849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  /**
4859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * Get a variable based on it's qualified name.
4869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * This is for external use only.
4879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param xctxt The XPath context, which must be passed in order to
4899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * lazy evaluate variables.
4909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @param qname The qualified name of the variable.
4929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @return The evaluated value of the variable.
4949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   *
4959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   * @throws javax.xml.transform.TransformerException
4969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson   */
4979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  public XObject getVariableOrParam(
4989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          XPathContext xctxt, org.apache.xml.utils.QName qname)
4999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            throws javax.xml.transform.TransformerException
5009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  {
5019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    org.apache.xml.utils.PrefixResolver prefixResolver =
5039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      xctxt.getNamespaceContext();
5049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // Get the current ElemTemplateElement, which must be pushed in as the
5069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // prefix resolver, and then walk backwards in document order, searching
5079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // for an xsl:param element or xsl:variable element that matches our
5089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // qname.  If we reach the top level, use the StylesheetRoot's composed
5099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    // list of top level variables and parameters.
5109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    if (prefixResolver instanceof org.apache.xalan.templates.ElemTemplateElement)
5129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    {
5139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      org.apache.xalan.templates.ElemVariable vvar;
5159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      org.apache.xalan.templates.ElemTemplateElement prev =
5179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        (org.apache.xalan.templates.ElemTemplateElement) prefixResolver;
5189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (!(prev instanceof org.apache.xalan.templates.Stylesheet))
5209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      {
5219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        while ( !(prev.getParentNode() instanceof org.apache.xalan.templates.Stylesheet) )
5229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        {
5239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          org.apache.xalan.templates.ElemTemplateElement savedprev = prev;
5249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          while (null != (prev = prev.getPreviousSiblingElem()))
5269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          {
5279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            if (prev instanceof org.apache.xalan.templates.ElemVariable)
5289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            {
5299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              vvar = (org.apache.xalan.templates.ElemVariable) prev;
5309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson              if (vvar.getName().equals(qname))
5329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson                return getLocalVariable(xctxt, vvar.getIndex());
5339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson            }
5349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          }
5359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson          prev = savedprev.getParentElem();
5369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        }
5379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      }
5389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      vvar = prev.getStylesheetRoot().getVariableOrParamComposed(qname);
5409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson      if (null != vvar)
5419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson        return getGlobalVariable(xctxt, vvar.getIndex());
5429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    }
5439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
5449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson    throw new javax.xml.transform.TransformerException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_VAR_NOT_RESOLVABLE, new Object[]{qname.toString()})); //"Variable not resolvable: " + qname);
5459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson  }
5469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson}  // end VariableStack
5479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson
548