1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the  "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 // Class header file...
20 #include "XPathProcessorImpl.hpp"
21 
22 
23 
24 #include <xercesc/sax/Locator.hpp>
25 
26 
27 
28 #include <xalanc/PlatformSupport/DOMStringHelper.hpp>
29 #include <xalanc/PlatformSupport/DOMStringPrintWriter.hpp>
30 #include <xalanc/PlatformSupport/DoubleSupport.hpp>
31 #include <xalanc/PlatformSupport/PrefixResolver.hpp>
32 #include <xalanc/PlatformSupport/XalanMessageLoader.hpp>
33 #include <xalanc/PlatformSupport/XalanUnicode.hpp>
34 #include <xalanc/PlatformSupport/XalanXMLChar.hpp>
35 
36 
37 
38 #include <xalanc/DOMSupport/DOMServices.hpp>
39 
40 
41 
42 #include "XalanQName.hpp"
43 #include "XPathEnvSupport.hpp"
44 #include "XPathFunctionTable.hpp"
45 #include "XPathConstructionContext.hpp"
46 #include "XPathExecutionContext.hpp"
47 #include "XPathParserException.hpp"
48 
49 
50 
51 namespace XALAN_CPP_NAMESPACE {
52 
53 
54 
XPathProcessorImpl(MemoryManager & theManager)55 XPathProcessorImpl::XPathProcessorImpl(MemoryManager&   theManager) :
56     m_token(theManager),
57     m_tokenChar(0),
58     m_xpath(0),
59     m_constructionContext(0),
60     m_expression(0),
61     m_prefixResolver(0),
62     m_requireLiterals(false),
63     m_isMatchPattern(false),
64     m_positionPredicateStack(theManager),
65     m_namespaces(theManager),
66     m_allowVariableReferences(true),
67     m_allowKeyFunction(true)
68 {
69 }
70 
71 
72 
73 XPathProcessorImpl*
create(MemoryManager & theManager)74 XPathProcessorImpl::create(MemoryManager&   theManager)
75 {
76     typedef XPathProcessorImpl ThisType;
77 
78     XalanAllocationGuard    theGuard(theManager, theManager.allocate(sizeof(ThisType)));
79 
80     ThisType* const     theResult =
81         new (theGuard.get()) ThisType(theManager);
82 
83     theGuard.release();
84 
85     return theResult;
86 }
87 
88 
89 
~XPathProcessorImpl()90 XPathProcessorImpl::~XPathProcessorImpl()
91 {
92 }
93 
94 
95 
96 void
initXPath(XPath & pathObj,XPathConstructionContext & constructionContext,const XalanDOMString & expression,const PrefixResolver & resolver,const Locator * locator,bool allowVariableReferences,bool allowKeyFunction)97 XPathProcessorImpl::initXPath(
98             XPath&                      pathObj,
99             XPathConstructionContext&   constructionContext,
100             const XalanDOMString&       expression,
101             const PrefixResolver&       resolver,
102             const Locator*              locator,
103             bool                        allowVariableReferences,
104             bool                        allowKeyFunction)
105 {
106     m_isMatchPattern = false;
107 
108     m_requireLiterals = false;
109 
110     m_allowVariableReferences = allowVariableReferences;
111 
112     m_allowKeyFunction = allowKeyFunction;
113 
114     m_xpath = &pathObj;
115 
116     m_constructionContext = &constructionContext;
117 
118     m_expression = &m_xpath->getExpression();
119 
120     m_prefixResolver = &resolver;
121 
122     m_locator = locator;
123 
124     m_expression->reset();
125 
126     tokenize(expression);
127 
128     m_expression->appendOpCode(XPathExpression::eOP_XPATH);
129 
130     nextToken();
131 
132     Expr();
133 
134     if (m_token.empty() == false)
135     {
136         error(XalanMessages::ExtraIllegalTokens);
137     }
138 
139     m_xpath = 0;
140     m_constructionContext = 0;
141     m_expression = 0;
142     m_prefixResolver = 0;
143     m_locator = 0;
144     m_positionPredicateStack.clear();
145     m_namespaces.clear();
146 }
147 
148 
149 
150 void
initMatchPattern(XPath & pathObj,XPathConstructionContext & constructionContext,const XalanDOMString & expression,const PrefixResolver & resolver,const Locator * locator,bool allowVariableReferences,bool allowKeyFunction)151 XPathProcessorImpl::initMatchPattern(
152             XPath&                      pathObj,
153             XPathConstructionContext&   constructionContext,
154             const XalanDOMString&       expression,
155             const PrefixResolver&       resolver,
156             const Locator*              locator,
157             bool                        allowVariableReferences,
158             bool                        allowKeyFunction)
159 {
160     m_isMatchPattern = true;
161 
162     m_allowVariableReferences = allowVariableReferences;
163 
164     m_allowKeyFunction = allowKeyFunction;
165 
166     m_xpath = &pathObj;
167 
168     m_constructionContext = &constructionContext;
169 
170     m_expression = &m_xpath->getExpression();
171 
172     m_prefixResolver = &resolver;
173 
174     m_locator = locator;
175 
176     m_expression->reset();
177 
178     tokenize(expression);
179 
180     m_expression->appendOpCode(XPathExpression::eOP_MATCHPATTERN);
181 
182     nextToken();
183 
184     Pattern();
185 
186     if (m_token.empty() == false)
187     {
188         error(XalanMessages::ExtraIllegalTokens);
189     }
190 
191     // Terminate for safety.
192     m_expression->appendOpCode(XPathExpression::eENDOP);
193 
194     m_expression->shrink();
195 
196     m_xpath = 0;
197     m_constructionContext = 0;
198     m_expression = 0;
199     m_prefixResolver = 0;
200     m_locator = 0;
201     m_positionPredicateStack.clear();
202     m_namespaces.clear();
203 }
204 
205 
206 
207 void
tokenize(const XalanDOMString & pat)208 XPathProcessorImpl::tokenize(const XalanDOMString&  pat)
209 {
210     assert(m_xpath != 0);
211     assert(m_expression != 0);
212     assert(m_constructionContext != 0);
213 
214     m_expression->setCurrentPattern(m_constructionContext->getPooledString(pat));
215 
216     const t_size_type   nChars = pat.length();
217 
218     t_size_type     startSubstring = XalanDOMString::npos;
219     t_size_type     posOfNSSep = XalanDOMString::npos;
220 
221     const XPathConstructionContext::GetCachedString     theGuard(*m_constructionContext);
222 
223     XalanDOMString&     theToken = theGuard.get();
224 
225     for(t_size_type i = 0; i < nChars; i++)
226     {
227         XalanDOMChar    c = pat[i];
228 
229         switch(c)
230         {
231         case XalanUnicode::charQuoteMark:
232             {
233                 if(startSubstring != XalanDOMString::npos)
234                 {
235                     if(XalanDOMString::npos != posOfNSSep)
236                     {
237                         posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, i);
238                     }
239                     else
240                     {
241                         substring(pat, theToken, startSubstring, i);
242 
243                         addToTokenQueue(theToken);
244                     }
245                 }
246 
247                 startSubstring = i;
248 
249                 for(++i; i < nChars && (c = pat[i]) != XalanUnicode::charQuoteMark; ++i);
250 
251                 if(c == XalanUnicode::charQuoteMark && i < nChars)
252                 {
253                     substring(pat, theToken, startSubstring, i + 1);
254 
255                     addToTokenQueue(theToken);
256 
257                     startSubstring = XalanDOMString::npos;
258                 }
259                 else
260                 {
261                     error(XalanMessages::UnterminatedStringLiteral);
262                 }
263             }
264             break;
265 
266         case XalanUnicode::charApostrophe:
267             {
268                 if(startSubstring != XalanDOMString::npos)
269                 {
270                     if(XalanDOMString::npos != posOfNSSep)
271                     {
272                         posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, i);
273                     }
274                     else
275                     {
276                         substring(pat, theToken, startSubstring, i);
277 
278                         addToTokenQueue(theToken);
279                     }
280                 }
281 
282                 startSubstring = i;
283 
284                 for(++i; i < nChars && (c = pat[i]) != XalanUnicode::charApostrophe; ++i);
285 
286                 if(c == XalanUnicode::charApostrophe && i < nChars)
287                 {
288                     substring(pat, theToken, startSubstring, i + 1);
289 
290                     addToTokenQueue(theToken);
291 
292                     startSubstring = XalanDOMString::npos;
293                 }
294                 else
295                 {
296                     error(XalanMessages::UnterminatedStringLiteral);
297                 }
298             }
299             break;
300 
301         case XalanUnicode::charLF:
302         case XalanUnicode::charCR:
303         case XalanUnicode::charSpace:
304         case XalanUnicode::charHTab:
305             {
306                 if(startSubstring != XalanDOMString::npos)
307                 {
308                     if(XalanDOMString::npos != posOfNSSep)
309                     {
310                         posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, i);
311                     }
312                     else
313                     {
314                         substring(pat, theToken, startSubstring, i);
315 
316                         addToTokenQueue(theToken);
317                     }
318 
319                     startSubstring = XalanDOMString::npos;
320                 }
321             }
322             break;
323 
324         case XalanUnicode::charHyphenMinus:
325             {
326                 if(!(startSubstring == XalanDOMString::npos))
327                 {
328                     break;
329                 }
330             }
331             // fall-through on purpose
332 
333         case XalanUnicode::charCommercialAt:
334         case XalanUnicode::charLeftParenthesis:
335         case XalanUnicode::charLeftSquareBracket:
336         case XalanUnicode::charRightParenthesis:
337         case XalanUnicode::charRightSquareBracket:
338         case XalanUnicode::charVerticalLine:
339         case XalanUnicode::charSolidus:
340         case XalanUnicode::charAsterisk:
341         case XalanUnicode::charPlusSign:
342         case XalanUnicode::charEqualsSign:
343         case XalanUnicode::charComma:
344         case XalanUnicode::charReverseSolidus: // Unused at the moment
345         case XalanUnicode::charCircumflexAccent: // Unused at the moment
346         case XalanUnicode::charExclamationMark: // Unused at the moment
347         case XalanUnicode::charDollarSign:
348         case XalanUnicode::charLessThanSign:
349         case XalanUnicode::charGreaterThanSign:
350             {
351                 if(startSubstring != XalanDOMString::npos)
352                 {
353                     if(XalanDOMString::npos != posOfNSSep)
354                     {
355                         posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, i);
356                     }
357                     else
358                     {
359                         substring(pat, theToken, startSubstring, i);
360 
361                         addToTokenQueue(theToken);
362                     }
363 
364                     startSubstring = XalanDOMString::npos;
365                 }
366 
367                 substring(pat, theToken, i, i + 1);
368 
369                 addToTokenQueue(theToken);
370             }
371             break;
372 
373         case XalanUnicode::charColon:
374             {
375                 if(posOfNSSep == i - 1 && i > 0)
376                 {
377                     if(startSubstring != XalanDOMString::npos)
378                     {
379                         if (startSubstring < i - 1)
380                         {
381                             substring(pat, theToken, startSubstring, i - 1);
382 
383                             addToTokenQueue(theToken);
384                         }
385                     }
386 
387                     startSubstring = XalanDOMString::npos;
388                     posOfNSSep = XalanDOMString::npos;
389 
390                     substring(pat, theToken, i - 1, i + 1);
391 
392                     addToTokenQueue(theToken);
393                     break;
394                 }
395                 else
396                 {
397                     posOfNSSep = i;
398                 }
399             }
400             // fall through on purpose
401 
402 
403         default:
404             {
405                 if(XalanDOMString::npos == startSubstring)
406                 {
407                     startSubstring = i;
408 
409                     if (XalanXMLChar::isDigit(c) == true)
410                     {
411                         bool    gotFullStop = false;
412 
413                         while(i < nChars - 1)
414                         {
415                             ++i;
416 
417                             const XalanDOMChar  currentChar = pat[i];
418 
419                             if (currentChar == XalanUnicode::charFullStop)
420                             {
421                                 if (gotFullStop == false)
422                                 {
423                                     gotFullStop = true;
424                                 }
425                                 else
426                                 {
427                                     --i;
428 
429                                     break;
430                                 }
431                             }
432                             else if (XalanXMLChar::isDigit(currentChar) == false)
433                             {
434                                 --i;
435 
436                                 break;
437                             }
438                         }
439 
440                         substring(pat, theToken, startSubstring, i + 1);
441 
442                         addToTokenQueue(theToken);
443 
444                         startSubstring = XalanDOMString::npos;
445                     }
446                 }
447             }
448         }
449     }
450 
451     if(startSubstring != XalanDOMString::npos)
452     {
453         if(XalanDOMString::npos != posOfNSSep)
454         {
455             posOfNSSep = mapNSTokens(pat, startSubstring, posOfNSSep, nChars);
456         }
457         else
458         {
459             substring(pat, theToken, startSubstring, nChars);
460 
461             addToTokenQueue(theToken);
462         }
463     }
464 
465     if (0 == m_expression->tokenQueueSize())
466     {
467         error(XalanMessages::EmptyExpression);
468 
469     }
470 
471     m_expression->resetTokenPosition();
472 }
473 
474 
475 
476 void
addToTokenQueue(const XalanDOMString & s) const477 XPathProcessorImpl::addToTokenQueue(const XalanDOMString&   s) const
478 {
479     assert(m_xpath != 0);
480     assert(m_expression != 0);
481 
482     m_expression->pushToken(m_constructionContext->getPooledString(s));
483 }
484 
485 
486 
487 void
replaceTokenWithNamespaceToken() const488 XPathProcessorImpl::replaceTokenWithNamespaceToken() const
489 {
490     assert(m_xpath != 0);
491     assert(m_expression != 0);
492     assert(m_token.empty() == false);
493 
494     StringToStringMapType::const_iterator   i = m_namespaces.find(m_token);
495     assert(i != m_namespaces.end());
496 
497     const XalanDOMString* const     theNamespaceURI = (*i).second;
498     assert(theNamespaceURI != 0 && theNamespaceURI->empty() == false);
499 
500     m_expression->replaceRelativeToken(
501             1,
502             XPathExpression::eRelativeBackward,
503             m_constructionContext->getPooledString(*theNamespaceURI));
504 }
505 
506 
507 
508 XPathProcessorImpl::t_size_type
mapNSTokens(const XalanDOMString & pat,t_size_type startSubstring,t_size_type posOfNSSep,t_size_type posOfScan)509 XPathProcessorImpl::mapNSTokens(
510             const XalanDOMString&   pat,
511             t_size_type             startSubstring,
512             t_size_type             posOfNSSep,
513             t_size_type             posOfScan)
514 {
515     assert(m_prefixResolver != 0);
516 
517     const XPathConstructionContext::GetCachedString     theGuard(*m_constructionContext);
518 
519     XalanDOMString&     scratchString = theGuard.get();
520 
521     // Get the prefix of the QName...
522     scratchString.assign(pat, startSubstring, posOfNSSep - startSubstring);
523 
524     if (XalanQName::isValidNCName(scratchString) == false)
525     {
526         error(
527             XalanMessages::IsNotValidNCName_1Param,
528             scratchString);
529 
530     }
531 
532     const XalanDOMString* const     uName =
533                 m_prefixResolver->getNamespaceForPrefix(scratchString);
534 
535     if(uName == 0)
536     {
537         error(
538             XalanMessages::PrefixIsNotDeclared_1Param,
539             scratchString);
540     }
541     else if (uName->empty() == true)
542     {
543         error(
544             XalanMessages::PrefixIsBoundToZeroLengthURI_1Param,
545             scratchString);
546     }
547     else
548     {
549         m_namespaces[scratchString] = uName;
550 
551         addToTokenQueue(scratchString);
552 
553         addToTokenQueue(DOMServices::s_XMLNamespaceSeparatorString);
554 
555         // If there's no local part, then don't bother.  We need to check
556         // this because '*' tokenizes separately, which means "ns:*" tokenizes
557         // differently from "ns:foo".  In the first case, '*' will be tokenized
558         // _after_ this code, in the second 'ns:foo' will be split into tokens
559         // here...
560         if(posOfNSSep + 1 < posOfScan)
561         {
562             scratchString.assign(pat, posOfNSSep + 1, posOfScan - (posOfNSSep + 1));
563 
564             assert(scratchString.empty() == false);
565 
566             if (XalanQName::isValidNCName(scratchString) == false)
567             {
568                 error(
569                     XalanMessages::NotValidNCName_1Param,
570                     scratchString);
571             }
572             else
573             {
574                 addToTokenQueue(scratchString);
575             }
576         }
577     }
578 
579     return XalanDOMString::npos;
580 }
581 
582 
583 
584 bool
tokenIs(const XalanDOMString & s) const585 XPathProcessorImpl::tokenIs(const XalanDOMString&   s) const
586 {
587     return equals(m_token, s);
588 }
589 
590 
591 
592 bool
tokenIs(const XalanDOMChar * s) const593 XPathProcessorImpl::tokenIs(const XalanDOMChar*     s) const
594 {
595     return equals(m_token, s);
596 }
597 
598 
599 
600 bool
tokenIs(XalanDOMChar c) const601 XPathProcessorImpl::tokenIs(XalanDOMChar    c) const
602 {
603     return m_tokenChar == c ? true : false;
604 }
605 
606 
607 
608 bool
lookahead(XalanDOMChar c,int n) const609 XPathProcessorImpl::lookahead(
610             XalanDOMChar    c,
611             int             n) const
612 {
613     const XalanDOMString&   tok =
614         getTokenRelative(n - 1);
615 
616     if (tok.length() == 1 &&
617         tok[0] == c)
618     {
619         return true;
620     }
621     else
622     {
623         return false;
624     }
625 }
626 
627 
628 
629 bool
lookahead(const XalanDOMChar * s,int n) const630 XPathProcessorImpl::lookahead(
631             const XalanDOMChar*     s,
632             int                     n) const
633 {
634     assert(s != 0);
635 
636     const XalanDOMString&   tok =
637         getTokenRelative(n - 1);
638 
639     return equals(tok, s);
640 }
641 
642 
643 
644 bool
lookahead(const XalanDOMString & s,int n) const645 XPathProcessorImpl::lookahead(
646             const XalanDOMString&   s,
647             int                     n) const
648 {
649     const XalanDOMString&   tok =
650         getTokenRelative(n - 1);
651 
652     return equals(tok, s);
653 }
654 
655 
656 
657 bool
lookbehind(char c,int n) const658 XPathProcessorImpl::lookbehind(
659             char    c,
660             int     n) const
661 {
662     const XalanDOMString&   tok =
663         getTokenRelative(-(n + 1));
664 
665     if (tok.length() == 1 &&
666         tok[0] == c)
667     {
668         return true;
669     }
670     else
671     {
672         return false;
673     }
674 }
675 
676 
677 
678 bool
lookbehindHasToken(int n) const679 XPathProcessorImpl::lookbehindHasToken(int  n) const
680 {
681     const XalanDOMString&   tok =
682         getTokenRelative(-(n + 1));
683 
684     const XalanDOMChar      c0 = tok.length() == 0 ?
685         XalanUnicode::charVerticalLine : tok[0];
686 
687     return c0 == XalanUnicode::charVerticalLine ? false : true;
688 }
689 
690 
691 
692 bool
nextToken()693 XPathProcessorImpl::nextToken()
694 {
695     assert(m_expression != 0);
696 
697     const XToken* const     theNextToken =
698             m_expression->getNextToken();
699 
700     if (theNextToken == 0)
701     {
702         m_token.clear();
703     }
704     else
705     {
706         m_token = theNextToken->str();
707     }
708 
709     if(m_token.empty() == false)
710     {
711         m_tokenChar = m_token[0];
712 
713         return true;
714     }
715     else
716     {
717         m_tokenChar = 0;
718 
719         return false;
720     }
721 }
722 
723 
724 
725 void
prevToken()726 XPathProcessorImpl::prevToken()
727 {
728     assert(m_expression != 0);
729 
730     const XToken* const     thePreviousToken =
731             m_expression->getPreviousToken();
732 
733     m_token = thePreviousToken == 0 ? s_emptyString : thePreviousToken->str();
734 
735     if(m_token.empty() == false)
736     {
737         m_tokenChar = m_token[0];
738     }
739     else
740     {
741         m_tokenChar = 0;
742     }
743 }
744 
745 
746 
747 const XalanDOMString&
getTokenRelative(int theOffset) const748 XPathProcessorImpl::getTokenRelative(int    theOffset) const
749 {
750     assert(m_expression != 0);
751 
752     const XToken*   theToken = 0;
753 
754     if (theOffset < 0)
755     {
756         theToken =
757             m_expression->getRelativeToken(
758                     XPathExpression::TokenQueueSizeType(-theOffset),
759                     XPathExpression::eRelativeBackward);
760     }
761     else
762     {
763         theToken =
764             m_expression->getRelativeToken(
765                     XPathExpression::TokenQueueSizeType(theOffset),
766                     XPathExpression::eRelativeForward);
767     }
768 
769     return theToken == 0 ? s_emptyString : theToken->str();
770 }
771 
772 
773 
774 void
consumeExpected(XalanDOMChar expected)775 XPathProcessorImpl::consumeExpected(XalanDOMChar    expected)
776 {
777     if(tokenIs(expected) == true)
778     {
779         nextToken();
780     }
781     else
782     {
783         error(
784             XalanMessages::NotFoundWhatExpected_2Param,
785             expected,
786             m_token);
787     }
788 }
789 
790 
791 
792 typedef XPathConstructionContext::GetCachedString   GetCachedString;
793 
794 
795 
796 void
error(const XalanDOMString & msg) const797 XPathProcessorImpl::error(const XalanDOMString&     msg) const
798 {
799     assert(m_constructionContext != 0);
800 
801     const GetCachedString   theGuard(*m_constructionContext);
802 
803     XalanDOMString&     emsg = theGuard.get();
804 
805     if (m_expression == 0)
806     {
807         emsg = msg;
808     }
809     else
810     {
811         const XalanDOMString&   theCurrentPattern =
812                 m_expression->getCurrentPattern();
813 
814         DOMStringPrintWriter    thePrintWriter(emsg);
815 
816         thePrintWriter.print(msg);
817 
818         thePrintWriter.println();
819 
820         if (theCurrentPattern.empty() == false)
821         {
822             const GetCachedString   theGuard(*m_constructionContext);
823 
824             XalanDOMString&     theResult = theGuard.get();
825 
826             const XalanMessages::Codes  theCode =
827                             m_isMatchPattern == true ?
828                                 XalanMessages::PatternIs_1Param :
829                                 XalanMessages::ExpressionIs_1Param;
830 
831             thePrintWriter.print(
832                 XalanMessageLoader::getMessage(
833                     theResult,
834                     theCode,
835                     theCurrentPattern));
836         }
837 
838         // Back up one token, since we've consumed one...
839         m_expression->getPreviousToken();
840 
841         // Ask the expression to dump the remaining tokens...
842         m_expression->dumpRemainingTokenQueue(thePrintWriter);
843     }
844 
845     m_constructionContext->problem(
846         XPathConstructionContext::eXPath,
847         XPathConstructionContext::eError,
848         emsg,
849         m_locator,
850         0);
851 
852     throw XPathParserException(
853                 emsg,
854                 m_constructionContext->getMemoryManager(),
855                 m_locator);
856 }
857 
858 
859 
860 void
error(XalanMessages::Codes theCode) const861 XPathProcessorImpl::error(XalanMessages::Codes  theCode) const
862 {
863     assert(m_constructionContext != 0);
864 
865     const GetCachedString   theGuard(*m_constructionContext);
866 
867     error(
868             XalanMessageLoader::getMessage(
869                 theGuard.get(),
870                 theCode));
871 }
872 
873 
874 
875 void
error(XalanMessages::Codes theCode,const XalanDOMString & theToken) const876 XPathProcessorImpl::error(
877             XalanMessages::Codes    theCode,
878             const XalanDOMString&   theToken) const
879 {
880     assert(m_constructionContext != 0);
881 
882     const GetCachedString   theGuard(*m_constructionContext);
883 
884     error(
885             XalanMessageLoader::getMessage(
886                 theGuard.get(),
887                 theCode,
888                 theToken));
889 }
890 
891 
892 
893 void
error(XalanMessages::Codes theCode,const XalanDOMChar * theToken) const894 XPathProcessorImpl::error(
895             XalanMessages::Codes    theCode,
896             const XalanDOMChar*     theToken) const
897 {
898     assert(m_constructionContext != 0);
899 
900     const GetCachedString   theGuard(*m_constructionContext);
901 
902     error(
903             XalanMessageLoader::getMessage(
904                 theGuard.get(),
905                 theCode,
906                 theToken));
907 }
908 
909 
910 
911 void
error(XalanMessages::Codes theCode,XalanDOMChar theToken1,const XalanDOMString & theToken2) const912 XPathProcessorImpl::error(
913             XalanMessages::Codes    theCode,
914             XalanDOMChar            theToken1,
915             const XalanDOMString&   theToken2) const
916 {
917     assert(m_constructionContext != 0);
918 
919     const GetCachedString   theGuard(*m_constructionContext);
920 
921     XalanDOMString&     theResult = theGuard.get();
922 
923     error(
924             XalanMessageLoader::getMessage(
925                 theResult,
926                 theCode,
927                 XalanDOMString(1, theToken1, theResult.getMemoryManager()),
928                 theToken2));
929 }
930 
931 
932 
933 void
Expr()934 XPathProcessorImpl::Expr()
935 {
936     OrExpr();
937 }
938 
939 
940 
941 void
OrExpr()942 XPathProcessorImpl::OrExpr()
943 {
944     const int   opPos = m_expression->opCodeMapLength();
945 
946     AndExpr();
947 
948     if(tokenIs(s_orString) == true)
949     {
950         if (nextToken() == false)
951         {
952             error(XalanMessages::ExpectedToken);
953         }
954         else
955         {
956             m_expression->insertOpCode(
957                 XPathExpression::eOP_OR,
958                 opPos);
959 
960             OrExpr();
961 
962             m_expression->updateOpCodeLength(
963                 XPathExpression::eOP_OR,
964                 opPos);
965         }
966     }
967 }
968 
969 
970 
971 void
AndExpr()972 XPathProcessorImpl::AndExpr()
973 {
974     const int   opPos = m_expression->opCodeMapLength();
975 
976     EqualityExpr();
977 
978     if(tokenIs(s_andString) == true)
979     {
980         if (nextToken() == false)
981         {
982             error(XalanMessages::ExpectedToken);
983         }
984         else
985         {
986             m_expression->insertOpCode(
987                 XPathExpression::eOP_AND,
988                 opPos);
989 
990             AndExpr();
991 
992             m_expression->updateOpCodeLength(
993                 XPathExpression::eOP_AND,
994                 opPos);
995         }
996     }
997 }
998 
999 
1000 
1001 int
EqualityExpr(int opCodePos)1002 XPathProcessorImpl::EqualityExpr(int    opCodePos)
1003 {
1004     int         theOpDisplacement = 0;
1005 
1006     const int   opPos = opCodePos != -1 ? opCodePos : m_expression->opCodeMapLength();
1007 
1008     RelationalExpr();
1009 
1010     XPathExpression::eOpCodes   theOpCode =
1011             XPathExpression::eENDOP;
1012 
1013     bool    foundToken = false;
1014 
1015     if(tokenIs(XalanUnicode::charExclamationMark) &&
1016        lookahead(XalanUnicode::charEqualsSign, 1))
1017     {
1018         nextToken();
1019 
1020         foundToken = nextToken();
1021 
1022         theOpCode = XPathExpression::eOP_NOTEQUALS;
1023     }
1024     else if(tokenIs(XalanUnicode::charEqualsSign))
1025     {
1026         foundToken = nextToken();
1027 
1028         theOpCode = XPathExpression::eOP_EQUALS;
1029     }
1030 
1031     if (theOpCode != XPathExpression::eENDOP)
1032     {
1033         if (foundToken == false)
1034         {
1035             error(XalanMessages::ExpectedToken);
1036         }
1037         else
1038         {
1039             // Save the number of bytes we inserted
1040             // into the map.
1041             const int   theLocalDisplacement =
1042                     m_expression->insertOpCode(theOpCode,
1043                                                opPos);
1044 
1045             // Update the length
1046             m_expression->updateOpCodeLength(theOpCode,
1047                                              opPos);
1048 
1049             // Do the right term of the expression.
1050             theOpDisplacement += EqualityExpr(opPos);
1051 
1052             // If there's any displacement from the right
1053             // term, update the length for a shift. Otherwise,
1054             // just update the length.
1055             if (theOpDisplacement > 0)
1056             {
1057                 m_expression->updateShiftedOpCodeLength(
1058                     theOpCode,
1059                     opPos,
1060                     opPos + theOpDisplacement);
1061             }
1062             else
1063             {
1064                 m_expression->updateOpCodeLength(
1065                     theOpCode,
1066                     opPos);
1067             }
1068 
1069             // Accumulate the displacement.
1070             theOpDisplacement += theLocalDisplacement;
1071         }
1072     }
1073 
1074     return theOpDisplacement;
1075 }
1076 
1077 
1078 
1079 int
RelationalExpr(int opCodePos)1080 XPathProcessorImpl::RelationalExpr(int  opCodePos)
1081 {
1082     int         theOpDisplacement = 0;
1083 
1084     const int   opPos = opCodePos != -1 ? opCodePos : m_expression->opCodeMapLength();
1085 
1086     AdditiveExpr();
1087 
1088     if(m_token.empty() == false)
1089     {
1090         bool    foundToken = false;
1091 
1092         XPathExpression::eOpCodes   theOpCode =
1093             XPathExpression::eENDOP;
1094 
1095         if(tokenIs(XalanUnicode::charLessThanSign) == true)
1096         {
1097             foundToken = nextToken();
1098 
1099             if(tokenIs(XalanUnicode::charEqualsSign) == true)
1100             {
1101                 foundToken = nextToken();
1102 
1103                 theOpCode = XPathExpression::eOP_LTE;
1104             }
1105             else
1106             {
1107                 theOpCode = XPathExpression::eOP_LT;
1108             }
1109         }
1110         else if(tokenIs(XalanUnicode::charGreaterThanSign) == true)
1111         {
1112             foundToken = nextToken();
1113 
1114             if(tokenIs(XalanUnicode::charEqualsSign) == true)
1115             {
1116                 foundToken = nextToken();
1117 
1118                 theOpCode = XPathExpression::eOP_GTE;
1119             }
1120             else
1121             {
1122                 theOpCode = XPathExpression::eOP_GT;
1123             }
1124         }
1125 
1126         if (theOpCode != XPathExpression::eENDOP)
1127         {
1128             if (foundToken == false)
1129             {
1130                 error(XalanMessages::ExpectedToken);
1131             }
1132             else
1133             {
1134                 // Save the number of bytes we inserted
1135                 // into the map.
1136                 const int   theLocalDisplacement =
1137                     m_expression->insertOpCode(theOpCode,
1138                                                opPos);
1139 
1140                 // Update the length
1141                 m_expression->updateOpCodeLength(theOpCode,
1142                                                  opPos);
1143 
1144                 // Do the right term of the expression.
1145                 theOpDisplacement += RelationalExpr(opPos);
1146 
1147                 // If there's any displacement from the right
1148                 // term, update the length for a shift. Otherwise,
1149                 // just update the length.
1150                 if (theOpDisplacement > 0)
1151                 {
1152                     m_expression->updateShiftedOpCodeLength(
1153                         theOpCode,
1154                         opPos,
1155                         opPos + theOpDisplacement);
1156                 }
1157                 else
1158                 {
1159                     m_expression->updateOpCodeLength(
1160                         theOpCode,
1161                         opPos);
1162                 }
1163 
1164                 // Accumulate the displacement.
1165                 theOpDisplacement += theLocalDisplacement;
1166             }
1167         }
1168     }
1169 
1170     return theOpDisplacement;
1171 }
1172 
1173 
1174 
1175 int
AdditiveExpr(int opCodePos)1176 XPathProcessorImpl::AdditiveExpr(int    opCodePos)
1177 {
1178     int         theOpDisplacement = 0;
1179 
1180     const int   opPos = opCodePos != -1 ? opCodePos : m_expression->opCodeMapLength();
1181 
1182     MultiplicativeExpr();
1183 
1184     if(m_token.empty() == false)
1185     {
1186         XPathExpression::eOpCodes   theOpCode =
1187             XPathExpression::eENDOP;
1188 
1189         if(tokenIs(XalanUnicode::charPlusSign) == true)
1190         {
1191             theOpCode = XPathExpression::eOP_PLUS;
1192         }
1193         else if(tokenIs(XalanUnicode::charHyphenMinus) == true)
1194         {
1195             theOpCode = XPathExpression::eOP_MINUS;
1196         }
1197 
1198         if (theOpCode != XPathExpression::eENDOP)
1199         {
1200             if (nextToken() == false)
1201             {
1202                 error(XalanMessages::ExpectedToken);
1203             }
1204             else
1205             {
1206                 // Save the number of bytes we inserted
1207                 // into the map.
1208                 const int   theLocalDisplacement =
1209                     m_expression->insertOpCode(theOpCode,
1210                                                opPos);
1211 
1212             // Update the length
1213             m_expression->updateOpCodeLength(theOpCode,
1214                                              opPos);
1215 
1216             // Do the right term of the expression.
1217             theOpDisplacement += AdditiveExpr(opPos);
1218 
1219                 // If there's any displacement from the right
1220                 // term, update the length for a shift. Otherwise,
1221                 // just update the length.
1222                 if (theOpDisplacement > 0)
1223                 {
1224                     m_expression->updateShiftedOpCodeLength(
1225                         theOpCode,
1226                         opPos,
1227                         opPos + theOpDisplacement);
1228                 }
1229                 else
1230                 {
1231                     m_expression->updateOpCodeLength(
1232                         theOpCode,
1233                         opPos);
1234                 }
1235 
1236             // Accumulate the displacement.
1237             theOpDisplacement += theLocalDisplacement;
1238         }
1239     }
1240     }
1241 
1242     return theOpDisplacement;
1243 }
1244 
1245 
1246 
1247 int
MultiplicativeExpr(int opCodePos)1248 XPathProcessorImpl::MultiplicativeExpr(int  opCodePos)
1249 {
1250     int         theOpDisplacement = 0;
1251 
1252     const int   opPos = opCodePos != -1 ? opCodePos : m_expression->opCodeMapLength();
1253 
1254     UnaryExpr();
1255 
1256     if(m_token.empty() == false)
1257     {
1258         XPathExpression::eOpCodes   theOpCode =
1259             XPathExpression::eENDOP;
1260 
1261         if(tokenIs(XalanUnicode::charAsterisk) == true)
1262         {
1263             theOpCode = XPathExpression::eOP_MULT;
1264         }
1265         else if(tokenIs(s_divString) == true)
1266         {
1267             theOpCode = XPathExpression::eOP_DIV;
1268         }
1269         else if(tokenIs(s_modString) == true)
1270         {
1271             theOpCode = XPathExpression::eOP_MOD;
1272         }
1273 
1274         if (theOpCode != XPathExpression::eENDOP)
1275         {
1276             if (nextToken() == false)
1277             {
1278                 error(XalanMessages::ExpectedToken);
1279             }
1280             else
1281             {
1282                 // Save the number of bytes we inserted
1283                 // into the map.
1284                 const int   theLocalDisplacement =
1285                     m_expression->insertOpCode(theOpCode,
1286                                                opPos);
1287 
1288                 // Update the length
1289                 m_expression->updateOpCodeLength(theOpCode,
1290                                                  opPos);
1291 
1292             // Do the right term of the expression.
1293             theOpDisplacement += MultiplicativeExpr(opPos);
1294 
1295                 // If there's any displacement from the right
1296                 // term, update the length for a shift. Otherwise,
1297                 // just update the length.
1298                 if (theOpDisplacement > 0)
1299                 {
1300                     m_expression->updateShiftedOpCodeLength(
1301                         theOpCode,
1302                         opPos,
1303                         opPos + theOpDisplacement);
1304                 }
1305                 else
1306                 {
1307                     m_expression->updateOpCodeLength(
1308                         theOpCode,
1309                         opPos);
1310                 }
1311 
1312             // Accumulate the displacement.
1313             theOpDisplacement += theLocalDisplacement;
1314         }
1315     }
1316     }
1317 
1318     return theOpDisplacement;
1319 }
1320 
1321 
1322 
1323 void
UnaryExpr()1324 XPathProcessorImpl::UnaryExpr()
1325 {
1326     const int   opPos = m_expression->opCodeMapLength();
1327 
1328     bool        isNeg = false;
1329 
1330     if(tokenIs(XalanUnicode::charHyphenMinus) == true)
1331     {
1332         nextToken();
1333 
1334         m_expression->insertOpCode(XPathExpression::eOP_NEG,
1335                                    opPos);
1336 
1337         isNeg = true;
1338     }
1339 
1340     UnionExpr();
1341 
1342     if(isNeg == true)
1343     {
1344         m_expression->updateOpCodeLength(XPathExpression::eOP_NEG,
1345                                          opPos);
1346     }
1347 }
1348 
1349 
1350 
1351 void
UnionExpr()1352 XPathProcessorImpl::UnionExpr()
1353 {
1354     const int   opPos = m_expression->opCodeMapLength();
1355 
1356     bool        continueOrLoop = true;
1357     bool        foundUnion = false;
1358 
1359     do
1360     {
1361         PathExpr();
1362 
1363         if(tokenIs(XalanUnicode::charVerticalLine) == true)
1364         {
1365             if(false == foundUnion)
1366             {
1367                 foundUnion = true;
1368 
1369                 m_expression->insertOpCode(XPathExpression::eOP_UNION,
1370                                            opPos);
1371             }
1372 
1373             nextToken();
1374         }
1375         else
1376         {
1377             if (foundUnion == true)
1378             {
1379                 // Terminate for safety.
1380                 m_expression->appendOpCode(XPathExpression::eENDOP);
1381             }
1382 
1383             break;
1384         }
1385     }
1386     while(continueOrLoop == true);
1387 
1388     m_expression->updateOpCodeLength(opPos);
1389 }
1390 
1391 
1392 
1393 void
PathExpr()1394 XPathProcessorImpl::PathExpr()
1395 {
1396     assert(m_expression != 0);
1397 
1398     const int   opPos = m_expression->opCodeMapLength();
1399 
1400     FilterExpr();
1401 
1402     if(tokenIs(XalanUnicode::charSolidus) == true)
1403     {
1404         nextToken();
1405 
1406         m_expression->insertOpCode(
1407             XPathExpression::eOP_LOCATIONPATH,
1408             opPos);
1409 
1410         RelativeLocationPath();
1411 
1412         m_expression->appendOpCode(XPathExpression::eENDOP);
1413 
1414         m_expression->updateOpCodeLength(
1415             XPathExpression::eOP_LOCATIONPATH,
1416             opPos);
1417     }
1418 }
1419 
1420 
1421 
1422 void
FilterExpr()1423 XPathProcessorImpl::FilterExpr()
1424 {
1425     assert(m_expression != 0);
1426 
1427     const int   opPos = m_expression->opCodeMapLength();
1428 
1429     //  const bool  isFunc = lookahead(XalanUnicode::charLeftParenthesis, 1);
1430 
1431     PrimaryExpr();
1432 
1433     if(tokenIs(XalanUnicode::charLeftSquareBracket) == true)
1434     {
1435         m_expression->insertOpCode(XPathExpression::eOP_LOCATIONPATH,
1436                                    opPos);
1437 
1438         while(tokenIs(XalanUnicode::charLeftSquareBracket) == true)
1439         {
1440             Predicate();
1441         }
1442 
1443         if(tokenIs(XalanUnicode::charSolidus) == true)
1444         {
1445             nextToken();
1446 
1447             RelativeLocationPath();
1448         }
1449 
1450         // Terminate for safety.
1451         m_expression->appendOpCode(XPathExpression::eENDOP);
1452 
1453         m_expression->updateOpCodeLength(XPathExpression::eOP_LOCATIONPATH,
1454                                          opPos);
1455     }
1456 }
1457 
1458 
1459 
1460 void
PrimaryExpr()1461 XPathProcessorImpl::PrimaryExpr()
1462 {
1463     assert(m_expression != 0);
1464 
1465     const int   opPos = m_expression->opCodeMapLength();
1466 
1467     if(tokenIs(XalanUnicode::charApostrophe) == true ||
1468        tokenIs(XalanUnicode::charQuoteMark) == true)
1469     {
1470         m_expression->appendOpCode(XPathExpression::eOP_LITERAL);
1471 
1472         Literal();
1473 
1474         m_expression->updateOpCodeLength(
1475             XPathExpression::eOP_LITERAL,
1476             opPos);
1477     }
1478     else if(tokenIs(XalanUnicode::charDollarSign) == true)
1479     {
1480         nextToken(); // consume '$'
1481 
1482         if (m_allowVariableReferences == false)
1483         {
1484             error(XalanMessages::VariableReferenceNotAllowed);
1485         }
1486         else
1487         {
1488             m_expression->appendOpCode(XPathExpression::eOP_VARIABLE);
1489 
1490             QName();
1491 
1492             m_expression->updateOpCodeLength(
1493                 XPathExpression::eOP_VARIABLE,
1494                 opPos);
1495         }
1496     }
1497     else if(tokenIs(XalanUnicode::charLeftParenthesis) == true)
1498     {
1499         nextToken();
1500 
1501         m_expression->appendOpCode(XPathExpression::eOP_GROUP);
1502 
1503         Expr();
1504 
1505         consumeExpected(XalanUnicode::charRightParenthesis);
1506 
1507         m_expression->updateOpCodeLength(
1508             XPathExpression::eOP_GROUP,
1509             opPos);
1510     }
1511     else if((tokenIs(XalanUnicode::charFullStop) == true &&
1512                 m_token.length() > 1 &&
1513                 XalanXMLChar::isDigit(m_token[1]) == true) ||
1514                 XalanXMLChar::isDigit(m_tokenChar) == true)
1515     {
1516         m_expression->appendOpCode(XPathExpression::eOP_NUMBERLIT);
1517 
1518         Number();
1519 
1520         m_expression->updateOpCodeLength(
1521             XPathExpression::eOP_NUMBERLIT,
1522             opPos);
1523     }
1524     else if(lookahead(XalanUnicode::charLeftParenthesis, 1) == true ||
1525             (lookahead(XalanUnicode::charColon, 1) == true && lookahead(XalanUnicode::charLeftParenthesis, 3) == true))
1526     {
1527         FunctionCall();
1528     }
1529     else
1530     {
1531         LocationPath();
1532     }
1533 }
1534 
1535 
1536 
1537 void
Argument()1538 XPathProcessorImpl::Argument()
1539 {
1540     assert(m_expression != 0);
1541 
1542     if (m_requireLiterals == false ||
1543         isCurrentLiteral() == true)
1544     {
1545         Expr();
1546     }
1547     else
1548     {
1549         error(XalanMessages::LiteralArgumentIsRequired);
1550     }
1551 }
1552 
1553 
1554 
1555 int
FunctionCallArguments()1556 XPathProcessorImpl::FunctionCallArguments()
1557 {
1558     int     argCount = 0;
1559 
1560     consumeExpected(XalanUnicode::charLeftParenthesis);
1561 
1562     while(tokenIs(XalanUnicode::charRightParenthesis) == false &&
1563           m_token.empty() == false)
1564     {
1565         if(tokenIs(XalanUnicode::charComma) == true)
1566         {
1567             error(XalanMessages::NoPrecedingArgument);
1568         }
1569 
1570         Argument();
1571 
1572         ++argCount;
1573 
1574         if(tokenIs(XalanUnicode::charRightParenthesis) == false)
1575         {
1576             consumeExpected(XalanUnicode::charComma);
1577 
1578             if(tokenIs(XalanUnicode::charRightParenthesis) == true)
1579             {
1580                 error(XalanMessages::NoFollowingArgument);
1581             }
1582         }
1583     }
1584 
1585     consumeExpected(XalanUnicode::charRightParenthesis);
1586 
1587     return argCount;
1588 }
1589 
1590 
1591 
1592 void
FunctionCall()1593 XPathProcessorImpl::FunctionCall()
1594 {
1595     assert(m_expression != 0);
1596 
1597     const int   opPos = m_expression->opCodeMapLength();
1598 
1599     if(lookahead(XalanUnicode::charColon, 1) == true)
1600     {
1601         m_expression->appendOpCode(XPathExpression::eOP_EXTFUNCTION);
1602 
1603         XPathExpression::OpCodeMapValueVectorType   theArgs(2, 0, m_constructionContext->getMemoryManager());
1604 
1605         // Replace the token in the queue with the actual namespace URI...
1606         replaceTokenWithNamespaceToken();
1607 
1608         theArgs[0] = m_expression->getTokenPosition() - 1;
1609 
1610         nextToken();
1611 
1612         consumeExpected(XalanUnicode::charColon);
1613 
1614         theArgs[1] = m_expression->getTokenPosition() - 1;
1615 
1616         m_expression->setOpCodeArgs(XPathExpression::eOP_EXTFUNCTION,
1617                                     opPos,
1618                                     theArgs);
1619 
1620         nextToken();
1621 
1622         FunctionCallArguments();
1623     }
1624     else
1625     {
1626         if (isValidFunction(m_token) == false)
1627         {
1628             error(
1629                 XalanMessages::CouldNotFindFunction_1Param,
1630                 m_token);
1631 
1632         }
1633 
1634         const XPathExpression::eOpCodes     funcTok = getFunctionToken(m_token);
1635 
1636         switch(funcTok)
1637         {
1638         case XPathExpression::eNODETYPE_PI:
1639         case XPathExpression::eNODETYPE_COMMENT:
1640         case XPathExpression::eNODETYPE_TEXT:
1641         case XPathExpression::eNODETYPE_NODE:
1642             LocationPath();
1643             // ************** Nasty return here!!! *********************** //
1644             return;
1645             break;
1646 
1647         case XPathExpression::eOP_FUNCTION_POSITION:
1648             FunctionPosition();
1649             break;
1650 
1651         case XPathExpression::eOP_FUNCTION_LAST:
1652             FunctionLast();
1653             break;
1654 
1655         case XPathExpression::eOP_FUNCTION_COUNT:
1656             FunctionCount();
1657             break;
1658 
1659         case XPathExpression::eOP_FUNCTION_NOT:
1660             FunctionNot();
1661             break;
1662 
1663         case XPathExpression::eOP_FUNCTION_TRUE:
1664             FunctionTrue();
1665             break;
1666 
1667         case XPathExpression::eOP_FUNCTION_FALSE:
1668             FunctionFalse();
1669             break;
1670 
1671         case XPathExpression::eOP_FUNCTION_BOOLEAN:
1672             FunctionBoolean();
1673             break;
1674 
1675         case XPathExpression::eOP_FUNCTION_NAME_0:
1676             FunctionName(opPos);
1677             break;
1678 
1679         case XPathExpression::eOP_FUNCTION_LOCALNAME_0:
1680             FunctionLocalName(opPos);
1681             break;
1682 
1683         case XPathExpression::eOP_FUNCTION_NUMBER_0:
1684             FunctionNumber(opPos);
1685             break;
1686 
1687         case XPathExpression::eOP_FUNCTION_FLOOR:
1688             FunctionFloor();
1689             break;
1690 
1691         case XPathExpression::eOP_FUNCTION_CEILING:
1692             FunctionCeiling();
1693             break;
1694 
1695         case XPathExpression::eOP_FUNCTION_ROUND:
1696             FunctionRound();
1697             break;
1698 
1699         case XPathExpression::eOP_FUNCTION_STRINGLENGTH_0:
1700             FunctionStringLength(opPos);
1701             break;
1702 
1703         case XPathExpression::eOP_FUNCTION_SUM:
1704             FunctionSum();
1705             break;
1706 
1707         default:
1708             {
1709                 // The position must be at least 1, since
1710                 // we've looked at a token.
1711                 assert(m_expression->getTokenPosition() > 0);
1712 
1713                 if (m_allowKeyFunction == false &&
1714                     m_token == XPathFunctionTable::s_key)
1715                 {
1716                     error(XalanMessages::KeyFunctionNotAllowed);
1717                 }
1718 
1719                 int     theFunctionID =
1720                     XPath::getFunctionTable().nameToID(m_token);
1721 
1722                 if ((equals(m_token, s_positionString) == true ||
1723                      equals(m_token, s_lastString) == true) &&
1724                     m_positionPredicateStack.empty() == false)
1725                 {
1726                     m_positionPredicateStack.back() = true;
1727                 }
1728 
1729                 XPathExpression::OpCodeMapValueVectorType   theArgs(2, 0, m_constructionContext->getMemoryManager());
1730 
1731                 theArgs[0] = theFunctionID;
1732                 theArgs[1] = 0;
1733 
1734                 m_expression->appendOpCode(
1735                         XPathExpression::eOP_FUNCTION,
1736                         theArgs);
1737 
1738                 nextToken();
1739 
1740                 // Get the arguments, and the argument count...
1741                 const int   argCount = FunctionCallArguments();
1742 
1743                 assert(m_expression->getOpCodeMapValue(opPos + 3) == 0);
1744 
1745                 // update the arg count in the op map...
1746                 m_expression->setOpCodeMapValue(opPos + 3, argCount);
1747             }
1748         }
1749     }
1750 
1751     // Terminate for safety.
1752     m_expression->appendOpCode(XPathExpression::eENDOP);
1753 
1754     m_expression->updateOpCodeLength(opPos);
1755 }
1756 
1757 
1758 
1759 void
FunctionPosition()1760 XPathProcessorImpl::FunctionPosition()
1761 {
1762     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_POSITION);
1763 
1764     // Consume the name...
1765     nextToken();
1766 
1767     // Get the arguments, and the argument count...
1768     const int   argCount = FunctionCallArguments();
1769 
1770     if (argCount != 0)
1771     {
1772         XalanDOMString  theResult(m_constructionContext->getMemoryManager());
1773 
1774         error(
1775             XalanMessages::FunctionDoesNotAcceptAnyArguments_1Param,
1776             XPathFunctionTable::s_position);
1777     }
1778     else
1779     {
1780         if (m_positionPredicateStack.empty() == false)
1781         {
1782             m_positionPredicateStack.back() = true;
1783         }
1784     }
1785 }
1786 
1787 
1788 
1789 void
FunctionLast()1790 XPathProcessorImpl::FunctionLast()
1791 {
1792     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_LAST);
1793 
1794     // Consume the name...
1795     nextToken();
1796 
1797     // Get the arguments, and the argument count...
1798     const int   argCount = FunctionCallArguments();
1799 
1800     if (argCount != 0)
1801     {
1802         error(
1803             XalanMessages::FunctionDoesNotAcceptAnyArguments_1Param,
1804             XPathFunctionTable::s_last);
1805     }
1806     else
1807     {
1808         if (m_positionPredicateStack.empty() == false)
1809         {
1810             m_positionPredicateStack.back() = true;
1811         }
1812     }
1813 }
1814 
1815 
1816 
1817 void
FunctionCount()1818 XPathProcessorImpl::FunctionCount()
1819 {
1820     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_COUNT);
1821 
1822     // Consume the name...
1823     nextToken();
1824 
1825     // Get the arguments, and the argument count...
1826     const int   argCount = FunctionCallArguments();
1827 
1828     if (argCount != 1)
1829     {
1830         error(
1831             XalanMessages::FunctionAcceptsOneArgument_1Param,
1832             XPathFunctionTable::s_count);
1833     }
1834 }
1835 
1836 
1837 
1838 void
FunctionNot()1839 XPathProcessorImpl::FunctionNot()
1840 {
1841     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_NOT);
1842 
1843     // Consume the name...
1844     nextToken();
1845 
1846     // Get the arguments, and the argument count...
1847     const int   argCount = FunctionCallArguments();
1848 
1849     if (argCount != 1)
1850     {
1851         error(
1852             XalanMessages::FunctionAcceptsOneArgument_1Param,
1853             XPathFunctionTable::s_not);
1854     }
1855 }
1856 
1857 
1858 
1859 void
FunctionTrue()1860 XPathProcessorImpl::FunctionTrue()
1861 {
1862     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_TRUE);
1863 
1864     // Consume the name...
1865     nextToken();
1866 
1867     // Get the arguments, and the argument count...
1868     const int   argCount = FunctionCallArguments();
1869 
1870     if (argCount != 0)
1871     {
1872         error(
1873             XalanMessages::FunctionDoesNotAcceptAnyArguments_1Param,
1874             XPathFunctionTable::s_true);
1875     }
1876 }
1877 
1878 
1879 
1880 void
FunctionFalse()1881 XPathProcessorImpl::FunctionFalse()
1882 {
1883     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_FALSE);
1884 
1885     // Consume the name...
1886     nextToken();
1887 
1888     // Get the arguments, and the argument count...
1889     const int   argCount = FunctionCallArguments();
1890 
1891     if (argCount != 0)
1892     {
1893         error(
1894             XalanMessages::FunctionDoesNotAcceptAnyArguments_1Param,
1895             XPathFunctionTable::s_false);
1896     }
1897 }
1898 
1899 
1900 
1901 void
FunctionBoolean()1902 XPathProcessorImpl::FunctionBoolean()
1903 {
1904     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_BOOLEAN);
1905 
1906     // Consume the name...
1907     nextToken();
1908 
1909     // Get the arguments, and the argument count...
1910     const int   argCount = FunctionCallArguments();
1911 
1912     if (argCount != 1)
1913     {
1914         error(
1915             XalanMessages::FunctionAcceptsOneArgument_1Param,
1916             XPathFunctionTable::s_boolean);
1917     }
1918 }
1919 
1920 
1921 
1922 void
FunctionName(int opPos)1923 XPathProcessorImpl::FunctionName(int    opPos)
1924 {
1925     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_NAME_0);
1926 
1927     // Consume the name...
1928     nextToken();
1929 
1930     // Get the arguments, and the argument count...
1931     const int   argCount = FunctionCallArguments();
1932 
1933     if (argCount != 0)
1934     {
1935         if (argCount == 1)
1936         {
1937             m_expression->replaceOpCode(
1938                 opPos,
1939                 XPathExpression::eOP_FUNCTION_NAME_0,
1940                 XPathExpression::eOP_FUNCTION_NAME_1);
1941         }
1942         else
1943         {
1944             error(
1945                 XalanMessages::FunctionTakesZeroOrOneArg_1Param,
1946                 XPathFunctionTable::s_name);
1947         }
1948     }
1949 }
1950 
1951 
1952 
1953 void
FunctionLocalName(int opPos)1954 XPathProcessorImpl::FunctionLocalName(int   opPos)
1955 {
1956     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_LOCALNAME_0);
1957 
1958     // Consume the name...
1959     nextToken();
1960 
1961     // Get the arguments, and the argument count...
1962     const int   argCount = FunctionCallArguments();
1963 
1964     if (argCount != 0)
1965     {
1966         if (argCount == 1)
1967         {
1968             m_expression->replaceOpCode(
1969                 opPos,
1970                 XPathExpression::eOP_FUNCTION_LOCALNAME_0,
1971                 XPathExpression::eOP_FUNCTION_LOCALNAME_1);
1972         }
1973         else
1974         {
1975             error(
1976                 XalanMessages::FunctionTakesZeroOrOneArg_1Param,
1977                 XPathFunctionTable::s_localName);
1978         }
1979     }
1980 }
1981 
1982 
1983 
1984 void
FunctionNumber(int opPos)1985 XPathProcessorImpl::FunctionNumber(int  opPos)
1986 {
1987     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_NUMBER_0);
1988 
1989     // Consume the name...
1990     nextToken();
1991 
1992     // Get the arguments, and the argument count...
1993     const int   argCount = FunctionCallArguments();
1994 
1995     if (argCount != 0)
1996     {
1997         if (argCount == 1)
1998         {
1999             m_expression->replaceOpCode(
2000                 opPos,
2001                 XPathExpression::eOP_FUNCTION_NUMBER_0,
2002                 XPathExpression::eOP_FUNCTION_NUMBER_1);
2003         }
2004         else
2005         {
2006             error(
2007                 XalanMessages::FunctionTakesZeroOrOneArg_1Param,
2008                 XPathFunctionTable::s_number);
2009         }
2010     }
2011 }
2012 
2013 
2014 
2015 void
FunctionFloor()2016 XPathProcessorImpl::FunctionFloor()
2017 {
2018     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_FLOOR);
2019 
2020     // Consume the name...
2021     nextToken();
2022 
2023     // Get the arguments, and the argument count...
2024     const int   argCount = FunctionCallArguments();
2025 
2026     if (argCount != 1)
2027     {
2028         error(
2029             XalanMessages::FunctionAcceptsOneArgument_1Param,
2030             XPathFunctionTable::s_floor);
2031     }
2032 }
2033 
2034 
2035 
2036 void
FunctionCeiling()2037 XPathProcessorImpl::FunctionCeiling()
2038 {
2039     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_CEILING);
2040 
2041     // Consume the name...
2042     nextToken();
2043 
2044     // Get the arguments, and the argument count...
2045     const int   argCount = FunctionCallArguments();
2046 
2047     if (argCount != 1)
2048     {
2049         error(
2050             XalanMessages::FunctionAcceptsOneArgument_1Param,
2051             XPathFunctionTable::s_ceiling);
2052     }
2053 }
2054 
2055 
2056 
2057 void
FunctionRound()2058 XPathProcessorImpl::FunctionRound()
2059 {
2060     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_ROUND);
2061 
2062     // Consume the name...
2063     nextToken();
2064 
2065     // Get the arguments, and the argument count...
2066     const int   argCount = FunctionCallArguments();
2067 
2068     if (argCount != 1)
2069     {
2070         error(
2071             XalanMessages::FunctionAcceptsOneArgument_1Param,
2072             XPathFunctionTable::s_round);
2073     }
2074 }
2075 
2076 
2077 
2078 void
FunctionString(int opPos)2079 XPathProcessorImpl::FunctionString(int  opPos)
2080 {
2081     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_STRING_0);
2082 
2083     // Consume the name...
2084     nextToken();
2085 
2086     // Get the arguments, and the argument count...
2087     const int   argCount = FunctionCallArguments();
2088 
2089     if (argCount != 0)
2090     {
2091         if (argCount == 1)
2092         {
2093             m_expression->replaceOpCode(
2094                 opPos,
2095                 XPathExpression::eOP_FUNCTION_STRING_0,
2096                 XPathExpression::eOP_FUNCTION_STRING_1);
2097         }
2098         else
2099         {
2100             error(
2101                 XalanMessages::FunctionTakesZeroOrOneArg_1Param,
2102                 XPathFunctionTable::s_string);
2103         }
2104     }
2105 }
2106 
2107 
2108 
2109 void
FunctionSum()2110 XPathProcessorImpl::FunctionSum()
2111 {
2112     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_SUM);
2113 
2114     // Consume the name...
2115     nextToken();
2116 
2117     // Get the arguments, and the argument count...
2118     const int   argCount = FunctionCallArguments();
2119 
2120     if (argCount != 1)
2121     {
2122         error(
2123             XalanMessages::FunctionAcceptsOneArgument_1Param,
2124             XPathFunctionTable::s_sum);
2125     }
2126 }
2127 
2128 
2129 
2130 void
FunctionStringLength(int opPos)2131 XPathProcessorImpl::FunctionStringLength(int    opPos)
2132 {
2133     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_STRINGLENGTH_0);
2134 
2135     // Consume the name...
2136     nextToken();
2137 
2138     // Get the arguments, and the argument count...
2139     const int   argCount = FunctionCallArguments();
2140 
2141     if (argCount != 0)
2142     {
2143         if (argCount == 1)
2144         {
2145             m_expression->replaceOpCode(
2146                 opPos,
2147                 XPathExpression::eOP_FUNCTION_STRINGLENGTH_0,
2148                 XPathExpression::eOP_FUNCTION_STRINGLENGTH_1);
2149         }
2150         else
2151         {
2152             error(
2153                 XalanMessages::FunctionTakesZeroOrOneArg_1Param,
2154                 XPathFunctionTable::s_stringLength);
2155         }
2156     }
2157 }
2158 
2159 
2160 
2161 void
FunctionNamespaceURI(int opPos)2162 XPathProcessorImpl::FunctionNamespaceURI(int    opPos)
2163 {
2164     m_expression->appendOpCode(XPathExpression::eOP_FUNCTION_NAMESPACEURI_0);
2165 
2166     // Consume the name...
2167     nextToken();
2168 
2169     // Get the arguments, and the argument count...
2170     const int   argCount = FunctionCallArguments();
2171 
2172     if (argCount != 0)
2173     {
2174         if (argCount == 1)
2175         {
2176             m_expression->replaceOpCode(
2177                 opPos,
2178                 XPathExpression::eOP_FUNCTION_NAMESPACEURI_0,
2179                 XPathExpression::eOP_FUNCTION_NAMESPACEURI_1);
2180         }
2181         else
2182         {
2183             error(
2184                 XalanMessages::FunctionTakesZeroOrOneArg_1Param,
2185                 XPathFunctionTable::s_namespaceUri);
2186         }
2187     }
2188 }
2189 
2190 
2191 
2192 void
LocationPath()2193 XPathProcessorImpl::LocationPath()
2194 {
2195     const int   opPos = m_expression->opCodeMapLength();
2196 
2197     m_expression->appendOpCode(XPathExpression::eOP_LOCATIONPATH);
2198 
2199     if(tokenIs(XalanUnicode::charSolidus) == true)
2200     {
2201         nextToken();
2202 
2203         const int   newOpPos = m_expression->opCodeMapLength();
2204 
2205         // Tell how long the step is without the predicate
2206         const XPathExpression::OpCodeMapValueVectorType     theArgs(1, 4, m_constructionContext->getMemoryManager());
2207 
2208         m_expression->appendOpCode(
2209             XPathExpression::eFROM_ROOT,
2210             theArgs);
2211 
2212         m_expression->appendOpCode(XPathExpression::eNODETYPE_ROOT);
2213 
2214         // Tell how long the entire step is.
2215         m_expression->updateOpCodeLength(newOpPos);
2216     }
2217 
2218     if(m_token.empty() == false)
2219     {
2220         RelativeLocationPath();
2221     }
2222 
2223     // Terminate for safety.
2224     m_expression->appendOpCode(XPathExpression::eENDOP);
2225 
2226     m_expression->updateOpCodeLength(XPathExpression::eOP_LOCATIONPATH,
2227                                      opPos);
2228 }
2229 
2230 
2231 
2232 void
RelativeLocationPath()2233 XPathProcessorImpl::RelativeLocationPath()
2234 {
2235     Step();
2236 
2237     while(tokenIs(XalanUnicode::charSolidus) == true)
2238     {
2239         nextToken();
2240 
2241         Step();
2242     }
2243 }
2244 
2245 
2246 
2247 void
Step()2248 XPathProcessorImpl::Step()
2249 {
2250     const int   opPos = m_expression->opCodeMapLength();
2251 
2252     if(m_token.empty() == true)
2253     {
2254         error(XalanMessages::ExpectedNodeTest);
2255     }
2256     else if(tokenIs(s_dotString) == true)
2257     {
2258         nextToken();
2259 
2260         if(tokenIs(XalanUnicode::charLeftSquareBracket) == true)
2261         {
2262             error(XalanMessages::IllegalSyntaxOfPredicatesSelf);
2263         }
2264 
2265         const XPathExpression::OpCodeMapValueVectorType     theArgs(1, 4, m_constructionContext->getMemoryManager());
2266 
2267         m_expression->appendOpCode(XPathExpression::eFROM_SELF,
2268                                    theArgs);
2269 
2270         m_expression->appendOpCode(XPathExpression::eNODETYPE_NODE);
2271 
2272         // Tell how long the entire step is.
2273         m_expression->updateOpCodeLength(opPos);
2274     }
2275     else if(tokenIs(s_dotDotString) == true)
2276     {
2277         nextToken();
2278 
2279         if(tokenIs(XalanUnicode::charLeftSquareBracket) == true)
2280         {
2281             error(XalanMessages::IllegalSyntaxOfPredicatesParent);
2282         }
2283 
2284         // Tell how long the step is without the predicate
2285         const XPathExpression::OpCodeMapValueVectorType     theArgs(1, 4,m_constructionContext->getMemoryManager());
2286 
2287         m_expression->appendOpCode(XPathExpression::eFROM_PARENT,
2288                                    theArgs);
2289 
2290         m_expression->appendOpCode(XPathExpression::eNODETYPE_NODE);
2291 
2292         // Tell how long the entire step is.
2293         m_expression->updateOpCodeLength(opPos);
2294     }
2295     else if (tokenIs(XalanUnicode::charAsterisk) ||
2296              tokenIs(XalanUnicode::charCommercialAt) ||
2297              tokenIs(XalanUnicode::charSolidus) ||
2298              (tokenIs(XalanUnicode::charLowLine) ||
2299               XalanXMLChar::isLetter(m_token[0])))
2300     {
2301         Basis();
2302 
2303         while(tokenIs(XalanUnicode::charLeftSquareBracket) == true)
2304         {
2305             Predicate();
2306         }
2307 
2308         // Tell how long the entire step is.
2309         m_expression->updateOpCodeLength(opPos);
2310     }
2311     else if (tokenIs(XalanUnicode::charRightParenthesis) == false)
2312     {
2313         error(
2314             XalanMessages::UnexpectedTokenFound_1Param,
2315             m_token);
2316     }
2317 }
2318 
2319 
2320 
2321 void
Basis()2322 XPathProcessorImpl::Basis()
2323 {
2324     assert(m_xpath != 0);
2325     assert(m_expression != 0);
2326 
2327     const int   opPos = m_expression->opCodeMapLength();
2328 
2329     XPathExpression::eOpCodes   axisType = XPathExpression::eENDOP;
2330 
2331     // The next blocks guarantee that a FROM_XXX will be added.
2332     if(lookahead(s_axisString, 1) == true)
2333     {
2334         axisType = AxisName();
2335 
2336         nextToken();
2337         nextToken();
2338     }
2339     else if(tokenIs(XalanUnicode::charCommercialAt) == true)
2340     {
2341         axisType = XPathExpression::eFROM_ATTRIBUTES;
2342 
2343         m_expression->appendOpCode(XPathExpression::eFROM_ATTRIBUTES);
2344 
2345         nextToken();
2346     }
2347     else if(tokenIs(XalanUnicode::charSolidus) == true)
2348     {
2349         // Check the current token in the expression.  It's
2350         // actually the next token in this context.
2351         //
2352         const XalanDOMString&   theNextToken = getTokenRelative(0);
2353 
2354         if (isAxis(theNextToken) == false && isNodeTest(theNextToken) == false)
2355         {
2356             nextToken();
2357 
2358             error(XalanMessages::ExpectedAxis);
2359         }
2360         else
2361         {
2362             // Tell how long the step is without the predicate
2363             const XPathExpression::OpCodeMapValueVectorType     theArgs(1, 4, m_constructionContext->getMemoryManager());
2364 
2365             m_expression->appendOpCode(XPathExpression::eFROM_DESCENDANTS_OR_SELF,
2366                                        theArgs);
2367 
2368             m_expression->appendOpCode(XPathExpression::eNODETYPE_NODE);
2369 
2370             // Tell how long the step is without the predicate
2371             m_expression->updateOpCodeLengthAfterNodeTest(opPos);
2372 
2373             return; // make a quick exit...
2374         }
2375     }
2376     else
2377     {
2378         axisType = XPathExpression::eFROM_CHILDREN;
2379 
2380         m_expression->appendOpCode(XPathExpression::eFROM_CHILDREN);
2381     }
2382 
2383     NodeTest();
2384 
2385     // Tell how long the step is without the predicate
2386     m_expression->updateOpCodeLengthAfterNodeTest(opPos);
2387 }
2388 
2389 
2390 
2391 XPathExpression::eOpCodes
AxisName()2392 XPathProcessorImpl::AxisName()
2393 {
2394     assert(m_xpath != 0);
2395     assert(m_expression != 0);
2396 
2397     const XPathExpression::eOpCodes     theOpCode =
2398         getAxisToken(m_token);
2399 
2400     if (theOpCode == XPathExpression::eENDOP)
2401     {
2402         error(
2403             XalanMessages::IllegalAxisName_1Param,
2404             m_token);
2405     }
2406     else
2407     {
2408         m_expression->appendOpCode(theOpCode);
2409     }
2410 
2411     return theOpCode;
2412 }
2413 
2414 
2415 
2416 int
NodeTest()2417 XPathProcessorImpl::NodeTest()
2418 {
2419     assert(m_xpath != 0);
2420     assert(m_expression != 0);
2421 
2422     int     nodeTestPos = -1;
2423 
2424     if (lookahead(XalanUnicode::charLeftParenthesis, 1) == true)
2425     {
2426         const XPathExpression::eOpCodes     theOpCode = getNodeTypeToken(m_token);
2427 
2428         if (theOpCode == XPathExpression::eENDOP)
2429         {
2430             error(
2431                 XalanMessages::UnknownNodeType_1Param,
2432                 m_token);
2433         }
2434         else
2435         {
2436             nextToken();
2437 
2438             nodeTestPos = m_expression->appendOpCode(theOpCode);
2439 
2440             consumeExpected(XalanUnicode::charLeftParenthesis);
2441 
2442             if(XPathExpression::eNODETYPE_PI == theOpCode)
2443             {
2444                 if(tokenIs(XalanUnicode::charRightParenthesis) == false)
2445                 {
2446                     Literal();
2447                 }
2448             }
2449 
2450             consumeExpected(XalanUnicode::charRightParenthesis);
2451         }
2452     }
2453     else
2454     {
2455         // Assume name of attribute or element.
2456         m_expression->appendOpCode(XPathExpression::eNODENAME);
2457 
2458         if(lookahead(XalanUnicode::charColon, 1) == true)
2459         {
2460             if(tokenIs(XalanUnicode::charAsterisk) == true)
2461             {
2462                 m_expression->appendOpCode(XPathExpression::eELEMWILDCARD);
2463             }
2464             else
2465             {
2466                 // Replace the token in the queue with the actual namespace...
2467                 replaceTokenWithNamespaceToken();
2468 
2469                 m_expression->pushCurrentTokenOnOpCodeMap();
2470             }
2471 
2472             nextToken();
2473 
2474             consumeExpected(XalanUnicode::charColon);
2475         }
2476         else
2477         {
2478             m_expression->appendOpCode(XPathExpression::eEMPTY);
2479         }
2480 
2481         if (tokenIs(XalanUnicode::charAsterisk) == true)
2482         {
2483             m_expression->appendOpCode(XPathExpression::eELEMWILDCARD);
2484         }
2485         else if (isNodeTest(m_token) == false)
2486         {
2487             error(XalanMessages::ExpectedNodeTest);
2488         }
2489         else
2490         {
2491             m_expression->pushCurrentTokenOnOpCodeMap();
2492         }
2493 
2494         nextToken();
2495     }
2496 
2497     return nodeTestPos;
2498 }
2499 
2500 
2501 
2502 void
Predicate()2503 XPathProcessorImpl::Predicate()
2504 {
2505     if(tokenIs(XalanUnicode::charLeftSquareBracket) == true)
2506     {
2507         nextToken();
2508 
2509         PredicateExpr();
2510 
2511         consumeExpected(XalanUnicode::charRightSquareBracket);
2512     }
2513 }
2514 
2515 
2516 
2517 void
PredicateExpr()2518 XPathProcessorImpl::PredicateExpr()
2519 {
2520     assert(m_xpath != 0);
2521     assert(m_expression != 0);
2522 
2523     const int   opPos = m_expression->opCodeMapLength();
2524 
2525     m_expression->appendOpCode(XPathExpression::eOP_PREDICATE);
2526 
2527     m_positionPredicateStack.push_back(false);
2528 
2529     Expr();
2530 
2531     // Terminate for safety.
2532     m_expression->appendOpCode(XPathExpression::eENDOP);
2533 
2534     m_expression->updateOpCodeLength(XPathExpression::eOP_PREDICATE,
2535                                      opPos);
2536 
2537     assert(m_positionPredicateStack.empty() == false);
2538 
2539     if (m_positionPredicateStack.back() == true)
2540     {
2541         m_expression->replaceOpCode(
2542             opPos,
2543             XPathExpression::eOP_PREDICATE,
2544             XPathExpression::eOP_PREDICATE_WITH_POSITION);
2545     }
2546 
2547     m_positionPredicateStack.pop_back();
2548 }
2549 
2550 
2551 
2552 void
QName()2553 XPathProcessorImpl::QName()
2554 {
2555     assert(m_xpath != 0);
2556     assert(m_expression != 0);
2557 
2558     // If there is no prefix, we have to fake things out...
2559     if (lookahead(XalanUnicode::charColon, 1) == false)
2560     {
2561         m_expression->insertToken(s_emptyString);
2562 
2563         m_expression->pushCurrentTokenOnOpCodeMap();
2564 
2565         nextToken();
2566     }
2567     else
2568     {
2569         // Replace the token in the queue with the actual namespace...
2570         replaceTokenWithNamespaceToken();
2571 
2572         m_expression->pushCurrentTokenOnOpCodeMap();
2573 
2574         nextToken();
2575 
2576         consumeExpected(XalanUnicode::charColon);
2577     }
2578 
2579     m_expression->pushCurrentTokenOnOpCodeMap();
2580 
2581     nextToken();
2582 }
2583 
2584 
2585 
2586 void
NCName()2587 XPathProcessorImpl::NCName()
2588 {
2589     assert(m_xpath != 0);
2590     assert(m_expression != 0);
2591 
2592     m_expression->pushCurrentTokenOnOpCodeMap();
2593 
2594     nextToken();
2595 }
2596 
2597 
2598 
2599 void
Literal()2600 XPathProcessorImpl::Literal()
2601 {
2602     assert(m_xpath != 0);
2603     assert(m_expression != 0);
2604 
2605     if(isCurrentLiteral() == true)
2606     {
2607         m_expression->pushArgumentOnOpCodeMap(
2608             m_constructionContext->getPooledString(m_token.c_str() + 1, m_token.length() - 2));
2609 
2610         nextToken();
2611     }
2612     else
2613     {
2614         error(XalanMessages::LiteralArgumentIsRequired);
2615     }
2616 }
2617 
2618 
2619 
2620 void
Number()2621 XPathProcessorImpl::Number()
2622 {
2623     assert(m_xpath != 0);
2624     assert(m_expression != 0);
2625 
2626     if(m_token.empty() == false)
2627     {
2628         const double    num = DoubleSupport::toDouble(m_token, m_constructionContext->getMemoryManager());
2629 
2630         const XPathConstructionContext::GetCachedString     theGuard(*m_constructionContext);
2631 
2632         XalanDOMString&     theStringValue = theGuard.get();
2633 
2634         NumberToDOMString(num, theStringValue);
2635 
2636         m_expression->pushNumberLiteralOnOpCodeMap(num);
2637 
2638         m_expression->pushArgumentOnOpCodeMap(num, m_constructionContext->getPooledString(theStringValue));
2639 
2640         nextToken();
2641     }
2642 }
2643 
2644 
2645 
2646 void
Pattern()2647 XPathProcessorImpl::Pattern()
2648 {
2649     while(true)
2650     {
2651         LocationPathPattern();
2652 
2653         if(tokenIs(XalanUnicode::charVerticalLine) == true)
2654         {
2655             nextToken();
2656         }
2657         else
2658         {
2659             break;
2660         }
2661     }
2662 }
2663 
2664 
2665 
2666 void
LocationPathPattern()2667 XPathProcessorImpl::LocationPathPattern()
2668 {
2669     assert(m_xpath != 0);
2670     assert(m_expression != 0);
2671 
2672     const int   opPos = m_expression->opCodeMapLength();
2673 
2674     m_expression->appendOpCode(XPathExpression::eOP_LOCATIONPATHPATTERN);
2675 
2676     if(lookahead(XalanUnicode::charLeftParenthesis, 1) == true &&
2677                 (tokenIs(s_functionIDString) == true ||
2678                  tokenIs(s_functionKeyString) == true))
2679     {
2680         IdKeyPattern();
2681 
2682         if(tokenIs(XalanUnicode::charSolidus) == true && lookahead(XalanUnicode::charSolidus, 1) == true)
2683         {
2684             const int   newOpPos = m_expression->opCodeMapLength();
2685 
2686             // Tell how long the step is without the predicate
2687             const XPathExpression::OpCodeMapValueVectorType     theArgs(1, 4, m_constructionContext->getMemoryManager());
2688 
2689             m_expression->appendOpCode(XPathExpression::eMATCH_ANY_ANCESTOR_WITH_FUNCTION_CALL,
2690                                        theArgs);
2691 
2692             m_expression->updateOpCodeLength(newOpPos);
2693 
2694             nextToken();
2695         }
2696     }
2697     else if(tokenIs(XalanUnicode::charSolidus) == true)
2698     {
2699         const int   newOpPos = m_expression->opCodeMapLength();
2700 
2701         // Tell how long the step is without the predicate
2702         const XPathExpression::OpCodeMapValueVectorType     theArgs(1, 4, m_constructionContext->getMemoryManager());
2703 
2704         if(lookahead(XalanUnicode::charSolidus, 1) == true)
2705         {
2706             m_expression->appendOpCode(
2707                 XPathExpression::eMATCH_ANY_ANCESTOR_WITH_PREDICATE,
2708                 theArgs);
2709 
2710             m_expression->appendOpCode(XPathExpression::eNODETYPE_NODE);
2711 
2712             nextToken();
2713         }
2714         else
2715         {
2716             m_expression->appendOpCode(XPathExpression::eFROM_ROOT,
2717                                        theArgs);
2718 
2719             m_expression->appendOpCode(XPathExpression::eNODETYPE_ROOT);
2720         }
2721 
2722         m_expression->updateOpCodeLength(newOpPos);
2723 
2724         nextToken();
2725     }
2726 
2727     if(m_token.empty() == false)
2728     {
2729         if (!tokenIs(XalanUnicode::charVerticalLine) == true)
2730         {
2731             RelativePathPattern();
2732         }
2733         else if (lookahead(XalanUnicode::charVerticalLine, -1) == true)
2734         {
2735             error(
2736                 XalanMessages::UnexpectedTokenFound_1Param,
2737                 m_token);
2738         }
2739     }
2740 
2741     // Terminate for safety.
2742     m_expression->appendOpCode(XPathExpression::eENDOP);
2743 
2744     m_expression->updateOpCodeLength(XPathExpression::eOP_LOCATIONPATHPATTERN,
2745                                      opPos);
2746 }
2747 
2748 
2749 
2750 void
IdKeyPattern()2751 XPathProcessorImpl::IdKeyPattern()
2752 {
2753     m_requireLiterals = true;
2754 
2755     FunctionCall();
2756 
2757     m_requireLiterals = false;
2758 }
2759 
2760 
2761 
2762 void
RelativePathPattern()2763 XPathProcessorImpl::RelativePathPattern()
2764 {
2765     StepPattern();
2766 
2767     while(tokenIs(XalanUnicode::charSolidus) == true)
2768     {
2769         nextToken();
2770 
2771         StepPattern();
2772     }
2773 }
2774 
2775 
2776 
2777 void
StepPattern()2778 XPathProcessorImpl::StepPattern()
2779 {
2780     AbbreviatedNodeTestStep();
2781 }
2782 
2783 
2784 
2785 void
AbbreviatedNodeTestStep()2786 XPathProcessorImpl::AbbreviatedNodeTestStep()
2787 {
2788     assert(m_xpath != 0);
2789     assert(m_expression != 0);
2790 
2791     const int   opPos = m_expression->opCodeMapLength();
2792 
2793     int         matchTypePos = -1;
2794 
2795     XPathExpression::eOpCodes   axisType = XPathExpression::eENDOP;
2796 
2797     // The next blocks guarantee that a MATCH_XXX will be added.
2798     if(tokenIs(XalanUnicode::charCommercialAt) == true)
2799     {
2800         axisType = XPathExpression::eMATCH_ATTRIBUTE;
2801 
2802         m_expression->appendOpCode(axisType);
2803 
2804         nextToken();
2805     }
2806     else if(lookahead(s_axisString, 1) == true)
2807     {
2808         if(tokenIs(s_attributeString) == true)
2809         {
2810             axisType = XPathExpression::eMATCH_ATTRIBUTE;
2811 
2812             m_expression->appendOpCode(axisType);
2813         }
2814         else if(tokenIs(s_childString) == true)
2815         {
2816             matchTypePos = m_expression->opCodeMapLength();
2817 
2818             axisType = XPathExpression::eMATCH_IMMEDIATE_ANCESTOR;
2819 
2820             m_expression->appendOpCode(axisType);
2821         }
2822         else
2823         {
2824             error(XalanMessages::OnlyChildAndAttributeAxesAreAllowed);
2825         }
2826 
2827         nextToken();
2828         nextToken();
2829     }
2830     else if(tokenIs(XalanUnicode::charSolidus) == true)
2831     {
2832         if(lookahead(s_axisString, 2) == false &&
2833            lookahead(XalanUnicode::charCommercialAt, 1) == false)
2834         {
2835             matchTypePos = m_expression->opCodeMapLength();
2836 
2837             axisType = XPathExpression::eMATCH_IMMEDIATE_ANCESTOR;
2838 
2839             m_expression->appendOpCode(axisType);
2840         }
2841         else
2842         {
2843             nextToken();
2844 
2845             // This matches an abbreviated step "@foo"
2846             if (tokenIs(XalanUnicode::charCommercialAt) == true)
2847             {
2848                 axisType = XPathExpression::eMATCH_ATTRIBUTE;
2849 
2850                 m_expression->appendOpCode(axisType);
2851             }
2852             else
2853             {
2854                 // This matches the attribute or child axis: attribute::name or child::name.
2855                 if(tokenIs(s_attributeString) == true)
2856                 {
2857                     axisType = XPathExpression::eMATCH_ATTRIBUTE;
2858 
2859                     m_expression->appendOpCode(axisType);
2860                 }
2861                 else if(tokenIs(s_childString) == true)
2862                 {
2863                     matchTypePos = m_expression->opCodeMapLength();
2864 
2865                     axisType = XPathExpression::eMATCH_IMMEDIATE_ANCESTOR;
2866 
2867                     m_expression->appendOpCode(axisType);
2868                 }
2869                 else
2870                 {
2871                     error(XalanMessages::OnlyChildAndAttributeAxesAreAllowed);
2872                 }
2873 
2874                 nextToken();
2875             }
2876         }
2877 
2878         nextToken();
2879     }
2880     else
2881     {
2882         if(tokenIs(XalanUnicode::charSolidus) == true)
2883         {
2884             nextToken();
2885         }
2886 
2887         matchTypePos = m_expression->opCodeMapLength();
2888 
2889         axisType = XPathExpression::eMATCH_IMMEDIATE_ANCESTOR;
2890 
2891         m_expression->appendOpCode(axisType);
2892     }
2893 
2894     // Make room for telling how long the step is without the predicate.
2895     // This will be replaced by the right value.
2896     m_expression->appendOpCode(XPathExpression::eENDOP);
2897 
2898     NodeTest();
2899 
2900     m_expression->updateOpCodeLengthAfterNodeTest(opPos);
2901 
2902     while(tokenIs(XalanUnicode::charLeftSquareBracket) == true)
2903     {
2904         Predicate();
2905     }
2906 
2907     if(matchTypePos > -1 && tokenIs(XalanUnicode::charSolidus) == true && lookahead(XalanUnicode::charSolidus, 1) == true)
2908     {
2909         assert(m_expression->opCodeMapLength() > matchTypePos);
2910 
2911         m_expression->setOpCodeMapValue(matchTypePos, XPathExpression::eMATCH_ANY_ANCESTOR);
2912     }
2913 
2914     m_expression->updateOpCodeLength(opPos);
2915 }
2916 
2917 
2918 
2919 bool
isValidFunction(const XalanDOMString & key)2920 XPathProcessorImpl::isValidFunction(const XalanDOMString&   key)
2921 {
2922     bool    fResult = true;
2923 
2924     if(XPath::isInstalledFunction(key) == false)
2925     {
2926         if (searchTable(s_functionTable, s_functionTableSize, key).m_opCode == XPathExpression::eENDOP)
2927         {
2928             fResult = false;
2929         }
2930     }
2931 
2932     return fResult;
2933 }
2934 
2935 
2936 
2937 bool
isCurrentLiteral() const2938 XPathProcessorImpl::isCurrentLiteral() const
2939 {
2940     const t_size_type   theLength = m_token.length();
2941 
2942     if (theLength <= 1)
2943     {
2944         return false;
2945     }
2946     else
2947     {
2948         const t_size_type   last = theLength - 1;
2949 
2950         const XalanDOMChar  c0 = m_tokenChar;
2951         const XalanDOMChar  cX = m_token[last];
2952 
2953         if((c0 == XalanUnicode::charQuoteMark && cX == XalanUnicode::charQuoteMark) ||
2954            (c0 == XalanUnicode::charApostrophe && cX == XalanUnicode::charApostrophe))
2955         {
2956             return true;
2957         }
2958         else
2959         {
2960             return false;
2961         }
2962     }
2963 }
2964 
2965 
2966 
2967 bool
isAxis(const XalanDOMString & theToken)2968 XPathProcessorImpl::isAxis(const XalanDOMString&    theToken)
2969 {
2970     const XalanDOMString::size_type     theLength =
2971         theToken.length();
2972 
2973     if (theLength == 0)
2974     {
2975         return false;
2976     }
2977     else if (theLength == 1 &&
2978              theToken[0] == XalanUnicode::charCommercialAt)
2979     {
2980         return true;
2981     }
2982     else if (equals(theToken, s_dotString) == true ||
2983              equals(theToken, s_dotDotString) == true)
2984     {
2985         return true;
2986     }
2987     else
2988     {
2989         const XPathExpression::eOpCodes     theOpCode =
2990             getAxisToken(theToken);
2991 
2992         if (theOpCode != XPathExpression::eENDOP)
2993         {
2994             return true;
2995         }
2996         else
2997         {
2998             return false;
2999         }
3000     }
3001 }
3002 
3003 
3004 
3005 bool
isNodeTest(const XalanDOMString & theToken)3006 XPathProcessorImpl::isNodeTest(const XalanDOMString&    theToken)
3007 {
3008     const XalanDOMString::size_type     theLength = theToken.length();
3009 
3010     if (theLength == 0)
3011     {
3012         return false;
3013     }
3014     else if (theLength == 1 &&
3015              theToken[0] == XalanUnicode::charAsterisk)
3016     {
3017         return true;
3018     }
3019     else if (theToken[0] == XalanUnicode::charLowLine ||
3020              XalanXMLChar::isLetter(theToken[0]) == true)
3021     {
3022         return true;
3023     }
3024     else
3025     {
3026         return false;
3027     }
3028 }
3029 
3030 
3031 
3032 const XPathProcessorImpl::TableEntry&
searchTable(const TableEntry theTable[],size_type theTableSize,const XalanDOMString & theString)3033 XPathProcessorImpl::searchTable(
3034         const TableEntry        theTable[],
3035         size_type               theTableSize,
3036         const XalanDOMString&   theString)
3037 {
3038     const TableEntry*   theFirst = theTable;
3039     const TableEntry*   theLast = &theTable[theTableSize - 1];
3040 
3041     while(theFirst <= theLast)
3042     {
3043         const TableEntry*   theCurrent = theFirst + (theLast - theFirst) / 2;
3044         assert(theCurrent->m_string[0] != 0);
3045 
3046         const int   theResult = compare(theString.c_str(), theCurrent->m_string);
3047 
3048         if (theResult < 0)
3049         {
3050             theLast = theCurrent - 1;
3051         }
3052         else if (theResult > 0)
3053         {
3054             theFirst = theCurrent + 1;
3055         }
3056         else
3057         {
3058             return *theCurrent;
3059         }
3060     }
3061 
3062     return s_dummyEntry;
3063 }
3064 
3065 
3066 
3067 const XalanDOMString    XPathProcessorImpl::s_emptyString(XalanMemMgrs::getDummyMemMgr());
3068 
3069 
3070 
3071 const XalanDOMChar  XPathProcessorImpl::s_functionIDString[] =
3072 {
3073     XalanUnicode::charLetter_i,
3074     XalanUnicode::charLetter_d,
3075     0
3076 };
3077 
3078 // This shouldn't really be here, since it's not part of the XPath standard,
3079 // but rather a part ofthe XSLT standard.
3080 const XalanDOMChar  XPathProcessorImpl::s_functionKeyString[] =
3081 {
3082     XalanUnicode::charLetter_k,
3083     XalanUnicode::charLetter_e,
3084     XalanUnicode::charLetter_y,
3085     0
3086 };
3087 
3088 const XalanDOMChar  XPathProcessorImpl::s_orString[] =
3089 {
3090     XalanUnicode::charLetter_o,
3091     XalanUnicode::charLetter_r,
3092     0
3093 };
3094 
3095 const XalanDOMChar  XPathProcessorImpl::s_andString[] =
3096 {
3097     XalanUnicode::charLetter_a,
3098     XalanUnicode::charLetter_n,
3099     XalanUnicode::charLetter_d,
3100     0
3101 };
3102 
3103 const XalanDOMChar  XPathProcessorImpl::s_divString[] =
3104 {
3105     XalanUnicode::charLetter_d,
3106     XalanUnicode::charLetter_i,
3107     XalanUnicode::charLetter_v,
3108     0
3109 };
3110 
3111 const XalanDOMChar  XPathProcessorImpl::s_modString[] =
3112 {
3113     XalanUnicode::charLetter_m,
3114     XalanUnicode::charLetter_o,
3115     XalanUnicode::charLetter_d,
3116     0
3117 };
3118 
3119 const XalanDOMChar  XPathProcessorImpl::s_dotString[] =
3120 {
3121     XalanUnicode::charFullStop,
3122     0
3123 };
3124 
3125 const XalanDOMChar  XPathProcessorImpl::s_dotDotString[] =
3126 {
3127     XalanUnicode::charFullStop,
3128     XalanUnicode::charFullStop,
3129     0
3130 };
3131 
3132 const XalanDOMChar  XPathProcessorImpl::s_axisString[] =
3133 {
3134     XalanUnicode::charColon,
3135     XalanUnicode::charColon,
3136     0
3137 };
3138 
3139 const XalanDOMChar  XPathProcessorImpl::s_attributeString[] =
3140 {
3141     XalanUnicode::charLetter_a,
3142     XalanUnicode::charLetter_t,
3143     XalanUnicode::charLetter_t,
3144     XalanUnicode::charLetter_r,
3145     XalanUnicode::charLetter_i,
3146     XalanUnicode::charLetter_b,
3147     XalanUnicode::charLetter_u,
3148     XalanUnicode::charLetter_t,
3149     XalanUnicode::charLetter_e,
3150     0
3151 };
3152 
3153 const XalanDOMChar  XPathProcessorImpl::s_childString[] =
3154 {
3155     XalanUnicode::charLetter_c,
3156     XalanUnicode::charLetter_h,
3157     XalanUnicode::charLetter_i,
3158     XalanUnicode::charLetter_l,
3159     XalanUnicode::charLetter_d,
3160     0
3161 };
3162 
3163 const XalanDOMChar  XPathProcessorImpl::s_lastString[] =
3164 {
3165     XalanUnicode::charLetter_l,
3166     XalanUnicode::charLetter_a,
3167     XalanUnicode::charLetter_s,
3168     XalanUnicode::charLetter_t,
3169     0
3170 };
3171 
3172 const XalanDOMChar  XPathProcessorImpl::s_positionString[] =
3173 {
3174     XalanUnicode::charLetter_p,
3175     XalanUnicode::charLetter_o,
3176     XalanUnicode::charLetter_s,
3177     XalanUnicode::charLetter_i,
3178     XalanUnicode::charLetter_t,
3179     XalanUnicode::charLetter_i,
3180     XalanUnicode::charLetter_o,
3181     XalanUnicode::charLetter_n,
3182     0
3183 };
3184 
3185 const XalanDOMChar  XPathProcessorImpl::s_asteriskString[] =
3186 {
3187     XalanUnicode::charAsterisk,
3188     0
3189 };
3190 
3191 const XalanDOMChar  XPathProcessorImpl::s_commentString[] =
3192 {
3193     XalanUnicode::charLetter_c,
3194     XalanUnicode::charLetter_o,
3195     XalanUnicode::charLetter_m,
3196     XalanUnicode::charLetter_m,
3197     XalanUnicode::charLetter_e,
3198     XalanUnicode::charLetter_n,
3199     XalanUnicode::charLetter_t,
3200     0
3201 };
3202 
3203 const XalanDOMChar  XPathProcessorImpl::s_piString[] =
3204 {
3205     XalanUnicode::charLetter_p,
3206     XalanUnicode::charLetter_r,
3207     XalanUnicode::charLetter_o,
3208     XalanUnicode::charLetter_c,
3209     XalanUnicode::charLetter_e,
3210     XalanUnicode::charLetter_s,
3211     XalanUnicode::charLetter_s,
3212     XalanUnicode::charLetter_i,
3213     XalanUnicode::charLetter_n,
3214     XalanUnicode::charLetter_g,
3215     XalanUnicode::charHyphenMinus,
3216     XalanUnicode::charLetter_i,
3217     XalanUnicode::charLetter_n,
3218     XalanUnicode::charLetter_s,
3219     XalanUnicode::charLetter_t,
3220     XalanUnicode::charLetter_r,
3221     XalanUnicode::charLetter_u,
3222     XalanUnicode::charLetter_c,
3223     XalanUnicode::charLetter_t,
3224     XalanUnicode::charLetter_i,
3225     XalanUnicode::charLetter_o,
3226     XalanUnicode::charLetter_n,
3227     0
3228 };
3229 
3230 const XalanDOMChar  XPathProcessorImpl::s_nodeString[] =
3231 {
3232     XalanUnicode::charLetter_n,
3233     XalanUnicode::charLetter_o,
3234     XalanUnicode::charLetter_d,
3235     XalanUnicode::charLetter_e,
3236     0
3237 };
3238 
3239 const XalanDOMChar  XPathProcessorImpl::s_textString[] =
3240 {
3241     XalanUnicode::charLetter_t,
3242     XalanUnicode::charLetter_e,
3243     XalanUnicode::charLetter_x,
3244     XalanUnicode::charLetter_t,
3245     0
3246 };
3247 
3248 const XalanDOMChar      XPathProcessorImpl::s_ancestorString[] =
3249 {
3250     XalanUnicode::charLetter_a,
3251     XalanUnicode::charLetter_n,
3252     XalanUnicode::charLetter_c,
3253     XalanUnicode::charLetter_e,
3254     XalanUnicode::charLetter_s,
3255     XalanUnicode::charLetter_t,
3256     XalanUnicode::charLetter_o,
3257     XalanUnicode::charLetter_r,
3258     0
3259 };
3260 
3261 const XalanDOMChar      XPathProcessorImpl::s_ancestorOrSelfString[] =
3262 {
3263     XalanUnicode::charLetter_a,
3264     XalanUnicode::charLetter_n,
3265     XalanUnicode::charLetter_c,
3266     XalanUnicode::charLetter_e,
3267     XalanUnicode::charLetter_s,
3268     XalanUnicode::charLetter_t,
3269     XalanUnicode::charLetter_o,
3270     XalanUnicode::charLetter_r,
3271     XalanUnicode::charHyphenMinus,
3272     XalanUnicode::charLetter_o,
3273     XalanUnicode::charLetter_r,
3274     XalanUnicode::charHyphenMinus,
3275     XalanUnicode::charLetter_s,
3276     XalanUnicode::charLetter_e,
3277     XalanUnicode::charLetter_l,
3278     XalanUnicode::charLetter_f,
3279     0
3280 };
3281 
3282 const XalanDOMChar      XPathProcessorImpl::s_descendantString[] =
3283 {
3284     XalanUnicode::charLetter_d,
3285     XalanUnicode::charLetter_e,
3286     XalanUnicode::charLetter_s,
3287     XalanUnicode::charLetter_c,
3288     XalanUnicode::charLetter_e,
3289     XalanUnicode::charLetter_n,
3290     XalanUnicode::charLetter_d,
3291     XalanUnicode::charLetter_a,
3292     XalanUnicode::charLetter_n,
3293     XalanUnicode::charLetter_t,
3294     0
3295 };
3296 
3297 const XalanDOMChar      XPathProcessorImpl::s_descendantOrSelfString[] =
3298 {
3299     XalanUnicode::charLetter_d,
3300     XalanUnicode::charLetter_e,
3301     XalanUnicode::charLetter_s,
3302     XalanUnicode::charLetter_c,
3303     XalanUnicode::charLetter_e,
3304     XalanUnicode::charLetter_n,
3305     XalanUnicode::charLetter_d,
3306     XalanUnicode::charLetter_a,
3307     XalanUnicode::charLetter_n,
3308     XalanUnicode::charLetter_t,
3309     XalanUnicode::charHyphenMinus,
3310     XalanUnicode::charLetter_o,
3311     XalanUnicode::charLetter_r,
3312     XalanUnicode::charHyphenMinus,
3313     XalanUnicode::charLetter_s,
3314     XalanUnicode::charLetter_e,
3315     XalanUnicode::charLetter_l,
3316     XalanUnicode::charLetter_f,
3317     0
3318 };
3319 
3320 const XalanDOMChar      XPathProcessorImpl::s_followingString[] =
3321 {
3322     XalanUnicode::charLetter_f,
3323     XalanUnicode::charLetter_o,
3324     XalanUnicode::charLetter_l,
3325     XalanUnicode::charLetter_l,
3326     XalanUnicode::charLetter_o,
3327     XalanUnicode::charLetter_w,
3328     XalanUnicode::charLetter_i,
3329     XalanUnicode::charLetter_n,
3330     XalanUnicode::charLetter_g,
3331     0
3332 };
3333 
3334 const XalanDOMChar      XPathProcessorImpl::s_followingSiblingString[] =
3335 {
3336     XalanUnicode::charLetter_f,
3337     XalanUnicode::charLetter_o,
3338     XalanUnicode::charLetter_l,
3339     XalanUnicode::charLetter_l,
3340     XalanUnicode::charLetter_o,
3341     XalanUnicode::charLetter_w,
3342     XalanUnicode::charLetter_i,
3343     XalanUnicode::charLetter_n,
3344     XalanUnicode::charLetter_g,
3345     XalanUnicode::charHyphenMinus,
3346     XalanUnicode::charLetter_s,
3347     XalanUnicode::charLetter_i,
3348     XalanUnicode::charLetter_b,
3349     XalanUnicode::charLetter_l,
3350     XalanUnicode::charLetter_i,
3351     XalanUnicode::charLetter_n,
3352     XalanUnicode::charLetter_g,
3353     0
3354 };
3355 
3356 const XalanDOMChar      XPathProcessorImpl::s_parentString[] =
3357 {
3358     XalanUnicode::charLetter_p,
3359     XalanUnicode::charLetter_a,
3360     XalanUnicode::charLetter_r,
3361     XalanUnicode::charLetter_e,
3362     XalanUnicode::charLetter_n,
3363     XalanUnicode::charLetter_t,
3364     0
3365 };
3366 
3367 const XalanDOMChar      XPathProcessorImpl::s_precedingString[] =
3368 {
3369     XalanUnicode::charLetter_p,
3370     XalanUnicode::charLetter_r,
3371     XalanUnicode::charLetter_e,
3372     XalanUnicode::charLetter_c,
3373     XalanUnicode::charLetter_e,
3374     XalanUnicode::charLetter_d,
3375     XalanUnicode::charLetter_i,
3376     XalanUnicode::charLetter_n,
3377     XalanUnicode::charLetter_g,
3378     0
3379 };
3380 
3381 const XalanDOMChar      XPathProcessorImpl::s_precedingSiblingString[] =
3382 {
3383     XalanUnicode::charLetter_p,
3384     XalanUnicode::charLetter_r,
3385     XalanUnicode::charLetter_e,
3386     XalanUnicode::charLetter_c,
3387     XalanUnicode::charLetter_e,
3388     XalanUnicode::charLetter_d,
3389     XalanUnicode::charLetter_i,
3390     XalanUnicode::charLetter_n,
3391     XalanUnicode::charLetter_g,
3392     XalanUnicode::charHyphenMinus,
3393     XalanUnicode::charLetter_s,
3394     XalanUnicode::charLetter_i,
3395     XalanUnicode::charLetter_b,
3396     XalanUnicode::charLetter_l,
3397     XalanUnicode::charLetter_i,
3398     XalanUnicode::charLetter_n,
3399     XalanUnicode::charLetter_g,
3400     0
3401 };
3402 
3403 const XalanDOMChar      XPathProcessorImpl::s_selfString[] =
3404 {
3405     XalanUnicode::charLetter_s,
3406     XalanUnicode::charLetter_e,
3407     XalanUnicode::charLetter_l,
3408     XalanUnicode::charLetter_f,
3409     0
3410 };
3411 
3412 const XalanDOMChar      XPathProcessorImpl::s_namespaceString[] =
3413 {
3414     XalanUnicode::charLetter_n,
3415     XalanUnicode::charLetter_a,
3416     XalanUnicode::charLetter_m,
3417     XalanUnicode::charLetter_e,
3418     XalanUnicode::charLetter_s,
3419     XalanUnicode::charLetter_p,
3420     XalanUnicode::charLetter_a,
3421     XalanUnicode::charLetter_c,
3422     XalanUnicode::charLetter_e,
3423     0
3424 };
3425 
3426 
3427 
3428 const XPathProcessorImpl::TableEntry    XPathProcessorImpl::s_functionTable[] =
3429 {
3430     { XPathFunctionTable::s_not, XPathExpression::eOP_FUNCTION_NOT },
3431     { XPathFunctionTable::s_sum, XPathExpression::eOP_FUNCTION_SUM },
3432     { XPathProcessorImpl::s_lastString, XPathExpression::eOP_FUNCTION_LAST },
3433     { XPathFunctionTable::s_name, XPathExpression::eOP_FUNCTION_NAME_0 },
3434     { XPathProcessorImpl::s_nodeString, XPathExpression::eNODETYPE_NODE },
3435     { XPathProcessorImpl::s_textString, XPathExpression::eNODETYPE_TEXT },
3436     { XPathFunctionTable::s_true, XPathExpression::eOP_FUNCTION_TRUE },
3437     { XPathFunctionTable::s_count, XPathExpression::eOP_FUNCTION_COUNT  },
3438     { XPathFunctionTable::s_false, XPathExpression::eOP_FUNCTION_FALSE },
3439     { XPathFunctionTable::s_floor, XPathExpression::eOP_FUNCTION_FLOOR },
3440     { XPathFunctionTable::s_round, XPathExpression::eOP_FUNCTION_ROUND },
3441     { XPathFunctionTable::s_number, XPathExpression::eOP_FUNCTION_NUMBER_0 },
3442     { XPathFunctionTable::s_boolean, XPathExpression::eOP_FUNCTION_BOOLEAN },
3443     { XPathFunctionTable::s_ceiling, XPathExpression::eOP_FUNCTION_CEILING },
3444     { XPathProcessorImpl::s_commentString, XPathExpression::eNODETYPE_COMMENT },
3445     { XPathProcessorImpl::s_positionString, XPathExpression::eOP_FUNCTION_POSITION },
3446     { XPathFunctionTable::s_localName, XPathExpression::eOP_FUNCTION_LOCALNAME_0 },
3447     { XPathFunctionTable::s_stringLength, XPathExpression::eOP_FUNCTION_STRINGLENGTH_0 },
3448     { XPathProcessorImpl::s_piString, XPathExpression::eNODETYPE_PI },
3449 };
3450 
3451 const XPathProcessorImpl::size_type     XPathProcessorImpl::s_functionTableSize =
3452     sizeof(s_functionTable) / sizeof(s_functionTable[0]);
3453 
3454 
3455 
3456 const XPathProcessorImpl::TableEntry    XPathProcessorImpl::s_nodeTypeTable[] =
3457 {
3458     { XPathProcessorImpl::s_asteriskString, XPathExpression::eNODETYPE_ANYELEMENT },
3459     { XPathProcessorImpl::s_nodeString, XPathExpression::eNODETYPE_NODE },
3460     { XPathProcessorImpl::s_textString, XPathExpression::eNODETYPE_TEXT },
3461     { XPathProcessorImpl::s_commentString, XPathExpression::eNODETYPE_COMMENT },
3462     { XPathProcessorImpl::s_piString, XPathExpression::eNODETYPE_PI },
3463 };
3464 
3465 const XPathProcessorImpl::size_type     XPathProcessorImpl::s_nodeTypeTableSize =
3466     sizeof(s_nodeTypeTable) / sizeof(s_nodeTypeTable[0]);
3467 
3468 
3469 
3470 const XPathProcessorImpl::TableEntry    XPathProcessorImpl::s_axisTable[] =
3471 {
3472     { XPathProcessorImpl::s_selfString, XPathExpression::eFROM_SELF },
3473     { XPathProcessorImpl::s_childString, XPathExpression::eFROM_CHILDREN },
3474     { XPathProcessorImpl::s_parentString, XPathExpression::eFROM_PARENT },
3475     { XPathProcessorImpl::s_ancestorString, XPathExpression::eFROM_ANCESTORS },
3476     { XPathProcessorImpl::s_attributeString, XPathExpression::eFROM_ATTRIBUTES },
3477     { XPathProcessorImpl::s_followingString, XPathExpression::eFROM_FOLLOWING },
3478     { XPathProcessorImpl::s_namespaceString, XPathExpression::eFROM_NAMESPACE },
3479     { XPathProcessorImpl::s_precedingString, XPathExpression::eFROM_PRECEDING },
3480     { XPathProcessorImpl::s_descendantString, XPathExpression::eFROM_DESCENDANTS },
3481     { XPathProcessorImpl::s_ancestorOrSelfString, XPathExpression::eFROM_ANCESTORS_OR_SELF },
3482     { XPathProcessorImpl::s_followingSiblingString, XPathExpression::eFROM_FOLLOWING_SIBLINGS },
3483     { XPathProcessorImpl::s_precedingSiblingString, XPathExpression::eFROM_PRECEDING_SIBLINGS },
3484     { XPathProcessorImpl::s_descendantOrSelfString, XPathExpression::eFROM_DESCENDANTS_OR_SELF },
3485 };
3486 
3487 const XPathProcessorImpl::size_type     XPathProcessorImpl::s_axisTableSize =
3488     sizeof(s_axisTable) / sizeof(s_axisTable[0]);
3489 
3490 
3491 const XPathProcessorImpl::TableEntry    XPathProcessorImpl::s_dummyEntry =
3492 {
3493     0, XPathExpression::eENDOP
3494 };
3495 
3496 
3497 
3498 }
3499