text: /*
   * 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.
   */
  
  // Class header file.
  #include "XPath.hpp"
  
  
  
  #include <cassert>
  #include <cfloat>
  
  
  
  #include <xalanc/Include/STLHelper.hpp>
  
  
  
  #include <xalanc/XalanDOM/XalanNamedNodeMap.hpp>
  
  
  
  #include <xalanc/PlatformSupport/DoubleSupport.hpp>
  #include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
  #include <xalanc/PlatformSupport/PrefixResolver.hpp>
  
  
  
  #include <xalanc/DOMSupport/DOMServices.hpp>
  
  
  
  #include "FormatterStringLengthCounter.hpp"
  #include "MutableNodeRefList.hpp"
  #include "XalanQNameByReference.hpp"
  #include "XObject.hpp"
  #include "XObjectFactory.hpp"
  #include "XPathConstructionContext.hpp"
  #include "XPathEnvSupport.hpp"
  
  
  
  XALAN_CPP_NAMESPACE_BEGIN
  
  
  
  
  const XalanDOMString    XPath::s_emptyString(XalanMemMgrs::getDummyMemMgr());
  
  
  
  XPath::XPath(MemoryManagerType& theManager, const LocatorType*      theLocator) :
      m_expression(theManager),
      m_locator(theLocator),
      m_inStylesheet(false)
  {
  }
  
  XPath*
  XPath::create(MemoryManagerType& theManager, const LocatorType* theLocator)
  {
      typedef XPath Type;
  
      XalanMemMgrAutoPtr<Type, false> theGuard( theManager , (Type*)theManager.allocate(sizeof(Type)));
  
      Type* theResult = theGuard.get();
  
      new (theResult) Type(theManager, theLocator);
  
      theGuard.release();
  
      return theResult;
  }
  
  XPath::~XPath()
  {
  }
  
  
  
  void
  XPath::unknownOpCodeError(
              XalanNode*              context,
              XPathExecutionContext&  executionContext,
              OpCodeMapPositionType   opPos) const
  {
      const GetCachedString   theGuard1(executionContext);
  
      XalanDOMString&     theOpCode = theGuard1.get();
  
      LongToDOMString(
          m_expression.getOpCodeMapValue(opPos),
          theOpCode);
  
      const GetCachedString   theGuard2(executionContext);
  
      executionContext.error(
          XalanMessageLoader::getMessage(
              theGuard2.get(),
              XalanMessages::InvalidOpcodeWasDetected_1Param,
              theOpCode),
          context,
          m_locator);
  }
  
  
  
  void
  XPath::notNodeSetError(
              XalanNode*              context,
              XPathExecutionContext&  executionContext) const
  {
      GetCachedString     theGuard(executionContext);
  
      XalanDOMString&     theBuffer = theGuard.get();
  
      executionContext.error(
          XalanMessageLoader::getMessage(
              theBuffer,
              XalanMessages::ExpressionDoesNotEvaluateToNodeSet),
          context,
          m_locator);
  }
  
  
  
  const XObjectPtr
  XPath::execute(
              XalanNode*              context,
              const PrefixResolver&   prefixResolver,
              XPathExecutionContext&  executionContext) const
  {
      // Push and pop the PrefixResolver...
      const PrefixResolverSetAndRestore   theResolverSetAndRestore(
                                      executionContext,
                                      &prefixResolver);
  
      // Push and pop the current node...
      const CurrentNodePushAndPop     theNodePushAndPop(
                                      executionContext,
                                      context);
  
      return executeMore(
              context,
              getInitialOpCodePosition(),
              executionContext);
  }
  
  
  
  void
  XPath::execute(
              XalanNode*              context,
              const PrefixResolver&   prefixResolver,
              XPathExecutionContext&  executionContext,
              bool&                   result) const
  {
      assert(context != 0);
  
      // Push and pop the PrefixResolver...
      const PrefixResolverSetAndRestore   theResolverSetAndRestore(
                                      executionContext,
                                      &prefixResolver);
  
      // Push and pop the current node...
      const CurrentNodePushAndPop theNodePushAndPop(
                                      executionContext,
                                      context);
  
      executeMore(
              context,
              getInitialOpCodePosition(),
              executionContext,
              result);
  }
  
  
  
  void
  XPath::execute(
              XalanNode*              context,
              const PrefixResolver&   prefixResolver,
              XPathExecutionContext&  executionContext,
              double&                 result) const
  {
      assert(context != 0);
  
      // Push and pop the PrefixResolver...
      const PrefixResolverSetAndRestore   theResolverSetAndRestore(
                                      executionContext,
                                      &prefixResolver);
  
      // Push and pop the current node...
      const CurrentNodePushAndPop theNodePushAndPop(
                                      executionContext,
                                      context);
  
      executeMore(
              context,
              getInitialOpCodePosition(),
              executionContext,
              result);
  }
  
  
  
  void
  XPath::execute(
              XalanNode*              context,
              const PrefixResolver&   prefixResolver,
              XPathExecutionContext&  executionContext,
              XalanDOMString&         result) const
  {
      assert(context != 0);
  
      // Push and pop the PrefixResolver...
      const PrefixResolverSetAndRestore   theResolverSetAndRestore(
                                      executionContext,
                                      &prefixResolver);
  
      // Push and pop the current node...
      const CurrentNodePushAndPop theNodePushAndPop(
                                      executionContext,
                                      context);
  
      executeMore(
              context,
              getInitialOpCodePosition(),
              executionContext,
              result);
  }
  
  
  
  void
  XPath::execute(
              XalanNode*              context,
              const PrefixResolver&   prefixResolver,
              XPathExecutionContext&  executionContext,
              FormatterListener&      formatterListener,
              MemberFunctionPtr       function) const
  {
      assert(context != 0);
  
      // Push and pop the PrefixResolver...
      const PrefixResolverSetAndRestore   theResolverSetAndRestore(
                                      executionContext,
                                      &prefixResolver);
  
      // Push and pop the current node...
      const CurrentNodePushAndPop theNodePushAndPop(
                                      executionContext,
                                      context);
  
      executeMore(
              context,
              getInitialOpCodePosition(),
              executionContext,
              formatterListener,
              function);
  }
  
  
  
  const XObjectPtr
  XPath::execute(
              XalanNode*              context,
              const PrefixResolver&   prefixResolver,
              XPathExecutionContext&  executionContext,
              MutableNodeRefList&     result) const
  {
      assert(context != 0);
      assert(result.empty() == true);
  
      // Push and pop the PrefixResolver...
      const PrefixResolverSetAndRestore   theResolverSetAndRestore(
                                              executionContext,
                                              &prefixResolver);
  
      // Push and pop the current node...
      const CurrentNodePushAndPop     theNodePushAndPop(
                                          executionContext,
                                          context);
  
      return executeMore(
              context,
              getInitialOpCodePosition(),
              executionContext,
              result);
  }
  
  
  
  const XObjectPtr
  XPath::executeMore(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      switch(m_expression.getOpCodeMapValue(opPos))
      {
      case XPathExpression::eOP_OR:
          return executionContext.getXObjectFactory().createBoolean(Or(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_AND:
          return executionContext.getXObjectFactory().createBoolean(And(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_NOTEQUALS:
          return executionContext.getXObjectFactory().createBoolean(notequals(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_EQUALS:
          return executionContext.getXObjectFactory().createBoolean(equals(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_LTE:
          return executionContext.getXObjectFactory().createBoolean(lte(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_LT:
          return executionContext.getXObjectFactory().createBoolean(lt(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_GTE:
          return executionContext.getXObjectFactory().createBoolean(gte(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_GT:
          return executionContext.getXObjectFactory().createBoolean(gt(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_PLUS:
          return executionContext.getXObjectFactory().createNumber(plus(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_MINUS:
          return executionContext.getXObjectFactory().createNumber(minus(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_MULT:
          return executionContext.getXObjectFactory().createNumber(mult(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_DIV:
          return executionContext.getXObjectFactory().createNumber(div(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_MOD:
          return executionContext.getXObjectFactory().createNumber(mod(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_NEG:
          return executionContext.getXObjectFactory().createNumber(neg(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_UNION:
          return Union(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_LITERAL:
          return literal(opPos, executionContext);
          break;
  
      case XPathExpression::eOP_VARIABLE:
          return variable(opPos, executionContext);
          break;
  
      case XPathExpression::eOP_GROUP:
          return group(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_NUMBERLIT:
          return numberlit(opPos, executionContext);
          break;
  
      case XPathExpression::eOP_EXTFUNCTION:
          return runExtFunction(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_FUNCTION:
          return runFunction(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_LOCATIONPATH:
          return locationPath(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_FUNCTION_POSITION:
          return executionContext.getXObjectFactory().createNumber(functionPosition(context, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_LAST:
          return executionContext.getXObjectFactory().createNumber(functionLast(executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_COUNT:
          return executionContext.getXObjectFactory().createNumber(functionCount(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_NOT:
          return executionContext.getXObjectFactory().createBoolean(functionNot(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_TRUE:
          return executionContext.getXObjectFactory().createBoolean(true);
          break;
  
      case XPathExpression::eOP_FUNCTION_FALSE:
          return executionContext.getXObjectFactory().createBoolean(false);
          break;
  
      case XPathExpression::eOP_FUNCTION_BOOLEAN:
          return executionContext.getXObjectFactory().createBoolean(functionBoolean(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_NAME_0:
          return executionContext.getXObjectFactory().createStringReference(functionName(context));
          break;
  
      case XPathExpression::eOP_FUNCTION_NAME_1:
          return executionContext.getXObjectFactory().createStringReference(functionName(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_LOCALNAME_0:
          return executionContext.getXObjectFactory().createStringReference(functionLocalName(context));
          break;
  
      case XPathExpression::eOP_FUNCTION_LOCALNAME_1:
          return executionContext.getXObjectFactory().createStringReference(functionLocalName(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_FLOOR:
          return executionContext.getXObjectFactory().createNumber(functionFloor(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_CEILING:
          return executionContext.getXObjectFactory().createNumber(functionCeiling(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_ROUND:
          return executionContext.getXObjectFactory().createNumber(functionRound(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_NUMBER_0:
          return executionContext.getXObjectFactory().createNumber(functionNumber(context, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_NUMBER_1:
          return executionContext.getXObjectFactory().createNumber(functionNumber(context, opPos, executionContext));
          break;
  
  //  case XPathExpression::eOP_FUNCTION_STRING_0:
  //      return functionString(context);
  //      break;
  
  //  case XPathExpression::eOP_FUNCTION_STRING_1:
  //      return functionString(context, opPos, executionContext);
  //      break;
  
      case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0:
          return executionContext.getXObjectFactory().createNumber(functionStringLength(context));
          break;
  
      case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1:
          return executionContext.getXObjectFactory().createNumber(functionStringLength(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_SUM:
          return executionContext.getXObjectFactory().createNumber(functionSum(context, opPos, executionContext));
          break;
  
      default:
          unknownOpCodeError(context, executionContext, opPos);
          break;
      }
  
      return XObjectPtr();
  }
  
  
  
  void
  XPath::executeMore(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              bool&                   result) const
  {
      switch(m_expression.getOpCodeMapValue(opPos))
      {
      case XPathExpression::eOP_OR:
          result = Or(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_AND:
          result = And(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_NOTEQUALS:
          result = notequals(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_EQUALS:
          result = equals(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_LTE:
          result = lte(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_LT:
          result = lt(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_GTE:
          result = gte(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_GT:
          result = gt(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_PLUS:
          result = XObject::boolean(plus(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_MINUS:
          result = XObject::boolean(minus(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_MULT:
          result = XObject::boolean(mult(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_DIV:
          result = XObject::boolean(div(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_MOD:
          result = XObject::boolean(mod(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_NEG:
          result = XObject::boolean(neg(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_UNION:
          Union(context, opPos, executionContext, result);
          break;
  
      case XPathExpression::eOP_LITERAL:
          literal(opPos, result);
          break;
  
      case XPathExpression::eOP_VARIABLE:
          result = variable(opPos, executionContext)->boolean();
          break;
  
      case XPathExpression::eOP_GROUP:
          group(context, opPos, executionContext, result);
          break;
  
      case XPathExpression::eOP_NUMBERLIT:
          numberlit(opPos, result);
          break;
  
      case XPathExpression::eOP_EXTFUNCTION:
          result = runExtFunction(context, opPos, executionContext)->boolean();
          break;
  
      case XPathExpression::eOP_FUNCTION:
          result = runFunction(context, opPos, executionContext)->boolean();
          break;
  
      case XPathExpression::eOP_LOCATIONPATH:
          locationPath(context, opPos, executionContext, result);
          break;
  
      case XPathExpression::eOP_FUNCTION_POSITION:
          result = XObject::boolean(functionPosition(context, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_LAST:
          result = XObject::boolean(functionLast(executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_COUNT:
          result = XObject::boolean(functionCount(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_NOT:
          result = functionNot(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_FUNCTION_TRUE:
          result = true;
          break;
  
      case XPathExpression::eOP_FUNCTION_FALSE:
          result = false;
          break;
  
      case XPathExpression::eOP_FUNCTION_BOOLEAN:
          result = functionBoolean(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_FUNCTION_NAME_0:
          result = XObject::boolean(functionName(context));
          break;
  
      case XPathExpression::eOP_FUNCTION_NAME_1:
          result = XObject::boolean(functionName(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_LOCALNAME_0:
          result = XObject::boolean(functionLocalName(context));
          break;
  
      case XPathExpression::eOP_FUNCTION_LOCALNAME_1:
          result = XObject::boolean(functionLocalName(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_FLOOR:
          result = XObject::boolean(functionFloor(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_CEILING:
          result = XObject::boolean(functionCeiling(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_ROUND:
          result = XObject::boolean(functionRound(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_NUMBER_0:
          result = XObject::boolean(functionNumber(context, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_NUMBER_1:
          result = XObject::boolean(functionNumber(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0:
          result = XObject::boolean(functionStringLength(context));
          break;
  
      case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1:
          result = XObject::boolean(functionStringLength(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_SUM:
          result = XObject::boolean(functionSum(context, opPos, executionContext));
          break;
  
      default:
          unknownOpCodeError(context, executionContext, opPos);
          break;
      }
  }
  
  
  
  void
  XPath::executeMore(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              double&                 result) const
  {
      switch(m_expression.getOpCodeMapValue(opPos))
      {
      case XPathExpression::eOP_OR:
          result = XObject::number(Or(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_AND:
          result = XObject::number(And(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_NOTEQUALS:
          result = XObject::number(notequals(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_EQUALS:
          result = XObject::number(equals(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_LTE:
          result = XObject::number(lte(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_LT:
          result = XObject::number(lt(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_GTE:
          result = XObject::number(gte(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_GT:
          result = XObject::number(gt(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_PLUS:
          result = plus(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_MINUS:
          result = minus(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_MULT:
          result = mult(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_DIV:
          result = div(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_MOD:
          result = mod(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_NEG:
          result = neg(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_UNION:
          Union(context, opPos, executionContext, result);
          break;
  
      case XPathExpression::eOP_LITERAL:
          literal(opPos, result);
          break;
  
      case XPathExpression::eOP_VARIABLE:
          result = variable(opPos, executionContext)->num();
          break;
  
      case XPathExpression::eOP_GROUP:
          group(context, opPos, executionContext, result);
          break;
  
      case XPathExpression::eOP_NUMBERLIT:
          result = numberlit(opPos);
          break;
  
      case XPathExpression::eOP_EXTFUNCTION:
          result = runExtFunction(context, opPos, executionContext)->num();
          break;
  
      case XPathExpression::eOP_FUNCTION:
          result = runFunction(context, opPos, executionContext)->num();
          break;
  
      case XPathExpression::eOP_LOCATIONPATH:
          locationPath(context, opPos, executionContext, result);
          break;
  
      case XPathExpression::eOP_FUNCTION_POSITION:
          result = functionPosition(context, executionContext);
          break;
  
      case XPathExpression::eOP_FUNCTION_LAST:
          result = functionLast(executionContext);
          break;
  
      case XPathExpression::eOP_FUNCTION_COUNT:
          result = functionCount(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_FUNCTION_NOT:
          result = XObject::number(functionNot(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_TRUE:
          result = XObject::number(true);
          break;
  
      case XPathExpression::eOP_FUNCTION_FALSE:
          result = XObject::number(false);
          break;
  
      case XPathExpression::eOP_FUNCTION_BOOLEAN:
          result = XObject::number(functionBoolean(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_NAME_0:
          result = XObject::number(functionName(context),executionContext.getMemoryManager());
          break;
  
      case XPathExpression::eOP_FUNCTION_NAME_1:
          result = XObject::number(functionName(context, opPos, executionContext),executionContext.getMemoryManager());
          break;
  
      case XPathExpression::eOP_FUNCTION_LOCALNAME_0:
          result = XObject::number(functionLocalName(context),executionContext.getMemoryManager());
          break;
  
      case XPathExpression::eOP_FUNCTION_LOCALNAME_1:
          result = XObject::number(functionLocalName(context, opPos, executionContext),executionContext.getMemoryManager());
          break;
  
      case XPathExpression::eOP_FUNCTION_FLOOR:
          result = functionFloor(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_FUNCTION_CEILING:
          result = functionCeiling(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_FUNCTION_ROUND:
          result = functionRound(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_FUNCTION_NUMBER_0:
          result = functionNumber(context, executionContext);
          break;
  
      case XPathExpression::eOP_FUNCTION_NUMBER_1:
          result = functionNumber(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0:
          result = functionStringLength(context);
          break;
  
      case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1:
          result = functionStringLength(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_FUNCTION_SUM:
          result = functionSum(context, opPos, executionContext);
          break;
  
      default:
          unknownOpCodeError(context, executionContext, opPos);
          break;
      }
  }
  
  
  
  void
  XPath::executeMore(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              XalanDOMString&         result) const
  {
      switch(m_expression.getOpCodeMapValue(opPos))
      {
      case XPathExpression::eOP_OR:
          XObject::string(Or(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_AND:
          XObject::string(And(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_NOTEQUALS:
          XObject::string(notequals(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_EQUALS:
          XObject::string(equals(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_LTE:
          XObject::string(lte(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_LT:
          XObject::string(lt(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_GTE:
          XObject::string(gte(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_GT:
          XObject::string(gt(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_PLUS:
          XObject::string(plus(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_MINUS:
          XObject::string(minus(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_MULT:
          XObject::string(mult(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_DIV:
          XObject::string(div(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_MOD:
          XObject::string(mod(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_NEG:
          XObject::string(neg(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_UNION:
          Union(context, opPos, executionContext, result);
          break;
  
      case XPathExpression::eOP_LITERAL:
          literal(opPos, result);
          break;
  
      case XPathExpression::eOP_VARIABLE:
          variable(opPos, executionContext)->str(result);
          break;
  
      case XPathExpression::eOP_GROUP:
          group(context, opPos, executionContext, result);
          break;
  
      case XPathExpression::eOP_NUMBERLIT:
          numberlit(opPos, result);
          break;
  
      case XPathExpression::eOP_EXTFUNCTION:
          runExtFunction(context, opPos, executionContext)->str(result);
          break;
  
      case XPathExpression::eOP_FUNCTION:
          runFunction(context, opPos, executionContext)->str(result);
          break;
  
      case XPathExpression::eOP_LOCATIONPATH:
          locationPath(context, opPos, executionContext, result);
          break;
  
      case XPathExpression::eOP_FUNCTION_POSITION:
          XObject::string(functionPosition(context, executionContext), result);
          break;
  
      case XPathExpression::eOP_FUNCTION_LAST:
          XObject::string(functionLast(executionContext), result);
          break;
  
      case XPathExpression::eOP_FUNCTION_COUNT:
          XObject::string(functionCount(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_FUNCTION_NOT:
          XObject::string(functionNot(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_FUNCTION_TRUE:
          XObject::string(true, result);
          break;
  
      case XPathExpression::eOP_FUNCTION_FALSE:
          XObject::string(false, result);
          break;
  
      case XPathExpression::eOP_FUNCTION_BOOLEAN:
          XObject::string(functionBoolean(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_FUNCTION_NAME_0:
          result.append(functionName(context));
          break;
  
      case XPathExpression::eOP_FUNCTION_NAME_1:
          result.append(functionName(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_LOCALNAME_0:
          result.append(functionLocalName(context));
          break;
  
      case XPathExpression::eOP_FUNCTION_LOCALNAME_1:
          result.append(functionLocalName(context, opPos, executionContext));
          break;
  
      case XPathExpression::eOP_FUNCTION_FLOOR:
          XObject::string(functionFloor(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_FUNCTION_CEILING:
          XObject::string(functionCeiling(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_FUNCTION_ROUND:
          XObject::string(functionRound(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_FUNCTION_NUMBER_0:
          XObject::string(functionNumber(context, executionContext), result);
          break;
  
      case XPathExpression::eOP_FUNCTION_NUMBER_1:
          XObject::string(functionNumber(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0:
          XObject::string(functionStringLength(context), result);
          break;
  
      case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1:
          XObject::string(functionStringLength(context, opPos, executionContext), result);
          break;
  
      case XPathExpression::eOP_FUNCTION_SUM:
          XObject::string(functionSum(context, opPos, executionContext), result);
          break;
  
      default:
          unknownOpCodeError(context, executionContext, opPos);
          break;
      }
  }
  
  
  
  inline void
  stringToCharacters(
              const XalanDOMString&       str,
              FormatterListener&          formatterListener,
              XPath::MemberFunctionPtr    function)
  {
      const XalanDOMString::size_type     theLength = str.length();
  
      if (theLength != 0)
      {
  	    assert(theLength == FormatterListener::size_type(theLength));
  
  	    (formatterListener.*function)(
              str.c_str(),
              FormatterListener::size_type(theLength));
      }
  }
  
  
  
  void
  XPath::executeMore(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              FormatterListener&      formatterListener,
              MemberFunctionPtr       function) const
  {
      switch(m_expression.getOpCodeMapValue(opPos))
      {
      case XPathExpression::eOP_OR:
          XObject::string(
                  Or(context, opPos, executionContext),
                  formatterListener,
                  function);
          break;
  
      case XPathExpression::eOP_AND:
          XObject::string(
                  And(context, opPos, executionContext),
                  formatterListener,
                  function);
          break;
  
      case XPathExpression::eOP_NOTEQUALS:
          XObject::string(
                  notequals(context, opPos, executionContext),
                  formatterListener,
                  function);
          break;
  
      case XPathExpression::eOP_EQUALS:
          XObject::string(
                  equals(context, opPos, executionContext),
                  formatterListener,
                  function);
          break;
  
      case XPathExpression::eOP_LTE:
          XObject::string(
                  lte(context, opPos, executionContext),
                  formatterListener,
                  function);
          break;
  
      case XPathExpression::eOP_LT:
          XObject::string(
                  lt(context, opPos, executionContext),
                  formatterListener,
                  function);
          break;
  
      case XPathExpression::eOP_GTE:
          XObject::string(
                  gte(context, opPos, executionContext),
                  formatterListener,
                  function);
          break;
  
      case XPathExpression::eOP_GT:
          XObject::string(
                  gt(context, opPos, executionContext),
                  formatterListener,
                  function);
          break;
  
      case XPathExpression::eOP_PLUS:
          plus(context, opPos, executionContext, formatterListener, function);
          break;
  
      case XPathExpression::eOP_MINUS:
          minus(context, opPos, executionContext, formatterListener, function);
          break;
  
      case XPathExpression::eOP_MULT:
          mult(context, opPos, executionContext, formatterListener, function);
          break;
  
      case XPathExpression::eOP_DIV:
          div(context, opPos, executionContext, formatterListener, function);
          break;
  
      case XPathExpression::eOP_MOD:
          mod(context, opPos, executionContext, formatterListener, function);
          break;
  
      case XPathExpression::eOP_NEG:
          neg(context, opPos, executionContext, formatterListener, function);
          break;
  
      case XPathExpression::eOP_UNION:
          Union(context, opPos, executionContext, formatterListener, function);
          break;
  
      case XPathExpression::eOP_LITERAL:
          literal(opPos, formatterListener, function);
          break;
  
      case XPathExpression::eOP_VARIABLE:
          variable(opPos, executionContext)->str( formatterListener, function);
          break;
  
      case XPathExpression::eOP_GROUP:
          group(context, opPos, executionContext, formatterListener, function);
          break;
  
      case XPathExpression::eOP_NUMBERLIT:
          numberlit(opPos, formatterListener, function);
          break;
  
      case XPathExpression::eOP_EXTFUNCTION:
          runExtFunction(context, opPos, executionContext)->str( formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION:
          runFunction(context, opPos, executionContext)->str(formatterListener, function);
          break;
  
      case XPathExpression::eOP_LOCATIONPATH:
          locationPath(context, opPos, executionContext, formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_POSITION:
          XObject::string(functionPosition(context, executionContext), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_LAST:
          XObject::string(functionLast(executionContext), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_COUNT:
          XObject::string(functionCount(context, opPos, executionContext), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_NOT:
          XObject::string(functionNot(context, opPos, executionContext), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_TRUE:
          XObject::string(true, formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_FALSE:
          XObject::string(false, formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_BOOLEAN:
          XObject::string(functionBoolean(context, opPos, executionContext), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_NAME_0:
          stringToCharacters(functionName(context), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_NAME_1:
          stringToCharacters(functionName(context, opPos, executionContext), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_LOCALNAME_0:
          stringToCharacters(functionLocalName(context), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_LOCALNAME_1:
          stringToCharacters(functionLocalName(context, opPos, executionContext), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_FLOOR:
          XObject::string(functionFloor(context, opPos, executionContext), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_CEILING:
          XObject::string(functionCeiling(context, opPos, executionContext), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_ROUND:
          XObject::string(functionRound(context, opPos, executionContext), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_NUMBER_0:
          XObject::string(functionNumber(context, executionContext), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_NUMBER_1:
          XObject::string(functionNumber(context, opPos, executionContext), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0:
          XObject::string(functionStringLength(context), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1:
          XObject::string(functionStringLength(context, opPos, executionContext), formatterListener, function);
          break;
  
      case XPathExpression::eOP_FUNCTION_SUM:
          XObject::string(functionSum(context, opPos, executionContext), formatterListener, function);
          break;
  
      default:
          unknownOpCodeError(context, executionContext, opPos);
          break;
      }
  }
  
  
  
  const XObjectPtr
  XPath::executeMore(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              MutableNodeRefList&     result) const
  {
      XObjectPtr  theXObject;
  
      switch(m_expression.getOpCodeMapValue(opPos))
      {
      case XPathExpression::eOP_XPATH:
          theXObject = executeMore(context, opPos + 2, executionContext, result);
          break;
  
      case XPathExpression::eOP_OR:
      case XPathExpression::eOP_AND:
      case XPathExpression::eOP_NOTEQUALS:
      case XPathExpression::eOP_EQUALS:
      case XPathExpression::eOP_LTE:
      case XPathExpression::eOP_LT:
      case XPathExpression::eOP_GTE:
      case XPathExpression::eOP_GT:
      case XPathExpression::eOP_PLUS:
      case XPathExpression::eOP_MINUS:
      case XPathExpression::eOP_MULT:
      case XPathExpression::eOP_DIV:
      case XPathExpression::eOP_MOD:
      case XPathExpression::eOP_NEG:
      case XPathExpression::eOP_LITERAL:
      case XPathExpression::eOP_NUMBERLIT:
      case XPathExpression::eOP_FUNCTION_POSITION:
      case XPathExpression::eOP_FUNCTION_LAST:
      case XPathExpression::eOP_FUNCTION_COUNT:
      case XPathExpression::eOP_FUNCTION_NOT:
      case XPathExpression::eOP_FUNCTION_TRUE:
      case XPathExpression::eOP_FUNCTION_FALSE:
      case XPathExpression::eOP_FUNCTION_BOOLEAN:
      case XPathExpression::eOP_FUNCTION_NAME_0:
      case XPathExpression::eOP_FUNCTION_NAME_1:
      case XPathExpression::eOP_FUNCTION_LOCALNAME_0:
      case XPathExpression::eOP_FUNCTION_LOCALNAME_1:
      case XPathExpression::eOP_FUNCTION_FLOOR:
      case XPathExpression::eOP_FUNCTION_CEILING:
      case XPathExpression::eOP_FUNCTION_ROUND:
      case XPathExpression::eOP_FUNCTION_NUMBER_0:
      case XPathExpression::eOP_FUNCTION_NUMBER_1:
      case XPathExpression::eOP_FUNCTION_STRING_0:
      case XPathExpression::eOP_FUNCTION_STRING_1:
      case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0:
      case XPathExpression::eOP_FUNCTION_STRINGLENGTH_1:
      case XPathExpression::eOP_FUNCTION_NAMESPACEURI_0:
      case XPathExpression::eOP_FUNCTION_NAMESPACEURI_1:
      case XPathExpression::eOP_FUNCTION_SUM:
          notNodeSetError(context, executionContext);
          break;
  
      case XPathExpression::eOP_UNION:
          Union(context, opPos, executionContext, result);
          break;
  
      case XPathExpression::eOP_VARIABLE:
          theXObject = variable(opPos, executionContext);
          break;
  
      case XPathExpression::eOP_GROUP:
          group(context, opPos, executionContext, result);
          break;
  
      case XPathExpression::eOP_EXTFUNCTION:
          theXObject = runExtFunction(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_FUNCTION:
          theXObject = runFunction(context, opPos, executionContext);
          break;
  
      case XPathExpression::eOP_LOCATIONPATH:
          locationPath(context, opPos, executionContext, result);
          break;
  
      default:
          unknownOpCodeError(context, executionContext, opPos);
          break;
      }
  
      if (theXObject.null() == false && theXObject->getType() != XObject::eTypeNodeSet)
      {
          notNodeSetError(context, executionContext);
      }
  
      return theXObject;
  }
  
  
  
  inline void
  XPath::doGetMatchScore(
              XalanNode*              context,
              XPathExecutionContext&  executionContext,
              eMatchScore&            score) const
  {
      assert(context != 0);
  
      OpCodeMapPositionType   opPos =
          m_expression.getInitialOpCodePosition() + 2;
  
      while(m_expression.getOpCodeMapValue(opPos) == XPathExpression::eOP_LOCATIONPATHPATTERN)
      {
          const OpCodeMapPositionType     nextOpPos = m_expression.getNextOpCodePosition(opPos);
  
          score = locationPathPattern(executionContext, *context, opPos);
  
          if(score == eMatchScoreNone)
          {
              opPos = nextOpPos;
          }
          else
          {
              break;
          }
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::getMatchScore(
              XalanNode*              node,
              XPathExecutionContext&  executionContext) const
  {
      eMatchScore     score = eMatchScoreNone;
  
      if(m_expression.getOpCodeMapValue(0) != XPathExpression::eOP_MATCHPATTERN)
      {
          GetCachedString     theGuard(executionContext);
  
          XalanDOMString&     theBuffer = theGuard.get();
  
          executionContext.error(
              XalanMessageLoader::getMessage(
                  theBuffer,
                  XalanMessages::CannotEvaluateXPathExpressionAsMatchPattern),
              node,
              m_locator);
      }
      else
      {
          assert(node != 0);
  
          doGetMatchScore(node, executionContext, score);
      }
  
      return score;
  }
  
  
  
  XPath::eMatchScore
  XPath::getMatchScore(
              XalanNode*              node,
              const PrefixResolver&   resolver,
              XPathExecutionContext&  executionContext) const
  {
      const PrefixResolver* const     theCurrentResolver =
          executionContext.getPrefixResolver();
  
      if (theCurrentResolver == &resolver)
      {
          return getMatchScore(node, executionContext);
      }
      else
      {
          // Push and pop the PrefixResolver...
          const PrefixResolverSetAndRestore   theSetAndRestore(
                                                  executionContext,
                                                  theCurrentResolver,
                                                  &resolver);
  
          return getMatchScore(node, executionContext);
      }
  }
  
  
  
  inline const XalanDOMString*
  getStringFromTokenQueue(
              const XPathExpression&          expression,
              XPath::OpCodeMapPositionType    opPos)
  {
      const XPath::OpCodeMapValueType     tokenPosition =
                  expression.getOpCodeMapValue(opPos);
  
      if (tokenPosition == XPathExpression::eEMPTY ||
          tokenPosition == XPathExpression::eELEMWILDCARD)
      {
          return 0;
      }
      else
      {
          assert(tokenPosition != XPathExpression::eENDOP);
  
          const XObject* const    token =
                      expression.getToken(tokenPosition);
          assert(token != 0);
  
          return &token->str();
      }
  }
  
  
  
  void
  XPath::getTargetData(TargetDataVectorType&  targetData) const
  {
      OpCodeMapPositionType   opPos =
          m_expression.getInitialOpCodePosition() + 2;
  
      targetData.reserve(eDefaultTargetDataSize);
  
      while(m_expression.getOpCodeMapValue(opPos) == XPathExpression::eOP_LOCATIONPATHPATTERN)
      {
          const OpCodeMapPositionType     nextOpPos = m_expression.getNextOpCodePosition(opPos);
  
          opPos += 2;
       
          unsigned long   stepCount = 0;
  
          while(m_expression.getOpCodeMapValue(opPos) != XPathExpression::eENDOP)
          {
              ++stepCount;
  
              const OpCodeMapPositionType     nextStepPos =
                  m_expression.getNextOpCodePosition(opPos);
  
              const OpCodeMapValueType    nextOp = m_expression.getOpCodeMapValue(nextStepPos);
  
              if(nextOp == XPathExpression::eENDOP)
              {
                  eMatchScore                 score = eMatchScoreNone;
  
                  const XalanDOMChar*         targetLocalName = 0;
  
                  TargetData::eTargetType     targetType = TargetData::eOther;
  
                  bool    fIsAttribute = false;
  
                  const OpCodeMapValueType    stepType = m_expression.getOpCodeMapValue(opPos);
  
                  opPos += 3;
  
                  switch(stepType)
                  {
                  case XPathExpression::eOP_FUNCTION:
                      targetLocalName = PSEUDONAME_ANY;
                      score = eMatchScoreOther;
                      targetType = TargetData::eAny;
                      break;
  
                  case XPathExpression::eFROM_ROOT:
                      targetLocalName = PSEUDONAME_ROOT;
                      score = eMatchScoreOther;
                      break;
  
                  case XPathExpression::eMATCH_ATTRIBUTE:
                      fIsAttribute = true;
                      // fall through on purpose...
  
                  case XPathExpression::eMATCH_ANY_ANCESTOR:
                  case XPathExpression::eMATCH_IMMEDIATE_ANCESTOR:
                      {
                          const OpCodeMapValueType    tok = m_expression.getOpCodeMapValue(opPos);
  
                          switch(tok)
                          {
                          case XPathExpression::eNODETYPE_COMMENT:
                              targetLocalName = PSEUDONAME_COMMENT;
                              score = eMatchScoreNodeTest;
                              break;
  
                          case XPathExpression::eNODETYPE_TEXT:
                              targetLocalName = PSEUDONAME_TEXT;
                              score = eMatchScoreNodeTest;
                              break;
  
                          case XPathExpression::eNODETYPE_NODE:
                              targetLocalName = PSEUDONAME_NODE;
                              score = eMatchScoreNodeTest;
                              break;
  
                          case XPathExpression::eNODETYPE_ROOT:
                              targetLocalName = PSEUDONAME_ROOT;
                              score = eMatchScoreNodeTest;
                              break;
  
                          case XPathExpression::eNODETYPE_ANYELEMENT:
                              targetLocalName = PSEUDONAME_ANY;
                              score = eMatchScoreNodeTest;
                              targetType = TargetData::eElement;
                              break;
  
                          case XPathExpression::eNODETYPE_PI:
                              {
                                  const OpCodeMapValueType    argLen =
                                      m_expression.getOpCodeArgumentLength(opPos - 3);
  
                                  targetLocalName = PSEUDONAME_PI;
  
                                  if (argLen == 1)
                                  {
                                      score = eMatchScoreNodeTest;
                                  }
                                  else if (argLen == 2)
                                  {
                                      score = eMatchScoreQName;
                                  }
                              }
                              break;
  
                          case XPathExpression::eNODENAME:
                              {
                                  const XalanDOMString* const     targetNamespace =
                                          getStringFromTokenQueue(m_expression, opPos + 1);
  
                                  const XalanDOMString* const     targetLocal =
                                          getStringFromTokenQueue(m_expression, opPos + 2);
  
                                  if (targetLocal == 0)
                                  {
                                      targetLocalName = 0;
                                  }
                                  else
                                  {
                                      targetLocalName = targetLocal->c_str();
                                  }
  
                                  targetType = fIsAttribute ?
                                      TargetData::eAttribute :
                                      TargetData::eElement;
  
                                  if(targetLocalName != 0)
                                  {
                                      if(targetLocalName == PSEUDONAME_ANY)
                                      {
                                          targetLocalName = PSEUDONAME_ANY;
  
                                          if (targetNamespace == 0 ||
                                              *targetNamespace == PSEUDONAME_ANY)
                                          {
                                              score = eMatchScoreNodeTest;
                                          }
                                          else
                                          {
                                              score = eMatchScoreNSWild;
                                          }
                                      }
                                      else
                                      {
                                          score = eMatchScoreQName;
                                      }
                                  }
                                  else
                                  {
                                      targetLocalName = PSEUDONAME_ANY;
  
                                      if (targetNamespace == 0 ||
                                          *targetNamespace == PSEUDONAME_ANY)
                                      {
                                          score = eMatchScoreNodeTest;
                                      }
                                      else
                                      {
                                          score = eMatchScoreNSWild;
                                      }
                                  }
                              }
  
                              break;
  
                          default:
                              targetLocalName = PSEUDONAME_ANY;
                              score = eMatchScoreNodeTest;
                              break;
                          }
                      }
                      break;
                  }
  
                  assert(targetLocalName != 0);
  
                  // If there are multiple steps, or a predicate,
                  // the priority is always eMatchScoreOther.
                  if (stepCount > 1 ||
                      opPos + 3 < nextStepPos)
                  {
                      score = eMatchScoreOther;
                  }
  
                  targetData.push_back(TargetData(targetLocalName, score, targetType));
              }
  
              opPos = nextStepPos;
          }
  
          opPos = nextOpPos;
      }
  }
  
  
  
  bool
  XPath::Or(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      opPos += 2;
  
      bool    theResult;
  
      executeMore(context, opPos, executionContext, theResult);
  
      if(theResult == false)
      {
          opPos = m_expression.getNextOpCodePosition(opPos);
  
          executeMore(context, opPos, executionContext, theResult);
      }
  
      return theResult;
  }
  
  
  
  bool
  XPath::And(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      opPos += 2; 
  
      bool    fResult;
  
      executeMore(context, opPos, executionContext, fResult);
  
      if (fResult == true)
      {
          opPos = m_expression.getNextOpCodePosition(opPos);
  
          executeMore(context, opPos, executionContext, fResult);
      }   
  
      return fResult;
  }
  
  
  
  bool
  XPath::notequals(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      opPos += 2; 
  
      const XObjectPtr    expr1(executeMore(context, opPos, executionContext));
      assert(expr1.get() != 0);
  
      opPos = m_expression.getNextOpCodePosition(opPos);
  
      return expr1->notEquals(
              *executeMore(context, opPos, executionContext).get(),
              executionContext);
  }
  
  
  
  bool
  XPath::equals(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      opPos += 2; 
  
      const XObjectPtr    expr1(executeMore(context, opPos, executionContext));
      assert(expr1.get() != 0);
  
      opPos = m_expression.getNextOpCodePosition(opPos);
  
      return expr1->equals(
              *executeMore(context, opPos, executionContext).get(),
              executionContext);
  }
  
  
  
  bool
  XPath::lte(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      opPos += 2; 
  
      const XObjectPtr    expr1(executeMore(context, opPos, executionContext));
      assert(expr1.get() != 0);
  
      opPos = m_expression.getNextOpCodePosition(opPos);
  
      return expr1->lessThanOrEquals(
              *executeMore(context, opPos, executionContext).get(),
              executionContext);
  }
  
  
  
  bool
  XPath::lt(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      opPos += 2;
  
      const XObjectPtr    expr1(executeMore(context, opPos, executionContext));
      assert(expr1.get() != 0);
  
      opPos = m_expression.getNextOpCodePosition(opPos);
  
      return expr1->lessThan(
              *executeMore(context, opPos, executionContext).get(),
              executionContext);
  }
  
  
  
  bool
  XPath::gte(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      opPos += 2;
  
      const XObjectPtr    expr1(executeMore(context, opPos, executionContext));
      assert(expr1.get() != 0);
  
      opPos = m_expression.getNextOpCodePosition(opPos);
  
      return expr1->greaterThanOrEquals(
              *executeMore(context, opPos, executionContext).get(),
              executionContext);
  }
  
  
  
  bool
  XPath::gt(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      opPos += 2;
  
      const XObjectPtr    expr1(executeMore(context, opPos, executionContext));
      assert(expr1.get() != 0);
  
      opPos = m_expression.getNextOpCodePosition(opPos);
  
      return expr1->greaterThan(
              *executeMore(context, opPos, executionContext).get(),
              executionContext);
  }
  
  
  
  double
  XPath::getNumericOperand(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      if (m_expression.getOpCodeMapValue(opPos) == XPathExpression::eOP_NUMBERLIT)
      {
          assert(m_expression.tokenQueueSize() >
              m_expression.getOpCodeMapValue(opPos + 3));
  
          return m_expression.getNumberLiteral(m_expression.getOpCodeMapValue(opPos + 2));
      }
      else
      {
          double  theResult;
  
          executeMore(context, opPos, executionContext, theResult);
  
          return theResult;
      }
  }
  
  
  
  double
  XPath::plus(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      opPos += 2;
  
      const double    expr1 = getNumericOperand(context, opPos, executionContext);
  
      opPos = m_expression.getNextOpCodePosition(opPos);
  
      const double    expr2 = getNumericOperand(context, opPos, executionContext);
  
      return DoubleSupport::add(expr1, expr2);
  }
  
  
  
  void
  XPath::plus(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              FormatterListener&      formatterListener,
              MemberFunctionPtr       function) const
  {
      const double    theResult = plus(context, opPos, executionContext);
  
      XObject::string(theResult, formatterListener, function);
  }
  
  
  
  double
  XPath::minus(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      opPos += 2;
  
      const double    expr1 = getNumericOperand(context, opPos, executionContext);
  
      opPos = m_expression.getNextOpCodePosition(opPos);
  
      const double    expr2 = getNumericOperand(context, opPos, executionContext);
  
      return DoubleSupport::subtract(expr1, expr2);
  }
  
  
  
  void
  XPath::minus(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              FormatterListener&      formatterListener,
              MemberFunctionPtr       function) const
  {
      const double    theResult = minus(context, opPos, executionContext);
  
      XObject::string(theResult, formatterListener, function);
  }
  
  
  
  double
  XPath::mult(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      opPos += 2;
  
      const double    expr1 = getNumericOperand(context, opPos, executionContext);
  
      opPos = m_expression.getNextOpCodePosition(opPos);
  
      const double    expr2 = getNumericOperand(context, opPos, executionContext);
  
      return DoubleSupport::multiply(expr1, expr2);
  }
  
  
  
  void
  XPath::mult(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              FormatterListener&      formatterListener,
              MemberFunctionPtr       function) const
  {
      const double    theResult = mult(context, opPos, executionContext);
  
      XObject::string(theResult, formatterListener, function);
  }
  
  
  
  double
  XPath::div(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      opPos += 2;
  
      const double    expr1 = getNumericOperand(context, opPos, executionContext);
  
      opPos = m_expression.getNextOpCodePosition(opPos);
  
      const double    expr2 = getNumericOperand(context, opPos, executionContext);
  
      return DoubleSupport::divide(expr1, expr2);
  }
  
  
  
  void
  XPath::div(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              FormatterListener&      formatterListener,
              MemberFunctionPtr       function) const
  {
      const double    theResult = div(context, opPos, executionContext);
  
      XObject::string(theResult, formatterListener, function);
  }
  
  
  
  double
  XPath::mod(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      opPos += 2; 
  
      const double    expr1 = getNumericOperand(context, opPos, executionContext);
  
      opPos = m_expression.getNextOpCodePosition(opPos);
  
      const double    expr2 = getNumericOperand(context, opPos, executionContext);
  
      return DoubleSupport::modulus(expr1, expr2);
  }
  
  
  
  void
  XPath::mod(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              FormatterListener&      formatterListener,
              MemberFunctionPtr       function) const
  {
      const double    theResult = mod(context, opPos, executionContext);
  
      XObject::string(theResult, formatterListener, function);
  }
  
  
  
  double
  XPath::neg(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      return DoubleSupport::negative(getNumericOperand(context, opPos + 2, executionContext));
  }
  
  
  
  void
  XPath::neg(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              FormatterListener&      formatterListener,
              MemberFunctionPtr       function) const
  {
      const double    theResult = neg(context, opPos, executionContext);
  
      XObject::string(theResult, formatterListener, function);
  }
  
  
  
  const XObjectPtr
  XPath::Union(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  resultNodeList(executionContext);
  
      Union(context, opPos, executionContext, *resultNodeList);
  
      return executionContext.getXObjectFactory().createNodeSet(resultNodeList);
  }
  
  
  
  void
  XPath::Union(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              bool&                   result) const
  {
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  resultNodeList(executionContext);
  
      Union(context, opPos, executionContext, *resultNodeList);
  
      result = XObject::boolean(*resultNodeList);
  }
  
  
  
  void
  XPath::Union(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              double&                 result) const
  {
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  resultNodeList(executionContext);
  
      Union(context, opPos, executionContext, *resultNodeList);
  
      result = XObject::number(executionContext, *resultNodeList);
  }
  
  
  
  void
  XPath::Union(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              XalanDOMString&         result) const
  {
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  resultNodeList(executionContext);
  
      Union(context, opPos, executionContext, *resultNodeList);
  
      XObject::string(*resultNodeList, result);
  }
  
  
  
  void
  XPath::Union(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              FormatterListener&      formatterListener,
              MemberFunctionPtr       function) const
  {
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  resultNodeList(executionContext);
  
      Union(context, opPos, executionContext, *resultNodeList);
  
      XObject::string(*resultNodeList, formatterListener, function);
  }
  
  
  
  void
  XPath::Union(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              MutableNodeRefList&     result) const
  {
      assert(result.empty() == true);
  
      opPos += 2;
  
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  theGuard(executionContext);
  
      MutableNodeRefList&     tempNodeList = *theGuard;
  
      while(m_expression.getOpCodeMapValue(opPos) != XPathExpression::eENDOP)
      {
          const XObjectPtr    nodesetResult(executeMore(context, opPos, executionContext, tempNodeList));
  
          if (nodesetResult.null() == false)
          {
              result.addNodesInDocOrder(nodesetResult->nodeset(), executionContext);
          }
          else
          {
              result.addNodesInDocOrder(tempNodeList, executionContext);
  
              tempNodeList.clear();
          }
  
          opPos = m_expression.getNextOpCodePosition(opPos);
      }
  
      result.setDocumentOrder();
  }
  
  
  
  const XObjectPtr
  XPath::literal(
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      assert(m_expression.isValidOpCodePosition(opPos + 2));
      assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2)));
  
      const XToken* const     theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2));
      assert(theLiteral != 0);
  
      if (m_inStylesheet == true)
      {
          return executionContext.getXObjectFactory().createString(*theLiteral);
      }
      else
      {
          return executionContext.getXObjectFactory().createString(theLiteral->str());
      }
  }
  
  
  
  void
  XPath::literal(
              OpCodeMapPositionType   opPos,
              bool&                   theResult) const
  {
      assert(m_expression.isValidOpCodePosition(opPos + 2));
      assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2)));
  
      const XToken* const     theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2));
      assert(theLiteral != 0);
  
      theResult = theLiteral->boolean();
  }
  
  
  
  void
  XPath::literal(
              OpCodeMapPositionType   opPos,
              double&                 theResult) const
  {
      assert(m_expression.isValidOpCodePosition(opPos + 2));
      assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2)));
  
      const XToken* const     theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2));
      assert(theLiteral != 0);
  
      theResult = theLiteral->num();
  }
  
  
  
  void
  XPath::literal(
              OpCodeMapPositionType   opPos,
              XalanDOMString&         theString) const
  {
      assert(m_expression.isValidOpCodePosition(opPos + 2));
      assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2)));
  
      const XToken* const     theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2));
      assert(theLiteral != 0);
  
      theLiteral->str(theString);
  }
  
  
  
  void
  XPath::literal(
              OpCodeMapPositionType   opPos,
              FormatterListener&      formatterListener,
              MemberFunctionPtr       function) const
  {
      assert(m_expression.isValidOpCodePosition(opPos + 2));
      assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 2)));
  
      const XToken* const     theLiteral = m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2));
      assert(theLiteral != 0);
  
      theLiteral->str( formatterListener, function);
  }
  
  
  
  const XObjectPtr
  XPath::variable(
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      assert(m_expression.isValidOpCodePosition(opPos + 3));
      assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3)));
  
      const XToken* const     ns =
          m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 2));
      assert(ns != 0);
  
      const XToken* const     varName =
          m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3));
      assert(varName != 0);
  
      return executionContext.getVariable(XalanQNameByReference(ns->str(), varName->str()), m_locator);
  }
  
  
  
  const XObjectPtr
  XPath::numberlit(
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      assert(m_expression.isValidOpCodePosition(opPos + 3));
      assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3)));
  
      const XToken* const     theLiteral =
          m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3));
      assert(theLiteral != 0);
  
      if (m_inStylesheet == true)
      {
          return executionContext.getXObjectFactory().createNumber(*theLiteral);
      }
      else
      {
          return executionContext.getXObjectFactory().createNumber(theLiteral->num());
      }
  }
  
  
  
  double
  XPath::numberlit(OpCodeMapPositionType  opPos) const
  {
      assert(m_expression.isValidOpCodePosition(opPos + 3));
      assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3)));
  
      const XToken* const     theLiteral =
          m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3));
      assert(theLiteral != 0);
  
      return theLiteral->num();
  }
  
  
  
  void
  XPath::numberlit(
              OpCodeMapPositionType   opPos,
              bool&                   theResult) const
  {
      assert(m_expression.isValidOpCodePosition(opPos + 3));
      assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3)));
  
      const XToken* const     theLiteral =
          m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3));
      assert(theLiteral != 0);
  
      theResult = theLiteral->boolean();
  }
  
  
  
  void
  XPath::numberlit(
              OpCodeMapPositionType   opPos,
              XalanDOMString&         theString) const
  {
      assert(m_expression.isValidOpCodePosition(opPos + 3));
      assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3)));
  
      const XToken* const     theLiteral =
          m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3));
      assert(theLiteral != 0);
  
      theLiteral->str(theString);
  }
  
  
  
  void
  XPath::numberlit(
              OpCodeMapPositionType   opPos,
              FormatterListener&      formatterListener,
              MemberFunctionPtr       function) const
  {
      assert(m_expression.isValidOpCodePosition(opPos + 3));
      assert(m_expression.isValidTokenQueuePosition(m_expression.getOpCodeMapValue(opPos + 3)));
  
      const XToken* const     theLiteral =
          m_expression.getToken(m_expression.getOpCodeMapValue(opPos + 3));
      assert(theLiteral != 0);
  
      theLiteral->str( formatterListener, function);
  }
  
  
  
  const XObjectPtr
  XPath::locationPath(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {    
      assert(context != 0);
  
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  mnl(executionContext);
  
      locationPath(context, opPos, executionContext, *mnl.get());
  
      return executionContext.getXObjectFactory().createNodeSet(mnl);
  }
  
  
  
  void
  XPath::locationPath(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              bool&                   theResult) const
  {
      assert(context != 0);
  
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  mnl(executionContext);
  
      locationPath(context, opPos, executionContext, *mnl.get());
  
      theResult = XObject::boolean(*mnl.get());
  }
  
  
  
  void
  XPath::locationPath(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              double&                 theResult) const
  {
      assert(context != 0);
  
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  mnl(executionContext);
  
      locationPath(context, opPos, executionContext, *mnl.get());
  
      theResult = XObject::number(executionContext, *mnl.get());
  }
  
  
  
  void
  XPath::locationPath(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              XalanDOMString&         theResult) const
  {
      assert(context != 0);
  
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  mnl(executionContext);
  
      locationPath(context, opPos, executionContext, *mnl.get());
  
      XObject::string(*mnl.get(), theResult);
  }
  
  
  
  void
  XPath::locationPath(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext,
              FormatterListener&      formatterListener,
              MemberFunctionPtr       function) const
  {
      assert(context != 0);
  
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  mnl(executionContext);
  
      locationPath(context, opPos, executionContext, *mnl.get());
  
      XObject::string(*mnl, formatterListener, function);
  }
  
  
  
  const XObjectPtr
  XPath::runExtFunction(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      assert(context != 0);
  
      const OpCodeMapPositionType     endExtFunc =
          opPos + m_expression.getOpCodeMapValue(opPos + 1) - 1;
  
      opPos += 2;
  
      const XToken* const     ns = m_expression.getToken(m_expression.getOpCodeMapValue(opPos));
      assert(ns != 0);
  
      ++opPos;
  
      const XToken* const     funcName = m_expression.getToken(m_expression.getOpCodeMapValue(opPos));
      assert(funcName != 0);
  
      ++opPos;
  
      typedef XPathExecutionContext::XObjectArgVectorType     XObjectArgVectorType;
  
      XObjectArgVectorType    args(executionContext.getMemoryManager());
  
      while(opPos < endExtFunc)
      {
          const OpCodeMapPositionType     nextOpPos =
              m_expression.getNextOpCodePosition(opPos);
  
          args.push_back(executeMore(context, opPos, executionContext));
  
          opPos = nextOpPos;
      }
  
      return extfunction(context, opPos, ns->str(), funcName->str(), args, executionContext);
  }
  
  
  
  const XObjectPtr
  XPath::runFunction(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      const OpCodeMapPositionType     endFunc =
          opPos + m_expression.getOpCodeMapValue(opPos + 1) - 1;
  
      opPos += 2;
  
      // This is index into the function table for the
      // function.
      const OpCodeMapValueType    funcID = m_expression.getOpCodeMapValue(opPos);
  
      opPos++;
  
      // Number of args is next.
      const OpCodeMapValueType    argCount = m_expression.getOpCodeMapValue(opPos);
  
      opPos++;
  
      if (argCount == 0)
      {
          assert(opPos == endFunc);
  
          return s_functions[funcID].execute(executionContext, context, m_locator);
      }
      else if (argCount == 1)
      {
          return s_functions[funcID].execute(
              executionContext,
              context,
              executeMore(context, opPos, executionContext),
              m_locator);
      }
      else if (argCount == 2)
      {
          const XObjectPtr    theArg1(executeMore(context, opPos, executionContext));
  
          opPos = m_expression.getNextOpCodePosition(opPos);
  
          assert(m_expression.getNextOpCodePosition(opPos) == endFunc);
  
          return s_functions[funcID].execute(
              executionContext,
              context,
              theArg1,
              executeMore(context, opPos, executionContext),
              m_locator);
      }
      else if (argCount == 3)
      {
          const XObjectPtr    theArg1(executeMore(context, opPos, executionContext));
  
          opPos = m_expression.getNextOpCodePosition(opPos);
  
          const XObjectPtr    theArg2(executeMore(context, opPos, executionContext));
  
          opPos = m_expression.getNextOpCodePosition(opPos);
  
          assert(m_expression.getNextOpCodePosition(opPos) == endFunc);
  
          return s_functions[funcID].execute(
              executionContext,
              context,
              theArg1,
              theArg2,
              executeMore(context, opPos, executionContext),
              m_locator);
      }
      else
      {
          typedef XPathExecutionContext::XObjectArgVectorType     XObjectArgVectorType;
  
          XObjectArgVectorType    args(executionContext.getMemoryManager());
  
          args.reserve(argCount);
  
          while(opPos < endFunc)
          {
              args.push_back(executeMore(context, opPos, executionContext));
  
              opPos = m_expression.getNextOpCodePosition(opPos);
          }
  
          return function(context, funcID, args, executionContext);
      }
  }
  
  
  
  double
  XPath::functionCount(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      assert(context != 0);
  
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  result(executionContext);
  
      const XObjectPtr    nodesetResult(executeMore(context, opPos + 2, executionContext, *result));
  
      if (nodesetResult.null() == false)
      {
          return nodesetResult->nodeset().getLength();
      }
      else
      {
          return result->getLength();
      }
  }
  
  
  
  const XalanDOMString&
  XPath::functionName(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      assert(context != 0);
  
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  result(executionContext);
  
      const XObjectPtr    nodesetResult(executeMore(context, opPos + 2, executionContext, *result));
  
      const NodeRefListBase* const    theNodeList = nodesetResult.null() == false ?
              &nodesetResult->nodeset() : &*result;
      assert(theNodeList != 0);
  
      if (theNodeList->getLength() == 0)
      {
          return s_emptyString;
      }
      else
      {
          assert(theNodeList->item(0) != 0);
  
          return functionName(theNodeList->item(0));
      }
  }
  
  
  
  const XalanDOMString&
  XPath::functionLocalName(XalanNode*     context) const
  {
      assert(context != 0);
  
      const XalanDOMString*       theResult = &s_emptyString;
  
      const XalanNode::NodeType   theType = context->getNodeType();
  
      if(theType == XalanNode::ELEMENT_NODE ||
         theType == XalanNode::PROCESSING_INSTRUCTION_NODE)
      {
          theResult = &DOMServices::getLocalNameOfNode(*context);
      }
      else if (theType == XalanNode::ATTRIBUTE_NODE)
      {
          const XalanDOMString&   theLocalName = DOMServices::getLocalNameOfNode(*context);
  
          if (theLocalName != DOMServices::s_XMLNamespace)
          {
              theResult = &theLocalName;
          }
      }
  
      return *theResult;
  }
  
  
  
  const XalanDOMString&
  XPath::functionLocalName(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      assert(context != 0);
  
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  result(executionContext);
  
      const XObjectPtr    nodesetResult(executeMore(context, opPos + 2, executionContext, *result));
  
      const NodeRefListBase* const    theNodeList = nodesetResult.null() == false ?
              &nodesetResult->nodeset() : &*result;
      assert(theNodeList != 0);
  
      if (theNodeList->getLength() == 0)
      {
          return s_emptyString;
      }
      else
      {
          assert(theNodeList->item(0) != 0);
  
          return functionLocalName(theNodeList->item(0));
      }
  }
  
  
  
  double
  XPath::functionStringLength(XalanNode*  context) const
  {
      assert(context != 0);
  
      FormatterStringLengthCounter    theCounter;
  
      DOMServices::getNodeData(*context, theCounter, &FormatterListener::characters);
  
      return theCounter.getCount();
  }
  
  
  
  double
  XPath::functionStringLength(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      assert(context != 0);
  
      FormatterStringLengthCounter    theCounter;
  
      executeMore(context, opPos + 2, executionContext, theCounter, &FormatterListener::characters);
  
      return theCounter.getCount();
  }
  
  
  
  double
  XPath::functionSum(
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              XPathExecutionContext&  executionContext) const
  {
      assert(context != 0);
  
      double  sum = 0.0;
  
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  result(executionContext);
  
      const XObjectPtr    nodesetResult(executeMore(context, opPos + 2, executionContext, *result));
  
      const NodeRefListBase* const    theNodeList = nodesetResult.null() == false ?
              &nodesetResult->nodeset() : &*result;
      assert(theNodeList != 0);
  
      const NodeRefListBase::size_type    theLength = theNodeList->getLength();
  
      if (theLength != 0)
      {
          assert(theNodeList->item(0) != 0);
  
          const XPathExecutionContext::GetAndReleaseCachedString  theData(executionContext);
  
          XalanDOMString&     theString = theData.get();
  
          for (NodeRefListBase::size_type i = 0; i < theLength; i++)
          {
              DOMServices::getNodeData(*theNodeList->item(i), theString);
  
              sum = DoubleSupport::add(sum, DoubleSupport::toDouble(theString, executionContext.getMemoryManager()));
  
              clear(theString);
          }
      }
  
      return sum;
  }
  
  
  
  XPath::eMatchScore
  XPath::locationPathPattern(
              XPathExecutionContext&  executionContext,
              XalanNode&              context, 
              OpCodeMapPositionType   opPos) const
  {
      eMatchScore score = eMatchScoreNone;
  
      stepPattern(executionContext, &context, opPos + 2, score);
  
      return score;
  }
  
  
  
  void
  XPath::step(
              XPathExecutionContext&  executionContext,
              XalanNode*              context,
              OpCodeMapPositionType   opPos,
              MutableNodeRefList&     queryResults) const
  {
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType   stepType =
          currentExpression.getOpCodeMapValue(opPos);
  
      typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
      BorrowReturnMutableNodeRefList  subQueryResults(executionContext);
  
      bool    continueStepRecursion = true;
  
      switch(stepType)
      {
      case XPathExpression::eOP_VARIABLE:
      case XPathExpression::eOP_EXTFUNCTION:
      case XPathExpression::eOP_FUNCTION:
      case XPathExpression::eOP_GROUP:
          opPos = findNodeSet(executionContext, context, opPos, stepType, *subQueryResults);
          break;
  
      case XPathExpression::eFROM_ROOT:
          opPos = findRoot(executionContext, context, opPos, stepType, *subQueryResults);
          break;
  
      case XPathExpression::eFROM_PARENT:
          opPos = findParent(executionContext, context, opPos, stepType, *subQueryResults);
          break;
  
      case XPathExpression::eFROM_SELF:
          opPos = findSelf(executionContext, context, opPos, stepType, *subQueryResults);
          break;
  
      case XPathExpression::eFROM_ANCESTORS:
          opPos = findAncestors(executionContext, context, opPos, stepType, *subQueryResults);
          break;
  
      case XPathExpression::eFROM_ANCESTORS_OR_SELF:
          opPos = findAncestorsOrSelf(executionContext, context, opPos, stepType, *subQueryResults);
          break;
  
      case XPathExpression::eMATCH_ATTRIBUTE:
          continueStepRecursion = false;
          // fall-through on purpose.
  
      case XPathExpression::eFROM_ATTRIBUTES:
          opPos = findAttributes(executionContext, context, opPos, stepType, *subQueryResults);
          break;
  
      case XPathExpression::eMATCH_ANY_ANCESTOR:
      case XPathExpression::eMATCH_IMMEDIATE_ANCESTOR:
      case XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE:
          continueStepRecursion = false;
          // fall-through on purpose.
  
      case XPathExpression::eFROM_CHILDREN:
          opPos = findChildren(executionContext, context, opPos, stepType, *subQueryResults);
          break;
  
      case XPathExpression::eFROM_DESCENDANTS:
      case XPathExpression::eFROM_DESCENDANTS_OR_SELF:
          opPos = findDescendants(executionContext, context, opPos, stepType, *subQueryResults);
          break;
  
      case XPathExpression::eFROM_FOLLOWING:
          opPos = findFollowing(executionContext, context, opPos, stepType, *subQueryResults);
          break;
  
      case XPathExpression::eFROM_FOLLOWING_SIBLINGS:
          opPos = findFollowingSiblings(executionContext, context, opPos, stepType, *subQueryResults);
          break;
  
      case XPathExpression::eFROM_PRECEDING:
          opPos = findPreceeding(executionContext, context, opPos, stepType, *subQueryResults);
          break;
  
      case XPathExpression::eFROM_PRECEDING_SIBLINGS:
          opPos = findPreceedingSiblings(executionContext, context, opPos, stepType, *subQueryResults);
          break;
  
      case XPathExpression::eFROM_NAMESPACE:
          opPos = findNamespace(executionContext, context, opPos,  stepType, *subQueryResults);
          break;
  
      default:
          opPos = findNodesOnUnknownAxis(executionContext, context, opPos, stepType, *subQueryResults);
          break;
      }
  
      OpCodeMapValueType  nextStepType = currentExpression.getOpCodeMapValue(opPos);
  
      // Push and pop the context node list...
      XPathExecutionContext::ContextNodeListPushAndPop    thePushAndPop(
                                          executionContext,
                                          *subQueryResults);
  
      if(XPathExpression::eOP_PREDICATE == nextStepType ||
         XPathExpression::eOP_PREDICATE_WITH_POSITION == nextStepType)
      {
          opPos =
              predicates(
                  executionContext,
                  opPos, 
                  *subQueryResults);
  
          nextStepType = currentExpression.getOpCodeMapValue(opPos);
      }
  
      if(XPathExpression::eENDOP != nextStepType && continueStepRecursion == true)
      {
          const NodeRefListBase::size_type    nContexts = subQueryResults->getLength();
  
          if (nContexts > 0)
          {
              for(NodeRefListBase::size_type i = 0; i < nContexts; i++)
              {
                  XalanNode* const    node = subQueryResults->item(i);
                  assert(node != 0);
  
                  BorrowReturnMutableNodeRefList  mnl(executionContext);
  
                  step(executionContext, node, opPos, *mnl);
  
                  if (mnl->empty() == false)
                  {
                      if(queryResults.empty() == false)
                      {
                          queryResults.addNodesInDocOrder(*mnl, executionContext);
  
                          queryResults.setDocumentOrder();
                      }
                      else
                      {
                          assert(mnl->getDocumentOrder() == true);
  
                          queryResults.swap(*mnl);
                      }
                  }
              }
  
              if (queryResults.empty() == true)
              {
                  queryResults.setDocumentOrder();
              }
          }
      }
      else
      {
          if (subQueryResults->empty() == true)
          {
              queryResults.clear();
          }
          else if (subQueryResults->getReverseDocumentOrder() == true)
          {
              queryResults.swap(*subQueryResults);
  
              queryResults.reverse();
          }
          else
          {
              assert(subQueryResults->getDocumentOrder() == true);
  
              queryResults.swap(*subQueryResults);
          }
      }
  }
  
  
  
  XalanNode*
  XPath::stepPattern(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              eMatchScore&            scoreHolder) const
  {
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapPositionType     endStep = currentExpression.getNextOpCodePosition(opPos);
      OpCodeMapValueType              nextStepType = currentExpression.getOpCodeMapValue(endStep);
  
      if(XPathExpression::eENDOP != nextStepType)
      {
          // Continue step via recursion...
          context = stepPattern(
                          executionContext,
                          context,
                          endStep,
                          scoreHolder);
  
          if(0 == context)
          {
              scoreHolder = eMatchScoreNone;
  
          }
  
          if (scoreHolder == eMatchScoreNone)
          {
              // !!!!!!!!!!!!! Big ugly return here !!!!!!!!!!!!!!!!!!!
              return 0;
          }
  
          scoreHolder = eMatchScoreOther;
  
          if (nextStepType != XPathExpression::eMATCH_ANY_ANCESTOR_WITH_FUNCTION_CALL)
          {
              context = DOMServices::getParentOfNode(*context);
          }
  
          if(0 == context)
          {
              // !!!!!!!!!!!!! Big ugly return here !!!!!!!!!!!!!!!!!!!
              return 0;
          }
      }
  
      assert(context != 0);
  
      OpCodeMapValueType  argLen = 0;
  
      eMatchScore         score = eMatchScoreNone;
  
      const OpCodeMapPositionType     startOpPos = opPos;
      const OpCodeMapValueType        stepType =
          currentExpression.getOpCodeMapValue(opPos);
  
      switch(stepType)
      {
      case XPathExpression::eMATCH_ANY_ANCESTOR_WITH_FUNCTION_CALL:
          score = scoreHolder;
          break;
  
      case XPathExpression::eOP_FUNCTION:
          {
              argLen = currentExpression.getOpCodeLengthFromOpMap(opPos,
                                                                  executionContext.getMemoryManager());
  
              const XObjectPtr        obj(executeMore(context, opPos, executionContext));
              assert(obj.get() != 0);
  
              const NodeRefListBase&              nl = obj->nodeset();
  
              const NodeRefListBase::size_type    len = nl.getLength();
  
              if (nextStepType == XPathExpression::eMATCH_ANY_ANCESTOR_WITH_FUNCTION_CALL)
              {
                  bool    fFound = false;
  
                  while(context != 0 && fFound == false)
                  {
                      for(NodeRefListBase::size_type i = 0; i < len; i++)
                      {
                          XalanNode* const    n = nl.item(i);
  
                          if(n == context)
                          {
                              score = eMatchScoreOther;
  
                              context = n;
  
                              fFound = true;
  
                              break;
                          }
                      }
  
                      context = DOMServices::getParentOfNode(*context);
                  }
              }
              else
              {
                  for(NodeRefListBase::size_type i = 0; i < len; i++)
                  {
                      XalanNode* const    n = nl.item(i);
  
                      if(n == context)
                      {
                          score = eMatchScoreOther;
  
                          context = n;
  
                          break;
                      }
                  }
              }
          }
          break;
  
      case XPathExpression::eFROM_ROOT:
          {
              argLen = currentExpression.getOpCodeArgumentLength(opPos);
  
              opPos += 3;
  
              const XalanNode::NodeType   nodeType = context->getNodeType();
  
              if (nodeType == XalanNode::DOCUMENT_NODE ||
                  nodeType == XalanNode::DOCUMENT_FRAGMENT_NODE)
              {
                  score = eMatchScoreOther;
              }
              else
              {
                  const OpCodeMapPositionType     prevPos = currentExpression.getNextOpCodePosition(startOpPos);      
                  const OpCodeMapValueType        prevStepType = currentExpression.getOpCodeMapValue(prevPos);
  
                  if (eMatchScoreNone == score  && 
                      (prevStepType == XPathExpression::eMATCH_ANY_ANCESTOR ||
                       prevStepType == XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE))
                  {
                      const NodeTester    theTester(
                                      *this,
                                      executionContext,
                                      opPos,
                                      argLen,
                                      stepType);
  
                      while(0 != context)
                      {
                          score =
                              theTester(*context, context->getNodeType());
                              assert(score == nodeTest(executionContext, context, context->getNodeType(), opPos, argLen, stepType));
  
                          if(eMatchScoreNone != score)
                              break;
  
                          context = DOMServices::getParentOfNode(*context);
                      }
                  }
              }
          }
          break;
  
      case XPathExpression::eMATCH_ATTRIBUTE:
          {
              argLen = currentExpression.getOpCodeArgumentLength(opPos);
  
              opPos += 3;
  
              score = NodeTester(
                              *this,
                              executionContext,
                              opPos,
                              argLen,
                              XPathExpression::eFROM_ATTRIBUTES)(*context, context->getNodeType());
  
              assert(score == nodeTest(
                               executionContext,
                               context,
                               context->getNodeType(),
                               opPos,
                               argLen,
                               XPathExpression::eFROM_ATTRIBUTES));
          }
          break;
  
      case XPathExpression::eMATCH_ANY_ANCESTOR:
      case XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE:
          {
              argLen = currentExpression.getOpCodeArgumentLength(opPos);
  
              XalanNode::NodeType     nodeType = context->getNodeType();
  
              if(nodeType != XalanNode::ATTRIBUTE_NODE)
              {
                  opPos += 3;
  
                  const NodeTester    theTester(
                                      *this,
                                      executionContext,
                                      opPos,
                                      argLen,
                                      stepType);
  
                  for(;;)
                  {
                      score = theTester(*context, nodeType);
                      assert(score == nodeTest(executionContext, context, nodeType, opPos, argLen, stepType));
  
                      if(eMatchScoreNone != score)
                          break;
  
                      context = DOMServices::getParentOfNode(*context);
  
                      if (context == 0)
                          break;
  
                      nodeType = context->getNodeType();
                  }
              }
          }
          break;
  
      case XPathExpression::eMATCH_IMMEDIATE_ANCESTOR:
          {
              argLen = currentExpression.getOpCodeArgumentLength(opPos);
  
              const XalanNode::NodeType   nodeType = context->getNodeType();
  
              if(nodeType != XalanNode::ATTRIBUTE_NODE)
              {
                  opPos += 3;
  
                  score = NodeTester(
                                  *this,
                                  executionContext,
                                  opPos,
                                  argLen,
                                  XPathExpression::eMATCH_IMMEDIATE_ANCESTOR)(*context, nodeType);
  
                  assert(score == nodeTest(
                                   executionContext,
                                   context,
                                   nodeType,
                                   opPos,
                                   argLen,
                                   XPathExpression::eMATCH_IMMEDIATE_ANCESTOR));
              }
          }
          break;
  
      default:
          {
              const GetCachedString   theGuard1(executionContext);
              const GetCachedString   theGuard2(executionContext);
  
              executionContext.error(
                  XalanMessageLoader::getMessage(
                      theGuard1.get(),
                      XalanMessages::UnknownMatchOpCode_1Param,
                      LongToDOMString(
                          stepType,
                          theGuard2.get())),
                  context,
                  getLocator());
  
              break;
          }
      }
  
      opPos += argLen;
  
      nextStepType = currentExpression.getOpCodeMapValue(opPos);
  
      if(score != eMatchScoreNone &&
         (XPathExpression::eOP_PREDICATE == nextStepType || XPathExpression::eOP_PREDICATE_WITH_POSITION == nextStepType))
      {
          score = eMatchScoreOther;
  
          while(XPathExpression::eOP_PREDICATE == nextStepType ||
                XPathExpression::eOP_PREDICATE_WITH_POSITION == nextStepType)
          {
              // This is a quick hack to look ahead and see if we have
              // number literal as the predicate, i.e. match="foo[1]".
              if (XPathExpression::eOP_PREDICATE_WITH_POSITION == nextStepType)
              {
                  if (m_expression.getOpCodeMapValue(opPos + 2) == XPathExpression::eOP_NUMBERLIT)
                  {
                      score = handleFoundIndexPositional(
                              executionContext,
                              context,
                              startOpPos);
                  }
                  else
                  {
                      score = handleFoundIndex(
                              executionContext,
                              context,
                              startOpPos);
                  }
              }
              else
              {
                  const XObjectPtr    pred(predicate(context, opPos, executionContext));
                  assert(pred.get() != 0);
  
                  if(XObject::eTypeNumber == pred->getType())
                  {
                      score = handleFoundIndex(executionContext, context, startOpPos);
                  }
                  else if(pred->boolean() == false)
                  {
                      score = eMatchScoreNone;
  
                      break;
                  }
              }
  
              opPos = currentExpression.getNextOpCodePosition(opPos);
              nextStepType = currentExpression.getOpCodeMapValue(opPos);
          }
      }
  
      if (scoreHolder == eMatchScoreNone || 
          score == eMatchScoreNone)
      {
          scoreHolder = score;
      }
  
      return score == eMatchScoreNone ? 0 : context;
  }
  
  
  
  XPath::eMatchScore
  XPath::handleFoundIndex(
              XPathExecutionContext&  executionContext,
              XalanNode*              localContext, 
              OpCodeMapPositionType   startOpPos) const
  {
      // We have an index somewhere in our pattern.  So, we have 
      // to do a full search for our step, using the parent as 
      // localContext, then see if the current localContext is found in the 
      // node set.  Seems crazy, but, so far, it seems like the 
      // easiest way.
      XalanNode* const    parentContext =
                  DOMServices::getParentOfNode(*localContext);
  
      if (parentContext == 0)
      {
          return eMatchScoreNone;
      }
      else
      {
          typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
          BorrowReturnMutableNodeRefList  mnl(executionContext);
  
          step(executionContext, parentContext, startOpPos, *mnl);
  
          if (mnl->indexOf(localContext) == MutableNodeRefList::npos)
          {
              return eMatchScoreNone;
          }
          else
          {
              return eMatchScoreOther;
          }
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::handleFoundIndexPositional(
              XPathExecutionContext&  executionContext,
              XalanNode*              localContext,
              OpCodeMapPositionType   startOpPos) const
  {
      XalanNode* const    parentContext =
                  DOMServices::getParentOfNode(*localContext);
  
      if (parentContext == 0)
      {
          return eMatchScoreNone;
      }
      else
      {
          typedef XPathExecutionContext::BorrowReturnMutableNodeRefList   BorrowReturnMutableNodeRefList;
  
          BorrowReturnMutableNodeRefList  mnl(executionContext);
  
          step(executionContext, parentContext, startOpPos, *mnl);
  
          if (mnl->empty() == true)
          {
              return eMatchScoreNone;
          }
          else
          {
              assert(mnl->getLength() == 1 && mnl->item(0) == localContext);
  
              return eMatchScoreOther;
          }
      }
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findNodeSet(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      /* stepType */,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(subQueryResults.empty() == true);
  
      const XObjectPtr    nodesetResult(executeMore(context, opPos, executionContext, subQueryResults));
  
      if (nodesetResult.null() == true)
      {
          assert(subQueryResults.getDocumentOrder());
      }
      else
      {
          subQueryResults.addNodesInDocOrder(nodesetResult->nodeset(), executionContext);
  
          subQueryResults.setDocumentOrder();
      }
  
      return opPos + getExpression().getOpCodeLengthFromOpMap(opPos, executionContext.getMemoryManager());
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findRoot(
              XPathExecutionContext&  /* executionContext */,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      /* stepType */,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(context != 0);
      assert(subQueryResults.empty() == true);
  
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType    argLen =
          currentExpression.getOpCodeArgumentLength(opPos);
  
      XalanNode::NodeType   nodeType =
                  context->getNodeType();
  
      XalanNode*  docContext =
          nodeType == XalanNode::DOCUMENT_NODE ?
              context :
              context->getOwnerDocument();
  
      // This is a special case for RTFs, as the "owner document" is
      // just a factory for the RTF.  Instead, we have to search for
      // the containing XalanDocumentFragment node.
  #if defined(XALAN_OLD_STYLE_CASTS)
      if (((const XalanDocument*)docContext)->getDocumentElement() == 0)
  #else
      if (static_cast<const XalanDocument*>(docContext)->getDocumentElement() == 0)
  #endif
      {
          docContext = context;
  
          for(;;)
          {
              if (nodeType == XalanNode::DOCUMENT_FRAGMENT_NODE)
              {
                  break;
              }
              else
              {
                  docContext =
                      DOMServices::getParentOfNode(*docContext);
                  assert(docContext != 0);
  
                  nodeType = docContext->getNodeType();
  
              }
          }
      }
  
      assert(docContext != 0);
  
      subQueryResults.addNode(docContext);
  
      subQueryResults.setDocumentOrder();
  
      return opPos + argLen + 3;
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findParent(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      stepType,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(subQueryResults.empty() == true);
      assert(context != 0);
  
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType    argLen =
              currentExpression.getOpCodeArgumentLength(opPos);
  
      XalanNode* const    theParent = DOMServices::getParentOfNode(*context);
  
      opPos += 3;
  
      if(0 != theParent)
      {
          if(argLen > 0)
          {
              const NodeTester    theTester(
                              *this,
                              executionContext,
                              opPos,
                              argLen,
                              stepType);
  
              const eMatchScore   score = theTester(*theParent, theParent->getNodeType());
              assert(score == nodeTest(executionContext, theParent, theParent->getNodeType(), opPos, argLen, stepType));
  
              if(eMatchScoreNone != score)
              {
                  subQueryResults.addNode(theParent);
              }
          }
          else
          {
              subQueryResults.addNode(theParent);
          }
      }
  
      subQueryResults.setDocumentOrder();
  
      return opPos + argLen;
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findSelf(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      stepType,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(subQueryResults.empty() == true);
      assert(context != 0);
  
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType    argLen =
          currentExpression.getOpCodeArgumentLength(opPos);
  
      opPos += 3;
  
      if(argLen == 0)
      {
          subQueryResults.addNode(context);
      }
      else
      {
          const NodeTester    theTester(
                          *this,
                          executionContext,
                          opPos,
                          argLen,
                          stepType);
  
          const eMatchScore   score =
              theTester(*context, context->getNodeType());
              assert(score == nodeTest(executionContext, context, context->getNodeType(), opPos, argLen, stepType));
  
          if(eMatchScoreNone != score)
          {
              subQueryResults.addNode(context);
          }
      }
  
      subQueryResults.setDocumentOrder();
  
      return opPos + argLen;
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findAncestors(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      stepType,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(subQueryResults.empty() == true);
      assert(context != 0);
  
      context = DOMServices::getParentOfNode(*context);
  
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType    argLen =
              currentExpression.getOpCodeArgumentLength(opPos);
  
      opPos += 3;
  
      if (context != 0)
      {
          const NodeTester    theTester(
                          *this,
                          executionContext,
                          opPos,
                          argLen,
                          stepType);
  
          do
          {
              const eMatchScore   score =
                  theTester(*context, context->getNodeType());
                  assert(score == nodeTest(executionContext, context, context->getNodeType(), opPos, argLen, stepType));
  
              if(eMatchScoreNone != score)
              {
                  subQueryResults.addNode(context);
              }
  
              context = DOMServices::getParentOfNode(*context);
          } while(0 != context);
      }
  
      subQueryResults.setReverseDocumentOrder();
  
      return opPos + argLen;
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findAncestorsOrSelf(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      stepType,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(subQueryResults.empty() == true);
      assert(context != 0);
  
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType    argLen =
          currentExpression.getOpCodeArgumentLength(opPos);
  
      opPos += 3;
  
      const NodeTester    theTester(
                      *this,
                      executionContext,
                      opPos,
                      argLen,
                      stepType);
  
      do
      {
          const eMatchScore   score =
                  theTester(*context, context->getNodeType());
                  assert(score == nodeTest(executionContext, context, context->getNodeType(), opPos, argLen, stepType));
  
          if(eMatchScoreNone != score)
          {
              subQueryResults.addNode(context);
          }
  
          context = DOMServices::getParentOfNode(*context);
      } while(0 != context);
  
      subQueryResults.setReverseDocumentOrder();
  
      return opPos + argLen;
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findAttributes(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      stepType,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(subQueryResults.empty() == true);
      assert(context != 0);
  
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType    argLen =
                  currentExpression.getOpCodeArgumentLength(opPos);
  
      opPos += 3;
  
      if(context->getNodeType() == XalanNode::ELEMENT_NODE)
      {
          const XalanNamedNodeMap* const  attributeList = context->getAttributes();
  
          if(attributeList != 0) 
          {
              const unsigned int  nAttrs = attributeList->getLength();
  
              if (nAttrs != 0)
              {
                  const NodeTester    theTester(
                                  *this,
                                  executionContext,
                                  opPos,
                                  argLen,
                                  stepType);
  
                  for(unsigned int j = 0; j < nAttrs; j++)
                  {
                      XalanNode* const    theNode = attributeList->item(j);
                      assert(theNode != 0 && theNode->getNodeType() == XalanNode::ATTRIBUTE_NODE);
  
                      const eMatchScore   score =
                          theTester(*theNode, XalanNode::ATTRIBUTE_NODE);
                          assert(score == nodeTest(executionContext, theNode, XalanNode::ATTRIBUTE_NODE, opPos, argLen, stepType));
  
                      if(eMatchScoreNone != score)
                      {
                          subQueryResults.addNode(theNode);
                      }
                  }
              }
          }
      }
  
      subQueryResults.setDocumentOrder();
  
      return opPos + argLen;
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findChildren(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      stepType,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(subQueryResults.empty() == true);
      assert(context != 0);
  
      XalanNode*  child = context->getFirstChild();
  
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType    argLen =
          currentExpression.getOpCodeArgumentLength(opPos);
  
      opPos += 3;
  
      if (child != 0)
      {
          const NodeTester    theTester(
                          *this,
                          executionContext,
                          opPos,
                          argLen,
                          stepType);
  
          do
          {
              const eMatchScore   score =
                      theTester(*child, child->getNodeType());
                      assert(score == nodeTest(executionContext, child, child->getNodeType(), opPos, argLen, stepType));
  
              if(eMatchScoreNone != score)
              {
                  subQueryResults.addNode(child);
              }
  
              child = child->getNextSibling();
          } while(0 != child);
      }
  
      subQueryResults.setDocumentOrder();
  
      return opPos + argLen;
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findDescendants(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      stepType,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(subQueryResults.empty() == true);
      assert(context != 0);
  
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType    argLen =
          currentExpression.getOpCodeArgumentLength(opPos);
  
      // Perform a pre-order traversal of descendents...
      XalanNode*  pos = context;
  
      opPos += 3;
  
      const NodeTester    theTester(
                          *this,
                          executionContext,
                          opPos,
                          argLen,
                          stepType);
  
      do
      {                   
          if(stepType == XPathExpression::eFROM_DESCENDANTS_OR_SELF ||
             context != pos)
          {
              const eMatchScore   score =
                  theTester(*pos, pos->getNodeType());
                  assert(score == nodeTest(executionContext, pos, pos->getNodeType(), opPos, argLen, stepType));
  
              if(score != eMatchScoreNone)
              {
                  subQueryResults.addNode(pos);
              }
          }
  
          XalanNode*  nextNode = pos->getFirstChild();
  
          while(0 == nextNode)
          {
              if(context == pos)
                  break;
  
              nextNode = pos->getNextSibling();
  
              if(0 == nextNode)
              {
                  pos = DOMServices::getParentOfNode(*pos);
  
                  if(context == pos || pos == 0)
                  {
                      nextNode = 0;
                      break;
                  }
              }
          }
  
          pos = nextNode;
      } while(0 != pos);
  
      subQueryResults.setDocumentOrder();
  
      return opPos + argLen;
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findFollowing(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      stepType,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(subQueryResults.empty() == true);
      assert(context != 0);
  
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType    argLen =
          currentExpression.getOpCodeArgumentLength(opPos);
  
      opPos += 3;
  
      // What fun...
      XalanDocument* const    doc = context->getOwnerDocument();
  
      XalanNode*              pos = context;
  
      const NodeTester    theTester(
                      *this,
                      executionContext,
                      opPos,
                      argLen,
                      stepType);
  
      while(0 != pos)
      {
          XalanNode*  nextNode = 0;
  
          if(pos != context)
          {
              const eMatchScore   score =
                  theTester(*pos, pos->getNodeType());
                  assert(score == nodeTest(executionContext, pos, pos->getNodeType(), opPos, argLen, stepType));
  
              if(eMatchScoreNone != score)
              {
                  subQueryResults.addNodeInDocOrder(pos, executionContext);
              }
  
              nextNode = pos->getFirstChild();
          }
          else
          {
              nextNode = 0;
          }
  
          while(0 == nextNode)
          {
              // This requires some explanation.  pos could be an attribute
              // node, so getNextSibling() will always return 0.  In that
              // case, I want to continue the search with the first child of
              // the owner element, as if attribute nodes are children which
              // are always _before_ the first child element.  I don't have to
              // consider following attributes, since they _never_ match the
              // following axis.
              if (pos->getNodeType() == XalanNode::ATTRIBUTE_NODE)
              {
                  assert(DOMServices::getParentOfNode(*pos) != 0);
  
                  nextNode = DOMServices::getParentOfNode(*pos)->getFirstChild();
              }
              else
              {
                  nextNode = pos->getNextSibling();
              }
  
              if(0 == nextNode)
              {
                  pos = DOMServices::getParentOfNode(*pos);
  
                  if(doc == pos || 0 == pos)
                  {
                      nextNode = 0;
  
                      break;
                  }
              }
          }
  
          pos = nextNode;
      }
  
      subQueryResults.setDocumentOrder();
  
      return opPos + argLen;
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findFollowingSiblings(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      stepType,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(subQueryResults.empty() == true);
      assert(context != 0);
  
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType    argLen =
          currentExpression.getOpCodeArgumentLength(opPos);
  
      XalanNode*  pos = context->getNextSibling();
  
      opPos += 3;
  
      if (pos != 0)
      {
          const NodeTester    theTester(
                          *this,
                          executionContext,
                          opPos,
                          argLen,
                          stepType);
  
          do
          {
              const eMatchScore   score =
                      theTester(*pos, pos->getNodeType());
                      assert(score == nodeTest(executionContext, pos, pos->getNodeType(), opPos, argLen, stepType));
  
              if(eMatchScoreNone != score)
              {
                  subQueryResults.addNode(pos);
              }
  
              pos = pos->getNextSibling();
          } while(0 != pos);
      }
  
      subQueryResults.setDocumentOrder();
  
      return opPos + argLen;
  }
  
  
  
  /*
   * This is bit of a hack to figure out where we should start for
   * the preceeding axis.  It's mostly to support RTFs which have
   * been coerced to nodesets through the nodeset() extension function.
   */
  static XalanNode*
  findTopNode(
              XalanNode*              context,
              XalanNode::NodeType     theType)
  {
      assert(context != 0);
  
      if (theType == XalanNode::DOCUMENT_NODE)
      {
          return context;
      }
      else
      {
          XalanDocument* const    theDocument = context->getOwnerDocument();
          assert(theDocument != 0);
  
          if (theDocument->getDocumentElement() != 0)
          {
              return theDocument;
          }
          else
          {
              XalanNode*  theNode = 0;
  
              while(context != 0 &&
                    context->getNodeType() != XalanNode::DOCUMENT_NODE)
              {
                  theNode = context;
  
                  context = DOMServices::getParentOfNode(*context);
              }
  
              assert(theNode != 0);
  
              return theNode;
          }
      }
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findPreceeding(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      stepType,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(subQueryResults.empty() == true);
      assert(context != 0);
  
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType    argLen =
          currentExpression.getOpCodeArgumentLength(opPos);
  
      opPos += 3;
  
      // Ugh.  Reverse document order, no parents, I guess.
      const XalanNode::NodeType   theType = context->getNodeType();
  
      XalanNode* const    topNode = findTopNode(context, theType);
  
      XalanNode*          pos = topNode;
  
      // If the context node is an attribute, we need to perform some
      // magic to stop the search at the appropriate point, which is when
      // we arrive back at the parent.
      const bool              contextIsAttribute =
              theType == XalanNode::ATTRIBUTE_NODE ? true : false;
  
      const XalanNode* const  theAttributeContextParent =
          contextIsAttribute == true ? DOMServices::getParentOfNode(*context) : 0;
  
      const NodeTester    theTester(
                          *this,
                          executionContext,
                          opPos,
                          argLen,
                          stepType);
  
      while(0 != pos)
      {
          if(context == pos)
          {
              break;
          }
  
          const eMatchScore   score =
                  theTester(*pos, pos->getNodeType());
                  assert(score == nodeTest(executionContext, pos, pos->getNodeType(), opPos, argLen, stepType));
  
          if(eMatchScoreNone != score)
          {
              // Ugh. If I could think a little better tonight, I'm
              // sure there's a better way to check for the parent.
              bool        isParent = false;
  
              XalanNode*  parent = DOMServices::getParentOfNode(*context);
  
              while(0 != parent)
              {
                  if(parent == pos)
                  {
                      isParent = true;
                      break;
                  }
  
                  parent = DOMServices::getParentOfNode(*parent);
              }
  
              if(isParent == false)
              {
                  subQueryResults.addNode(pos);
              }
          }
  
          XalanNode*  nextNode = 0;
  
          // Check to see if we're back at the attribute context node's
          // parent, in which case, we should stop.
          if (contextIsAttribute == true &&
              pos == theAttributeContextParent)
          {
              nextNode = context;
          }
          else
          {
              nextNode = pos->getFirstChild();
          }
  
          while(0 == nextNode)
          {
              nextNode = pos->getNextSibling();
  
              if(0 == nextNode)
              {
                  pos = DOMServices::getParentOfNode(*pos);
  
                  if(topNode == pos)
                  {
                      nextNode = 0;
                      break;
                  }
              }
          }
  
          pos = nextNode;
      }
  
      // Now, reverse the order of the nodes, since
      // preceeding is a reverse axis, and we searched
      // the document from the root to this node.
      subQueryResults.reverse();
  
      subQueryResults.setReverseDocumentOrder();
  
      return opPos + argLen;
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findPreceedingSiblings(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      stepType,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(subQueryResults.empty() == true);
      assert(context != 0);
  
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType    argLen =
          currentExpression.getOpCodeArgumentLength(opPos);
  
      opPos += 3;
  
  #if 1
      XalanNode*  pos = context->getPreviousSibling();
  
      if (pos != 0)
      {
          const NodeTester    theTester(
                          *this,
                          executionContext,
                          opPos,
                          argLen,
                          stepType);
  
          do
          {
              const eMatchScore   score = 
                  theTester(*pos, pos->getNodeType());
                  assert(score == nodeTest(executionContext, pos, pos->getNodeType(), opPos, argLen, stepType));
  
              if(eMatchScoreNone != score)
              {
                  subQueryResults.addNode(pos);
              }
  
              pos = pos->getPreviousSibling();
          } while(0 != pos);
      }
  #else
      // This is some experimental code which avoids using getPreviousSibling(), with the idea that we
      // could reduce our in-memory representation size by not keeping the previous sibling node.
      XalanNode*  pos = context->getParentNode();
  
      if (pos != 0)
      {
          pos = pos->getFirstChild();
  
          if (pos != context)
          {
              const NodeTester    theTester(
                              *this,
                              executionContext,
                              opPos,
                              argLen,
                              stepType);
  
              do
              {
                  const eMatchScore   score = 
                      theTester(*pos, pos->getNodeType());
                      assert(score == nodeTest(executionContext, pos, pos->getNodeType(), opPos, argLen, stepType));
  
                  if(eMatchScoreNone != score)
                  {
                      subQueryResults.addNode(pos);
                  }
  
                  pos = pos->getNextSibling();
              } while(pos != context);
          }
  
          // Now, reverse the order of the nodes, since
          // preceeding-sibling is a reverse axis, and we searched
          // the document from the root to this node.
          subQueryResults.reverse();
      }
  #endif
  
      subQueryResults.setReverseDocumentOrder();
  
      return opPos + argLen;
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findNamespace(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      stepType,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(subQueryResults.empty() == true);
      assert(context != 0);
  
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType    argLen =
          currentExpression.getOpCodeArgumentLength(opPos);
  
      opPos += 3;
  
      if(context->getNodeType() == XalanNode::ELEMENT_NODE)
      {
          // Look up the element chain until we hit the document, so that we
          // get all of the attribute/namespace nodes.
          const XalanNode* const  theOwnerDocument = context->getOwnerDocument();
          assert(theOwnerDocument != 0);
  
          const XalanNode*        theCurrentNode = context;
  
          const NodeTester    theTester(
                          *this,
                          executionContext,
                          opPos,
                          argLen,
                          stepType);
  
          NodeRefListBase::size_type  nNSFound = 0;
          bool                        defaultNSFound = false;
  
          do
          {
              const XalanNamedNodeMap* const  attributeList =
                  theCurrentNode->getAttributes();
  
              if(attributeList != 0) 
              {
                  unsigned int    nAttrs = attributeList->getLength();
  
                  while(nAttrs > 0)
                  {
                      --nAttrs;
  
                      XalanNode* const    attr = attributeList->item(nAttrs);
                      assert(attr != 0 && attr->getNodeType() == XalanNode::ATTRIBUTE_NODE);
  
                      const XalanDOMString&   theNodeName = attr->getNodeName();
  
                      // This is an optimization to keep non-namespace attributes out of
                      // the call to nodeTest().
                      if (startsWith(theNodeName, DOMServices::s_XMLNamespaceWithSeparator) == true ||
                          theNodeName == DOMServices::s_XMLNamespace)
                      {
                          const eMatchScore   score =
                              theTester(*attr, XalanNode::ATTRIBUTE_NODE);
                              assert(score == nodeTest(executionContext, attr, XalanNode::ATTRIBUTE_NODE, opPos, argLen, stepType));
  
                          if(score != eMatchScoreNone)
                          {
                              const XalanDOMString&   theNodeValue = attr->getNodeValue();
  
                              bool            foundNSMatch = false;
   
                              // Need to check default NS slightly differently
                              if (theNodeName == DOMServices::s_XMLNamespace)
                              {
                                  // If namespace is empty, don't add anything
                                  // as under XPath an empty default is indicated
                                  // by no node.
   
                                  foundNSMatch = defaultNSFound ||
                                      (theNodeValue == DOMServices::s_emptyString);
                                  defaultNSFound = true;
                              }
   
                              for (NodeRefListBase::size_type lstIndex = 0; 
                                   foundNSMatch == false && lstIndex < nNSFound;
                                   ++lstIndex)
                              {
                                  if (subQueryResults.item(lstIndex)->getNodeName() == theNodeName)
                                  {
                                      foundNSMatch = true;
                                  }
                              }
  
                              if (foundNSMatch == false) 
                              {
                                  subQueryResults.addNode(attr);
                                  ++nNSFound;
                              }
                          }
                      }
                  }
              }
  
              theCurrentNode = theCurrentNode->getParentNode();
          } while (theCurrentNode != theOwnerDocument && theCurrentNode != 0);
      }
  
      subQueryResults.reverse();
  
      subQueryResults.setDocumentOrder();
  
      return opPos + argLen;
  }
  
  
  
  XPath::OpCodeMapPositionType
  XPath::findNodesOnUnknownAxis(
              XPathExecutionContext&  executionContext,
              XalanNode*              context, 
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      stepType,
              MutableNodeRefList&     /* subQueryResults */) const
  {
      const XPathExpression&  currentExpression = getExpression();
  
      const OpCodeMapValueType    argLen =
          currentExpression.getOpCodeArgumentLength(opPos);
  
      const GetCachedString   theGuard1(executionContext);
      const GetCachedString   theGuard2(executionContext);
  
      executionContext.error(
              XalanMessageLoader::getMessage(
                  theGuard1.get(),
                  XalanMessages::UnknownAxis_1Param,
                  LongToDOMString(
                      stepType,
                      theGuard2.get())),
              context,
              getLocator());
  
      return opPos + argLen + 3;
  }
  
  
  
  #if !defined(NDEBUG)
  XPath::eMatchScore
  XPath::nodeTest(
              XPathExecutionContext&  executionContext,
              XalanNode*              context,
              XalanNode::NodeType     nodeType,
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      argLen,
              OpCodeMapValueType      stepType) const
  {
      assert(context->getNodeType() == nodeType);
  
      const XPathExpression&  currentExpression = getExpression();
  
      eMatchScore     score = eMatchScoreNone;
  
      const OpCodeMapValueType    testType = currentExpression.getOpCodeMapValue(opPos);
  
      switch(testType)
      {
      case XPathExpression::eNODETYPE_COMMENT:
          if (XalanNode::COMMENT_NODE == nodeType)
          {
              score = eMatchScoreNodeTest;
          }
          break;
  
      case XPathExpression::eNODETYPE_TEXT:
          if ((XalanNode::CDATA_SECTION_NODE == nodeType ||
               XalanNode::TEXT_NODE == nodeType) &&
  #if defined(XALAN_OLD_STYLE_CASTS)
              executionContext.shouldStripSourceNode((const XalanText&)*context) == false)
  #else
              executionContext.shouldStripSourceNode(static_cast<const XalanText&>(*context)) == false)
  #endif          
          {
                score = eMatchScoreNodeTest;
          }
        break;
  
      case XPathExpression::eNODETYPE_PI:
          if(XalanNode::PROCESSING_INSTRUCTION_NODE == nodeType)
          {
              if(argLen == 1)
              {
                  score = eMatchScoreNodeTest;
              }
              else if(argLen == 2)
              {
                  opPos++;
  
                  const OpCodeMapValueType    tokenPosition =
                      currentExpression.getOpCodeMapValue(opPos);
  
                  const XObject* const    name =
                      currentExpression.getToken(tokenPosition);
                  assert(name != 0);
  
                  if (context->getNodeName() == name->str())
                  {
                      score = eMatchScoreQName;
                  }
              }
              else
              {
                  XalanDOMString  theBuffer(executionContext.getMemoryManager());
  
                  executionContext.error(
                      XalanMessageLoader::getMessage(
                          theBuffer,
                          XalanMessages::ArgLengthNodeTestIsIncorrect_1Param, 
                          "processing-instruction()"),
                      context,
                      getLocator());
              }
          }
  
          break;
  
      case XPathExpression::eNODETYPE_NODE:
          if (nodeType == XalanNode::CDATA_SECTION_NODE ||
              nodeType == XalanNode::TEXT_NODE)
          {
  #if defined(XALAN_OLD_STYLE_CASTS)
              if (executionContext.shouldStripSourceNode((const XalanText&)*context) == false)
  #else
              if (executionContext.shouldStripSourceNode(static_cast<const XalanText&>(*context)) == false)
  #endif
              {
                  score = eMatchScoreNodeTest;
              }
          }
          else
          {
              score = eMatchScoreNodeTest;
          }
          break;
  
      case XPathExpression::eNODETYPE_ROOT:
          if (XalanNode::DOCUMENT_FRAGMENT_NODE == nodeType ||
              XalanNode::DOCUMENT_NODE == nodeType)
          {
              score =  eMatchScoreOther;
          }
          break;
  
      case XPathExpression::eNODENAME:
          {
              opPos++;
  
              if (nodeType == XalanNode::ATTRIBUTE_NODE || nodeType == XalanNode::ELEMENT_NODE)
              {
                  bool                    test = false;
  
                  OpCodeMapValueType      queueIndex = currentExpression.getOpCodeMapValue(opPos);
                  assert(queueIndex == XPathExpression::eEMPTY ||
                         queueIndex < currentExpression.tokenQueueSize());
  
                  const XalanDOMString&   targetNS = queueIndex != XPathExpression::eEMPTY ?
                                          currentExpression.getToken(queueIndex)->str() :
                                              s_emptyString;
  
                  opPos++;
  
                  // From the draft: "Two expanded names are equal if they 
                  // have the same local part, and either both have no URI or 
                  // both have the same URI."
                  // "A node test * is true for any node of the principal node type. 
                  // For example, child::* will select all element children of the 
                  // context node, and attribute::* will select all attributes of 
                  // the context node."
                  // "A node test can have the form NCName:*. In this case, the prefix 
                  // is expanded in the same way as with a QName using the context 
                  // namespace declarations. The node test will be true for any node 
                  // of the principal type whose expanded name has the URI to which 
                  // the prefix expands, regardless of the local part of the name."
                  const bool  isTotallyWild =
                              0 == length(targetNS) &&
                              currentExpression.getOpCodeMapValue(opPos) == XPathExpression::eELEMWILDCARD;
  
                  bool        didMatchNS = false;
  
                  if(isTotallyWild == false)
                  {
                      const XalanDOMString&   contextNS = DOMServices::getNamespaceOfNode(*context);
  
                      if(0 != length(targetNS) && 0 != length(contextNS))
                      {
                          test = contextNS == targetNS;
  
                          didMatchNS = true;
                      }
                      else
                      {
                          test = XPathExpression::eELEMWILDCARD == queueIndex || 
                             (0 == length(contextNS) && 0 == length(targetNS));
                      }
                  }
                  else
                  {
                      test = true;
                  }
  
                  queueIndex = currentExpression.getOpCodeMapValue(opPos);
  
                  if(test == true)
                  {
                      switch(nodeType)
                      {
                      case XalanNode::ATTRIBUTE_NODE:
                          if(stepType == XPathExpression::eFROM_ATTRIBUTES ||
                              stepType == XPathExpression::eFROM_NAMESPACE)
                          {
                              assert(context->getNodeType() == XalanNode::ATTRIBUTE_NODE);
  
                              const XalanDOMString&   attrName =
                                          context->getNodeName();
  
                              const bool              isNamespace =
                                      startsWith(attrName, DOMServices::s_XMLNamespaceWithSeparator) ||
                                      attrName == DOMServices::s_XMLNamespace;
  
                              if(XPathExpression::eELEMWILDCARD == queueIndex)
                              {
                                  if(stepType == XPathExpression::eFROM_ATTRIBUTES)
                                  {
                                      if (isNamespace == false)
                                      {
                                          if (isTotallyWild == true)
                                          {
                                              score = eMatchScoreNodeTest;
                                          }
                                          else
                                          {
                                              score = eMatchScoreNSWild;
                                          }
                                      }
                                  }
                                  else
                                  {
                                      if (isNamespace == true)
                                      {
                                          score = eMatchScoreNodeTest;
                                      }
                                  }
                              }
                              else
                              {
                                  if(stepType == XPathExpression::eFROM_ATTRIBUTES)
                                  {
                                      if (isNamespace == false)
                                      {
                                          assert(queueIndex >= 0);
  
                                          const XalanDOMString&   targetLocalName =
                                                              currentExpression.getToken(queueIndex)->str();
  
                                          const XalanDOMString&   localAttrName =
                                                  DOMServices::getLocalNameOfNode(*context);
  
                                          if (localAttrName == targetLocalName)
                                          {
                                              score = eMatchScoreQName;
                                          }
                                      }
                                  }
                                  else
                                  {
                                      if (isNamespace == true)
                                      {
                                          const XalanAttr* const  theAttrNode =
  #if defined(XALAN_OLD_STYLE_CASTS)
                                              (const XalanAttr*)context;
  #else
                                              static_cast<const XalanAttr*>(context);
  #endif
                                          assert(theAttrNode != 0);
  
                                          const XalanDOMString&   theNamespace =
                                                      theAttrNode->getLocalName();
  
                                          assert(queueIndex >= 0);
  
                                          const XalanDOMString&   targetLocalName =
                                                              currentExpression.getToken(queueIndex)->str();
  
                                          if (theNamespace == targetLocalName)
                                          {
                                              score = eMatchScoreQName;
                                          }
                                      }
                                  }
                              }
                          }
                          break;
  
                      case XalanNode::ELEMENT_NODE:
                          if(stepType != XPathExpression::eFROM_ATTRIBUTES)
                          {
                              if(XPathExpression::eELEMWILDCARD == queueIndex)
                              {
                                  score = didMatchNS == true ?
                                      eMatchScoreNSWild : eMatchScoreNodeTest;
                              }
                              else
                              {
                                  assert(queueIndex >= 0);
  
                                  const XalanDOMString&   targetLocalName =
                                                              currentExpression.getToken(queueIndex)->str();
  
                                  if (DOMServices::getLocalNameOfNode(*context) == targetLocalName)
                                  {
                                      score = eMatchScoreQName;
                                  }
                              }
                          }
                          break;
  
                      default:
                          // Trying to match on anything else causes nasty bugs.
                          break;
                      } // end switch(nodeType)
                  } // end if(test)
              } // end if (nodeType == XalanNode::ATTRIBUTE_NODE || nodeType == XalanNode::ELEMENT_NODE)
          } // end case XPathExpression::eNODENAME
          break;
  
      default:
          break;
      } // end switch(testType)
  
      return score;
  }
  #endif  // !defined(NDEBUG)
  
  
  
  XPath::OpCodeMapPositionType
  XPath::predicates(
              XPathExecutionContext&  executionContext,
              OpCodeMapPositionType   opPos,
              MutableNodeRefList&     subQueryResults) const
  {
      assert(&executionContext.getContextNodeList() == &subQueryResults);
  
      const XPathExpression&  currentExpression = getExpression();
  
      assert(currentExpression.getOpCodeMapValue(opPos) == XPathExpression::eOP_PREDICATE ||
             currentExpression.getOpCodeMapValue(opPos) == XPathExpression::eOP_PREDICATE_WITH_POSITION);
  
      NodeRefListBase::size_type  theLength = subQueryResults.getLength();
  
      for(;;)
      {
          // If we have no nodes left, then there's no point in executing any
          // predicates.  However, we will continue to loop, since we need to
          // update endPredicatePos.
          if (theLength > 0)
          {
              const OpCodeMapPositionType predOpPos = opPos + 2;
  
              // OK, this is a huge hack/optimization.  If the predicate is
              // simple a number, such as [2], we can just get the
              // numeric value from the expression, and not bother executing
              // the predicate.  Furthermore, we don't need to execute the
              // predicate for each node, since the evaluation is no dependent
              // on the context node.  All we really have to do is remove all
              // nodes from subQueryResults, _except_ for the node at that
              // position.  The only trick is that XPath indexes from 1, while
              // our node lists index from 0.
              if (m_expression.getOpCodeMapValue(predOpPos) == XPathExpression::eOP_NUMBERLIT)
              {
                  assert(m_expression.tokenQueueSize() > m_expression.getOpCodeMapValue(predOpPos + 3));
  
                  // Get the value of the number...
                  const double    theIndex =
                      m_expression.getNumberLiteral(m_expression.getOpCodeMapValue(predOpPos + 2));
  
                  // If the index is out of range, or not an integer, just clear subQueryResults...
                  if (theIndex <= 0.0 ||
                      NodeRefListBase::size_type(theIndex) > theLength ||
                      double(NodeRefListBase::size_type(theIndex)) != theIndex)
                  {
                      subQueryResults.clear();
                  }
                  else if (theLength > 1)
                  {
                      // Save the matching node...
                      XalanNode* const    theNode =
                          subQueryResults.item(NodeRefListBase::size_type(theIndex) - 1);
  
                      // Clear the list...
                      subQueryResults.clear();
  
                      // Add the node back in...
                      subQueryResults.addNode(theNode);
  
                      subQueryResults.setDocumentOrder();
                  }
                  else
                  {
                      // OK, if there's only 1 node in the list, then
                      // we don't need to bother modifying the list.
                      // Just assert that theIndex == 1.0...
                      assert(theIndex == 1.0);
                  }
              }
              else
              {
                  for(NodeRefListBase::size_type i = 0; i < theLength; ++i)
                  {
                      XalanNode* const    theNode = subQueryResults.item(i);
                      assert(theNode != 0);
  
                      const XObjectPtr        pred(predicate(theNode, opPos, executionContext));
                      assert(pred.get() != 0);
  
                      // Remove any node that doesn't satisfy the predicate.
                      if((XObject::eTypeNumber == pred->getType() && i + 1 != pred->num()) ||
                         pred->boolean() == false)
                      {
                          // Set the node to 0.  After we're done,
                          // we'll clear it out.
                          subQueryResults.setNode(i, 0);
                      }
                  }
  
                  // Clear out any null entries...
                  subQueryResults.clearNulls();
              }
          }
  
          opPos = currentExpression.getNextOpCodePosition(opPos);
  
          const OpCodeMapValueType    nextStepType = currentExpression.getOpCodeMapValue(opPos);
  
          if (nextStepType != XPathExpression::eOP_PREDICATE &&
              nextStepType != XPathExpression::eOP_PREDICATE_WITH_POSITION)
          {
              break;
          }
          else
          {
              theLength = subQueryResults.getLength();
          }
      }
  
      return opPos;
  }
  
  
  
  XPath::NodeTester::NodeTester(const NodeTester&     theSource) :
      m_executionContext(theSource.m_executionContext),
      m_targetNamespace(theSource.m_targetNamespace),
      m_targetLocalName(theSource.m_targetLocalName),
      m_testFunction(theSource.m_testFunction),
      m_testFunction2(theSource.m_testFunction2)
  {
  }
  
  
  
  XPath::NodeTester::NodeTester(
              const XPath&            xpath,
              XPathExecutionContext&  executionContext,
              OpCodeMapPositionType   opPos,
              OpCodeMapValueType      argLen,
              OpCodeMapValueType      stepType) :
      m_executionContext(&executionContext),
      m_targetNamespace(0),
      m_targetLocalName(0),
      m_testFunction(0),
      m_testFunction2(&NodeTester::testDefault2)
  {
      const XPathExpression&  theExpression = xpath.getExpression();
  
      switch(theExpression.getOpCodeMapValue(opPos))
      {
      case XPathExpression::eNODETYPE_COMMENT:
          m_testFunction = &NodeTester::testComment;
          break;
  
      case XPathExpression::eNODETYPE_TEXT:
          m_testFunction = &NodeTester::testText;
          break;
  
      case XPathExpression::eNODETYPE_PI:
          if (argLen == 1)
          {
              m_testFunction = &NodeTester::testPI;
          }
          else if(argLen == 2)
          {
              m_testFunction = &NodeTester::testPIName;
  
              m_targetLocalName = getStringFromTokenQueue(
                  theExpression,
                  opPos + 1);
          }
          else
          {
              GetCachedString     theGuard(executionContext);
  
              executionContext.error(
                  XalanMessageLoader::getMessage(
                      theGuard.get(),
                      XalanMessages::ArgLengthNodeTestIsIncorrect_1Param,
                      "processing-instruction()"),
                  0,
                  xpath.getLocator());
          }
          break;
  
      case XPathExpression::eNODETYPE_NODE:
          m_testFunction = &NodeTester::testNode;
          break;
  
      case XPathExpression::eNODETYPE_ROOT:
          m_testFunction = &NodeTester::testRoot;
          break;
  
      case XPathExpression::eNODENAME:
          {
              bool    isTotallyWild = false;
  
              m_targetNamespace = getStringFromTokenQueue(
                      theExpression,
                      opPos + 1);
  
              if (m_targetNamespace == 0 &&
                  theExpression.getOpCodeMapValue(opPos + 2) == XPathExpression::eELEMWILDCARD)
              {
                  isTotallyWild = true;
              }
              else
              {
                  m_targetLocalName = getStringFromTokenQueue(
                      theExpression,
                      opPos + 2);
              }
  
              if(stepType == XPathExpression::eFROM_ATTRIBUTES)
              {
                  if (isTotallyWild == true)
                  {
                      m_testFunction = &NodeTester::testAttributeTotallyWild;
                  }
                  else if (m_targetNamespace == 0)
                  {
                      assert(m_targetLocalName != 0);
  
                      m_testFunction = &NodeTester::testAttributeNCName;
                  }
                  else if (m_targetLocalName == 0)
                  {
                      assert(m_targetNamespace != 0);
  
                      m_testFunction = &NodeTester::testAttributeNamespaceOnly;
                  }
                  else
                  {
                      assert(m_targetNamespace != 0 && m_targetLocalName != 0);
  
  
                      m_testFunction = &NodeTester::testAttributeQName;
                  }
              }
              else if (stepType == XPathExpression::eFROM_NAMESPACE)
              {
                  if (isTotallyWild == true)
                  {
                      m_testFunction = &NodeTester::testNamespaceTotallyWild;
                  }
                  else
                  {
                      m_testFunction = &NodeTester::testNamespaceNCName;
                  }
              }
              else
              {
                  if (isTotallyWild == true)
                  {
                      m_testFunction = &NodeTester::testElementTotallyWild;
                  }
                  else if (m_targetNamespace == 0)
                  {
                      m_testFunction = &NodeTester::testElementNCName;
                  }
                  else if (m_targetLocalName == 0)
                  {
                      assert(m_targetNamespace != 0);
  
                      m_testFunction = &NodeTester::testElementNamespaceOnly;
                  }
                  else
                  {
                      assert(m_targetNamespace != 0 && m_targetLocalName != 0);
  
                      m_testFunction = &NodeTester::testElementQName;
                  }
              }
          }
          break;
  
      default:
          m_testFunction = &NodeTester::testDefault;
          break;
      }
  
      assert(m_testFunction != 0);
  }
  
  
  
  XPath::NodeTester::NodeTester() :
      m_executionContext(0),
      m_targetNamespace(0),
      m_targetLocalName(0),
      m_testFunction(&NodeTester::testDefault),
      m_testFunction2(&NodeTester::testDefault2)
  {
  }
  
  
  
  XPath::NodeTester::NodeTester(
              XPathConstructionContext&   theConstructionContext,
              const XalanDOMString&       theNameTest,
              const PrefixResolver&       thePrefixResolver,
              const LocatorType*          theLocator,
              eMatchScore*                theMatchScore) :
      m_executionContext(0),
      m_targetNamespace(0),
      m_targetLocalName(0),
      m_testFunction(&NodeTester::testDefault),
      m_testFunction2(&NodeTester::testDefault2)
  {
      const eMatchScore   theScore =
          initialize(
              theConstructionContext,
              theNameTest,
              thePrefixResolver,
              theLocator);
  
      if (theMatchScore != 0)
      {
          *theMatchScore = theScore;
      }
  }
      
  
  
  XPath::NodeTester::NodeTester(
              const XalanDOMString&   theNamespaceURI,
              const XalanDOMString&   theLocalName,
              eMatchScore*            theMatchScore) :
      m_executionContext(0),
      m_targetNamespace(0),
      m_targetLocalName(0),
      m_testFunction(&NodeTester::testDefault),
      m_testFunction2(0)
  {
      const eMatchScore   theScore =
          initialize(theNamespaceURI, theLocalName);
  
      if (theMatchScore != 0)
      {
          *theMatchScore = theScore;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::initialize(
              XPathConstructionContext&   theConstructionContext,
              const XalanDOMString&       theNameTest,
              const PrefixResolver&       thePrefixResolver,
              const LocatorType*          theLocator)
  {
      const XalanDOMString::size_type     theLength =
                  length(theNameTest);
  
      if (theLength == 1 && theNameTest[0] == XPath::PSEUDONAME_ANY[0])
      {
          return initialize(s_emptyString, s_emptyString);
      }
      else
      {
          eMatchScore     theResult = eMatchScoreNone;
  
          const XalanDOMString::size_type     theIndex =
                  indexOf(theNameTest, XalanUnicode::charColon);
  
          // If there's no ':', it's an NCName...
          if (theIndex == theLength)
          {
              if (XalanQName::isValidNCName(theNameTest) == false)
              {
                  const XPathConstructionContext::GetAndReleaseCachedString   theGuard(theConstructionContext);
  
                  theConstructionContext.error(
                      XalanMessageLoader::getMessage(
                          theGuard.get(),
                          XalanMessages::IsNotValidQName_1Param,
                          theNameTest),
                          0,
                          theLocator);
              }
              else
              {
                  theResult = initialize(
                      s_emptyString,
                      theConstructionContext.getPooledString(theNameTest));
              }
          }
          else
          {
              const XPathConstructionContext::GetAndReleaseCachedString   scratchGuard(theConstructionContext);
  
              XalanDOMString&     theScratchString = scratchGuard.get();
  
              theScratchString.assign(theNameTest, 0, theIndex);
  
              // Get the namespace URI for the prefix...
              const XalanDOMString* const     theNamespaceURI =
                  thePrefixResolver.getNamespaceForPrefix(theScratchString);
  
              if (theNamespaceURI == 0)
              {
                  theConstructionContext.error(
                      XalanMessageLoader::getMessage(
                          theScratchString,
                          XalanMessages::PrefixIsNotDeclared_1Param),
                          0,
                          theLocator);
              }
              else
              {
                  // OK, now we have a namespace URI...
                  if (XalanQName::isValidNCName(theScratchString) == false)
                  {
                      theConstructionContext.error(
                          XalanMessageLoader::getMessage(
                              theScratchString,
                              XalanMessages::IsNotValidQName_1Param,
                              theNameTest),
                              0,
                              theLocator);
                  }
                  else if (theIndex == theLength - 2 &&
                           theNameTest[theIndex + 1] == XPath::PSEUDONAME_ANY[0])
                  {
                      // It's of the form "NCName:*"
                      theResult = initialize(
                          theConstructionContext.getPooledString(*theNamespaceURI),
                          s_emptyString);
                  }
                  else
                  {
                      theScratchString.assign(theNameTest, theIndex + 1, theLength - theIndex - 1);
  
                      if (XalanQName::isValidNCName(theScratchString) == false)
                      {
                          theConstructionContext.error(
                              XalanMessageLoader::getMessage(
                                  theScratchString,
                                  XalanMessages::IsNotValidQName_1Param,
                                  theNameTest),
                              0,
                              theLocator);
                      }
                      else
                      {
                          // It's of the form "NCName:NCName"
                          theResult = initialize(
                              theConstructionContext.getPooledString(*theNamespaceURI),
                              theConstructionContext.getPooledString(theScratchString));
                      }
                  }
              }
          }
  
          return theResult;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::initialize(
              const XalanDOMString&   theNamespaceURI,
              const XalanDOMString&   theLocalName)
  {
      if (theNamespaceURI.empty() == false)
      {
          m_targetNamespace = &theNamespaceURI;
  
          if (theLocalName.empty() == true)
          {
              m_testFunction2 = &NodeTester::testElementNamespaceOnly2;
  
              return eMatchScoreNSWild;
          }
          else
          {
              m_testFunction2 = &NodeTester::testElementQName2;
  
              m_targetLocalName = &theLocalName;
  
              return eMatchScoreQName;
          }
      }
      else if (theLocalName.empty() == false)
      {
          m_testFunction2 = &NodeTester::testElementNCName2;
  
          m_targetLocalName = &theLocalName;
  
          return eMatchScoreQName;
      }
      else
      {
          m_testFunction2 = &NodeTester::testElementTotallyWild2;
  
          return eMatchScoreNodeTest;
      }
  }
  
  
  
  inline bool
  isNamespaceDeclaration(const XalanNode&     theAttributeNode)
  {
      assert(theAttributeNode.getNodeType() == XalanNode::ATTRIBUTE_NODE);
  
  #if defined(XALAN_OLD_STYLE_CASTS)
      return DOMServices::isNamespaceDeclaration((const XalanAttr&)theAttributeNode);
  #else
      return DOMServices::isNamespaceDeclaration(static_cast<const XalanAttr&>(theAttributeNode));
  #endif
  }
  
  
  
  // MSVC generates some really horrible code for some of these very simple functions when they're inlined...
  #if defined(_MSC_VER) && _MSC_VER <= 1300 && !defined(__INTEL_COMPILER)
  #pragma auto_inline(off)
  #endif
  
  XPath::eMatchScore
  XPath::NodeTester::testComment(
              const XalanNode&        /* context */,
              XalanNode::NodeType     nodeType) const
  {
      if (XalanNode::COMMENT_NODE == nodeType)
      {
          return eMatchScoreNodeTest;
      }
      else
      {
          return eMatchScoreNone;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testText(
              const XalanNode&        context,
              XalanNode::NodeType     nodeType) const
  {
      if ((XalanNode::TEXT_NODE == nodeType || XalanNode::CDATA_SECTION_NODE == nodeType) &&
  #if defined(XALAN_OLD_STYLE_CASTS)
          shouldStripSourceNode((const XalanText&)context) == false)
  #else
          shouldStripSourceNode(static_cast<const XalanText&>(context)) == false)
  #endif
      {
          return eMatchScoreNodeTest;
      }
      else
      {
          return eMatchScoreNone;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testPI(
              const XalanNode&        /* context */,
              XalanNode::NodeType     nodeType) const
  {
      if (XalanNode::PROCESSING_INSTRUCTION_NODE == nodeType)
      {
          return eMatchScoreNodeTest;
      }
      else
      {
          return eMatchScoreNone;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testPIName(
              const XalanNode&        context,
              XalanNode::NodeType     nodeType) const
  {
      assert(m_targetLocalName != 0);
  
      if (XalanNode::PROCESSING_INSTRUCTION_NODE == nodeType &&
          context.getNodeName() == *m_targetLocalName)
      {
          return eMatchScoreQName;
      }
      else
      {
          return eMatchScoreNone;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testNode(
              const XalanNode&        context,
              XalanNode::NodeType     nodeType) const
  {
      if ((nodeType != XalanNode::TEXT_NODE && nodeType != XalanNode::CDATA_SECTION_NODE) ||
  #if defined(XALAN_OLD_STYLE_CASTS)
          shouldStripSourceNode((const XalanText&)context) == false)
  #else
          shouldStripSourceNode(static_cast<const XalanText&>(context)) == false)
  #endif
      {
          return eMatchScoreNodeTest;
      }
      else
      {
          return eMatchScoreNone;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testRoot(
              const XalanNode&        /* context */,
              XalanNode::NodeType     nodeType) const
  {
      if (XalanNode::DOCUMENT_NODE == nodeType ||
          XalanNode::DOCUMENT_FRAGMENT_NODE == nodeType)
      {
          return eMatchScoreOther;
      }
      else
      {
          return eMatchScoreNone;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testAttributeNCName(
              const XalanNode&        context,
              XalanNode::NodeType     nodeType) const
  {
      assert(m_targetNamespace == 0 && m_targetLocalName != 0);
  
      if (XalanNode::ATTRIBUTE_NODE != nodeType ||
          isNamespaceDeclaration(context) == true ||
          matchLocalName(context) == false)
      {
          return eMatchScoreNone;
      }
      else
      {
          return eMatchScoreQName;
      }
  }
  
  inline bool
  XPath::NodeTester::matchLocalNameAndNamespaceURI(const XalanNode&   context) const
  {
      assert(m_targetNamespace != 0 && m_targetLocalName != 0);
  
      return DOMServices::getLocalNameOfNode(context) == *m_targetLocalName &&
             context.getNamespaceURI() == *m_targetNamespace;
  }
  
  
  XPath::eMatchScore
  XPath::NodeTester::testAttributeQName(
              const XalanNode&        context,
              XalanNode::NodeType     nodeType) const
  {
      assert(m_targetNamespace != 0 && m_targetLocalName != 0);
  
      if (XalanNode::ATTRIBUTE_NODE != nodeType ||
          isNamespaceDeclaration(context) == true ||
          matchLocalNameAndNamespaceURI(context) == false)
      {
          return eMatchScoreNone;
      }
      else
      {
          return eMatchScoreQName;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testAttributeNamespaceOnly(
              const XalanNode&        context,
              XalanNode::NodeType     nodeType) const
  {
      assert(m_targetNamespace != 0 && m_targetLocalName == 0);
  
      if (XalanNode::ATTRIBUTE_NODE != nodeType ||
          isNamespaceDeclaration(context) == true ||
          matchNamespaceURI(context) == false)
      {
          return eMatchScoreNone;
      }
      else
      {
          return eMatchScoreNSWild;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testAttributeTotallyWild(
              const XalanNode&        context,
              XalanNode::NodeType     nodeType) const
  {
      if (XalanNode::ATTRIBUTE_NODE != nodeType ||
          isNamespaceDeclaration(context) == true)
      {
          return eMatchScoreNone;
      }
      else
      {
          return eMatchScoreNodeTest;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testElementNCName(
              const XalanNode&        context,
              XalanNode::NodeType     nodeType) const
  {
      assert(m_targetNamespace == 0 && m_targetLocalName != 0);
  
      if (XalanNode::ELEMENT_NODE != nodeType ||
          matchLocalName(context) == false)
      {
          return eMatchScoreNone;
      }
      else
      {
          return eMatchScoreQName;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testElementQName(
              const XalanNode&        context,
              XalanNode::NodeType     nodeType) const
  {
      assert(m_targetNamespace != 0 && m_targetLocalName != 0);
  
      if (XalanNode::ELEMENT_NODE != nodeType ||
          matchLocalNameAndNamespaceURI(context) == false)
      {
          return eMatchScoreNone;
      }
      else
      {
          return eMatchScoreQName;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testElementNamespaceOnly(
              const XalanNode&        context,
              XalanNode::NodeType     nodeType) const
  {
      assert(m_targetNamespace != 0 && m_targetLocalName == 0);
  
      if (XalanNode::ELEMENT_NODE != nodeType ||
          matchNamespaceURI(context) == false)
      {
          return eMatchScoreNone;
      }
      else
      {
          return eMatchScoreNSWild;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testElementTotallyWild(
              const XalanNode&        /* context */,
              XalanNode::NodeType     nodeType) const
  {
      assert(m_targetNamespace == 0 && m_targetLocalName == 0);
  
      if (XalanNode::ELEMENT_NODE != nodeType)
      {
          return eMatchScoreNone;
      }
      else
      {
          return eMatchScoreNodeTest;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testElementNCName2(const XalanElement&   context) const
  {
      assert(
          m_targetNamespace == 0 &&
          m_targetLocalName != 0);
  
      if (matchLocalName(context) == false)
      {
          return eMatchScoreNone;
      }
      else
      {
          return eMatchScoreQName;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testElementQName2(const XalanElement&    context) const
  {
      assert(
          m_targetNamespace != 0 &&
          m_targetLocalName != 0);
  
      if (matchLocalNameAndNamespaceURI(context) == false)
      {
          return eMatchScoreNone;
      }
      else
      {
          return eMatchScoreQName;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testElementNamespaceOnly2(const XalanElement&    context) const
  {
      assert(
          m_targetNamespace != 0 &&
          m_targetLocalName == 0);
  
      if (matchNamespaceURI(context) == false)
      {
          return eMatchScoreNone;
      }
      else
      {
          return eMatchScoreNSWild;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testElementTotallyWild2(const XalanElement&  /* context */) const
  {
      assert(
          m_targetNamespace == 0 &&
          m_targetLocalName == 0);
  
      return eMatchScoreNodeTest;
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testNamespaceNCName(
              const XalanNode&        context,
              XalanNode::NodeType     nodeType) const
  {
      assert(m_targetNamespace == 0 && m_targetLocalName != 0);
  
      if (XalanNode::ATTRIBUTE_NODE != nodeType ||
          isNamespaceDeclaration(context) == false ||
          matchNamespace(context) == false)
      {
          return eMatchScoreNone;
      }
      else
      {
          return eMatchScoreQName;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testNamespaceTotallyWild(
              const XalanNode&        context,
              XalanNode::NodeType     nodeType) const
  {
      assert(m_targetNamespace == 0 && m_targetLocalName == 0);
  
      if (XalanNode::ATTRIBUTE_NODE != nodeType ||
          isNamespaceDeclaration(context) == false)
      {
          return eMatchScoreNone;
      }
      else
      {
          return eMatchScoreNodeTest;
      }
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testDefault(
              const XalanNode&        /* context */,
              XalanNode::NodeType     /* nodeType */) const
  {
      return eMatchScoreNone;
  }
  
  
  
  XPath::eMatchScore
  XPath::NodeTester::testDefault2(const XalanElement&     /* context */) const
  {
      return eMatchScoreNone;
  }
  
  
  
  bool
  XPath::NodeTester::matchLocalName(const XalanNode&  context) const
  {
      assert(m_targetLocalName != 0);
  
      return length(context.getNamespaceURI()) == 0 &&
          DOMServices::getLocalNameOfNode(context) == *m_targetLocalName;
  }
  
  
  
  bool
  XPath::NodeTester::matchNamespaceURI(const XalanNode&   context) const
  {
      assert(m_targetNamespace != 0);
  
      return context.getNamespaceURI() == *m_targetNamespace;
  }
  
  
  bool
  XPath::NodeTester::matchNamespace(const XalanNode&  context) const
  {
      assert(m_targetLocalName != 0);
  
      return context.getLocalName() == *m_targetLocalName;
  }
  
  
  
  bool
  XPath::NodeTester::shouldStripSourceNode(const XalanText&   context) const
  {
      assert(m_executionContext != 0);
  
      return m_executionContext->shouldStripSourceNode(context);
  }
  
  
  
  const XalanDOMChar  XPath::PSEUDONAME_ANY[] =
  {
      XalanUnicode::charAsterisk,
      0
  };
  
  const XalanDOMChar  XPath::PSEUDONAME_ROOT[] =
  {
      XalanUnicode::charSolidus,
      0
  };
  
  const XalanDOMChar  XPath::PSEUDONAME_TEXT[] =
  {
      XalanUnicode::charNumberSign,
      XalanUnicode::charLetter_t,
      XalanUnicode::charLetter_e,
      XalanUnicode::charLetter_x,
      XalanUnicode::charLetter_t,
      0
  };
  
  const XalanDOMChar  XPath::PSEUDONAME_COMMENT[] =
  {
      XalanUnicode::charNumberSign,
      XalanUnicode::charLetter_c,
      XalanUnicode::charLetter_o,
      XalanUnicode::charLetter_m,
      XalanUnicode::charLetter_m,
      XalanUnicode::charLetter_e,
      XalanUnicode::charLetter_n,
      XalanUnicode::charLetter_t,
      0
  };
  
  const XalanDOMChar  XPath::PSEUDONAME_PI[] =
  {
      XalanUnicode::charNumberSign,
      XalanUnicode::charLetter_p,
      XalanUnicode::charLetter_i,
      0
  };
  
  const XalanDOMChar  XPath::PSEUDONAME_OTHER[] =
  {
      XalanUnicode::charAsterisk,
      0
  };
  
  const XalanDOMChar  XPath::PSEUDONAME_NODE[] =
  {
      XalanUnicode::charNumberSign,
      XalanUnicode::charLetter_n,
      XalanUnicode::charLetter_o,
      XalanUnicode::charLetter_d,
      XalanUnicode::charLetter_e,
      0
  };
  
  
  
  // Don't auto-create the table...
  
  XPath::FunctionTableType        XPath::s_functions(false);
  
  
  
  void
  XPath::initialize(MemoryManagerType& theManager)
  {
      s_functions.setMemoryManager(theManager);
  
      s_functions.CreateTable();
  }
  
  
  
  void
  XPath::terminate()
  {
      s_functions.DestroyTable();
  }
  
  
  
  XALAN_CPP_NAMESPACE_END
  