Orb/Doxygen/qtools/qxml.cpp
changeset 0 42188c7ea2d9
equal deleted inserted replaced
-1:000000000000 0:42188c7ea2d9
       
     1 /****************************************************************************
       
     2 ** 
       
     3 **
       
     4 ** Implementation of QXmlSimpleReader and related classes.
       
     5 **
       
     6 ** Created : 000518
       
     7 **
       
     8 ** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
       
     9 **
       
    10 ** This file is part of the XML module of the Qt GUI Toolkit.
       
    11 **
       
    12 ** This file may be distributed under the terms of the Q Public License
       
    13 ** as defined by Trolltech AS of Norway and appearing in the file
       
    14 ** LICENSE.QPL included in the packaging of this file.
       
    15 **
       
    16 ** This file may be distributed and/or modified under the terms of the
       
    17 ** GNU General Public License version 2 as published by the Free Software
       
    18 ** Foundation and appearing in the file LICENSE.GPL included in the
       
    19 ** packaging of this file.
       
    20 **
       
    21 ** Licensees holding valid Qt Enterprise Edition licenses may use this
       
    22 ** file in accordance with the Qt Commercial License Agreement provided
       
    23 ** with the Software.
       
    24 **
       
    25 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
       
    26 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
       
    27 **
       
    28 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
       
    29 **   information about Qt Commercial License Agreements.
       
    30 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
       
    31 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
       
    32 **
       
    33 ** Contact info@trolltech.com if any conditions of this licensing are
       
    34 ** not clear to you.
       
    35 **
       
    36 **********************************************************************/
       
    37 
       
    38 #define QT_XML_CPP
       
    39 #include "qxml.h"
       
    40 #include "qtextcodec.h"
       
    41 #include "qbuffer.h"
       
    42 
       
    43 #ifndef QT_NO_XML
       
    44 // NOT REVISED
       
    45 
       
    46 // Error strings for the XML reader
       
    47 #define XMLERR_OK                         "no error occured"
       
    48 #define XMLERR_TAGMISMATCH                "tag mismatch"
       
    49 #define XMLERR_UNEXPECTEDEOF              "unexpected end of file"
       
    50 #define XMLERR_FINISHEDPARSINGWHILENOTEOF "parsing is finished but end of file is not reached"
       
    51 #define XMLERR_LETTEREXPECTED             "letter is expected"
       
    52 #define XMLERR_ERRORPARSINGELEMENT        "error while parsing element"
       
    53 #define XMLERR_ERRORPARSINGPROLOG         "error while parsing prolog"
       
    54 #define XMLERR_ERRORPARSINGMAINELEMENT    "error while parsing main element"
       
    55 #define XMLERR_ERRORPARSINGCONTENT        "error while parsing content"
       
    56 #define XMLERR_ERRORPARSINGNAME           "error while parsing name"
       
    57 #define XMLERR_ERRORPARSINGNMTOKEN        "error while parsing Nmtoken"
       
    58 #define XMLERR_ERRORPARSINGATTRIBUTE      "error while parsing attribute"
       
    59 #define XMLERR_ERRORPARSINGMISC           "error while parsing misc"
       
    60 #define XMLERR_ERRORPARSINGCHOICE         "error while parsing choice or seq"
       
    61 #define XMLERR_ERRORBYCONSUMER            "error triggered by consumer"
       
    62 #define XMLERR_UNEXPECTEDCHARACTER        "unexpected character"
       
    63 #define XMLERR_EQUALSIGNEXPECTED          "expected '=' but not found"
       
    64 #define XMLERR_QUOTATIONEXPECTED          "expected \" or ' but not found"
       
    65 #define XMLERR_ERRORPARSINGREFERENCE      "error while parsing reference"
       
    66 #define XMLERR_ERRORPARSINGPI             "error while parsing processing instruction"
       
    67 #define XMLERR_ERRORPARSINGATTLISTDECL    "error while parsing attribute list declaration"
       
    68 #define XMLERR_ERRORPARSINGATTTYPE        "error while parsing attribute type declaration"
       
    69 #define XMLERR_ERRORPARSINGATTVALUE       "error while parsing attribute value declaration"
       
    70 #define XMLERR_ERRORPARSINGELEMENTDECL    "error while parsing element declaration"
       
    71 #define XMLERR_ERRORPARSINGENTITYDECL     "error while parsing entity declaration"
       
    72 #define XMLERR_ERRORPARSINGNOTATIONDECL   "error while parsing notation declaration"
       
    73 #define XMLERR_ERRORPARSINGEXTERNALID     "error while parsing external id"
       
    74 #define XMLERR_ERRORPARSINGCOMMENT        "error while parsing comment"
       
    75 #define XMLERR_ERRORPARSINGENTITYVALUE    "error while parsing entity value declaration"
       
    76 #define XMLERR_CDSECTHEADEREXPECTED       "expected the header for a cdata section"
       
    77 #define XMLERR_MORETHANONEDOCTYPE         "more than one document type definition"
       
    78 #define XMLERR_ERRORPARSINGDOCTYPE        "error while parsing document type definition"
       
    79 #define XMLERR_INVALIDNAMEFORPI           "invalid name for processing instruction"
       
    80 #define XMLERR_VERSIONEXPECTED            "version expected while reading the XML declaration"
       
    81 #define XMLERR_EDECLORSDDECLEXPECTED      "EDecl or SDDecl expected while reading the XML declaration"
       
    82 #define XMLERR_SDDECLEXPECTED             "SDDecl expected while reading the XML declaration"
       
    83 #define XMLERR_WRONGVALUEFORSDECL         "wrong value for standalone declaration"
       
    84 #define XMLERR_UNPARSEDENTITYREFERENCE    "unparsed entity reference in wrong context"
       
    85 #define XMLERR_INTERNALGENERALENTITYINDTD "internal general entity reference not allowed in DTD"
       
    86 #define XMLERR_EXTERNALGENERALENTITYINDTD "external parsed general entity reference not allowed in DTD"
       
    87 #define XMLERR_EXTERNALGENERALENTITYINAV  "external parsed general entity reference not allowed in attribute value"
       
    88 
       
    89 
       
    90 // the constants for the lookup table
       
    91 static const signed char cltWS      =  0; // white space
       
    92 static const signed char cltPer     =  1; // %
       
    93 static const signed char cltAmp     =  2; // &
       
    94 static const signed char cltGt      =  3; // >
       
    95 static const signed char cltLt      =  4; // <
       
    96 static const signed char cltSlash   =  5; // /
       
    97 static const signed char cltQm      =  6; // ?
       
    98 static const signed char cltEm      =  7; // !
       
    99 static const signed char cltDash    =  8; // -
       
   100 static const signed char cltCB      =  9; // ]
       
   101 static const signed char cltOB      = 10; // [
       
   102 static const signed char cltEq      = 11; // =
       
   103 static const signed char cltDq      = 12; // "
       
   104 static const signed char cltSq      = 13; // '
       
   105 static const signed char cltUnknown = 14;
       
   106 
       
   107 // character lookup table
       
   108 static const signed char charLookupTable[256]={
       
   109     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x00 - 0x07
       
   110     cltUnknown, // 0x08
       
   111     cltWS,      // 0x09 \t
       
   112     cltWS,      // 0x0A \n
       
   113     cltUnknown, // 0x0B
       
   114     cltUnknown, // 0x0C
       
   115     cltWS,      // 0x0D \r
       
   116     cltUnknown, // 0x0E
       
   117     cltUnknown, // 0x0F
       
   118     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x17 - 0x16
       
   119     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x18 - 0x1F
       
   120     cltWS,      // 0x20 Space
       
   121     cltEm,      // 0x21 !
       
   122     cltDq,      // 0x22 "
       
   123     cltUnknown, // 0x23
       
   124     cltUnknown, // 0x24
       
   125     cltPer,     // 0x25 %
       
   126     cltAmp,     // 0x26 &
       
   127     cltSq,      // 0x27 '
       
   128     cltUnknown, // 0x28
       
   129     cltUnknown, // 0x29
       
   130     cltUnknown, // 0x2A
       
   131     cltUnknown, // 0x2B
       
   132     cltUnknown, // 0x2C
       
   133     cltDash,    // 0x2D -
       
   134     cltUnknown, // 0x2E
       
   135     cltSlash,   // 0x2F /
       
   136     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x30 - 0x37
       
   137     cltUnknown, // 0x38
       
   138     cltUnknown, // 0x39
       
   139     cltUnknown, // 0x3A
       
   140     cltUnknown, // 0x3B
       
   141     cltLt,      // 0x3C <
       
   142     cltEq,      // 0x3D =
       
   143     cltGt,      // 0x3E >
       
   144     cltQm,      // 0x3F ?
       
   145     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x40 - 0x47
       
   146     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x48 - 0x4F
       
   147     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x50 - 0x57
       
   148     cltUnknown, // 0x58
       
   149     cltUnknown, // 0x59
       
   150     cltUnknown, // 0x5A
       
   151     cltOB,      // 0x5B [
       
   152     cltUnknown, // 0x5C
       
   153     cltCB,      // 0x5D ]
       
   154     cltUnknown, // 0x5E
       
   155     cltUnknown, // 0x5F
       
   156     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x60 - 0x67
       
   157     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x68 - 0x6F
       
   158     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x70 - 0x77
       
   159     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x78 - 0x7F
       
   160     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x80 - 0x87
       
   161     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x88 - 0x8F
       
   162     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x90 - 0x97
       
   163     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x98 - 0x9F
       
   164     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA0 - 0xA7
       
   165     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA8 - 0xAF
       
   166     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB0 - 0xB7
       
   167     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB8 - 0xBF
       
   168     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC0 - 0xC7
       
   169     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC8 - 0xCF
       
   170     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD0 - 0xD7
       
   171     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD8 - 0xDF
       
   172     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE0 - 0xE7
       
   173     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE8 - 0xEF
       
   174     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xF0 - 0xF7
       
   175     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown  // 0xF8 - 0xFF
       
   176 };
       
   177 
       
   178 
       
   179 class QXmlNamespaceSupportPrivate
       
   180 {
       
   181 };
       
   182 class QXmlAttributesPrivate
       
   183 {
       
   184 };
       
   185 class QXmlInputSourcePrivate
       
   186 {
       
   187 };
       
   188 class QXmlParseExceptionPrivate
       
   189 {
       
   190 };
       
   191 class QXmlLocatorPrivate
       
   192 {
       
   193 };
       
   194 class QXmlDefaultHandlerPrivate
       
   195 {
       
   196 };
       
   197 
       
   198 #if defined(Q_FULL_TEMPLATE_INSTANTIATION)
       
   199 bool operator==( const QMap<QString, QString>, const QMap<QString, QString> )
       
   200 {
       
   201     return FALSE;
       
   202 }
       
   203 #endif
       
   204 
       
   205 /*!
       
   206   \class QXmlParseException qxml.h
       
   207   \brief The QXmlParseException class is used to report errors with the
       
   208   QXmlErrorHandler interface.
       
   209 
       
   210   \module XML
       
   211 
       
   212   \sa QXmlErrorHandler
       
   213 */
       
   214 /*!
       
   215   \fn QXmlParseException::QXmlParseException( const QString& name, int c, int l, const QString& p, const QString& s )
       
   216 
       
   217   Constructs a parse exception with the error string \a name in the column
       
   218   \a c and line \a l for the public identifier \a p and the system identifier
       
   219   \a s.
       
   220 */
       
   221 /*!
       
   222   Returns the error message.
       
   223 */
       
   224 QString QXmlParseException::message() const
       
   225 {
       
   226     return msg;
       
   227 }
       
   228 /*!
       
   229   Returns the column number the error occured.
       
   230 */
       
   231 int QXmlParseException::columnNumber() const
       
   232 {
       
   233     return column;
       
   234 }
       
   235 /*!
       
   236   Returns the line number the error occured.
       
   237 */
       
   238 int QXmlParseException::lineNumber() const
       
   239 {
       
   240     return line;
       
   241 }
       
   242 /*!
       
   243   Returns the public identifier the error occured.
       
   244 */
       
   245 QString QXmlParseException::publicId() const
       
   246 {
       
   247     return pub;
       
   248 }
       
   249 /*!
       
   250   Returns the system identifier the error occured.
       
   251 */
       
   252 QString QXmlParseException::systemId() const
       
   253 {
       
   254     return sys;
       
   255 }
       
   256 
       
   257 
       
   258 /*!
       
   259   \class QXmlLocator qxml.h
       
   260   \brief The QXmlLocator class provides the XML handler classes with
       
   261   information about the actual parsing position.
       
   262 
       
   263   \module XML
       
   264 
       
   265   The reader reports a QXmlLocator to the content handler before he starts to
       
   266   parse the document. This is done with the
       
   267   QXmlContentHandler::setDocumentLocator() function. The handler classes can
       
   268   now use this locator to get the actual position the reader is at.
       
   269 */
       
   270 /*!
       
   271     \fn QXmlLocator::QXmlLocator( QXmlSimpleReader* parent )
       
   272 
       
   273     Constructor.
       
   274 */
       
   275 /*!
       
   276     \fn QXmlLocator::~QXmlLocator()
       
   277 
       
   278     Destructor.
       
   279 */
       
   280 /*!
       
   281     Gets the column number (starting with 1) or -1 if there is no column number
       
   282     available.
       
   283 */
       
   284 int QXmlLocator::columnNumber()
       
   285 {
       
   286     return ( reader->columnNr == -1 ? -1 : reader->columnNr + 1 );
       
   287 }
       
   288 /*!
       
   289     Gets the line number (starting with 1) or -1 if there is no line number
       
   290     available.
       
   291 */
       
   292 int QXmlLocator::lineNumber()
       
   293 {
       
   294     return ( reader->lineNr == -1 ? -1 : reader->lineNr + 1 );
       
   295 }
       
   296 
       
   297 
       
   298 /*********************************************
       
   299  *
       
   300  * QXmlNamespaceSupport
       
   301  *
       
   302  *********************************************/
       
   303 
       
   304 /*!
       
   305   \class QXmlNamespaceSupport qxml.h
       
   306   \brief The QXmlNamespaceSupport class is a helper class for XML readers which
       
   307   want to include namespace support.
       
   308 
       
   309   \module XML
       
   310 
       
   311   It provides some functions that makes it easy to handle namespaces. Its main
       
   312   use is for subclasses of QXmlReader which want to provide namespace
       
   313   support.
       
   314 
       
   315   See also the <a href="xml-sax.html#namespaces">namespace description</a>.
       
   316 */
       
   317 
       
   318 /*!
       
   319   Constructs a QXmlNamespaceSupport.
       
   320 */
       
   321 QXmlNamespaceSupport::QXmlNamespaceSupport()
       
   322 {
       
   323     reset();
       
   324 }
       
   325 
       
   326 /*!
       
   327   Destructs a QXmlNamespaceSupport.
       
   328 */
       
   329 QXmlNamespaceSupport::~QXmlNamespaceSupport()
       
   330 {
       
   331 }
       
   332 
       
   333 /*!
       
   334   This function declares a prefix in the current namespace context; the prefix
       
   335   will remain in force until this context is popped, unless it is shadowed in a
       
   336   descendant context.
       
   337 
       
   338   Note that there is an asymmetry in this library: while prefix() will not
       
   339   return the default "" prefix, even if you have declared one; to check for a
       
   340   default prefix, you have to look it up explicitly using uri(). This
       
   341   asymmetry exists to make it easier to look up prefixes for attribute names,
       
   342   where the default prefix is not allowed.
       
   343 */
       
   344 void QXmlNamespaceSupport::setPrefix( const QString& pre, const QString& uri )
       
   345 {
       
   346     if( pre.isNull() ) {
       
   347 	ns.insert( "", uri );
       
   348     } else {
       
   349 	ns.insert( pre, uri );
       
   350     }
       
   351 }
       
   352 
       
   353 /*!
       
   354   Returns one of the prefixes mapped to a namespace URI.
       
   355 
       
   356   If more than one prefix is currently mapped to the same URI, this function
       
   357   will make an arbitrary selection; if you want all of the prefixes, use the
       
   358   prefixes() function instead.
       
   359 
       
   360   Note: this will never return the empty (default) prefix; to check for a
       
   361   default prefix, use the uri() function with an argument of "".
       
   362 */
       
   363 QString QXmlNamespaceSupport::prefix( const QString& uri ) const
       
   364 {
       
   365     QMap<QString, QString>::ConstIterator itc, it = ns.begin();
       
   366     while ( (itc=it) != ns.end() ) {
       
   367 	++it;
       
   368 	if ( itc.data() == uri && !itc.key().isEmpty() )
       
   369 	    return itc.key();
       
   370     }
       
   371     return "";
       
   372 }
       
   373 
       
   374 /*!
       
   375   Looks up a prefix in the current context and returns the currently-mapped
       
   376   namespace URI. Use the empty string ("") for the default namespace.
       
   377 */
       
   378 QString QXmlNamespaceSupport::uri( const QString& prefix ) const
       
   379 {
       
   380     const QString& returi = ns[ prefix ];
       
   381     return returi;
       
   382 }
       
   383 
       
   384 /*!
       
   385   Splits the name at the ':' and returns the prefix and the local name.
       
   386 */
       
   387 void QXmlNamespaceSupport::splitName( const QString& qname,
       
   388 	QString& prefix, QString& localname ) const
       
   389 {
       
   390     uint pos;
       
   391     // search the ':'
       
   392     for( pos=0; pos<qname.length(); pos++ ) {
       
   393 	if ( qname.at(pos) == ':' )
       
   394 	    break;
       
   395     }
       
   396     // and split
       
   397     prefix = qname.left( pos );
       
   398     localname = qname.mid( pos+1 );
       
   399 }
       
   400 
       
   401 /*!
       
   402   Processes a raw XML 1.0 name in the current context by removing the prefix
       
   403   and looking it up among the prefixes currently declared.
       
   404 
       
   405   First parameter is the raw XML 1.0 name to be processed. The second parameter
       
   406   is a flag wheter the name is the name of an attribute (TRUE) or not (FALSE).
       
   407 
       
   408   The return values will be stored in the last two parameters as follows:
       
   409   <ul>
       
   410   <li> The namespace URI, or an empty string if none is in use.
       
   411   <li> The local name (without prefix).
       
   412   </ul>
       
   413 
       
   414   If the raw name has a prefix that has not been declared, then the return
       
   415   value will be empty.
       
   416 
       
   417   Note that attribute names are processed differently than element names: an
       
   418   unprefixed element name will received the default namespace (if any), while
       
   419   an unprefixed element name will not
       
   420 */
       
   421 void QXmlNamespaceSupport::processName( const QString& qname,
       
   422 	bool isAttribute,
       
   423 	QString& nsuri, QString& localname ) const
       
   424 {
       
   425     uint pos;
       
   426     // search the ':'
       
   427     for( pos=0; pos<qname.length(); pos++ ) {
       
   428 	if ( qname.at(pos) == ':' )
       
   429 	    break;
       
   430     }
       
   431     if ( pos < qname.length() ) {
       
   432 	// there was a ':'
       
   433 	nsuri = uri( qname.left( pos ) );
       
   434 	localname = qname.mid( pos+1 );
       
   435     } else {
       
   436 	// there was no ':'
       
   437 	if ( isAttribute ) {
       
   438 	    nsuri = ""; // attributes don't take default namespace
       
   439 	} else {
       
   440 	    nsuri = uri( "" ); // get default namespace
       
   441 	}
       
   442 	localname = qname;
       
   443     }
       
   444 }
       
   445 
       
   446 /*!
       
   447   Returns an enumeration of all prefixes currently declared.
       
   448 
       
   449   Note: if there is a default prefix, it will not be returned in this
       
   450   enumeration; check for the default prefix using uri() with an argument
       
   451   of "".
       
   452 */
       
   453 QStringList QXmlNamespaceSupport::prefixes() const
       
   454 {
       
   455     QStringList list;
       
   456 
       
   457     QMap<QString, QString>::ConstIterator itc, it = ns.begin();
       
   458     while ( (itc=it) != ns.end() ) {
       
   459 	++it;
       
   460 	if ( !itc.key().isEmpty() )
       
   461 	    list.append( itc.key() );
       
   462     }
       
   463     return list;
       
   464 }
       
   465 
       
   466 /*!
       
   467   Returns a list of all prefixes currently declared for a URI.
       
   468 
       
   469   The xml: prefix will be included. If you want only one prefix that's
       
   470   mapped to the namespace URI, and you don't care which one you get, use the
       
   471   prefix() function instead.
       
   472 
       
   473   Note: the empty (default) prefix is never included in this enumeration; to
       
   474   check for the presence of a default namespace, use uri() with an
       
   475   argument of "".
       
   476 */
       
   477 QStringList QXmlNamespaceSupport::prefixes( const QString& uri ) const
       
   478 {
       
   479     QStringList list;
       
   480 
       
   481     QMap<QString, QString>::ConstIterator itc, it = ns.begin();
       
   482     while ( (itc=it) != ns.end() ) {
       
   483 	++it;
       
   484 	if ( itc.data() == uri && !itc.key().isEmpty() )
       
   485 	    list.append( itc.key() );
       
   486     }
       
   487     return list;
       
   488 }
       
   489 
       
   490 /*!
       
   491   Starts a new namespace context.
       
   492 
       
   493   Normally, you should push a new context at the beginning of each XML element:
       
   494   the new context will automatically inherit the declarations of its parent
       
   495   context, but it will also keep track of which declarations were made within
       
   496   this context.
       
   497 */
       
   498 void QXmlNamespaceSupport::pushContext()
       
   499 {
       
   500     nsStack.push( ns );
       
   501 }
       
   502 
       
   503 /*!
       
   504   Reverts to the previous namespace context.
       
   505 
       
   506   Normally, you should pop the context at the end of each XML element.  After
       
   507   popping the context, all namespace prefix mappings that were previously in
       
   508   force are restored.
       
   509 */
       
   510 void QXmlNamespaceSupport::popContext()
       
   511 {
       
   512     if( !nsStack.isEmpty() )
       
   513 	ns = nsStack.pop();
       
   514 }
       
   515 
       
   516 /*!
       
   517   Resets this namespace support object for reuse.
       
   518 */
       
   519 void QXmlNamespaceSupport::reset()
       
   520 {
       
   521     nsStack.clear();
       
   522     ns.clear();
       
   523     ns.insert( "xml", "http://www.w3.org/XML/1998/namespace" ); // the XML namespace
       
   524 }
       
   525 
       
   526 
       
   527 
       
   528 /*********************************************
       
   529  *
       
   530  * QXmlAttributes
       
   531  *
       
   532  *********************************************/
       
   533 
       
   534 /*!
       
   535   \class QXmlAttributes qxml.h
       
   536   \brief The QXmlAttributes class provides XML attributes.
       
   537 
       
   538   \module XML
       
   539 
       
   540   If attributes are reported by QXmlContentHandler::startElement() this
       
   541   class is used to pass the attribute values. It provides you with different
       
   542   functions to access the attribute names and values.
       
   543 */
       
   544 /*!
       
   545   \fn QXmlAttributes::QXmlAttributes()
       
   546 
       
   547   Constructs an empty attribute list.
       
   548 */
       
   549 /*!
       
   550   \fn QXmlAttributes::~QXmlAttributes()
       
   551 
       
   552   Destructs attributes.
       
   553 */
       
   554 
       
   555 /*!
       
   556   Look up the index of an attribute by an XML 1.0 qualified name.
       
   557 
       
   558   Returns the index of the attribute (starting with 0) or -1 if it wasn't
       
   559   found.
       
   560 
       
   561   See also the <a href="xml-sax.html#namespaces">namespace description</a>.
       
   562 */
       
   563 int QXmlAttributes::index( const QString& qName ) const
       
   564 {
       
   565     return qnameList.findIndex( qName );
       
   566 }
       
   567 
       
   568 /*!
       
   569   Looks up the index of an attribute by a namespace name.
       
   570 
       
   571   \a uri specifies the namespace URI, or the empty string if the name has no
       
   572   namespace URI. \a localPart specifies the attribute's local name.
       
   573 
       
   574   Returns the index of the attribute (starting with 0) or -1 if it wasn't
       
   575   found.
       
   576 
       
   577   See also the <a href="xml-sax.html#namespaces">namespace description</a>.
       
   578 */
       
   579 int QXmlAttributes::index( const QString& uri, const QString& localPart ) const
       
   580 {
       
   581     uint count = uriList.count();
       
   582     for ( uint i=0; i<count; i++ ) {
       
   583 	if ( uriList[i] == uri && localnameList[i] == localPart )
       
   584 	    return i;
       
   585     }
       
   586     return -1;
       
   587 }
       
   588 
       
   589 /*!
       
   590   Returns the number of attributes in the list.
       
   591 */
       
   592 int QXmlAttributes::length() const
       
   593 {
       
   594     return valueList.count();
       
   595 }
       
   596 
       
   597 /*!
       
   598   Looks up an attribute's local name by index (starting with 0).
       
   599 
       
   600   See also the <a href="xml-sax.html#namespaces">namespace description</a>.
       
   601 */
       
   602 QString QXmlAttributes::localName( int index ) const
       
   603 {
       
   604     return localnameList[index];
       
   605 }
       
   606 
       
   607 /*!
       
   608   Looks up an attribute's XML 1.0 qualified name by index (starting with 0).
       
   609 
       
   610   See also the <a href="xml-sax.html#namespaces">namespace description</a>.
       
   611 */
       
   612 QString QXmlAttributes::qName( int index ) const
       
   613 {
       
   614     return qnameList[index];
       
   615 }
       
   616 
       
   617 /*!
       
   618   Looks up an attribute's namespace URI by index (starting with 0).
       
   619 
       
   620   See also the <a href="xml-sax.html#namespaces">namespace description</a>.
       
   621 */
       
   622 QString QXmlAttributes::uri( int index ) const
       
   623 {
       
   624     return uriList[index];
       
   625 }
       
   626 
       
   627 /*!
       
   628   Looks up an attribute's type by index (starting with 0).
       
   629 
       
   630   At the moment only 'CDATA' is returned.
       
   631 */
       
   632 QString QXmlAttributes::type( int ) const
       
   633 {
       
   634     return "CDATA";
       
   635 }
       
   636 
       
   637 /*!
       
   638   Looks up an attribute's type by XML 1.0 qualified name.
       
   639 
       
   640   At the moment only 'CDATA' is returned.
       
   641 */
       
   642 QString QXmlAttributes::type( const QString& ) const
       
   643 {
       
   644     return "CDATA";
       
   645 }
       
   646 
       
   647 /*!
       
   648   Looks up an attribute's type by namespace name.
       
   649 
       
   650   The first parameter specifies the namespace URI, or the empty string if
       
   651   the name has no namespace URI. The second parameter specifies the
       
   652   attribute's local name.
       
   653 
       
   654   At the moment only 'CDATA' is returned.
       
   655 */
       
   656 QString QXmlAttributes::type( const QString&, const QString& ) const
       
   657 {
       
   658     return "CDATA";
       
   659 }
       
   660 
       
   661 /*!
       
   662   Looks up an attribute's value by index (starting with 0).
       
   663 */
       
   664 QString QXmlAttributes::value( int index ) const
       
   665 {
       
   666     return valueList[index];
       
   667 }
       
   668 
       
   669 /*!
       
   670   Looks up an attribute's value by XML 1.0 qualified name.
       
   671 
       
   672   See also the <a href="xml-sax.html#namespaces">namespace description</a>.
       
   673 */
       
   674 QString QXmlAttributes::value( const QString& qName ) const
       
   675 {
       
   676     int i = index( qName );
       
   677     if ( i == -1 )
       
   678 	return QString::null;
       
   679     return valueList[ i ];
       
   680 }
       
   681 
       
   682 /*!
       
   683   Looks up an attribute's value by namespace name.
       
   684 
       
   685   \a uri specifies the namespace URI, or the empty string if the name has no
       
   686   namespace URI. \a localName specifies the attribute's local name.
       
   687 
       
   688   See also the <a href="xml-sax.html#namespaces">namespace description</a>.
       
   689 */
       
   690 QString QXmlAttributes::value( const QString& uri, const QString& localName ) const
       
   691 {
       
   692     int i = index( uri, localName );
       
   693     if ( i == -1 )
       
   694 	return QString::null;
       
   695     return valueList[ i ];
       
   696 }
       
   697 
       
   698 
       
   699 /*********************************************
       
   700  *
       
   701  * QXmlInputSource
       
   702  *
       
   703  *********************************************/
       
   704 
       
   705 /*!
       
   706   \class QXmlInputSource qxml.h
       
   707   \brief The QXmlInputSource class is the source where XML data is read from.
       
   708 
       
   709   \module XML
       
   710 
       
   711   All subclasses of QXmlReader read the input from this class.
       
   712 */
       
   713 
       
   714 /*!
       
   715   Returns all the data this input source contains.
       
   716 */
       
   717 const QString& QXmlInputSource::data() const
       
   718 {
       
   719     return input;
       
   720 }
       
   721 
       
   722 /*!
       
   723   Constructs a input source which contains no data.
       
   724 */
       
   725 QXmlInputSource::QXmlInputSource( )
       
   726 {
       
   727     input = "";
       
   728 }
       
   729 
       
   730 /*!
       
   731   Constructs a input source and get the data from the text stream.
       
   732 */
       
   733 QXmlInputSource::QXmlInputSource( QTextStream& stream )
       
   734 {
       
   735     QByteArray rawData;
       
   736     if ( stream.device()->isDirectAccess() ) {
       
   737 	rawData = stream.device()->readAll();
       
   738     } else {
       
   739 	int nread = 0;
       
   740 	const int bufsize = 512;
       
   741 	while ( !stream.device()->atEnd() ) {
       
   742 	    rawData.resize( nread + bufsize );
       
   743 	    nread += stream.device()->readBlock( rawData.data()+nread, bufsize );
       
   744 	}
       
   745 	rawData.resize( nread );
       
   746     }
       
   747     readInput( rawData );
       
   748 }
       
   749 
       
   750 /*!
       
   751   Constructs a input source and get the data from a file. If the file cannot be
       
   752   read the input source is empty.
       
   753 */
       
   754 QXmlInputSource::QXmlInputSource( QFile& file )
       
   755 {
       
   756     if ( !file.open(IO_ReadOnly) ) {
       
   757 	input = "";
       
   758 	return;
       
   759     }
       
   760     QByteArray rawData = file.readAll();
       
   761     readInput( rawData );
       
   762     file.close();
       
   763 }
       
   764 
       
   765 /*!
       
   766   Destructor.
       
   767 */
       
   768 QXmlInputSource::~QXmlInputSource()
       
   769 {
       
   770 }
       
   771 
       
   772 /*!
       
   773   Sets the data of the input source to \a dat.
       
   774 */
       
   775 void QXmlInputSource::setData( const QString& dat )
       
   776 {
       
   777     input = dat;
       
   778 }
       
   779 
       
   780 /*!
       
   781   Read the XML file from the byte array; try to recoginize the encoding.
       
   782 */
       
   783 // ### The input source should not do the encoding detection!
       
   784 void QXmlInputSource::readInput( QByteArray& rawData )
       
   785 {
       
   786     QBuffer buf( rawData );
       
   787     buf.open( IO_ReadOnly );
       
   788     QTextStream *stream = new QTextStream( &buf );
       
   789     QChar tmp;
       
   790     // assume UTF8 or UTF16 at first
       
   791     stream->setEncoding( QTextStream::UnicodeUTF8 );
       
   792     input = "";
       
   793     // read the first 5 characters
       
   794     for ( int i=0; i<5; i++ ) {
       
   795 	*stream >> tmp;
       
   796 	input += tmp;
       
   797     }
       
   798     // starts the document with an XML declaration?
       
   799     if ( input == "<?xml" ) {
       
   800 	// read the whole XML declaration
       
   801 	do {
       
   802 	    *stream >> tmp;
       
   803 	    input += tmp;
       
   804 	} while( tmp != '>' );
       
   805 	// and try to find out if there is an encoding
       
   806 	int pos = input.find( "encoding" );
       
   807 	if ( pos != -1 ) {
       
   808 	    QString encoding;
       
   809 	    do {
       
   810 		pos++;
       
   811 		if ( pos > (int)input.length() )
       
   812 		    goto finished;
       
   813 	    } while( input[pos] != '"' && input[pos] != '\'' );
       
   814 	    pos++;
       
   815 	    while( input[pos] != '"' && input[pos] != '\'' ) {
       
   816 		encoding += input[pos];
       
   817 		pos++;
       
   818 		if ( pos > (int)input.length() )
       
   819 		    goto finished;
       
   820 	    }
       
   821 	    delete stream;
       
   822 	    stream = new QTextStream( &buf );
       
   823 	    stream->setCodec( QTextCodec::codecForName( encoding ) );
       
   824 	    buf.reset();
       
   825 	    input = "";
       
   826 	}
       
   827     }
       
   828 finished:
       
   829     input += stream->read();
       
   830     delete stream;
       
   831     buf.close();
       
   832 }
       
   833 
       
   834 
       
   835 /*********************************************
       
   836  *
       
   837  * QXmlDefaultHandler
       
   838  *
       
   839  *********************************************/
       
   840 
       
   841 /*!
       
   842   \class QXmlContentHandler qxml.h
       
   843   \brief The QXmlContentHandler class provides an interface to report logical
       
   844   content of XML data.
       
   845 
       
   846   \module XML
       
   847 
       
   848   If the application needs to be informed of basic parsing events, it
       
   849   implements this interface and sets it with QXmlReader::setContentHandler().
       
   850   The reader reports basic document-related events like the start and end of
       
   851   elements and character data through this interface.
       
   852 
       
   853   The order of events in this interface is very important, and mirrors the
       
   854   order of information in the document itself. For example, all of an element's
       
   855   content (character data, processing instructions, and/or subelements) will
       
   856   appear, in order, between the startElement() event and the corresponding
       
   857   endElement() event.
       
   858 
       
   859   The class QXmlDefaultHandler gives a default implementation for this
       
   860   interface; subclassing from this class is very convenient if you want only be
       
   861   informed of some parsing events.
       
   862 
       
   863   See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>.
       
   864 
       
   865   \sa QXmlDTDHandler QXmlDeclHandler QXmlEntityResolver QXmlErrorHandler
       
   866   QXmlLexicalHandler
       
   867 */
       
   868 /*!
       
   869   \fn void QXmlContentHandler::setDocumentLocator( QXmlLocator* locator )
       
   870 
       
   871   The reader calls this function before he starts parsing the document. The
       
   872   argument \a locator is a pointer to a QXmlLocator which allows the
       
   873   application to get the actual position of the parsing in the document.
       
   874 
       
   875   Do not destroy the \a locator; it is destroyed when the reader is destroyed
       
   876   (do not use the \a locator after the reader got destroyed).
       
   877 */
       
   878 /*!
       
   879   \fn bool QXmlContentHandler::startDocument()
       
   880 
       
   881   The reader calls this function when he starts parsing the document.
       
   882   The reader will call this function only once before any other functions in
       
   883   this class or in the QXmlDTDHandler class are called (except
       
   884   QXmlContentHandler::setDocumentLocator()).
       
   885 
       
   886   If this function returns FALSE the reader will stop parsing and will report
       
   887   an error. The reader will use the function errorString() to get the error
       
   888   message that will be used for reporting the error.
       
   889 
       
   890   \sa endDocument()
       
   891 */
       
   892 /*!
       
   893   \fn bool QXmlContentHandler::endDocument()
       
   894 
       
   895   The reader calls this function after he has finished the parsing. It
       
   896   is only called once. It is the last function of all handler functions that is
       
   897   called. It is called after the reader has read all input or has abandoned
       
   898   parsing because of a fatal error.
       
   899 
       
   900   If this function returns FALSE the reader will stop parsing and will report
       
   901   an error. The reader will use the function errorString() to get the error
       
   902   message that will be used for reporting the error.
       
   903 
       
   904   \sa startDocument()
       
   905 */
       
   906 /*!
       
   907   \fn bool QXmlContentHandler::startPrefixMapping( const QString& prefix, const QString& uri )
       
   908 
       
   909   The reader calls this function to signal the begin of a prefix-URI
       
   910   namespace mapping scope. This information is not necessary for normal
       
   911   namespace processing since the reader automatically replaces prefixes for
       
   912   element and attribute names.
       
   913 
       
   914   Note that startPrefixMapping and endPrefixMapping calls are not guaranteed to
       
   915   be properly nested relative to each-other: all startPrefixMapping events will
       
   916   occur before the corresponding startElement event, and all endPrefixMapping
       
   917   events will occur after the corresponding endElement event, but their order
       
   918   is not otherwise guaranteed.
       
   919 
       
   920   The argument \a prefix is the namespace prefix being declared and the
       
   921   argument \a uri is the namespace URI the prefix is mapped to.
       
   922 
       
   923   If this function returns FALSE the reader will stop parsing and will report
       
   924   an error. The reader will use the function errorString() to get the error
       
   925   message that will be used for reporting the error.
       
   926 
       
   927   See also the <a href="xml-sax.html#namespaces">namespace description</a>.
       
   928 
       
   929   \sa endPrefixMapping()
       
   930 */
       
   931 /*!
       
   932   \fn bool QXmlContentHandler::endPrefixMapping( const QString& prefix )
       
   933 
       
   934   The reader calls this function to signal the end of a prefix mapping.
       
   935 
       
   936   If this function returns FALSE the reader will stop parsing and will report
       
   937   an error. The reader will use the function errorString() to get the error
       
   938   message that will be used for reporting the error.
       
   939 
       
   940   See also the <a href="xml-sax.html#namespaces">namespace description</a>.
       
   941 
       
   942   \sa startPrefixMapping()
       
   943 */
       
   944 /*!
       
   945   \fn bool QXmlContentHandler::startElement( const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts )
       
   946 
       
   947   The reader calls this function when he has parsed a start element tag.
       
   948 
       
   949   There will be a corresponding endElement() call when the corresponding end
       
   950   element tag was read. The startElement() and endElement() calls are always
       
   951   nested correctly. Empty element tags (e.g. &lt;a/&gt;) are reported by
       
   952   startElement() directly followed by a call to endElement().
       
   953 
       
   954   The attribute list provided will contain only attributes with explicit
       
   955   values. The attribute list will contain attributes used for namespace
       
   956   declaration (i.e. attributes starting with xmlns) only if the
       
   957   namespace-prefix property of the reader is TRUE.
       
   958 
       
   959   The argument \a uri is the namespace URI, or the empty string if the element
       
   960   has no namespace URI or if namespace processing is not being performed, \a
       
   961   localName is the local name (without prefix), or the empty string if
       
   962   namespace processing is not being performed, \a qName is the qualified name
       
   963   (with prefix), or the empty string if qualified names are not available and
       
   964   \a atts are the attributes attached to the element. If there are no
       
   965   attributes, \a atts is an empty attributes object
       
   966 
       
   967   If this function returns FALSE the reader will stop parsing and will report
       
   968   an error. The reader will use the function errorString() to get the error
       
   969   message that will be used for reporting the error.
       
   970 
       
   971   See also the <a href="xml-sax.html#namespaces">namespace description</a>.
       
   972 
       
   973   \sa endElement()
       
   974 */
       
   975 /*!
       
   976   \fn bool QXmlContentHandler::endElement( const QString& namespaceURI, const QString& localName, const QString& qName )
       
   977 
       
   978   The reader calls this function when he has parsed an end element tag.
       
   979 
       
   980   If this function returns FALSE the reader will stop parsing and will report
       
   981   an error. The reader will use the function errorString() to get the error
       
   982   message that will be used for reporting the error.
       
   983 
       
   984   See also the <a href="xml-sax.html#namespaces">namespace description</a>.
       
   985 
       
   986   \sa startElement()
       
   987 */
       
   988 /*!
       
   989   \fn bool QXmlContentHandler::characters( const QString& ch )
       
   990 
       
   991   The reader calls this function when he has parsed a chunk of character
       
   992   data (either normal character data or character data inside a CDATA section;
       
   993   if you have to distinguish between those two types you have to use
       
   994   QXmlLexicalHandler::startCDATA() and QXmlLexicalHandler::endCDATA() in
       
   995   addition).
       
   996 
       
   997   Some readers will report whitespace in element content using the
       
   998   ignorableWhitespace() function rather than this one (QXmlSimpleReader will
       
   999   do it not though).
       
  1000 
       
  1001   A reader is allowed to report the character data of an element in more than
       
  1002   one chunk; e.g. a reader might want to report "a &amp;lt; b" in three
       
  1003   characters() events ("a ", "<" and " b").
       
  1004 
       
  1005   If this function returns FALSE the reader will stop parsing and will report
       
  1006   an error. The reader will use the function errorString() to get the error
       
  1007   message that will be used for reporting the error.
       
  1008 */
       
  1009 /*!
       
  1010   \fn bool QXmlContentHandler::ignorableWhitespace( const QString& ch )
       
  1011 
       
  1012   Some readers may use this function to report each chunk of whitespace in
       
  1013   element content (QXmlSimpleReader does not though).
       
  1014 
       
  1015   If this function returns FALSE the reader will stop parsing and will report
       
  1016   an error. The reader will use the function errorString() to get the error
       
  1017   message that will be used for reporting the error.
       
  1018 */
       
  1019 /*!
       
  1020   \fn bool QXmlContentHandler::processingInstruction( const QString& target, const QString& data )
       
  1021 
       
  1022   The reader calls this function when he has parsed a processing
       
  1023   instruction.
       
  1024 
       
  1025   \a target is the target name of the processing instruction and \a data is the
       
  1026   data of the processing instruction.
       
  1027 
       
  1028   If this function returns FALSE the reader will stop parsing and will report
       
  1029   an error. The reader will use the function errorString() to get the error
       
  1030   message that will be used for reporting the error.
       
  1031 */
       
  1032 /*!
       
  1033   \fn bool QXmlContentHandler::skippedEntity( const QString& name )
       
  1034 
       
  1035   Some readers may skip entities if they have not seen the declarations (e.g.
       
  1036   because they are in an external DTD). If they do so they will report it by
       
  1037   calling this function.
       
  1038 
       
  1039   If this function returns FALSE the reader will stop parsing and will report
       
  1040   an error. The reader will use the function errorString() to get the error
       
  1041   message that will be used for reporting the error.
       
  1042 */
       
  1043 /*!
       
  1044   \fn QString QXmlContentHandler::errorString()
       
  1045 
       
  1046   The reader calls this function to get an error string if any of the handler
       
  1047   functions returns FALSE to him.
       
  1048 */
       
  1049 
       
  1050 
       
  1051 /*!
       
  1052   \class QXmlErrorHandler qxml.h
       
  1053   \brief The QXmlErrorHandler class provides an interface to report errors in
       
  1054   XML data.
       
  1055 
       
  1056   \module XML
       
  1057 
       
  1058   If the application is interested in reporting errors to the user or any other
       
  1059   customized error handling, you should subclass this class.
       
  1060 
       
  1061   You can set the error handler with QXmlReader::setErrorHandler().
       
  1062 
       
  1063   See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>.
       
  1064 
       
  1065   \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver
       
  1066   QXmlLexicalHandler
       
  1067 */
       
  1068 /*!
       
  1069   \fn bool QXmlErrorHandler::warning( const QXmlParseException& exception )
       
  1070 
       
  1071   A reader might use this function to report a warning. Warnings are conditions
       
  1072   that are not errors or fatal errors as defined by the XML 1.0 specification.
       
  1073 
       
  1074   If this function returns FALSE the reader will stop parsing and will report
       
  1075   an error. The reader will use the function errorString() to get the error
       
  1076   message that will be used for reporting the error.
       
  1077 */
       
  1078 /*!
       
  1079   \fn bool QXmlErrorHandler::error( const QXmlParseException& exception )
       
  1080 
       
  1081   A reader might use this function to report a recoverable error. A recoverable
       
  1082   error corresponds to the definiton of "error" in section 1.2 of the XML 1.0
       
  1083   specification.
       
  1084 
       
  1085   The reader must continue to provide normal parsing events after invoking this
       
  1086   function.
       
  1087 
       
  1088   If this function returns FALSE the reader will stop parsing and will report
       
  1089   an error. The reader will use the function errorString() to get the error
       
  1090   message that will be used for reporting the error.
       
  1091 */
       
  1092 /*!
       
  1093   \fn bool QXmlErrorHandler::fatalError( const QXmlParseException& exception )
       
  1094 
       
  1095   A reader must use this function to report a non-recoverable error.
       
  1096 
       
  1097   If this function returns TRUE the reader might try to go on parsing and
       
  1098   reporting further errors; but no regular parsing events are reported.
       
  1099 */
       
  1100 /*!
       
  1101   \fn QString QXmlErrorHandler::errorString()
       
  1102 
       
  1103   The reader calls this function to get an error string if any of the handler
       
  1104   functions returns FALSE to him.
       
  1105 */
       
  1106 
       
  1107 
       
  1108 /*!
       
  1109   \class QXmlDTDHandler qxml.h
       
  1110   \brief The QXmlDTDHandler class provides an interface to report DTD content
       
  1111   of XML data.
       
  1112 
       
  1113   \module XML
       
  1114 
       
  1115   If an application needs information about notations and unparsed entities,
       
  1116   then the application implements this interface and registers an instance with
       
  1117   QXmlReader::setDTDHandler().
       
  1118 
       
  1119   Note that this interface includes only those DTD events that the XML
       
  1120   recommendation requires processors to report: notation and unparsed entity
       
  1121   declarations.
       
  1122 
       
  1123   See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>.
       
  1124 
       
  1125   \sa QXmlDeclHandler QXmlContentHandler QXmlEntityResolver QXmlErrorHandler
       
  1126   QXmlLexicalHandler
       
  1127 */
       
  1128 /*!
       
  1129   \fn bool QXmlDTDHandler::notationDecl( const QString& name, const QString& publicId, const QString& systemId )
       
  1130 
       
  1131   The reader calls this function when he has parsed a notation
       
  1132   declaration.
       
  1133 
       
  1134   The argument \a name is the notation name, \a publicId is the notations's
       
  1135   public identifier and \a systemId is the notations's system identifier.
       
  1136 
       
  1137   If this function returns FALSE the reader will stop parsing and will report
       
  1138   an error. The reader will use the function errorString() to get the error
       
  1139   message that will be used for reporting the error.
       
  1140 */
       
  1141 /*!
       
  1142   \fn bool QXmlDTDHandler::unparsedEntityDecl( const QString& name, const QString& publicId, const QString& systemId, const QString& notationName )
       
  1143 
       
  1144   The reader calls this function when he finds an unparsed entity declaration.
       
  1145 
       
  1146   The argument \a name is the unparsed entity's name, \a publicId is the
       
  1147   entity's public identifier, \a systemId is the entity's system identifier and
       
  1148   \a notation is the name of the associated notation.
       
  1149 
       
  1150   If this function returns FALSE the reader will stop parsing and will report
       
  1151   an error. The reader will use the function errorString() to get the error
       
  1152   message that will be used for reporting the error.
       
  1153 */
       
  1154 /*!
       
  1155   \fn QString QXmlDTDHandler::errorString()
       
  1156 
       
  1157   The reader calls this function to get an error string if any of the handler
       
  1158   functions returns FALSE to him.
       
  1159 */
       
  1160 
       
  1161 
       
  1162 /*!
       
  1163   \class QXmlEntityResolver qxml.h
       
  1164   \brief The QXmlEntityResolver class provides an interface to resolve extern
       
  1165   entities contained in XML data.
       
  1166 
       
  1167   \module XML
       
  1168 
       
  1169   If an application needs to implement customized handling for external
       
  1170   entities, it must implement this interface and register it with
       
  1171   QXmlReader::setEntityResolver().
       
  1172 
       
  1173   See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>.
       
  1174 
       
  1175   \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlErrorHandler
       
  1176   QXmlLexicalHandler
       
  1177 */
       
  1178 /*!
       
  1179   \fn bool QXmlEntityResolver::resolveEntity( const QString& publicId, const QString& systemId, QXmlInputSource* ret )
       
  1180 
       
  1181   The reader will call this function before he opens any external entity,
       
  1182   except the top-level document entity. The application may request the reader
       
  1183   to resolve the entity itself (\a ret is 0) or to use an entirely different
       
  1184   input source (\a ret points to the input source).
       
  1185 
       
  1186   The reader will delete the input source \a ret when he no longer needs it. So
       
  1187   you should allocate it on the heap with \c new.
       
  1188 
       
  1189   The argument \a publicId is the public identifier of the external entity, \a
       
  1190   systemId is the system identifier of the external entity and \a ret is the
       
  1191   return value of this function: if it is 0 the reader should resolve the
       
  1192   entity itself, if it is non-zero it must point to an input source which the
       
  1193   reader will use instead.
       
  1194 
       
  1195   If this function returns FALSE the reader will stop parsing and will report
       
  1196   an error. The reader will use the function errorString() to get the error
       
  1197   message that will be used for reporting the error.
       
  1198 */
       
  1199 /*!
       
  1200   \fn QString QXmlEntityResolver::errorString()
       
  1201 
       
  1202   The reader calls this function to get an error string if any of the handler
       
  1203   functions returns FALSE to him.
       
  1204 */
       
  1205 
       
  1206 
       
  1207 /*!
       
  1208   \class QXmlLexicalHandler qxml.h
       
  1209   \brief The QXmlLexicalHandler class provides an interface to report lexical
       
  1210   content of XML data.
       
  1211 
       
  1212   \module XML
       
  1213 
       
  1214   The events in the lexical handler apply to the entire document, not just to
       
  1215   the document element, and all lexical handler events appear between the
       
  1216   content handler's startDocument and endDocument events.
       
  1217 
       
  1218   You can set the lexical handler with QXmlReader::setLexicalHandler().
       
  1219 
       
  1220   This interface is designed after the SAX2 extension LexicalHandler. The
       
  1221   functions startEntity() and endEntity() are not included though.
       
  1222 
       
  1223   See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>.
       
  1224 
       
  1225   \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver
       
  1226   QXmlErrorHandler
       
  1227 */
       
  1228 /*!
       
  1229   \fn bool QXmlLexicalHandler::startDTD( const QString& name, const QString& publicId, const QString& systemId )
       
  1230 
       
  1231   The reader calls this function to report the start of a DTD declaration, if
       
  1232   any.
       
  1233 
       
  1234   All declarations reported through QXmlDTDHandler or QXmlDeclHandler appear
       
  1235   between the startDTD() and endDTD() calls.
       
  1236 
       
  1237   If this function returns FALSE the reader will stop parsing and will report
       
  1238   an error. The reader will use the function errorString() to get the error
       
  1239   message that will be used for reporting the error.
       
  1240 
       
  1241   \sa endDTD()
       
  1242 */
       
  1243 /*!
       
  1244   \fn bool QXmlLexicalHandler::endDTD()
       
  1245 
       
  1246   The reader calls this function to report the end of a DTD declaration, if
       
  1247   any.
       
  1248 
       
  1249   If this function returns FALSE the reader will stop parsing and will report
       
  1250   an error. The reader will use the function errorString() to get the error
       
  1251   message that will be used for reporting the error.
       
  1252 
       
  1253   \sa startDTD()
       
  1254 */
       
  1255 /*!
       
  1256   \fn bool QXmlLexicalHandler::startCDATA()
       
  1257 
       
  1258   The reader calls this function to report the start of a CDATA section. The
       
  1259   content of the CDATA section will be reported through the regular
       
  1260   QXmlContentHandler::characters(). This function is intended only to report
       
  1261   the boundary.
       
  1262 
       
  1263   If this function returns FALSE the reader will stop parsing and will report
       
  1264   an error. The reader will use the function errorString() to get the error
       
  1265   message that will be used for reporting the error.
       
  1266 
       
  1267   \sa endCDATA()
       
  1268 */
       
  1269 /*!
       
  1270   \fn bool QXmlLexicalHandler::endCDATA()
       
  1271 
       
  1272   The reader calls this function to report the end of a CDATA section.
       
  1273 
       
  1274   If this function returns FALSE the reader will stop parsing and will report
       
  1275   an error. The reader will use the function errorString() to get the error
       
  1276   message that will be used for reporting the error.
       
  1277 
       
  1278   \sa startCDATA()
       
  1279 */
       
  1280 /*!
       
  1281   \fn bool QXmlLexicalHandler::comment( const QString& ch )
       
  1282 
       
  1283   The reader calls this function to report an XML comment anywhere in the
       
  1284   document.
       
  1285 
       
  1286   If this function returns FALSE the reader will stop parsing and will report
       
  1287   an error. The reader will use the function errorString() to get the error
       
  1288   message that will be used for reporting the error.
       
  1289 */
       
  1290 /*!
       
  1291   \fn QString QXmlLexicalHandler::errorString()
       
  1292 
       
  1293   The reader calls this function to get an error string if any of the handler
       
  1294   functions returns FALSE to him.
       
  1295 */
       
  1296 
       
  1297 
       
  1298 /*!
       
  1299   \class QXmlDeclHandler qxml.h
       
  1300   \brief The QXmlDeclHandler class provides an interface to report declaration
       
  1301   content of XML data.
       
  1302 
       
  1303   \module XML
       
  1304 
       
  1305   You can set the declaration handler with QXmlReader::setDeclHandler().
       
  1306 
       
  1307   This interface is designed after the SAX2 extension DeclHandler.
       
  1308 
       
  1309   See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>.
       
  1310 
       
  1311   \sa QXmlDTDHandler QXmlContentHandler QXmlEntityResolver QXmlErrorHandler
       
  1312   QXmlLexicalHandler
       
  1313 */
       
  1314 /*!
       
  1315   \fn bool QXmlDeclHandler::attributeDecl( const QString& eName, const QString& aName, const QString& type, const QString& valueDefault, const QString& value )
       
  1316 
       
  1317   The reader calls this function to report an attribute type declaration. Only
       
  1318   the effective (first) declaration for an attribute will be reported.
       
  1319 
       
  1320   If this function returns FALSE the reader will stop parsing and will report
       
  1321   an error. The reader will use the function errorString() to get the error
       
  1322   message that will be used for reporting the error.
       
  1323 */
       
  1324 /*!
       
  1325   \fn bool QXmlDeclHandler::internalEntityDecl( const QString& name, const QString& value )
       
  1326 
       
  1327   The reader calls this function to report an internal entity declaration. Only
       
  1328   the effective (first) declaration will be reported.
       
  1329 
       
  1330   If this function returns FALSE the reader will stop parsing and will report
       
  1331   an error. The reader will use the function errorString() to get the error
       
  1332   message that will be used for reporting the error.
       
  1333 */
       
  1334 /*!
       
  1335   \fn bool QXmlDeclHandler::externalEntityDecl( const QString& name, const QString& publicId, const QString& systemId )
       
  1336 
       
  1337   The reader calls this function to report a parsed external entity
       
  1338   declaration. Only the effective (first) declaration for each entity will be
       
  1339   reported.
       
  1340 
       
  1341   If this function returns FALSE the reader will stop parsing and will report
       
  1342   an error. The reader will use the function errorString() to get the error
       
  1343   message that will be used for reporting the error.
       
  1344 */
       
  1345 /*!
       
  1346   \fn QString QXmlDeclHandler::errorString()
       
  1347 
       
  1348   The reader calls this function to get an error string if any of the handler
       
  1349   functions returns FALSE to him.
       
  1350 */
       
  1351 
       
  1352 
       
  1353 /*!
       
  1354   \class QXmlDefaultHandler qxml.h
       
  1355   \brief The QXmlDefaultHandler class provides a default implementation of all
       
  1356   XML handler classes.
       
  1357 
       
  1358   \module XML
       
  1359 
       
  1360   Very often you are only interested in parts of the things that that the
       
  1361   reader reports to you. This class simply implements a default behaviour of
       
  1362   the handler classes (most of the time: do nothing). Normally this is the
       
  1363   class you subclass for implementing your customized handler.
       
  1364 
       
  1365   See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>.
       
  1366 
       
  1367   \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver
       
  1368   QXmlErrorHandler QXmlLexicalHandler
       
  1369 */
       
  1370 /*!
       
  1371   \fn QXmlDefaultHandler::QXmlDefaultHandler()
       
  1372 
       
  1373   Constructor.
       
  1374 */
       
  1375 /*!
       
  1376   \fn QXmlDefaultHandler::~QXmlDefaultHandler()
       
  1377 
       
  1378   Destructor.
       
  1379 */
       
  1380 
       
  1381 /*!
       
  1382   Does nothing.
       
  1383 */
       
  1384 void QXmlDefaultHandler::setDocumentLocator( QXmlLocator* )
       
  1385 {
       
  1386 }
       
  1387 
       
  1388 /*!
       
  1389   Does nothing.
       
  1390 */
       
  1391 bool QXmlDefaultHandler::startDocument()
       
  1392 {
       
  1393     return TRUE;
       
  1394 }
       
  1395 
       
  1396 /*!
       
  1397   Does nothing.
       
  1398 */
       
  1399 bool QXmlDefaultHandler::endDocument()
       
  1400 {
       
  1401     return TRUE;
       
  1402 }
       
  1403 
       
  1404 /*!
       
  1405   Does nothing.
       
  1406 */
       
  1407 bool QXmlDefaultHandler::startPrefixMapping( const QString&, const QString& )
       
  1408 {
       
  1409     return TRUE;
       
  1410 }
       
  1411 
       
  1412 /*!
       
  1413   Does nothing.
       
  1414 */
       
  1415 bool QXmlDefaultHandler::endPrefixMapping( const QString& )
       
  1416 {
       
  1417     return TRUE;
       
  1418 }
       
  1419 
       
  1420 /*!
       
  1421   Does nothing.
       
  1422 */
       
  1423 bool QXmlDefaultHandler::startElement( const QString&, const QString&,
       
  1424 	const QString&, const QXmlAttributes& )
       
  1425 {
       
  1426     return TRUE;
       
  1427 }
       
  1428 
       
  1429 /*!
       
  1430   Does nothing.
       
  1431 */
       
  1432 bool QXmlDefaultHandler::endElement( const QString&, const QString&,
       
  1433 	const QString& )
       
  1434 {
       
  1435     return TRUE;
       
  1436 }
       
  1437 
       
  1438 /*!
       
  1439   Does nothing.
       
  1440 */
       
  1441 bool QXmlDefaultHandler::characters( const QString& )
       
  1442 {
       
  1443     return TRUE;
       
  1444 }
       
  1445 
       
  1446 /*!
       
  1447   Does nothing.
       
  1448 */
       
  1449 bool QXmlDefaultHandler::ignorableWhitespace( const QString& )
       
  1450 {
       
  1451     return TRUE;
       
  1452 }
       
  1453 
       
  1454 /*!
       
  1455   Does nothing.
       
  1456 */
       
  1457 bool QXmlDefaultHandler::processingInstruction( const QString&,
       
  1458 	const QString& )
       
  1459 {
       
  1460     return TRUE;
       
  1461 }
       
  1462 
       
  1463 /*!
       
  1464   Does nothing.
       
  1465 */
       
  1466 bool QXmlDefaultHandler::skippedEntity( const QString& )
       
  1467 {
       
  1468     return TRUE;
       
  1469 }
       
  1470 
       
  1471 /*!
       
  1472   Does nothing.
       
  1473 */
       
  1474 bool QXmlDefaultHandler::warning( const QXmlParseException& )
       
  1475 {
       
  1476     return TRUE;
       
  1477 }
       
  1478 
       
  1479 /*!
       
  1480   Does nothing.
       
  1481 */
       
  1482 bool QXmlDefaultHandler::error( const QXmlParseException& )
       
  1483 {
       
  1484     return TRUE;
       
  1485 }
       
  1486 
       
  1487 /*!
       
  1488   Does nothing.
       
  1489 */
       
  1490 bool QXmlDefaultHandler::fatalError( const QXmlParseException& )
       
  1491 {
       
  1492     return TRUE;
       
  1493 }
       
  1494 
       
  1495 /*!
       
  1496   Does nothing.
       
  1497 */
       
  1498 bool QXmlDefaultHandler::notationDecl( const QString&, const QString&,
       
  1499 	const QString& )
       
  1500 {
       
  1501     return TRUE;
       
  1502 }
       
  1503 
       
  1504 /*!
       
  1505   Does nothing.
       
  1506 */
       
  1507 bool QXmlDefaultHandler::unparsedEntityDecl( const QString&, const QString&,
       
  1508 	const QString&, const QString& )
       
  1509 {
       
  1510     return TRUE;
       
  1511 }
       
  1512 
       
  1513 /*!
       
  1514   Always sets \a ret to 0, so that the reader will use the system identifier
       
  1515   provided in the XML document.
       
  1516 */
       
  1517 bool QXmlDefaultHandler::resolveEntity( const QString&, const QString&,
       
  1518 	QXmlInputSource* ret )
       
  1519 {
       
  1520     ret = 0;
       
  1521     return TRUE;
       
  1522 }
       
  1523 
       
  1524 /*!
       
  1525   Returns the default error string.
       
  1526 */
       
  1527 QString QXmlDefaultHandler::errorString()
       
  1528 {
       
  1529     return QString( XMLERR_ERRORBYCONSUMER );
       
  1530 }
       
  1531 
       
  1532 /*!
       
  1533   Does nothing.
       
  1534 */
       
  1535 bool QXmlDefaultHandler::startDTD( const QString&, const QString&, const QString& )
       
  1536 {
       
  1537     return TRUE;
       
  1538 }
       
  1539 
       
  1540 /*!
       
  1541   Does nothing.
       
  1542 */
       
  1543 bool QXmlDefaultHandler::endDTD()
       
  1544 {
       
  1545     return TRUE;
       
  1546 }
       
  1547 
       
  1548 #if 0
       
  1549 /*!
       
  1550   Does nothing.
       
  1551 */
       
  1552 bool QXmlDefaultHandler::startEntity( const QString& )
       
  1553 {
       
  1554     return TRUE;
       
  1555 }
       
  1556 
       
  1557 /*!
       
  1558   Does nothing.
       
  1559 */
       
  1560 bool QXmlDefaultHandler::endEntity( const QString& )
       
  1561 {
       
  1562     return TRUE;
       
  1563 }
       
  1564 #endif
       
  1565 
       
  1566 /*!
       
  1567   Does nothing.
       
  1568 */
       
  1569 bool QXmlDefaultHandler::startCDATA()
       
  1570 {
       
  1571     return TRUE;
       
  1572 }
       
  1573 
       
  1574 /*!
       
  1575   Does nothing.
       
  1576 */
       
  1577 bool QXmlDefaultHandler::endCDATA()
       
  1578 {
       
  1579     return TRUE;
       
  1580 }
       
  1581 
       
  1582 /*!
       
  1583   Does nothing.
       
  1584 */
       
  1585 bool QXmlDefaultHandler::comment( const QString& )
       
  1586 {
       
  1587     return TRUE;
       
  1588 }
       
  1589 
       
  1590 /*!
       
  1591   Does nothing.
       
  1592 */
       
  1593 bool QXmlDefaultHandler::attributeDecl( const QString&, const QString&, const QString&, const QString&, const QString& )
       
  1594 {
       
  1595     return TRUE;
       
  1596 }
       
  1597 
       
  1598 /*!
       
  1599   Does nothing.
       
  1600 */
       
  1601 bool QXmlDefaultHandler::internalEntityDecl( const QString&, const QString& )
       
  1602 {
       
  1603     return TRUE;
       
  1604 }
       
  1605 
       
  1606 /*!
       
  1607   Does nothing.
       
  1608 */
       
  1609 bool QXmlDefaultHandler::externalEntityDecl( const QString&, const QString&, const QString& )
       
  1610 {
       
  1611     return TRUE;
       
  1612 }
       
  1613 
       
  1614 
       
  1615 /*********************************************
       
  1616  *
       
  1617  * QXmlSimpleReaderPrivate
       
  1618  *
       
  1619  *********************************************/
       
  1620 
       
  1621 class QXmlSimpleReaderPrivate
       
  1622 {
       
  1623 private:
       
  1624     // constructor
       
  1625     QXmlSimpleReaderPrivate()
       
  1626     { }
       
  1627 
       
  1628 
       
  1629     // used for entity declarations
       
  1630     struct ExternParameterEntity
       
  1631     {
       
  1632 	ExternParameterEntity( ) {}
       
  1633 	ExternParameterEntity( const QString &p, const QString &s )
       
  1634 	    : publicId(p), systemId(s) {}
       
  1635 	QString publicId;
       
  1636 	QString systemId;
       
  1637     };
       
  1638     struct ExternEntity
       
  1639     {
       
  1640 	ExternEntity( ) {}
       
  1641 	ExternEntity( const QString &p, const QString &s, const QString &n )
       
  1642 	    : publicId(p), systemId(s), notation(n) {}
       
  1643 	QString publicId;
       
  1644 	QString systemId;
       
  1645 	QString notation;
       
  1646     };
       
  1647     QMap<QString,ExternParameterEntity> externParameterEntities;
       
  1648     QMap<QString,QString> parameterEntities;
       
  1649     QMap<QString,ExternEntity> externEntities;
       
  1650     QMap<QString,QString> entities;
       
  1651 
       
  1652     // used for standalone declaration
       
  1653     enum Standalone { Yes, No, Unknown };
       
  1654 
       
  1655     QString doctype; // only used for the doctype
       
  1656     QString xmlVersion; // only used to store the version information
       
  1657     QString encoding; // only used to store the encoding
       
  1658     Standalone standalone; // used to store the value of the standalone declaration
       
  1659 
       
  1660     QString publicId; // used by parseExternalID() to store the public ID
       
  1661     QString systemId; // used by parseExternalID() to store the system ID
       
  1662     QString attDeclEName; // use by parseAttlistDecl()
       
  1663     QString attDeclAName; // use by parseAttlistDecl()
       
  1664 
       
  1665     // flags for some features support
       
  1666     bool useNamespaces;
       
  1667     bool useNamespacePrefixes;
       
  1668     bool reportWhitespaceCharData;
       
  1669 
       
  1670     // used to build the attribute list
       
  1671     QXmlAttributes attList;
       
  1672 
       
  1673     // helper classes
       
  1674     QXmlLocator *locator;
       
  1675     QXmlNamespaceSupport namespaceSupport;
       
  1676 
       
  1677     // error string
       
  1678     QString error;
       
  1679 
       
  1680     // friend declarations
       
  1681     friend class QXmlSimpleReader;
       
  1682 };
       
  1683 
       
  1684 
       
  1685 /*********************************************
       
  1686  *
       
  1687  * QXmlSimpleReader
       
  1688  *
       
  1689  *********************************************/
       
  1690 
       
  1691 /*!
       
  1692   \class QXmlReader qxml.h
       
  1693   \brief The QXmlReader class provides an interface for XML readers (i.e.
       
  1694   parsers).
       
  1695 
       
  1696   \module XML
       
  1697 
       
  1698   This abstract class describes an interface for all XML readers in Qt. At the
       
  1699   moment there is only one implementation of a reader included in the XML
       
  1700   module of Qt (QXmlSimpleReader). In future releases there might be more
       
  1701   readers with different properties available (e.g. a validating parser).
       
  1702 
       
  1703   The design of the XML classes follow the
       
  1704   <a href="http://www.megginson.com/SAX/">SAX2 java interface</a>.
       
  1705   It was adopted to fit into the Qt naming conventions; so it should be very
       
  1706   easy for anybody who has worked with SAX2 to get started with the Qt XML
       
  1707   classes.
       
  1708 
       
  1709   All readers use the class QXmlInputSource to read the input document from.
       
  1710   Since you are normally interested in certain contents of the XML document,
       
  1711   the reader reports those contents through special handler classes
       
  1712   (QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver,
       
  1713   QXmlErrorHandler and QXmlLexicalHandler).
       
  1714 
       
  1715   You have to subclass these classes. Since the handler classes describe only
       
  1716   interfaces you must implement all functions; there is a class
       
  1717   (QXmlDefaultHandler) to make this easier; it implements a default behaviour
       
  1718   (do nothing) for all functions.
       
  1719 
       
  1720   For getting started see also the
       
  1721   <a href="xml-sax.html#quickStart">Quick start</a>.
       
  1722 
       
  1723   \sa QXmlSimpleReader
       
  1724 */
       
  1725 /*!
       
  1726   \fn bool QXmlReader::feature( const QString& name, bool *ok ) const
       
  1727 
       
  1728   If the reader has the feature \a name, this function returns the value of the
       
  1729   feature.
       
  1730 
       
  1731   If the reader has not the feature \a name, the return value may be anything.
       
  1732 
       
  1733   If \a ok is not 0, then \a ok  is set to TRUE if the reader has the feature
       
  1734   \a name, otherwise \a ok is set to FALSE.
       
  1735 
       
  1736   \sa setFeature() hasFeature()
       
  1737 */
       
  1738 /*!
       
  1739   \fn void QXmlReader::setFeature( const QString& name, bool value )
       
  1740 
       
  1741   Sets the feature \a name to \a value. If the reader has not the feature \a
       
  1742   name, this value is ignored.
       
  1743 
       
  1744   \sa feature() hasFeature()
       
  1745 */
       
  1746 /*!
       
  1747   \fn bool QXmlReader::hasFeature( const QString& name ) const
       
  1748 
       
  1749   Returns \c TRUE if the reader has the feature \a name, otherwise FALSE.
       
  1750 
       
  1751   \sa feature() setFeature()
       
  1752 */
       
  1753 /*!
       
  1754   \fn void* QXmlReader::property( const QString& name, bool *ok ) const
       
  1755 
       
  1756   If the reader has the property \a name, this function returns the value of
       
  1757   the property.
       
  1758 
       
  1759   If the reader has not the property \a name, the return value is 0.
       
  1760 
       
  1761   If \a ok is not 0, then \a ok  is set to TRUE if the reader has the property
       
  1762   \a name, otherwise \a ok is set to FALSE.
       
  1763 
       
  1764   \sa setProperty() hasProperty()
       
  1765 */
       
  1766 /*!
       
  1767   \fn void QXmlReader::setProperty( const QString& name, void* value )
       
  1768 
       
  1769   Sets the property \a name to \a value. If the reader has not the property \a
       
  1770   name, this value is ignored.
       
  1771 
       
  1772   \sa property() hasProperty()
       
  1773 */
       
  1774 /*!
       
  1775   \fn bool QXmlReader::hasProperty( const QString& name ) const
       
  1776 
       
  1777   Returns TRUE if the reader has the property \a name, otherwise FALSE.
       
  1778 
       
  1779   \sa property() setProperty()
       
  1780 */
       
  1781 /*!
       
  1782   \fn void QXmlReader::setEntityResolver( QXmlEntityResolver* handler )
       
  1783 
       
  1784   Sets the entity resolver to \a handler.
       
  1785 
       
  1786   \sa entityResolver()
       
  1787 */
       
  1788 /*!
       
  1789   \fn QXmlEntityResolver* QXmlReader::entityResolver() const
       
  1790 
       
  1791   Returns the entity resolver or 0 if none was set.
       
  1792 
       
  1793   \sa setEntityResolver()
       
  1794 */
       
  1795 /*!
       
  1796   \fn void QXmlReader::setDTDHandler( QXmlDTDHandler* handler )
       
  1797 
       
  1798   Sets the DTD handler to \a handler.
       
  1799 
       
  1800   \sa DTDHandler()
       
  1801 */
       
  1802 /*!
       
  1803   \fn QXmlDTDHandler* QXmlReader::DTDHandler() const
       
  1804 
       
  1805   Returns the DTD handler or 0 if none was set.
       
  1806 
       
  1807   \sa setDTDHandler()
       
  1808 */
       
  1809 /*!
       
  1810   \fn void QXmlReader::setContentHandler( QXmlContentHandler* handler )
       
  1811 
       
  1812   Sets the content handler to \a handler.
       
  1813 
       
  1814   \sa contentHandler()
       
  1815 */
       
  1816 /*!
       
  1817   \fn QXmlContentHandler* QXmlReader::contentHandler() const
       
  1818 
       
  1819   Returns the content handler or 0 if none was set.
       
  1820 
       
  1821   \sa setContentHandler()
       
  1822 */
       
  1823 /*!
       
  1824   \fn void QXmlReader::setErrorHandler( QXmlErrorHandler* handler )
       
  1825 
       
  1826   Sets the error handler to \a handler.
       
  1827 
       
  1828   \sa errorHandler()
       
  1829 */
       
  1830 /*!
       
  1831   \fn QXmlErrorHandler* QXmlReader::errorHandler() const
       
  1832 
       
  1833   Returns the error handler or 0 if none was set
       
  1834 
       
  1835   \sa setErrorHandler()
       
  1836 */
       
  1837 /*!
       
  1838   \fn void QXmlReader::setLexicalHandler( QXmlLexicalHandler* handler )
       
  1839 
       
  1840   Sets the lexical handler to \a handler.
       
  1841 
       
  1842   \sa lexicalHandler()
       
  1843 */
       
  1844 /*!
       
  1845   \fn QXmlLexicalHandler* QXmlReader::lexicalHandler() const
       
  1846 
       
  1847   Returns the lexical handler or 0 if none was set.
       
  1848 
       
  1849   \sa setLexicalHandler()
       
  1850 */
       
  1851 /*!
       
  1852   \fn void QXmlReader::setDeclHandler( QXmlDeclHandler* handler )
       
  1853 
       
  1854   Sets the declaration handler to \a handler.
       
  1855 
       
  1856   \sa declHandler()
       
  1857 */
       
  1858 /*!
       
  1859   \fn QXmlDeclHandler* QXmlReader::declHandler() const
       
  1860 
       
  1861   Returns the declaration handler or 0 if none was set.
       
  1862 
       
  1863   \sa setDeclHandler()
       
  1864 */
       
  1865 /*!
       
  1866   \fn bool QXmlReader::parse( const QXmlInputSource& input )
       
  1867 
       
  1868   Parses the XML document \a input. Returns TRUE if the parsing was successful,
       
  1869   otherwise FALSE.
       
  1870 */
       
  1871 /*!
       
  1872   \fn bool QXmlReader::parse( const QString& systemId )
       
  1873 
       
  1874   Parses the XML document at the location \a systemId. Returns TRUE if the
       
  1875   parsing was successful, otherwise FALSE.
       
  1876 */
       
  1877 
       
  1878 
       
  1879 /*!
       
  1880   \class QXmlSimpleReader qxml.h
       
  1881   \brief The QXmlSimpleReader class provides an implementation of a simple XML
       
  1882   reader (i.e. parser).
       
  1883 
       
  1884   \module XML
       
  1885 
       
  1886   This XML reader is sufficient for simple parsing tasks. Here is a short list
       
  1887   of the properties of this reader:
       
  1888   <ul>
       
  1889   <li> well-formed parser
       
  1890   <li> does not parse any external entities
       
  1891   <li> can do namespace processing
       
  1892   </ul>
       
  1893 
       
  1894   For getting started see also the
       
  1895   <a href="xml-sax.html#quickStart">Quick start</a>.
       
  1896 */
       
  1897 
       
  1898 //guaranteed not to be a characater
       
  1899 const QChar QXmlSimpleReader::QEOF = QChar((ushort)0xffff);
       
  1900 
       
  1901 /*!
       
  1902   Constructs a simple XML reader.
       
  1903 */
       
  1904 QXmlSimpleReader::QXmlSimpleReader()
       
  1905 {
       
  1906     d = new QXmlSimpleReaderPrivate();
       
  1907     d->locator = new QXmlLocator( this );
       
  1908 
       
  1909     entityRes  = 0;
       
  1910     dtdHnd     = 0;
       
  1911     contentHnd = 0;
       
  1912     errorHnd   = 0;
       
  1913     lexicalHnd = 0;
       
  1914     declHnd    = 0;
       
  1915 
       
  1916     // default feature settings
       
  1917     d->useNamespaces = TRUE;
       
  1918     d->useNamespacePrefixes = FALSE;
       
  1919     d->reportWhitespaceCharData = TRUE;
       
  1920 }
       
  1921 
       
  1922 /*!
       
  1923   Destroys a simple XML reader.
       
  1924 */
       
  1925 QXmlSimpleReader::~QXmlSimpleReader()
       
  1926 {
       
  1927     delete d->locator;
       
  1928     delete d;
       
  1929 }
       
  1930 
       
  1931 /*!
       
  1932   Gets the state of a feature.
       
  1933 
       
  1934   \sa setFeature() hasFeature()
       
  1935 */
       
  1936 bool QXmlSimpleReader::feature( const QString& name, bool *ok ) const
       
  1937 {
       
  1938     if ( ok != 0 )
       
  1939 	*ok = TRUE;
       
  1940     if        ( name == "http://xml.org/sax/features/namespaces" ) {
       
  1941 	return d->useNamespaces;
       
  1942     } else if ( name == "http://xml.org/sax/features/namespace-prefixes" ) {
       
  1943 	return d->useNamespacePrefixes;
       
  1944     } else if ( name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) {
       
  1945 	return d->reportWhitespaceCharData;
       
  1946     } else {
       
  1947 	qWarning( "Unknown feature " + name );
       
  1948 	if ( ok != 0 )
       
  1949 	    *ok = FALSE;
       
  1950     }
       
  1951     return FALSE;
       
  1952 }
       
  1953 
       
  1954 /*!
       
  1955   Sets the state of a feature.
       
  1956 
       
  1957   Supported features are:
       
  1958   <ul>
       
  1959   <li> http://xml.org/sax/features/namespaces:
       
  1960        if this feature is TRUE, namespace processing is performed
       
  1961   <li> http://xml.org/sax/features/namespace-prefixes:
       
  1962        if this feature is TRUE, the the original prefixed names and attributes
       
  1963        used for namespace declarations are reported
       
  1964   <li> http://trolltech.com/xml/features/report-whitespace-only-CharData:
       
  1965        if this feature is TRUE, CharData that consists only of whitespace (and
       
  1966        no other characters) is not reported via
       
  1967        QXmlContentHandler::characters()
       
  1968   </ul>
       
  1969 
       
  1970   \sa feature() hasFeature()
       
  1971 */
       
  1972 void QXmlSimpleReader::setFeature( const QString& name, bool value )
       
  1973 {
       
  1974     if        ( name == "http://xml.org/sax/features/namespaces" ) {
       
  1975 	d->useNamespaces = value;
       
  1976     } else if ( name == "http://xml.org/sax/features/namespace-prefixes" ) {
       
  1977 	d->useNamespacePrefixes = value;
       
  1978     } else if ( name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) {
       
  1979 	d->reportWhitespaceCharData = value;
       
  1980     } else {
       
  1981 	qWarning( "Unknown feature " + name );
       
  1982     }
       
  1983 }
       
  1984 
       
  1985 /*!
       
  1986   Returns TRUE if the class has a feature named \a feature, otherwise FALSE.
       
  1987 
       
  1988   \sa setFeature() feature()
       
  1989 */
       
  1990 bool QXmlSimpleReader::hasFeature( const QString& name ) const
       
  1991 {
       
  1992     if (    name == "http://xml.org/sax/features/namespaces" ||
       
  1993 	    name == "http://xml.org/sax/features/namespace-prefixes" ||
       
  1994 	    name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) {
       
  1995 	return TRUE;
       
  1996     } else {
       
  1997 	return FALSE;
       
  1998     }
       
  1999 }
       
  2000 
       
  2001 /*!
       
  2002   Returns 0 since this class does not support any properties.
       
  2003 */
       
  2004 void* QXmlSimpleReader::property( const QString&, bool *ok ) const
       
  2005 {
       
  2006     if ( ok != 0 )
       
  2007 	*ok = FALSE;
       
  2008     return 0;
       
  2009 }
       
  2010 
       
  2011 /*!
       
  2012   Does nothing since this class does not support any properties.
       
  2013 */
       
  2014 void QXmlSimpleReader::setProperty( const QString&, void* )
       
  2015 {
       
  2016 }
       
  2017 
       
  2018 /*!
       
  2019   Returns FALSE since this class does not support any properties.
       
  2020 */
       
  2021 bool QXmlSimpleReader::hasProperty( const QString& ) const
       
  2022 {
       
  2023     return FALSE;
       
  2024 }
       
  2025 
       
  2026 /*! \reimp */
       
  2027 void QXmlSimpleReader::setEntityResolver( QXmlEntityResolver* handler )
       
  2028 { entityRes = handler; }
       
  2029 
       
  2030 /*! \reimp */
       
  2031 QXmlEntityResolver* QXmlSimpleReader::entityResolver() const
       
  2032 { return entityRes; }
       
  2033 
       
  2034 /*! \reimp */
       
  2035 void QXmlSimpleReader::setDTDHandler( QXmlDTDHandler* handler )
       
  2036 { dtdHnd = handler; }
       
  2037 
       
  2038 /*! \reimp */
       
  2039 QXmlDTDHandler* QXmlSimpleReader::DTDHandler() const
       
  2040 { return dtdHnd; }
       
  2041 
       
  2042 /*! \reimp */
       
  2043 void QXmlSimpleReader::setContentHandler( QXmlContentHandler* handler )
       
  2044 { contentHnd = handler; }
       
  2045 
       
  2046 /*! \reimp */
       
  2047 QXmlContentHandler* QXmlSimpleReader::contentHandler() const
       
  2048 { return contentHnd; }
       
  2049 
       
  2050 /*! \reimp */
       
  2051 void QXmlSimpleReader::setErrorHandler( QXmlErrorHandler* handler )
       
  2052 { errorHnd = handler; }
       
  2053 
       
  2054 /*! \reimp */
       
  2055 QXmlErrorHandler* QXmlSimpleReader::errorHandler() const
       
  2056 { return errorHnd; }
       
  2057 
       
  2058 /*! \reimp */
       
  2059 void QXmlSimpleReader::setLexicalHandler( QXmlLexicalHandler* handler )
       
  2060 { lexicalHnd = handler; }
       
  2061 
       
  2062 /*! \reimp */
       
  2063 QXmlLexicalHandler* QXmlSimpleReader::lexicalHandler() const
       
  2064 { return lexicalHnd; }
       
  2065 
       
  2066 /*! \reimp */
       
  2067 void QXmlSimpleReader::setDeclHandler( QXmlDeclHandler* handler )
       
  2068 { declHnd = handler; }
       
  2069 
       
  2070 /*! \reimp */
       
  2071 QXmlDeclHandler* QXmlSimpleReader::declHandler() const
       
  2072 { return declHnd; }
       
  2073 
       
  2074 
       
  2075 
       
  2076 /*! \reimp */
       
  2077 bool QXmlSimpleReader::parse( const QXmlInputSource& input )
       
  2078 {
       
  2079     init( input );
       
  2080     // call the handler
       
  2081     if ( contentHnd ) {
       
  2082 	contentHnd->setDocumentLocator( d->locator );
       
  2083 	if ( !contentHnd->startDocument() ) {
       
  2084 	    d->error = contentHnd->errorString();
       
  2085 	    goto parseError;
       
  2086 	}
       
  2087     }
       
  2088     // parse prolog
       
  2089     if ( !parseProlog() ) {
       
  2090 	d->error = XMLERR_ERRORPARSINGPROLOG;
       
  2091 	goto parseError;
       
  2092     }
       
  2093     // parse element
       
  2094     if ( !parseElement() ) {
       
  2095 	d->error = XMLERR_ERRORPARSINGMAINELEMENT;
       
  2096 	goto parseError;
       
  2097     }
       
  2098     // parse Misc*
       
  2099     while ( !atEnd() ) {
       
  2100 	if ( !parseMisc() ) {
       
  2101 	    d->error = XMLERR_ERRORPARSINGMISC;
       
  2102 	    goto parseError;
       
  2103 	}
       
  2104     }
       
  2105     // is stack empty?
       
  2106     if ( !tags.isEmpty() ) {
       
  2107 	d->error = XMLERR_UNEXPECTEDEOF;
       
  2108 	goto parseError;
       
  2109     }
       
  2110     // call the handler
       
  2111     if ( contentHnd ) {
       
  2112 	if ( !contentHnd->endDocument() ) {
       
  2113 	    d->error = contentHnd->errorString();
       
  2114 	    goto parseError;
       
  2115 	}
       
  2116     }
       
  2117 
       
  2118     return TRUE;
       
  2119 
       
  2120     // error handling
       
  2121 
       
  2122 parseError:
       
  2123     reportParseError();
       
  2124     tags.clear();
       
  2125     return FALSE;
       
  2126 }
       
  2127 
       
  2128 /*!
       
  2129   Parses the prolog [22].
       
  2130 */
       
  2131 bool QXmlSimpleReader::parseProlog()
       
  2132 {
       
  2133     bool xmldecl_possible = TRUE;
       
  2134     bool doctype_read = FALSE;
       
  2135 
       
  2136     const signed char Init             = 0;
       
  2137     const signed char EatWS            = 1; // eat white spaces
       
  2138     const signed char Lt               = 2; // '<' read
       
  2139     const signed char Em               = 3; // '!' read
       
  2140     const signed char DocType          = 4; // read doctype
       
  2141     const signed char Comment          = 5; // read comment
       
  2142     const signed char PI               = 6; // read PI
       
  2143     const signed char Done             = 7;
       
  2144 
       
  2145     const signed char InpWs            = 0;
       
  2146     const signed char InpLt            = 1; // <
       
  2147     const signed char InpQm            = 2; // ?
       
  2148     const signed char InpEm            = 3; // !
       
  2149     const signed char InpD             = 4; // D
       
  2150     const signed char InpDash          = 5; // -
       
  2151     const signed char InpUnknown       = 6;
       
  2152 
       
  2153     // use some kind of state machine for parsing
       
  2154     static signed char table[7][7] = {
       
  2155      /*  InpWs   InpLt  InpQm  InpEm  InpD      InpDash  InpUnknown */
       
  2156 	{ EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }, // Init
       
  2157 	{ -1,     Lt,    -1,    -1,    -1,       -1,       -1      }, // EatWS
       
  2158 	{ -1,     -1,    PI,    Em,    Done,     -1,       Done    }, // Lt
       
  2159 	{ -1,     -1,    -1,    -1,    DocType,  Comment,  -1      }, // Em
       
  2160 	{ EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }, // DocType
       
  2161 	{ EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }, // Comment
       
  2162 	{ EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }  // PI
       
  2163     };
       
  2164     signed char state = Init;
       
  2165     signed char input;
       
  2166     bool parseOk = TRUE;
       
  2167 
       
  2168     while ( TRUE ) {
       
  2169 
       
  2170 	// read input
       
  2171 	if ( atEnd() ) {
       
  2172 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  2173 	    goto parseError;
       
  2174 	}
       
  2175 	if        ( is_S(c) ) {
       
  2176 	    input = InpWs;
       
  2177 	} else if ( c == '<' ) {
       
  2178 	    input = InpLt;
       
  2179 	} else if ( c == '?' ) {
       
  2180 	    input = InpQm;
       
  2181 	} else if ( c == '!' ) {
       
  2182 	    input = InpEm;
       
  2183 	} else if ( c == 'D' ) {
       
  2184 	    input = InpD;
       
  2185 	} else if ( c == '-' ) {
       
  2186 	    input = InpDash;
       
  2187 	} else {
       
  2188 	    input = InpUnknown;
       
  2189 	}
       
  2190 	// get new state
       
  2191 	state = table[state][input];
       
  2192 
       
  2193 	// in some cases do special actions depending on state
       
  2194 	switch ( state ) {
       
  2195 	    case EatWS:
       
  2196 		// XML declaration only on first position possible
       
  2197 		xmldecl_possible = FALSE;
       
  2198 		// eat white spaces
       
  2199 		eat_ws();
       
  2200 		break;
       
  2201 	    case Lt:
       
  2202 		// next character
       
  2203 		next();
       
  2204 		break;
       
  2205 	    case Em:
       
  2206 		// XML declaration only on first position possible
       
  2207 		xmldecl_possible = FALSE;
       
  2208 		// next character
       
  2209 		next();
       
  2210 		break;
       
  2211 	    case DocType:
       
  2212 		parseOk = parseDoctype();
       
  2213 		break;
       
  2214 	    case Comment:
       
  2215 		parseOk = parseComment();
       
  2216 		break;
       
  2217 	    case PI:
       
  2218 		parseOk = parsePI( xmldecl_possible );
       
  2219 		break;
       
  2220 	}
       
  2221 	// no input is read after this
       
  2222 	switch ( state ) {
       
  2223 	    case DocType:
       
  2224 		if ( !parseOk ) {
       
  2225 		    d->error = XMLERR_ERRORPARSINGPROLOG;
       
  2226 		    goto parseError;
       
  2227 		}
       
  2228 		if ( doctype_read ) {
       
  2229 		    d->error = XMLERR_MORETHANONEDOCTYPE;
       
  2230 		    goto parseError;
       
  2231 		} else {
       
  2232 		    doctype_read = FALSE;
       
  2233 		}
       
  2234 		break;
       
  2235 	    case Comment:
       
  2236 		if ( !parseOk ) {
       
  2237 		    d->error = XMLERR_ERRORPARSINGPROLOG;
       
  2238 		    goto parseError;
       
  2239 		}
       
  2240 		if ( lexicalHnd ) {
       
  2241 		    if ( !lexicalHnd->comment( string() ) ) {
       
  2242 			d->error = lexicalHnd->errorString();
       
  2243 			goto parseError;
       
  2244 		    }
       
  2245 		}
       
  2246 		break;
       
  2247 	    case PI:
       
  2248 		if ( !parseOk ) {
       
  2249 		    d->error = XMLERR_ERRORPARSINGPROLOG;
       
  2250 		    goto parseError;
       
  2251 		}
       
  2252 		// call the handler
       
  2253 		if ( contentHnd ) {
       
  2254 		    if ( xmldecl_possible && !d->xmlVersion.isEmpty() ) {
       
  2255 			QString value( "version = '" );
       
  2256 			value += d->xmlVersion;
       
  2257 			value += "'";
       
  2258 			if ( !d->encoding.isEmpty() ) {
       
  2259 			    value += " encoding = '";
       
  2260 			    value += d->encoding;
       
  2261 			    value += "'";
       
  2262 			}
       
  2263 			if ( d->standalone == QXmlSimpleReaderPrivate::Yes ) {
       
  2264 			    value += " standalone = 'yes'";
       
  2265 			} else if ( d->standalone == QXmlSimpleReaderPrivate::No ) {
       
  2266 			    value += " standalone = 'no'";
       
  2267 			}
       
  2268 			if ( !contentHnd->processingInstruction( "xml", value ) ) {
       
  2269 			    d->error = contentHnd->errorString();
       
  2270 			    goto parseError;
       
  2271 			}
       
  2272 		    } else {
       
  2273 			if ( !contentHnd->processingInstruction( name(), string() ) ) {
       
  2274 			    d->error = contentHnd->errorString();
       
  2275 			    goto parseError;
       
  2276 			}
       
  2277 		    }
       
  2278 		}
       
  2279 		// XML declaration only on first position possible
       
  2280 		xmldecl_possible = FALSE;
       
  2281 		break;
       
  2282 	    case Done:
       
  2283 		return TRUE;
       
  2284 	    case -1:
       
  2285 		d->error = XMLERR_ERRORPARSINGELEMENT;
       
  2286 		goto parseError;
       
  2287 	}
       
  2288 
       
  2289     }
       
  2290 
       
  2291     return TRUE;
       
  2292 
       
  2293 parseError:
       
  2294     reportParseError();
       
  2295     return FALSE;
       
  2296 }
       
  2297 
       
  2298 /*!
       
  2299   Parse an element [39].
       
  2300 
       
  2301   Precondition: the opening '<' is already read.
       
  2302 */
       
  2303 bool QXmlSimpleReader::parseElement()
       
  2304 {
       
  2305     static QString uri, lname, prefix;
       
  2306     static bool t;
       
  2307 
       
  2308     const signed char Init             =  0;
       
  2309     const signed char ReadName         =  1;
       
  2310     const signed char Ws1              =  2;
       
  2311     const signed char STagEnd          =  3;
       
  2312     const signed char STagEnd2         =  4;
       
  2313     const signed char ETagBegin        =  5;
       
  2314     const signed char ETagBegin2       =  6;
       
  2315     const signed char Ws2              =  7;
       
  2316     const signed char EmptyTag         =  8;
       
  2317     const signed char Attribute        =  9;
       
  2318     const signed char Ws3              = 10;
       
  2319     const signed char Done             = 11;
       
  2320 
       
  2321     const signed char InpWs            = 0; // whitespace
       
  2322     const signed char InpNameBe        = 1; // is_NameBeginning()
       
  2323     const signed char InpGt            = 2; // >
       
  2324     const signed char InpSlash         = 3; // /
       
  2325     const signed char InpUnknown       = 4;
       
  2326 
       
  2327     // use some kind of state machine for parsing
       
  2328     static signed char table[11][5] = {
       
  2329      /*  InpWs      InpNameBe    InpGt        InpSlash     InpUnknown */
       
  2330 	{ -1,        ReadName,    -1,          -1,          -1        }, // Init
       
  2331 	{ Ws1,       Attribute,   STagEnd,     EmptyTag,    -1        }, // ReadName
       
  2332 	{ -1,        Attribute,   STagEnd,     EmptyTag,    -1        }, // Ws1
       
  2333 	{ STagEnd2,  STagEnd2,    STagEnd2,    STagEnd2,    STagEnd2  }, // STagEnd
       
  2334 	{ -1,        -1,          -1,          ETagBegin,   -1        }, // STagEnd2
       
  2335 	{ -1,        ETagBegin2,  -1,          -1,          -1        }, // ETagBegin
       
  2336 	{ Ws2,       -1,          Done,        -1,          -1        }, // ETagBegin2
       
  2337 	{ -1,        -1,          Done,        -1,          -1        }, // Ws2
       
  2338 	{ -1,        -1,          Done,        -1,          -1        }, // EmptyTag
       
  2339 	{ Ws3,       Attribute,   STagEnd,     EmptyTag,    -1        }, // Attribute
       
  2340 	{ -1,        Attribute,   STagEnd,     EmptyTag,    -1        }  // Ws3
       
  2341     };
       
  2342     signed char state = Init;
       
  2343     signed char input;
       
  2344     bool parseOk = TRUE;
       
  2345 
       
  2346     while ( TRUE ) {
       
  2347 
       
  2348 	// read input
       
  2349 	if ( atEnd() ) {
       
  2350 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  2351 	    goto parseError;
       
  2352 	}
       
  2353 	if        ( is_S(c) ) {
       
  2354 	    input = InpWs;
       
  2355 	} else if ( is_NameBeginning(c) ) {
       
  2356 	    input = InpNameBe;
       
  2357 	} else if ( c == '>' ) {
       
  2358 	    input = InpGt;
       
  2359 	} else if ( c == '/' ) {
       
  2360 	    input = InpSlash;
       
  2361 	} else {
       
  2362 	    input = InpUnknown;
       
  2363 	}
       
  2364 	// get new state
       
  2365 //qDebug( "%d -%d(%c)-> %d", state, input, c.latin1(), table[state][input] );
       
  2366 	state = table[state][input];
       
  2367 
       
  2368 	// in some cases do special actions depending on state
       
  2369 	switch ( state ) {
       
  2370 	    case ReadName:
       
  2371 		parseOk = parseName();
       
  2372 		break;
       
  2373 	    case Ws1:
       
  2374 	    case Ws2:
       
  2375 	    case Ws3:
       
  2376 		eat_ws();
       
  2377 		break;
       
  2378 	    case STagEnd:
       
  2379 		// call the handler
       
  2380 		if ( contentHnd ) {
       
  2381 		    if ( d->useNamespaces ) {
       
  2382 			d->namespaceSupport.processName( tags.top(), FALSE, uri, lname );
       
  2383 			t = contentHnd->startElement( uri, lname, tags.top(), d->attList );
       
  2384 		    } else {
       
  2385 			t = contentHnd->startElement( "", "", tags.top(), d->attList );
       
  2386 		    }
       
  2387 		    if ( !t ) {
       
  2388 			d->error = contentHnd->errorString();
       
  2389 			goto parseError;
       
  2390 		    }
       
  2391 		}
       
  2392 		next();
       
  2393 		break;
       
  2394 	    case STagEnd2:
       
  2395 		parseOk = parseContent();
       
  2396 		break;
       
  2397 	    case ETagBegin:
       
  2398 		next();
       
  2399 		break;
       
  2400 	    case ETagBegin2:
       
  2401 		// get the name of the tag
       
  2402 		parseOk = parseName();
       
  2403 		break;
       
  2404 	    case EmptyTag:
       
  2405 		if  ( tags.isEmpty() ) {
       
  2406 		    d->error = XMLERR_TAGMISMATCH;
       
  2407 		    goto parseError;
       
  2408 		}
       
  2409 		if ( !parseElementEmptyTag( t, uri, lname ) )
       
  2410 		    goto parseError;
       
  2411 		// next character
       
  2412 		next();
       
  2413 		break;
       
  2414 	    case Attribute:
       
  2415 		// get name and value of attribute
       
  2416 		parseOk = parseAttribute();
       
  2417 		break;
       
  2418 	    case Done:
       
  2419 		next();
       
  2420 		break;
       
  2421 	}
       
  2422 	// no input is read after this
       
  2423 	switch ( state ) {
       
  2424 	    case ReadName:
       
  2425 		if ( !parseOk ) {
       
  2426 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  2427 		    goto parseError;
       
  2428 		}
       
  2429 		// store it on the stack
       
  2430 		tags.push( name() );
       
  2431 		// empty the attributes
       
  2432 		d->attList.qnameList.clear();
       
  2433 		d->attList.uriList.clear();
       
  2434 		d->attList.localnameList.clear();
       
  2435 		d->attList.valueList.clear();
       
  2436 		// namespace support?
       
  2437 		if ( d->useNamespaces ) {
       
  2438 		    d->namespaceSupport.pushContext();
       
  2439 		}
       
  2440 		break;
       
  2441 	    case STagEnd2:
       
  2442 		if ( !parseOk ) {
       
  2443 		    d->error = XMLERR_ERRORPARSINGCONTENT;
       
  2444 		    goto parseError;
       
  2445 		}
       
  2446 		break;
       
  2447 	    case ETagBegin2:
       
  2448 		if ( !parseOk ) {
       
  2449 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  2450 		    goto parseError;
       
  2451 		}
       
  2452 		if ( !parseElementETagBegin2() )
       
  2453 		    goto parseError;
       
  2454 		break;
       
  2455 	    case Attribute:
       
  2456 		if ( !parseOk ) {
       
  2457 		    d->error = XMLERR_ERRORPARSINGATTRIBUTE;
       
  2458 		    goto parseError;
       
  2459 		}
       
  2460 		if ( !parseElementAttribute( prefix, uri, lname ) )
       
  2461 		    goto parseError;
       
  2462 		break;
       
  2463 	    case Done:
       
  2464 		return TRUE;
       
  2465 	    case -1:
       
  2466 		d->error = XMLERR_ERRORPARSINGELEMENT;
       
  2467 		goto parseError;
       
  2468 	}
       
  2469 
       
  2470     }
       
  2471 
       
  2472     return TRUE;
       
  2473 
       
  2474 parseError:
       
  2475     reportParseError();
       
  2476     return FALSE;
       
  2477 }
       
  2478 /*!
       
  2479   Helper to break down the size of the code in the case statement.
       
  2480   Return FALSE on error, otherwise TRUE.
       
  2481 */
       
  2482 bool QXmlSimpleReader::parseElementEmptyTag( bool &t, QString &uri, QString &lname )
       
  2483 {
       
  2484     // pop the stack and call the handler
       
  2485     if ( contentHnd ) {
       
  2486 	// report startElement first...
       
  2487 	if ( d->useNamespaces ) {
       
  2488 	    d->namespaceSupport.processName( tags.top(), FALSE, uri, lname );
       
  2489 	    t = contentHnd->startElement( uri, lname, tags.top(), d->attList );
       
  2490 	} else {
       
  2491 	    t = contentHnd->startElement( "", "", tags.top(), d->attList );
       
  2492 	}
       
  2493 	if ( !t ) {
       
  2494 	    d->error = contentHnd->errorString();
       
  2495 	    return FALSE;
       
  2496 	}
       
  2497 	// ... followed by endElement
       
  2498 	// ### missing namespace support!
       
  2499 	if ( !contentHnd->endElement( "","",tags.pop() ) ) {
       
  2500 	    d->error = contentHnd->errorString();
       
  2501 	    return FALSE;
       
  2502 	}
       
  2503 	// namespace support?
       
  2504 	if ( d->useNamespaces ) {
       
  2505 	    QStringList prefixesBefore, prefixesAfter;
       
  2506 	    if ( contentHnd ) {
       
  2507 		prefixesBefore = d->namespaceSupport.prefixes();
       
  2508 	    }
       
  2509 	    d->namespaceSupport.popContext();
       
  2510 	    // call the handler for prefix mapping
       
  2511 	    if ( contentHnd ) {
       
  2512 		prefixesAfter = d->namespaceSupport.prefixes();
       
  2513 		for ( QStringList::Iterator it = prefixesBefore.begin(); it != prefixesBefore.end(); ++it ) {
       
  2514 		    if ( prefixesAfter.contains(*it) == 0 ) {
       
  2515 			if ( !contentHnd->endPrefixMapping( *it ) ) {
       
  2516 			    d->error = contentHnd->errorString();
       
  2517 			    return FALSE;
       
  2518 			}
       
  2519 		    }
       
  2520 		}
       
  2521 	    }
       
  2522 	}
       
  2523     } else {
       
  2524 	tags.pop();
       
  2525     }
       
  2526     return TRUE;
       
  2527 }
       
  2528 /*!
       
  2529   Helper to break down the size of the code in the case statement.
       
  2530   Return FALSE on error, otherwise TRUE.
       
  2531 */
       
  2532 bool QXmlSimpleReader::parseElementETagBegin2()
       
  2533 {
       
  2534 
       
  2535     // pop the stack and compare it with the name
       
  2536     if ( tags.pop() != name() ) {
       
  2537 	d->error = XMLERR_TAGMISMATCH;
       
  2538 	return FALSE;
       
  2539     }
       
  2540     // call the handler
       
  2541     // ### missing namespace support!
       
  2542     if ( contentHnd ) {
       
  2543 	if ( !contentHnd->endElement("","",name()) ) {
       
  2544 	    d->error = contentHnd->errorString();
       
  2545 	    return FALSE;
       
  2546 	}
       
  2547     }
       
  2548     // namespace support?
       
  2549     if ( d->useNamespaces ) {
       
  2550 	QStringList prefixesBefore, prefixesAfter;
       
  2551 	if ( contentHnd ) {
       
  2552 	    prefixesBefore = d->namespaceSupport.prefixes();
       
  2553 	}
       
  2554 	d->namespaceSupport.popContext();
       
  2555 	// call the handler for prefix mapping
       
  2556 	if ( contentHnd ) {
       
  2557 	    prefixesAfter = d->namespaceSupport.prefixes();
       
  2558 	    for ( QStringList::Iterator it = prefixesBefore.begin(); it != prefixesBefore.end(); ++it ) {
       
  2559 		if ( prefixesAfter.contains(*it) == 0 ) {
       
  2560 		    if ( !contentHnd->endPrefixMapping( *it ) ) {
       
  2561 			d->error = contentHnd->errorString();
       
  2562 			return FALSE;
       
  2563 		    }
       
  2564 		}
       
  2565 	    }
       
  2566 	}
       
  2567     }
       
  2568     return TRUE;
       
  2569 }
       
  2570 /*!
       
  2571   Helper to break down the size of the code in the case statement.
       
  2572   Return FALSE on error, otherwise TRUE.
       
  2573 */
       
  2574 bool QXmlSimpleReader::parseElementAttribute( QString &prefix, QString &uri, QString &lname )
       
  2575 {
       
  2576     // add the attribute to the list
       
  2577     if ( d->useNamespaces ) {
       
  2578 	// is it a namespace declaration?
       
  2579 	d->namespaceSupport.splitName( name(), prefix, lname );
       
  2580 	if ( prefix == "xmlns" ) {
       
  2581 	    // namespace declaration
       
  2582 	    d->namespaceSupport.setPrefix( lname, string() );
       
  2583 	    if ( d->useNamespacePrefixes ) {
       
  2584 		d->attList.qnameList.append( name() );
       
  2585 		d->attList.uriList.append( "" );
       
  2586 		d->attList.localnameList.append( "" );
       
  2587 		d->attList.valueList.append( string() );
       
  2588 	    }
       
  2589 	    // call the handler for prefix mapping
       
  2590 	    if ( contentHnd ) {
       
  2591 		if ( !contentHnd->startPrefixMapping( lname, string() ) ) {
       
  2592 		    d->error = contentHnd->errorString();
       
  2593 		    return FALSE;
       
  2594 		}
       
  2595 	    }
       
  2596 	} else {
       
  2597 	    // no namespace delcaration
       
  2598 	    d->namespaceSupport.processName( name(), TRUE, uri, lname );
       
  2599 	    d->attList.qnameList.append( name() );
       
  2600 	    d->attList.uriList.append( uri );
       
  2601 	    d->attList.localnameList.append( lname );
       
  2602 	    d->attList.valueList.append( string() );
       
  2603 	}
       
  2604     } else {
       
  2605 	// no namespace support
       
  2606 	d->attList.qnameList.append( name() );
       
  2607 	d->attList.uriList.append( "" );
       
  2608 	d->attList.localnameList.append( "" );
       
  2609 	d->attList.valueList.append( string() );
       
  2610     }
       
  2611     return TRUE;
       
  2612 }
       
  2613 
       
  2614 /*!
       
  2615   Parse a content [43].
       
  2616 
       
  2617   A content is only used between tags. If a end tag is found the < is already
       
  2618   read and the head stand on the '/' of the end tag '</name>'.
       
  2619 */
       
  2620 bool QXmlSimpleReader::parseContent()
       
  2621 {
       
  2622     bool charDataRead = FALSE;
       
  2623 
       
  2624     const signed char Init             =  0;
       
  2625     const signed char ChD              =  1; // CharData
       
  2626     const signed char ChD1             =  2; // CharData help state
       
  2627     const signed char ChD2             =  3; // CharData help state
       
  2628     const signed char Ref              =  4; // Reference
       
  2629     const signed char Lt               =  5; // '<' read
       
  2630     const signed char PI               =  6; // PI
       
  2631     const signed char Elem             =  7; // Element
       
  2632     const signed char Em               =  8; // '!' read
       
  2633     const signed char Com              =  9; // Comment
       
  2634     const signed char CDS              = 10; // CDSect
       
  2635     const signed char CDS1             = 11; // read a CDSect
       
  2636     const signed char CDS2             = 12; // read a CDSect (help state)
       
  2637     const signed char CDS3             = 13; // read a CDSect (help state)
       
  2638     const signed char Done             = 14; // finished reading content
       
  2639 
       
  2640     const signed char InpLt            = 0; // <
       
  2641     const signed char InpGt            = 1; // >
       
  2642     const signed char InpSlash         = 2; // /
       
  2643     const signed char InpQMark         = 3; // ?
       
  2644     const signed char InpEMark         = 4; // !
       
  2645     const signed char InpAmp           = 5; // &
       
  2646     const signed char InpDash          = 6; // -
       
  2647     const signed char InpOpenB         = 7; // [
       
  2648     const signed char InpCloseB        = 8; // ]
       
  2649     const signed char InpUnknown       = 9;
       
  2650 
       
  2651     static signed char mapCLT2FSMChar[] = {
       
  2652 	InpUnknown, // white space
       
  2653 	InpUnknown, // %
       
  2654 	InpAmp,     // &
       
  2655 	InpGt,      // >
       
  2656 	InpLt,      // <
       
  2657 	InpSlash,   // /
       
  2658 	InpQMark,   // ?
       
  2659 	InpEMark,   // !
       
  2660 	InpDash,    // -
       
  2661 	InpCloseB,  // ]
       
  2662 	InpOpenB,   // [
       
  2663 	InpUnknown, // =
       
  2664 	InpUnknown, // "
       
  2665 	InpUnknown, // '
       
  2666 	InpUnknown  // unknown
       
  2667     };
       
  2668 
       
  2669     // use some kind of state machine for parsing
       
  2670     static signed char const table[14][10] = {
       
  2671      /*  InpLt  InpGt  InpSlash  InpQMark  InpEMark  InpAmp  InpDash  InpOpenB  InpCloseB  InpUnknown */
       
  2672 	{ Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD1,      ChD  }, // Init
       
  2673 	{ Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD1,      ChD  }, // ChD
       
  2674 	{ Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD2,      ChD  }, // ChD1
       
  2675 	{ Lt,    -1,    ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD2,      ChD  }, // ChD2
       
  2676 	{ Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // Ref (same as Init)
       
  2677 	{ -1,    -1,    Done,     PI,       Em,       -1,     -1,      -1,       -1,        Elem }, // Lt
       
  2678 	{ Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // PI (same as Init)
       
  2679 	{ Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // Elem (same as Init)
       
  2680 	{ -1,    -1,    -1,       -1,       -1,       -1,     Com,     CDS,      -1,        -1   }, // Em
       
  2681 	{ Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // Com (same as Init)
       
  2682 	{ CDS1,  CDS1,  CDS1,     CDS1,     CDS1,     CDS1,   CDS1,    CDS1,     CDS2,      CDS1 }, // CDS
       
  2683 	{ CDS1,  CDS1,  CDS1,     CDS1,     CDS1,     CDS1,   CDS1,    CDS1,     CDS2,      CDS1 }, // CDS1
       
  2684 	{ CDS1,  CDS1,  CDS1,     CDS1,     CDS1,     CDS1,   CDS1,    CDS1,     CDS3,      CDS1 }, // CDS2
       
  2685 	{ CDS1,  Init,  CDS1,     CDS1,     CDS1,     CDS1,   CDS1,    CDS1,     CDS3,      CDS1 }  // CDS3
       
  2686     };
       
  2687     signed char state = Init;
       
  2688     signed char input;
       
  2689     bool parseOk = TRUE;
       
  2690 
       
  2691     while ( TRUE ) {
       
  2692 
       
  2693 	// get input (use lookup-table instead of nested ifs for performance
       
  2694 	// reasons)
       
  2695 	if ( atEnd() ) {
       
  2696 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  2697 	    goto parseError;
       
  2698 	}
       
  2699 	if ( c.row() ) {
       
  2700 	    input = InpUnknown;
       
  2701 	} else {
       
  2702 	    input = mapCLT2FSMChar[ charLookupTable[ c.cell() ] ];
       
  2703 	}
       
  2704 
       
  2705 	// set state according to input
       
  2706 	state = table[state][input];
       
  2707 
       
  2708 	// do some actions according to state
       
  2709 	switch ( state ) {
       
  2710 	    case Init:
       
  2711 		// next character
       
  2712 		next();
       
  2713 		break;
       
  2714 	    case ChD:
       
  2715 		// on first call: clear string
       
  2716 		if ( !charDataRead ) {
       
  2717 		    charDataRead = TRUE;
       
  2718 		    stringClear();
       
  2719 		}
       
  2720 		stringAddC();
       
  2721 		next();
       
  2722 		break;
       
  2723 	    case ChD1:
       
  2724 		// on first call: clear string
       
  2725 		if ( !charDataRead ) {
       
  2726 		    charDataRead = TRUE;
       
  2727 		    stringClear();
       
  2728 		}
       
  2729 		stringAddC();
       
  2730 		next();
       
  2731 		break;
       
  2732 	    case ChD2:
       
  2733 		stringAddC();
       
  2734 		next();
       
  2735 		break;
       
  2736 	    case Ref:
       
  2737 		if ( !charDataRead) {
       
  2738 		    // reference may be CharData; so clear string to be safe
       
  2739 		    stringClear();
       
  2740 		    parseOk = parseReference( charDataRead, InContent );
       
  2741 		} else {
       
  2742 		    bool tmp;
       
  2743 		    parseOk = parseReference( tmp, InContent );
       
  2744 		}
       
  2745 		break;
       
  2746 	    case Lt:
       
  2747 		// call the handler for CharData
       
  2748 		if ( contentHnd ) {
       
  2749 		    if ( charDataRead ) {
       
  2750 			if ( d->reportWhitespaceCharData || !string().simplifyWhiteSpace().isEmpty() ) {
       
  2751 			    if ( !contentHnd->characters( string() ) ) {
       
  2752 				d->error = contentHnd->errorString();
       
  2753 				goto parseError;
       
  2754 			    }
       
  2755 			}
       
  2756 		    }
       
  2757 		}
       
  2758 		charDataRead = FALSE;
       
  2759 		// next character
       
  2760 		next();
       
  2761 		break;
       
  2762 	    case PI:
       
  2763 		parseOk = parsePI();
       
  2764 		break;
       
  2765 	    case Elem:
       
  2766 		parseOk = parseElement();
       
  2767 		break;
       
  2768 	    case Em:
       
  2769 		// next character
       
  2770 		next();
       
  2771 		break;
       
  2772 	    case Com:
       
  2773 		parseOk = parseComment();
       
  2774 		break;
       
  2775 	    case CDS:
       
  2776 		parseOk = parseString( "[CDATA[" );
       
  2777 		break;
       
  2778 	    case CDS1:
       
  2779 		// read one character and add it
       
  2780 		stringAddC();
       
  2781 		next();
       
  2782 		break;
       
  2783 	    case CDS2:
       
  2784 		// skip ']'
       
  2785 		next();
       
  2786 		break;
       
  2787 	    case CDS3:
       
  2788 		// skip ']'...
       
  2789 		next();
       
  2790 		break;
       
  2791 	}
       
  2792 	// no input is read after this
       
  2793 	switch ( state ) {
       
  2794 	    case Ref:
       
  2795 		if ( !parseOk ) {
       
  2796 		    d->error = XMLERR_ERRORPARSINGREFERENCE;
       
  2797 		    goto parseError;
       
  2798 		}
       
  2799 		break;
       
  2800 	    case PI:
       
  2801 		if ( !parseOk ) {
       
  2802 		    d->error = XMLERR_ERRORPARSINGPI;
       
  2803 		    goto parseError;
       
  2804 		}
       
  2805 		// call the handler
       
  2806 		if ( contentHnd ) {
       
  2807 		    if ( !contentHnd->processingInstruction(name(),string()) ) {
       
  2808 			d->error = contentHnd->errorString();
       
  2809 			goto parseError;
       
  2810 		    }
       
  2811 		}
       
  2812 		break;
       
  2813 	    case Elem:
       
  2814 		if ( !parseOk ) {
       
  2815 		    d->error = XMLERR_ERRORPARSINGELEMENT;
       
  2816 		    goto parseError;
       
  2817 		}
       
  2818 		break;
       
  2819 	    case Com:
       
  2820 		if ( !parseOk ) {
       
  2821 		    d->error = XMLERR_ERRORPARSINGCOMMENT;
       
  2822 		    goto parseError;
       
  2823 		}
       
  2824 		if ( lexicalHnd ) {
       
  2825 		    if ( !lexicalHnd->comment( string() ) ) {
       
  2826 			d->error = lexicalHnd->errorString();
       
  2827 			goto parseError;
       
  2828 		    }
       
  2829 		}
       
  2830 		break;
       
  2831 	    case CDS:
       
  2832 		if( !parseOk ) {
       
  2833 		    d->error = XMLERR_CDSECTHEADEREXPECTED;
       
  2834 		    goto parseError;
       
  2835 		}
       
  2836 		// empty string
       
  2837 		stringClear();
       
  2838 		break;
       
  2839 	    case CDS2:
       
  2840 		if (c != ']') {
       
  2841 		    stringAddC( ']' );
       
  2842 		}
       
  2843 		break;
       
  2844 	    case CDS3:
       
  2845 		// test if this skipping was legal
       
  2846 		if        ( c == '>' ) {
       
  2847 		    // the end of the CDSect
       
  2848 		    if ( lexicalHnd ) {
       
  2849 			if ( !lexicalHnd->startCDATA() ) {
       
  2850 			    d->error = lexicalHnd->errorString();
       
  2851 			    goto parseError;
       
  2852 			}
       
  2853 		    }
       
  2854 		    if ( contentHnd ) {
       
  2855 			if ( !contentHnd->characters( string() ) ) {
       
  2856 			    d->error = contentHnd->errorString();
       
  2857 			    goto parseError;
       
  2858 			}
       
  2859 		    }
       
  2860 		    if ( lexicalHnd ) {
       
  2861 			if ( !lexicalHnd->endCDATA() ) {
       
  2862 			    d->error = lexicalHnd->errorString();
       
  2863 			    goto parseError;
       
  2864 			}
       
  2865 		    }
       
  2866 		} else if (c == ']') {
       
  2867 		    // three or more ']'
       
  2868 		    stringAddC( ']' );
       
  2869 		} else {
       
  2870 		    // after ']]' comes another character
       
  2871 		    stringAddC( ']' );
       
  2872 		    stringAddC( ']' );
       
  2873 		}
       
  2874 		break;
       
  2875 	    case Done:
       
  2876 		// call the handler for CharData
       
  2877 		if ( contentHnd ) {
       
  2878 		    if ( charDataRead ) {
       
  2879 			if ( d->reportWhitespaceCharData || !string().simplifyWhiteSpace().isEmpty() ) {
       
  2880 			    if ( !contentHnd->characters( string() ) ) {
       
  2881 				d->error = contentHnd->errorString();
       
  2882 				goto parseError;
       
  2883 			    }
       
  2884 			}
       
  2885 		    }
       
  2886 		}
       
  2887 		// Done
       
  2888 		return TRUE;
       
  2889 	    case -1:
       
  2890 		// Error
       
  2891 		d->error = XMLERR_ERRORPARSINGCONTENT;
       
  2892 		goto parseError;
       
  2893 	}
       
  2894 
       
  2895     }
       
  2896 
       
  2897     return TRUE;
       
  2898 
       
  2899 parseError:
       
  2900     reportParseError();
       
  2901     return FALSE;
       
  2902 }
       
  2903 
       
  2904 /*!
       
  2905   Parse Misc [27].
       
  2906 */
       
  2907 bool QXmlSimpleReader::parseMisc()
       
  2908 {
       
  2909     const signed char Init             = 0;
       
  2910     const signed char Lt               = 1; // '<' was read
       
  2911     const signed char Comment          = 2; // read comment
       
  2912     const signed char eatWS            = 3; // eat whitespaces
       
  2913     const signed char PI               = 4; // read PI
       
  2914     const signed char Comment2         = 5; // read comment
       
  2915 
       
  2916     const signed char InpWs            = 0; // S
       
  2917     const signed char InpLt            = 1; // <
       
  2918     const signed char InpQm            = 2; // ?
       
  2919     const signed char InpEm            = 3; // !
       
  2920     const signed char InpUnknown       = 4;
       
  2921 
       
  2922     // use some kind of state machine for parsing
       
  2923     static signed char table[3][5] = {
       
  2924      /*  InpWs   InpLt  InpQm  InpEm     InpUnknown */
       
  2925 	{ eatWS,  Lt,    -1,    -1,       -1        }, // Init
       
  2926 	{ -1,     -1,    PI,    Comment,  -1        }, // Lt
       
  2927 	{ -1,     -1,    -1,    -1,       Comment2  }  // Comment
       
  2928     };
       
  2929     signed char state = Init;
       
  2930     signed char input;
       
  2931     bool parseOk = TRUE;
       
  2932 
       
  2933     while ( TRUE ) {
       
  2934 
       
  2935 	// get input
       
  2936 	if ( atEnd() ) {
       
  2937 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  2938 	    goto parseError;
       
  2939 	}
       
  2940 	if        ( is_S(c) ) {
       
  2941 	    input = InpWs;
       
  2942 	} else if ( c == '<' ) {
       
  2943 	    input = InpLt;
       
  2944 	} else if ( c == '?' ) {
       
  2945 	    input = InpQm;
       
  2946 	} else if ( c == '!' ) {
       
  2947 	    input = InpEm;
       
  2948 	} else {
       
  2949 	    input = InpUnknown;
       
  2950 	}
       
  2951 
       
  2952 	// set state according to input
       
  2953 	state = table[state][input];
       
  2954 
       
  2955 	// do some actions according to state
       
  2956 	switch ( state ) {
       
  2957 	    case eatWS:
       
  2958 		eat_ws();
       
  2959 		break;
       
  2960 	    case Lt:
       
  2961 		next();
       
  2962 		break;
       
  2963 	    case PI:
       
  2964 		parseOk = parsePI();
       
  2965 		break;
       
  2966 	    case Comment:
       
  2967 		next();
       
  2968 		break;
       
  2969 	    case Comment2:
       
  2970 		parseOk = parseComment();
       
  2971 		break;
       
  2972 	}
       
  2973 	// no input is read after this
       
  2974 	switch ( state ) {
       
  2975 	    case eatWS:
       
  2976 		return TRUE;
       
  2977 	    case PI:
       
  2978 		if ( !parseOk ) {
       
  2979 		    d->error = XMLERR_ERRORPARSINGPI;
       
  2980 		    goto parseError;
       
  2981 		}
       
  2982 		if ( contentHnd ) {
       
  2983 		    if ( !contentHnd->processingInstruction(name(),string()) ) {
       
  2984 			d->error = contentHnd->errorString();
       
  2985 			goto parseError;
       
  2986 		    }
       
  2987 		}
       
  2988 		return TRUE;
       
  2989 	    case Comment2:
       
  2990 		if ( !parseOk ) {
       
  2991 		    d->error = XMLERR_ERRORPARSINGCOMMENT;
       
  2992 		    goto parseError;
       
  2993 		}
       
  2994 		if ( lexicalHnd ) {
       
  2995 		    if ( !lexicalHnd->comment( string() ) ) {
       
  2996 			d->error = lexicalHnd->errorString();
       
  2997 			goto parseError;
       
  2998 		    }
       
  2999 		}
       
  3000 		return TRUE;
       
  3001 	    case -1:
       
  3002 		// Error
       
  3003 		d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  3004 		goto parseError;
       
  3005 	}
       
  3006 
       
  3007     }
       
  3008 
       
  3009     return TRUE;
       
  3010 
       
  3011 parseError:
       
  3012     reportParseError();
       
  3013     return FALSE;
       
  3014 }
       
  3015 
       
  3016 /*!
       
  3017   Parse a processing instruction [16].
       
  3018 
       
  3019   If xmldec is TRUE, it tries to parse a PI or a XML declaration [23].
       
  3020 
       
  3021   Precondition: the beginning '<' of the PI is already read and the head stand
       
  3022   on the '?' of '<?'.
       
  3023 
       
  3024   If this funktion was successful, the head-position is on the first
       
  3025   character after the PI.
       
  3026 */
       
  3027 bool QXmlSimpleReader::parsePI( bool xmldecl )
       
  3028 {
       
  3029     const signed char Init             =  0;
       
  3030     const signed char QmI              =  1; // ? was read
       
  3031     const signed char Name             =  2; // read Name
       
  3032     const signed char XMLDecl          =  3; // read XMLDecl
       
  3033     const signed char Ws1              =  4; // eat ws after "xml" of XMLDecl
       
  3034     const signed char PI               =  5; // read PI
       
  3035     const signed char Ws2              =  6; // eat ws after Name of PI
       
  3036     const signed char Version          =  7; // read versionInfo
       
  3037     const signed char Ws3              =  8; // eat ws after versionInfo
       
  3038     const signed char EorSD            =  9; // read EDecl or SDDecl
       
  3039     const signed char Ws4              = 10; // eat ws after EDecl or SDDecl
       
  3040     const signed char SD               = 11; // read SDDecl
       
  3041     const signed char Ws5              = 12; // eat ws after SDDecl
       
  3042     const signed char ADone            = 13; // almost done
       
  3043     const signed char Char             = 14; // Char was read
       
  3044     const signed char Qm               = 15; // Qm was read
       
  3045     const signed char Done             = 16; // finished reading content
       
  3046 
       
  3047     const signed char InpWs            = 0; // whitespace
       
  3048     const signed char InpNameBe        = 1; // is_nameBeginning()
       
  3049     const signed char InpGt            = 2; // >
       
  3050     const signed char InpQm            = 3; // ?
       
  3051     const signed char InpUnknown       = 4;
       
  3052 
       
  3053     // use some kind of state machine for parsing
       
  3054     static signed char table[16][5] = {
       
  3055      /*  InpWs,  InpNameBe  InpGt  InpQm   InpUnknown  */
       
  3056 	{ -1,     -1,        -1,    QmI,    -1     }, // Init
       
  3057 	{ -1,     Name,      -1,    -1,     -1     }, // QmI
       
  3058 	{ -1,     -1,        -1,    -1,     -1     }, // Name (this state is left not through input)
       
  3059 	{ Ws1,    -1,        -1,    -1,     -1     }, // XMLDecl
       
  3060 	{ -1,     Version,   -1,    -1,     -1     }, // Ws1
       
  3061 	{ Ws2,    -1,        -1,    Qm,     -1     }, // PI
       
  3062 	{ Char,   Char,      Char,  Qm,     Char   }, // Ws2
       
  3063 	{ Ws3,    -1,        -1,    ADone,  -1     }, // Version
       
  3064 	{ -1,     EorSD,     -1,    ADone,  -1     }, // Ws3
       
  3065 	{ Ws4,    -1,        -1,    ADone,  -1     }, // EorSD
       
  3066 	{ -1,     SD,        -1,    ADone,  -1     }, // Ws4
       
  3067 	{ Ws5,    -1,        -1,    ADone,  -1     }, // SD
       
  3068 	{ -1,     -1,        -1,    ADone,  -1     }, // Ws5
       
  3069 	{ -1,     -1,        Done,  -1,     -1     }, // ADone
       
  3070 	{ Char,   Char,      Char,  Qm,     Char   }, // Char
       
  3071 	{ Char,   Char,      Done,  Qm,     Char   }, // Qm
       
  3072     };
       
  3073     signed char state = Init;
       
  3074     signed char input;
       
  3075     bool parseOk = TRUE;
       
  3076 
       
  3077     while ( TRUE ) {
       
  3078 
       
  3079 	// get input
       
  3080 	if ( atEnd() ) {
       
  3081 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  3082 	    goto parseError;
       
  3083 	}
       
  3084 	if        ( is_S(c) ) {
       
  3085 	    input = InpWs;
       
  3086 	} else if ( is_NameBeginning(c) ) {
       
  3087 	    input = InpNameBe;
       
  3088 	} else if ( c == '>' ) {
       
  3089 	    input = InpGt;
       
  3090 	} else if ( c == '?' ) {
       
  3091 	    input = InpQm;
       
  3092 	} else {
       
  3093 	    input = InpUnknown;
       
  3094 	}
       
  3095 
       
  3096 	// set state according to input
       
  3097 	state = table[state][input];
       
  3098 
       
  3099 	// do some actions according to state
       
  3100 	switch ( state ) {
       
  3101 	    case QmI:
       
  3102 		next();
       
  3103 		break;
       
  3104 	    case Name:
       
  3105 		parseOk = parseName();
       
  3106 		break;
       
  3107 	    case Ws1:
       
  3108 	    case Ws2:
       
  3109 	    case Ws3:
       
  3110 	    case Ws4:
       
  3111 	    case Ws5:
       
  3112 		eat_ws();
       
  3113 		break;
       
  3114 	    case Version:
       
  3115 		parseOk = parseAttribute();
       
  3116 		break;
       
  3117 	    case EorSD:
       
  3118 		parseOk = parseAttribute();
       
  3119 		break;
       
  3120 	    case SD:
       
  3121 		// get the SDDecl (syntax like an attribute)
       
  3122 		if ( d->standalone != QXmlSimpleReaderPrivate::Unknown ) {
       
  3123 		    // already parsed the standalone declaration
       
  3124 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  3125 		    goto parseError;
       
  3126 		}
       
  3127 		parseOk = parseAttribute();
       
  3128 		break;
       
  3129 	    case ADone:
       
  3130 		next();
       
  3131 		break;
       
  3132 	    case Char:
       
  3133 		stringAddC();
       
  3134 		next();
       
  3135 		break;
       
  3136 	    case Qm:
       
  3137 		// skip the '?'
       
  3138 		next();
       
  3139 		break;
       
  3140 	    case Done:
       
  3141 		next();
       
  3142 		break;
       
  3143 	}
       
  3144 	// no input is read after this
       
  3145 	switch ( state ) {
       
  3146 	    case Name:
       
  3147 		if ( !parseOk ) {
       
  3148 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  3149 		    goto parseError;
       
  3150 		}
       
  3151 		// test what name was read and determine the next state
       
  3152 		// (not very beautiful, I admit)
       
  3153 		if ( name().lower() == "xml" ) {
       
  3154 		    if ( xmldecl && name()=="xml" ) {
       
  3155 			state = XMLDecl;
       
  3156 		    } else {
       
  3157 			d->error = XMLERR_INVALIDNAMEFORPI;
       
  3158 			goto parseError;
       
  3159 		    }
       
  3160 		} else {
       
  3161 		    state = PI;
       
  3162 		    stringClear();
       
  3163 		}
       
  3164 		break;
       
  3165 	    case Version:
       
  3166 		// get version (syntax like an attribute)
       
  3167 		if ( !parseOk ) {
       
  3168 		    d->error = XMLERR_VERSIONEXPECTED;
       
  3169 		    goto parseError;
       
  3170 		}
       
  3171 		if ( name() != "version" ) {
       
  3172 		    d->error = XMLERR_VERSIONEXPECTED;
       
  3173 		    goto parseError;
       
  3174 		}
       
  3175 		d->xmlVersion = string();
       
  3176 		break;
       
  3177 	    case EorSD:
       
  3178 		// get the EDecl or SDDecl (syntax like an attribute)
       
  3179 		if ( !parseOk ) {
       
  3180 		    d->error = XMLERR_EDECLORSDDECLEXPECTED;
       
  3181 		    goto parseError;
       
  3182 		}
       
  3183 		if        ( name() == "standalone" ) {
       
  3184 		    if ( string()=="yes" ) {
       
  3185 			d->standalone = QXmlSimpleReaderPrivate::Yes;
       
  3186 		    } else if ( string()=="no" ) {
       
  3187 			d->standalone = QXmlSimpleReaderPrivate::No;
       
  3188 		    } else {
       
  3189 			d->error = XMLERR_WRONGVALUEFORSDECL;
       
  3190 			goto parseError;
       
  3191 		    }
       
  3192 		} else if ( name() == "encoding" ) {
       
  3193 		    d->encoding = string();
       
  3194 		} else {
       
  3195 		    d->error = XMLERR_EDECLORSDDECLEXPECTED;
       
  3196 		    goto parseError;
       
  3197 		}
       
  3198 		break;
       
  3199 	    case SD:
       
  3200 		if ( !parseOk ) {
       
  3201 		    d->error = XMLERR_SDDECLEXPECTED;
       
  3202 		    goto parseError;
       
  3203 		}
       
  3204 		if ( name() != "standalone" ) {
       
  3205 		    d->error = XMLERR_SDDECLEXPECTED;
       
  3206 		    goto parseError;
       
  3207 		}
       
  3208 		if ( string()=="yes" ) {
       
  3209 		    d->standalone = QXmlSimpleReaderPrivate::Yes;
       
  3210 		} else if ( string()=="no" ) {
       
  3211 		    d->standalone = QXmlSimpleReaderPrivate::No;
       
  3212 		} else {
       
  3213 		    d->error = XMLERR_WRONGVALUEFORSDECL;
       
  3214 		    goto parseError;
       
  3215 		}
       
  3216 		break;
       
  3217 	    case Qm:
       
  3218 		// test if the skipping was legal
       
  3219 		if ( c != '>' ) {
       
  3220 		    stringAddC( '?' );
       
  3221 		}
       
  3222 		break;
       
  3223 	    case Done:
       
  3224 		return TRUE;
       
  3225 	    case -1:
       
  3226 		// Error
       
  3227 		d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  3228 		goto parseError;
       
  3229 	}
       
  3230 
       
  3231     }
       
  3232 
       
  3233     return TRUE;
       
  3234 
       
  3235 parseError:
       
  3236     reportParseError();
       
  3237     return FALSE;
       
  3238 }
       
  3239 
       
  3240 /*!
       
  3241   Parse a document type definition (doctypedecl [28]).
       
  3242 
       
  3243   Precondition: the beginning '<!' of the doctype is already read the head
       
  3244   stands on the 'D' of '<!DOCTYPE'.
       
  3245 
       
  3246   If this funktion was successful, the head-position is on the first
       
  3247   character after the document type definition.
       
  3248 */
       
  3249 bool QXmlSimpleReader::parseDoctype()
       
  3250 {
       
  3251     // some init-stuff
       
  3252     d->systemId = QString::null;
       
  3253     d->publicId = QString::null;
       
  3254 
       
  3255     const signed char Init             =  0;
       
  3256     const signed char Doctype          =  1; // read the doctype
       
  3257     const signed char Ws1              =  2; // eat_ws
       
  3258     const signed char Doctype2         =  3; // read the doctype, part 2
       
  3259     const signed char Ws2              =  4; // eat_ws
       
  3260     const signed char Sys              =  5; // read SYSTEM
       
  3261     const signed char Ws3              =  6; // eat_ws
       
  3262     const signed char MP               =  7; // markupdecl or PEReference
       
  3263     const signed char PER              =  8; // PERReference
       
  3264     const signed char Mup              =  9; // markupdecl
       
  3265     const signed char Ws4              = 10; // eat_ws
       
  3266     const signed char MPE              = 11; // end of markupdecl or PEReference
       
  3267     const signed char Done             = 12;
       
  3268 
       
  3269     const signed char InpWs            = 0;
       
  3270     const signed char InpD             = 1; // 'D'
       
  3271     const signed char InpS             = 2; // 'S' or 'P'
       
  3272     const signed char InpOB            = 3; // [
       
  3273     const signed char InpCB            = 4; // ]
       
  3274     const signed char InpPer           = 5; // %
       
  3275     const signed char InpGt            = 6; // >
       
  3276     const signed char InpUnknown       = 7;
       
  3277 
       
  3278     // use some kind of state machine for parsing
       
  3279     static signed char table[12][8] = {
       
  3280      /*  InpWs,  InpD       InpS       InpOB  InpCB  InpPer InpGt  InpUnknown */
       
  3281 	{ -1,     Doctype,   -1,        -1,    -1,    -1,    -1,    -1        }, // Init
       
  3282 	{ Ws1,    Doctype2,  Doctype2,  -1,    -1,    -1,    -1,    Doctype2  }, // Doctype
       
  3283 	{ -1,     Doctype2,  Doctype2,  -1,    -1,    -1,    -1,    Doctype2  }, // Ws1
       
  3284 	{ Ws2,    -1,        Sys,       MP,    -1,    -1,    Done,  -1        }, // Doctype2
       
  3285 	{ -1,     -1,        Sys,       MP,    -1,    -1,    Done,  -1        }, // Ws2
       
  3286 	{ Ws3,    -1,        -1,        MP,    -1,    -1,    Done,  -1        }, // Sys
       
  3287 	{ -1,     -1,        -1,        MP,    -1,    -1,    Done,  -1        }, // Ws3
       
  3288 	{ -1,     -1,        -1,        -1,    MPE,   PER,   -1,    Mup       }, // MP
       
  3289 	{ Ws4,    -1,        -1,        -1,    MPE,   PER,   -1,    Mup       }, // PER
       
  3290 	{ Ws4,    -1,        -1,        -1,    MPE,   PER,   -1,    Mup       }, // Mup
       
  3291 	{ -1,     -1,        -1,        -1,    MPE,   PER,   -1,    Mup       }, // Ws4
       
  3292 	{ -1,     -1,        -1,        -1,    -1,    -1,    Done,  -1        }  // MPE
       
  3293     };
       
  3294     signed char state = Init;
       
  3295     signed char input;
       
  3296     bool parseOk = TRUE;
       
  3297 
       
  3298     while ( TRUE ) {
       
  3299 
       
  3300 	// get input
       
  3301 	if ( atEnd() ) {
       
  3302 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  3303 	    goto parseError;
       
  3304 	}
       
  3305 	if        ( is_S(c) ) {
       
  3306 	    input = InpWs;
       
  3307 	} else if ( c == 'D' ) {
       
  3308 	    input = InpD;
       
  3309 	} else if ( c == 'S' ) {
       
  3310 	    input = InpS;
       
  3311 	} else if ( c == 'P' ) {
       
  3312 	    input = InpS;
       
  3313 	} else if ( c == '[' ) {
       
  3314 	    input = InpOB;
       
  3315 	} else if ( c == ']' ) {
       
  3316 	    input = InpCB;
       
  3317 	} else if ( c == '%' ) {
       
  3318 	    input = InpPer;
       
  3319 	} else if ( c == '>' ) {
       
  3320 	    input = InpGt;
       
  3321 	} else {
       
  3322 	    input = InpUnknown;
       
  3323 	}
       
  3324 
       
  3325 	// set state according to input
       
  3326 	state = table[state][input];
       
  3327 
       
  3328 	// do some actions according to state
       
  3329 	switch ( state ) {
       
  3330 	    case Doctype:
       
  3331 		parseOk = parseString( "DOCTYPE" );
       
  3332 		break;
       
  3333 	    case Ws1:
       
  3334 	    case Ws2:
       
  3335 	    case Ws3:
       
  3336 	    case Ws4:
       
  3337 		eat_ws();
       
  3338 		break;
       
  3339 	    case Doctype2:
       
  3340 		parseName();
       
  3341 		break;
       
  3342 	    case Sys:
       
  3343 		parseOk = parseExternalID();
       
  3344 		break;
       
  3345 	    case MP:
       
  3346 		next_eat_ws();
       
  3347 		break;
       
  3348 	    case PER:
       
  3349 		parseOk = parsePEReference( InDTD );
       
  3350 		break;
       
  3351 	    case Mup:
       
  3352 		parseOk = parseMarkupdecl();
       
  3353 		break;
       
  3354 	    case MPE:
       
  3355 		next_eat_ws();
       
  3356 		break;
       
  3357 	    case Done:
       
  3358 		if ( lexicalHnd ) {
       
  3359 		    if ( !lexicalHnd->endDTD() ) {
       
  3360 			d->error = lexicalHnd->errorString();
       
  3361 			goto parseError;
       
  3362 		    }
       
  3363 		}
       
  3364 		next();
       
  3365 		break;
       
  3366 	}
       
  3367 	// no input is read after this
       
  3368 	switch ( state ) {
       
  3369 	    case Doctype:
       
  3370 		if ( !parseOk ) {
       
  3371 		    d->error = XMLERR_ERRORPARSINGDOCTYPE;
       
  3372 		    goto parseError;
       
  3373 		}
       
  3374 		if ( !is_S(c) ) {
       
  3375 		    d->error = XMLERR_ERRORPARSINGDOCTYPE;
       
  3376 		    goto parseError;
       
  3377 		}
       
  3378 		break;
       
  3379 	    case Doctype2:
       
  3380 		d->doctype = name();
       
  3381 		if ( lexicalHnd ) {
       
  3382 		    if ( !lexicalHnd->startDTD( d->doctype, d->publicId, d->systemId ) ) {
       
  3383 			d->error = lexicalHnd->errorString();
       
  3384 			goto parseError;
       
  3385 		    }
       
  3386 		}
       
  3387 		break;
       
  3388 	    case Sys:
       
  3389 		if ( !parseOk ) {
       
  3390 		    d->error = XMLERR_ERRORPARSINGDOCTYPE;
       
  3391 		    goto parseError;
       
  3392 		}
       
  3393 		break;
       
  3394 	    case PER:
       
  3395 		if ( !parseOk ) {
       
  3396 		    d->error = XMLERR_ERRORPARSINGDOCTYPE;
       
  3397 		    goto parseError;
       
  3398 		}
       
  3399 		break;
       
  3400 	    case Mup:
       
  3401 		if ( !parseOk ) {
       
  3402 		    d->error = XMLERR_ERRORPARSINGDOCTYPE;
       
  3403 		    goto parseError;
       
  3404 		}
       
  3405 		break;
       
  3406 	    case Done:
       
  3407 		return TRUE;
       
  3408 	    case -1:
       
  3409 		// Error
       
  3410 		d->error = XMLERR_ERRORPARSINGDOCTYPE;
       
  3411 		goto parseError;
       
  3412 	}
       
  3413 
       
  3414     }
       
  3415 
       
  3416     return TRUE;
       
  3417 
       
  3418 parseError:
       
  3419     reportParseError();
       
  3420     return FALSE;
       
  3421 }
       
  3422 
       
  3423 /*!
       
  3424   Parse a ExternalID [75].
       
  3425 
       
  3426   If allowPublicID is TRUE parse ExternalID [75] or PublicID [83].
       
  3427 */
       
  3428 bool QXmlSimpleReader::parseExternalID( bool allowPublicID )
       
  3429 {
       
  3430     // some init-stuff
       
  3431     d->systemId = QString::null;
       
  3432     d->publicId = QString::null;
       
  3433 
       
  3434     const signed char Init             =  0;
       
  3435     const signed char Sys              =  1; // parse 'SYSTEM'
       
  3436     const signed char SysWS            =  2; // parse the whitespace after 'SYSTEM'
       
  3437     const signed char SysSQ            =  3; // parse SystemLiteral with '
       
  3438     const signed char SysSQ2           =  4; // parse SystemLiteral with '
       
  3439     const signed char SysDQ            =  5; // parse SystemLiteral with "
       
  3440     const signed char SysDQ2           =  6; // parse SystemLiteral with "
       
  3441     const signed char Pub              =  7; // parse 'PUBLIC'
       
  3442     const signed char PubWS            =  8; // parse the whitespace after 'PUBLIC'
       
  3443     const signed char PubSQ            =  9; // parse PubidLiteral with '
       
  3444     const signed char PubSQ2           = 10; // parse PubidLiteral with '
       
  3445     const signed char PubDQ            = 11; // parse PubidLiteral with "
       
  3446     const signed char PubDQ2           = 12; // parse PubidLiteral with "
       
  3447     const signed char PubE             = 13; // finished parsing the PubidLiteral
       
  3448     const signed char PubWS2           = 14; // parse the whitespace after the PubidLiteral
       
  3449     const signed char PDone            = 15; // done if allowPublicID is TRUE
       
  3450     const signed char Done             = 16;
       
  3451 
       
  3452     const signed char InpSQ            = 0; // '
       
  3453     const signed char InpDQ            = 1; // "
       
  3454     const signed char InpS             = 2; // S
       
  3455     const signed char InpP             = 3; // P
       
  3456     const signed char InpWs            = 4; // white space
       
  3457     const signed char InpUnknown       = 5;
       
  3458 
       
  3459     // use some kind of state machine for parsing
       
  3460     static signed char table[15][6] = {
       
  3461      /*  InpSQ    InpDQ    InpS     InpP     InpWs     InpUnknown */
       
  3462 	{ -1,      -1,      Sys,     Pub,     -1,       -1      }, // Init
       
  3463 	{ -1,      -1,      -1,      -1,      SysWS,    -1      }, // Sys
       
  3464 	{ SysSQ,   SysDQ,   -1,      -1,      -1,       -1      }, // SysWS
       
  3465 	{ Done,    SysSQ2,  SysSQ2,  SysSQ2,  SysSQ2,   SysSQ2  }, // SysSQ
       
  3466 	{ Done,    SysSQ2,  SysSQ2,  SysSQ2,  SysSQ2,   SysSQ2  }, // SysSQ2
       
  3467 	{ SysDQ2,  Done,    SysDQ2,  SysDQ2,  SysDQ2,   SysDQ2  }, // SysDQ
       
  3468 	{ SysDQ2,  Done,    SysDQ2,  SysDQ2,  SysDQ2,   SysDQ2  }, // SysDQ2
       
  3469 	{ -1,      -1,      -1,      -1,      PubWS,    -1      }, // Pub
       
  3470 	{ PubSQ,   PubDQ,   -1,      -1,      -1,       -1      }, // PubWS
       
  3471 	{ PubE,    -1,      PubSQ2,  PubSQ2,  PubSQ2,   PubSQ2  }, // PubSQ
       
  3472 	{ PubE,    -1,      PubSQ2,  PubSQ2,  PubSQ2,   PubSQ2  }, // PubSQ2
       
  3473 	{ -1,      PubE,    PubDQ2,  PubDQ2,  PubDQ2,   PubDQ2  }, // PubDQ
       
  3474 	{ -1,      PubE,    PubDQ2,  PubDQ2,  PubDQ2,   PubDQ2  }, // PubDQ2
       
  3475 	{ PDone,   PDone,   PDone,   PDone,   PubWS2,   PDone   }, // PubE
       
  3476 	{ SysSQ,   SysDQ,   PDone,   PDone,   PDone,    PDone   }  // PubWS2
       
  3477     };
       
  3478     signed char state = Init;
       
  3479     signed char input;
       
  3480     bool parseOk = TRUE;
       
  3481 
       
  3482     while ( TRUE ) {
       
  3483 
       
  3484 	// get input
       
  3485 	if ( atEnd() ) {
       
  3486 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  3487 	    goto parseError;
       
  3488 	}
       
  3489 	if        ( is_S(c) ) {
       
  3490 	    input = InpWs;
       
  3491 	} else if ( c == '\'' ) {
       
  3492 	    input = InpSQ;
       
  3493 	} else if ( c == '"' ) {
       
  3494 	    input = InpDQ;
       
  3495 	} else if ( c == 'S' ) {
       
  3496 	    input = InpS;
       
  3497 	} else if ( c == 'P' ) {
       
  3498 	    input = InpP;
       
  3499 	} else {
       
  3500 	    input = InpUnknown;
       
  3501 	}
       
  3502 
       
  3503 	// set state according to input
       
  3504 	state = table[state][input];
       
  3505 
       
  3506 	// do some actions according to state
       
  3507 	switch ( state ) {
       
  3508 	    case Sys:
       
  3509 		parseOk = parseString( "SYSTEM" );
       
  3510 		break;
       
  3511 	    case SysWS:
       
  3512 		eat_ws();
       
  3513 		break;
       
  3514 	    case SysSQ:
       
  3515 	    case SysDQ:
       
  3516 		stringClear();
       
  3517 		next();
       
  3518 		break;
       
  3519 	    case SysSQ2:
       
  3520 	    case SysDQ2:
       
  3521 		stringAddC();
       
  3522 		next();
       
  3523 		break;
       
  3524 	    case Pub:
       
  3525 		parseOk = parseString( "PUBLIC" );
       
  3526 		break;
       
  3527 	    case PubWS:
       
  3528 		eat_ws();
       
  3529 		break;
       
  3530 	    case PubSQ:
       
  3531 	    case PubDQ:
       
  3532 		stringClear();
       
  3533 		next();
       
  3534 		break;
       
  3535 	    case PubSQ2:
       
  3536 	    case PubDQ2:
       
  3537 		stringAddC();
       
  3538 		next();
       
  3539 		break;
       
  3540 	    case PubE:
       
  3541 		next();
       
  3542 		break;
       
  3543 	    case PubWS2:
       
  3544 		d->publicId = string();
       
  3545 		eat_ws();
       
  3546 		break;
       
  3547 	    case Done:
       
  3548 		d->systemId = string();
       
  3549 		next();
       
  3550 		break;
       
  3551 	}
       
  3552 	// no input is read after this
       
  3553 	switch ( state ) {
       
  3554 	    case Sys:
       
  3555 		if( !parseOk ) {
       
  3556 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  3557 		    goto parseError;
       
  3558 		}
       
  3559 		break;
       
  3560 	    case Pub:
       
  3561 		if( !parseOk ) {
       
  3562 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  3563 		    goto parseError;
       
  3564 		}
       
  3565 		break;
       
  3566 	    case PDone:
       
  3567 		if ( allowPublicID ) {
       
  3568 		    d->publicId = string();
       
  3569 		    return TRUE;
       
  3570 		} else {
       
  3571 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  3572 		    goto parseError;
       
  3573 		}
       
  3574 		break;
       
  3575 	    case Done:
       
  3576 		return TRUE;
       
  3577 	    case -1:
       
  3578 		// Error
       
  3579 		d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  3580 		goto parseError;
       
  3581 	}
       
  3582 
       
  3583     }
       
  3584 
       
  3585     return TRUE;
       
  3586 
       
  3587 parseError:
       
  3588     reportParseError();
       
  3589     return FALSE;
       
  3590 }
       
  3591 
       
  3592 /*!
       
  3593   Parse a markupdecl [29].
       
  3594 */
       
  3595 bool QXmlSimpleReader::parseMarkupdecl()
       
  3596 {
       
  3597     const signed char Init             = 0;
       
  3598     const signed char Lt               = 1; // < was read
       
  3599     const signed char Em               = 2; // ! was read
       
  3600     const signed char CE               = 3; // E was read
       
  3601     const signed char Qm               = 4; // ? was read
       
  3602     const signed char Dash             = 5; // - was read
       
  3603     const signed char CA               = 6; // A was read
       
  3604     const signed char CEL              = 7; // EL was read
       
  3605     const signed char CEN              = 8; // EN was read
       
  3606     const signed char CN               = 9; // N was read
       
  3607     const signed char Done             = 10;
       
  3608 
       
  3609     const signed char InpLt            = 0; // <
       
  3610     const signed char InpQm            = 1; // ?
       
  3611     const signed char InpEm            = 2; // !
       
  3612     const signed char InpDash          = 3; // -
       
  3613     const signed char InpA             = 4; // A
       
  3614     const signed char InpE             = 5; // E
       
  3615     const signed char InpL             = 6; // L
       
  3616     const signed char InpN             = 7; // N
       
  3617     const signed char InpUnknown       = 8;
       
  3618 
       
  3619     // use some kind of state machine for parsing
       
  3620     static signed char table[4][9] = {
       
  3621      /*  InpLt  InpQm  InpEm  InpDash  InpA   InpE   InpL   InpN   InpUnknown */
       
  3622 	{ Lt,    -1,    -1,    -1,      -1,    -1,    -1,    -1,    -1     }, // Init
       
  3623 	{ -1,    Qm,    Em,    -1,      -1,    -1,    -1,    -1,    -1     }, // Lt
       
  3624 	{ -1,    -1,    -1,    Dash,    CA,    CE,    -1,    CN,    -1     }, // Em
       
  3625 	{ -1,    -1,    -1,    -1,      -1,    -1,    CEL,   CEN,   -1     }  // CE
       
  3626     };
       
  3627     signed char state = Init;
       
  3628     signed char input;
       
  3629     bool parseOk = TRUE;
       
  3630 
       
  3631     while ( TRUE ) {
       
  3632 
       
  3633 	// get input
       
  3634 	if ( atEnd() ) {
       
  3635 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  3636 	    goto parseError;
       
  3637 	}
       
  3638 	if        ( c == '<' ) {
       
  3639 	    input = InpLt;
       
  3640 	} else if ( c == '?' ) {
       
  3641 	    input = InpQm;
       
  3642 	} else if ( c == '!' ) {
       
  3643 	    input = InpEm;
       
  3644 	} else if ( c == '-' ) {
       
  3645 	    input = InpDash;
       
  3646 	} else if ( c == 'A' ) {
       
  3647 	    input = InpA;
       
  3648 	} else if ( c == 'E' ) {
       
  3649 	    input = InpE;
       
  3650 	} else if ( c == 'L' ) {
       
  3651 	    input = InpL;
       
  3652 	} else if ( c == 'N' ) {
       
  3653 	    input = InpN;
       
  3654 	} else {
       
  3655 	    input = InpUnknown;
       
  3656 	}
       
  3657 
       
  3658 	// set state according to input
       
  3659 	state = table[state][input];
       
  3660 
       
  3661 	// do some actions according to state
       
  3662 	switch ( state ) {
       
  3663 	    case Lt:
       
  3664 		next();
       
  3665 		break;
       
  3666 	    case Em:
       
  3667 		next();
       
  3668 		break;
       
  3669 	    case CE:
       
  3670 		next();
       
  3671 		break;
       
  3672 	    case Qm:
       
  3673 		parseOk = parsePI();
       
  3674 		break;
       
  3675 	    case Dash:
       
  3676 		parseOk = parseComment();
       
  3677 		break;
       
  3678 	    case CA:
       
  3679 		parseOk = parseAttlistDecl();
       
  3680 		break;
       
  3681 	    case CEL:
       
  3682 		parseOk = parseElementDecl();
       
  3683 		break;
       
  3684 	    case CEN:
       
  3685 		parseOk = parseEntityDecl();
       
  3686 		break;
       
  3687 	    case CN:
       
  3688 		parseOk = parseNotationDecl();
       
  3689 		break;
       
  3690 	}
       
  3691 	// no input is read after this
       
  3692 	switch ( state ) {
       
  3693 	    case Qm:
       
  3694 		if ( !parseOk ) {
       
  3695 		    d->error = XMLERR_ERRORPARSINGPI;
       
  3696 		    goto parseError;
       
  3697 		}
       
  3698 		if ( contentHnd ) {
       
  3699 		    if ( !contentHnd->processingInstruction(name(),string()) ) {
       
  3700 			d->error = contentHnd->errorString();
       
  3701 			goto parseError;
       
  3702 		    }
       
  3703 		}
       
  3704 		return TRUE;
       
  3705 	    case Dash:
       
  3706 		if ( !parseOk ) {
       
  3707 		    d->error = XMLERR_ERRORPARSINGCOMMENT;
       
  3708 		    goto parseError;
       
  3709 		}
       
  3710 		if ( lexicalHnd ) {
       
  3711 		    if ( !lexicalHnd->comment( string() ) ) {
       
  3712 			d->error = lexicalHnd->errorString();
       
  3713 			goto parseError;
       
  3714 		    }
       
  3715 		}
       
  3716 		return TRUE;
       
  3717 	    case CA:
       
  3718 		if ( !parseOk ) {
       
  3719 		    d->error = XMLERR_ERRORPARSINGATTLISTDECL;
       
  3720 		    goto parseError;
       
  3721 		}
       
  3722 		return TRUE;
       
  3723 	    case CEL:
       
  3724 		if ( !parseOk ) {
       
  3725 		    d->error = XMLERR_ERRORPARSINGELEMENTDECL;
       
  3726 		    goto parseError;
       
  3727 		}
       
  3728 		return TRUE;
       
  3729 	    case CEN:
       
  3730 		if ( !parseOk ) {
       
  3731 		    d->error = XMLERR_ERRORPARSINGENTITYDECL;
       
  3732 		    goto parseError;
       
  3733 		}
       
  3734 		return TRUE;
       
  3735 	    case CN:
       
  3736 		if ( !parseOk ) {
       
  3737 		    d->error = XMLERR_ERRORPARSINGNOTATIONDECL;
       
  3738 		    goto parseError;
       
  3739 		}
       
  3740 		return TRUE;
       
  3741 	    case Done:
       
  3742 		return TRUE;
       
  3743 	    case -1:
       
  3744 		// Error
       
  3745 		d->error = XMLERR_LETTEREXPECTED;
       
  3746 		goto parseError;
       
  3747 	}
       
  3748 
       
  3749     }
       
  3750 
       
  3751     return TRUE;
       
  3752 
       
  3753 parseError:
       
  3754     reportParseError();
       
  3755     return FALSE;
       
  3756 }
       
  3757 
       
  3758 /*!
       
  3759   Parse a PEReference [69]
       
  3760 */
       
  3761 bool QXmlSimpleReader::parsePEReference( EntityRecognitionContext context )
       
  3762 {
       
  3763     const signed char Init             = 0;
       
  3764     const signed char Next             = 1;
       
  3765     const signed char Name             = 2;
       
  3766     const signed char Done             = 3;
       
  3767 
       
  3768     const signed char InpSemi          = 0; // ;
       
  3769     const signed char InpPer           = 1; // %
       
  3770     const signed char InpUnknown       = 2;
       
  3771 
       
  3772     // use some kind of state machine for parsing
       
  3773     static signed char table[3][3] = {
       
  3774      /*  InpSemi  InpPer  InpUnknown */
       
  3775 	{ -1,      Next,   -1    }, // Init
       
  3776 	{ -1,      -1,     Name  }, // Next
       
  3777 	{ Done,    -1,     -1    }  // Name
       
  3778     };
       
  3779     signed char state = Init;
       
  3780     signed char input;
       
  3781     bool parseOk = TRUE;
       
  3782 
       
  3783     while ( TRUE ) {
       
  3784 
       
  3785 	// get input
       
  3786 	if ( atEnd() ) {
       
  3787 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  3788 	    goto parseError;
       
  3789 	}
       
  3790 	if        ( c == ';' ) {
       
  3791 	    input = InpSemi;
       
  3792 	} else if ( c == '%' ) {
       
  3793 	    input = InpPer;
       
  3794 	} else {
       
  3795 	    input = InpUnknown;
       
  3796 	}
       
  3797 
       
  3798 	// set state according to input
       
  3799 	state = table[state][input];
       
  3800 
       
  3801 	// do some actions according to state
       
  3802 	switch ( state ) {
       
  3803 	    case Next:
       
  3804 		next();
       
  3805 		break;
       
  3806 	    case Name:
       
  3807 		parseOk = parseName( TRUE );
       
  3808 		break;
       
  3809 	    case Done:
       
  3810 		next();
       
  3811 		break;
       
  3812 	}
       
  3813 	// no input is read after this
       
  3814 	switch ( state ) {
       
  3815 	    case Name:
       
  3816 		if ( !parseOk ) {
       
  3817 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  3818 		    goto parseError;
       
  3819 		}
       
  3820 		if ( d->parameterEntities.find( ref() ) == d->parameterEntities.end() ) {
       
  3821 		    // ### skip it???
       
  3822 		    if ( contentHnd ) {
       
  3823 			if ( !contentHnd->skippedEntity( QString("%") + ref() ) ) {
       
  3824 			    d->error = contentHnd->errorString();
       
  3825 			    goto parseError;
       
  3826 			}
       
  3827 		    }
       
  3828 		} else {
       
  3829 		    if ( context == InEntityValue ) {
       
  3830 			// Included in literal
       
  3831 			xmlRef = d->parameterEntities.find( ref() )
       
  3832 			    .data().replace( QRegExp("\""), "&quot;" ).replace( QRegExp("'"), "&apos;" )
       
  3833 			    + xmlRef;
       
  3834 		    } else if ( context == InDTD ) {
       
  3835 			// Included as PE
       
  3836 			xmlRef = QString(" ") +
       
  3837 			    d->parameterEntities.find( ref() ).data() +
       
  3838 			    QString(" ") + xmlRef;
       
  3839 		    }
       
  3840 		}
       
  3841 		break;
       
  3842 	    case Done:
       
  3843 		return TRUE;
       
  3844 	    case -1:
       
  3845 		// Error
       
  3846 		d->error = XMLERR_LETTEREXPECTED;
       
  3847 		goto parseError;
       
  3848 	}
       
  3849 
       
  3850     }
       
  3851 
       
  3852     return TRUE;
       
  3853 
       
  3854 parseError:
       
  3855     reportParseError();
       
  3856     return FALSE;
       
  3857 }
       
  3858 
       
  3859 /*!
       
  3860   Parse a AttlistDecl [52].
       
  3861 
       
  3862   Precondition: the beginning '<!' is already read and the head
       
  3863   stands on the 'A' of '<!ATTLIST'
       
  3864 */
       
  3865 bool QXmlSimpleReader::parseAttlistDecl()
       
  3866 {
       
  3867     const signed char Init             =  0;
       
  3868     const signed char Attlist          =  1; // parse the string "ATTLIST"
       
  3869     const signed char Ws               =  2; // whitespace read
       
  3870     const signed char Name             =  3; // parse name
       
  3871     const signed char Ws1              =  4; // whitespace read
       
  3872     const signed char Attdef           =  5; // parse the AttDef
       
  3873     const signed char Ws2              =  6; // whitespace read
       
  3874     const signed char Atttype          =  7; // parse the AttType
       
  3875     const signed char Ws3              =  8; // whitespace read
       
  3876     const signed char DDecH            =  9; // DefaultDecl with #
       
  3877     const signed char DefReq           = 10; // parse the string "REQUIRED"
       
  3878     const signed char DefImp           = 11; // parse the string "IMPLIED"
       
  3879     const signed char DefFix           = 12; // parse the string "FIXED"
       
  3880     const signed char Attval           = 13; // parse the AttValue
       
  3881     const signed char Ws4              = 14; // whitespace read
       
  3882     const signed char Done             = 15;
       
  3883 
       
  3884     const signed char InpWs            = 0; // white space
       
  3885     const signed char InpGt            = 1; // >
       
  3886     const signed char InpHash          = 2; // #
       
  3887     const signed char InpA             = 3; // A
       
  3888     const signed char InpI             = 4; // I
       
  3889     const signed char InpF             = 5; // F
       
  3890     const signed char InpR             = 6; // R
       
  3891     const signed char InpUnknown       = 7;
       
  3892 
       
  3893     // use some kind of state machine for parsing
       
  3894     static signed char table[15][8] = {
       
  3895      /*  InpWs    InpGt    InpHash  InpA      InpI     InpF     InpR     InpUnknown */
       
  3896 	{ -1,      -1,      -1,      Attlist,  -1,      -1,      -1,      -1      }, // Init
       
  3897 	{ Ws,      -1,      -1,      -1,       -1,      -1,      -1,      -1      }, // Attlist
       
  3898 	{ -1,      -1,      -1,      Name,     Name,    Name,    Name,    Name    }, // Ws
       
  3899 	{ Ws1,     Done,    Attdef,  Attdef,   Attdef,  Attdef,  Attdef,  Attdef  }, // Name
       
  3900 	{ -1,      Done,    Attdef,  Attdef,   Attdef,  Attdef,  Attdef,  Attdef  }, // Ws1
       
  3901 	{ Ws2,     -1,      -1,      -1,       -1,      -1,      -1,      -1      }, // Attdef
       
  3902 	{ -1,      Atttype, Atttype, Atttype,  Atttype, Atttype, Atttype, Atttype }, // Ws2
       
  3903 	{ Ws3,     -1,      -1,      -1,       -1,      -1,      -1,      -1      }, // Attype
       
  3904 	{ -1,      Attval,  DDecH,   Attval,   Attval,  Attval,  Attval,  Attval  }, // Ws3
       
  3905 	{ -1,      -1,      -1,      -1,       DefImp,  DefFix,  DefReq,  -1      }, // DDecH
       
  3906 	{ Ws4,     Ws4,     -1,      -1,       -1,      -1,      -1,      -1      }, // DefReq
       
  3907 	{ Ws4,     Ws4,     -1,      -1,       -1,      -1,      -1,      -1      }, // DefImp
       
  3908 	{ Ws3,     -1,      -1,      -1,       -1,      -1,      -1,      -1      }, // DefFix
       
  3909 	{ Ws4,     Ws4,     -1,      -1,       -1,      -1,      -1,      -1      }, // Attval
       
  3910 	{ -1,      Done,    Attdef,  Attdef,   Attdef,  Attdef,  Attdef,  Attdef  }  // Ws4
       
  3911     };
       
  3912     signed char state = Init;
       
  3913     signed char input;
       
  3914     bool parseOk = TRUE;
       
  3915 
       
  3916     while ( TRUE ) {
       
  3917 
       
  3918 	// get input
       
  3919 	if ( atEnd() ) {
       
  3920 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  3921 	    goto parseError;
       
  3922 	}
       
  3923 	if        ( is_S(c) ) {
       
  3924 	    input = InpWs;
       
  3925 	} else if ( c == '>' ) {
       
  3926 	    input = InpGt;
       
  3927 	} else if ( c == '#' ) {
       
  3928 	    input = InpHash;
       
  3929 	} else if ( c == 'A' ) {
       
  3930 	    input = InpA;
       
  3931 	} else if ( c == 'I' ) {
       
  3932 	    input = InpI;
       
  3933 	} else if ( c == 'F' ) {
       
  3934 	    input = InpF;
       
  3935 	} else if ( c == 'R' ) {
       
  3936 	    input = InpR;
       
  3937 	} else {
       
  3938 	    input = InpUnknown;
       
  3939 	}
       
  3940 
       
  3941 	// set state according to input
       
  3942 	state = table[state][input];
       
  3943 
       
  3944 	// do some actions according to state
       
  3945 	switch ( state ) {
       
  3946 	    case Attlist:
       
  3947 		parseOk = parseString( "ATTLIST" );
       
  3948 		break;
       
  3949 	    case Ws:
       
  3950 	    case Ws1:
       
  3951 	    case Ws2:
       
  3952 	    case Ws3:
       
  3953 		eat_ws();
       
  3954 		break;
       
  3955 	    case Name:
       
  3956 		parseOk = parseName();
       
  3957 		break;
       
  3958 	    case Attdef:
       
  3959 		parseOk = parseName();
       
  3960 		break;
       
  3961 	    case Atttype:
       
  3962 		parseOk = parseAttType();
       
  3963 		break;
       
  3964 	    case DDecH:
       
  3965 		next();
       
  3966 		break;
       
  3967 	    case DefReq:
       
  3968 		parseOk = parseString( "REQUIRED" );
       
  3969 		break;
       
  3970 	    case DefImp:
       
  3971 		parseOk = parseString( "IMPLIED" );
       
  3972 		break;
       
  3973 	    case DefFix:
       
  3974 		parseOk = parseString( "FIXED" );
       
  3975 		break;
       
  3976 	    case Attval:
       
  3977 		parseOk = parseAttValue();
       
  3978 		break;
       
  3979 	    case Ws4:
       
  3980 		if ( declHnd ) {
       
  3981 		    // TODO: not all values are computed yet...
       
  3982 		    if ( !declHnd->attributeDecl( d->attDeclEName, d->attDeclAName, "", "", "" ) ) {
       
  3983 			d->error = declHnd->errorString();
       
  3984 			goto parseError;
       
  3985 		    }
       
  3986 		}
       
  3987 		eat_ws();
       
  3988 		break;
       
  3989 	    case Done:
       
  3990 		next();
       
  3991 		break;
       
  3992 	}
       
  3993 	// no input is read after this
       
  3994 	switch ( state ) {
       
  3995 	    case Attlist:
       
  3996 		if( !parseOk ) {
       
  3997 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  3998 		    goto parseError;
       
  3999 		}
       
  4000 		break;
       
  4001 	    case Name:
       
  4002 		if ( !parseOk ) {
       
  4003 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  4004 		    goto parseError;
       
  4005 		}
       
  4006 		d->attDeclEName = name();
       
  4007 		break;
       
  4008 	    case Attdef:
       
  4009 		if ( !parseOk ) {
       
  4010 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  4011 		    goto parseError;
       
  4012 		}
       
  4013 		d->attDeclAName = name();
       
  4014 		break;
       
  4015 	    case Atttype:
       
  4016 		if ( !parseOk ) {
       
  4017 		    d->error = XMLERR_ERRORPARSINGATTTYPE;
       
  4018 		    goto parseError;
       
  4019 		}
       
  4020 		break;
       
  4021 	    case DefReq:
       
  4022 		if( !parseOk ) {
       
  4023 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4024 		    goto parseError;
       
  4025 		}
       
  4026 		break;
       
  4027 	    case DefImp:
       
  4028 		if( !parseOk ) {
       
  4029 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4030 		    goto parseError;
       
  4031 		}
       
  4032 		break;
       
  4033 	    case DefFix:
       
  4034 		if( !parseOk ) {
       
  4035 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4036 		    goto parseError;
       
  4037 		}
       
  4038 		break;
       
  4039 	    case Attval:
       
  4040 		if ( !parseOk ) {
       
  4041 		    d->error = XMLERR_ERRORPARSINGATTVALUE;
       
  4042 		    goto parseError;
       
  4043 		}
       
  4044 		break;
       
  4045 	    case Done:
       
  4046 		return TRUE;
       
  4047 	    case -1:
       
  4048 		// Error
       
  4049 		d->error = XMLERR_LETTEREXPECTED;
       
  4050 		goto parseError;
       
  4051 	}
       
  4052 
       
  4053     }
       
  4054 
       
  4055     return TRUE;
       
  4056 
       
  4057 parseError:
       
  4058     reportParseError();
       
  4059     return FALSE;
       
  4060 }
       
  4061 
       
  4062 /*!
       
  4063   Parse a AttType [54]
       
  4064 */
       
  4065 bool QXmlSimpleReader::parseAttType()
       
  4066 {
       
  4067     const signed char Init             =  0;
       
  4068     const signed char ST               =  1; // StringType
       
  4069     const signed char TTI              =  2; // TokenizedType starting with 'I'
       
  4070     const signed char TTI2             =  3; // TokenizedType helpstate
       
  4071     const signed char TTI3             =  4; // TokenizedType helpstate
       
  4072     const signed char TTE              =  5; // TokenizedType starting with 'E'
       
  4073     const signed char TTEY             =  6; // TokenizedType starting with 'ENTITY'
       
  4074     const signed char TTEI             =  7; // TokenizedType starting with 'ENTITI'
       
  4075     const signed char N                =  8; // N read (TokenizedType or Notation)
       
  4076     const signed char TTNM             =  9; // TokenizedType starting with 'NM'
       
  4077     const signed char TTNM2            = 10; // TokenizedType helpstate
       
  4078     const signed char NO               = 11; // Notation
       
  4079     const signed char NO2              = 12; // Notation helpstate
       
  4080     const signed char NO3              = 13; // Notation helpstate
       
  4081     const signed char NOName           = 14; // Notation, read name
       
  4082     const signed char NO4              = 15; // Notation helpstate
       
  4083     const signed char EN               = 16; // Enumeration
       
  4084     const signed char ENNmt            = 17; // Enumeration, read Nmtoken
       
  4085     const signed char EN2              = 18; // Enumeration helpstate
       
  4086     const signed char ADone            = 19; // almost done (make next and accept)
       
  4087     const signed char Done             = 20;
       
  4088 
       
  4089     const signed char InpWs            =  0; // whitespace
       
  4090     const signed char InpOp            =  1; // (
       
  4091     const signed char InpCp            =  2; // )
       
  4092     const signed char InpPipe          =  3; // |
       
  4093     const signed char InpC             =  4; // C
       
  4094     const signed char InpE             =  5; // E
       
  4095     const signed char InpI             =  6; // I
       
  4096     const signed char InpM             =  7; // M
       
  4097     const signed char InpN             =  8; // N
       
  4098     const signed char InpO             =  9; // O
       
  4099     const signed char InpR             = 10; // R
       
  4100     const signed char InpS             = 11; // S
       
  4101     const signed char InpY             = 12; // Y
       
  4102     const signed char InpUnknown       = 13;
       
  4103 
       
  4104     // use some kind of state machine for parsing
       
  4105     static signed char table[19][14] = {
       
  4106      /*  InpWs    InpOp    InpCp    InpPipe  InpC     InpE     InpI     InpM     InpN     InpO     InpR     InpS     InpY     InpUnknown */
       
  4107 	{ -1,      EN,      -1,      -1,      ST,      TTE,     TTI,     -1,      N,       -1,      -1,      -1,      -1,      -1     }, // Init
       
  4108 	{ Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // ST
       
  4109 	{ Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    TTI2,    Done,    Done,    Done   }, // TTI
       
  4110 	{ Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    TTI3,    Done,    Done   }, // TTI2
       
  4111 	{ Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // TTI3
       
  4112 	{ -1,      -1,      -1,      -1,      -1,      -1,      TTEI,    -1,      -1,      -1,      -1,      -1,      TTEY,    -1     }, // TTE
       
  4113 	{ Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // TTEY
       
  4114 	{ Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // TTEI
       
  4115 	{ -1,      -1,      -1,      -1,      -1,      -1,      -1,      TTNM,    -1,      NO,      -1,      -1,      -1,      -1     }, // N
       
  4116 	{ Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    TTNM2,   Done,    Done   }, // TTNM
       
  4117 	{ Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // TTNM2
       
  4118 	{ NO2,     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // NO
       
  4119 	{ -1,      NO3,     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // NO2
       
  4120 	{ NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName }, // NO3
       
  4121 	{ NO4,     -1,      ADone,   NO3,     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // NOName
       
  4122 	{ -1,      -1,      ADone,   NO3,     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // NO4
       
  4123 	{ -1,      -1,      ENNmt,   -1,      ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt  }, // EN
       
  4124 	{ EN2,     -1,      ADone,   EN,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // ENNmt
       
  4125 	{ -1,      -1,      ADone,   EN,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }  // EN2
       
  4126     };
       
  4127     signed char state = Init;
       
  4128     signed char input;
       
  4129     bool parseOk = TRUE;
       
  4130 
       
  4131     while ( TRUE ) {
       
  4132 
       
  4133 	// get input
       
  4134 	if ( atEnd() ) {
       
  4135 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  4136 	    goto parseError;
       
  4137 	}
       
  4138 	if        ( is_S(c) ) {
       
  4139 	    input = InpWs;
       
  4140 	} else if ( c == '(' ) {
       
  4141 	    input = InpOp;
       
  4142 	} else if ( c == ')' ) {
       
  4143 	    input = InpCp;
       
  4144 	} else if ( c == '|' ) {
       
  4145 	    input = InpPipe;
       
  4146 	} else if ( c == 'C' ) {
       
  4147 	    input = InpC;
       
  4148 	} else if ( c == 'E' ) {
       
  4149 	    input = InpE;
       
  4150 	} else if ( c == 'I' ) {
       
  4151 	    input = InpI;
       
  4152 	} else if ( c == 'M' ) {
       
  4153 	    input = InpM;
       
  4154 	} else if ( c == 'N' ) {
       
  4155 	    input = InpN;
       
  4156 	} else if ( c == 'O' ) {
       
  4157 	    input = InpO;
       
  4158 	} else if ( c == 'R' ) {
       
  4159 	    input = InpR;
       
  4160 	} else if ( c == 'S' ) {
       
  4161 	    input = InpS;
       
  4162 	} else if ( c == 'Y' ) {
       
  4163 	    input = InpY;
       
  4164 	} else {
       
  4165 	    input = InpUnknown;
       
  4166 	}
       
  4167 
       
  4168 	// set state according to input
       
  4169 	state = table[state][input];
       
  4170 
       
  4171 	// do some actions according to state
       
  4172 	switch ( state ) {
       
  4173 	    case ST:
       
  4174 		parseOk = parseString( "CDATA" );
       
  4175 		break;
       
  4176 	    case TTI:
       
  4177 		parseOk = parseString( "ID" );
       
  4178 		break;
       
  4179 	    case TTI2:
       
  4180 		parseOk = parseString( "REF" );
       
  4181 		break;
       
  4182 	    case TTI3:
       
  4183 		next(); // S
       
  4184 		break;
       
  4185 	    case TTE:
       
  4186 		parseOk = parseString( "ENTIT" );
       
  4187 		break;
       
  4188 	    case TTEY:
       
  4189 		next(); // Y
       
  4190 		break;
       
  4191 	    case TTEI:
       
  4192 		parseOk = parseString( "IES" );
       
  4193 		break;
       
  4194 	    case N:
       
  4195 		next(); // N
       
  4196 		break;
       
  4197 	    case TTNM:
       
  4198 		parseOk = parseString( "MTOKEN" );
       
  4199 		break;
       
  4200 	    case TTNM2:
       
  4201 		next(); // S
       
  4202 		break;
       
  4203 	    case NO:
       
  4204 		parseOk = parseString( "OTATION" );
       
  4205 		break;
       
  4206 	    case NO2:
       
  4207 		eat_ws();
       
  4208 		break;
       
  4209 	    case NO3:
       
  4210 		next_eat_ws();
       
  4211 		break;
       
  4212 	    case NOName:
       
  4213 		parseOk = parseName();
       
  4214 		break;
       
  4215 	    case NO4:
       
  4216 		eat_ws();
       
  4217 		break;
       
  4218 	    case EN:
       
  4219 		next_eat_ws();
       
  4220 		break;
       
  4221 	    case ENNmt:
       
  4222 		parseOk = parseNmtoken();
       
  4223 		break;
       
  4224 	    case EN2:
       
  4225 		eat_ws();
       
  4226 		break;
       
  4227 	    case ADone:
       
  4228 		next();
       
  4229 		break;
       
  4230 	}
       
  4231 	// no input is read after this
       
  4232 	switch ( state ) {
       
  4233 	    case ST:
       
  4234 		if( !parseOk ) {
       
  4235 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4236 		    goto parseError;
       
  4237 		}
       
  4238 		break;
       
  4239 	    case TTI:
       
  4240 		if( !parseOk ) {
       
  4241 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4242 		    goto parseError;
       
  4243 		}
       
  4244 		break;
       
  4245 	    case TTI2:
       
  4246 		if( !parseOk ) {
       
  4247 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4248 		    goto parseError;
       
  4249 		}
       
  4250 		break;
       
  4251 	    case TTE:
       
  4252 		if( !parseOk ) {
       
  4253 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4254 		    goto parseError;
       
  4255 		}
       
  4256 		break;
       
  4257 	    case TTEI:
       
  4258 		if( !parseOk ) {
       
  4259 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4260 		    goto parseError;
       
  4261 		}
       
  4262 		break;
       
  4263 	    case TTNM:
       
  4264 		if( !parseOk ) {
       
  4265 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4266 		    goto parseError;
       
  4267 		}
       
  4268 		break;
       
  4269 	    case NO:
       
  4270 		if( !parseOk ) {
       
  4271 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4272 		    goto parseError;
       
  4273 		}
       
  4274 		break;
       
  4275 	    case NOName:
       
  4276 		if ( !parseOk ) {
       
  4277 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  4278 		    goto parseError;
       
  4279 		}
       
  4280 		break;
       
  4281 	    case ENNmt:
       
  4282 		if ( !parseOk ) {
       
  4283 		    d->error = XMLERR_ERRORPARSINGNMTOKEN;
       
  4284 		    goto parseError;
       
  4285 		}
       
  4286 		break;
       
  4287 	    case ADone:
       
  4288 		return TRUE;
       
  4289 	    case Done:
       
  4290 		return TRUE;
       
  4291 	    case -1:
       
  4292 		// Error
       
  4293 		d->error = XMLERR_LETTEREXPECTED;
       
  4294 		goto parseError;
       
  4295 	}
       
  4296 
       
  4297     }
       
  4298 
       
  4299     return TRUE;
       
  4300 
       
  4301 parseError:
       
  4302     reportParseError();
       
  4303     return FALSE;
       
  4304 }
       
  4305 
       
  4306 /*!
       
  4307   Parse a AttValue [10]
       
  4308 
       
  4309   Precondition: the head stands on the beginning " or '
       
  4310 
       
  4311   If this function was successful, the head stands on the first
       
  4312   character after the closing " or ' and the value of the attribute
       
  4313   is in string().
       
  4314 */
       
  4315 bool QXmlSimpleReader::parseAttValue()
       
  4316 {
       
  4317     bool tmp;
       
  4318 
       
  4319     const signed char Init             = 0;
       
  4320     const signed char Dq               = 1; // double quotes were read
       
  4321     const signed char DqRef            = 2; // read references in double quotes
       
  4322     const signed char DqC              = 3; // signed character read in double quotes
       
  4323     const signed char Sq               = 4; // single quotes were read
       
  4324     const signed char SqRef            = 5; // read references in single quotes
       
  4325     const signed char SqC              = 6; // signed character read in single quotes
       
  4326     const signed char Done             = 7;
       
  4327 
       
  4328     const signed char InpDq            = 0; // "
       
  4329     const signed char InpSq            = 1; // '
       
  4330     const signed char InpAmp           = 2; // &
       
  4331     const signed char InpLt            = 3; // <
       
  4332     const signed char InpUnknown       = 4;
       
  4333 
       
  4334     // use some kind of state machine for parsing
       
  4335     static signed char table[7][5] = {
       
  4336      /*  InpDq  InpSq  InpAmp  InpLt InpUnknown */
       
  4337 	{ Dq,    Sq,    -1,     -1,   -1    }, // Init
       
  4338 	{ Done,  DqC,   DqRef,  -1,   DqC   }, // Dq
       
  4339 	{ Done,  DqC,   DqRef,  -1,   DqC   }, // DqRef
       
  4340 	{ Done,  DqC,   DqRef,  -1,   DqC   }, // DqC
       
  4341 	{ SqC,   Done,  SqRef,  -1,   SqC   }, // Sq
       
  4342 	{ SqC,   Done,  SqRef,  -1,   SqC   }, // SqRef
       
  4343 	{ SqC,   Done,  SqRef,  -1,   SqC   }  // SqRef
       
  4344     };
       
  4345     signed char state = Init;
       
  4346     signed char input;
       
  4347     bool parseOk = TRUE;
       
  4348 
       
  4349     while ( TRUE ) {
       
  4350 
       
  4351 	// get input
       
  4352 	if ( atEnd() ) {
       
  4353 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  4354 	    goto parseError;
       
  4355 	}
       
  4356 	if        ( c == '"' ) {
       
  4357 	    input = InpDq;
       
  4358 	} else if ( c == '\'' ) {
       
  4359 	    input = InpSq;
       
  4360 	} else if ( c == '&' ) {
       
  4361 	    input = InpAmp;
       
  4362 	} else if ( c == '<' ) {
       
  4363 	    input = InpLt;
       
  4364 	} else {
       
  4365 	    input = InpUnknown;
       
  4366 	}
       
  4367 
       
  4368 	// set state according to input
       
  4369 	state = table[state][input];
       
  4370 
       
  4371 	// do some actions according to state
       
  4372 	switch ( state ) {
       
  4373 	    case Dq:
       
  4374 	    case Sq:
       
  4375 		stringClear();
       
  4376 		next();
       
  4377 		break;
       
  4378 	    case DqRef:
       
  4379 	    case SqRef:
       
  4380 		parseOk = parseReference( tmp, InAttributeValue );
       
  4381 		break;
       
  4382 	    case DqC:
       
  4383 	    case SqC:
       
  4384 		stringAddC();
       
  4385 		next();
       
  4386 		break;
       
  4387 	    case Done:
       
  4388 		next();
       
  4389 		break;
       
  4390 	}
       
  4391 	// no input is read after this
       
  4392 	switch ( state ) {
       
  4393 	    case DqRef:
       
  4394 	    case SqRef:
       
  4395 		if ( !parseOk ) {
       
  4396 		    d->error = XMLERR_ERRORPARSINGREFERENCE;
       
  4397 		    goto parseError;
       
  4398 		}
       
  4399 		break;
       
  4400 	    case Done:
       
  4401 		return TRUE;
       
  4402 	    case -1:
       
  4403 		// Error
       
  4404 		d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4405 		goto parseError;
       
  4406 	}
       
  4407 
       
  4408     }
       
  4409 
       
  4410     return TRUE;
       
  4411 
       
  4412 parseError:
       
  4413     reportParseError();
       
  4414     return FALSE;
       
  4415 }
       
  4416 
       
  4417 /*!
       
  4418   Parse a elementdecl [45].
       
  4419 
       
  4420   Precondition: the beginning '<!E' is already read and the head
       
  4421   stands on the 'L' of '<!ELEMENT'
       
  4422 */
       
  4423 bool QXmlSimpleReader::parseElementDecl()
       
  4424 {
       
  4425     const signed char Init             =  0;
       
  4426     const signed char Elem             =  1; // parse the beginning string
       
  4427     const signed char Ws1              =  2; // whitespace required
       
  4428     const signed char Nam              =  3; // parse Name
       
  4429     const signed char Ws2              =  4; // whitespace required
       
  4430     const signed char Empty            =  5; // read EMPTY
       
  4431     const signed char Any              =  6; // read ANY
       
  4432     const signed char Cont             =  7; // read contentspec (except ANY or EMPTY)
       
  4433     const signed char Mix              =  8; // read Mixed
       
  4434     const signed char Mix2             =  9; //
       
  4435     const signed char Mix3             = 10; //
       
  4436     const signed char MixN1            = 11; //
       
  4437     const signed char MixN2            = 12; //
       
  4438     const signed char MixN3            = 13; //
       
  4439     const signed char MixN4            = 14; //
       
  4440     const signed char Cp               = 15; // parse cp
       
  4441     const signed char Cp2              = 16; //
       
  4442     const signed char WsD              = 17; // eat whitespace before Done
       
  4443     const signed char Done             = 18;
       
  4444 
       
  4445     const signed char InpWs            =  0;
       
  4446     const signed char InpGt            =  1; // >
       
  4447     const signed char InpPipe          =  2; // |
       
  4448     const signed char InpOp            =  3; // (
       
  4449     const signed char InpCp            =  4; // )
       
  4450     const signed char InpHash          =  5; // #
       
  4451     const signed char InpQm            =  6; // ?
       
  4452     const signed char InpAst           =  7; // *
       
  4453     const signed char InpPlus          =  8; // +
       
  4454     const signed char InpA             =  9; // A
       
  4455     const signed char InpE             = 10; // E
       
  4456     const signed char InpL             = 11; // L
       
  4457     const signed char InpUnknown       = 12;
       
  4458 
       
  4459     // use some kind of state machine for parsing
       
  4460     static signed char table[18][13] = {
       
  4461      /*  InpWs   InpGt  InpPipe  InpOp  InpCp   InpHash  InpQm  InpAst  InpPlus  InpA    InpE    InpL    InpUnknown */
       
  4462 	{ -1,     -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     Elem,   -1     }, // Init
       
  4463 	{ Ws1,    -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Elem
       
  4464 	{ -1,     -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      Nam,    Nam,    Nam,    Nam    }, // Ws1
       
  4465 	{ Ws2,    -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Nam
       
  4466 	{ -1,     -1,    -1,      Cont,  -1,     -1,      -1,    -1,     -1,      Any,    Empty,  -1,     -1     }, // Ws2
       
  4467 	{ WsD,    Done,  -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Empty
       
  4468 	{ WsD,    Done,  -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Any
       
  4469 	{ -1,     -1,    -1,      Cp,    Cp,     Mix,     -1,    -1,     -1,      Cp,     Cp,     Cp,     Cp     }, // Cont
       
  4470 	{ Mix2,   -1,    MixN1,   -1,    Mix3,   -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Mix
       
  4471 	{ -1,     -1,    MixN1,   -1,    Mix3,   -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Mix2
       
  4472 	{ WsD,    Done,  -1,      -1,    -1,     -1,      -1,    WsD,    -1,      -1,     -1,     -1,     -1     }, // Mix3
       
  4473 	{ -1,     -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      MixN2,  MixN2,  MixN2,  MixN2  }, // MixN1
       
  4474 	{ MixN3,  -1,    MixN1,   -1,    MixN4,  -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // MixN2
       
  4475 	{ -1,     -1,    MixN1,   -1,    MixN4,  -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // MixN3
       
  4476 	{ -1,     -1,    -1,      -1,    -1,     -1,      -1,    WsD,    -1,      -1,     -1,     -1,     -1     }, // MixN4
       
  4477 	{ WsD,    Done,  -1,      -1,    -1,     -1,      Cp2,   Cp2,    Cp2,     -1,     -1,     -1,     -1     }, // Cp
       
  4478 	{ WsD,    Done,  -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Cp2
       
  4479 	{ -1,     Done,  -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }  // WsD
       
  4480     };
       
  4481     signed char state = Init;
       
  4482     signed char input;
       
  4483     bool parseOk = TRUE;
       
  4484 
       
  4485     while ( TRUE ) {
       
  4486 
       
  4487 	// read input
       
  4488 	if ( atEnd() ) {
       
  4489 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  4490 	    goto parseError;
       
  4491 	}
       
  4492 	if        ( is_S(c) ) {
       
  4493 	    input = InpWs;
       
  4494 	} else if ( c == '>' ) {
       
  4495 	    input = InpGt;
       
  4496 	} else if ( c == '|' ) {
       
  4497 	    input = InpPipe;
       
  4498 	} else if ( c == '(' ) {
       
  4499 	    input = InpOp;
       
  4500 	} else if ( c == ')' ) {
       
  4501 	    input = InpCp;
       
  4502 	} else if ( c == '#' ) {
       
  4503 	    input = InpHash;
       
  4504 	} else if ( c == '?' ) {
       
  4505 	    input = InpQm;
       
  4506 	} else if ( c == '*' ) {
       
  4507 	    input = InpAst;
       
  4508 	} else if ( c == '+' ) {
       
  4509 	    input = InpPlus;
       
  4510 	} else if ( c == 'A' ) {
       
  4511 	    input = InpA;
       
  4512 	} else if ( c == 'E' ) {
       
  4513 	    input = InpE;
       
  4514 	} else if ( c == 'L' ) {
       
  4515 	    input = InpL;
       
  4516 	} else {
       
  4517 	    input = InpUnknown;
       
  4518 	}
       
  4519 	// get new state
       
  4520 //qDebug( "%d -%d(%c)-> %d", state, input, c.latin1(), table[state][input] );
       
  4521 	state = table[state][input];
       
  4522 
       
  4523 	// in some cases do special actions depending on state
       
  4524 	switch ( state ) {
       
  4525 	    case Elem:
       
  4526 		parseOk = parseString( "LEMENT" );
       
  4527 		break;
       
  4528 	    case Ws1:
       
  4529 		eat_ws();
       
  4530 		break;
       
  4531 	    case Nam:
       
  4532 		parseOk = parseName();
       
  4533 		break;
       
  4534 	    case Ws2:
       
  4535 		eat_ws();
       
  4536 		break;
       
  4537 	    case Empty:
       
  4538 		parseOk = parseString( "EMPTY" );
       
  4539 		break;
       
  4540 	    case Any:
       
  4541 		parseOk = parseString( "ANY" );
       
  4542 		break;
       
  4543 	    case Cont:
       
  4544 		next_eat_ws();
       
  4545 		break;
       
  4546 	    case Mix:
       
  4547 		parseOk = parseString( "#PCDATA" );
       
  4548 		break;
       
  4549 	    case Mix2:
       
  4550 		eat_ws();
       
  4551 		break;
       
  4552 	    case Mix3:
       
  4553 		next();
       
  4554 		break;
       
  4555 	    case MixN1:
       
  4556 		next_eat_ws();
       
  4557 		break;
       
  4558 	    case MixN2:
       
  4559 		parseOk = parseName();
       
  4560 		break;
       
  4561 	    case MixN3:
       
  4562 		eat_ws();
       
  4563 		break;
       
  4564 	    case MixN4:
       
  4565 		next();
       
  4566 		break;
       
  4567 	    case Cp:
       
  4568 		parseOk = parseChoiceSeq();
       
  4569 		break;
       
  4570 	    case Cp2:
       
  4571 		next();
       
  4572 		break;
       
  4573 	    case WsD:
       
  4574 		next_eat_ws();
       
  4575 		break;
       
  4576 	    case Done:
       
  4577 		next();
       
  4578 		break;
       
  4579 	}
       
  4580 	// no input is read after this
       
  4581 	switch ( state ) {
       
  4582 	    case Elem:
       
  4583 		if( !parseOk ) {
       
  4584 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4585 		    goto parseError;
       
  4586 		}
       
  4587 		break;
       
  4588 	    case Nam:
       
  4589 		if ( !parseOk ) {
       
  4590 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  4591 		    goto parseError;
       
  4592 		}
       
  4593 		break;
       
  4594 	    case Empty:
       
  4595 		if( !parseOk ) {
       
  4596 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4597 		    goto parseError;
       
  4598 		}
       
  4599 		break;
       
  4600 	    case Any:
       
  4601 		if( !parseOk ) {
       
  4602 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4603 		    goto parseError;
       
  4604 		}
       
  4605 		break;
       
  4606 	    case Mix:
       
  4607 		if( !parseOk ) {
       
  4608 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4609 		    goto parseError;
       
  4610 		}
       
  4611 		break;
       
  4612 	    case MixN2:
       
  4613 		if ( !parseOk ) {
       
  4614 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  4615 		    goto parseError;
       
  4616 		}
       
  4617 		break;
       
  4618 	    case Cp:
       
  4619 		if ( !parseOk ) {
       
  4620 		    d->error = XMLERR_ERRORPARSINGCHOICE;
       
  4621 		    goto parseError;
       
  4622 		}
       
  4623 		break;
       
  4624 	    case Done:
       
  4625 		return TRUE;
       
  4626 	    case -1:
       
  4627 		d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4628 		goto parseError;
       
  4629 	}
       
  4630 
       
  4631     }
       
  4632 
       
  4633     return TRUE;
       
  4634 
       
  4635 parseError:
       
  4636     reportParseError();
       
  4637     return FALSE;
       
  4638 }
       
  4639 
       
  4640 /*!
       
  4641   Parse a NotationDecl [82].
       
  4642 
       
  4643   Precondition: the beginning '<!' is already read and the head
       
  4644   stands on the 'N' of '<!NOTATION'
       
  4645 */
       
  4646 bool QXmlSimpleReader::parseNotationDecl()
       
  4647 {
       
  4648     const signed char Init             = 0;
       
  4649     const signed char Not              = 1; // read NOTATION
       
  4650     const signed char Ws1              = 2; // eat whitespaces
       
  4651     const signed char Nam              = 3; // read Name
       
  4652     const signed char Ws2              = 4; // eat whitespaces
       
  4653     const signed char ExtID            = 5; // parse ExternalID
       
  4654     const signed char Ws3              = 6; // eat whitespaces
       
  4655     const signed char Done             = 7;
       
  4656 
       
  4657     const signed char InpWs            = 0;
       
  4658     const signed char InpGt            = 1; // >
       
  4659     const signed char InpN             = 2; // N
       
  4660     const signed char InpUnknown       = 3;
       
  4661 
       
  4662     // use some kind of state machine for parsing
       
  4663     static signed char table[7][4] = {
       
  4664      /*  InpWs   InpGt  InpN    InpUnknown */
       
  4665 	{ -1,     -1,    Not,    -1     }, // Init
       
  4666 	{ Ws1,    -1,    -1,     -1     }, // Not
       
  4667 	{ -1,     -1,    Nam,    Nam    }, // Ws1
       
  4668 	{ Ws2,    Done,  -1,     -1     }, // Nam
       
  4669 	{ -1,     Done,  ExtID,  ExtID  }, // Ws2
       
  4670 	{ Ws3,    Done,  -1,     -1     }, // ExtID
       
  4671 	{ -1,     Done,  -1,     -1     }  // Ws3
       
  4672     };
       
  4673     signed char state = Init;
       
  4674     signed char input;
       
  4675     bool parseOk = TRUE;
       
  4676 
       
  4677     while ( TRUE ) {
       
  4678 
       
  4679 	// get input
       
  4680 	if ( atEnd() ) {
       
  4681 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  4682 	    goto parseError;
       
  4683 	}
       
  4684 	if        ( is_S(c) ) {
       
  4685 	    input = InpWs;
       
  4686 	} else if ( c == '>' ) {
       
  4687 	    input = InpGt;
       
  4688 	} else if ( c == 'N' ) {
       
  4689 	    input = InpN;
       
  4690 	} else {
       
  4691 	    input = InpUnknown;
       
  4692 	}
       
  4693 
       
  4694 	// set state according to input
       
  4695 	state = table[state][input];
       
  4696 
       
  4697 	// do some actions according to state
       
  4698 	switch ( state ) {
       
  4699 	    case Not:
       
  4700 		parseOk = parseString( "NOTATION" );
       
  4701 		break;
       
  4702 	    case Ws1:
       
  4703 		eat_ws();
       
  4704 		break;
       
  4705 	    case Nam:
       
  4706 		parseOk = parseName();
       
  4707 		break;
       
  4708 	    case Ws2:
       
  4709 		eat_ws();
       
  4710 		break;
       
  4711 	    case ExtID:
       
  4712 		parseOk = parseExternalID( TRUE );
       
  4713 		break;
       
  4714 	    case Ws3:
       
  4715 		eat_ws();
       
  4716 		break;
       
  4717 	    case Done:
       
  4718 		next();
       
  4719 		break;
       
  4720 	}
       
  4721 	// no input is read after this
       
  4722 	switch ( state ) {
       
  4723 	    case Not:
       
  4724 		if ( !parseOk ) {
       
  4725 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4726 		    goto parseError;
       
  4727 		}
       
  4728 		break;
       
  4729 	    case Nam:
       
  4730 		if ( !parseOk ) {
       
  4731 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  4732 		    goto parseError;
       
  4733 		}
       
  4734 		break;
       
  4735 	    case ExtID:
       
  4736 		if ( !parseOk ) {
       
  4737 		    d->error = XMLERR_ERRORPARSINGEXTERNALID;
       
  4738 		    goto parseError;
       
  4739 		}
       
  4740 		// call the handler
       
  4741 		if ( dtdHnd ) {
       
  4742 		    if ( !dtdHnd->notationDecl( name(), d->publicId, d->systemId ) ) {
       
  4743 			d->error = dtdHnd->errorString();
       
  4744 			goto parseError;
       
  4745 		    }
       
  4746 		}
       
  4747 		break;
       
  4748 	    case Done:
       
  4749 		return TRUE;
       
  4750 	    case -1:
       
  4751 		// Error
       
  4752 		d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4753 		goto parseError;
       
  4754 	}
       
  4755 
       
  4756     }
       
  4757 
       
  4758     return TRUE;
       
  4759 
       
  4760 parseError:
       
  4761     reportParseError();
       
  4762     return FALSE;
       
  4763 }
       
  4764 
       
  4765 /*!
       
  4766   Parse choice [49] or seq [50].
       
  4767 
       
  4768   Precondition: the beginning '('S? is already read and the head
       
  4769   stands on the first non-whitespace character after it.
       
  4770 */
       
  4771 bool QXmlSimpleReader::parseChoiceSeq()
       
  4772 {
       
  4773     const signed char Init             = 0;
       
  4774     const signed char Ws1              = 1; // eat whitespace
       
  4775     const signed char CS_              = 2; // choice or set
       
  4776     const signed char Ws2              = 3; // eat whitespace
       
  4777     const signed char More             = 4; // more cp to read
       
  4778     const signed char Name             = 5; // read name
       
  4779     const signed char Done             = 6; //
       
  4780 
       
  4781     const signed char InpWs            = 0; // S
       
  4782     const signed char InpOp            = 1; // (
       
  4783     const signed char InpCp            = 2; // )
       
  4784     const signed char InpQm            = 3; // ?
       
  4785     const signed char InpAst           = 4; // *
       
  4786     const signed char InpPlus          = 5; // +
       
  4787     const signed char InpPipe          = 6; // |
       
  4788     const signed char InpComm          = 7; // ,
       
  4789     const signed char InpUnknown       = 8;
       
  4790 
       
  4791     // use some kind of state machine for parsing
       
  4792     static signed char table[6][9] = {
       
  4793      /*  InpWs   InpOp  InpCp  InpQm  InpAst  InpPlus  InpPipe  InpComm  InpUnknown */
       
  4794 	{ -1,     Ws1,   -1,    -1,    -1,     -1,      -1,      -1,      Name  }, // Init
       
  4795 	{ -1,     CS_,   -1,    -1,    -1,     -1,      -1,      -1,      CS_    }, // Ws1
       
  4796 	{ Ws2,    -1,    Done,  Ws2,   Ws2,    Ws2,     More,    More,    -1    }, // CS_
       
  4797 	{ -1,     -1,    Done,  -1,    -1,     -1,      More,    More,    -1    }, // Ws2
       
  4798 	{ -1,     Ws1,   -1,    -1,    -1,     -1,      -1,      -1,      Name  }, // More (same as Init)
       
  4799 	{ Ws2,    -1,    Done,  Ws2,   Ws2,    Ws2,     More,    More,    -1    }  // Name (same as CS_)
       
  4800     };
       
  4801     signed char state = Init;
       
  4802     signed char input;
       
  4803     bool parseOk = TRUE;
       
  4804 
       
  4805     while ( TRUE ) {
       
  4806 
       
  4807 	// get input
       
  4808 	if ( atEnd() ) {
       
  4809 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  4810 	    goto parseError;
       
  4811 	}
       
  4812 	if        ( is_S(c) ) {
       
  4813 	    input = InpWs;
       
  4814 	} else if ( c == '(' ) {
       
  4815 	    input = InpOp;
       
  4816 	} else if ( c == ')' ) {
       
  4817 	    input = InpCp;
       
  4818 	} else if ( c == '?' ) {
       
  4819 	    input = InpQm;
       
  4820 	} else if ( c == '*' ) {
       
  4821 	    input = InpAst;
       
  4822 	} else if ( c == '+' ) {
       
  4823 	    input = InpPlus;
       
  4824 	} else if ( c == '|' ) {
       
  4825 	    input = InpPipe;
       
  4826 	} else if ( c == ',' ) {
       
  4827 	    input = InpComm;
       
  4828 	} else {
       
  4829 	    input = InpUnknown;
       
  4830 	}
       
  4831 
       
  4832 	// set state according to input
       
  4833 	state = table[state][input];
       
  4834 
       
  4835 	// do some actions according to state
       
  4836 	switch ( state ) {
       
  4837 	    case Ws1:
       
  4838 		next_eat_ws();
       
  4839 		break;
       
  4840 	    case CS_:
       
  4841 		parseOk = parseChoiceSeq();
       
  4842 		break;
       
  4843 	    case Ws2:
       
  4844 		next_eat_ws();
       
  4845 		break;
       
  4846 	    case More:
       
  4847 		next_eat_ws();
       
  4848 		break;
       
  4849 	    case Name:
       
  4850 		parseOk = parseName();
       
  4851 		break;
       
  4852 	    case Done:
       
  4853 		next();
       
  4854 		break;
       
  4855 	}
       
  4856 	// no input is read after this
       
  4857 	switch ( state ) {
       
  4858 	    case CS_:
       
  4859 		if ( !parseOk ) {
       
  4860 		    d->error = XMLERR_ERRORPARSINGCHOICE;
       
  4861 		    goto parseError;
       
  4862 		}
       
  4863 		break;
       
  4864 	    case Name:
       
  4865 		if ( !parseOk ) {
       
  4866 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  4867 		    goto parseError;
       
  4868 		}
       
  4869 		break;
       
  4870 	    case Done:
       
  4871 		return TRUE;
       
  4872 	    case -1:
       
  4873 		// Error
       
  4874 		d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  4875 		goto parseError;
       
  4876 	}
       
  4877 
       
  4878     }
       
  4879 
       
  4880     return TRUE;
       
  4881 
       
  4882 parseError:
       
  4883     reportParseError();
       
  4884     return FALSE;
       
  4885 }
       
  4886 
       
  4887 /*!
       
  4888   Parse a EntityDecl [70].
       
  4889 
       
  4890   Precondition: the beginning '<!E' is already read and the head
       
  4891   stand on the 'N' of '<!ENTITY'
       
  4892 */
       
  4893 bool QXmlSimpleReader::parseEntityDecl()
       
  4894 {
       
  4895     const signed char Init             =  0;
       
  4896     const signed char Ent              =  1; // parse "ENTITY"
       
  4897     const signed char Ws1              =  2; // white space read
       
  4898     const signed char Name             =  3; // parse name
       
  4899     const signed char Ws2              =  4; // white space read
       
  4900     const signed char EValue           =  5; // parse entity value
       
  4901     const signed char ExtID            =  6; // parse ExternalID
       
  4902     const signed char Ws3              =  7; // white space read
       
  4903     const signed char Ndata            =  8; // parse "NDATA"
       
  4904     const signed char Ws4              =  9; // white space read
       
  4905     const signed char NNam             = 10; // parse name
       
  4906     const signed char PEDec            = 11; // parse PEDecl
       
  4907     const signed char Ws6              = 12; // white space read
       
  4908     const signed char PENam            = 13; // parse name
       
  4909     const signed char Ws7              = 14; // white space read
       
  4910     const signed char PEVal            = 15; // parse entity value
       
  4911     const signed char PEEID            = 16; // parse ExternalID
       
  4912     const signed char WsE              = 17; // white space read
       
  4913     const signed char EDDone           = 19; // done, but also report an external, unparsed entity decl
       
  4914     const signed char Done             = 18;
       
  4915 
       
  4916     const signed char InpWs            = 0; // white space
       
  4917     const signed char InpPer           = 1; // %
       
  4918     const signed char InpQuot          = 2; // " or '
       
  4919     const signed char InpGt            = 3; // >
       
  4920     const signed char InpN             = 4; // N
       
  4921     const signed char InpUnknown       = 5;
       
  4922 
       
  4923     // use some kind of state machine for parsing
       
  4924     static signed char table[18][6] = {
       
  4925      /*  InpWs  InpPer  InpQuot  InpGt  InpN    InpUnknown */
       
  4926 	{ -1,    -1,     -1,      -1,    Ent,    -1      }, // Init
       
  4927 	{ Ws1,   -1,     -1,      -1,    -1,     -1      }, // Ent
       
  4928 	{ -1,    PEDec,  -1,      -1,    Name,   Name    }, // Ws1
       
  4929 	{ Ws2,   -1,     -1,      -1,    -1,     -1      }, // Name
       
  4930 	{ -1,    -1,     EValue,  -1,    -1,     ExtID   }, // Ws2
       
  4931 	{ WsE,   -1,     -1,      Done,  -1,     -1      }, // EValue
       
  4932 	{ Ws3,   -1,     -1,      EDDone,-1,     -1      }, // ExtID
       
  4933 	{ -1,    -1,     -1,      EDDone,Ndata,  -1      }, // Ws3
       
  4934 	{ Ws4,   -1,     -1,      -1,    -1,     -1      }, // Ndata
       
  4935 	{ -1,    -1,     -1,      -1,    NNam,   NNam    }, // Ws4
       
  4936 	{ WsE,   -1,     -1,      Done,  -1,     -1      }, // NNam
       
  4937 	{ Ws6,   -1,     -1,      -1,    -1,     -1      }, // PEDec
       
  4938 	{ -1,    -1,     -1,      -1,    PENam,  PENam   }, // Ws6
       
  4939 	{ Ws7,   -1,     -1,      -1,    -1,     -1      }, // PENam
       
  4940 	{ -1,    -1,     PEVal,   -1,    -1,     PEEID   }, // Ws7
       
  4941 	{ WsE,   -1,     -1,      Done,  -1,     -1      }, // PEVal
       
  4942 	{ WsE,   -1,     -1,      Done,  -1,     -1      }, // PEEID
       
  4943 	{ -1,    -1,     -1,      Done,  -1,     -1      }  // WsE
       
  4944     };
       
  4945     signed char state = Init;
       
  4946     signed char input;
       
  4947     bool parseOk = TRUE;
       
  4948 
       
  4949     while ( TRUE ) {
       
  4950 
       
  4951 	// get input
       
  4952 	if ( atEnd() ) {
       
  4953 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  4954 	    goto parseError;
       
  4955 	}
       
  4956 	if        ( is_S(c) ) {
       
  4957 	    input = InpWs;
       
  4958 	} else if ( c == '%' ) {
       
  4959 	    input = InpPer;
       
  4960 	} else if ( c == '"' || c == '\'' ) {
       
  4961 	    input = InpQuot;
       
  4962 	} else if ( c == '>' ) {
       
  4963 	    input = InpGt;
       
  4964 	} else if ( c == 'N' ) {
       
  4965 	    input = InpN;
       
  4966 	} else {
       
  4967 	    input = InpUnknown;
       
  4968 	}
       
  4969 
       
  4970 	// set state according to input
       
  4971 	state = table[state][input];
       
  4972 
       
  4973 	// do some actions according to state
       
  4974 	switch ( state ) {
       
  4975 	    case Ent:
       
  4976 		parseOk = parseString( "NTITY" );
       
  4977 		break;
       
  4978 	    case Ws1:
       
  4979 		eat_ws();
       
  4980 		break;
       
  4981 	    case Name:
       
  4982 		parseOk = parseName();
       
  4983 		break;
       
  4984 	    case Ws2:
       
  4985 		eat_ws();
       
  4986 		break;
       
  4987 	    case EValue:
       
  4988 		parseOk = parseEntityValue();
       
  4989 		break;
       
  4990 	    case ExtID:
       
  4991 		parseOk = parseExternalID();
       
  4992 		break;
       
  4993 	    case Ws3:
       
  4994 		eat_ws();
       
  4995 		break;
       
  4996 	    case Ndata:
       
  4997 		parseOk = parseString( "NDATA" );
       
  4998 		break;
       
  4999 	    case Ws4:
       
  5000 		eat_ws();
       
  5001 		break;
       
  5002 	    case NNam:
       
  5003 		parseOk = parseName( TRUE );
       
  5004 		break;
       
  5005 	    case PEDec:
       
  5006 		next();
       
  5007 		break;
       
  5008 	    case Ws6:
       
  5009 		eat_ws();
       
  5010 		break;
       
  5011 	    case PENam:
       
  5012 		parseOk = parseName();
       
  5013 		break;
       
  5014 	    case Ws7:
       
  5015 		eat_ws();
       
  5016 		break;
       
  5017 	    case PEVal:
       
  5018 		parseOk = parseEntityValue();
       
  5019 		break;
       
  5020 	    case PEEID:
       
  5021 		parseOk = parseExternalID();
       
  5022 		break;
       
  5023 	    case WsE:
       
  5024 		eat_ws();
       
  5025 		break;
       
  5026 	    case EDDone:
       
  5027 		next();
       
  5028 		break;
       
  5029 	    case Done:
       
  5030 		next();
       
  5031 		break;
       
  5032 	}
       
  5033 	// no input is read after this
       
  5034 	switch ( state ) {
       
  5035 	    case Ent:
       
  5036 		if ( !parseOk ) {
       
  5037 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  5038 		    goto parseError;
       
  5039 		}
       
  5040 		break;
       
  5041 	    case Name:
       
  5042 		if ( !parseOk ) {
       
  5043 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  5044 		    goto parseError;
       
  5045 		}
       
  5046 		break;
       
  5047 	    case EValue:
       
  5048 		if ( !parseOk ) {
       
  5049 		    d->error = XMLERR_ERRORPARSINGENTITYVALUE;
       
  5050 		    goto parseError;
       
  5051 		}
       
  5052 		if (  !entityExist( name() ) ) {
       
  5053 		    d->entities.insert( name(), string() );
       
  5054 		    if ( declHnd ) {
       
  5055 			if ( !declHnd->internalEntityDecl( name(), string() ) ) {
       
  5056 			    d->error = declHnd->errorString();
       
  5057 			    goto parseError;
       
  5058 			}
       
  5059 		    }
       
  5060 		}
       
  5061 		break;
       
  5062 	    case ExtID:
       
  5063 		if ( !parseOk ) {
       
  5064 		    d->error = XMLERR_ERRORPARSINGEXTERNALID;
       
  5065 		    goto parseError;
       
  5066 		}
       
  5067 		break;
       
  5068 	    case Ndata:
       
  5069 		if ( !parseOk ) {
       
  5070 		    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  5071 		    goto parseError;
       
  5072 		}
       
  5073 		break;
       
  5074 	    case NNam:
       
  5075 		if ( !parseOk ) {
       
  5076 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  5077 		    goto parseError;
       
  5078 		}
       
  5079 		if (  !entityExist( name() ) ) {
       
  5080 		    d->externEntities.insert( name(), QXmlSimpleReaderPrivate::ExternEntity( d->publicId, d->systemId, ref() ) );
       
  5081 		    if ( dtdHnd ) {
       
  5082 			if ( !dtdHnd->unparsedEntityDecl( name(), d->publicId, d->systemId, ref() ) ) {
       
  5083 			    d->error = declHnd->errorString();
       
  5084 			    goto parseError;
       
  5085 			}
       
  5086 		    }
       
  5087 		}
       
  5088 		break;
       
  5089 	    case PENam:
       
  5090 		if ( !parseOk ) {
       
  5091 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  5092 		    goto parseError;
       
  5093 		}
       
  5094 		break;
       
  5095 	    case PEVal:
       
  5096 		if ( !parseOk ) {
       
  5097 		    d->error = XMLERR_ERRORPARSINGENTITYVALUE;
       
  5098 		    goto parseError;
       
  5099 		}
       
  5100 		if (  !entityExist( name() ) ) {
       
  5101 		    d->parameterEntities.insert( name(), string() );
       
  5102 		    if ( declHnd ) {
       
  5103 			if ( !declHnd->internalEntityDecl( QString("%")+name(), string() ) ) {
       
  5104 			    d->error = declHnd->errorString();
       
  5105 			    goto parseError;
       
  5106 			}
       
  5107 		    }
       
  5108 		}
       
  5109 		break;
       
  5110 	    case PEEID:
       
  5111 		if ( !parseOk ) {
       
  5112 		    d->error = XMLERR_ERRORPARSINGEXTERNALID;
       
  5113 		    goto parseError;
       
  5114 		}
       
  5115 		if (  !entityExist( name() ) ) {
       
  5116 		    d->externParameterEntities.insert( name(), QXmlSimpleReaderPrivate::ExternParameterEntity( d->publicId, d->systemId ) );
       
  5117 		    if ( declHnd ) {
       
  5118 			if ( !declHnd->externalEntityDecl( QString("%")+name(), d->publicId, d->systemId ) ) {
       
  5119 			    d->error = declHnd->errorString();
       
  5120 			    goto parseError;
       
  5121 			}
       
  5122 		    }
       
  5123 		}
       
  5124 		break;
       
  5125 	    case EDDone:
       
  5126 		if (  !entityExist( name() ) ) {
       
  5127 		    d->externEntities.insert( name(), QXmlSimpleReaderPrivate::ExternEntity( d->publicId, d->systemId, QString::null ) );
       
  5128 		    if ( declHnd ) {
       
  5129 			if ( !declHnd->externalEntityDecl( name(), d->publicId, d->systemId ) ) {
       
  5130 			    d->error = declHnd->errorString();
       
  5131 			    goto parseError;
       
  5132 			}
       
  5133 		    }
       
  5134 		}
       
  5135 		return TRUE;
       
  5136 	    case Done:
       
  5137 		return TRUE;
       
  5138 	    case -1:
       
  5139 		// Error
       
  5140 		d->error = XMLERR_LETTEREXPECTED;
       
  5141 		goto parseError;
       
  5142 	}
       
  5143 
       
  5144     }
       
  5145 
       
  5146     return TRUE;
       
  5147 
       
  5148 parseError:
       
  5149     reportParseError();
       
  5150     return FALSE;
       
  5151 }
       
  5152 
       
  5153 /*!
       
  5154   Parse a EntityValue [9]
       
  5155 */
       
  5156 bool QXmlSimpleReader::parseEntityValue()
       
  5157 {
       
  5158     bool tmp;
       
  5159 
       
  5160     const signed char Init             = 0;
       
  5161     const signed char Dq               = 1; // EntityValue is double quoted
       
  5162     const signed char DqC              = 2; // signed character
       
  5163     const signed char DqPER            = 3; // PERefence
       
  5164     const signed char DqRef            = 4; // Reference
       
  5165     const signed char Sq               = 5; // EntityValue is double quoted
       
  5166     const signed char SqC              = 6; // signed character
       
  5167     const signed char SqPER            = 7; // PERefence
       
  5168     const signed char SqRef            = 8; // Reference
       
  5169     const signed char Done             = 9;
       
  5170 
       
  5171     const signed char InpDq            = 0; // "
       
  5172     const signed char InpSq            = 1; // '
       
  5173     const signed char InpAmp           = 2; // &
       
  5174     const signed char InpPer           = 3; // %
       
  5175     const signed char InpUnknown       = 4;
       
  5176 
       
  5177     // use some kind of state machine for parsing
       
  5178     static signed char table[9][5] = {
       
  5179      /*  InpDq  InpSq  InpAmp  InpPer  InpUnknown */
       
  5180 	{ Dq,    Sq,    -1,     -1,     -1    }, // Init
       
  5181 	{ Done,  DqC,   DqRef,  DqPER,  DqC   }, // Dq
       
  5182 	{ Done,  DqC,   DqRef,  DqPER,  DqC   }, // DqC
       
  5183 	{ Done,  DqC,   DqRef,  DqPER,  DqC   }, // DqPER
       
  5184 	{ Done,  DqC,   DqRef,  DqPER,  DqC   }, // DqRef
       
  5185 	{ SqC,   Done,  SqRef,  SqPER,  SqC   }, // Sq
       
  5186 	{ SqC,   Done,  SqRef,  SqPER,  SqC   }, // SqC
       
  5187 	{ SqC,   Done,  SqRef,  SqPER,  SqC   }, // SqPER
       
  5188 	{ SqC,   Done,  SqRef,  SqPER,  SqC   }  // SqRef
       
  5189     };
       
  5190     signed char state = Init;
       
  5191     signed char input;
       
  5192     bool parseOk = TRUE;
       
  5193 
       
  5194     while ( TRUE ) {
       
  5195 
       
  5196 	// get input
       
  5197 	if ( atEnd() ) {
       
  5198 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  5199 	    goto parseError;
       
  5200 	}
       
  5201 	if        ( c == '"' ) {
       
  5202 	    input = InpDq;
       
  5203 	} else if ( c == '\'' ) {
       
  5204 	    input = InpSq;
       
  5205 	} else if ( c == '&' ) {
       
  5206 	    input = InpAmp;
       
  5207 	} else if ( c == '%' ) {
       
  5208 	    input = InpPer;
       
  5209 	} else {
       
  5210 	    input = InpUnknown;
       
  5211 	}
       
  5212 
       
  5213 	// set state according to input
       
  5214 	state = table[state][input];
       
  5215 
       
  5216 	// do some actions according to state
       
  5217 	switch ( state ) {
       
  5218 	    case Dq:
       
  5219 	    case Sq:
       
  5220 		stringClear();
       
  5221 		next();
       
  5222 		break;
       
  5223 	    case DqC:
       
  5224 	    case SqC:
       
  5225 		stringAddC();
       
  5226 		next();
       
  5227 		break;
       
  5228 	    case DqPER:
       
  5229 	    case SqPER:
       
  5230 		parseOk = parsePEReference( InEntityValue );
       
  5231 		break;
       
  5232 	    case DqRef:
       
  5233 	    case SqRef:
       
  5234 		parseOk = parseReference( tmp, InEntityValue );
       
  5235 		break;
       
  5236 	    case Done:
       
  5237 		next();
       
  5238 		break;
       
  5239 	}
       
  5240 	// no input is read after this
       
  5241 	switch ( state ) {
       
  5242 	    case DqPER:
       
  5243 	    case SqPER:
       
  5244 		if ( !parseOk ) {
       
  5245 		    d->error = XMLERR_ERRORPARSINGDOCTYPE;
       
  5246 		    goto parseError;
       
  5247 		}
       
  5248 		break;
       
  5249 	    case DqRef:
       
  5250 	    case SqRef:
       
  5251 		if ( !parseOk ) {
       
  5252 		    d->error = XMLERR_ERRORPARSINGREFERENCE;
       
  5253 		    goto parseError;
       
  5254 		}
       
  5255 		break;
       
  5256 	    case Done:
       
  5257 		return TRUE;
       
  5258 	    case -1:
       
  5259 		// Error
       
  5260 		d->error = XMLERR_LETTEREXPECTED;
       
  5261 		goto parseError;
       
  5262 	}
       
  5263 
       
  5264     }
       
  5265 
       
  5266     return TRUE;
       
  5267 
       
  5268 parseError:
       
  5269     reportParseError();
       
  5270     return FALSE;
       
  5271 }
       
  5272 
       
  5273 /*!
       
  5274   Parse a comment [15].
       
  5275 
       
  5276   Precondition: the beginning '<!' of the comment is already read and the head
       
  5277   stands on the first '-' of '<!--'.
       
  5278 
       
  5279   If this funktion was successful, the head-position is on the first
       
  5280   character after the comment.
       
  5281 */
       
  5282 bool QXmlSimpleReader::parseComment()
       
  5283 {
       
  5284     const signed char Init             = 0;
       
  5285     const signed char Dash1            = 1; // the first dash was read
       
  5286     const signed char Dash2            = 2; // the second dash was read
       
  5287     const signed char Com              = 3; // read comment
       
  5288     const signed char Com2             = 4; // read comment (help state)
       
  5289     const signed char ComE             = 5; // finished reading comment
       
  5290     const signed char Done             = 6;
       
  5291 
       
  5292     const signed char InpDash          = 0; // -
       
  5293     const signed char InpGt            = 1; // >
       
  5294     const signed char InpUnknown       = 2;
       
  5295 
       
  5296     // use some kind of state machine for parsing
       
  5297     static signed char table[6][3] = {
       
  5298      /*  InpDash  InpGt  InpUnknown */
       
  5299 	{ Dash1,   -1,    -1  }, // Init
       
  5300 	{ Dash2,   -1,    -1  }, // Dash1
       
  5301 	{ Com2,    Com,   Com }, // Dash2
       
  5302 	{ Com2,    Com,   Com }, // Com
       
  5303 	{ ComE,    Com,   Com }, // Com2
       
  5304 	{ -1,      Done,  -1  }  // ComE
       
  5305     };
       
  5306     signed char state = Init;
       
  5307     signed char input;
       
  5308 
       
  5309     while ( TRUE ) {
       
  5310 
       
  5311 	// get input
       
  5312 	if ( atEnd() ) {
       
  5313 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  5314 	    goto parseError;
       
  5315 	}
       
  5316 	if        ( c == '-' ) {
       
  5317 	    input = InpDash;
       
  5318 	} else if ( c == '>' ) {
       
  5319 	    input = InpGt;
       
  5320 	} else {
       
  5321 	    input = InpUnknown;
       
  5322 	}
       
  5323 
       
  5324 	// set state according to input
       
  5325 	state = table[state][input];
       
  5326 
       
  5327 	// do some actions according to state
       
  5328 	switch ( state ) {
       
  5329 	    case Dash1:
       
  5330 		next();
       
  5331 		break;
       
  5332 	    case Dash2:
       
  5333 		next();
       
  5334 		break;
       
  5335 	    case Com:
       
  5336 		stringAddC();
       
  5337 		next();
       
  5338 		break;
       
  5339 	    case Com2:
       
  5340 		next();
       
  5341 		break;
       
  5342 	    case ComE:
       
  5343 		next();
       
  5344 		break;
       
  5345 	    case Done:
       
  5346 		next();
       
  5347 		break;
       
  5348 	}
       
  5349 	// no input is read after this
       
  5350 	switch ( state ) {
       
  5351 	    case Dash2:
       
  5352 		stringClear();
       
  5353 		break;
       
  5354 	    case Com2:
       
  5355 		// if next character is not a dash than don't skip it
       
  5356 		if ( c != '-' ) {
       
  5357 		    stringAddC( '-' );
       
  5358 		}
       
  5359 		break;
       
  5360 	    case Done:
       
  5361 		return TRUE;
       
  5362 	    case -1:
       
  5363 		// Error
       
  5364 		d->error = XMLERR_ERRORPARSINGCOMMENT;
       
  5365 		goto parseError;
       
  5366 	}
       
  5367 
       
  5368     }
       
  5369 
       
  5370     return TRUE;
       
  5371 
       
  5372 parseError:
       
  5373     reportParseError();
       
  5374     return FALSE;
       
  5375 }
       
  5376 
       
  5377 /*!
       
  5378   Parse a Attribute [41].
       
  5379 
       
  5380   Precondition: the head stands on the first character of the name of the
       
  5381   attribute (i.e. all whitespaces are already parsed).
       
  5382 
       
  5383   The head stand on the next character after the end quotes. The variable name
       
  5384   contains the name of the attribute and the variable string contains the value
       
  5385   of the attribute.
       
  5386 */
       
  5387 bool QXmlSimpleReader::parseAttribute()
       
  5388 {
       
  5389     const signed char Init             = 0;
       
  5390     const signed char PName            = 1; // parse name
       
  5391     const signed char Ws               = 2; // eat ws
       
  5392     const signed char Eq               = 3; // the '=' was read
       
  5393     const signed char Quotes           = 4; // " or ' were read
       
  5394 
       
  5395     const signed char InpNameBe        = 0;
       
  5396     const signed char InpEq            = 1; // =
       
  5397     const signed char InpDq            = 2; // "
       
  5398     const signed char InpSq            = 3; // '
       
  5399     const signed char InpUnknown       = 4;
       
  5400 
       
  5401     // use some kind of state machine for parsing
       
  5402     static signed char table[4][5] = {
       
  5403      /*  InpNameBe  InpEq  InpDq    InpSq    InpUnknown */
       
  5404 	{ PName,     -1,    -1,      -1,      -1    }, // Init
       
  5405 	{ -1,        Eq,    -1,      -1,      Ws    }, // PName
       
  5406 	{ -1,        Eq,    -1,      -1,      -1    }, // Ws
       
  5407 	{ -1,        -1,    Quotes,  Quotes,  -1    }  // Eq
       
  5408     };
       
  5409     signed char state = Init;
       
  5410     signed char input;
       
  5411     bool parseOk = TRUE;
       
  5412 
       
  5413     while ( TRUE ) {
       
  5414 
       
  5415 	// get input
       
  5416 	if ( atEnd() ) {
       
  5417 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  5418 	    goto parseError;
       
  5419 	}
       
  5420 	if        ( is_NameBeginning(c) ) {
       
  5421 	    input = InpNameBe;
       
  5422 	} else if ( c == '=' ) {
       
  5423 	    input = InpEq;
       
  5424 	} else if ( c == '"' ) {
       
  5425 	    input = InpDq;
       
  5426 	} else if ( c == '\'' ) {
       
  5427 	    input = InpSq;
       
  5428 	} else {
       
  5429 	    input = InpUnknown;
       
  5430 	}
       
  5431 
       
  5432 	// set state according to input
       
  5433 	state = table[state][input];
       
  5434 
       
  5435 	// do some actions according to state
       
  5436 	switch ( state ) {
       
  5437 	    case PName:
       
  5438 		parseOk = parseName();
       
  5439 		break;
       
  5440 	    case Ws:
       
  5441 		eat_ws();
       
  5442 		break;
       
  5443 	    case Eq:
       
  5444 		next_eat_ws();
       
  5445 		break;
       
  5446 	    case Quotes:
       
  5447 		parseOk = parseAttValue();
       
  5448 		break;
       
  5449 	}
       
  5450 	// no input is read after this
       
  5451 	switch ( state ) {
       
  5452 	    case PName:
       
  5453 		if ( !parseOk ) {
       
  5454 		    d->error = XMLERR_ERRORPARSINGNAME;
       
  5455 		    goto parseError;
       
  5456 		}
       
  5457 		break;
       
  5458 	    case Quotes:
       
  5459 		if ( !parseOk ) {
       
  5460 		    d->error = XMLERR_ERRORPARSINGATTVALUE;
       
  5461 		    goto parseError;
       
  5462 		}
       
  5463 		// Done
       
  5464 		return TRUE;
       
  5465 	    case -1:
       
  5466 		// Error
       
  5467 		d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  5468 		goto parseError;
       
  5469 	}
       
  5470 
       
  5471     }
       
  5472 
       
  5473     return TRUE;
       
  5474 
       
  5475 parseError:
       
  5476     reportParseError();
       
  5477     return FALSE;
       
  5478 }
       
  5479 
       
  5480 /*!
       
  5481   Parse a Name [5] and store the name in name or ref (if useRef is TRUE).
       
  5482 */
       
  5483 bool QXmlSimpleReader::parseName( bool useRef )
       
  5484 {
       
  5485     const signed char Init             = 0;
       
  5486     const signed char Name1            = 1; // parse first signed character of the name
       
  5487     const signed char Name             = 2; // parse name
       
  5488     const signed char Done             = 3;
       
  5489 
       
  5490     const signed char InpNameBe        = 0; // name beginning signed characters
       
  5491     const signed char InpNameCh        = 1; // NameChar without InpNameBe
       
  5492     const signed char InpUnknown       = 2;
       
  5493 
       
  5494     // use some kind of state machine for parsing
       
  5495     static signed char table[3][3] = {
       
  5496      /*  InpNameBe  InpNameCh  InpUnknown */
       
  5497 	{ Name1,     -1,        -1    }, // Init
       
  5498 	{ Name,      Name,      Done  }, // Name1
       
  5499 	{ Name,      Name,      Done  }  // Name
       
  5500     };
       
  5501     signed char state = Init;
       
  5502     signed char input;
       
  5503 
       
  5504     while ( TRUE ) {
       
  5505 
       
  5506 	// get input
       
  5507 	if ( atEnd() ) {
       
  5508 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  5509 	    goto parseError;
       
  5510 	}
       
  5511 	if        ( is_NameBeginning(c) ) {
       
  5512 	    input = InpNameBe;
       
  5513 	} else if ( is_NameChar(c) ) {
       
  5514 	    input = InpNameCh;
       
  5515 	} else {
       
  5516 	    input = InpUnknown;
       
  5517 	}
       
  5518 
       
  5519 	// set state according to input
       
  5520 	state = table[state][input];
       
  5521 
       
  5522 	// do some actions according to state
       
  5523 	switch ( state ) {
       
  5524 	    case Name1:
       
  5525 		if ( useRef ) {
       
  5526 		    refClear();
       
  5527 		    refAddC();
       
  5528 		} else {
       
  5529 		    nameClear();
       
  5530 		    nameAddC();
       
  5531 		}
       
  5532 		next();
       
  5533 		break;
       
  5534 	    case Name:
       
  5535 		if ( useRef ) {
       
  5536 		    refAddC();
       
  5537 		} else {
       
  5538 		    nameAddC();
       
  5539 		}
       
  5540 		next();
       
  5541 		break;
       
  5542 	}
       
  5543 	// no input is read after this
       
  5544 	switch ( state ) {
       
  5545 	    case Done:
       
  5546 		return TRUE;
       
  5547 	    case -1:
       
  5548 		// Error
       
  5549 		d->error = XMLERR_LETTEREXPECTED;
       
  5550 		goto parseError;
       
  5551 	}
       
  5552 
       
  5553     }
       
  5554 
       
  5555     return TRUE;
       
  5556 
       
  5557 parseError:
       
  5558     reportParseError();
       
  5559     return FALSE;
       
  5560 }
       
  5561 
       
  5562 /*!
       
  5563   Parse a Nmtoken [7] and store the name in name.
       
  5564 */
       
  5565 bool QXmlSimpleReader::parseNmtoken()
       
  5566 {
       
  5567     const signed char Init             = 0;
       
  5568     const signed char NameF            = 1;
       
  5569     const signed char Name             = 2;
       
  5570     const signed char Done             = 3;
       
  5571 
       
  5572     const signed char InpNameCh        = 0; // NameChar without InpNameBe
       
  5573     const signed char InpUnknown       = 1;
       
  5574 
       
  5575     // use some kind of state machine for parsing
       
  5576     static signed char table[3][2] = {
       
  5577      /*  InpNameCh  InpUnknown */
       
  5578 	{ NameF,     -1    }, // Init
       
  5579 	{ Name,      Done  }, // NameF
       
  5580 	{ Name,      Done  }  // Name
       
  5581     };
       
  5582     signed char state = Init;
       
  5583     signed char input;
       
  5584 
       
  5585     while ( TRUE ) {
       
  5586 
       
  5587 	// get input
       
  5588 	if ( atEnd() ) {
       
  5589 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  5590 	    goto parseError;
       
  5591 	}
       
  5592 	if ( is_NameChar(c) ) {
       
  5593 	    input = InpNameCh;
       
  5594 	} else {
       
  5595 	    input = InpUnknown;
       
  5596 	}
       
  5597 
       
  5598 	// set state according to input
       
  5599 	state = table[state][input];
       
  5600 
       
  5601 	// do some actions according to state
       
  5602 	switch ( state ) {
       
  5603 	    case NameF:
       
  5604 		nameClear();
       
  5605 		nameAddC();
       
  5606 		next();
       
  5607 		break;
       
  5608 	    case Name:
       
  5609 		nameAddC();
       
  5610 		next();
       
  5611 		break;
       
  5612 	}
       
  5613 	// no input is read after this
       
  5614 	switch ( state ) {
       
  5615 	    case Done:
       
  5616 		return TRUE;
       
  5617 	    case -1:
       
  5618 		// Error
       
  5619 		d->error = XMLERR_LETTEREXPECTED;
       
  5620 		goto parseError;
       
  5621 	}
       
  5622 
       
  5623     }
       
  5624 
       
  5625     return TRUE;
       
  5626 
       
  5627 parseError:
       
  5628     reportParseError();
       
  5629     return FALSE;
       
  5630 }
       
  5631 
       
  5632 /*!
       
  5633   Parse a Reference [67].
       
  5634 
       
  5635   charDataRead is set to TRUE if the reference must not be parsed. The
       
  5636   character(s) which the reference mapped to are appended to string. The
       
  5637   head stands on the first character after the reference.
       
  5638 
       
  5639   charDataRead is set to FALSE if the reference must be parsed. The
       
  5640   charachter(s) which the reference mapped to are inserted at the reference
       
  5641   position. The head stands on the first character of the replacement).
       
  5642 */
       
  5643 bool QXmlSimpleReader::parseReference( bool &charDataRead, EntityRecognitionContext context )
       
  5644 {
       
  5645     // temporary variables
       
  5646     uint tmp;
       
  5647     bool ok;
       
  5648 
       
  5649     const signed char Init             =  0;
       
  5650     const signed char SRef             =  1; // start of a reference
       
  5651     const signed char ChRef            =  2; // parse CharRef
       
  5652     const signed char ChDec            =  3; // parse CharRef decimal
       
  5653     const signed char ChHexS           =  4; // start CharRef hexadecimal
       
  5654     const signed char ChHex            =  5; // parse CharRef hexadecimal
       
  5655     const signed char Name             =  6; // parse name
       
  5656     const signed char DoneD            =  7; // done CharRef decimal
       
  5657     const signed char DoneH            =  8; // done CharRef hexadecimal
       
  5658     const signed char DoneN            =  9; // done EntityRef
       
  5659 
       
  5660     const signed char InpAmp           = 0; // &
       
  5661     const signed char InpSemi          = 1; // ;
       
  5662     const signed char InpHash          = 2; // #
       
  5663     const signed char InpX             = 3; // x
       
  5664     const signed char InpNum           = 4; // 0-9
       
  5665     const signed char InpHex           = 5; // a-f A-F
       
  5666     const signed char InpUnknown       = 6;
       
  5667 
       
  5668     // use some kind of state machine for parsing
       
  5669     static signed char table[8][7] = {
       
  5670      /*  InpAmp  InpSemi  InpHash  InpX     InpNum  InpHex  InpUnknown */
       
  5671 	{ SRef,   -1,      -1,      -1,      -1,     -1,     -1    }, // Init
       
  5672 	{ -1,     -1,      ChRef,   Name,    Name,   Name,   Name  }, // SRef
       
  5673 	{ -1,     -1,      -1,      ChHexS,  ChDec,  -1,     -1    }, // ChRef
       
  5674 	{ -1,     DoneD,   -1,      -1,      ChDec,  -1,     -1    }, // ChDec
       
  5675 	{ -1,     -1,      -1,      -1,      ChHex,  ChHex,  -1    }, // ChHexS
       
  5676 	{ -1,     DoneH,   -1,      -1,      ChHex,  ChHex,  -1    }, // ChHex
       
  5677 	{ -1,     DoneN,   -1,      -1,      -1,     -1,     -1    }  // Name
       
  5678     };
       
  5679     signed char state = Init;
       
  5680     signed char input;
       
  5681 
       
  5682     while ( TRUE ) {
       
  5683 
       
  5684 	// get input
       
  5685 	if ( atEnd() ) {
       
  5686 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  5687 	    goto parseError;
       
  5688 	}
       
  5689 	if        ( c.row() ) {
       
  5690 	    input = InpUnknown;
       
  5691 	} else if ( c.cell() == '&' ) {
       
  5692 	    input = InpAmp;
       
  5693 	} else if ( c.cell() == ';' ) {
       
  5694 	    input = InpSemi;
       
  5695 	} else if ( c.cell() == '#' ) {
       
  5696 	    input = InpHash;
       
  5697 	} else if ( c.cell() == 'x' ) {
       
  5698 	    input = InpX;
       
  5699 	} else if ( '0' <= c.cell() && c.cell() <= '9' ) {
       
  5700 	    input = InpNum;
       
  5701 	} else if ( 'a' <= c.cell() && c.cell() <= 'f' ) {
       
  5702 	    input = InpHex;
       
  5703 	} else if ( 'A' <= c.cell() && c.cell() <= 'F' ) {
       
  5704 	    input = InpHex;
       
  5705 	} else {
       
  5706 	    input = InpUnknown;
       
  5707 	}
       
  5708 
       
  5709 	// set state according to input
       
  5710 	state = table[state][input];
       
  5711 
       
  5712 	// do some actions according to state
       
  5713 	switch ( state ) {
       
  5714 	    case SRef:
       
  5715 		refClear();
       
  5716 		next();
       
  5717 		break;
       
  5718 	    case ChRef:
       
  5719 		next();
       
  5720 		break;
       
  5721 	    case ChDec:
       
  5722 		refAddC();
       
  5723 		next();
       
  5724 		break;
       
  5725 	    case ChHexS:
       
  5726 		next();
       
  5727 		break;
       
  5728 	    case ChHex:
       
  5729 		refAddC();
       
  5730 		next();
       
  5731 		break;
       
  5732 	    case Name:
       
  5733 		// read the name into the ref
       
  5734 		parseName( TRUE );
       
  5735 		break;
       
  5736 	    case DoneD:
       
  5737 		tmp = ref().toUInt( &ok, 10 );
       
  5738 		if ( ok ) {
       
  5739 		    stringAddC( QChar(tmp) );
       
  5740 		} else {
       
  5741 		    d->error = XMLERR_ERRORPARSINGREFERENCE;
       
  5742 		    goto parseError;
       
  5743 		}
       
  5744 		charDataRead = TRUE;
       
  5745 		next();
       
  5746 		break;
       
  5747 	    case DoneH:
       
  5748 		tmp = ref().toUInt( &ok, 16 );
       
  5749 		if ( ok ) {
       
  5750 		    stringAddC( QChar(tmp) );
       
  5751 		} else {
       
  5752 		    d->error = XMLERR_ERRORPARSINGREFERENCE;
       
  5753 		    goto parseError;
       
  5754 		}
       
  5755 		charDataRead = TRUE;
       
  5756 		next();
       
  5757 		break;
       
  5758 	    case DoneN:
       
  5759 		if ( !processReference( charDataRead, context ) )
       
  5760 		    goto parseError;
       
  5761 		next();
       
  5762 		break;
       
  5763 	}
       
  5764 	// no input is read after this
       
  5765 	switch ( state ) {
       
  5766 	    case DoneD:
       
  5767 		return TRUE;
       
  5768 	    case DoneH:
       
  5769 		return TRUE;
       
  5770 	    case DoneN:
       
  5771 		return TRUE;
       
  5772 	    case -1:
       
  5773 		// Error
       
  5774 		d->error = XMLERR_ERRORPARSINGREFERENCE;
       
  5775 		goto parseError;
       
  5776 	}
       
  5777 
       
  5778     }
       
  5779 
       
  5780     return TRUE;
       
  5781 
       
  5782 parseError:
       
  5783     reportParseError();
       
  5784     return FALSE;
       
  5785 }
       
  5786 
       
  5787 /*!
       
  5788   Helper function for parseReference()
       
  5789 */
       
  5790 bool QXmlSimpleReader::processReference( bool &charDataRead, EntityRecognitionContext context )
       
  5791 {
       
  5792     QString reference = ref();
       
  5793     if ( reference == "amp" ) {
       
  5794 	if ( context == InEntityValue ) {
       
  5795 	    // Bypassed
       
  5796 	    stringAddC( '&' ); stringAddC( 'a' ); stringAddC( 'm' ); stringAddC( 'p' ); stringAddC( ';' );
       
  5797 	} else {
       
  5798 	    // Included or Included in literal
       
  5799 	    stringAddC( '&' );
       
  5800 	}
       
  5801 	charDataRead = TRUE;
       
  5802     } else if ( reference == "lt" ) {
       
  5803 	if ( context == InEntityValue ) {
       
  5804 	    // Bypassed
       
  5805 	    stringAddC( '&' ); stringAddC( 'l' ); stringAddC( 't' ); stringAddC( ';' );
       
  5806 	} else {
       
  5807 	    // Included or Included in literal
       
  5808 	    stringAddC( '<' );
       
  5809 	}
       
  5810 	charDataRead = TRUE;
       
  5811     } else if ( reference == "gt" ) {
       
  5812 	if ( context == InEntityValue ) {
       
  5813 	    // Bypassed
       
  5814 	    stringAddC( '&' ); stringAddC( 'g' ); stringAddC( 't' ); stringAddC( ';' );
       
  5815 	} else {
       
  5816 	    // Included or Included in literal
       
  5817 	    stringAddC( '>' );
       
  5818 	}
       
  5819 	charDataRead = TRUE;
       
  5820     } else if ( reference == "apos" ) {
       
  5821 	if ( context == InEntityValue ) {
       
  5822 	    // Bypassed
       
  5823 	    stringAddC( '&' ); stringAddC( 'a' ); stringAddC( 'p' ); stringAddC( 'o' ); stringAddC( 's' ); stringAddC( ';' );
       
  5824 	} else {
       
  5825 	    // Included or Included in literal
       
  5826 	    stringAddC( '\'' );
       
  5827 	}
       
  5828 	charDataRead = TRUE;
       
  5829     } else if ( reference == "quot" ) {
       
  5830 	if ( context == InEntityValue ) {
       
  5831 	    // Bypassed
       
  5832 	    stringAddC( '&' ); stringAddC( 'q' ); stringAddC( 'u' ); stringAddC( 'o' ); stringAddC( 't' ); stringAddC( ';' );
       
  5833 	} else {
       
  5834 	    // Included or Included in literal
       
  5835 	    stringAddC( '"' );
       
  5836 	}
       
  5837 	charDataRead = TRUE;
       
  5838     } else {
       
  5839 	QMap<QString,QString>::Iterator it;
       
  5840 	it = d->entities.find( reference );
       
  5841 	if ( it != d->entities.end() ) {
       
  5842 	    // "Internal General"
       
  5843 	    switch ( context ) {
       
  5844 		case InContent:
       
  5845 		    // Included
       
  5846 		    xmlRef = it.data() + xmlRef;
       
  5847 		    charDataRead = FALSE;
       
  5848 		    break;
       
  5849 		case InAttributeValue:
       
  5850 		    // Included in literal
       
  5851 		    xmlRef = it.data().replace( QRegExp("\""), "&quot;" ).replace( QRegExp("'"), "&apos;" )
       
  5852 			+ xmlRef;
       
  5853 		    charDataRead = FALSE;
       
  5854 		    break;
       
  5855 		case InEntityValue:
       
  5856 		    {
       
  5857 			// Bypassed
       
  5858 			stringAddC( '&' );
       
  5859 			for ( int i=0; i<(int)reference.length(); i++ ) {
       
  5860 			    stringAddC( reference[i] );
       
  5861 			}
       
  5862 			stringAddC( ';');
       
  5863 			charDataRead = TRUE;
       
  5864 		    }
       
  5865 		    break;
       
  5866 		case InDTD:
       
  5867 		    // Forbidden
       
  5868 		    d->error = XMLERR_INTERNALGENERALENTITYINDTD;
       
  5869 		    charDataRead = FALSE;
       
  5870 		    break;
       
  5871 	    }
       
  5872 	} else {
       
  5873 	    QMap<QString,QXmlSimpleReaderPrivate::ExternEntity>::Iterator itExtern;
       
  5874 	    itExtern = d->externEntities.find( reference );
       
  5875 	    if ( itExtern == d->externEntities.end() ) {
       
  5876 		// entity not declared
       
  5877 		// ### check this case for conformance
       
  5878 		if ( context == InEntityValue ) {
       
  5879 		    // Bypassed
       
  5880 		    stringAddC( '&' );
       
  5881 		    for ( int i=0; i<(int)reference.length(); i++ ) {
       
  5882 			stringAddC( reference[i] );
       
  5883 		    }
       
  5884 		    stringAddC( ';');
       
  5885 		    charDataRead = TRUE;
       
  5886 		} else {
       
  5887 		    if ( contentHnd ) {
       
  5888 			if ( !contentHnd->skippedEntity( reference ) ) {
       
  5889 			    d->error = contentHnd->errorString();
       
  5890 			    return FALSE; // error
       
  5891 			}
       
  5892 		    }
       
  5893 		}
       
  5894 	    } else if ( (*itExtern).notation.isNull() ) {
       
  5895 		// "External Parsed General"
       
  5896 		switch ( context ) {
       
  5897 		    case InContent:
       
  5898 			// Included if validating
       
  5899 			if ( contentHnd ) {
       
  5900 			    if ( !contentHnd->skippedEntity( reference ) ) {
       
  5901 				d->error = contentHnd->errorString();
       
  5902 				return FALSE; // error
       
  5903 			    }
       
  5904 			}
       
  5905 			charDataRead = FALSE;
       
  5906 			break;
       
  5907 		    case InAttributeValue:
       
  5908 			// Forbidden
       
  5909 			d->error = XMLERR_EXTERNALGENERALENTITYINAV;
       
  5910 			charDataRead = FALSE;
       
  5911 			break;
       
  5912 		    case InEntityValue:
       
  5913 			{
       
  5914 			    // Bypassed
       
  5915 			    stringAddC( '&' );
       
  5916 			    for ( int i=0; i<(int)reference.length(); i++ ) {
       
  5917 				stringAddC( reference[i] );
       
  5918 			    }
       
  5919 			    stringAddC( ';');
       
  5920 			    charDataRead = TRUE;
       
  5921 			}
       
  5922 			break;
       
  5923 		    case InDTD:
       
  5924 			// Forbidden
       
  5925 			d->error = XMLERR_EXTERNALGENERALENTITYINDTD;
       
  5926 			charDataRead = FALSE;
       
  5927 			break;
       
  5928 		}
       
  5929 	    } else {
       
  5930 		// "Unparsed"
       
  5931 		// ### notify for "Occurs as Attribute Value" missing (but this is no refence, anyway)
       
  5932 		// Forbidden
       
  5933 		d->error = XMLERR_UNPARSEDENTITYREFERENCE;
       
  5934 		charDataRead = FALSE;
       
  5935 		return FALSE; // error
       
  5936 	    }
       
  5937 	}
       
  5938     }
       
  5939     return TRUE; // no error
       
  5940 }
       
  5941 
       
  5942 
       
  5943 /*!
       
  5944   Parse over a simple string.
       
  5945 
       
  5946   After the string was successfully parsed, the head is on the first
       
  5947   character after the string.
       
  5948 */
       
  5949 bool QXmlSimpleReader::parseString( const QString& s )
       
  5950 {
       
  5951     signed char Done                   = s.length();
       
  5952 
       
  5953     const signed char InpCharExpected  = 0; // the character that was expected
       
  5954     const signed char InpUnknown       = 1;
       
  5955 
       
  5956     signed char state = 0; // state in this function is the position in the string s
       
  5957     signed char input;
       
  5958 
       
  5959     while ( TRUE ) {
       
  5960 
       
  5961 	// get input
       
  5962 	if ( atEnd() ) {
       
  5963 	    d->error = XMLERR_UNEXPECTEDEOF;
       
  5964 	    goto parseError;
       
  5965 	}
       
  5966 	if ( c == s[(int)state] ) {
       
  5967 	    input = InpCharExpected;
       
  5968 	} else {
       
  5969 	    input = InpUnknown;
       
  5970 	}
       
  5971 
       
  5972 	// set state according to input
       
  5973 	if ( input == InpCharExpected ) {
       
  5974 	    state++;
       
  5975 	} else {
       
  5976 	    // Error
       
  5977 	    d->error = XMLERR_UNEXPECTEDCHARACTER;
       
  5978 	    goto parseError;
       
  5979 	}
       
  5980 
       
  5981 	// do some actions according to state
       
  5982 	next();
       
  5983 	// no input is read after this
       
  5984 	if ( state == Done ) {
       
  5985 	    return TRUE;
       
  5986 	}
       
  5987 
       
  5988     }
       
  5989 
       
  5990     return TRUE;
       
  5991 
       
  5992 parseError:
       
  5993     reportParseError();
       
  5994     return FALSE;
       
  5995 }
       
  5996 
       
  5997 
       
  5998 /*!
       
  5999   Inits the data values.
       
  6000 */
       
  6001 void QXmlSimpleReader::init( const QXmlInputSource& i )
       
  6002 {
       
  6003     xml = i.data();
       
  6004     xmlLength = xml.length();
       
  6005     xmlRef = "";
       
  6006 
       
  6007     d->externParameterEntities.clear();
       
  6008     d->parameterEntities.clear();
       
  6009     d->externEntities.clear();
       
  6010     d->entities.clear();
       
  6011 
       
  6012     tags.clear();
       
  6013 
       
  6014     d->doctype = "";
       
  6015     d->xmlVersion = "";
       
  6016     d->encoding = "";
       
  6017     d->standalone = QXmlSimpleReaderPrivate::Unknown;
       
  6018 
       
  6019     lineNr = 0;
       
  6020     columnNr = -1;
       
  6021     pos = 0;
       
  6022     next();
       
  6023     d->error = XMLERR_OK;
       
  6024 }
       
  6025 
       
  6026 /*!
       
  6027   Returns TRUE if a entity with the name \a e exists,
       
  6028   otherwise returns FALSE.
       
  6029 */
       
  6030 bool QXmlSimpleReader::entityExist( const QString& e ) const
       
  6031 {
       
  6032     if (  d->parameterEntities.find(e) == d->parameterEntities.end() &&
       
  6033 	    d->externParameterEntities.find(e) == d->externParameterEntities.end() ) {
       
  6034 	return FALSE;
       
  6035     } else {
       
  6036 	return TRUE;
       
  6037     }
       
  6038 }
       
  6039 
       
  6040 void QXmlSimpleReader::reportParseError()
       
  6041 {
       
  6042     if ( errorHnd )
       
  6043 	errorHnd->fatalError( QXmlParseException( d->error, columnNr+1, lineNr+1 ) );
       
  6044 }
       
  6045 
       
  6046 #endif //QT_NO_XML