source: icXML/icXML-devel/src/icxercesc/internal/XMLScanner.cpp @ 3104

Last change on this file since 3104 was 3104, checked in by cameron, 6 years ago

Additional files for icXML 0.9

File size: 61.6 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: XMLScanner.cpp 882548 2009-11-20 13:44:14Z borisk $
20 */
21
22
23// ---------------------------------------------------------------------------
24//  Includes
25// ---------------------------------------------------------------------------
26#include <icxercesc/internal/XMLScanner.hpp>
27#include <icxercesc/internal/ValidationContextImpl.hpp>
28#include <xercesc/util/Janitor.hpp>
29#include <xercesc/util/Mutexes.hpp>
30#include <xercesc/util/RuntimeException.hpp>
31#include <xercesc/util/UnexpectedEOFException.hpp>
32#include <xercesc/util/XMLMsgLoader.hpp>
33#include <xercesc/util/XMLInitializer.hpp>
34#include <xercesc/framework/LocalFileInputSource.hpp>
35#include <xercesc/framework/URLInputSource.hpp>
36#include <icxercesc/framework/XMLDocumentHandler.hpp>
37#include <xercesc/framework/XMLEntityHandler.hpp>
38#include <xercesc/framework/XMLPScanToken.hpp>
39#include <icxercesc/framework/XMLValidator.hpp>
40#include <xercesc/validators/DTD/DocTypeHandler.hpp>
41#include <icxercesc/validators/common/GrammarResolver.hpp>
42#include <xercesc/util/OutOfMemoryException.hpp>
43#include <icxmlc/XMLNameChars.hpp>
44#include <xercesc/util/XMLResourceIdentifier.hpp>
45
46XERCES_CPP_NAMESPACE_BEGIN
47
48// ---------------------------------------------------------------------------
49//  Local static data
50// ---------------------------------------------------------------------------
51static XMLUInt32       gScannerId = 0;
52static XMLMutex*       sScannerMutex = 0;
53static XMLMsgLoader*   gMsgLoader = 0;
54
55void XMLInitializer::initializeXMLScanner()
56{
57        gMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgXMLErrDomain);
58
59        if (!gMsgLoader)
60          XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
61
62        sScannerMutex = new XMLMutex(XMLPlatformUtils::fgMemoryManager);
63}
64
65void XMLInitializer::terminateXMLScanner()
66{
67        delete gMsgLoader;
68        gMsgLoader = 0;
69
70        delete sScannerMutex;
71        sScannerMutex = 0;
72}
73
74//
75//
76typedef JanitorMemFunCall<XMLScanner>   CleanupType;
77typedef JanitorMemFunCall<ReaderMgr>    ReaderMgrResetType;
78
79
80// ---------------------------------------------------------------------------
81//  XMLScanner: Constructors and Destructor
82// ---------------------------------------------------------------------------
83XMLScanner::XMLScanner
84(       XMLValidator* const valToAdopt
85        , GrammarResolver* const grammarResolver
86        , MemoryManager* const manager
87)
88        : fLowWaterMark (100)
89        , fStandardUriConformant(false)
90        , fCalculateSrcOfs(false)
91        , fDoNamespaces(false)
92        , fExitOnFirstFatal(true)
93        , fValidationConstraintFatal(false)
94        , fInException(false)
95        , fStandalone(false)
96        , fHasNoDTD(true)
97    , fHasInternalOrExternalDTD(false)
98        , fValidate(false)
99        , fValidatorFromUser(false)
100        , fDoSchema(false)
101        , fSchemaFullChecking(false)
102        , fIdentityConstraintChecking(true)
103        , fToCacheGrammar(false)
104        , fUseCachedGrammar(false)
105        , fLoadExternalDTD(true)
106        , fLoadSchema(true)
107        , fNormalizeData(true)
108        , fGenerateSyntheticAnnotations(false)
109        , fValidateAnnotations(false)
110        , fIgnoreCachedDTD(false)
111        , fIgnoreAnnotations(false)
112        , fDisableDefaultEntityResolution(false)
113        , fSkipDTDValidation(false)
114        , fHandleMultipleImports(false)
115        , fErrorCount(0)
116        , fEntityExpansionLimit(0)
117        , fEntityExpansionCount(0)
118        , fScannerId(0)
119        , fSequenceId(0)       
120        , fDocHandler(0)
121        , fDocTypeHandler(0)
122        , fEntityHandler(0)
123        , fErrorReporter(0)
124        , fErrorHandler(0)
125        , fPSVIHandler(0)
126        , fValidationContext(0)
127        , fEntityDeclPoolRetrieved(false)
128        , fReaderMgr(manager)
129        , fValidator(valToAdopt)
130        , fValScheme(Val_Never)
131        , fGrammarResolver(grammarResolver)
132        , fGrammarPoolMemoryManager(grammarResolver->getGrammarPoolMemoryManager())
133        , fGrammar(0)
134        , fRootGrammar(0)
135        , fRootElemName(0)
136        , fExternalSchemaLocation(0)
137        , fExternalNoNamespaceSchemaLocation(0)
138        , fSecurityManager(0)
139        , fXMLVersion(XMLReader::XMLV1_0)
140        , fMemoryManager(manager)
141        , fBufMgr(manager)
142        , fElemStack(manager)
143        , fUriResolver(0)
144{
145        CleanupType cleanup(this, &XMLScanner::cleanUp);
146
147        try
148        {
149                commonInit();
150        }
151        catch(const OutOfMemoryException&)
152        {
153                // Don't cleanup when out of memory, since executing the
154                // code can cause problems.
155                cleanup.release();
156
157                throw;
158        }
159
160        cleanup.release();
161}
162
163XMLScanner::XMLScanner
164(
165        XMLDocumentHandler* const  docHandler
166        , DocTypeHandler* const    docTypeHandler
167        , XMLEntityHandler* const  entityHandler
168        , XMLErrorReporter* const  errHandler
169        , XMLValidator* const      valToAdopt
170        , GrammarResolver* const   grammarResolver
171        , MemoryManager* const     manager
172)
173        : fLowWaterMark (100)
174        , fStandardUriConformant(false)
175        , fCalculateSrcOfs(false)
176        , fDoNamespaces(false)
177        , fExitOnFirstFatal(true)
178        , fValidationConstraintFatal(false)
179        , fInException(false)
180        , fStandalone(false)
181        , fHasNoDTD(true)
182    , fHasInternalOrExternalDTD(false)
183        , fValidate(false)
184        , fValidatorFromUser(false)
185        , fDoSchema(false)
186        , fSchemaFullChecking(false)
187        , fIdentityConstraintChecking(true)
188        , fToCacheGrammar(false)
189        , fUseCachedGrammar(false)
190        , fLoadExternalDTD(true)
191        , fLoadSchema(true)
192        , fNormalizeData(true)
193        , fGenerateSyntheticAnnotations(false)
194        , fValidateAnnotations(false)
195        , fIgnoreCachedDTD(false)
196        , fIgnoreAnnotations(false)
197        , fDisableDefaultEntityResolution(false)
198        , fSkipDTDValidation(false)
199        , fHandleMultipleImports(false)
200        , fErrorCount(0)
201        , fEntityExpansionLimit(0)
202        , fEntityExpansionCount(0)
203        , fScannerId(0)
204        , fSequenceId(0)
205        , fDocHandler(docHandler)
206        , fDocTypeHandler(docTypeHandler)
207        , fEntityHandler(entityHandler)
208        , fErrorReporter(errHandler)
209        , fErrorHandler(0)
210        , fPSVIHandler(0)
211        , fValidationContext(0)
212        , fEntityDeclPoolRetrieved(false)
213        , fReaderMgr(manager)
214        , fValidator(valToAdopt)
215        , fValScheme(Val_Never)
216        , fGrammarResolver(grammarResolver)
217        , fGrammarPoolMemoryManager(grammarResolver->getGrammarPoolMemoryManager())
218        , fGrammar(0)
219        , fRootGrammar(0)
220        , fRootElemName(0)
221        , fExternalSchemaLocation(0)
222        , fExternalNoNamespaceSchemaLocation(0)
223        , fSecurityManager(0)
224        , fXMLVersion(XMLReader::XMLV1_0)
225        , fMemoryManager(manager)
226        , fBufMgr(manager)
227        , fElemStack(manager)
228{
229        CleanupType cleanup(this, &XMLScanner::cleanUp);
230
231        try
232        {
233                commonInit();
234        }
235        catch(const OutOfMemoryException&)
236        {
237                // Don't cleanup when out of memory, since executing the
238                // code can cause problems.
239                cleanup.release();
240
241                throw;
242        }
243
244        cleanup.release();
245}
246
247XMLScanner::~XMLScanner()
248{
249        cleanUp();
250}
251
252void XMLScanner::resetCachedGrammar ()
253{
254}
255
256void XMLScanner::setValidator(XMLValidator* const valToAdopt)
257{
258        if (fValidatorFromUser)
259                delete fValidator;
260        fValidator = valToAdopt;
261        fValidatorFromUser = true;
262        initValidator(fValidator);
263}
264
265// ---------------------------------------------------------------------------
266//  XMLScanner: Main entry point to scan a document
267// ---------------------------------------------------------------------------
268void XMLScanner::scanDocument(  const   XMLCh* const    systemId)
269{
270        //  First we try to parse it as a URL. If that fails, we assume its
271        //  a file and try it that way.
272        InputSource* srcToUse = 0;
273        try
274        {
275                //  Create a temporary URL. Since this is the primary document,
276                //  it has to be fully qualified. If not, then assume we are just
277                //  mistaking a file for a URL.
278                XMLURL tmpURL(fMemoryManager);
279
280                if (XMLURL::parse(systemId, tmpURL))
281                {
282                        if (tmpURL.isRelative())
283                        {
284                                if (!fStandardUriConformant)
285                                        srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager);
286                                else {
287                                        // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr
288                                        // emit the error directly
289                                        MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_NoProtocolPresent, fMemoryManager);
290                                        fInException = true;
291                                        emitError
292                                        (
293                                                XMLErrs::XMLException_Fatal
294                                                , e.getCode()
295                                                , e.getMessage()
296                                        );
297                                        return;
298                                }
299                        }
300                        else
301                        {
302                                if (fStandardUriConformant && tmpURL.hasInvalidChar()) {
303                                        MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL, fMemoryManager);
304                                        fInException = true;
305                                        emitError
306                                        (
307                                                XMLErrs::XMLException_Fatal
308                                                , e.getCode()
309                                                , e.getMessage()
310                                        );
311                                        return;
312                                }
313                                srcToUse = new (fMemoryManager) URLInputSource(tmpURL, fMemoryManager);
314                        }
315                }
316                else {
317
318                        if (!fStandardUriConformant)
319                                srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager);
320                        else {
321                                // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr
322                                // emit the error directly
323                                // lazy bypass ... since all MalformedURLException are fatal, no need to check the type
324                                MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL, fMemoryManager);
325                                fInException = true;
326                                emitError
327                                (
328                                        XMLErrs::XMLException_Fatal
329                                        , e.getCode()
330                                        , e.getMessage()
331                                );
332                                return;
333                        }
334                }
335        }
336        catch(const XMLException& excToCatch)
337        {
338                //  For any other XMLException,
339                //  emit the error and catch any user exception thrown from here.
340                fInException = true;
341                if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
342                        emitError
343                        (
344                                XMLErrs::XMLException_Warning
345                                , excToCatch.getCode()
346                                , excToCatch.getMessage()
347                        );
348                else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
349                        emitError
350                        (
351                                XMLErrs::XMLException_Fatal
352                                , excToCatch.getCode()
353                                , excToCatch.getMessage()
354                        );
355                else
356                        emitError
357                        (
358                                XMLErrs::XMLException_Error
359                                , excToCatch.getCode()
360                                , excToCatch.getMessage()
361                        );
362                return;
363        }
364
365        Janitor<InputSource> janSrc(srcToUse);
366        scanDocument(*srcToUse);
367
368}
369
370void XMLScanner::scanDocument(  const   char* const systemId)
371{
372        // We just delegate this to the XMLCh version after transcoding
373        XMLCh* tmpBuf = XMLString::transcode(systemId, fMemoryManager);
374        ArrayJanitor<XMLCh> janBuf(tmpBuf, fMemoryManager);
375        scanDocument(tmpBuf);
376
377}
378
379
380//  This method begins a progressive parse. It scans through the prolog and
381//  returns a token to be used on subsequent scanNext() calls. If the return
382//  value is true, then the token is legal and ready for further use. If it
383//  returns false, then the scan of the prolog failed and the token is not
384//  going to work on subsequent scanNext() calls.
385//  This method begins a progressive parse. It scans through the prolog and
386//  returns a token to be used on subsequent scanNext() calls. If the return
387//  value is true, then the token is legal and ready for further use. If it
388//  returns false, then the scan of the prolog failed and the token is not
389//  going to work on subsequent scanNext() calls.
390bool XMLScanner::scanFirst( const   XMLCh* const    systemId
391                                                        ,       XMLPScanToken&  toFill)
392{
393        //  First we try to parse it as a URL. If that fails, we assume its
394        //  a file and try it that way.
395        InputSource* srcToUse = 0;
396        try
397        {
398                //  Create a temporary URL. Since this is the primary document,
399                //  it has to be fully qualified. If not, then assume we are just
400                //  mistaking a file for a URL.
401                XMLURL tmpURL(fMemoryManager);
402                if (XMLURL::parse(systemId, tmpURL)) {
403                        if (tmpURL.isRelative()) {
404                                if (!fStandardUriConformant)
405                                        srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager);
406                                else {
407                                        // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr
408                                        // emit the error directly
409                                        MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_NoProtocolPresent, fMemoryManager);
410                                        fInException = true;
411                                        emitError
412                                        (
413                                                XMLErrs::XMLException_Fatal
414                                                , e.getCode()
415                                                , e.getMessage()
416                                        );
417                                        return false;
418                                }
419                        }
420                        else
421                        {
422                                if (fStandardUriConformant && tmpURL.hasInvalidChar()) {
423                                        MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL, fMemoryManager);
424                                        fInException = true;
425                                        emitError
426                                        (
427                                                XMLErrs::XMLException_Fatal
428                                                , e.getCode()
429                                                , e.getMessage()
430                                        );
431                                        return false;
432                                }
433                                srcToUse = new (fMemoryManager) URLInputSource(tmpURL, fMemoryManager);
434                        }
435                }
436                else {
437                        if (!fStandardUriConformant)
438                                srcToUse = new (fMemoryManager) LocalFileInputSource(systemId,  fMemoryManager);
439                        else {
440                                // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr
441                                // emit the error directly
442                                // lazy bypass ... since all MalformedURLException are fatal, no need to check the type
443                                MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL);
444                                fInException = true;
445                                emitError
446                                (
447                                        XMLErrs::XMLException_Fatal
448                                        , e.getCode()
449                                        , e.getMessage()
450                                );
451                                return false;
452                        }
453                }
454        }
455        catch(const XMLException& excToCatch)
456        {
457                //  For any other XMLException,
458                //  emit the error and catch any user exception thrown from here.
459                fInException = true;
460                if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
461                        emitError
462                        (
463                                XMLErrs::XMLException_Warning
464                                , excToCatch.getCode()
465                                , excToCatch.getMessage()
466                        );
467                else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
468                        emitError
469                        (
470                                XMLErrs::XMLException_Fatal
471                                , excToCatch.getCode()
472                                , excToCatch.getMessage()
473                        );
474                else
475                        emitError
476                        (
477                                XMLErrs::XMLException_Error
478                                , excToCatch.getCode()
479                                , excToCatch.getMessage()
480                        );
481                return false;
482        }
483
484        Janitor<InputSource> janSrc(srcToUse);
485        return scanFirst(*srcToUse, toFill);
486}
487
488bool XMLScanner::scanFirst( const   char* const     systemId
489                                                        ,       XMLPScanToken&  toFill)
490{
491        // We just delegate this to the XMLCh version after transcoding
492        XMLCh* tmpBuf = XMLString::transcode(systemId, fMemoryManager);
493        ArrayJanitor<XMLCh> janBuf(tmpBuf, fMemoryManager);
494        return scanFirst(tmpBuf, toFill);
495}
496
497bool XMLScanner::scanFirst( const   InputSource&    src
498                                                   ,       XMLPScanToken&  toFill)
499{
500        //  Bump up the sequence id for this new scan cycle. This will invalidate
501        //  any previous tokens we've returned.
502        fSequenceId++;
503
504        ReaderMgrResetType  resetReaderMgr(&fReaderMgr, &ReaderMgr::reset);
505
506   // Reset the scanner and its plugged in stuff for a new run.  This
507        // resets all the data structures, creates the initial reader and
508        // pushes it on the stack, and sets up the base document path
509        scanReset(src);
510
511        // If we have a document handler, then call the start document
512        if (fDocHandler)
513                fDocHandler->startDocument();
514
515        try
516        {
517                //  Scan the prolog part, which is everything before the root element
518                //  including the DTD subsets. This is all that is done on the scan
519                //  first.
520                scanProlog();
521
522                //  If we got to the end of input, then its not a valid XML file.
523                //  Else, go on to scan the content.
524                if (fReaderMgr.atEOF())
525                {
526                        emitError(XMLErrs::EmptyMainEntity);
527                }
528        }
529        //  NOTE:
530        //
531        //  In all of the error processing below, the emitError() call MUST come
532        //  before the flush of the reader mgr, or it will fail because it tries
533        //  to find out the position in the XML source of the error.
534        catch(const XMLErrs::Codes)
535        {
536                // This is a 'first failure' exception so return failure
537                return false;
538        }
539        catch(const XMLValid::Codes)
540        {
541                // This is a 'first fatal error' type exit, return failure
542                return false;
543        }
544        catch(const XMLException& excToCatch)
545        {
546                //  Emit the error and catch any user exception thrown from here. Make
547                //  sure in all cases we flush the reader manager.
548                fInException = true;
549                try
550                {
551                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
552                                emitError
553                                (
554                                        XMLErrs::XMLException_Warning
555                                        , excToCatch.getCode()
556                                        , excToCatch.getMessage()
557                                );
558                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
559                                emitError
560                                (
561                                        XMLErrs::XMLException_Fatal
562                                        , excToCatch.getCode()
563                                        , excToCatch.getMessage()
564                                );
565                        else
566                                emitError
567                                (
568                                        XMLErrs::XMLException_Error
569                                        , excToCatch.getCode()
570                                        , excToCatch.getMessage()
571                                );
572                }
573                catch(const OutOfMemoryException&)
574                {
575                        // This is a special case for out-of-memory
576                        // conditions, because resetting the ReaderMgr
577                        // can be problematic.
578                        resetReaderMgr.release();
579
580                        throw;
581                }
582
583                return false;
584        }
585        catch(const OutOfMemoryException&)
586        {
587                // This is a special case for out-of-memory
588                // conditions, because resetting the ReaderMgr
589                // can be problematic.
590                resetReaderMgr.release();
591
592                throw;
593        }
594
595        // Fill in the caller's token to make it legal and return success
596        toFill.set(fScannerId, fSequenceId);
597
598        // Release the object that will reset the ReaderMgr, since there's
599        // more to scan.
600        resetReaderMgr.release();
601
602        // Instruct this scanner to construct and initialize a progressive parser
603        scanFirst();
604
605        return true;
606}
607
608
609
610
611void XMLScanner::scanReset(XMLPScanToken& token)
612{
613        // Make sure this token is still legal
614        if (!isLegalToken(token))
615                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_BadPScanToken, fMemoryManager);
616
617        // Reset the reader manager
618        fReaderMgr.reset();
619
620        // And invalidate any tokens by bumping our sequence number
621        fSequenceId++;
622
623        // Reset our error count
624        fErrorCount = 0;
625
626}
627
628void XMLScanner::setParseSettings(XMLScanner* const refScanner)
629{
630        setDocHandler(refScanner->getDocHandler());
631        setDocTypeHandler(refScanner->getDocTypeHandler());
632        setErrorHandler(refScanner->getErrorHandler());
633        setErrorReporter(refScanner->getErrorReporter());
634        setEntityHandler(refScanner->getEntityHandler());
635        setDoNamespaces(refScanner->getDoNamespaces());
636        setDoSchema(refScanner->getDoSchema());
637        setCalculateSrcOfs(refScanner->getCalculateSrcOfs());
638        setStandardUriConformant(refScanner->getStandardUriConformant());
639        setExitOnFirstFatal(refScanner->getExitOnFirstFatal());
640        setValidationConstraintFatal(refScanner->getValidationConstraintFatal());
641        setIdentityConstraintChecking(refScanner->getIdentityConstraintChecking());
642        setValidationSchemaFullChecking(refScanner->getValidationSchemaFullChecking());
643        cacheGrammarFromParse(refScanner->isCachingGrammarFromParse());
644        useCachedGrammarInParse(refScanner->isUsingCachedGrammarInParse());
645        setLoadExternalDTD(refScanner->getLoadExternalDTD());
646        setLoadSchema(refScanner->getLoadSchema());
647        setNormalizeData(refScanner->getNormalizeData());
648        setExternalSchemaLocation(refScanner->getExternalSchemaLocation());
649        setExternalNoNamespaceSchemaLocation(refScanner->getExternalNoNamespaceSchemaLocation());
650        setValidationScheme(refScanner->getValidationScheme());
651        setSecurityManager(refScanner->getSecurityManager());
652        setPSVIHandler(refScanner->getPSVIHandler());
653}
654
655// ---------------------------------------------------------------------------
656//  XMLScanner: Private helper methods.
657// ---------------------------------------------------------------------------
658
659//  This method handles the common initialization, to avoid having to do
660//  it redundantly in multiple constructors.
661void XMLScanner::commonInit()
662{
663        //  We have to do a little init that involves statics, so we have to
664        //  use the mutex to protect it.
665        {
666                XMLMutexLock lockInit(sScannerMutex);
667
668                // And assign ourselves the next available scanner id
669                fScannerId = ++gScannerId;
670        }
671
672        //  Create the id ref list. This is used to enforce XML 1.0 ID ref
673        //  semantics, i.e. all id refs must refer to elements that exist
674        fValidationContext = new (fMemoryManager) ValidationContextImpl(fMemoryManager);
675        fValidationContext->setScanner(this);
676
677        //  Create the GrammarResolver
678        //fGrammarResolver = new GrammarResolver();
679
680/*
681        // Register self as handler for XMLBufferFull events on the CDATA buffer
682        fCDataBuf.setFullHandler(this, fBufferSize);
683*/
684   if (fValidator)
685        {
686           fValidatorFromUser = true;
687           initValidator(fValidator);
688   }
689}
690
691void XMLScanner::cleanUp()
692{
693        delete fValidationContext;
694        fMemoryManager->deallocate(fExternalSchemaLocation);
695        fMemoryManager->deallocate(fExternalNoNamespaceSchemaLocation);
696}
697
698void XMLScanner::initValidator(XMLValidator* theValidator)
699{
700        //  Tell the validator about the stuff it needs to know in order to do its work.
701        theValidator->setScannerInfo(this, &fReaderMgr, &fBufMgr);
702        theValidator->setErrorReporter(fErrorReporter);
703}
704
705// ---------------------------------------------------------------------------
706//  XMLScanner: Error emitting methods
707// ---------------------------------------------------------------------------
708
709//  These methods are called whenever the scanner wants to emit an error.
710//  It handles getting the message loaded, doing token replacement, etc...
711//  and then calling the error handler, if its installed.
712bool XMLScanner::emitErrorWillThrowException(const XMLErrs::Codes toEmit)
713{
714        if (XMLErrs::isFatal(toEmit) && fExitOnFirstFatal && !fInException)
715                return true;
716        return false;
717}
718
719void XMLScanner::emitError(const XMLErrs::Codes toEmit)
720{
721        // Bump the error count if it is not a warning
722        if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
723                incrementErrorCount();
724
725        if (fErrorReporter)
726        {
727                // Load the message into a local for display
728                const XMLSize_t msgSize = 1023;
729                XMLCh errText[msgSize + 1];
730
731                if (!gMsgLoader->loadMsg(toEmit, errText, msgSize))
732                {
733                                // <TBD> Probably should load a default msg here
734                }
735
736                //  Create a LastExtEntityInfo structure and get the reader manager
737                //  to fill it in for us. This will give us the information about
738                //  the last reader on the stack that was an external entity of some
739                //  sort (i.e. it will ignore internal entities.
740                ReaderMgr::LastExtEntityInfo lastInfo;
741                fReaderMgr.getLastExtEntityInfo(lastInfo);
742
743                fErrorReporter->error
744                (
745                        toEmit
746                        , XMLUni::fgXMLErrDomain
747                        , XMLErrs::errorType(toEmit)
748                        , errText
749                        , lastInfo.systemId
750                        , lastInfo.publicId
751                        , lastInfo.lineNumber
752                        , lastInfo.colNumber
753                );
754        }
755
756        // Bail out if its fatal an we are to give up on the first fatal error
757        if (emitErrorWillThrowException(toEmit))
758                throw toEmit;
759}
760
761void XMLScanner::emitError(const XMLErrs::Codes toEmit, const XMLFileLoc line, const XMLFileLoc col)
762{
763        // Bump the error count if it is not a warning
764        if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
765                incrementErrorCount();
766
767        if (fErrorReporter)
768        {
769                // Load the message into a local for display
770                const XMLSize_t msgSize = 1023;
771                XMLCh errText[msgSize + 1];
772
773                if (!gMsgLoader->loadMsg(toEmit, errText, msgSize))
774                {
775                                // <TBD> Probably should load a default msg here
776                }
777
778        // We have at least one entity so get the data
779        const XMLEntityDecl* theEntity;
780        const XMLReader* theReader = fReaderMgr.getLastExtEntity(theEntity);
781
782                fErrorReporter->error
783                (
784                        toEmit
785                        , XMLUni::fgXMLErrDomain
786                        , XMLErrs::errorType(toEmit)
787                        , errText
788            , theReader->getSystemId()
789            , theReader->getPublicId()
790                        , line
791                        , col
792                );
793        }
794
795        // Bail out if its fatal an we are to give up on the first fatal error
796        if (emitErrorWillThrowException(toEmit))
797                throw toEmit;
798}
799
800
801void XMLScanner::emitError( const   XMLErrs::Codes    toEmit
802                                                        , const XMLCh* const        text1
803                                                        , const XMLCh* const        text2
804                                                        , const XMLCh* const        text3
805                                                        , const XMLCh* const        text4)
806{
807        // Bump the error count if it is not a warning
808        if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
809                incrementErrorCount();
810
811        if (fErrorReporter)
812        {
813                //  Load the message into alocal and replace any tokens found in
814                //  the text.
815                const XMLSize_t maxChars = 2047;
816                XMLCh errText[maxChars + 1];
817
818                if (!gMsgLoader->loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fMemoryManager))
819                {
820                        // <TBD> Should probably load a default message here
821                }
822
823                //  Create a LastExtEntityInfo structure and get the reader manager
824                //  to fill it in for us. This will give us the information about
825                //  the last reader on the stack that was an external entity of some
826                //  sort (i.e. it will ignore internal entities.
827                ReaderMgr::LastExtEntityInfo lastInfo;
828                fReaderMgr.getLastExtEntityInfo(lastInfo);
829
830                fErrorReporter->error
831                (
832                        toEmit
833                        , XMLUni::fgXMLErrDomain
834                        , XMLErrs::errorType(toEmit)
835                        , errText
836                        , lastInfo.systemId
837                        , lastInfo.publicId
838                        , lastInfo.lineNumber
839                        , lastInfo.colNumber
840                );
841        }
842
843        // Bail out if its fatal an we are to give up on the first fatal error
844        if (emitErrorWillThrowException(toEmit))
845                throw toEmit;
846}
847
848void XMLScanner::emitError( const   XMLErrs::Codes    toEmit
849                                                        , const char* const         text1
850                                                        , const char* const         text2
851                                                        , const char* const         text3
852                                                        , const char* const         text4)
853{
854        // Bump the error count if it is not a warning
855        if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
856                incrementErrorCount();
857
858        if (fErrorReporter)
859        {
860                //  Load the message into alocal and replace any tokens found in
861                //  the text.
862                const XMLSize_t maxChars = 2047;
863                XMLCh errText[maxChars + 1];
864
865                if (!gMsgLoader->loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fMemoryManager))
866                {
867                                // <TBD> Should probably load a default message here
868                }
869
870                //  Create a LastExtEntityInfo structure and get the reader manager
871                //  to fill it in for us. This will give us the information about
872                //  the last reader on the stack that was an external entity of some
873                //  sort (i.e. it will ignore internal entities.
874                ReaderMgr::LastExtEntityInfo lastInfo;
875                fReaderMgr.getLastExtEntityInfo(lastInfo);
876
877                fErrorReporter->error
878                (
879                        toEmit
880                        , XMLUni::fgXMLErrDomain
881                        , XMLErrs::errorType(toEmit)
882                        , errText
883                        , lastInfo.systemId
884                        , lastInfo.publicId
885                        , lastInfo.lineNumber
886                        , lastInfo.colNumber
887                );
888        }
889
890        // Bail out if its fatal an we are to give up on the first fatal error
891        if (emitErrorWillThrowException(toEmit))
892                throw toEmit;
893}
894
895void XMLScanner::emitError( const   XMLErrs::Codes      toEmit
896                                                        , const XMLExcepts::Codes   originalExceptCode
897                                                        , const XMLCh* const        text1
898                                                        , const XMLCh* const        text2
899                                                        , const XMLCh* const        text3
900                                                        , const XMLCh* const        text4)
901{
902        // Bump the error count if it is not a warning
903        if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
904                incrementErrorCount();
905
906        if (fErrorReporter)
907        {
908                //  Load the message into alocal and replace any tokens found in
909                //  the text.
910                const XMLSize_t maxChars = 2047;
911                XMLCh errText[maxChars + 1];
912
913                if (!gMsgLoader->loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fMemoryManager))
914                {
915                                // <TBD> Should probably load a default message here
916                }
917
918                //  Create a LastExtEntityInfo structure and get the reader manager
919                //  to fill it in for us. This will give us the information about
920                //  the last reader on the stack that was an external entity of some
921                //  sort (i.e. it will ignore internal entities.
922                ReaderMgr::LastExtEntityInfo lastInfo;
923                fReaderMgr.getLastExtEntityInfo(lastInfo);
924
925                fErrorReporter->error
926                (
927                        originalExceptCode
928                        , XMLUni::fgExceptDomain    //fgXMLErrDomain
929                        , XMLErrs::errorType(toEmit)
930                        , errText
931                        , lastInfo.systemId
932                        , lastInfo.publicId
933                        , lastInfo.lineNumber
934                        , lastInfo.colNumber
935                );
936        }
937
938        // Bail out if its fatal an we are to give up on the first fatal error
939        if (emitErrorWillThrowException(toEmit))
940                throw toEmit;
941}
942
943// --------------------------------------------------------------------------------------------------------
944
945//  Scans the <?xml .... ?> line. This stuff is all sequential so we don't
946//  do any state machine loop here. We just bull straight through it. It ends
947//  past the closing bracket. If there is a document handler, then its called
948//  on the XMLDecl callback.
949//
950//  On entry, the <?xml has been scanned, and we pick it up from there.
951//
952//  NOTE: In order to provide good recovery from bad XML here, we try to be
953//  very flexible. No matter what order the stuff is in, we'll keep going
954//  though we'll issue errors.
955//
956//  The parameter tells us which type of decl we should expect, Text or XML.
957//    [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
958//    [77] TextDecl::= '<?xml' VersionInfo? EncodingDecl S? '?>'
959void XMLScanner::scanXMLDecl(const DeclTypes type)
960{
961        // Get us some buffers to use
962        XMLBufBid bbVersion(&fBufMgr);
963        XMLBufBid bbEncoding(&fBufMgr);
964        XMLBufBid bbStand(&fBufMgr);
965        XMLBufBid bbDummy(&fBufMgr);
966        XMLBufBid bbName(&fBufMgr);
967
968        //  We use this little enum and array to keep up with what we found
969        //  and what order we found them in. This lets us get them free form
970        //  without too much overhead, but still know that they were in the
971        //  wrong order.
972        enum Strings
973        {
974                VersionString
975                , EncodingString
976                , StandaloneString
977                , UnknownString
978
979                , StringCount
980        };
981        int flags[StringCount] = { -1, -1, -1, -1 };
982
983        //  Also set up a list of buffers in the right order so that we know
984        //  where to put stuff.
985        XMLBuffer* buffers[StringCount] ;
986        buffers[0] = &bbVersion.getBuffer();
987        buffers[1] = &bbEncoding.getBuffer();
988        buffers[2] = &bbStand.getBuffer();
989        buffers[3] = &bbDummy.getBuffer();
990
991        int curCount = 0;
992        Strings curString;
993        XMLBuffer& nameBuf = bbName.getBuffer();
994        while (true)
995        {
996                // Skip any spaces
997                bool skippedSomething;
998                fReaderMgr.skipPastSpaces(skippedSomething, true);
999
1000                // If we are looking at a question mark, then break out
1001                if (fReaderMgr.lookingAtChar(chQuestion))
1002                {
1003                        break;
1004                }
1005
1006                // If this is not the first string, then we require the spaces
1007                if (!skippedSomething && curCount)
1008                {
1009                        emitError(XMLErrs::ExpectedWhitespace);
1010                }
1011
1012                //  Get characters up to the next whitespace or equal's sign.
1013                if (!scanUpToWSOr(nameBuf, chEqual))
1014                {
1015                        emitError(XMLErrs::ExpectedDeclString);
1016                }
1017
1018                // See if it matches any of our expected strings
1019                if (XMLString::equals(nameBuf.getRawBuffer(), XMLUni::fgVersionString))
1020                {
1021                        curString = VersionString;
1022                }
1023                else if (XMLString::equals(nameBuf.getRawBuffer(), XMLUni::fgEncodingString))
1024                {
1025                        curString = EncodingString;
1026                }
1027                else if (XMLString::equals(nameBuf.getRawBuffer(), XMLUni::fgStandaloneString))
1028                {
1029                        curString = StandaloneString;
1030                }
1031                else
1032                {
1033                        curString = UnknownString;
1034                }
1035
1036                //  If its an unknown string, then give that error. Else check to
1037                //  see if this one has been done already and give that error.
1038                if (curString == UnknownString)
1039                        emitError(XMLErrs::ExpectedDeclString, nameBuf.getRawBuffer());
1040                else if (flags[curString] != -1)
1041                        emitError(XMLErrs::DeclStringRep, nameBuf.getRawBuffer());
1042                else if (flags[curString] == -1)
1043                        flags[curString] = ++curCount;
1044
1045                //  Scan for an equal's sign. If we don't find it, issue an error
1046                //  but keep trying to go on.
1047                if (!scanEq(true))
1048                        emitError(XMLErrs::ExpectedEqSign);
1049
1050                //  Get a quote string into the buffer for the string that we are
1051                //  currently working on.
1052                if (!getQuotedString(*buffers[curString]))
1053                {
1054                        emitError(XMLErrs::ExpectedQuotedString);
1055                        fReaderMgr.skipPastChar(chCloseAngle);
1056                        return;
1057                }
1058
1059                // And validate the value according which one it was
1060                const XMLCh* rawValue = buffers[curString]->getRawBuffer();
1061                if (curString == VersionString)
1062        {
1063
1064//            4.3.4 Version Information in Entities
1065
1066//            Each entity, including the document entity, can be separately declared as XML 1.0 or XML 1.1. The version declaration appearing in the document entity determines
1067//            the version of the document as a whole. An XML 1.1 document may invoke XML 1.0 external entities, so that otherwise duplicated versions of external entities, particularly
1068//            DTD external subsets, need not be maintained. However, in such a case the rules of XML 1.1 are applied to the entire document.
1069
1070
1071                        if (XMLString::equals(rawValue, XMLUni::fgVersion1_0))
1072                        {
1073                if (type == Decl_XML)
1074                {
1075                    fXMLVersion = XMLReader::XMLV1_0;
1076                    fReaderMgr.setXMLVersion(XMLReader::XMLV1_0);
1077                }
1078                        }
1079                        else if (XMLString::equals(rawValue, XMLUni::fgVersion1_1))
1080            {
1081                if (type == Decl_XML)
1082                {
1083                    fXMLVersion = XMLReader::XMLV1_1;
1084                    fReaderMgr.setXMLVersion(XMLReader::XMLV1_1);
1085                }
1086                else if (unlikely(fXMLVersion != XMLReader::XMLV1_1))
1087                {
1088                    emitError(XMLErrs::UnsupportedXMLVersion, rawValue);
1089                }
1090                        }
1091                        else
1092            {
1093                                emitError(XMLErrs::UnsupportedXMLVersion, rawValue);
1094            }
1095
1096            DEBUG_MESSAGE("fXMLVersion=" << fXMLVersion);
1097                }
1098                else if (curString == EncodingString)
1099                {
1100                        if (!XMLString::isValidEncName(rawValue))
1101                                emitError(XMLErrs::BadXMLEncoding, rawValue);
1102                }
1103                 else if (curString == StandaloneString)
1104                {
1105                        if (XMLString::equals(rawValue, XMLUni::fgYesString))
1106                                fStandalone = true;
1107                        else if (XMLString::equals(rawValue, XMLUni::fgNoString))
1108                                fStandalone = false;
1109                        else
1110                        {
1111                                emitError(XMLErrs::BadStandalone);
1112                                //if (!XMLString::compareIString(rawValue, XMLUni::fgYesString))
1113                                //else if (!XMLString::compareIString(rawValue, XMLUni::fgNoString))
1114                                if (buffers[curString]->getLen() == 3 &&
1115                                        (((rawValue[0] == chLatin_y) || (rawValue[0] == chLatin_Y)) &&
1116                                         ((rawValue[1] == chLatin_e) || (rawValue[1] == chLatin_E)) &&
1117                                         ((rawValue[2] == chLatin_s) || (rawValue[2] == chLatin_S))))
1118                                        fStandalone = true;
1119                                else if (buffers[curString]->getLen() == 2 &&
1120                                        (((rawValue[0] == chLatin_n) || (rawValue[0] == chLatin_N)) &&
1121                                         ((rawValue[1] == chLatin_o) || (rawValue[1] == chLatin_O))))
1122                                        fStandalone = false;
1123                        }
1124                }
1125        }
1126
1127        //  Make sure that the strings present are in order. We don't care about
1128        //  which ones are present at this point, just that any there are in the
1129        //  right order.
1130        int curTop = 0;
1131        for (int index = VersionString; index < StandaloneString; index++)
1132        {
1133                if (flags[index] != -1)
1134                {
1135                        if (flags[index] !=  curTop + 1)
1136                        {
1137                                emitError(XMLErrs::DeclStringsInWrongOrder);
1138                                break;
1139                        }
1140                        curTop = flags[index];
1141                }
1142        }
1143
1144        //  If its an XML decl, the version must be present.
1145        //  If its a Text decl, then encoding must be present AND standalone must not be present.
1146        if ((type == Decl_XML) && (flags[VersionString] == -1))
1147    {
1148                emitError(XMLErrs::XMLVersionRequired);
1149    }
1150    else if (type == Decl_Text)
1151    {
1152                if (flags[StandaloneString] != -1)
1153                        emitError(XMLErrs::StandaloneNotLegal);
1154                if (flags[EncodingString] == -1)
1155                        emitError(XMLErrs::EncodingRequired);
1156        }
1157
1158        if (!fReaderMgr.skippedChar(chQuestion))
1159        {
1160                emitError(XMLErrs::UnterminatedXMLDecl);
1161                fReaderMgr.skipPastChar(chCloseAngle);
1162        }
1163        else if (!fReaderMgr.skippedChar(chCloseAngle))
1164        {
1165                emitError(XMLErrs::UnterminatedXMLDecl);
1166                fReaderMgr.skipPastChar(chCloseAngle);
1167        }
1168
1169        //  Do this before we possibly update the reader with the
1170        //  actual encoding string. Otherwise, we will pass the wrong thing
1171        //  for the last parameter!
1172        const XMLCh* actualEnc = fReaderMgr.getCurrentEncodingStr();
1173
1174        //  Ok, we've now seen the real encoding string, if there was one, so
1175        //  lets call back on the current reader and tell it what the real
1176        //  encoding string was. If it fails, that's because it represents some
1177        //  sort of contradiction with the autosensed format, and it keeps the
1178        //  original encoding.
1179        //
1180        //  NOTE: This can fail for a number of reasons, such as a bogus encoding
1181        //  name or because its in flagrant contradiction of the auto-sensed
1182        //  format.
1183        if (flags[EncodingString] != -1)
1184        {
1185                if (!fReaderMgr.getCurrentReader()->setEncoding(bbEncoding.getRawBuffer()))
1186                        emitError(XMLErrs::ContradictoryEncoding, bbEncoding.getRawBuffer());
1187                else
1188                        actualEnc = bbEncoding.getRawBuffer();
1189        }
1190
1191        //  If we have a document handler then call the XML Decl callback.
1192        if (type == Decl_XML)
1193        {
1194                if (fDocHandler)
1195                        fDocHandler->XMLDecl
1196                        (
1197                                bbVersion.getRawBuffer()
1198                                , bbEncoding.getRawBuffer()
1199                                , bbStand.getRawBuffer()
1200                                , actualEnc
1201                        );
1202        }
1203        else if (type == Decl_Text)
1204        {
1205                if (fDocTypeHandler)
1206                        fDocTypeHandler->TextDecl
1207                        (
1208                                bbVersion.getRawBuffer()
1209                                , bbEncoding.getRawBuffer()
1210                        );
1211        }
1212}
1213
1214bool XMLScanner::checkXMLDecl(bool startWithAngle)
1215{
1216        // [23] XMLDecl     ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
1217        // [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
1218        //
1219        // [3]  S           ::= (#x20 | #x9 | #xD | #xA)+
1220
1221    bool found = false;
1222
1223    XMLReader * reader = fReaderMgr.getCurrentReader();
1224
1225        if (startWithAngle)
1226        {
1227        if (reader->peekString(XMLUni::fgXMLDeclStringSpace, 5, true))
1228        {
1229            found = true;
1230        }
1231        else if (unlikely(reader->peekString(XMLUni::fgXMLDeclStringSpaceU, 5, true)))
1232        {
1233            emitError(XMLErrs::XMLDeclMustBeLowerCase);
1234            found = true;
1235        }
1236        if (found)
1237        {
1238            reader->skipChars(6);
1239        }
1240        }
1241        else
1242        {
1243        if (reader->peekString(XMLUni::fgXMLStringSpace, 3, true))
1244        {
1245            found = true;
1246        }
1247        else if (unlikely(reader->peekString(XMLUni::fgXMLStringSpaceU, 3, true)))
1248        {
1249            emitError(XMLErrs::XMLDeclMustBeLowerCase);
1250            found = true;
1251        }
1252        if (found)
1253        {
1254            reader->skipChars(4);
1255        }
1256        }
1257
1258    return found;
1259}
1260
1261
1262// ---------------------------------------------------------------------------
1263//  XMLScanner: Grammar preparsing
1264// ---------------------------------------------------------------------------
1265Grammar* XMLScanner::loadGrammar(const   XMLCh* const systemId
1266                                                                 , const short        grammarType
1267                                                                 , const bool         toCache)
1268{
1269        InputSource* srcToUse = 0;
1270
1271        if (fEntityHandler){
1272                ReaderMgr::LastExtEntityInfo lastInfo;
1273                fReaderMgr.getLastExtEntityInfo(lastInfo);
1274                XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::ExternalEntity,
1275                                                        systemId, 0, XMLUni::fgZeroLenString, lastInfo.systemId,
1276                                                        &fReaderMgr);
1277                srcToUse = fEntityHandler->resolveEntity(&resourceIdentifier);
1278        }
1279
1280        //  First we try to parse it as a URL. If that fails, we assume its
1281        //  a file and try it that way.
1282        if (!srcToUse) {
1283                if (fDisableDefaultEntityResolution)
1284                        return 0;
1285
1286                try
1287                {
1288                        //  Create a temporary URL. Since this is the primary document,
1289                        //  it has to be fully qualified. If not, then assume we are just
1290                        //  mistaking a file for a URL.
1291                        XMLURL tmpURL(fMemoryManager);
1292
1293                        if (XMLURL::parse(systemId, tmpURL)) {
1294
1295                                if (tmpURL.isRelative())
1296                                {
1297                                        if (!fStandardUriConformant)
1298                                                srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager);
1299                                        else {
1300                                                // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr
1301                                                // emit the error directly
1302                                                MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_NoProtocolPresent, fMemoryManager);
1303                                                fInException = true;
1304                                                emitError
1305                                                (
1306                                                        XMLErrs::XMLException_Fatal
1307                                                        , e.getCode()
1308                                                        , e.getMessage()
1309                                                );
1310                                                return 0;
1311                                        }
1312                                }
1313                                else
1314                                {
1315                                        if (fStandardUriConformant && tmpURL.hasInvalidChar()) {
1316                                                MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL, fMemoryManager);
1317                                                fInException = true;
1318                                                emitError
1319                                                (
1320                                                        XMLErrs::XMLException_Fatal
1321                                                        , e.getCode()
1322                                                        , e.getMessage()
1323                                                );
1324                                                return 0;
1325                                        }
1326                                        srcToUse = new (fMemoryManager) URLInputSource(tmpURL, fMemoryManager);
1327                                }
1328                        }
1329                        else
1330                        {
1331                                if (!fStandardUriConformant)
1332                                        srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager);
1333                                else {
1334                                        // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr
1335                                        // emit the error directly
1336                                        // lazy bypass ... since all MalformedURLException are fatal, no need to check the type
1337                                        MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL);
1338                                        fInException = true;
1339                                        emitError
1340                                        (
1341                                                XMLErrs::XMLException_Fatal
1342                                                , e.getCode()
1343                                                , e.getMessage()
1344                                        );
1345                                        return 0;
1346                                }
1347                        }
1348                }
1349                catch(const XMLException& excToCatch)
1350                {
1351                        //  For any other XMLException,
1352                        //  emit the error and catch any user exception thrown from here.
1353                        fInException = true;
1354                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
1355                                emitError
1356                                (
1357                                        XMLErrs::XMLException_Warning
1358                                        , excToCatch.getCode()
1359                                        , excToCatch.getMessage()
1360                                );
1361                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
1362                                emitError
1363                                (
1364                                        XMLErrs::XMLException_Fatal
1365                                        , excToCatch.getCode()
1366                                        , excToCatch.getMessage()
1367                                );
1368                        else
1369                                emitError
1370                                (
1371                                        XMLErrs::XMLException_Error
1372                                        , excToCatch.getCode()
1373                                        , excToCatch.getMessage()
1374                                );
1375                                return 0;
1376                }
1377        }
1378
1379        Janitor<InputSource> janSrc(srcToUse);
1380        return loadGrammar(*srcToUse, grammarType, toCache);
1381}
1382
1383Grammar* XMLScanner::loadGrammar(const   char* const systemId
1384                                                                 , const short       grammarType
1385                                                                 , const bool        toCache)
1386{
1387        // We just delegate this to the XMLCh version after transcoding
1388        XMLCh* tmpBuf = XMLString::transcode(systemId, fMemoryManager);
1389        ArrayJanitor<XMLCh> janBuf(tmpBuf, fMemoryManager);
1390        return loadGrammar(tmpBuf, grammarType, toCache);
1391}
1392
1393// ---------------------------------------------------------------------------
1394//  XMLScanner: Error handling methods
1395// ---------------------------------------------------------------------------
1396
1397void XMLScanner::reportUndefinedAttribute(unsigned int uriId, const QName * attributeName, const XMLElementDecl & element)
1398{
1399    XMLBuffer bufMsg(1023, fMemoryManager);
1400    if (uriId != XMLNamespaceResolver::fEmptyUriId)
1401    {
1402        bufMsg.append(chOpenCurly);
1403        bufMsg.append(fUriResolver->getUriForId(uriId));
1404        bufMsg.append(chCloseCurly);
1405    }
1406    bufMsg.append(attributeName->getLocalPart());
1407
1408    fValidator->emitError(XMLValid::AttNotDefinedForElement, bufMsg.getRawBuffer(), element.getBaseName());
1409}
1410
1411// ---------------------------------------------------------------------------
1412//  XMLScanner: Private helper methods
1413// ---------------------------------------------------------------------------
1414
1415/***
1416 * In reusing grammars (cacheing grammar from parse, or use cached grammar), internal
1417 * dtd is allowed conditionally.
1418 *
1419 * In the case of cacheing grammar from parse, it is NOT allowed.
1420 *
1421 * In the case of use cached grammar,
1422 *   if external dtd is present and it is parsed before, then it is not allowed,
1423 *   otherwise it is allowed.
1424 *
1425 ***/
1426void XMLScanner::checkInternalDTD(bool hasExtSubset
1427                                                                 ,const XMLCh* const sysId
1428                                                                 ,const XMLCh* const pubId)
1429{
1430        if (fToCacheGrammar)
1431                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Val_CantHaveIntSS, fMemoryManager);
1432
1433        if (fUseCachedGrammar && hasExtSubset && !fIgnoreCachedDTD)
1434        {
1435                InputSource* sysIdSrc = resolveSystemId(sysId, pubId);
1436        if (sysIdSrc)
1437        {
1438                        Janitor<InputSource> janSysIdSrc(sysIdSrc);
1439                        Grammar* grammar = fGrammarResolver->getGrammar(sysIdSrc->getSystemId());
1440
1441                        if (grammar && grammar->getGrammarType() == Grammar::DTDGrammarType)
1442                        {
1443                                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Val_CantHaveIntSS, fMemoryManager);
1444                        }
1445                }
1446        }
1447
1448}
1449
1450//  This method is called after the content scan to insure that all the
1451//  ID/IDREF attributes match up (i.e. that all IDREFs refer to IDs.) This is
1452//  an XML 1.0 rule, so we can do here in the core.
1453
1454void XMLScanner::checkIDRefs()
1455{
1456        //  Iterate the id ref list. If we find any entries here which are used
1457        //  but not declared, then that's an error.
1458        RefHashTableOfEnumerator<XMLRefInfo> refEnum(fValidationContext->getIdRefList(), false, fMemoryManager);
1459        while (refEnum.hasMoreElements())
1460        {
1461                // Get a ref to the current element
1462                const XMLRefInfo& curRef = refEnum.nextElement();
1463
1464                // If its used but not declared, then its an error
1465                if (!curRef.getDeclared() && curRef.getUsed() && fValidate)
1466                        fValidator->emitError(XMLValid::IDNotDeclared, curRef.getRefName());
1467        }
1468}
1469
1470
1471//  This just does a simple check that the passed progressive scan token is
1472//  legal for this scanner.
1473bool XMLScanner::isLegalToken(const XMLPScanToken& toCheck)
1474{
1475        return ((fScannerId == toCheck.fScannerId) && (fSequenceId == toCheck.fSequenceId));
1476}
1477
1478//  Scans a PI and calls the appropriate callbacks. At entry we have just
1479//  scanned the <? part, and need to now start on the PI target name.
1480void XMLScanner::scanPI()
1481{
1482#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
1483        const XMLCh* namePtr = 0;
1484        const XMLCh* targetPtr = 0;
1485
1486        //  If there are any spaces here, then warn about it. If we aren't in
1487        //  'first error' mode, then we'll come back and can easily pick up
1488        //  again by just skipping them.
1489        if (fReaderMgr.lookingAtSpace())
1490        {
1491                emitError(XMLErrs::PINameExpected);
1492                fReaderMgr.skipPastSpaces();
1493        }
1494
1495        // Get a buffer for the PI name and scan it in
1496        XMLBufBid bbName(&fBufMgr);
1497        if (!fReaderMgr.getName(bbName.getBuffer()))
1498        {
1499                emitError(XMLErrs::PINameExpected);
1500                fReaderMgr.skipPastChar(chCloseAngle);
1501                return;
1502        }
1503
1504        // Point the name pointer at the raw data
1505        namePtr = bbName.getRawBuffer();
1506
1507        // See if it is some form of 'xml' and emit a warning
1508        //if (!XMLString::compareIString(namePtr, XMLUni::fgXMLString))
1509        if (bbName.getLen() == 3 &&
1510                (((namePtr[0] == chLatin_x) || (namePtr[0] == chLatin_X)) &&
1511                 ((namePtr[1] == chLatin_m) || (namePtr[1] == chLatin_M)) &&
1512                 ((namePtr[2] == chLatin_l) || (namePtr[2] == chLatin_L))))
1513                emitError(XMLErrs::NoPIStartsWithXML);
1514
1515        // If namespaces are enabled, then no colons allowed
1516        if (fDoNamespaces)
1517        {
1518                if (XMLString::indexOf(namePtr, chColon) != -1)
1519                        emitError(XMLErrs::ColonNotLegalWithNS);
1520        }
1521
1522        //  If we don't hit a space next, then the PI has no target. If we do
1523        //  then get out the target. Get a buffer for it as well
1524        XMLBufBid bbTarget(&fBufMgr);
1525        if (fReaderMgr.skippedSpace())
1526        {
1527                // Skip any leading spaces
1528                fReaderMgr.skipPastSpaces();
1529
1530                bool gotLeadingSurrogate = false;
1531
1532                // It does have a target, so lets move on to deal with that.
1533                while (1)
1534                {
1535                        const XMLCh nextCh = fReaderMgr.getNextChar();
1536
1537                        // Watch for an end of file, which is always bad here
1538                        if (!nextCh)
1539                        {
1540                                emitError(XMLErrs::UnterminatedPI);
1541                                ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager);
1542                        }
1543
1544                        // Watch for potential terminating character
1545                        if (nextCh == chQuestion)
1546                        {
1547                                // It must be followed by '>' to be a termination of the target
1548                                if (fReaderMgr.skippedChar(chCloseAngle))
1549                                        break;
1550                        }
1551
1552                        // Check for correct surrogate pairs
1553            if (unlikely((nextCh >= 0xD800) && (nextCh <= 0xDBFF)))
1554                        {
1555                                if (gotLeadingSurrogate)
1556                                        emitError(XMLErrs::Expected2ndSurrogateChar);
1557                                else
1558                                        gotLeadingSurrogate = true;
1559                        }
1560            else
1561                        {
1562                if (unlikely(gotLeadingSurrogate))
1563                                {
1564                                        if ((nextCh < 0xDC00) || (nextCh > 0xDFFF))
1565                                                emitError(XMLErrs::Expected2ndSurrogateChar);
1566                    gotLeadingSurrogate = false;
1567                                }
1568                // Its got to at least be a valid XML character
1569                else if (!XMLNameChar::isXMLChar(nextCh, (getXMLVersion() == XMLReader::XMLV1_0)))
1570                {
1571
1572                    XMLCh tmpBuf[9];
1573                    XMLString::binToText
1574                    (
1575                        nextCh
1576                        , tmpBuf
1577                        , 8
1578                        , 16
1579                        , fMemoryManager
1580                    );
1581                    emitError(XMLErrs::InvalidCharacter, tmpBuf);
1582                }
1583                        }
1584
1585                        bbTarget.append(nextCh);
1586                }
1587        }
1588        else
1589        {
1590                // No target, but make sure its terminated ok
1591                if (!fReaderMgr.skippedChar(chQuestion))
1592                {
1593                        emitError(XMLErrs::UnterminatedPI);
1594                        fReaderMgr.skipPastChar(chCloseAngle);
1595                        return;
1596                }
1597
1598                if (!fReaderMgr.skippedChar(chCloseAngle))
1599                {
1600                        emitError(XMLErrs::UnterminatedPI);
1601                        fReaderMgr.skipPastChar(chCloseAngle);
1602                        return;
1603                }
1604        }
1605
1606        // Point the target pointer at the raw data
1607    targetPtr = bbTarget.getRawBuffer();
1608
1609        // If we have a handler, then call it
1610        if (fDocHandler)
1611        {
1612                fDocHandler->docPI
1613                (
1614                        namePtr
1615                        , targetPtr
1616           );
1617        }
1618
1619    DEBUG_MESSAGE("scanPI(" << namePtr << ',' << targetPtr << ')');
1620
1621        //mark PI is seen within the current element
1622        if (! fElemStack.isEmpty())
1623                fElemStack.setCommentOrPISeen();
1624#else
1625        DEPRECATED_FEATURE_IN_ICXML;
1626#endif
1627}
1628
1629//  We get here after the '<!--' part of the comment. We scan past the
1630//  terminating '-->' It will calls the appropriate handler with the comment
1631//  text, if one is provided. A comment can be in either the document or
1632//  the DTD, so the fInDocument flag is used to know which handler to send
1633//  it to.
1634void XMLScanner::scanComment()
1635{
1636#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
1637
1638        enum States
1639        {
1640                InText
1641                , OneDash
1642                , TwoDashes
1643        };
1644
1645        // Get a buffer for this
1646        XMLBufBid bbComment(&fBufMgr);
1647
1648        //  Get the comment text into a temp buffer. Be sure to use temp buffer
1649        //  two here, since its to be used for stuff that is potentially longer
1650        //  than just a name.
1651        States curState = InText;
1652        bool gotLeadingSurrogate = false;
1653        while (true)
1654        {
1655                // Get the next character
1656                const XMLCh nextCh = fReaderMgr.getNextChar();
1657
1658                //  Watch for an end of file
1659                if (!nextCh)
1660                {
1661                        emitError(XMLErrs::UnterminatedComment);
1662                        ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager);
1663                }
1664
1665                // Check for correct surrogate pairs
1666                if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF))
1667                {
1668                        if (gotLeadingSurrogate)
1669                                emitError(XMLErrs::Expected2ndSurrogateChar);
1670                        else
1671                                gotLeadingSurrogate = true;
1672                }
1673                else
1674                {
1675                        if (gotLeadingSurrogate)
1676                        {
1677                                if ((nextCh < 0xDC00) || (nextCh > 0xDFFF))
1678                                        emitError(XMLErrs::Expected2ndSurrogateChar);
1679                        }
1680                        // Its got to at least be a valid XML character
1681            else if (!XMLNameChar::isXMLChar(nextCh, (getXMLVersion() == XMLReader::XMLV1_0))) {
1682
1683                                XMLCh tmpBuf[9];
1684                                XMLString::binToText
1685                                (
1686                                        nextCh
1687                                        , tmpBuf
1688                                        , 8
1689                                        , 16
1690                                        , fMemoryManager
1691                                );
1692                                emitError(XMLErrs::InvalidCharacter, tmpBuf);
1693                        }
1694
1695                        gotLeadingSurrogate = false;
1696                }
1697
1698                if (curState == InText)
1699                {
1700                        // If its a dash, go to OneDash state. Otherwise take as text
1701                        if (nextCh == chDash)
1702                                curState = OneDash;
1703                        else
1704                                bbComment.append(nextCh);
1705                }
1706                else if (curState == OneDash)
1707                {
1708                        //  If its another dash, then we change to the two dashes states.
1709                        //  Otherwise, we have to put in the deficit dash and the new
1710                        //  character and go back to InText.
1711                        if (nextCh == chDash)
1712                        {
1713                                curState = TwoDashes;
1714                        }
1715                        else
1716                        {
1717                                bbComment.append(chDash);
1718                                bbComment.append(nextCh);
1719                                curState = InText;
1720                        }
1721                }
1722                else if (curState == TwoDashes)
1723                {
1724                        // The next character must be the closing bracket
1725                        if (nextCh != chCloseAngle)
1726                        {
1727                                emitError(XMLErrs::IllegalSequenceInComment);
1728                                fReaderMgr.skipPastChar(chCloseAngle);
1729                                return;
1730                        }
1731                        break;
1732                }
1733        }
1734
1735        // If we have an available handler, call back with the comment.
1736        if (fDocHandler)
1737        {
1738                fDocHandler->docComment
1739                (
1740                        bbComment.getRawBuffer()
1741                );
1742        }
1743
1744        DEBUG_MESSAGE("scanComment(" << bbComment.getRawBuffer() << ')');
1745
1746        //mark comment is seen within the current element
1747        if (! fElemStack.isEmpty())
1748                fElemStack.setCommentOrPISeen();
1749#else
1750        DEPRECATED_FEATURE_IN_ICXML;
1751#endif
1752}
1753
1754
1755//  Scans all the input from the start of the file to the root element.
1756//  There does not have to be anything in the prolog necessarily, but usually
1757//  there is at least an XMLDecl.
1758//
1759//  On exit from here we are either at the end of the file or about to read
1760//  the opening < of the root element.
1761void XMLScanner::scanProlog()
1762{
1763    DEBUG_MESSAGE("XMLScanner::scanProlog()")
1764
1765        bool sawDocTypeDecl = false;
1766    bool seenAnything = false;
1767        // Get a buffer for whitespace processing
1768        XMLBufBid bbCData(&fBufMgr);
1769
1770        //  Loop through the prolog. If there is no content, this could go all
1771        //  the way to the end of the file.
1772
1773    for (;;)
1774    {
1775        const XMLCh nextCh = fReaderMgr.peekNextChar();
1776
1777        DEBUG_MESSAGE(" -- nextCh=" << nextCh << ' ' << (char)nextCh)
1778
1779        if (nextCh == chOpenAngle)
1780        {
1781            //  Ok, it could be the xml decl, a comment, the doc type line,
1782            //  or the start of the root element.
1783            if (checkXMLDecl(true))
1784            {
1785                // There shall be at lease --ONE-- space in between
1786                // the tag '<?xml' and the VersionInfo.
1787                //
1788                //  If we are not at line 1, col 6, then the decl was not
1789                //  the first text, so its invalid.
1790                if (seenAnything)
1791                {
1792                    emitError(XMLErrs::XMLDeclMustBeFirst);
1793                }
1794
1795                DEBUG_MESSAGE("XMLScanner::scanXMLDecl()")
1796                scanXMLDecl(Decl_XML);
1797            }
1798            else if (fReaderMgr.skippedString(XMLUni::fgPIString))
1799            {
1800                DEBUG_MESSAGE("XMLScanner::scanPI()")
1801                scanPI();
1802                seenAnything = true;
1803            }
1804            else if (fReaderMgr.skippedString(XMLUni::fgCommentString))
1805            {
1806                DEBUG_MESSAGE("XMLScanner::scanComment()")
1807                scanComment();
1808                seenAnything = true;
1809            }
1810            else if (fReaderMgr.skippedString(XMLUni::fgDocTypeString))
1811            {
1812                DEBUG_MESSAGE("XMLScanner::scanDocTypeDecl()")
1813                if (sawDocTypeDecl)
1814                {
1815                    emitError(XMLErrs::DuplicateDocTypeDecl);
1816                }
1817                scanDocTypeDecl();
1818                sawDocTypeDecl = true;
1819                seenAnything = true;
1820                // if reusing grammar, this has been validated already in first scan
1821                // skip for performance
1822                if (fValidate && fGrammar && !fGrammar->getValidated())
1823                {
1824                    //  validate the DTD scan so far
1825                    fValidator->preContentValidation(fUseCachedGrammar, true);
1826                }
1827            }
1828            else
1829            {
1830                // Assume its the start of the root element
1831                break;
1832            }
1833        }
1834        else if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh))
1835        {
1836            //  If we have a document handler then gather up the
1837            //  whitespace and call back. Otherwise just skip over spaces.
1838            if (fDocHandler)
1839            {
1840                fReaderMgr.getSpaces(bbCData.getBuffer());
1841                fDocHandler->ignorableWhitespace
1842                (
1843                    bbCData.getRawBuffer()
1844                    , bbCData.getLen()
1845                    , false
1846                );
1847            }
1848            else
1849            {
1850                fReaderMgr.skipPastSpaces();
1851            }
1852        }
1853        else
1854        {
1855            emitError(XMLErrs::InvalidDocumentStructure);
1856
1857            // Watch for end of file and break out
1858            if (!nextCh)
1859                break;
1860            else
1861                fReaderMgr.skipPastChar(chCloseAngle);
1862        }
1863
1864    }
1865
1866}
1867
1868
1869// ---------------------------------------------------------------------------
1870//  XMLScanner: Private parsing methods
1871// ---------------------------------------------------------------------------
1872
1873//  This guy just scans out a single or double quoted string of characters.
1874//  It does not pass any judgement on the contents and assumes that it is
1875//  illegal to have another quote of the same kind inside the string's
1876//  contents.
1877//
1878//  NOTE: This is for simple stuff like the strings in the XMLDecl which
1879//  cannot have any entities inside them. So this guy does not handle any
1880//  end of entity stuff.
1881bool XMLScanner::getQuotedString(XMLBuffer& toFill)
1882{
1883#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
1884        // Reset the target buffer
1885        toFill.reset();
1886
1887        // Get the next char which must be a single or double quote
1888        XMLCh quoteCh;
1889        if (!fReaderMgr.skipIfQuote(quoteCh))
1890                return false;
1891
1892                XMLCh nextCh;
1893        // Get another char and see if it matches the starting quote char
1894        while ((nextCh=fReaderMgr.getNextChar())!=quoteCh)
1895        {
1896                //  We should never get either an end of file null char here. If we
1897                //  do, just fail. It will be handled more gracefully in the higher
1898                //  level code that called us.
1899                if (!nextCh)
1900                        return false;
1901
1902                // Else add it to the buffer
1903                toFill.append(nextCh);
1904        }
1905        return true;
1906#else
1907        DEPRECATED_FEATURE_IN_ICXML;
1908#endif
1909}
1910
1911bool XMLScanner::expandEntityReference
1912(
1913    const XMLCh *                   /* entityReference */
1914    , const XMLSize_t               /* length */
1915    , const bool                    /* inAttributeValue */
1916    , XMLBuffer &                   /* toFill */
1917    , bool      &                   /* isPredefined */
1918    , XMLReader::XMLVersion &       /* version */
1919    , XMLFileLoc &                  /* line */
1920    , XMLFileLoc &                  /* column */
1921)
1922{
1923    return 0;
1924}
1925
1926//  This method scans a character reference and returns the character that
1927//  was refered to. It assumes that we've already scanned the &# characters
1928//  that prefix the numeric code.
1929bool XMLScanner::scanCharRef(XMLBuffer & toFill)
1930{
1931        bool gotOne = false;
1932        unsigned int value = 0;
1933
1934        //  Set the radix. Its supposed to be a lower case x if hex. But, in
1935        //  order to recover well, we check for an upper and put out an error
1936        //  for that.
1937        unsigned int radix = 10;
1938        if (fReaderMgr.skippedChar(chLatin_x))
1939        {
1940                radix = 16;
1941        }
1942        else if (fReaderMgr.skippedChar(chLatin_X))
1943        {
1944                emitError(XMLErrs::HexRadixMustBeLowerCase);
1945                radix = 16;
1946        }
1947
1948        while (true)
1949        {
1950                const XMLCh nextCh = fReaderMgr.peekNextChar();
1951
1952                // Watch for EOF
1953                if (!nextCh)
1954                        ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager);
1955
1956                // Break out on the terminating semicolon
1957                if (nextCh == chSemiColon)
1958                {
1959                        fReaderMgr.getNextChar();
1960                        break;
1961                }
1962
1963                //  Convert this char to a binary value, or bail out if its not
1964                //  one.
1965                unsigned int nextVal;
1966                if ((nextCh >= chDigit_0) && (nextCh <= chDigit_9))
1967                        nextVal = (unsigned int)(nextCh - chDigit_0);
1968                else if ((nextCh >= chLatin_A) && (nextCh <= chLatin_F))
1969                        nextVal= (unsigned int)(10 + (nextCh - chLatin_A));
1970                else if ((nextCh >= chLatin_a) && (nextCh <= chLatin_f))
1971                        nextVal = (unsigned int)(10 + (nextCh - chLatin_a));
1972                else
1973                {
1974                        //  If we got at least a sigit, then do an unterminated ref error.
1975                        //  Else, do an expected a numerical ref thing.
1976                        if (gotOne)
1977                                emitError(XMLErrs::UnterminatedCharRef);
1978                        else
1979                                emitError(XMLErrs::ExpectedNumericalCharRef);
1980                        // Return failure
1981                        return false;
1982                }
1983
1984                //  Make sure its valid for the radix. If not, then just eat the
1985                //  digit and go on after issueing an error. Else, update the
1986                //  running value with this new digit.
1987                if (nextVal >= radix)
1988                {
1989                        XMLCh tmpStr[2];
1990                        tmpStr[0] = nextCh;
1991                        tmpStr[1] = chNull;
1992                        emitError(XMLErrs::BadDigitForRadix, tmpStr);
1993                }
1994                else
1995                {
1996                        value = (value * radix) + nextVal;
1997                        // Guard against overflow.
1998                        if (value > 0x10FFFF)
1999                        {
2000                                // Character reference was not in the valid range
2001                                emitError(XMLErrs::InvalidCharacterRef);
2002                                return false;
2003                        }
2004                }
2005
2006                // Indicate that we got at least one good digit
2007                gotOne = true;
2008
2009                // And eat the last char
2010                fReaderMgr.getNextChar();
2011        }
2012
2013        // Return the char (or chars)
2014        // And check if the character expanded is valid or not
2015        if (value >= 0x10000 && value <= 0x10FFFF)
2016        {
2017                value -= 0x10000;
2018                toFill.append(XMLCh((value >> 10) + 0xD800));
2019                toFill.append(XMLCh((value & 0x3FF) + 0xDC00));
2020        }
2021        else if (value <= 0xFFFD)
2022        {
2023                XMLCh Char = XMLCh(value);
2024                toFill.append(Char);       
2025        if (!XMLNameChar::isXMLChar(Char, (getXMLVersion() == XMLReader::XMLV1_0)))
2026                {
2027                        // Character reference was not in the valid range
2028                        emitError(XMLErrs::InvalidCharacterRef);
2029                        return false;
2030                }
2031        }
2032        else
2033        {
2034                // Character reference was not in the valid range
2035                emitError(XMLErrs::InvalidCharacterRef);
2036                return false;
2037        }
2038
2039        return true;
2040}
2041
2042//  Most equal signs can have white space around them, so this little guy
2043//  just makes the calling code cleaner by eating whitespace.
2044bool XMLScanner::scanEq(bool inDecl)
2045{
2046#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
2047        if (inDecl)
2048        {
2049                bool skippedSomething;
2050                fReaderMgr.skipPastSpaces(skippedSomething, inDecl);
2051                if (fReaderMgr.skippedChar(chEqual))
2052                {
2053                        fReaderMgr.skipPastSpaces(skippedSomething, inDecl);
2054                        return true;
2055                }
2056        }
2057        else
2058        {
2059                fReaderMgr.skipPastSpaces();
2060                if (fReaderMgr.skippedChar(chEqual))
2061                {
2062                        fReaderMgr.skipPastSpaces();
2063                        return true;
2064                }
2065        }
2066        return false;
2067#else
2068        DEPRECATED_FEATURE_IN_ICXML;
2069#endif
2070}
2071
2072XMLSize_t
2073XMLScanner::scanUpToWSOr(XMLBuffer& toFill, const XMLCh chEndChar)
2074{
2075#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
2076        fReaderMgr.getUpToCharOrWS(toFill, chEndChar);
2077        return toFill.getLen();
2078#else
2079        DEPRECATED_FEATURE_IN_ICXML;
2080#endif
2081}
2082
2083
2084
2085unsigned int
2086XMLScanner::resolveQName(  const XMLCh* const           qName
2087                                                 ,       XMLBuffer&             prefixBuf
2088                                                 , const ElemStack::MapModes    mode
2089                                                 ,       int&                   prefixColonPos)
2090{
2091        DEPRECATED_FEATURE_IN_ICXML;
2092}
2093
2094unsigned int
2095XMLScanner::resolveQNameWithColon(  const XMLCh* const          qName
2096                                                                  ,       XMLBuffer&            prefixBuf
2097                                                                  , const ElemStack::MapModes   mode
2098                                                                  , const int                   prefixColonPos)
2099{
2100        DEPRECATED_FEATURE_IN_ICXML;
2101}
2102
2103// ---------------------------------------------------------------------------
2104//  XMLScanner: Private scanning methods
2105// ---------------------------------------------------------------------------
2106
2107//  This method is called after the end of the root element, to handle
2108//  any miscellaneous stuff hanging around.
2109void XMLScanner::scanMiscellaneous()
2110{
2111        DEPRECATED_FEATURE_IN_ICXML;
2112}
2113
2114/******************************************************************************************************
2115  ICXML - DEPRECATED FUNCTIONS
2116 ******************************************************************************************************/
2117unsigned int XMLScanner::resolvePrefix(const XMLCh* const, const ElemStack::MapModes)
2118{
2119        DEPRECATED_FEATURE_IN_ICXML;
2120}
2121
2122unsigned int *XMLScanner::getNewUIntPtr()
2123{
2124        DEPRECATED_FEATURE_IN_ICXML;
2125}
2126
2127void XMLScanner::resetUIntPool()
2128{
2129        DEPRECATED_FEATURE_IN_ICXML;
2130}
2131
2132void XMLScanner::recreateUIntPool()
2133{
2134        DEPRECATED_FEATURE_IN_ICXML;
2135}
2136
2137void XMLScanner::setURIStringPool(XMLStringPool* const)
2138{
2139        DEPRECATED_FEATURE_IN_ICXML;
2140}
2141
2142bool XMLScanner::getURIText(const unsigned int, XMLBuffer &) const
2143{
2144        DEPRECATED_FEATURE_IN_ICXML;
2145}
2146
2147bool XMLScanner::scanCharRef(XMLCh &, XMLCh &)
2148{
2149        DEPRECATED_FEATURE_IN_ICXML;
2150}
2151
2152XMLScanner::XMLTokens XMLScanner::senseNextToken(XMLSize_t&)
2153{
2154    DEPRECATED_FEATURE_IN_ICXML;
2155}
2156
2157
2158XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.