dbertoni    00/07/21 12:46:11

  Added:       c/src/XSLT TopLevelArg.cpp TopLevelArg.hpp
                        VariablesStack.cpp VariablesStack.hpp
  Log:
  Initial revision.
  
  Revision  Changes    Path
  1.1                  xml-xalan/c/src/XSLT/TopLevelArg.cpp
  
  Index: TopLevelArg.cpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xalan" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * $ Id: $
   *
   */
  
  #include "TopLevelArg.hpp"
  
  
  
  TopLevelArg::TopLevelArg(
                const QName&                    name,
                const XalanDOMString&   expr) :
        m_qname(name),
        m_expression(expr),
        m_xobject(0)
  {
  }
  
  
  
  TopLevelArg::TopLevelArg(
                const QName&    name,
                XObject*                variable) :
        m_qname(name),
        m_expression(),
        m_xobject(variable)
  {
  }
  
  
  
  TopLevelArg::TopLevelArg(const TopLevelArg&           theSource) :
        m_qname(theSource.m_qname),
        m_expression(theSource.m_expression),
        m_xobject(theSource.m_xobject)
  {
  }
  
  
  
  TopLevelArg::~TopLevelArg()
  {
  }
  
  
  
  1.1                  xml-xalan/c/src/XSLT/TopLevelArg.hpp
  
  Index: TopLevelArg.hpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xalan" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * $ Id: $
   *
   */
  
  #if !defined(XALAN_TOPLEVELARG_HEADER_GUARD)
  #define XALAN_TOPLEVELARG_HEADER_GUARD
  
  
  
  
  // Base include file.  Must be first.
  #include <XSLT/XSLTDefinitions.hpp>
  
  
  
  #include <XalanDOM/XalanDOMString.hpp>
  
  
  
  #include <XPath/QName.hpp>
  
  
  
  class XObject;
  
  
  
  /**
   * This class holds an instance of an argument on the stack.
   */
  class TopLevelArg
  {
  public:
  
        /**
         * Construct an argument object from a string expression
         * 
         * @param name  name of argument
         * @param expr  expression argument represents
         */
        TopLevelArg(
                const QName&                    name,
                const XalanDOMString&   expr);
  
        /**
         * Construct an argument object from an XObject instance.
         * 
         * @param name  name of argument
         * @param variable      the XObject instance.
         */
        TopLevelArg(
                const QName&    name,
                XObject*                variable);
  
        /**
         * Copy constructor
         * 
         * @param theSource     the TopLevelArg to copy.
         */
        TopLevelArg(const TopLevelArg&  theSource);
  
        /**
         * Destructor
         */
        ~TopLevelArg();
  
        /**
         * Retrieve object name
         * 
         * @return qualified name of object
         */
        const QName&
        getName() const
        {
                return m_qname;
        }
  
        /**
         * Retrieve object's expression
         * 
         * @return string representation of expression
         */
        const XalanDOMString&
        getExpression() const
        {
                return m_expression;
        };
  
        /**
         * Retrieve object's XObject variable.
         * 
         * @return pointer to the XObject instance
         */
        XObject*
        getXObject() const
        {
                return m_xobject;
        }
  
        /**
         * Assignment operator
         */
        TopLevelArg&
        operator=(const TopLevelArg&    theRHS)
        {
                if (&theRHS != this)
                {
                        m_qname = theRHS.m_qname;
  
                        m_expression = theRHS.m_expression;
                }
  
                return *this;
        }
  
  private:
  
        QName                                                   m_qname;
  
        XalanDOMString                                  m_expression;
  
        XObject*                                                m_xobject;
  };
  
  
  
  #endif        // XALAN_TOPLEVELARG_HEADER_GUARD
  
  
  
  1.1                  xml-xalan/c/src/XSLT/VariablesStack.cpp
  
  Index: VariablesStack.cpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xalan" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  
  
  // Class header file.
  #include "VariablesStack.hpp"
  
  
  
  #include <algorithm>
  
  
  
  VariablesStack::VariablesStack() :
        m_stack(),
        m_globalStackFrameIndex(-1),
        m_currentStackFrameIndex(0)
  {
        m_stack.reserve(eDefaultStackSize);
  }
  
  
  
  VariablesStack::~VariablesStack()
  {
  }
  
  
  
  void
  VariablesStack::reset()
  {
        while(m_stack.size() > 0)
        {
                pop();
        }
  
        m_stack.clear();
  }
  
  
  
  bool
  VariablesStack::elementFrameAlreadyPushed(const ElemTemplateElement*  elem) 
const
  {
        const unsigned int      nElems = m_stack.size();
  
        // There is guaranteed to be a context marker at
        // the bottom of the stack, so i should stop at
        // 1.
        for(unsigned int i = nElems - 1; i > 0; --i)
        {
                const StackEntry&       theEntry = m_stack[i];
  
                if(theEntry.getType() == StackEntry::eElementFrameMarker)
                {
                        if(theEntry.getElement() == elem)
                        {
                                return true;
                        }
                }
        }
  
        return false;
  }
  
  
  
  void
  VariablesStack::pushContextMarker()
  {
        push(StackEntry());
  }
  
  
  
  void
  VariablesStack::popContextMarker()
  {
        const unsigned int      nElems = m_stack.size();
  
        for(unsigned int i = (nElems - 1); i > 0 && m_stack.empty() == false; 
--i)
        {
                const StackEntry&       theEntry = m_stack[i];
                assert(theEntry == back());
  
                const StackEntry::eStackEntryType       type = 
theEntry.getType();
                assert(type < StackEntry::eNextValue && type >= 0);
  
                pop();
  
                if (type == StackEntry::eContextMarker)
                {
                        break;
                }
        }
  }
  
  
  
  class PopPushStackEntry
  {
  public:
  
        PopPushStackEntry(VariablesStack&       theVariablesStack) :
                m_variablesStack(theVariablesStack),
                m_stackEntry(theVariablesStack.back())
        {
                assert(m_stackEntry.getType() == 
VariablesStack::StackEntry::eContextMarker);
  
                theVariablesStack.pop();
        }
  
        ~PopPushStackEntry()
        {
                m_variablesStack.push(m_stackEntry);
        }
  
  private:
  
        VariablesStack&                                         
m_variablesStack;
  
        const VariablesStack::StackEntry        m_stackEntry;
  };
  
  
  
  class CommitPushElementFrame
  {
  public:
  
        CommitPushElementFrame(
                        VariablesStack&                                         
                theVariableStack,
                        const ElemTemplateElement*                              
        targetTemplate) :
                m_variableStack(&theVariableStack),
                m_targetTemplate(targetTemplate)
        {
                theVariableStack.pushElementFrame(targetTemplate);
        }
  
        ~CommitPushElementFrame()
        {
                if (m_variableStack != 0)
                {
                        m_variableStack->popElementFrame(m_targetTemplate);
                }
        }
  
        void
        commit()
        {
                m_variableStack = 0;
        }
  
  private:
  
        VariablesStack*                                                         
m_variableStack;
  
        const ElemTemplateElement* const                        
m_targetTemplate;
  };
  
  
  
  void
  VariablesStack::push(const StackEntry&        theEntry)
  {
        assert(theEntry.getType() < StackEntry::eNextValue && 
theEntry.getType() >= 0);
  
        if(m_currentStackFrameIndex == m_stack.size())
        {
                ++m_currentStackFrameIndex;
        }
  
        m_stack.push_back(theEntry);
  }
  
  
  
  void
  VariablesStack::pop()
  {
        assert(m_stack.empty() == false);
  
        if(m_currentStackFrameIndex == m_stack.size())
        {
                --m_currentStackFrameIndex;
        }
  
        m_stack.pop_back();
  }
  
  
  
  class PushFunctor
  {
  public:
  
        PushFunctor(VariablesStack&             theVariablesStack) :
                m_variablesStack(theVariablesStack)
        {
        }
  
        const void
        operator()(const VariablesStack::VariableStackStackType::value_type&    
theEntry)
        {
                m_variablesStack.push(theEntry);
        }
  
  private:
  
        VariablesStack&                                         
m_variablesStack;
  };
  
  
  
  class PushParamFunctor
  {
  public:
  
        PushParamFunctor(VariablesStack&                theVariablesStack) :
                m_variablesStack(theVariablesStack)
        {
        }
  
        const void
        operator()(const VariablesStack::ParamsVectorType::value_type&  
theEntry)
        {
                
m_variablesStack.push(VariablesStack::StackEntry(theEntry.first, 
theEntry.second));
        }
  
  private:
  
        VariablesStack&                                         
m_variablesStack;
  };
  
  
  
  void
  VariablesStack::pushParams(
                        const ParamsVectorType&         theParams,
                        const ElemTemplateElement*      targetTemplate)
  {
        // This object will push an element marker, and pop it
        // if we don't call it's commit() member function.  So
        // if an exception is thrown while transferring the
        // parameters, the element marker will be popped.
        // This keeps the stack in a consistent state.
        // It will also delete things left in the temp stack
        // as well.
        CommitPushElementFrame          thePusher(*this,
                                                                                
  targetTemplate);
  
  #if !defined (XALAN_NO_NAMESPACES)
        using std::for_each;
  #endif
  
        for_each(theParams.begin(), theParams.end(), PushParamFunctor(*this));
  
        thePusher.commit();
  }
  
  
  
  void
  VariablesStack::pushVariable(
                        const QName&                            name,
                        XObject*                                        val,
                        const ElemTemplateElement*      e)
  {
        if(elementFrameAlreadyPushed(e) == false)
        {
                pushElementFrame(e);
        }
  
        push(StackEntry(name, val));
  }
  
  
  
  void
  VariablesStack::start()
  {
  }
  
  
  
  void
  VariablesStack::markGlobalStackFrame()
  {
        m_globalStackFrameIndex = m_stack.size();
  
        pushContextMarker();
  }
  
  
  
  XObject*
  VariablesStack::findXObject(
                        const QName&    name,
                        bool                    fSearchGlobalSpace) const
  {
        XObject*                theXObject = 0;
  
        const StackEntry*       theVariable = findVariable(name, 
fSearchGlobalSpace);
  
        if (theVariable != 0)
        {
                assert(theVariable->getType() == StackEntry::eVariable);
  
                theXObject = theVariable->getVariable();
        }
  
        return theXObject;
  }
  
  
  
  const VariablesStack::StackEntry*
  VariablesStack::findVariable(
                        const QName&    qname,
                        bool                    fSearchGlobalSpace) const
  {
        const StackEntry*       theResult = 0;
  
        const unsigned int      nElems = getCurrentStackFrameIndex();
  
        // There is guaranteed to be a context marker at
        // the bottom of the stack, so i should stop at
        // 1.
        for(unsigned int i = nElems - 1; i > 0; --i)
        {
                const StackEntry&       theEntry =
                        m_stack[i];
  
                if(theEntry.getType() == StackEntry::eVariable)
                {
                        if(theEntry.getName().equals(qname))
                        {
                                theResult = &theEntry;
  
                                break;
                        }
                }
                else if(theEntry.getType() == StackEntry::eContextMarker)
                {
                        break;
                }
        }
  
        if(0 == theResult && true == fSearchGlobalSpace)
        {
                // Look in the global space
                for(unsigned int i = m_globalStackFrameIndex - 1; i > 0; i--)
                {
                        const StackEntry&       theEntry = m_stack[i];
  
                        if(theEntry.getType() == StackEntry::eVariable)
                        {
                                if(theEntry.getName().equals(qname))
                                {
                                        theResult = &theEntry;
  
                                        break;
                                }
                        }
                        else if(theEntry.getType() == 
StackEntry::eContextMarker)
                        {
                                break;
                        }
                }
        }
  
        return theResult;
  }
  
  
  
  void
  VariablesStack::pushElementFrame(const ElemTemplateElement*   elem)
  {
        push(StackEntry(elem));
  }
  
  
  
  class EnsurePop
  {
  public:
  
        EnsurePop(VariablesStack&       theVariablesStack) :
                m_variablesStack(theVariablesStack)
        {
        }
  
        ~EnsurePop()
        {
                m_variablesStack.pop();
        }
  
  private:
  
        VariablesStack&         m_variablesStack;
  };
  
  
  
  void
  VariablesStack::popElementFrame(const ElemTemplateElement*    elem)
  {
        const unsigned int      nElems = getCurrentStackFrameIndex();
  
        // Sub 1 extra for the context marker.
        for(unsigned int i = nElems - 1; i > 0; --i)
        {
                const StackEntry&       theEntry = m_stack[i];
  
                // Guarantee that it will be popped when we're done.
                EnsurePop       theEnsurePop(*this);
  
                if(theEntry.getType() == StackEntry::eContextMarker)
                {
                        throw InvalidStackContextException();
                }
                else if (theEntry.getType() == StackEntry::eElementFrameMarker)
                {
                        const ElemTemplateElement* const        theElement =
                                theEntry.getElement();
  
                        if (theElement != elem)
                        {
                                throw InvalidStackContextException();
                        }
  
                        break;
                }
      }
  }
  
  
  
  VariablesStack::StackEntry::StackEntry() :
        m_type(eContextMarker),
        m_qname(),
        m_variable(0)
  {
  }
  
  
  
  VariablesStack::StackEntry::StackEntry(
                const QName&    name,
                XObject*                val) :
        m_type(eVariable),
        m_qname(name),
        m_variable(val)
  {
  }
  
  
  
  VariablesStack::StackEntry::StackEntry(const ElemTemplateElement*             
elem) :
        m_type(eElementFrameMarker),
        m_qname(),
        m_element(elem)
  {
  }
  
  
  
  VariablesStack::StackEntry::StackEntry(const StackEntry&      theSource) :
        m_type(theSource.m_type),
        m_qname(theSource.m_qname),
        m_variable(0)
  {
        if (theSource.m_type == eVariable)
        {
                m_variable = theSource.m_variable;
        }
        else if (theSource.m_type == eElementFrameMarker)
        {
                m_element = theSource.m_element;
        }
        else
        {
                m_variable = 0;
        }
  }
  
  
  
  VariablesStack::StackEntry::~StackEntry()
  {
  }
  
  
  
  VariablesStack::StackEntry&
  VariablesStack::StackEntry::operator=(const StackEntry&               theRHS)
  {
        if (&theRHS != this)
        {
                m_type = theRHS.m_type;
                m_qname = theRHS.m_qname;
  
                if (m_type == eVariable)
                {
                        m_variable = theRHS.m_variable;
                }
                else if (m_type == eElementFrameMarker)
                {
                        m_element = theRHS.m_element;
                }
                else
                {
                        m_variable = 0;
                }
        }
  
        return *this;
  }
  
  
  
  bool
  VariablesStack::StackEntry::operator==(const StackEntry&      theRHS) const
  {
        bool    fResult = false;
  
        if (m_type == theRHS.m_type)
        {
                if (m_type == eContextMarker)
                {
                        if (&theRHS == this)
                        {
                                fResult = true;
                        }
                }
                else if (m_type == eVariable)
                {
                        if (m_qname == theRHS.m_qname &&
                                m_variable == theRHS.m_variable)
                        {
                                fResult = true;
                        }
                }
                else if (m_type == eElementFrameMarker)
                {
                        if (m_element == theRHS.m_element)
                        {
                                fResult = true;
                        }
                }
                else
                {
                        assert(0);
                }
        }
  
        return fResult;
  }
  
  
  
  VariablesStack::InvalidStackContextException::InvalidStackContextException() :
        XSLTProcessorException(XALAN_STATIC_UCODE_STRING("Invalid stack 
context"),
                                                   
XALAN_STATIC_UCODE_STRING("InvalidStackContextException"))
  {
  }
  
  
  
  VariablesStack::InvalidStackContextException::~InvalidStackContextException()
  {
  }
  
  
  
  1.1                  xml-xalan/c/src/XSLT/VariablesStack.hpp
  
  Index: VariablesStack.hpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *      notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *      notice, this list of conditions and the following disclaimer in
   *      the documentation and/or other materials provided with the
   *      distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *      if any, must include the following acknowledgment:  
   *             "This product includes software developed by the
   *              Apache Software Foundation (http://www.apache.org/)."
   *      Alternately, this acknowledgment may appear in the software itself,
   *      if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xalan" and "Apache Software Foundation" must
   *      not be used to endorse or promote products derived from this
   *      software without prior written permission. For written 
   *      permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache",
   *      nor may "Apache" appear in their name, without prior written
   *      permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.        IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  #if !defined(XALAN_VARIABLESSTACK_HEADER_GUARD)
  #define XALAN_VARIABLESSTACK_HEADER_GUARD
  
  
  
  // Base include file.  Must be first.
  #include <XSLT/XSLTDefinitions.hpp>
  
  
  
  #include <cassert>
  #include <vector>
  
  
  
  #include <XPath/QName.hpp>
  
  
  
  #include <XSLT/XSLTProcessorException.hpp>
  
  
  
  class Arg;
  class ElemTemplateElement;
  class StylesheetExecutionContext;
  class XObject;
  class XalanNode;
  
  
  
  /**
   * Defines a class to keep track of a stack for macro arguments.
   */
  class XALAN_XSLT_EXPORT VariablesStack
  {
  public:
  
        /**
         * Constructor for a variable stack.
         */
        explicit
        VariablesStack();
  
        ~VariablesStack();
  
        
        /**
         * Reset the stack.
         */
        void
        reset();
  
        /**
         * Push a frame marker for an element.
         *
         * @param elem the element
         */
        void
        pushElementFrame(const ElemTemplateElement*             elem);
  
        /**
         * Pop a frame marker for an element.
         *
         * @param elem the element
         */
        void
        popElementFrame(const ElemTemplateElement*      elem);
  
        /**
         * Push a context marker onto the stack to let us know when to stop
         * searching for a var.
         *
         * @param caller         caller node
         * @param sourceNode source node
         */
        void
        pushContextMarker();
  
        /**
         * Pop the current context from the current context stack.
         */
        void
        popContextMarker();
  
  #if defined(XALAN_NO_NAMESPACES)
        typedef vector<pair<QName, XObject*> >                          
ParamsVectorType;
  #else
        typedef std::vector<std::pair<QName, XObject*> >        
ParamsVectorType;
  #endif
  
        /**
         * Push the provided objects as parameters.  You must call
         * popContextMarker() when you are done with the arguments.
         *
         * @param theParam The vector containing the parameters.
         * @param targetTemplate target template for the parameters
         */
        void
        pushParams(
                        const ParamsVectorType&         theParams,
                        const ElemTemplateElement*      targetTemplate);
  
        /**
         * Given a name, return a string representing the value, but don't look
         * in the global space.
         *
         * @param theName name of variable
         * @return pointer to XObject for variable
         */
        XObject*
        getParamVariable(const QName& qname) const
        {
                return findXObject(qname, false);
        }
  
        /**
         * Given a name, find the corresponding XObject.
         *
         * @param qname name of variable
         * @return pointer to the corresponding XObject
         */
        XObject*
        getVariable(const QName&        name) const
        {
                return findXObject(name, true);
        }
  
        /**
         * Push a named variable onto the processor variable stack. Don't forget
         * to call startContext before pushing a series of arguments for a given
         * macro call.
         *
         * @param name    name of variable
         * @param val     pointer to XObject value
         * @param e       element marker for variable
         */
        void
        pushVariable(
                        const QName&                            name,
                        XObject*                                        val,
                        const ElemTemplateElement*      e);
  
        /**
         * Mark the top of the stack.
         */
        void
        start();
  
        /**
         * Mark the top of the global stack frame.
         */
        void
        markGlobalStackFrame();
  
        /**
         * Set the top of the stack frame from where a search for a variable or
         * param should take place.  Calling with no parameter will cause the
         * index to be set to the size of the stack.
         *
         * @param currentStackFrameIndex new value of index
         */
        void
        setCurrentStackFrameIndex(int   currentStackFrameIndex = -1)
        {
                if (currentStackFrameIndex == -1)
                        m_currentStackFrameIndex = m_stack.size();
                else
                        m_currentStackFrameIndex = currentStackFrameIndex;
        }
  
        /**
         * Get the top of the stack frame from where a search 
         * for a variable or param should take place.
         *
         * @return current value of index
         */
        int
        getCurrentStackFrameIndex() const
        {
                return m_currentStackFrameIndex;
        }
  
        class InvalidStackContextException : public XSLTProcessorException
        {
        public:
  
                InvalidStackContextException();
  
                virtual
                ~InvalidStackContextException();
  
        private:
  
        };
  
  private:
  
        class StackEntry;
  
        /**
         * Check to see if an element frame for the particular element has 
already
         * been pushed.
         * 
         * @param elem element in question
         * @return true if it has been pushed already
         */
        bool
        elementFrameAlreadyPushed(const ElemTemplateElement*    elem) const;
  
        /**
         * Push an entry onto the stack.
         *
         * @param stack entry to push
         */
        void
        push(const StackEntry&  theEntry);
  
        /**
         * Pop an entry from the top of the stack.
         */
        void
        pop();
  
        /**
         * Get a reference to the entry at the back (top) of the stack.
         *
         * @return a reference to the back of the stack.
         */
        const StackEntry&
        back() const
        {
                assert(m_stack.empty() == false);
  
                return m_stack.back();
        }
  
        friend class CommitPushElementFrame;
        friend class EnsurePop;
        friend class PopPushStackEntry;
        friend class PushFunctor;
        friend class PushParamFunctor;
  
        class StackEntry
        {
        public:
  
                /**
                 * Enumeration for types of stack entries, one of context 
state, context
                 * marker, element marker, or argument.
                 */
                enum eStackEntryType { eContextMarker,
                                                           eVariable,
                                                           eElementFrameMarker,
                                                           eNextValue };
  
                /**
                 * Construct a context marker.
                 */
                explicit
                StackEntry();
  
                /**
                 * Construct a variable.
                 */
                StackEntry(
                        const QName&    name,
                        XObject*                val);
  
                /**
                 * Construct an element frame marker.
                 */
                StackEntry(const ElemTemplateElement*   elem);
  
  
                /**
                 * Copy constructor...
                 */
                StackEntry(const StackEntry&    theSource);
  
                /**
                 * Destructor...
                 */
                ~StackEntry();
  
                /**
                 * Determine type of stack entry
                 * 
                 * @return enumeration value for type
                 */
                eStackEntryType
                getType() const
                {
                        return m_type;
                }
  
                /**
                 * Retrieve object name.  Valid only for variables
                 * 
                 * @return qualified name of object
                 */
                const QName&
                getName() const
                {
                        return m_qname;
                }
  
                /**
                 * Retrieve object's XObject pointer.  Valid only for variables
                 * 
                 * @return pointer to XObject
                 */
                XObject*
                getVariable() const
                {
                        return m_variable;
                }
  
                /**
                 * Retrieve the ElemTemplateElem where frame begins.  Valid 
only for element frame markers
                 *
                 * @return ElemTemplateElement corresponding to marker
                 */
                const ElemTemplateElement*
                getElement() const
                {
                        return m_element;
                }
  
                StackEntry&
                operator=(const StackEntry&             theRHS);
  
                bool
                operator==(const StackEntry&    theRHS) const;
  
        private:
  
                // Data members...
                eStackEntryType                         m_type;
  
                QName                                           m_qname;
  
                union
                {
                        XObject*                                        
m_variable;
  
                        const ElemTemplateElement*      m_element;
                };
        };
  
  #if defined(XALAN_NO_NAMESPACES)
        typedef vector<StackEntry>                      VariableStackStackType;
  #else
        typedef std::vector<StackEntry>         VariableStackStackType;
  #endif
  
        enum { eDefaultStackSize = 100 };
  
  
        XObject*
        findXObject(
                        const QName&    name,
                        bool                    fSearchGlobalSpace) const;
  
        const StackEntry*
        findVariable(
                        const QName&    name,
                        bool                    fSearchGlobalSpace) const;
  
  
        VariableStackStackType                  m_stack;
  
        int                                                             
m_globalStackFrameIndex;
  
        /**
         * This is the top of the stack frame from where a search 
         * for a variable or param should take place.  It may not 
         * be the real stack top.
         */
        unsigned int                                    
m_currentStackFrameIndex;       
  };
  
  
  
  #endif        // #if !defined(XALAN_VARIABLESSTACK_HEADER_GUARD)
  
  
  

Reply via email to