1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xalan" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, Lotus
  53. * Development Corporation., http://www.lotus.com. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package org.apache.xpath.axes;
  58. import org.apache.xpath.compiler.OpCodes;
  59. import org.apache.xpath.compiler.Compiler;
  60. import org.apache.xpath.compiler.FunctionTable;
  61. import org.apache.xpath.patterns.NodeTest;
  62. import org.apache.xpath.patterns.StepPattern;
  63. import org.apache.xpath.patterns.ContextMatchStepPattern;
  64. import org.apache.xpath.patterns.FunctionPattern;
  65. import org.apache.xpath.Expression;
  66. import org.apache.xpath.objects.XNumber;
  67. import org.apache.xalan.res.XSLMessages;
  68. import org.apache.xpath.res.XPATHErrorResources;
  69. import org.apache.xml.dtm.DTMFilter;
  70. import org.apache.xml.dtm.DTMIterator;
  71. import org.apache.xml.dtm.Axis;
  72. /**
  73. * This class is both a factory for XPath location path expressions,
  74. * which are built from the opcode map output, and an analysis engine
  75. * for the location path expressions in order to provide optimization hints.
  76. */
  77. public class WalkerFactory
  78. {
  79. /**
  80. * <meta name="usage" content="advanced"/>
  81. * This method is for building an array of possible levels
  82. * where the target element(s) could be found for a match.
  83. * @param xpath The xpath that is executing.
  84. * @param context The current source tree context node.
  85. *
  86. * @param lpi The owning location path iterator.
  87. * @param compiler non-null reference to compiler object that has processed
  88. * the XPath operations into an opcode map.
  89. * @param stepOpCodePos The opcode position for the step.
  90. *
  91. * @return non-null AxesWalker derivative.
  92. *
  93. * @throws javax.xml.transform.TransformerException
  94. */
  95. static AxesWalker loadOneWalker(
  96. WalkingIterator lpi, Compiler compiler, int stepOpCodePos)
  97. throws javax.xml.transform.TransformerException
  98. {
  99. AxesWalker firstWalker = null;
  100. int stepType = compiler.getOp(stepOpCodePos);
  101. if (stepType != OpCodes.ENDOP)
  102. {
  103. // m_axesWalkers = new AxesWalker[1];
  104. // As we unwind from the recursion, create the iterators.
  105. firstWalker = createDefaultWalker(compiler, stepType, lpi, 0);
  106. firstWalker.init(compiler, stepOpCodePos, stepType);
  107. }
  108. return firstWalker;
  109. }
  110. /**
  111. * <meta name="usage" content="advanced"/>
  112. * This method is for building an array of possible levels
  113. * where the target element(s) could be found for a match.
  114. * @param xpath The xpath that is executing.
  115. * @param context The current source tree context node.
  116. *
  117. * @param lpi The owning location path iterator object.
  118. * @param compiler non-null reference to compiler object that has processed
  119. * the XPath operations into an opcode map.
  120. * @param stepOpCodePos The opcode position for the step.
  121. * @param stepIndex The top-level step index withing the iterator.
  122. *
  123. * @return non-null AxesWalker derivative.
  124. *
  125. * @throws javax.xml.transform.TransformerException
  126. */
  127. static AxesWalker loadWalkers(
  128. WalkingIterator lpi, Compiler compiler, int stepOpCodePos, int stepIndex)
  129. throws javax.xml.transform.TransformerException
  130. {
  131. int stepType;
  132. AxesWalker firstWalker = null;
  133. AxesWalker walker, prevWalker = null;
  134. int analysis = analyze(compiler, stepOpCodePos, stepIndex);
  135. while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
  136. {
  137. walker = createDefaultWalker(compiler, stepOpCodePos, lpi, analysis);
  138. walker.init(compiler, stepOpCodePos, stepType);
  139. walker.exprSetParent(lpi);
  140. // walker.setAnalysis(analysis);
  141. if (null == firstWalker)
  142. {
  143. firstWalker = walker;
  144. }
  145. else
  146. {
  147. prevWalker.setNextWalker(walker);
  148. walker.setPrevWalker(prevWalker);
  149. }
  150. prevWalker = walker;
  151. stepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
  152. if (stepOpCodePos < 0)
  153. break;
  154. }
  155. return firstWalker;
  156. }
  157. public static boolean isSet(int analysis, int bits)
  158. {
  159. return (0 != (analysis & bits));
  160. }
  161. public static void diagnoseIterator(String name, int analysis, Compiler compiler)
  162. {
  163. System.out.println(compiler.toString()+", "+name+", "
  164. + Integer.toBinaryString(analysis) + ", "
  165. + getAnalysisString(analysis));
  166. }
  167. /**
  168. * Create a new LocPathIterator iterator. The exact type of iterator
  169. * returned is based on an analysis of the XPath operations.
  170. *
  171. * @param compiler non-null reference to compiler object that has processed
  172. * the XPath operations into an opcode map.
  173. * @param opPos The position of the operation code for this itterator.
  174. *
  175. * @return non-null reference to a LocPathIterator or derivative.
  176. *
  177. * @throws javax.xml.transform.TransformerException
  178. */
  179. public static DTMIterator newDTMIterator(
  180. Compiler compiler, int opPos,
  181. boolean isTopLevel)
  182. throws javax.xml.transform.TransformerException
  183. {
  184. int firstStepPos = compiler.getFirstChildPos(opPos);
  185. int analysis = analyze(compiler, firstStepPos, 0);
  186. boolean isOneStep = isOneStep(analysis);
  187. DTMIterator iter;
  188. // Is the iteration a one-step attribute pattern (i.e. select="@foo")?
  189. if (isOneStep && walksSelfOnly(analysis) &&
  190. isWild(analysis) && !hasPredicate(analysis))
  191. {
  192. if (DEBUG_ITERATOR_CREATION)
  193. diagnoseIterator("SelfIteratorNoPredicate", analysis, compiler);
  194. // Then use a simple iteration of the attributes, with node test
  195. // and predicate testing.
  196. iter = new SelfIteratorNoPredicate(compiler, opPos, analysis);
  197. }
  198. // Is the iteration exactly one child step?
  199. else if (walksChildrenOnly(analysis) && isOneStep)
  200. {
  201. // Does the pattern specify *any* child with no predicate? (i.e. select="child::node()".
  202. if (isWild(analysis) && !hasPredicate(analysis))
  203. {
  204. if (DEBUG_ITERATOR_CREATION)
  205. diagnoseIterator("ChildIterator", analysis, compiler);
  206. // Use simple child iteration without any test.
  207. iter = new ChildIterator(compiler, opPos, analysis);
  208. }
  209. else
  210. {
  211. if (DEBUG_ITERATOR_CREATION)
  212. diagnoseIterator("ChildTestIterator", analysis, compiler);
  213. // Else use simple node test iteration with predicate test.
  214. iter = new ChildTestIterator(compiler, opPos, analysis);
  215. }
  216. }
  217. // Is the iteration a one-step attribute pattern (i.e. select="@foo")?
  218. else if (isOneStep && walksAttributes(analysis))
  219. {
  220. if (DEBUG_ITERATOR_CREATION)
  221. diagnoseIterator("AttributeIterator", analysis, compiler);
  222. // Then use a simple iteration of the attributes, with node test
  223. // and predicate testing.
  224. iter = new AttributeIterator(compiler, opPos, analysis);
  225. }
  226. else if(isOneStep && !walksFilteredList(analysis))
  227. {
  228. if( !walksNamespaces(analysis)
  229. && (walksInDocOrder(analysis) || isSet(analysis, BIT_PARENT)))
  230. {
  231. if (false || DEBUG_ITERATOR_CREATION)
  232. diagnoseIterator("OneStepIteratorForward", analysis, compiler);
  233. // Then use a simple iteration of the attributes, with node test
  234. // and predicate testing.
  235. iter = new OneStepIteratorForward(compiler, opPos, analysis);
  236. }
  237. else
  238. {
  239. if (false || DEBUG_ITERATOR_CREATION)
  240. diagnoseIterator("OneStepIterator", analysis, compiler);
  241. // Then use a simple iteration of the attributes, with node test
  242. // and predicate testing.
  243. iter = new OneStepIterator(compiler, opPos, analysis);
  244. }
  245. }
  246. // Analysis of "//center":
  247. // bits: 1001000000001010000000000000011
  248. // count: 3
  249. // root
  250. // child:node()
  251. // BIT_DESCENDANT_OR_SELF
  252. // It's highly possible that we should have a seperate bit set for
  253. // "//foo" patterns.
  254. // For at least the time being, we can't optimize patterns like
  255. // "//table[3]", because this has to be analyzed as
  256. // "/descendant-or-self::node()/table[3]" in order for the indexes
  257. // to work right.
  258. else if (isOptimizableForDescendantIterator(compiler, firstStepPos, 0)
  259. // && getStepCount(analysis) <= 3
  260. // && walksDescendants(analysis)
  261. // && walksSubtreeOnlyFromRootOrContext(analysis)
  262. )
  263. {
  264. if (DEBUG_ITERATOR_CREATION)
  265. diagnoseIterator("DescendantIterator", analysis, compiler);
  266. iter = new DescendantIterator(compiler, opPos, analysis);
  267. }
  268. else
  269. {
  270. if(isNaturalDocOrder(compiler, firstStepPos, 0, analysis))
  271. {
  272. if (false || DEBUG_ITERATOR_CREATION)
  273. {
  274. diagnoseIterator("WalkingIterator", analysis, compiler);
  275. }
  276. iter = new WalkingIterator(compiler, opPos, analysis, true);
  277. }
  278. else
  279. {
  280. // if (DEBUG_ITERATOR_CREATION)
  281. // diagnoseIterator("MatchPatternIterator", analysis, compiler);
  282. //
  283. // return new MatchPatternIterator(compiler, opPos, analysis);
  284. if (DEBUG_ITERATOR_CREATION)
  285. diagnoseIterator("WalkingIteratorSorted", analysis, compiler);
  286. iter = new WalkingIteratorSorted(compiler, opPos, analysis, true);
  287. }
  288. }
  289. if(iter instanceof LocPathIterator)
  290. ((LocPathIterator)iter).setIsTopLevel(isTopLevel);
  291. return iter;
  292. }
  293. /**
  294. * Special purpose function to see if we can optimize the pattern for
  295. * a DescendantIterator.
  296. *
  297. * @param compiler non-null reference to compiler object that has processed
  298. * the XPath operations into an opcode map.
  299. * @param stepOpCodePos The opcode position for the step.
  300. * @param stepIndex The top-level step index withing the iterator.
  301. *
  302. * @return 32 bits as an integer that give information about the location
  303. * path as a whole.
  304. *
  305. * @throws javax.xml.transform.TransformerException
  306. */
  307. public static int getAxisFromStep(
  308. Compiler compiler, int stepOpCodePos)
  309. throws javax.xml.transform.TransformerException
  310. {
  311. int stepType = compiler.getOp(stepOpCodePos);
  312. switch (stepType)
  313. {
  314. case OpCodes.FROM_FOLLOWING :
  315. return Axis.FOLLOWING;
  316. case OpCodes.FROM_FOLLOWING_SIBLINGS :
  317. return Axis.FOLLOWINGSIBLING;
  318. case OpCodes.FROM_PRECEDING :
  319. return Axis.PRECEDING;
  320. case OpCodes.FROM_PRECEDING_SIBLINGS :
  321. return Axis.PRECEDINGSIBLING;
  322. case OpCodes.FROM_PARENT :
  323. return Axis.PARENT;
  324. case OpCodes.FROM_NAMESPACE :
  325. return Axis.NAMESPACE;
  326. case OpCodes.FROM_ANCESTORS :
  327. return Axis.ANCESTOR;
  328. case OpCodes.FROM_ANCESTORS_OR_SELF :
  329. return Axis.ANCESTORORSELF;
  330. case OpCodes.FROM_ATTRIBUTES :
  331. return Axis.ATTRIBUTE;
  332. case OpCodes.FROM_ROOT :
  333. return Axis.ROOT;
  334. case OpCodes.FROM_CHILDREN :
  335. return Axis.CHILD;
  336. case OpCodes.FROM_DESCENDANTS_OR_SELF :
  337. return Axis.DESCENDANTORSELF;
  338. case OpCodes.FROM_DESCENDANTS :
  339. return Axis.DESCENDANT;
  340. case OpCodes.FROM_SELF :
  341. return Axis.SELF;
  342. case OpCodes.OP_EXTFUNCTION :
  343. case OpCodes.OP_FUNCTION :
  344. case OpCodes.OP_GROUP :
  345. case OpCodes.OP_VARIABLE :
  346. return Axis.FILTEREDLIST;
  347. }
  348. throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
  349. //+ stepType);
  350. }
  351. /**
  352. * Get a corresponding BIT_XXX from an axis.
  353. * @param axis One of Axis.ANCESTOR, etc.
  354. * @return One of BIT_ANCESTOR, etc.
  355. */
  356. static public int getAnalysisBitFromAxes(int axis)
  357. {
  358. switch (axis) // Generate new traverser
  359. {
  360. case Axis.ANCESTOR :
  361. return BIT_ANCESTOR;
  362. case Axis.ANCESTORORSELF :
  363. return BIT_ANCESTOR_OR_SELF;
  364. case Axis.ATTRIBUTE :
  365. return BIT_ATTRIBUTE;
  366. case Axis.CHILD :
  367. return BIT_CHILD;
  368. case Axis.DESCENDANT :
  369. return BIT_DESCENDANT;
  370. case Axis.DESCENDANTORSELF :
  371. return BIT_DESCENDANT_OR_SELF;
  372. case Axis.FOLLOWING :
  373. return BIT_FOLLOWING;
  374. case Axis.FOLLOWINGSIBLING :
  375. return BIT_FOLLOWING_SIBLING;
  376. case Axis.NAMESPACE :
  377. case Axis.NAMESPACEDECLS :
  378. return BIT_NAMESPACE;
  379. case Axis.PARENT :
  380. return BIT_PARENT;
  381. case Axis.PRECEDING :
  382. return BIT_PRECEDING;
  383. case Axis.PRECEDINGSIBLING :
  384. return BIT_PRECEDING_SIBLING;
  385. case Axis.SELF :
  386. return BIT_SELF;
  387. case Axis.ALLFROMNODE :
  388. return BIT_DESCENDANT_OR_SELF;
  389. // case Axis.PRECEDINGANDANCESTOR :
  390. case Axis.DESCENDANTSFROMROOT :
  391. case Axis.ALL :
  392. case Axis.DESCENDANTSORSELFFROMROOT :
  393. return BIT_ANY_DESCENDANT_FROM_ROOT;
  394. case Axis.ROOT :
  395. return BIT_ROOT;
  396. case Axis.FILTEREDLIST :
  397. return BIT_FILTER;
  398. default :
  399. return BIT_FILTER;
  400. }
  401. }
  402. static boolean functionProximateOrContainsProximate(Compiler compiler,
  403. int opPos)
  404. {
  405. int endFunc = opPos + compiler.getOp(opPos + 1) - 1;
  406. opPos = compiler.getFirstChildPos(opPos);
  407. int funcID = compiler.getOp(opPos);
  408. // System.out.println("funcID: "+funcID);
  409. // System.out.println("opPos: "+opPos);
  410. // System.out.println("endFunc: "+endFunc);
  411. switch(funcID)
  412. {
  413. case FunctionTable.FUNC_LAST:
  414. case FunctionTable.FUNC_POSITION:
  415. return true;
  416. default:
  417. opPos++;
  418. int i = 0;
  419. for (int p = opPos; p < endFunc; p = compiler.getNextOpPos(p), i++)
  420. {
  421. int innerExprOpPos = p+2;
  422. int argOp = compiler.getOp(innerExprOpPos);
  423. boolean prox = isProximateInnerExpr(compiler, innerExprOpPos);
  424. if(prox)
  425. return true;
  426. }
  427. }
  428. return false;
  429. }
  430. static boolean isProximateInnerExpr(Compiler compiler, int opPos)
  431. {
  432. int op = compiler.getOp(opPos);
  433. int innerExprOpPos = opPos+2;
  434. switch(op)
  435. {
  436. case OpCodes.OP_ARGUMENT:
  437. if(isProximateInnerExpr(compiler, innerExprOpPos))
  438. return true;
  439. break;
  440. case OpCodes.OP_VARIABLE:
  441. case OpCodes.OP_NUMBERLIT:
  442. case OpCodes.OP_LITERAL:
  443. case OpCodes.OP_LOCATIONPATH:
  444. break; // OK
  445. case OpCodes.OP_FUNCTION:
  446. boolean isProx = functionProximateOrContainsProximate(compiler, opPos);
  447. if(isProx)
  448. return true;
  449. break;
  450. case OpCodes.OP_GT:
  451. case OpCodes.OP_GTE:
  452. case OpCodes.OP_LT:
  453. case OpCodes.OP_LTE:
  454. case OpCodes.OP_EQUALS:
  455. int leftPos = compiler.getFirstChildPos(op);
  456. int rightPos = compiler.getNextOpPos(leftPos);
  457. isProx = isProximateInnerExpr(compiler, leftPos);
  458. if(isProx)
  459. return true;
  460. isProx = isProximateInnerExpr(compiler, rightPos);
  461. if(isProx)
  462. return true;
  463. break;
  464. default:
  465. return true; // be conservative...
  466. }
  467. return false;
  468. }
  469. /**
  470. * Tell if the predicates need to have proximity knowledge.
  471. */
  472. public static boolean mightBeProximate(Compiler compiler, int opPos, int stepType)
  473. throws javax.xml.transform.TransformerException
  474. {
  475. boolean mightBeProximate = false;
  476. int argLen;
  477. switch (stepType)
  478. {
  479. case OpCodes.OP_VARIABLE :
  480. case OpCodes.OP_EXTFUNCTION :
  481. case OpCodes.OP_FUNCTION :
  482. case OpCodes.OP_GROUP :
  483. argLen = compiler.getArgLength(opPos);
  484. break;
  485. default :
  486. argLen = compiler.getArgLengthOfStep(opPos);
  487. }
  488. int predPos = compiler.getFirstPredicateOpPos(opPos);
  489. int count = 0;
  490. while (OpCodes.OP_PREDICATE == compiler.getOp(predPos))
  491. {
  492. count++;
  493. int innerExprOpPos = predPos+2;
  494. int predOp = compiler.getOp(innerExprOpPos);
  495. switch(predOp)
  496. {
  497. case OpCodes.OP_VARIABLE:
  498. return true; // Would need more smarts to tell if this could be a number or not!
  499. case OpCodes.OP_LOCATIONPATH:
  500. // OK.
  501. break;
  502. case OpCodes.OP_NUMBER:
  503. case OpCodes.OP_NUMBERLIT:
  504. return true; // that's all she wrote!
  505. case OpCodes.OP_FUNCTION:
  506. boolean isProx
  507. = functionProximateOrContainsProximate(compiler, innerExprOpPos);
  508. if(isProx)
  509. return true;
  510. break;
  511. case OpCodes.OP_GT:
  512. case OpCodes.OP_GTE:
  513. case OpCodes.OP_LT:
  514. case OpCodes.OP_LTE:
  515. case OpCodes.OP_EQUALS:
  516. int leftPos = compiler.getFirstChildPos(innerExprOpPos);
  517. int rightPos = compiler.getNextOpPos(leftPos);
  518. isProx = isProximateInnerExpr(compiler, leftPos);
  519. if(isProx)
  520. return true;
  521. isProx = isProximateInnerExpr(compiler, rightPos);
  522. if(isProx)
  523. return true;
  524. break;
  525. default:
  526. return true; // be conservative...
  527. }
  528. predPos = compiler.getNextOpPos(predPos);
  529. }
  530. return mightBeProximate;
  531. }
  532. /**
  533. * Special purpose function to see if we can optimize the pattern for
  534. * a DescendantIterator.
  535. *
  536. * @param compiler non-null reference to compiler object that has processed
  537. * the XPath operations into an opcode map.
  538. * @param stepOpCodePos The opcode position for the step.
  539. * @param stepIndex The top-level step index withing the iterator.
  540. *
  541. * @return 32 bits as an integer that give information about the location
  542. * path as a whole.
  543. *
  544. * @throws javax.xml.transform.TransformerException
  545. */
  546. private static boolean isOptimizableForDescendantIterator(
  547. Compiler compiler, int stepOpCodePos, int stepIndex)
  548. throws javax.xml.transform.TransformerException
  549. {
  550. int stepType;
  551. int stepCount = 0;
  552. boolean foundDorDS = false;
  553. boolean foundSelf = false;
  554. boolean foundDS = false;
  555. int nodeTestType = OpCodes.NODETYPE_NODE;
  556. while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
  557. {
  558. // The DescendantIterator can only do one node test. If there's more
  559. // than one, use another iterator.
  560. if(nodeTestType != OpCodes.NODETYPE_NODE && nodeTestType != OpCodes.NODETYPE_ROOT)
  561. return false;
  562. stepCount++;
  563. if(stepCount > 3)
  564. return false;
  565. boolean mightBeProximate = mightBeProximate(compiler, stepOpCodePos, stepType);
  566. if(mightBeProximate)
  567. return false;
  568. switch (stepType)
  569. {
  570. case OpCodes.FROM_FOLLOWING :
  571. case OpCodes.FROM_FOLLOWING_SIBLINGS :
  572. case OpCodes.FROM_PRECEDING :
  573. case OpCodes.FROM_PRECEDING_SIBLINGS :
  574. case OpCodes.FROM_PARENT :
  575. case OpCodes.OP_VARIABLE :
  576. case OpCodes.OP_EXTFUNCTION :
  577. case OpCodes.OP_FUNCTION :
  578. case OpCodes.OP_GROUP :
  579. case OpCodes.FROM_NAMESPACE :
  580. case OpCodes.FROM_ANCESTORS :
  581. case OpCodes.FROM_ANCESTORS_OR_SELF :
  582. case OpCodes.FROM_ATTRIBUTES :
  583. case OpCodes.MATCH_ATTRIBUTE :
  584. case OpCodes.MATCH_ANY_ANCESTOR :
  585. case OpCodes.MATCH_IMMEDIATE_ANCESTOR :
  586. return false;
  587. case OpCodes.FROM_ROOT :
  588. if(1 != stepCount)
  589. return false;
  590. break;
  591. case OpCodes.FROM_CHILDREN :
  592. if(!foundDS && !(foundDorDS && foundSelf))
  593. return false;
  594. break;
  595. case OpCodes.FROM_DESCENDANTS_OR_SELF :
  596. foundDS = true;
  597. case OpCodes.FROM_DESCENDANTS :
  598. if(3 == stepCount)
  599. return false;
  600. foundDorDS = true;
  601. break;
  602. case OpCodes.FROM_SELF :
  603. if(1 != stepCount)
  604. return false;
  605. foundSelf = true;
  606. break;
  607. default :
  608. throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
  609. // + stepType);
  610. }
  611. nodeTestType = compiler.getStepTestType(stepOpCodePos);
  612. int nextStepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
  613. if (nextStepOpCodePos < 0)
  614. break;
  615. if(OpCodes.ENDOP != compiler.getOp(nextStepOpCodePos))
  616. {
  617. if(compiler.countPredicates(stepOpCodePos) > 0)
  618. {
  619. return false;
  620. }
  621. }
  622. stepOpCodePos = nextStepOpCodePos;
  623. }
  624. return true;
  625. }
  626. /**
  627. * Analyze the location path and return 32 bits that give information about
  628. * the location path as a whole. See the BIT_XXX constants for meaning about
  629. * each of the bits.
  630. *
  631. * @param compiler non-null reference to compiler object that has processed
  632. * the XPath operations into an opcode map.
  633. * @param stepOpCodePos The opcode position for the step.
  634. * @param stepIndex The top-level step index withing the iterator.
  635. *
  636. * @return 32 bits as an integer that give information about the location
  637. * path as a whole.
  638. *
  639. * @throws javax.xml.transform.TransformerException
  640. */
  641. private static int analyze(
  642. Compiler compiler, int stepOpCodePos, int stepIndex)
  643. throws javax.xml.transform.TransformerException
  644. {
  645. int stepType;
  646. int stepCount = 0;
  647. int analysisResult = 0x00000000; // 32 bits of analysis
  648. while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
  649. {
  650. stepCount++;
  651. // String namespace = compiler.getStepNS(stepOpCodePos);
  652. // boolean isNSWild = (null != namespace)
  653. // ? namespace.equals(NodeTest.WILD) : false;
  654. // String localname = compiler.getStepLocalName(stepOpCodePos);
  655. // boolean isWild = (null != localname) ? localname.equals(NodeTest.WILD) : false;
  656. boolean predAnalysis = analyzePredicate(compiler, stepOpCodePos,
  657. stepType);
  658. if (predAnalysis)
  659. analysisResult |= BIT_PREDICATE;
  660. switch (stepType)
  661. {
  662. case OpCodes.OP_VARIABLE :
  663. case OpCodes.OP_EXTFUNCTION :
  664. case OpCodes.OP_FUNCTION :
  665. case OpCodes.OP_GROUP :
  666. analysisResult |= BIT_FILTER;
  667. break;
  668. case OpCodes.FROM_ROOT :
  669. analysisResult |= BIT_ROOT;
  670. break;
  671. case OpCodes.FROM_ANCESTORS :
  672. analysisResult |= BIT_ANCESTOR;
  673. break;
  674. case OpCodes.FROM_ANCESTORS_OR_SELF :
  675. analysisResult |= BIT_ANCESTOR_OR_SELF;
  676. break;
  677. case OpCodes.FROM_ATTRIBUTES :
  678. analysisResult |= BIT_ATTRIBUTE;
  679. break;
  680. case OpCodes.FROM_NAMESPACE :
  681. analysisResult |= BIT_NAMESPACE;
  682. break;
  683. case OpCodes.FROM_CHILDREN :
  684. analysisResult |= BIT_CHILD;
  685. break;
  686. case OpCodes.FROM_DESCENDANTS :
  687. analysisResult |= BIT_DESCENDANT;
  688. break;
  689. case OpCodes.FROM_DESCENDANTS_OR_SELF :
  690. // Use a special bit to to make sure we get the right analysis of "//foo".
  691. if (2 == stepCount && BIT_ROOT == analysisResult)
  692. {
  693. analysisResult |= BIT_ANY_DESCENDANT_FROM_ROOT;
  694. }
  695. analysisResult |= BIT_DESCENDANT_OR_SELF;
  696. break;
  697. case OpCodes.FROM_FOLLOWING :
  698. analysisResult |= BIT_FOLLOWING;
  699. break;
  700. case OpCodes.FROM_FOLLOWING_SIBLINGS :
  701. analysisResult |= BIT_FOLLOWING_SIBLING;
  702. break;
  703. case OpCodes.FROM_PRECEDING :
  704. analysisResult |= BIT_PRECEDING;
  705. break;
  706. case OpCodes.FROM_PRECEDING_SIBLINGS :
  707. analysisResult |= BIT_PRECEDING_SIBLING;
  708. break;
  709. case OpCodes.FROM_PARENT :
  710. analysisResult |= BIT_PARENT;
  711. break;
  712. case OpCodes.FROM_SELF :
  713. analysisResult |= BIT_SELF;
  714. break;
  715. case OpCodes.MATCH_ATTRIBUTE :
  716. analysisResult |= (BIT_MATCH_PATTERN | BIT_ATTRIBUTE);
  717. break;
  718. case OpCodes.MATCH_ANY_ANCESTOR :
  719. analysisResult |= (BIT_MATCH_PATTERN | BIT_ANCESTOR);
  720. break;
  721. case OpCodes.MATCH_IMMEDIATE_ANCESTOR :
  722. analysisResult |= (BIT_MATCH_PATTERN | BIT_PARENT);
  723. break;
  724. default :
  725. throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
  726. //+ stepType);
  727. }
  728. if (OpCodes.NODETYPE_NODE == compiler.getOp(stepOpCodePos + 3)) // child::node()
  729. {
  730. analysisResult |= BIT_NODETEST_ANY;
  731. }
  732. stepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
  733. if (stepOpCodePos < 0)
  734. break;
  735. }
  736. analysisResult |= (stepCount & BITS_COUNT);
  737. return analysisResult;
  738. }
  739. /**
  740. * Tell if the given axis goes downword. Bogus name, if you can think of
  741. * a better one, please do tell. This really has to do with inverting
  742. * attribute axis.
  743. * @param axis One of Axis.XXX.
  744. * @return true if the axis is not a child axis and does not go up from
  745. * the axis root.
  746. */
  747. public static boolean isDownwardAxisOfMany(int axis)
  748. {
  749. return ((Axis.DESCENDANTORSELF == axis) ||
  750. (Axis.DESCENDANT == axis)
  751. || (Axis.FOLLOWING == axis)
  752. // || (Axis.FOLLOWINGSIBLING == axis)
  753. || (Axis.PRECEDING == axis)
  754. // || (Axis.PRECEDINGSIBLING == axis)
  755. );
  756. }
  757. /**
  758. * Read a <a href="http://www.w3.org/TR/xpath#location-paths">LocationPath</a>
  759. * as a generalized match pattern. What this means is that the LocationPath
  760. * is read backwards, as a test on a given node, to see if it matches the
  761. * criteria of the selection, and ends up at the context node. Essentially,
  762. * this is a backwards query from a given node, to find the context node.
  763. * <p>So, the selection "foo/daz[2]" is, in non-abreviated expanded syntax,
  764. * "self::node()/following-sibling::foo/child::daz[position()=2]".
  765. * Taking this as a match pattern for a probable node, it works out to
  766. * "self::daz/parent::foo[child::daz[position()=2 and isPrevStepNode()]
  767. * precedingSibling::node()[isContextNodeOfLocationPath()]", adding magic
  768. * isPrevStepNode and isContextNodeOfLocationPath operations. Predicates in
  769. * the location path have to be executed by the following step,
  770. * because they have to know the context of their execution.
  771. *
  772. * @param mpi The MatchPatternIterator to which the steps will be attached.
  773. * @param compiler The compiler that holds the syntax tree/op map to
  774. * construct from.
  775. * @param stepOpCodePos The current op code position within the opmap.
  776. * @param stepIndex The top-level step index withing the iterator.
  777. *
  778. * @return A StepPattern object, which may contain relative StepPatterns.
  779. *
  780. * @throws javax.xml.transform.TransformerException
  781. */
  782. static StepPattern loadSteps(
  783. MatchPatternIterator mpi, Compiler compiler, int stepOpCodePos,
  784. int stepIndex)
  785. throws javax.xml.transform.TransformerException
  786. {
  787. if (DEBUG_PATTERN_CREATION)
  788. {
  789. System.out.println("================");
  790. System.out.println("loadSteps for: "+compiler.getPatternString());
  791. }
  792. int stepType;
  793. StepPattern step = null;
  794. StepPattern firstStep = null, prevStep = null;
  795. int analysis = analyze(compiler, stepOpCodePos, stepIndex);
  796. while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
  797. {
  798. step = createDefaultStepPattern(compiler, stepOpCodePos, mpi, analysis,
  799. firstStep, prevStep);
  800. if (null == firstStep)
  801. {
  802. firstStep = step;
  803. }
  804. else
  805. {
  806. //prevStep.setNextWalker(step);
  807. step.setRelativePathPattern(prevStep);
  808. }
  809. prevStep = step;
  810. stepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
  811. if (stepOpCodePos < 0)
  812. break;
  813. }
  814. int axis = Axis.SELF;
  815. int paxis = Axis.SELF;
  816. StepPattern tail = step;
  817. for (StepPattern pat = step; null != pat;
  818. pat = pat.getRelativePathPattern())
  819. {
  820. int nextAxis = pat.getAxis();
  821. //int nextPaxis = pat.getPredicateAxis();
  822. pat.setAxis(axis);
  823. // The predicate axis can't be moved!!! Test Axes103
  824. // pat.setPredicateAxis(paxis);
  825. // If we have an attribute or namespace axis that went up, then
  826. // it won't find the attribute in the inverse, since the select-to-match
  827. // axes are not invertable (an element is a parent of an attribute, but
  828. // and attribute is not a child of an element).
  829. // If we don't do the magic below, then "@*/ancestor-or-self::*" gets
  830. // inverted for match to "self::*/descendant-or-self::@*/parent::node()",
  831. // which obviously won't work.
  832. // So we will rewrite this as:
  833. // "self::*/descendant-or-self::*/attribute::*/parent::node()"
  834. // Child has to be rewritten a little differently:
  835. // select: "@*/parent::*"
  836. // inverted match: "self::*/child::@*/parent::node()"
  837. // rewrite: "self::*/attribute::*/parent::node()"
  838. // Axes that go down in the select, do not have to have special treatment
  839. // in the rewrite. The following inverted match will still not select
  840. // anything.
  841. // select: "@*/child::*"
  842. // inverted match: "self::*/parent::@*/parent::node()"
  843. // Lovely business, this.
  844. // -sb
  845. int whatToShow = pat.getWhatToShow();
  846. if(whatToShow == DTMFilter.SHOW_ATTRIBUTE ||
  847. whatToShow == DTMFilter.SHOW_NAMESPACE)
  848. {
  849. int newAxis = (whatToShow == DTMFilter.SHOW_ATTRIBUTE) ?
  850. Axis.ATTRIBUTE : Axis.NAMESPACE;
  851. if(isDownwardAxisOfMany(axis))
  852. {
  853. StepPattern attrPat = new StepPattern(whatToShow,
  854. pat.getNamespace(),
  855. pat.getLocalName(),
  856. //newAxis, pat.getPredicateAxis);
  857. newAxis, 0); // don't care about the predicate axis
  858. XNumber score = pat.getStaticScore();
  859. pat.setNamespace(null);
  860. pat.setLocalName(NodeTest.WILD);
  861. attrPat.setPredicates(pat.getPredicates());
  862. pat.setPredicates(null);
  863. pat.setWhatToShow(DTMFilter.SHOW_ELEMENT);
  864. StepPattern rel = pat.getRelativePathPattern();
  865. pat.setRelativePathPattern(attrPat);
  866. attrPat.setRelativePathPattern(rel);
  867. attrPat.setStaticScore(score);
  868. // This is needed to inverse a following pattern, because of the
  869. // wacky Xalan rules for following from an attribute. See axes108.
  870. // By these rules, following from an attribute is not strictly
  871. // inverseable.
  872. if(Axis.PRECEDING == pat.getAxis())
  873. pat.setAxis(Axis.PRECEDINGANDANCESTOR);
  874. else if(Axis.DESCENDANT == pat.getAxis())
  875. pat.setAxis(Axis.DESCENDANTORSELF);
  876. pat = attrPat;
  877. }
  878. else if(Axis.CHILD == pat.getAxis())
  879. {
  880. // In this case just change the axis.
  881. // pat.setWhatToShow(whatToShow);
  882. pat.setAxis(Axis.ATTRIBUTE);
  883. }
  884. }
  885. axis = nextAxis;
  886. //paxis = nextPaxis;
  887. tail = pat;
  888. }
  889. if(axis < Axis.ALL)
  890. {
  891. StepPattern selfPattern = new ContextMatchStepPattern(axis, paxis);
  892. // We need to keep the new nodetest from affecting the score...
  893. XNumber score = tail.getStaticScore();
  894. tail.setRelativePathPattern(selfPattern);
  895. tail.setStaticScore(score);
  896. selfPattern.setStaticScore(score);
  897. }
  898. if (DEBUG_PATTERN_CREATION)
  899. {
  900. System.out.println("Done loading steps: "+step.toString());
  901. System.out.println("");
  902. }
  903. return step; // start from last pattern?? //firstStep;
  904. }
  905. /**
  906. * Create a StepPattern that is contained within a LocationPath.
  907. *
  908. *
  909. * @param compiler The compiler that holds the syntax tree/op map to
  910. * construct from.
  911. * @param stepOpCodePos The current op code position within the opmap.
  912. * @param mpi The MatchPatternIterator to which the steps will be attached.
  913. * @param analysis 32 bits of analysis, from which the type of AxesWalker
  914. * may be influenced.
  915. * @param tail The step that is the first step analyzed, but the last
  916. * step in the relative match linked list, i.e. the tail.
  917. * May be null.
  918. * @param head The step that is the current head of the relative
  919. * match step linked list.
  920. * May be null.
  921. *
  922. * @return the head of the list.
  923. *
  924. * @throws javax.xml.transform.TransformerException
  925. */
  926. private static StepPattern createDefaultStepPattern(
  927. Compiler compiler, int opPos, MatchPatternIterator mpi,
  928. int analysis, StepPattern tail, StepPattern head)
  929. throws javax.xml.transform.TransformerException
  930. {
  931. int stepType = compiler.getOp(opPos);
  932. boolean simpleInit = false;
  933. int totalNumberWalkers = (analysis & BITS_COUNT);
  934. boolean prevIsOneStepDown = true;
  935. int firstStepPos = compiler.getFirstChildPos(opPos);
  936. int whatToShow = compiler.getWhatToShow(opPos);
  937. StepPattern ai = null;
  938. int axis, predicateAxis;
  939. switch (stepType)
  940. {
  941. case OpCodes.OP_VARIABLE :
  942. case OpCodes.OP_EXTFUNCTION :
  943. case OpCodes.OP_FUNCTION :
  944. case OpCodes.OP_GROUP :
  945. prevIsOneStepDown = false;
  946. Expression expr;
  947. switch (stepType)
  948. {
  949. case OpCodes.OP_VARIABLE :
  950. case OpCodes.OP_EXTFUNCTION :
  951. case OpCodes.OP_FUNCTION :
  952. case OpCodes.OP_GROUP :
  953. expr = compiler.compile(opPos);
  954. break;
  955. default :
  956. expr = compiler.compile(opPos + 2);
  957. }
  958. axis = Axis.FILTEREDLIST;
  959. predicateAxis = Axis.FILTEREDLIST;
  960. ai = new FunctionPattern(expr, axis, predicateAxis);
  961. simpleInit = true;
  962. break;
  963. case OpCodes.FROM_ROOT :
  964. whatToShow = DTMFilter.SHOW_DOCUMENT
  965. | DTMFilter.SHOW_DOCUMENT_FRAGMENT;
  966. axis = Axis.ROOT;
  967. predicateAxis = Axis.ROOT;
  968. ai = new StepPattern(DTMFilter.SHOW_DOCUMENT |
  969. DTMFilter.SHOW_DOCUMENT_FRAGMENT,
  970. axis, predicateAxis);
  971. break;
  972. case OpCodes.FROM_ATTRIBUTES :
  973. whatToShow = DTMFilter.SHOW_ATTRIBUTE;
  974. axis = Axis.PARENT;
  975. predicateAxis = Axis.ATTRIBUTE;
  976. // ai = new StepPattern(whatToShow, Axis.SELF, Axis.SELF);
  977. break;
  978. case OpCodes.FROM_NAMESPACE :
  979. whatToShow = DTMFilter.SHOW_NAMESPACE;
  980. axis = Axis.PARENT;
  981. predicateAxis = Axis.NAMESPACE;
  982. // ai = new StepPattern(whatToShow, axis, predicateAxis);
  983. break;
  984. case OpCodes.FROM_ANCESTORS :
  985. axis = Axis.DESCENDANT;
  986. predicateAxis = Axis.ANCESTOR;
  987. break;
  988. case OpCodes.FROM_CHILDREN :
  989. axis = Axis.PARENT;
  990. predicateAxis = Axis.CHILD;
  991. break;
  992. case OpCodes.FROM_ANCESTORS_OR_SELF :
  993. axis = Axis.DESCENDANTORSELF;
  994. predicateAxis = Axis.ANCESTORORSELF;
  995. break;
  996. case OpCodes.FROM_SELF :
  997. axis = Axis.SELF;
  998. predicateAxis = Axis.SELF;
  999. break;
  1000. case OpCodes.FROM_PARENT :
  1001. axis = Axis.CHILD;
  1002. predicateAxis = Axis.PARENT;
  1003. break;
  1004. case OpCodes.FROM_PRECEDING_SIBLINGS :
  1005. axis = Axis.FOLLOWINGSIBLING;
  1006. predicateAxis = Axis.PRECEDINGSIBLING;
  1007. break;
  1008. case OpCodes.FROM_PRECEDING :
  1009. axis = Axis.FOLLOWING;
  1010. predicateAxis = Axis.PRECEDING;
  1011. break;
  1012. case OpCodes.FROM_FOLLOWING_SIBLINGS :
  1013. axis = Axis.PRECEDINGSIBLING;
  1014. predicateAxis = Axis.FOLLOWINGSIBLING;
  1015. break;
  1016. case OpCodes.FROM_FOLLOWING :
  1017. axis = Axis.PRECEDING;
  1018. predicateAxis = Axis.FOLLOWING;
  1019. break;
  1020. case OpCodes.FROM_DESCENDANTS_OR_SELF :
  1021. axis = Axis.ANCESTORORSELF;
  1022. predicateAxis = Axis.DESCENDANTORSELF;
  1023. break;
  1024. case OpCodes.FROM_DESCENDANTS :
  1025. axis = Axis.ANCESTOR;
  1026. predicateAxis = Axis.DESCENDANT;
  1027. break;
  1028. default :
  1029. throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
  1030. //+ stepType);
  1031. }
  1032. if(null == ai)
  1033. {
  1034. whatToShow = compiler.getWhatToShow(opPos); // %REVIEW%
  1035. ai = new StepPattern(whatToShow, compiler.getStepNS(opPos),
  1036. compiler.getStepLocalName(opPos),
  1037. axis, predicateAxis);
  1038. }
  1039. if (false || DEBUG_PATTERN_CREATION)
  1040. {
  1041. System.out.print("new step: "+ ai);
  1042. System.out.print(", axis: " + Axis.names[ai.getAxis()]);
  1043. System.out.print(", predAxis: " + Axis.names[ai.getAxis()]);
  1044. System.out.print(", what: ");
  1045. System.out.print(" ");
  1046. ai.debugWhatToShow(ai.getWhatToShow());
  1047. }
  1048. int argLen = compiler.getFirstPredicateOpPos(opPos);
  1049. ai.setPredicates(compiler.getCompiledPredicates(argLen));
  1050. return ai;
  1051. }
  1052. /**
  1053. * Analyze a step and give information about it's predicates. Right now this
  1054. * just returns true or false if the step has a predicate.
  1055. *
  1056. * @param compiler non-null reference to compiler object that has processed
  1057. * the XPath operations into an opcode map.
  1058. * @param opPos The opcode position for the step.
  1059. * @param stepType The type of step, one of OP_GROUP, etc.
  1060. *
  1061. * @return true if step has a predicate.
  1062. *
  1063. * @throws javax.xml.transform.TransformerException
  1064. */
  1065. static boolean analyzePredicate(Compiler compiler, int opPos, int stepType)
  1066. throws javax.xml.transform.TransformerException
  1067. {
  1068. int argLen;
  1069. switch (stepType)
  1070. {
  1071. case OpCodes.OP_VARIABLE :
  1072. case OpCodes.OP_EXTFUNCTION :
  1073. case OpCodes.OP_FUNCTION :
  1074. case OpCodes.OP_GROUP :
  1075. argLen = compiler.getArgLength(opPos);
  1076. break;
  1077. default :
  1078. argLen = compiler.getArgLengthOfStep(opPos);
  1079. }
  1080. int pos = compiler.getFirstPredicateOpPos(opPos);
  1081. int nPredicates = compiler.countPredicates(pos);
  1082. return (nPredicates > 0) ? true : false;
  1083. }
  1084. /**
  1085. * Create the proper Walker from the axes type.
  1086. *
  1087. * @param compiler non-null reference to compiler object that has processed
  1088. * the XPath operations into an opcode map.
  1089. * @param opPos The opcode position for the step.
  1090. * @param lpi The owning location path iterator.
  1091. * @param analysis 32 bits of analysis, from which the type of AxesWalker
  1092. * may be influenced.
  1093. *
  1094. * @return non-null reference to AxesWalker derivative.
  1095. * @throws RuntimeException if the input is bad.
  1096. */
  1097. private static AxesWalker createDefaultWalker(Compiler compiler, int opPos,
  1098. WalkingIterator lpi, int analysis)
  1099. {
  1100. AxesWalker ai = null;
  1101. int stepType = compiler.getOp(opPos);
  1102. /*
  1103. System.out.println("0: "+compiler.getOp(opPos));
  1104. System.out.println("1: "+compiler.getOp(opPos+1));
  1105. System.out.println("2: "+compiler.getOp(opPos+2));
  1106. System.out.println("3: "+compiler.getOp(opPos+3));
  1107. System.out.println("4: "+compiler.getOp(opPos+4));
  1108. System.out.println("5: "+compiler.getOp(opPos+5));
  1109. */
  1110. boolean simpleInit = false;
  1111. int totalNumberWalkers = (analysis & BITS_COUNT);
  1112. boolean prevIsOneStepDown = true;
  1113. switch (stepType)
  1114. {
  1115. case OpCodes.OP_VARIABLE :
  1116. case OpCodes.OP_EXTFUNCTION :
  1117. case OpCodes.OP_FUNCTION :
  1118. case OpCodes.OP_GROUP :
  1119. prevIsOneStepDown = false;
  1120. if (DEBUG_WALKER_CREATION)
  1121. System.out.println("new walker: FilterExprWalker: " + analysis
  1122. + ", " + compiler.toString());
  1123. ai = new FilterExprWalker(lpi);
  1124. simpleInit = true;
  1125. break;
  1126. case OpCodes.FROM_ROOT :
  1127. ai = new AxesWalker(lpi, Axis.ROOT);
  1128. break;
  1129. case OpCodes.FROM_ANCESTORS :
  1130. prevIsOneStepDown = false;
  1131. ai = new ReverseAxesWalker(lpi, Axis.ANCESTOR);
  1132. break;
  1133. case OpCodes.FROM_ANCESTORS_OR_SELF :
  1134. prevIsOneStepDown = false;
  1135. ai = new ReverseAxesWalker(lpi, Axis.ANCESTORORSELF);
  1136. break;
  1137. case OpCodes.FROM_ATTRIBUTES :
  1138. ai = new AxesWalker(lpi, Axis.ATTRIBUTE);
  1139. break;
  1140. case OpCodes.FROM_NAMESPACE :
  1141. ai = new AxesWalker(lpi, Axis.NAMESPACE);
  1142. break;
  1143. case OpCodes.FROM_CHILDREN :
  1144. ai = new AxesWalker(lpi, Axis.CHILD);
  1145. break;
  1146. case OpCodes.FROM_DESCENDANTS :
  1147. prevIsOneStepDown = false;
  1148. ai = new AxesWalker(lpi, Axis.DESCENDANT);
  1149. break;
  1150. case OpCodes.FROM_DESCENDANTS_OR_SELF :
  1151. prevIsOneStepDown = false;
  1152. ai = new AxesWalker(lpi, Axis.DESCENDANTORSELF);
  1153. break;
  1154. case OpCodes.FROM_FOLLOWING :
  1155. prevIsOneStepDown = false;
  1156. ai = new AxesWalker(lpi, Axis.FOLLOWING);
  1157. break;
  1158. case OpCodes.FROM_FOLLOWING_SIBLINGS :
  1159. prevIsOneStepDown = false;
  1160. ai = new AxesWalker(lpi, Axis.FOLLOWINGSIBLING);
  1161. break;
  1162. case OpCodes.FROM_PRECEDING :
  1163. prevIsOneStepDown = false;
  1164. ai = new ReverseAxesWalker(lpi, Axis.PRECEDING);
  1165. break;
  1166. case OpCodes.FROM_PRECEDING_SIBLINGS :
  1167. prevIsOneStepDown = false;
  1168. ai = new ReverseAxesWalker(lpi, Axis.PRECEDINGSIBLING);
  1169. break;
  1170. case OpCodes.FROM_PARENT :
  1171. prevIsOneStepDown = false;
  1172. ai = new ReverseAxesWalker(lpi, Axis.PARENT);
  1173. break;
  1174. case OpCodes.FROM_SELF :
  1175. ai = new AxesWalker(lpi, Axis.SELF);
  1176. break;
  1177. default :
  1178. throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
  1179. //+ stepType);
  1180. }
  1181. if (simpleInit)
  1182. {
  1183. ai.initNodeTest(DTMFilter.SHOW_ALL);
  1184. }
  1185. else
  1186. {
  1187. int whatToShow = compiler.getWhatToShow(opPos);
  1188. /*
  1189. System.out.print("construct: ");
  1190. NodeTest.debugWhatToShow(whatToShow);
  1191. System.out.println("or stuff: "+(whatToShow & (DTMFilter.SHOW_ATTRIBUTE
  1192. | DTMFilter.SHOW_ELEMENT
  1193. | DTMFilter.SHOW_PROCESSING_INSTRUCTION)));
  1194. */
  1195. if ((0 == (whatToShow
  1196. & (DTMFilter.SHOW_ATTRIBUTE | DTMFilter.SHOW_NAMESPACE | DTMFilter.SHOW_ELEMENT
  1197. | DTMFilter.SHOW_PROCESSING_INSTRUCTION))) || (whatToShow == DTMFilter.SHOW_ALL))
  1198. ai.initNodeTest(whatToShow);
  1199. else
  1200. {
  1201. ai.initNodeTest(whatToShow, compiler.getStepNS(opPos),
  1202. compiler.getStepLocalName(opPos));
  1203. }
  1204. }
  1205. return ai;
  1206. }
  1207. public static String getAnalysisString(int analysis)
  1208. {
  1209. StringBuffer buf = new StringBuffer();
  1210. buf.append("count: "+getStepCount(analysis)+" ");
  1211. if((analysis & BIT_NODETEST_ANY) != 0)
  1212. {
  1213. buf.append("NTANY|");
  1214. }
  1215. if((analysis & BIT_PREDICATE) != 0)
  1216. {
  1217. buf.append("PRED|");
  1218. }
  1219. if((analysis & BIT_ANCESTOR) != 0)
  1220. {
  1221. buf.append("ANC|");
  1222. }
  1223. if((analysis & BIT_ANCESTOR_OR_SELF) != 0)
  1224. {
  1225. buf.append("ANCOS|");
  1226. }
  1227. if((analysis & BIT_ATTRIBUTE) != 0)
  1228. {
  1229. buf.append("ATTR|");
  1230. }
  1231. if((analysis & BIT_CHILD) != 0)
  1232. {
  1233. buf.append("CH|");
  1234. }
  1235. if((analysis & BIT_DESCENDANT) != 0)
  1236. {
  1237. buf.append("DESC|");
  1238. }
  1239. if((analysis & BIT_DESCENDANT_OR_SELF) != 0)
  1240. {
  1241. buf.append("DESCOS|");
  1242. }
  1243. if((analysis & BIT_FOLLOWING) != 0)
  1244. {
  1245. buf.append("FOL|");
  1246. }
  1247. if((analysis & BIT_FOLLOWING_SIBLING) != 0)
  1248. {
  1249. buf.append("FOLS|");
  1250. }
  1251. if((analysis & BIT_NAMESPACE) != 0)
  1252. {
  1253. buf.append("NS|");
  1254. }
  1255. if((analysis & BIT_PARENT) != 0)
  1256. {
  1257. buf.append("P|");
  1258. }
  1259. if((analysis & BIT_PRECEDING) != 0)
  1260. {
  1261. buf.append("PREC|");
  1262. }
  1263. if((analysis & BIT_PRECEDING_SIBLING) != 0)
  1264. {
  1265. buf.append("PRECS|");
  1266. }
  1267. if((analysis & BIT_SELF) != 0)
  1268. {
  1269. buf.append(".|");
  1270. }
  1271. if((analysis & BIT_FILTER) != 0)
  1272. {
  1273. buf.append("FLT|");
  1274. }
  1275. if((analysis & BIT_ROOT) != 0)
  1276. {
  1277. buf.append("R|");
  1278. }
  1279. return buf.toString();
  1280. }
  1281. /** Set to true for diagnostics about walker creation */
  1282. static final boolean DEBUG_PATTERN_CREATION = false;
  1283. /** Set to true for diagnostics about walker creation */
  1284. static final boolean DEBUG_WALKER_CREATION = false;
  1285. /** Set to true for diagnostics about iterator creation */
  1286. static final boolean DEBUG_ITERATOR_CREATION = false;
  1287. public static boolean hasPredicate(int analysis)
  1288. {
  1289. return (0 != (analysis & BIT_PREDICATE));
  1290. }
  1291. public static boolean isWild(int analysis)
  1292. {
  1293. return (0 != (analysis & BIT_NODETEST_ANY));
  1294. }
  1295. public static boolean walksAncestors(int analysis)
  1296. {
  1297. return isSet(analysis, BIT_ANCESTOR | BIT_ANCESTOR_OR_SELF);
  1298. }
  1299. public static boolean walksAttributes(int analysis)
  1300. {
  1301. return (0 != (analysis & BIT_ATTRIBUTE));
  1302. }
  1303. public static boolean walksNamespaces(int analysis)
  1304. {
  1305. return (0 != (analysis & BIT_NAMESPACE));
  1306. }
  1307. public static boolean walksChildren(int analysis)
  1308. {
  1309. return (0 != (analysis & BIT_CHILD));
  1310. }
  1311. public static boolean walksDescendants(int analysis)
  1312. {
  1313. return isSet(analysis, BIT_DESCENDANT | BIT_DESCENDANT_OR_SELF);
  1314. }
  1315. public static boolean walksSubtree(int analysis)
  1316. {
  1317. return isSet(analysis, BIT_DESCENDANT | BIT_DESCENDANT_OR_SELF | BIT_CHILD);
  1318. }
  1319. public static boolean walksSubtreeOnlyMaybeAbsolute(int analysis)
  1320. {
  1321. return walksSubtree(analysis)
  1322. && !walksExtraNodes(analysis)
  1323. && !walksUp(analysis)
  1324. && !walksSideways(analysis)
  1325. ;
  1326. }
  1327. public static boolean walksSubtreeOnly(int analysis)
  1328. {
  1329. return walksSubtreeOnlyMaybeAbsolute(analysis)
  1330. && !isAbsolute(analysis)
  1331. ;
  1332. }
  1333. public static boolean walksFilteredList(int analysis)
  1334. {
  1335. return isSet(analysis, BIT_FILTER);
  1336. }
  1337. public static boolean walksSubtreeOnlyFromRootOrContext(int analysis)
  1338. {
  1339. return walksSubtree(analysis)
  1340. && !walksExtraNodes(analysis)
  1341. && !walksUp(analysis)
  1342. && !walksSideways(analysis)
  1343. && !isSet(analysis, BIT_FILTER)
  1344. ;
  1345. }
  1346. public static boolean walksInDocOrder(int analysis)
  1347. {
  1348. return (walksSubtreeOnlyMaybeAbsolute(analysis)
  1349. || walksExtraNodesOnly(analysis)
  1350. || walksFollowingOnlyMaybeAbsolute(analysis))
  1351. && !isSet(analysis, BIT_FILTER)
  1352. ;
  1353. }
  1354. public static boolean walksFollowingOnlyMaybeAbsolute(int analysis)
  1355. {
  1356. return isSet(analysis, BIT_SELF | BIT_FOLLOWING_SIBLING | BIT_FOLLOWING)
  1357. && !walksSubtree(analysis)
  1358. && !walksUp(analysis)
  1359. && !walksSideways(analysis)
  1360. ;
  1361. }
  1362. public static boolean walksUp(int analysis)
  1363. {
  1364. return isSet(analysis, BIT_PARENT | BIT_ANCESTOR | BIT_ANCESTOR_OR_SELF);
  1365. }
  1366. public static boolean walksSideways(int analysis)
  1367. {
  1368. return isSet(analysis, BIT_FOLLOWING | BIT_FOLLOWING_SIBLING |
  1369. BIT_PRECEDING | BIT_PRECEDING_SIBLING);
  1370. }
  1371. public static boolean walksExtraNodes(int analysis)
  1372. {
  1373. return isSet(analysis, BIT_NAMESPACE | BIT_ATTRIBUTE);
  1374. }
  1375. public static boolean walksExtraNodesOnly(int analysis)
  1376. {
  1377. return walksExtraNodes(analysis)
  1378. && !isSet(analysis, BIT_SELF)
  1379. && !walksSubtree(analysis)
  1380. && !walksUp(analysis)
  1381. && !walksSideways(analysis)
  1382. && !isAbsolute(analysis)
  1383. ;
  1384. }
  1385. public static boolean isAbsolute(int analysis)
  1386. {
  1387. return isSet(analysis, BIT_ROOT | BIT_FILTER);
  1388. }
  1389. public static boolean walksChildrenOnly(int analysis)
  1390. {
  1391. return walksChildren(analysis)
  1392. && !isSet(analysis, BIT_SELF)
  1393. && !walksExtraNodes(analysis)
  1394. && !walksDescendants(analysis)
  1395. && !walksUp(analysis)
  1396. && !walksSideways(analysis)
  1397. && (!isAbsolute(analysis) || isSet(analysis, BIT_ROOT))
  1398. ;
  1399. }
  1400. public static boolean walksChildrenAndExtraAndSelfOnly(int analysis)
  1401. {
  1402. return walksChildren(analysis)
  1403. && !walksDescendants(analysis)
  1404. && !walksUp(analysis)
  1405. && !walksSideways(analysis)
  1406. && (!isAbsolute(analysis) || isSet(analysis, BIT_ROOT))
  1407. ;
  1408. }
  1409. public static boolean walksDescendantsAndExtraAndSelfOnly(int analysis)
  1410. {
  1411. return !walksChildren(analysis)
  1412. && walksDescendants(analysis)
  1413. && !walksUp(analysis)
  1414. && !walksSideways(analysis)
  1415. && (!isAbsolute(analysis) || isSet(analysis, BIT_ROOT))
  1416. ;
  1417. }
  1418. public static boolean walksSelfOnly(int analysis)
  1419. {
  1420. return isSet(analysis, BIT_SELF)
  1421. && !walksSubtree(analysis)
  1422. && !walksUp(analysis)
  1423. && !walksSideways(analysis)
  1424. && !isAbsolute(analysis)
  1425. ;
  1426. }
  1427. public static boolean walksUpOnly(int analysis)
  1428. {
  1429. return !walksSubtree(analysis)
  1430. && walksUp(analysis)
  1431. && !walksSideways(analysis)
  1432. && !isAbsolute(analysis)
  1433. ;
  1434. }
  1435. public static boolean walksDownOnly(int analysis)
  1436. {
  1437. return walksSubtree(analysis)
  1438. && !walksUp(analysis)
  1439. && !walksSideways(analysis)
  1440. && !isAbsolute(analysis)
  1441. ;
  1442. }
  1443. public static boolean walksDownExtraOnly(int analysis)
  1444. {
  1445. return walksSubtree(analysis) && walksExtraNodes(analysis)
  1446. && !walksUp(analysis)
  1447. && !walksSideways(analysis)
  1448. && !isAbsolute(analysis)
  1449. ;
  1450. }
  1451. public static boolean canSkipSubtrees(int analysis)
  1452. {
  1453. return isSet(analysis, BIT_CHILD) | walksSideways(analysis);
  1454. }
  1455. public static boolean canCrissCross(int analysis)
  1456. {
  1457. // This could be done faster. Coded for clarity.
  1458. if(walksSelfOnly(analysis))
  1459. return false;
  1460. else if(walksDownOnly(analysis) && !canSkipSubtrees(analysis))
  1461. return false;
  1462. else if(walksChildrenAndExtraAndSelfOnly(analysis))
  1463. return false;
  1464. else if(walksDescendantsAndExtraAndSelfOnly(analysis))
  1465. return false;
  1466. else if(walksUpOnly(analysis))
  1467. return false;
  1468. else if(walksExtraNodesOnly(analysis))
  1469. return false;
  1470. else if(walksSubtree(analysis)
  1471. && (walksSideways(analysis)
  1472. || walksUp(analysis)
  1473. || canSkipSubtrees(analysis)))
  1474. return true;
  1475. else
  1476. return false;
  1477. }
  1478. /**
  1479. * Tell if the pattern can be 'walked' with the iteration steps in natural
  1480. * document order, without duplicates.
  1481. *
  1482. * @param analysis The general analysis of the pattern.
  1483. *
  1484. * @return true if the walk can be done in natural order.
  1485. *
  1486. * @throws javax.xml.transform.TransformerException
  1487. */
  1488. static public boolean isNaturalDocOrder(int analysis)
  1489. {
  1490. if(canCrissCross(analysis) || isSet(analysis, BIT_NAMESPACE) ||
  1491. walksFilteredList(analysis))
  1492. return false;
  1493. if(walksInDocOrder(analysis))
  1494. return true;
  1495. return false;
  1496. }
  1497. /**
  1498. * Tell if the pattern can be 'walked' with the iteration steps in natural
  1499. * document order, without duplicates.
  1500. *
  1501. * @param compiler non-null reference to compiler object that has processed
  1502. * the XPath operations into an opcode map.
  1503. * @param stepOpCodePos The opcode position for the step.
  1504. * @param stepIndex The top-level step index withing the iterator.
  1505. * @param analysis The general analysis of the pattern.
  1506. *
  1507. * @return true if the walk can be done in natural order.
  1508. *
  1509. * @throws javax.xml.transform.TransformerException
  1510. */
  1511. private static boolean isNaturalDocOrder(
  1512. Compiler compiler, int stepOpCodePos, int stepIndex, int analysis)
  1513. throws javax.xml.transform.TransformerException
  1514. {
  1515. if(canCrissCross(analysis))
  1516. return false;
  1517. // Namespaces can present some problems, so just punt if we're looking for
  1518. // these.
  1519. if(isSet(analysis, BIT_NAMESPACE))
  1520. return false;
  1521. // The following, preceding, following-sibling, and preceding sibling can
  1522. // be found in doc order if we get to this point, but if they occur
  1523. // together, they produce
  1524. // duplicates, so it's better for us to eliminate this case so we don't
  1525. // have to check for duplicates during runtime if we're using a
  1526. // WalkingIterator.
  1527. if(isSet(analysis, BIT_FOLLOWING | BIT_FOLLOWING_SIBLING) &&
  1528. isSet(analysis, BIT_PRECEDING | BIT_PRECEDING_SIBLING))
  1529. return false;
  1530. // OK, now we have to check for select="@*/axis::*" patterns, which
  1531. // can also cause duplicates to happen. But select="axis*/@::*" patterns
  1532. // are OK, as are select="@foo/axis::*" patterns.
  1533. // Unfortunately, we can't do this just via the analysis bits.
  1534. int stepType;
  1535. int stepCount = 0;
  1536. boolean foundWildAttribute = false;
  1537. // Steps that can traverse anything other than down a
  1538. // subtree or that can produce duplicates when used in
  1539. // combonation are counted with this variable.
  1540. int potentialDuplicateMakingStepCount = 0;
  1541. while (OpCodes.ENDOP != (stepType = compiler.getOp(stepOpCodePos)))
  1542. {
  1543. stepCount++;
  1544. switch (stepType)
  1545. {
  1546. case OpCodes.FROM_ATTRIBUTES :
  1547. case OpCodes.MATCH_ATTRIBUTE :
  1548. if(foundWildAttribute) // Maybe not needed, but be safe.
  1549. return false;
  1550. // This doesn't seem to work as a test for wild card. Hmph.
  1551. // int nodeTestType = compiler.getStepTestType(stepOpCodePos);
  1552. String localName = compiler.getStepLocalName(stepOpCodePos);
  1553. // System.err.println("localName: "+localName);
  1554. if(localName.equals("*"))
  1555. {
  1556. foundWildAttribute = true;
  1557. }
  1558. break;
  1559. case OpCodes.FROM_FOLLOWING :
  1560. case OpCodes.FROM_FOLLOWING_SIBLINGS :
  1561. case OpCodes.FROM_PRECEDING :
  1562. case OpCodes.FROM_PRECEDING_SIBLINGS :
  1563. case OpCodes.FROM_PARENT :
  1564. case OpCodes.OP_VARIABLE :
  1565. case OpCodes.OP_EXTFUNCTION :
  1566. case OpCodes.OP_FUNCTION :
  1567. case OpCodes.OP_GROUP :
  1568. case OpCodes.FROM_NAMESPACE :
  1569. case OpCodes.FROM_ANCESTORS :
  1570. case OpCodes.FROM_ANCESTORS_OR_SELF :
  1571. case OpCodes.MATCH_ANY_ANCESTOR :
  1572. case OpCodes.MATCH_IMMEDIATE_ANCESTOR :
  1573. case OpCodes.FROM_DESCENDANTS_OR_SELF :
  1574. case OpCodes.FROM_DESCENDANTS :
  1575. if(potentialDuplicateMakingStepCount > 0)
  1576. return false;
  1577. potentialDuplicateMakingStepCount++;
  1578. case OpCodes.FROM_ROOT :
  1579. case OpCodes.FROM_CHILDREN :
  1580. case OpCodes.FROM_SELF :
  1581. if(foundWildAttribute)
  1582. return false;
  1583. break;
  1584. default :
  1585. throw new RuntimeException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, new Object[]{Integer.toString(stepType)})); //"Programmer's assertion: unknown opcode: "
  1586. // + stepType);
  1587. }
  1588. int nextStepOpCodePos = compiler.getNextStepPos(stepOpCodePos);
  1589. if (nextStepOpCodePos < 0)
  1590. break;
  1591. stepOpCodePos = nextStepOpCodePos;
  1592. }
  1593. return true;
  1594. }
  1595. public static boolean isOneStep(int analysis)
  1596. {
  1597. return (analysis & BITS_COUNT) == 0x00000001;
  1598. }
  1599. public static int getStepCount(int analysis)
  1600. {
  1601. return (analysis & BITS_COUNT);
  1602. }
  1603. /**
  1604. * First 8 bits are the number of top-level location steps. Hopefully
  1605. * there will never be more that 255 location steps!!!
  1606. */
  1607. public static final int BITS_COUNT = 0x000000FF;
  1608. /** 4 bits are reserved for future use. */
  1609. public static final int BITS_RESERVED = 0x00000F00;
  1610. /** Bit is on if the expression contains a top-level predicate. */
  1611. public static final int BIT_PREDICATE = (0x00001000);
  1612. /** Bit is on if any of the walkers contain an ancestor step. */
  1613. public static final int BIT_ANCESTOR = (0x00001000 << 1);
  1614. /** Bit is on if any of the walkers contain an ancestor-or-self step. */
  1615. public static final int BIT_ANCESTOR_OR_SELF = (0x00001000 << 2);
  1616. /** Bit is on if any of the walkers contain an attribute step. */
  1617. public static final int BIT_ATTRIBUTE = (0x00001000 << 3);
  1618. /** Bit is on if any of the walkers contain a child step. */
  1619. public static final int BIT_CHILD = (0x00001000 << 4);
  1620. /** Bit is on if any of the walkers contain a descendant step. */
  1621. public static final int BIT_DESCENDANT = (0x00001000 << 5);
  1622. /** Bit is on if any of the walkers contain a descendant-or-self step. */
  1623. public static final int BIT_DESCENDANT_OR_SELF = (0x00001000 << 6);
  1624. /** Bit is on if any of the walkers contain a following step. */
  1625. public static final int BIT_FOLLOWING = (0x00001000 << 7);
  1626. /** Bit is on if any of the walkers contain a following-sibiling step. */
  1627. public static final int BIT_FOLLOWING_SIBLING = (0x00001000 << 8);
  1628. /** Bit is on if any of the walkers contain a namespace step. */
  1629. public static final int BIT_NAMESPACE = (0x00001000 << 9);
  1630. /** Bit is on if any of the walkers contain a parent step. */
  1631. public static final int BIT_PARENT = (0x00001000 << 10);
  1632. /** Bit is on if any of the walkers contain a preceding step. */
  1633. public static final int BIT_PRECEDING = (0x00001000 << 11);
  1634. /** Bit is on if any of the walkers contain a preceding-sibling step. */
  1635. public static final int BIT_PRECEDING_SIBLING = (0x00001000 << 12);
  1636. /** Bit is on if any of the walkers contain a self step. */
  1637. public static final int BIT_SELF = (0x00001000 << 13);
  1638. /**
  1639. * Bit is on if any of the walkers contain a filter (i.e. id(), extension
  1640. * function, etc.) step.
  1641. */
  1642. public static final int BIT_FILTER = (0x00001000 << 14);
  1643. /** Bit is on if any of the walkers contain a root step. */
  1644. public static final int BIT_ROOT = (0x00001000 << 15);
  1645. /**
  1646. * If any of these bits are on, the expression may likely traverse outside
  1647. * the given subtree.
  1648. */
  1649. public static final int BITMASK_TRAVERSES_OUTSIDE_SUBTREE = (BIT_NAMESPACE // ??
  1650. | BIT_PRECEDING_SIBLING
  1651. | BIT_PRECEDING
  1652. | BIT_FOLLOWING_SIBLING
  1653. | BIT_FOLLOWING
  1654. | BIT_PARENT // except parent of attrs.
  1655. | BIT_ANCESTOR_OR_SELF
  1656. | BIT_ANCESTOR
  1657. | BIT_FILTER
  1658. | BIT_ROOT);
  1659. /**
  1660. * Bit is on if any of the walkers can go backwards in document
  1661. * order from the context node.
  1662. */
  1663. public static final int BIT_BACKWARDS_SELF = (0x00001000 << 16);
  1664. /** Found "//foo" pattern */
  1665. public static final int BIT_ANY_DESCENDANT_FROM_ROOT = (0x00001000 << 17);
  1666. /**
  1667. * Bit is on if any of the walkers contain an node() test. This is
  1668. * really only useful if the count is 1.
  1669. */
  1670. public static final int BIT_NODETEST_ANY = (0x00001000 << 18);
  1671. // can't go higher than 18!
  1672. /** Bit is on if the expression is a match pattern. */
  1673. public static final int BIT_MATCH_PATTERN = (0x00001000 << 19);
  1674. }