ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

parser.c
Go to the documentation of this file.
00001 /*
00002  * parser.c : an XML 1.0 parser, namespaces and validity support are mostly
00003  *            implemented on top of the SAX interfaces
00004  *
00005  * References:
00006  *   The XML specification:
00007  *     http://www.w3.org/TR/REC-xml
00008  *   Original 1.0 version:
00009  *     http://www.w3.org/TR/1998/REC-xml-19980210
00010  *   XML second edition working draft
00011  *     http://www.w3.org/TR/2000/WD-xml-2e-20000814
00012  *
00013  * Okay this is a big file, the parser core is around 7000 lines, then it
00014  * is followed by the progressive parser top routines, then the various
00015  * high level APIs to call the parser and a few miscellaneous functions.
00016  * A number of helper functions and deprecated ones have been moved to
00017  * parserInternals.c to reduce this file size.
00018  * As much as possible the functions are associated with their relative
00019  * production in the XML specification. A few productions defining the
00020  * different ranges of character are actually implanted either in 
00021  * parserInternals.h or parserInternals.c
00022  * The DOM tree build is realized from the default SAX callbacks in
00023  * the module SAX.c.
00024  * The routines doing the validation checks are in valid.c and called either
00025  * from the SAX callbacks or as standalone functions using a preparsed
00026  * document.
00027  *
00028  * See Copyright for the status of this software.
00029  *
00030  * daniel@veillard.com
00031  */
00032 
00033 #define IN_LIBXML
00034 #include "libxml.h"
00035 
00036 #if defined(WIN32) && !defined (__CYGWIN__)
00037 #define XML_DIR_SEP '\\'
00038 #else
00039 #define XML_DIR_SEP '/'
00040 #endif
00041 
00042 #include <stdlib.h>
00043 #include <string.h>
00044 #include <stdarg.h>
00045 #include <libxml/xmlmemory.h>
00046 #include <libxml/threads.h>
00047 #include <libxml/globals.h>
00048 #include <libxml/tree.h>
00049 #include <libxml/parser.h>
00050 #include <libxml/parserInternals.h>
00051 #include <libxml/valid.h>
00052 #include <libxml/entities.h>
00053 #include <libxml/xmlerror.h>
00054 #include <libxml/encoding.h>
00055 #include <libxml/xmlIO.h>
00056 #include <libxml/uri.h>
00057 #ifdef LIBXML_CATALOG_ENABLED
00058 #include <libxml/catalog.h>
00059 #endif
00060 #ifdef LIBXML_SCHEMAS_ENABLED
00061 #include <libxml/xmlschemastypes.h>
00062 #include <libxml/relaxng.h>
00063 #endif
00064 #ifdef HAVE_CTYPE_H
00065 #include <ctype.h>
00066 #endif
00067 #ifdef HAVE_STDLIB_H
00068 #include <stdlib.h>
00069 #endif
00070 #ifdef HAVE_SYS_STAT_H
00071 #include <sys/stat.h>
00072 #endif
00073 #ifdef HAVE_FCNTL_H
00074 #include <fcntl.h>
00075 #endif
00076 #ifdef HAVE_UNISTD_H
00077 #include <unistd.h>
00078 #endif
00079 #ifdef HAVE_ZLIB_H
00080 #include <zlib.h>
00081 #endif
00082 
00083 static void
00084 xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info);
00085 
00086 static xmlParserCtxtPtr
00087 xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
00088                       const xmlChar *base, xmlParserCtxtPtr pctx);
00089 
00090 /************************************************************************
00091  *                                  *
00092  *  Arbitrary limits set in the parser. See XML_PARSE_HUGE      *
00093  *                                  *
00094  ************************************************************************/
00095 
00096 #define XML_PARSER_BIG_ENTITY 1000
00097 #define XML_PARSER_LOT_ENTITY 5000
00098 
00099 /*
00100  * XML_PARSER_NON_LINEAR is the threshold where the ratio of parsed entity
00101  *    replacement over the size in byte of the input indicates that you have
00102  *    and eponential behaviour. A value of 10 correspond to at least 3 entity
00103  *    replacement per byte of input.
00104  */
00105 #define XML_PARSER_NON_LINEAR 10
00106 
00107 /*
00108  * xmlParserEntityCheck
00109  *
00110  * Function to check non-linear entity expansion behaviour
00111  * This is here to detect and stop exponential linear entity expansion
00112  * This is not a limitation of the parser but a safety
00113  * boundary feature. It can be disabled with the XML_PARSE_HUGE
00114  * parser option.
00115  */
00116 static int
00117 xmlParserEntityCheck(xmlParserCtxtPtr ctxt, unsigned long size,
00118                      xmlEntityPtr ent)
00119 {
00120     unsigned long consumed = 0;
00121 
00122     if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
00123         return (0);
00124     if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
00125         return (1);
00126     if (size != 0) {
00127         /*
00128          * Do the check based on the replacement size of the entity
00129          */
00130         if (size < XML_PARSER_BIG_ENTITY)
00131         return(0);
00132 
00133         /*
00134          * A limit on the amount of text data reasonably used
00135          */
00136         if (ctxt->input != NULL) {
00137             consumed = ctxt->input->consumed +
00138                 (ctxt->input->cur - ctxt->input->base);
00139         }
00140         consumed += ctxt->sizeentities;
00141 
00142         if ((size < XML_PARSER_NON_LINEAR * consumed) &&
00143         (ctxt->nbentities * 3 < XML_PARSER_NON_LINEAR * consumed))
00144             return (0);
00145     } else if (ent != NULL) {
00146         /*
00147          * use the number of parsed entities in the replacement
00148          */
00149         size = ent->checked;
00150 
00151         /*
00152          * The amount of data parsed counting entities size only once
00153          */
00154         if (ctxt->input != NULL) {
00155             consumed = ctxt->input->consumed +
00156                 (ctxt->input->cur - ctxt->input->base);
00157         }
00158         consumed += ctxt->sizeentities;
00159 
00160         /*
00161          * Check the density of entities for the amount of data
00162      * knowing an entity reference will take at least 3 bytes
00163          */
00164         if (size * 3 < consumed * XML_PARSER_NON_LINEAR)
00165             return (0);
00166     } else {
00167         /*
00168          * strange we got no data for checking just return
00169          */
00170         return (0);
00171     }
00172 
00173     xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
00174     return (1);
00175 }
00176 
00185 unsigned int xmlParserMaxDepth = 256;
00186 
00187 
00188 
00189 #define SAX2 1
00190 #define XML_PARSER_BIG_BUFFER_SIZE 300
00191 #define XML_PARSER_BUFFER_SIZE 100
00192 #define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
00193 
00194 /*
00195  * List of XML prefixed PI allowed by W3C specs
00196  */
00197 
00198 static const char *xmlW3CPIs[] = {
00199     "xml-stylesheet",
00200     NULL
00201 };
00202 
00203 
00204 /* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
00205 static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
00206                                               const xmlChar **str);
00207 
00208 static xmlParserErrors
00209 xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
00210                   xmlSAXHandlerPtr sax,
00211               void *user_data, int depth, const xmlChar *URL,
00212               const xmlChar *ID, xmlNodePtr *list);
00213 
00214 static int
00215 xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options,
00216                           const char *encoding);
00217 #ifdef LIBXML_LEGACY_ENABLED
00218 static void
00219 xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
00220                       xmlNodePtr lastNode);
00221 #endif /* LIBXML_LEGACY_ENABLED */
00222 
00223 static xmlParserErrors
00224 xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
00225               const xmlChar *string, void *user_data, xmlNodePtr *lst);
00226 
00227 static int
00228 xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
00229 
00230 /************************************************************************
00231  *                                  *
00232  *      Some factorized error routines              *
00233  *                                  *
00234  ************************************************************************/
00235 
00244 static void
00245 xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix,
00246                    const xmlChar * localname)
00247 {
00248     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00249         (ctxt->instate == XML_PARSER_EOF))
00250     return;
00251     if (ctxt != NULL)
00252     ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
00253 
00254     if (prefix == NULL)
00255         __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
00256                         XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
00257                         (const char *) localname, NULL, NULL, 0, 0,
00258                         "Attribute %s redefined\n", localname);
00259     else
00260         __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
00261                         XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
00262                         (const char *) prefix, (const char *) localname,
00263                         NULL, 0, 0, "Attribute %s:%s redefined\n", prefix,
00264                         localname);
00265     if (ctxt != NULL) {
00266     ctxt->wellFormed = 0;
00267     if (ctxt->recovery == 0)
00268         ctxt->disableSAX = 1;
00269     }
00270 }
00271 
00280 static void
00281 xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
00282 {
00283     const char *errmsg;
00284 
00285     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00286         (ctxt->instate == XML_PARSER_EOF))
00287     return;
00288     switch (error) {
00289         case XML_ERR_INVALID_HEX_CHARREF:
00290             errmsg = "CharRef: invalid hexadecimal value\n";
00291             break;
00292         case XML_ERR_INVALID_DEC_CHARREF:
00293             errmsg = "CharRef: invalid decimal value\n";
00294             break;
00295         case XML_ERR_INVALID_CHARREF:
00296             errmsg = "CharRef: invalid value\n";
00297             break;
00298         case XML_ERR_INTERNAL_ERROR:
00299             errmsg = "internal error";
00300             break;
00301         case XML_ERR_PEREF_AT_EOF:
00302             errmsg = "PEReference at end of document\n";
00303             break;
00304         case XML_ERR_PEREF_IN_PROLOG:
00305             errmsg = "PEReference in prolog\n";
00306             break;
00307         case XML_ERR_PEREF_IN_EPILOG:
00308             errmsg = "PEReference in epilog\n";
00309             break;
00310         case XML_ERR_PEREF_NO_NAME:
00311             errmsg = "PEReference: no name\n";
00312             break;
00313         case XML_ERR_PEREF_SEMICOL_MISSING:
00314             errmsg = "PEReference: expecting ';'\n";
00315             break;
00316         case XML_ERR_ENTITY_LOOP:
00317             errmsg = "Detected an entity reference loop\n";
00318             break;
00319         case XML_ERR_ENTITY_NOT_STARTED:
00320             errmsg = "EntityValue: \" or ' expected\n";
00321             break;
00322         case XML_ERR_ENTITY_PE_INTERNAL:
00323             errmsg = "PEReferences forbidden in internal subset\n";
00324             break;
00325         case XML_ERR_ENTITY_NOT_FINISHED:
00326             errmsg = "EntityValue: \" or ' expected\n";
00327             break;
00328         case XML_ERR_ATTRIBUTE_NOT_STARTED:
00329             errmsg = "AttValue: \" or ' expected\n";
00330             break;
00331         case XML_ERR_LT_IN_ATTRIBUTE:
00332             errmsg = "Unescaped '<' not allowed in attributes values\n";
00333             break;
00334         case XML_ERR_LITERAL_NOT_STARTED:
00335             errmsg = "SystemLiteral \" or ' expected\n";
00336             break;
00337         case XML_ERR_LITERAL_NOT_FINISHED:
00338             errmsg = "Unfinished System or Public ID \" or ' expected\n";
00339             break;
00340         case XML_ERR_MISPLACED_CDATA_END:
00341             errmsg = "Sequence ']]>' not allowed in content\n";
00342             break;
00343         case XML_ERR_URI_REQUIRED:
00344             errmsg = "SYSTEM or PUBLIC, the URI is missing\n";
00345             break;
00346         case XML_ERR_PUBID_REQUIRED:
00347             errmsg = "PUBLIC, the Public Identifier is missing\n";
00348             break;
00349         case XML_ERR_HYPHEN_IN_COMMENT:
00350             errmsg = "Comment must not contain '--' (double-hyphen)\n";
00351             break;
00352         case XML_ERR_PI_NOT_STARTED:
00353             errmsg = "xmlParsePI : no target name\n";
00354             break;
00355         case XML_ERR_RESERVED_XML_NAME:
00356             errmsg = "Invalid PI name\n";
00357             break;
00358         case XML_ERR_NOTATION_NOT_STARTED:
00359             errmsg = "NOTATION: Name expected here\n";
00360             break;
00361         case XML_ERR_NOTATION_NOT_FINISHED:
00362             errmsg = "'>' required to close NOTATION declaration\n";
00363             break;
00364         case XML_ERR_VALUE_REQUIRED:
00365             errmsg = "Entity value required\n";
00366             break;
00367         case XML_ERR_URI_FRAGMENT:
00368             errmsg = "Fragment not allowed";
00369             break;
00370         case XML_ERR_ATTLIST_NOT_STARTED:
00371             errmsg = "'(' required to start ATTLIST enumeration\n";
00372             break;
00373         case XML_ERR_NMTOKEN_REQUIRED:
00374             errmsg = "NmToken expected in ATTLIST enumeration\n";
00375             break;
00376         case XML_ERR_ATTLIST_NOT_FINISHED:
00377             errmsg = "')' required to finish ATTLIST enumeration\n";
00378             break;
00379         case XML_ERR_MIXED_NOT_STARTED:
00380             errmsg = "MixedContentDecl : '|' or ')*' expected\n";
00381             break;
00382         case XML_ERR_PCDATA_REQUIRED:
00383             errmsg = "MixedContentDecl : '#PCDATA' expected\n";
00384             break;
00385         case XML_ERR_ELEMCONTENT_NOT_STARTED:
00386             errmsg = "ContentDecl : Name or '(' expected\n";
00387             break;
00388         case XML_ERR_ELEMCONTENT_NOT_FINISHED:
00389             errmsg = "ContentDecl : ',' '|' or ')' expected\n";
00390             break;
00391         case XML_ERR_PEREF_IN_INT_SUBSET:
00392             errmsg =
00393                 "PEReference: forbidden within markup decl in internal subset\n";
00394             break;
00395         case XML_ERR_GT_REQUIRED:
00396             errmsg = "expected '>'\n";
00397             break;
00398         case XML_ERR_CONDSEC_INVALID:
00399             errmsg = "XML conditional section '[' expected\n";
00400             break;
00401         case XML_ERR_EXT_SUBSET_NOT_FINISHED:
00402             errmsg = "Content error in the external subset\n";
00403             break;
00404         case XML_ERR_CONDSEC_INVALID_KEYWORD:
00405             errmsg =
00406                 "conditional section INCLUDE or IGNORE keyword expected\n";
00407             break;
00408         case XML_ERR_CONDSEC_NOT_FINISHED:
00409             errmsg = "XML conditional section not closed\n";
00410             break;
00411         case XML_ERR_XMLDECL_NOT_STARTED:
00412             errmsg = "Text declaration '<?xml' required\n";
00413             break;
00414         case XML_ERR_XMLDECL_NOT_FINISHED:
00415             errmsg = "parsing XML declaration: '?>' expected\n";
00416             break;
00417         case XML_ERR_EXT_ENTITY_STANDALONE:
00418             errmsg = "external parsed entities cannot be standalone\n";
00419             break;
00420         case XML_ERR_ENTITYREF_SEMICOL_MISSING:
00421             errmsg = "EntityRef: expecting ';'\n";
00422             break;
00423         case XML_ERR_DOCTYPE_NOT_FINISHED:
00424             errmsg = "DOCTYPE improperly terminated\n";
00425             break;
00426         case XML_ERR_LTSLASH_REQUIRED:
00427             errmsg = "EndTag: '</' not found\n";
00428             break;
00429         case XML_ERR_EQUAL_REQUIRED:
00430             errmsg = "expected '='\n";
00431             break;
00432         case XML_ERR_STRING_NOT_CLOSED:
00433             errmsg = "String not closed expecting \" or '\n";
00434             break;
00435         case XML_ERR_STRING_NOT_STARTED:
00436             errmsg = "String not started expecting ' or \"\n";
00437             break;
00438         case XML_ERR_ENCODING_NAME:
00439             errmsg = "Invalid XML encoding name\n";
00440             break;
00441         case XML_ERR_STANDALONE_VALUE:
00442             errmsg = "standalone accepts only 'yes' or 'no'\n";
00443             break;
00444         case XML_ERR_DOCUMENT_EMPTY:
00445             errmsg = "Document is empty\n";
00446             break;
00447         case XML_ERR_DOCUMENT_END:
00448             errmsg = "Extra content at the end of the document\n";
00449             break;
00450         case XML_ERR_NOT_WELL_BALANCED:
00451             errmsg = "chunk is not well balanced\n";
00452             break;
00453         case XML_ERR_EXTRA_CONTENT:
00454             errmsg = "extra content at the end of well balanced chunk\n";
00455             break;
00456         case XML_ERR_VERSION_MISSING:
00457             errmsg = "Malformed declaration expecting version\n";
00458             break;
00459 #if 0
00460         case:
00461             errmsg = "\n";
00462             break;
00463 #endif
00464         default:
00465             errmsg = "Unregistered error message\n";
00466     }
00467     if (ctxt != NULL)
00468     ctxt->errNo = error;
00469     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
00470                     XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, errmsg,
00471                     info);
00472     if (ctxt != NULL) {
00473     ctxt->wellFormed = 0;
00474     if (ctxt->recovery == 0)
00475         ctxt->disableSAX = 1;
00476     }
00477 }
00478 
00487 static void
00488 xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
00489                const char *msg)
00490 {
00491     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00492         (ctxt->instate == XML_PARSER_EOF))
00493     return;
00494     if (ctxt != NULL)
00495     ctxt->errNo = error;
00496     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
00497                     XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
00498     if (ctxt != NULL) {
00499     ctxt->wellFormed = 0;
00500     if (ctxt->recovery == 0)
00501         ctxt->disableSAX = 1;
00502     }
00503 }
00504 
00515 static void
00516 xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
00517               const char *msg, const xmlChar *str1, const xmlChar *str2)
00518 {
00519     xmlStructuredErrorFunc schannel = NULL;
00520 
00521     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00522         (ctxt->instate == XML_PARSER_EOF))
00523     return;
00524     if ((ctxt != NULL) && (ctxt->sax != NULL) &&
00525         (ctxt->sax->initialized == XML_SAX2_MAGIC))
00526         schannel = ctxt->sax->serror;
00527     if (ctxt != NULL) {
00528         __xmlRaiseError(schannel,
00529                     (ctxt->sax) ? ctxt->sax->warning : NULL,
00530                     ctxt->userData,
00531                     ctxt, NULL, XML_FROM_PARSER, error,
00532                     XML_ERR_WARNING, NULL, 0,
00533             (const char *) str1, (const char *) str2, NULL, 0, 0,
00534             msg, (const char *) str1, (const char *) str2);
00535     } else {
00536         __xmlRaiseError(schannel, NULL, NULL,
00537                     ctxt, NULL, XML_FROM_PARSER, error,
00538                     XML_ERR_WARNING, NULL, 0,
00539             (const char *) str1, (const char *) str2, NULL, 0, 0,
00540             msg, (const char *) str1, (const char *) str2);
00541     }
00542 }
00543 
00553 static void
00554 xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
00555               const char *msg, const xmlChar *str1, const xmlChar *str2)
00556 {
00557     xmlStructuredErrorFunc schannel = NULL;
00558 
00559     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00560         (ctxt->instate == XML_PARSER_EOF))
00561     return;
00562     if (ctxt != NULL) {
00563     ctxt->errNo = error;
00564     if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
00565         schannel = ctxt->sax->serror;
00566     }
00567     if (ctxt != NULL) {
00568         __xmlRaiseError(schannel,
00569                     ctxt->vctxt.error, ctxt->vctxt.userData,
00570                     ctxt, NULL, XML_FROM_DTD, error,
00571                     XML_ERR_ERROR, NULL, 0, (const char *) str1,
00572             (const char *) str2, NULL, 0, 0,
00573             msg, (const char *) str1, (const char *) str2);
00574     ctxt->valid = 0;
00575     } else {
00576         __xmlRaiseError(schannel, NULL, NULL,
00577                     ctxt, NULL, XML_FROM_DTD, error,
00578                     XML_ERR_ERROR, NULL, 0, (const char *) str1,
00579             (const char *) str2, NULL, 0, 0,
00580             msg, (const char *) str1, (const char *) str2);
00581     }
00582 }
00583 
00593 static void
00594 xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
00595                   const char *msg, int val)
00596 {
00597     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00598         (ctxt->instate == XML_PARSER_EOF))
00599     return;
00600     if (ctxt != NULL)
00601     ctxt->errNo = error;
00602     __xmlRaiseError(NULL, NULL, NULL,
00603                     ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
00604                     NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
00605     if (ctxt != NULL) {
00606     ctxt->wellFormed = 0;
00607     if (ctxt->recovery == 0)
00608         ctxt->disableSAX = 1;
00609     }
00610 }
00611 
00623 static void
00624 xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
00625                   const char *msg, const xmlChar *str1, int val, 
00626           const xmlChar *str2)
00627 {
00628     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00629         (ctxt->instate == XML_PARSER_EOF))
00630     return;
00631     if (ctxt != NULL)
00632     ctxt->errNo = error;
00633     __xmlRaiseError(NULL, NULL, NULL,
00634                     ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
00635                     NULL, 0, (const char *) str1, (const char *) str2,
00636             NULL, val, 0, msg, str1, val, str2);
00637     if (ctxt != NULL) {
00638     ctxt->wellFormed = 0;
00639     if (ctxt->recovery == 0)
00640         ctxt->disableSAX = 1;
00641     }
00642 }
00643 
00653 static void
00654 xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
00655                   const char *msg, const xmlChar * val)
00656 {
00657     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00658         (ctxt->instate == XML_PARSER_EOF))
00659     return;
00660     if (ctxt != NULL)
00661     ctxt->errNo = error;
00662     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
00663                     XML_FROM_PARSER, error, XML_ERR_FATAL,
00664                     NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
00665                     val);
00666     if (ctxt != NULL) {
00667     ctxt->wellFormed = 0;
00668     if (ctxt->recovery == 0)
00669         ctxt->disableSAX = 1;
00670     }
00671 }
00672 
00682 static void
00683 xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
00684                   const char *msg, const xmlChar * val)
00685 {
00686     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00687         (ctxt->instate == XML_PARSER_EOF))
00688     return;
00689     if (ctxt != NULL)
00690     ctxt->errNo = error;
00691     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
00692                     XML_FROM_PARSER, error, XML_ERR_ERROR,
00693                     NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
00694                     val);
00695 }
00696 
00707 static void
00708 xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
00709          const char *msg,
00710          const xmlChar * info1, const xmlChar * info2,
00711          const xmlChar * info3)
00712 {
00713     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00714         (ctxt->instate == XML_PARSER_EOF))
00715     return;
00716     if (ctxt != NULL)
00717     ctxt->errNo = error;
00718     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
00719                     XML_ERR_ERROR, NULL, 0, (const char *) info1,
00720                     (const char *) info2, (const char *) info3, 0, 0, msg,
00721                     info1, info2, info3);
00722     if (ctxt != NULL)
00723     ctxt->nsWellFormed = 0;
00724 }
00725 
00736 static void
00737 xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
00738          const char *msg,
00739          const xmlChar * info1, const xmlChar * info2,
00740          const xmlChar * info3)
00741 {
00742     if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
00743         (ctxt->instate == XML_PARSER_EOF))
00744     return;
00745     __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
00746                     XML_ERR_WARNING, NULL, 0, (const char *) info1,
00747                     (const char *) info2, (const char *) info3, 0, 0, msg,
00748                     info1, info2, info3);
00749 }
00750 
00751 /************************************************************************
00752  *                                  *
00753  *      Library wide options                    *
00754  *                                  *
00755  ************************************************************************/
00756 
00767 int
00768 xmlHasFeature(xmlFeature feature)
00769 {
00770     switch (feature) {
00771     case XML_WITH_THREAD:
00772 #ifdef LIBXML_THREAD_ENABLED
00773         return(1);
00774 #else
00775         return(0);
00776 #endif
00777         case XML_WITH_TREE:
00778 #ifdef LIBXML_TREE_ENABLED
00779             return(1);
00780 #else
00781             return(0);
00782 #endif
00783         case XML_WITH_OUTPUT:
00784 #ifdef LIBXML_OUTPUT_ENABLED
00785             return(1);
00786 #else
00787             return(0);
00788 #endif
00789         case XML_WITH_PUSH:
00790 #ifdef LIBXML_PUSH_ENABLED
00791             return(1);
00792 #else
00793             return(0);
00794 #endif
00795         case XML_WITH_READER:
00796 #ifdef LIBXML_READER_ENABLED
00797             return(1);
00798 #else
00799             return(0);
00800 #endif
00801         case XML_WITH_PATTERN:
00802 #ifdef LIBXML_PATTERN_ENABLED
00803             return(1);
00804 #else
00805             return(0);
00806 #endif
00807         case XML_WITH_WRITER:
00808 #ifdef LIBXML_WRITER_ENABLED
00809             return(1);
00810 #else
00811             return(0);
00812 #endif
00813         case XML_WITH_SAX1:
00814 #ifdef LIBXML_SAX1_ENABLED
00815             return(1);
00816 #else
00817             return(0);
00818 #endif
00819         case XML_WITH_FTP:
00820 #ifdef LIBXML_FTP_ENABLED
00821             return(1);
00822 #else
00823             return(0);
00824 #endif
00825         case XML_WITH_HTTP:
00826 #ifdef LIBXML_HTTP_ENABLED
00827             return(1);
00828 #else
00829             return(0);
00830 #endif
00831         case XML_WITH_VALID:
00832 #ifdef LIBXML_VALID_ENABLED
00833             return(1);
00834 #else
00835             return(0);
00836 #endif
00837         case XML_WITH_HTML:
00838 #ifdef LIBXML_HTML_ENABLED
00839             return(1);
00840 #else
00841             return(0);
00842 #endif
00843         case XML_WITH_LEGACY:
00844 #ifdef LIBXML_LEGACY_ENABLED
00845             return(1);
00846 #else
00847             return(0);
00848 #endif
00849         case XML_WITH_C14N:
00850 #ifdef LIBXML_C14N_ENABLED
00851             return(1);
00852 #else
00853             return(0);
00854 #endif
00855         case XML_WITH_CATALOG:
00856 #ifdef LIBXML_CATALOG_ENABLED
00857             return(1);
00858 #else
00859             return(0);
00860 #endif
00861         case XML_WITH_XPATH:
00862 #ifdef LIBXML_XPATH_ENABLED
00863             return(1);
00864 #else
00865             return(0);
00866 #endif
00867         case XML_WITH_XPTR:
00868 #ifdef LIBXML_XPTR_ENABLED
00869             return(1);
00870 #else
00871             return(0);
00872 #endif
00873         case XML_WITH_XINCLUDE:
00874 #ifdef LIBXML_XINCLUDE_ENABLED
00875             return(1);
00876 #else
00877             return(0);
00878 #endif
00879         case XML_WITH_ICONV:
00880 #ifdef LIBXML_ICONV_ENABLED
00881             return(1);
00882 #else
00883             return(0);
00884 #endif
00885         case XML_WITH_ISO8859X:
00886 #ifdef LIBXML_ISO8859X_ENABLED
00887             return(1);
00888 #else
00889             return(0);
00890 #endif
00891         case XML_WITH_UNICODE:
00892 #ifdef LIBXML_UNICODE_ENABLED
00893             return(1);
00894 #else
00895             return(0);
00896 #endif
00897         case XML_WITH_REGEXP:
00898 #ifdef LIBXML_REGEXP_ENABLED
00899             return(1);
00900 #else
00901             return(0);
00902 #endif
00903         case XML_WITH_AUTOMATA:
00904 #ifdef LIBXML_AUTOMATA_ENABLED
00905             return(1);
00906 #else
00907             return(0);
00908 #endif
00909         case XML_WITH_EXPR:
00910 #ifdef LIBXML_EXPR_ENABLED
00911             return(1);
00912 #else
00913             return(0);
00914 #endif
00915         case XML_WITH_SCHEMAS:
00916 #ifdef LIBXML_SCHEMAS_ENABLED
00917             return(1);
00918 #else
00919             return(0);
00920 #endif
00921         case XML_WITH_SCHEMATRON:
00922 #ifdef LIBXML_SCHEMATRON_ENABLED
00923             return(1);
00924 #else
00925             return(0);
00926 #endif
00927         case XML_WITH_MODULES:
00928 #ifdef LIBXML_MODULES_ENABLED
00929             return(1);
00930 #else
00931             return(0);
00932 #endif
00933         case XML_WITH_DEBUG:
00934 #ifdef LIBXML_DEBUG_ENABLED
00935             return(1);
00936 #else
00937             return(0);
00938 #endif
00939         case XML_WITH_DEBUG_MEM:
00940 #ifdef DEBUG_MEMORY_LOCATION
00941             return(1);
00942 #else
00943             return(0);
00944 #endif
00945         case XML_WITH_DEBUG_RUN:
00946 #ifdef LIBXML_DEBUG_RUNTIME
00947             return(1);
00948 #else
00949             return(0);
00950 #endif
00951         case XML_WITH_ZLIB:
00952 #ifdef LIBXML_ZLIB_ENABLED
00953             return(1);
00954 #else
00955             return(0);
00956 #endif
00957         case XML_WITH_ICU:
00958 #ifdef LIBXML_ICU_ENABLED
00959             return(1);
00960 #else
00961             return(0);
00962 #endif
00963         default:
00964         break;
00965      }
00966      return(0);
00967 }
00968 
00969 /************************************************************************
00970  *                                  *
00971  *      SAX2 defaulted attributes handling          *
00972  *                                  *
00973  ************************************************************************/
00974 
00981 static void
00982 xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
00983     if (ctxt == NULL) return;
00984 #ifdef LIBXML_SAX1_ENABLED
00985     if ((ctxt->sax) &&  (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
00986         ((ctxt->sax->startElementNs != NULL) ||
00987          (ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1;
00988 #else
00989     ctxt->sax2 = 1;
00990 #endif /* LIBXML_SAX1_ENABLED */
00991 
00992     ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
00993     ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
00994     ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
00995     if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) || 
00996             (ctxt->str_xml_ns == NULL)) {
00997         xmlErrMemory(ctxt, NULL);
00998     }
00999 }
01000 
01001 typedef struct _xmlDefAttrs xmlDefAttrs;
01002 typedef xmlDefAttrs *xmlDefAttrsPtr;
01003 struct _xmlDefAttrs {
01004     int nbAttrs;    /* number of defaulted attributes on that element */
01005     int maxAttrs;       /* the size of the array */
01006     const xmlChar *values[5]; /* array of localname/prefix/values/external */
01007 };
01008 
01026 static xmlChar *
01027 xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst)
01028 {
01029     if ((src == NULL) || (dst == NULL))
01030         return(NULL);
01031 
01032     while (*src == 0x20) src++;
01033     while (*src != 0) {
01034     if (*src == 0x20) {
01035         while (*src == 0x20) src++;
01036         if (*src != 0)
01037         *dst++ = 0x20;
01038     } else {
01039         *dst++ = *src++;
01040     }
01041     }
01042     *dst = 0;
01043     if (dst == src)
01044        return(NULL);
01045     return(dst);
01046 }
01047 
01059 static const xmlChar *
01060 xmlAttrNormalizeSpace2(xmlParserCtxtPtr ctxt, xmlChar *src, int *len)
01061 {
01062     int i;
01063     int remove_head = 0;
01064     int need_realloc = 0;
01065     const xmlChar *cur;
01066 
01067     if ((ctxt == NULL) || (src == NULL) || (len == NULL))
01068         return(NULL);
01069     i = *len;
01070     if (i <= 0)
01071         return(NULL);
01072 
01073     cur = src;
01074     while (*cur == 0x20) {
01075         cur++;
01076     remove_head++;
01077     }
01078     while (*cur != 0) {
01079     if (*cur == 0x20) {
01080         cur++;
01081         if ((*cur == 0x20) || (*cur == 0)) {
01082             need_realloc = 1;
01083         break;
01084         }
01085     } else
01086         cur++;
01087     }
01088     if (need_realloc) {
01089         xmlChar *ret;
01090 
01091     ret = xmlStrndup(src + remove_head, i - remove_head + 1);
01092     if (ret == NULL) {
01093         xmlErrMemory(ctxt, NULL);
01094         return(NULL);
01095     }
01096     xmlAttrNormalizeSpace(ret, ret);
01097     *len = (int) strlen((const char *)ret);
01098         return(ret);
01099     } else if (remove_head) {
01100         *len -= remove_head;
01101         memmove(src, src + remove_head, 1 + *len);
01102     return(src);
01103     }
01104     return(NULL);
01105 }
01106 
01116 static void
01117 xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
01118                const xmlChar *fullname,
01119                const xmlChar *fullattr,
01120                const xmlChar *value) {
01121     xmlDefAttrsPtr defaults;
01122     int len;
01123     const xmlChar *name;
01124     const xmlChar *prefix;
01125 
01126     /*
01127      * Allows to detect attribute redefinitions
01128      */
01129     if (ctxt->attsSpecial != NULL) {
01130         if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
01131         return;
01132     }
01133 
01134     if (ctxt->attsDefault == NULL) {
01135         ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict);
01136     if (ctxt->attsDefault == NULL)
01137         goto mem_error;
01138     }
01139 
01140     /*
01141      * split the element name into prefix:localname , the string found
01142      * are within the DTD and then not associated to namespace names.
01143      */
01144     name = xmlSplitQName3(fullname, &len);
01145     if (name == NULL) {
01146         name = xmlDictLookup(ctxt->dict, fullname, -1);
01147     prefix = NULL;
01148     } else {
01149         name = xmlDictLookup(ctxt->dict, name, -1);
01150     prefix = xmlDictLookup(ctxt->dict, fullname, len);
01151     }
01152 
01153     /*
01154      * make sure there is some storage
01155      */
01156     defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix);
01157     if (defaults == NULL) {
01158         defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) +
01159                        (4 * 5) * sizeof(const xmlChar *));
01160     if (defaults == NULL)
01161         goto mem_error;
01162     defaults->nbAttrs = 0;
01163     defaults->maxAttrs = 4;
01164     if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
01165                             defaults, NULL) < 0) {
01166         xmlFree(defaults);
01167         goto mem_error;
01168     }
01169     } else if (defaults->nbAttrs >= defaults->maxAttrs) {
01170         xmlDefAttrsPtr temp;
01171 
01172         temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) +
01173                (2 * defaults->maxAttrs * 5) * sizeof(const xmlChar *));
01174     if (temp == NULL)
01175         goto mem_error;
01176     defaults = temp;
01177     defaults->maxAttrs *= 2;
01178     if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
01179                             defaults, NULL) < 0) {
01180         xmlFree(defaults);
01181         goto mem_error;
01182     }
01183     }
01184 
01185     /*
01186      * Split the element name into prefix:localname , the string found
01187      * are within the DTD and hen not associated to namespace names.
01188      */
01189     name = xmlSplitQName3(fullattr, &len);
01190     if (name == NULL) {
01191         name = xmlDictLookup(ctxt->dict, fullattr, -1);
01192     prefix = NULL;
01193     } else {
01194         name = xmlDictLookup(ctxt->dict, name, -1);
01195     prefix = xmlDictLookup(ctxt->dict, fullattr, len);
01196     }
01197 
01198     defaults->values[5 * defaults->nbAttrs] = name;
01199     defaults->values[5 * defaults->nbAttrs + 1] = prefix;
01200     /* intern the string and precompute the end */
01201     len = xmlStrlen(value);
01202     value = xmlDictLookup(ctxt->dict, value, len);
01203     defaults->values[5 * defaults->nbAttrs + 2] = value;
01204     defaults->values[5 * defaults->nbAttrs + 3] = value + len;
01205     if (ctxt->external)
01206         defaults->values[5 * defaults->nbAttrs + 4] = BAD_CAST "external";
01207     else
01208         defaults->values[5 * defaults->nbAttrs + 4] = NULL;
01209     defaults->nbAttrs++;
01210 
01211     return;
01212 
01213 mem_error:
01214     xmlErrMemory(ctxt, NULL);
01215     return;
01216 }
01217 
01227 static void
01228 xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
01229           const xmlChar *fullname,
01230           const xmlChar *fullattr,
01231           int type)
01232 {
01233     if (ctxt->attsSpecial == NULL) {
01234         ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict);
01235     if (ctxt->attsSpecial == NULL)
01236         goto mem_error;
01237     }
01238 
01239     if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
01240         return;
01241 
01242     xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
01243                      (void *) (long) type);
01244     return;
01245 
01246 mem_error:
01247     xmlErrMemory(ctxt, NULL);
01248     return;
01249 }
01250 
01256 static void
01257 xmlCleanSpecialAttrCallback(void *payload, void *data,
01258                             const xmlChar *fullname, const xmlChar *fullattr,
01259                             const xmlChar *unused ATTRIBUTE_UNUSED) {
01260     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data;
01261 
01262     if (((long) payload) == XML_ATTRIBUTE_CDATA) {
01263         xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL);
01264     }
01265 }
01266 
01275 static void
01276 xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt)
01277 {
01278     if (ctxt->attsSpecial == NULL)
01279         return;
01280 
01281     xmlHashScanFull(ctxt->attsSpecial, xmlCleanSpecialAttrCallback, ctxt);
01282 
01283     if (xmlHashSize(ctxt->attsSpecial) == 0) {
01284         xmlHashFree(ctxt->attsSpecial, NULL);
01285         ctxt->attsSpecial = NULL;
01286     }
01287     return;
01288 }
01289 
01348 int
01349 xmlCheckLanguageID(const xmlChar * lang)
01350 {
01351     const xmlChar *cur = lang, *nxt;
01352 
01353     if (cur == NULL)
01354         return (0);
01355     if (((cur[0] == 'i') && (cur[1] == '-')) ||
01356         ((cur[0] == 'I') && (cur[1] == '-')) ||
01357         ((cur[0] == 'x') && (cur[1] == '-')) ||
01358         ((cur[0] == 'X') && (cur[1] == '-'))) {
01359         /*
01360          * Still allow IANA code and user code which were coming
01361          * from the previous version of the XML-1.0 specification
01362          * it's deprecated but we should not fail
01363          */
01364         cur += 2;
01365         while (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
01366                ((cur[0] >= 'a') && (cur[0] <= 'z')))
01367             cur++;
01368         return(cur[0] == 0);
01369     }
01370     nxt = cur;
01371     while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
01372            ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
01373            nxt++;
01374     if (nxt - cur >= 4) {
01375         /*
01376          * Reserved
01377          */
01378         if ((nxt - cur > 8) || (nxt[0] != 0))
01379             return(0);
01380         return(1);
01381     }
01382     if (nxt - cur < 2)
01383         return(0);
01384     /* we got an ISO 639 code */
01385     if (nxt[0] == 0)
01386         return(1);
01387     if (nxt[0] != '-')
01388         return(0);
01389 
01390     nxt++;
01391     cur = nxt;
01392     /* now we can have extlang or script or region or variant */
01393     if ((nxt[0] >= '0') && (nxt[0] <= '9'))
01394         goto region_m49;
01395 
01396     while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
01397            ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
01398            nxt++;
01399     if (nxt - cur == 4)
01400         goto script;
01401     if (nxt - cur == 2)
01402         goto region;
01403     if ((nxt - cur >= 5) && (nxt - cur <= 8))
01404         goto variant;
01405     if (nxt - cur != 3)
01406         return(0);
01407     /* we parsed an extlang */
01408     if (nxt[0] == 0)
01409         return(1);
01410     if (nxt[0] != '-')
01411         return(0);
01412 
01413     nxt++;
01414     cur = nxt;
01415     /* now we can have script or region or variant */
01416     if ((nxt[0] >= '0') && (nxt[0] <= '9'))
01417         goto region_m49;
01418 
01419     while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
01420            ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
01421            nxt++;
01422     if (nxt - cur == 2)
01423         goto region;
01424     if ((nxt - cur >= 5) && (nxt - cur <= 8))
01425         goto variant;
01426     if (nxt - cur != 4)
01427         return(0);
01428     /* we parsed a script */
01429 script:
01430     if (nxt[0] == 0)
01431         return(1);
01432     if (nxt[0] != '-')
01433         return(0);
01434 
01435     nxt++;
01436     cur = nxt;
01437     /* now we can have region or variant */
01438     if ((nxt[0] >= '0') && (nxt[0] <= '9'))
01439         goto region_m49;
01440 
01441     while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
01442            ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
01443            nxt++;
01444 
01445     if ((nxt - cur >= 5) && (nxt - cur <= 8))
01446         goto variant;
01447     if (nxt - cur != 2)
01448         return(0);
01449     /* we parsed a region */
01450 region:
01451     if (nxt[0] == 0)
01452         return(1);
01453     if (nxt[0] != '-')
01454         return(0);
01455 
01456     nxt++;
01457     cur = nxt;
01458     /* now we can just have a variant */
01459     while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
01460            ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
01461            nxt++;
01462 
01463     if ((nxt - cur < 5) || (nxt - cur > 8))
01464         return(0);
01465 
01466     /* we parsed a variant */
01467 variant:
01468     if (nxt[0] == 0)
01469         return(1);
01470     if (nxt[0] != '-')
01471         return(0);
01472     /* extensions and private use subtags not checked */
01473     return (1);
01474 
01475 region_m49:
01476     if (((nxt[1] >= '0') && (nxt[1] <= '9')) &&
01477         ((nxt[2] >= '0') && (nxt[2] <= '9'))) {
01478         nxt += 3;
01479         goto region;
01480     }
01481     return(0);
01482 }
01483 
01484 /************************************************************************
01485  *                                  *
01486  *      Parser stacks related functions and macros      *
01487  *                                  *
01488  ************************************************************************/
01489 
01490 static xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
01491                                             const xmlChar ** str);
01492 
01493 #ifdef SAX2
01494 
01505 static int
01506 nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL)
01507 {
01508     if (ctxt->options & XML_PARSE_NSCLEAN) {
01509         int i;
01510     for (i = 0;i < ctxt->nsNr;i += 2) {
01511         if (ctxt->nsTab[i] == prefix) {
01512         /* in scope */
01513             if (ctxt->nsTab[i + 1] == URL)
01514             return(-2);
01515         /* out of scope keep it */
01516         break;
01517         }
01518     }
01519     }
01520     if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) {
01521     ctxt->nsMax = 10;
01522     ctxt->nsNr = 0;
01523     ctxt->nsTab = (const xmlChar **)
01524                   xmlMalloc(ctxt->nsMax * sizeof(xmlChar *));
01525     if (ctxt->nsTab == NULL) {
01526         xmlErrMemory(ctxt, NULL);
01527         ctxt->nsMax = 0;
01528             return (-1);
01529     }
01530     } else if (ctxt->nsNr >= ctxt->nsMax) {
01531         const xmlChar ** tmp;
01532         ctxt->nsMax *= 2;
01533         tmp = (const xmlChar **) xmlRealloc((char *) ctxt->nsTab,
01534                     ctxt->nsMax * sizeof(ctxt->nsTab[0]));
01535         if (tmp == NULL) {
01536             xmlErrMemory(ctxt, NULL);
01537         ctxt->nsMax /= 2;
01538             return (-1);
01539         }
01540     ctxt->nsTab = tmp;
01541     }
01542     ctxt->nsTab[ctxt->nsNr++] = prefix;
01543     ctxt->nsTab[ctxt->nsNr++] = URL;
01544     return (ctxt->nsNr);
01545 }
01555 static int
01556 nsPop(xmlParserCtxtPtr ctxt, int nr)
01557 {
01558     int i;
01559 
01560     if (ctxt->nsTab == NULL) return(0);
01561     if (ctxt->nsNr < nr) {
01562         xmlGenericError(xmlGenericErrorContext, "Pbm popping %d NS\n", nr);
01563         nr = ctxt->nsNr;
01564     }
01565     if (ctxt->nsNr <= 0)
01566         return (0);
01567 
01568     for (i = 0;i < nr;i++) {
01569          ctxt->nsNr--;
01570      ctxt->nsTab[ctxt->nsNr] = NULL;
01571     }
01572     return(nr);
01573 }
01574 #endif
01575 
01576 static int
01577 xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
01578     const xmlChar **atts;
01579     int *attallocs;
01580     int maxatts;
01581 
01582     if (ctxt->atts == NULL) {
01583     maxatts = 55; /* allow for 10 attrs by default */
01584     atts = (const xmlChar **)
01585            xmlMalloc(maxatts * sizeof(xmlChar *));
01586     if (atts == NULL) goto mem_error;
01587     ctxt->atts = atts;
01588     attallocs = (int *) xmlMalloc((maxatts / 5) * sizeof(int));
01589     if (attallocs == NULL) goto mem_error;
01590     ctxt->attallocs = attallocs;
01591     ctxt->maxatts = maxatts;
01592     } else if (nr + 5 > ctxt->maxatts) {
01593     maxatts = (nr + 5) * 2;
01594     atts = (const xmlChar **) xmlRealloc((void *) ctxt->atts,
01595                      maxatts * sizeof(const xmlChar *));
01596     if (atts == NULL) goto mem_error;
01597     ctxt->atts = atts;
01598     attallocs = (int *) xmlRealloc((void *) ctxt->attallocs,
01599                                  (maxatts / 5) * sizeof(int));
01600     if (attallocs == NULL) goto mem_error;
01601     ctxt->attallocs = attallocs;
01602     ctxt->maxatts = maxatts;
01603     }
01604     return(ctxt->maxatts);
01605 mem_error:
01606     xmlErrMemory(ctxt, NULL);
01607     return(-1);
01608 }
01609 
01619 int
01620 inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
01621 {
01622     if ((ctxt == NULL) || (value == NULL))
01623         return(-1);
01624     if (ctxt->inputNr >= ctxt->inputMax) {
01625         ctxt->inputMax *= 2;
01626         ctxt->inputTab =
01627             (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
01628                                              ctxt->inputMax *
01629                                              sizeof(ctxt->inputTab[0]));
01630         if (ctxt->inputTab == NULL) {
01631             xmlErrMemory(ctxt, NULL);
01632         xmlFreeInputStream(value);
01633         ctxt->inputMax /= 2;
01634         value = NULL;
01635             return (-1);
01636         }
01637     }
01638     ctxt->inputTab[ctxt->inputNr] = value;
01639     ctxt->input = value;
01640     return (ctxt->inputNr++);
01641 }
01650 xmlParserInputPtr
01651 inputPop(xmlParserCtxtPtr ctxt)
01652 {
01653     xmlParserInputPtr ret;
01654 
01655     if (ctxt == NULL)
01656         return(NULL);
01657     if (ctxt->inputNr <= 0)
01658         return (NULL);
01659     ctxt->inputNr--;
01660     if (ctxt->inputNr > 0)
01661         ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
01662     else
01663         ctxt->input = NULL;
01664     ret = ctxt->inputTab[ctxt->inputNr];
01665     ctxt->inputTab[ctxt->inputNr] = NULL;
01666     return (ret);
01667 }
01677 int
01678 nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
01679 {
01680     if (ctxt == NULL) return(0);
01681     if (ctxt->nodeNr >= ctxt->nodeMax) {
01682         xmlNodePtr *tmp;
01683 
01684     tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
01685                                       ctxt->nodeMax * 2 *
01686                                       sizeof(ctxt->nodeTab[0]));
01687         if (tmp == NULL) {
01688             xmlErrMemory(ctxt, NULL);
01689             return (-1);
01690         }
01691         ctxt->nodeTab = tmp;
01692     ctxt->nodeMax *= 2;
01693     }
01694     if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) &&
01695         ((ctxt->options & XML_PARSE_HUGE) == 0)) {
01696     xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
01697          "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
01698               xmlParserMaxDepth);
01699     ctxt->instate = XML_PARSER_EOF;
01700     return(-1);
01701     }
01702     ctxt->nodeTab[ctxt->nodeNr] = value;
01703     ctxt->node = value;
01704     return (ctxt->nodeNr++);
01705 }
01706 
01715 xmlNodePtr
01716 nodePop(xmlParserCtxtPtr ctxt)
01717 {
01718     xmlNodePtr ret;
01719 
01720     if (ctxt == NULL) return(NULL);
01721     if (ctxt->nodeNr <= 0)
01722         return (NULL);
01723     ctxt->nodeNr--;
01724     if (ctxt->nodeNr > 0)
01725         ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
01726     else
01727         ctxt->node = NULL;
01728     ret = ctxt->nodeTab[ctxt->nodeNr];
01729     ctxt->nodeTab[ctxt->nodeNr] = NULL;
01730     return (ret);
01731 }
01732 
01733 #ifdef LIBXML_PUSH_ENABLED
01734 
01745 static int
01746 nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
01747            const xmlChar *prefix, const xmlChar *URI, int nsNr)
01748 {
01749     if (ctxt->nameNr >= ctxt->nameMax) {
01750         const xmlChar * *tmp;
01751         void **tmp2;
01752         ctxt->nameMax *= 2;
01753         tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
01754                                     ctxt->nameMax *
01755                                     sizeof(ctxt->nameTab[0]));
01756         if (tmp == NULL) {
01757         ctxt->nameMax /= 2;
01758         goto mem_error;
01759         }
01760     ctxt->nameTab = tmp;
01761         tmp2 = (void **) xmlRealloc((void * *)ctxt->pushTab,
01762                                     ctxt->nameMax * 3 *
01763                                     sizeof(ctxt->pushTab[0]));
01764         if (tmp2 == NULL) {
01765         ctxt->nameMax /= 2;
01766         goto mem_error;
01767         }
01768     ctxt->pushTab = tmp2;
01769     }
01770     ctxt->nameTab[ctxt->nameNr] = value;
01771     ctxt->name = value;
01772     ctxt->pushTab[ctxt->nameNr * 3] = (void *) prefix;
01773     ctxt->pushTab[ctxt->nameNr * 3 + 1] = (void *) URI;
01774     ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (long) nsNr;
01775     return (ctxt->nameNr++);
01776 mem_error:
01777     xmlErrMemory(ctxt, NULL);
01778     return (-1);
01779 }
01788 static const xmlChar *
01789 nameNsPop(xmlParserCtxtPtr ctxt)
01790 {
01791     const xmlChar *ret;
01792 
01793     if (ctxt->nameNr <= 0)
01794         return (NULL);
01795     ctxt->nameNr--;
01796     if (ctxt->nameNr > 0)
01797         ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
01798     else
01799         ctxt->name = NULL;
01800     ret = ctxt->nameTab[ctxt->nameNr];
01801     ctxt->nameTab[ctxt->nameNr] = NULL;
01802     return (ret);
01803 }
01804 #endif /* LIBXML_PUSH_ENABLED */
01805 
01815 int
01816 namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
01817 {
01818     if (ctxt == NULL) return (-1);
01819 
01820     if (ctxt->nameNr >= ctxt->nameMax) {
01821         const xmlChar * *tmp;
01822         ctxt->nameMax *= 2;
01823         tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
01824                                     ctxt->nameMax *
01825                                     sizeof(ctxt->nameTab[0]));
01826         if (tmp == NULL) {
01827         ctxt->nameMax /= 2;
01828         goto mem_error;
01829         }
01830     ctxt->nameTab = tmp;
01831     }
01832     ctxt->nameTab[ctxt->nameNr] = value;
01833     ctxt->name = value;
01834     return (ctxt->nameNr++);
01835 mem_error:
01836     xmlErrMemory(ctxt, NULL);
01837     return (-1);
01838 }
01847 const xmlChar *
01848 namePop(xmlParserCtxtPtr ctxt)
01849 {
01850     const xmlChar *ret;
01851 
01852     if ((ctxt == NULL) || (ctxt->nameNr <= 0))
01853         return (NULL);
01854     ctxt->nameNr--;
01855     if (ctxt->nameNr > 0)
01856         ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
01857     else
01858         ctxt->name = NULL;
01859     ret = ctxt->nameTab[ctxt->nameNr];
01860     ctxt->nameTab[ctxt->nameNr] = NULL;
01861     return (ret);
01862 }
01863 
01864 static int spacePush(xmlParserCtxtPtr ctxt, int val) {
01865     if (ctxt->spaceNr >= ctxt->spaceMax) {
01866         int *tmp;
01867 
01868     ctxt->spaceMax *= 2;
01869         tmp = (int *) xmlRealloc(ctxt->spaceTab,
01870                              ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
01871         if (tmp == NULL) {
01872         xmlErrMemory(ctxt, NULL);
01873         ctxt->spaceMax /=2;
01874         return(-1);
01875     }
01876     ctxt->spaceTab = tmp;
01877     }
01878     ctxt->spaceTab[ctxt->spaceNr] = val;
01879     ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
01880     return(ctxt->spaceNr++);
01881 }
01882 
01883 static int spacePop(xmlParserCtxtPtr ctxt) {
01884     int ret;
01885     if (ctxt->spaceNr <= 0) return(0);
01886     ctxt->spaceNr--;
01887     if (ctxt->spaceNr > 0)
01888     ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
01889     else
01890         ctxt->space = &ctxt->spaceTab[0];
01891     ret = ctxt->spaceTab[ctxt->spaceNr];
01892     ctxt->spaceTab[ctxt->spaceNr] = -1;
01893     return(ret);
01894 }
01895 
01896 /*
01897  * Macros for accessing the content. Those should be used only by the parser,
01898  * and not exported.
01899  *
01900  * Dirty macros, i.e. one often need to make assumption on the context to
01901  * use them
01902  *
01903  *   CUR_PTR return the current pointer to the xmlChar to be parsed.
01904  *           To be used with extreme caution since operations consuming
01905  *           characters may move the input buffer to a different location !
01906  *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
01907  *           This should be used internally by the parser
01908  *           only to compare to ASCII values otherwise it would break when
01909  *           running with UTF-8 encoding.
01910  *   RAW     same as CUR but in the input buffer, bypass any token
01911  *           extraction that may have been done
01912  *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
01913  *           to compare on ASCII based substring.
01914  *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
01915  *           strings without newlines within the parser.
01916  *   NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII 
01917  *           defined char within the parser.
01918  * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
01919  *
01920  *   NEXT    Skip to the next character, this does the proper decoding
01921  *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
01922  *   NEXTL(l) Skip the current unicode character of l xmlChars long.
01923  *   CUR_CHAR(l) returns the current unicode character (int), set l
01924  *           to the number of xmlChars used for the encoding [0-5].
01925  *   CUR_SCHAR  same but operate on a string instead of the context
01926  *   COPY_BUF  copy the current unicode char to the target buffer, increment
01927  *            the index
01928  *   GROW, SHRINK  handling of input buffers
01929  */
01930 
01931 #define RAW (*ctxt->input->cur)
01932 #define CUR (*ctxt->input->cur)
01933 #define NXT(val) ctxt->input->cur[(val)]
01934 #define CUR_PTR ctxt->input->cur
01935 
01936 #define CMP4( s, c1, c2, c3, c4 ) \
01937   ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
01938     ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
01939 #define CMP5( s, c1, c2, c3, c4, c5 ) \
01940   ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )
01941 #define CMP6( s, c1, c2, c3, c4, c5, c6 ) \
01942   ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 )
01943 #define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \
01944   ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 )
01945 #define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \
01946   ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 )
01947 #define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \
01948   ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \
01949     ((unsigned char *) s)[ 8 ] == c9 )
01950 #define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \
01951   ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \
01952     ((unsigned char *) s)[ 9 ] == c10 )
01953 
01954 #define SKIP(val) do {                          \
01955     ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val);           \
01956     if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
01957     if ((*ctxt->input->cur == 0) &&                 \
01958         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))        \
01959         xmlPopInput(ctxt);                      \
01960   } while (0)
01961 
01962 #define SKIPL(val) do {                         \
01963     int skipl;                              \
01964     for(skipl=0; skipl<val; skipl++) {                  \
01965         if (*(ctxt->input->cur) == '\n') {              \
01966     ctxt->input->line++; ctxt->input->col = 1;          \
01967         } else ctxt->input->col++;                  \
01968         ctxt->nbChars++;                        \
01969     ctxt->input->cur++;                     \
01970     }                                   \
01971     if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
01972     if ((*ctxt->input->cur == 0) &&                 \
01973         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))        \
01974         xmlPopInput(ctxt);                      \
01975   } while (0)
01976 
01977 #define SHRINK if ((ctxt->progressive == 0) &&              \
01978            (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
01979            (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
01980     xmlSHRINK (ctxt);
01981 
01982 static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
01983     xmlParserInputShrink(ctxt->input);
01984     if ((*ctxt->input->cur == 0) &&
01985         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
01986         xmlPopInput(ctxt);
01987   }
01988 
01989 #define GROW if ((ctxt->progressive == 0) &&                \
01990          (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK))   \
01991     xmlGROW (ctxt);
01992 
01993 static void xmlGROW (xmlParserCtxtPtr ctxt) {
01994     xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
01995     if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0) &&
01996         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
01997         xmlPopInput(ctxt);
01998 }
01999 
02000 #define SKIP_BLANKS xmlSkipBlankChars(ctxt)
02001 
02002 #define NEXT xmlNextChar(ctxt)
02003 
02004 #define NEXT1 {                             \
02005     ctxt->input->col++;                     \
02006     ctxt->input->cur++;                     \
02007     ctxt->nbChars++;                        \
02008     if (*ctxt->input->cur == 0)                 \
02009         xmlParserInputGrow(ctxt->input, INPUT_CHUNK);       \
02010     }
02011 
02012 #define NEXTL(l) do {                           \
02013     if (*(ctxt->input->cur) == '\n') {                  \
02014     ctxt->input->line++; ctxt->input->col = 1;          \
02015     } else ctxt->input->col++;                      \
02016     ctxt->input->cur += l;              \
02017     if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt); \
02018   } while (0)
02019 
02020 #define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
02021 #define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
02022 
02023 #define COPY_BUF(l,b,i,v)                       \
02024     if (l == 1) b[i++] = (xmlChar) v;                   \
02025     else i += xmlCopyCharMultiByte(&b[i],v)
02026 
02037 int
02038 xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
02039     int res = 0;
02040 
02041     /*
02042      * It's Okay to use CUR/NEXT here since all the blanks are on
02043      * the ASCII range.
02044      */
02045     if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) {
02046     const xmlChar *cur;
02047     /*
02048      * if we are in the document content, go really fast
02049      */
02050     cur = ctxt->input->cur;
02051     while (IS_BLANK_CH(*cur)) {
02052         if (*cur == '\n') {
02053         ctxt->input->line++; ctxt->input->col = 1;
02054         }
02055         cur++;
02056         res++;
02057         if (*cur == 0) {
02058         ctxt->input->cur = cur;
02059         xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
02060         cur = ctxt->input->cur;
02061         }
02062     }
02063     ctxt->input->cur = cur;
02064     } else {
02065     int cur;
02066     do {
02067         cur = CUR;
02068         while (IS_BLANK_CH(cur)) { /* CHECKED tstblanks.xml */
02069         NEXT;
02070         cur = CUR;
02071         res++;
02072         }
02073         while ((cur == 0) && (ctxt->inputNr > 1) &&
02074            (ctxt->instate != XML_PARSER_COMMENT)) {
02075         xmlPopInput(ctxt);
02076         cur = CUR;
02077         }
02078         /*
02079          * Need to handle support of entities branching here
02080          */
02081         if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
02082     } while (IS_BLANK(cur)); /* CHECKED tstblanks.xml */
02083     }
02084     return(res);
02085 }
02086 
02087 /************************************************************************
02088  *                                  *
02089  *      Commodity functions to handle entities          *
02090  *                                  *
02091  ************************************************************************/
02092 
02102 xmlChar
02103 xmlPopInput(xmlParserCtxtPtr ctxt) {
02104     if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0);
02105     if (xmlParserDebugEntities)
02106     xmlGenericError(xmlGenericErrorContext,
02107         "Popping input %d\n", ctxt->inputNr);
02108     xmlFreeInputStream(inputPop(ctxt));
02109     if ((*ctxt->input->cur == 0) &&
02110         (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
02111         return(xmlPopInput(ctxt));
02112     return(CUR);
02113 }
02114 
02124 int
02125 xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
02126     int ret;
02127     if (input == NULL) return(-1);
02128 
02129     if (xmlParserDebugEntities) {
02130     if ((ctxt->input != NULL) && (ctxt->input->filename))
02131         xmlGenericError(xmlGenericErrorContext,
02132             "%s(%d): ", ctxt->input->filename,
02133             ctxt->input->line);
02134     xmlGenericError(xmlGenericErrorContext,
02135         "Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
02136     }
02137     ret = inputPush(ctxt, input);
02138     GROW;
02139     return(ret);
02140 }
02141 
02157 int
02158 xmlParseCharRef(xmlParserCtxtPtr ctxt) {
02159     unsigned int val = 0;
02160     int count = 0;
02161     unsigned int outofrange = 0;
02162 
02163     /*
02164      * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
02165      */
02166     if ((RAW == '&') && (NXT(1) == '#') &&
02167         (NXT(2) == 'x')) {
02168     SKIP(3);
02169     GROW;
02170     while (RAW != ';') { /* loop blocked by count */
02171         if (count++ > 20) {
02172         count = 0;
02173         GROW;
02174         }
02175         if ((RAW >= '0') && (RAW <= '9')) 
02176             val = val * 16 + (CUR - '0');
02177         else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
02178             val = val * 16 + (CUR - 'a') + 10;
02179         else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
02180             val = val * 16 + (CUR - 'A') + 10;
02181         else {
02182         xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
02183         val = 0;
02184         break;
02185         }
02186         if (val > 0x10FFFF)
02187             outofrange = val;
02188 
02189         NEXT;
02190         count++;
02191     }
02192     if (RAW == ';') {
02193         /* on purpose to avoid reentrancy problems with NEXT and SKIP */
02194         ctxt->input->col++;
02195         ctxt->nbChars ++;
02196         ctxt->input->cur++;
02197     }
02198     } else if  ((RAW == '&') && (NXT(1) == '#')) {
02199     SKIP(2);
02200     GROW;
02201     while (RAW != ';') { /* loop blocked by count */
02202         if (count++ > 20) {
02203         count = 0;
02204         GROW;
02205         }
02206         if ((RAW >= '0') && (RAW <= '9')) 
02207             val = val * 10 + (CUR - '0');
02208         else {
02209         xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
02210         val = 0;
02211         break;
02212         }
02213         if (val > 0x10FFFF)
02214             outofrange = val;
02215 
02216         NEXT;
02217         count++;
02218     }
02219     if (RAW == ';') {
02220         /* on purpose to avoid reentrancy problems with NEXT and SKIP */
02221         ctxt->input->col++;
02222         ctxt->nbChars ++;
02223         ctxt->input->cur++;
02224     }
02225     } else {
02226         xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
02227     }
02228 
02229     /*
02230      * [ WFC: Legal Character ]
02231      * Characters referred to using character references must match the
02232      * production for Char. 
02233      */
02234     if ((IS_CHAR(val) && (outofrange == 0))) {
02235         return(val);
02236     } else {
02237         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
02238                           "xmlParseCharRef: invalid xmlChar value %d\n",
02239                       val);
02240     }
02241     return(0);
02242 }
02243 
02262 static int
02263 xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
02264     const xmlChar *ptr;
02265     xmlChar cur;
02266     unsigned int val = 0;
02267     unsigned int outofrange = 0;
02268 
02269     if ((str == NULL) || (*str == NULL)) return(0);
02270     ptr = *str;
02271     cur = *ptr;
02272     if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
02273     ptr += 3;
02274     cur = *ptr;
02275     while (cur != ';') { /* Non input consuming loop */
02276         if ((cur >= '0') && (cur <= '9')) 
02277             val = val * 16 + (cur - '0');
02278         else if ((cur >= 'a') && (cur <= 'f'))
02279             val = val * 16 + (cur - 'a') + 10;
02280         else if ((cur >= 'A') && (cur <= 'F'))
02281             val = val * 16 + (cur - 'A') + 10;
02282         else {
02283         xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
02284         val = 0;
02285         break;
02286         }
02287         if (val > 0x10FFFF)
02288             outofrange = val;
02289 
02290         ptr++;
02291         cur = *ptr;
02292     }
02293     if (cur == ';')
02294         ptr++;
02295     } else if  ((cur == '&') && (ptr[1] == '#')){
02296     ptr += 2;
02297     cur = *ptr;
02298     while (cur != ';') { /* Non input consuming loops */
02299         if ((cur >= '0') && (cur <= '9')) 
02300             val = val * 10 + (cur - '0');
02301         else {
02302         xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
02303         val = 0;
02304         break;
02305         }
02306         if (val > 0x10FFFF)
02307             outofrange = val;
02308 
02309         ptr++;
02310         cur = *ptr;
02311     }
02312     if (cur == ';')
02313         ptr++;
02314     } else {
02315     xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
02316     return(0);
02317     }
02318     *str = ptr;
02319 
02320     /*
02321      * [ WFC: Legal Character ]
02322      * Characters referred to using character references must match the
02323      * production for Char. 
02324      */
02325     if ((IS_CHAR(val) && (outofrange == 0))) {
02326         return(val);
02327     } else {
02328         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
02329               "xmlParseStringCharRef: invalid xmlChar value %d\n",
02330               val);
02331     }
02332     return(0);
02333 }
02334 
02346 static void deallocblankswrapper (xmlChar *str) {xmlFree(str);}
02347  
02348 static xmlParserInputPtr
02349 xmlNewBlanksWrapperInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
02350     xmlParserInputPtr input;
02351     xmlChar *buffer;
02352     size_t length;
02353     if (entity == NULL) {
02354     xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
02355                 "xmlNewBlanksWrapperInputStream entity\n");
02356     return(NULL);
02357     }
02358     if (xmlParserDebugEntities)
02359     xmlGenericError(xmlGenericErrorContext,
02360         "new blanks wrapper for entity: %s\n", entity->name);
02361     input = xmlNewInputStream(ctxt);
02362     if (input == NULL) {
02363     return(NULL);
02364     }
02365     length = xmlStrlen(entity->name) + 5;
02366     buffer = xmlMallocAtomic(length);
02367     if (buffer == NULL) {
02368     xmlErrMemory(ctxt, NULL);
02369         xmlFree(input);
02370         return(NULL);
02371     }
02372     buffer [0] = ' ';
02373     buffer [1] = '%';
02374     buffer [length-3] = ';';
02375     buffer [length-2] = ' ';
02376     buffer [length-1] = 0;
02377     memcpy(buffer + 2, entity->name, length - 5);
02378     input->free = deallocblankswrapper;
02379     input->base = buffer;
02380     input->cur = buffer;
02381     input->length = length;
02382     input->end = &buffer[length];
02383     return(input);
02384 }
02385 
02418 void
02419 xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
02420     const xmlChar *name;
02421     xmlEntityPtr entity = NULL;
02422     xmlParserInputPtr input;
02423 
02424     if (RAW != '%') return;
02425     switch(ctxt->instate) {
02426     case XML_PARSER_CDATA_SECTION:
02427         return;
02428         case XML_PARSER_COMMENT:
02429         return;
02430     case XML_PARSER_START_TAG:
02431         return;
02432     case XML_PARSER_END_TAG:
02433         return;
02434         case XML_PARSER_EOF:
02435         xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL);
02436         return;
02437         case XML_PARSER_PROLOG:
02438     case XML_PARSER_START:
02439     case XML_PARSER_MISC:
02440         xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL);
02441         return;
02442     case XML_PARSER_ENTITY_DECL:
02443         case XML_PARSER_CONTENT:
02444         case XML_PARSER_ATTRIBUTE_VALUE:
02445         case XML_PARSER_PI:
02446     case XML_PARSER_SYSTEM_LITERAL:
02447     case XML_PARSER_PUBLIC_LITERAL:
02448         /* we just ignore it there */
02449         return;
02450         case XML_PARSER_EPILOG:
02451         xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL);
02452         return;
02453     case XML_PARSER_ENTITY_VALUE:
02454         /*
02455          * NOTE: in the case of entity values, we don't do the
02456          *       substitution here since we need the literal
02457          *       entity value to be able to save the internal
02458          *       subset of the document.
02459          *       This will be handled by xmlStringDecodeEntities
02460          */
02461         return;
02462         case XML_PARSER_DTD:
02463         /*
02464          * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
02465          * In the internal DTD subset, parameter-entity references
02466          * can occur only where markup declarations can occur, not
02467          * within markup declarations.
02468          * In that case this is handled in xmlParseMarkupDecl
02469          */
02470         if ((ctxt->external == 0) && (ctxt->inputNr == 1))
02471         return;
02472         if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0)
02473         return;
02474             break;
02475         case XML_PARSER_IGNORE:
02476             return;
02477     }
02478 
02479     NEXT;
02480     name = xmlParseName(ctxt);
02481     if (xmlParserDebugEntities)
02482     xmlGenericError(xmlGenericErrorContext,
02483         "PEReference: %s\n", name);
02484     if (name == NULL) {
02485     xmlFatalErr(ctxt, XML_ERR_PEREF_NO_NAME, NULL);
02486     } else {
02487     if (RAW == ';') {
02488         NEXT;
02489         if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
02490         entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
02491         if (entity == NULL) {
02492             
02493         /*
02494          * [ WFC: Entity Declared ]
02495          * In a document without any DTD, a document with only an
02496          * internal DTD subset which contains no parameter entity
02497          * references, or a document with "standalone='yes'", ...
02498          * ... The declaration of a parameter entity must precede
02499          * any reference to it...
02500          */
02501         if ((ctxt->standalone == 1) ||
02502             ((ctxt->hasExternalSubset == 0) &&
02503              (ctxt->hasPErefs == 0))) {
02504             xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
02505              "PEReference: %%%s; not found\n", name);
02506             } else {
02507             /*
02508              * [ VC: Entity Declared ]
02509              * In a document with an external subset or external
02510              * parameter entities with "standalone='no'", ...
02511              * ... The declaration of a parameter entity must precede
02512              * any reference to it...
02513              */
02514             if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
02515                 xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
02516                              "PEReference: %%%s; not found\n",
02517                          name, NULL);
02518             } else 
02519                 xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
02520                           "PEReference: %%%s; not found\n",
02521                       name, NULL);
02522             ctxt->valid = 0;
02523         }
02524         } else if (ctxt->input->free != deallocblankswrapper) {
02525             input = xmlNewBlanksWrapperInputStream(ctxt, entity);
02526             if (xmlPushInput(ctxt, input) < 0)
02527                 return;
02528         } else {
02529             if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
02530             (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
02531             xmlChar start[4];
02532             xmlCharEncoding enc;
02533 
02534             /*
02535              * handle the extra spaces added before and after
02536              * c.f. http://www.w3.org/TR/REC-xml#as-PE
02537              * this is done independently.
02538              */
02539             input = xmlNewEntityInputStream(ctxt, entity);
02540             if (xmlPushInput(ctxt, input) < 0)
02541                 return;
02542 
02543             /* 
02544              * Get the 4 first bytes and decode the charset
02545              * if enc != XML_CHAR_ENCODING_NONE
02546              * plug some encoding conversion routines.
02547              * Note that, since we may have some non-UTF8
02548              * encoding (like UTF16, bug 135229), the 'length'
02549              * is not known, but we can calculate based upon
02550              * the amount of data in the buffer.
02551              */
02552             GROW
02553             if ((ctxt->input->end - ctxt->input->cur)>=4) {
02554             start[0] = RAW;
02555             start[1] = NXT(1);
02556             start[2] = NXT(2);
02557             start[3] = NXT(3);
02558             enc = xmlDetectCharEncoding(start, 4);
02559             if (enc != XML_CHAR_ENCODING_NONE) {
02560                 xmlSwitchEncoding(ctxt, enc);
02561             }
02562             }
02563 
02564             if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
02565             (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l' )) &&
02566             (IS_BLANK_CH(NXT(5)))) {
02567             xmlParseTextDecl(ctxt);
02568             }
02569         } else {
02570             xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
02571                  "PEReference: %s is not a parameter entity\n",
02572                       name);
02573         }
02574         }
02575     } else {
02576         xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
02577     }
02578     }
02579 }
02580 
02581 /*
02582  * Macro used to grow the current buffer.
02583  */
02584 #define growBuffer(buffer, n) {                     \
02585     xmlChar *tmp;                           \
02586     buffer##_size *= 2;                         \
02587     buffer##_size += n;                         \
02588     tmp = (xmlChar *)                           \
02589         xmlRealloc(buffer, buffer##_size * sizeof(xmlChar));    \
02590     if (tmp == NULL) goto mem_error;                    \
02591     buffer = tmp;                           \
02592 }
02593 
02613 xmlChar *
02614 xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
02615               int what, xmlChar end, xmlChar  end2, xmlChar end3) {
02616     xmlChar *buffer = NULL;
02617     int buffer_size = 0;
02618 
02619     xmlChar *current = NULL;
02620     xmlChar *rep = NULL;
02621     const xmlChar *last;
02622     xmlEntityPtr ent;
02623     int c,l;
02624     int nbchars = 0;
02625 
02626     if ((ctxt == NULL) || (str == NULL) || (len < 0))
02627     return(NULL);
02628     last = str + len;
02629 
02630     if (((ctxt->depth > 40) &&
02631          ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
02632     (ctxt->depth > 1024)) {
02633     xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
02634     return(NULL);
02635     }
02636 
02637     /*
02638      * allocate a translation buffer.
02639      */
02640     buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
02641     buffer = (xmlChar *) xmlMallocAtomic(buffer_size * sizeof(xmlChar));
02642     if (buffer == NULL) goto mem_error;
02643 
02644     /*
02645      * OK loop until we reach one of the ending char or a size limit.
02646      * we are operating on already parsed values.
02647      */
02648     if (str < last)
02649     c = CUR_SCHAR(str, l);
02650     else
02651         c = 0;
02652     while ((c != 0) && (c != end) && /* non input consuming loop */
02653        (c != end2) && (c != end3)) {
02654 
02655     if (c == 0) break;
02656         if ((c == '&') && (str[1] == '#')) {
02657         int val = xmlParseStringCharRef(ctxt, &str);
02658         if (val != 0) {
02659         COPY_BUF(0,buffer,nbchars,val);
02660         }
02661         if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
02662             growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
02663         }
02664     } else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
02665         if (xmlParserDebugEntities)
02666         xmlGenericError(xmlGenericErrorContext,
02667             "String decoding Entity Reference: %.30s\n",
02668             str);
02669         ent = xmlParseStringEntityRef(ctxt, &str);
02670         if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
02671             (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
02672             goto int_error;
02673         if (ent != NULL)
02674             ctxt->nbentities += ent->checked;
02675         if ((ent != NULL) &&
02676         (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
02677         if (ent->content != NULL) {
02678             COPY_BUF(0,buffer,nbchars,ent->content[0]);
02679             if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
02680             growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
02681             }
02682         } else {
02683             xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
02684                 "predefined entity has no content\n");
02685         }
02686         } else if ((ent != NULL) && (ent->content != NULL)) {
02687         ctxt->depth++;
02688         rep = xmlStringDecodeEntities(ctxt, ent->content, what,
02689                                   0, 0, 0);
02690         ctxt->depth--;
02691 
02692         if (rep != NULL) {
02693             current = rep;
02694             while (*current != 0) { /* non input consuming loop */
02695             buffer[nbchars++] = *current++;
02696             if (nbchars >
02697                     buffer_size - XML_PARSER_BUFFER_SIZE) {
02698                 if (xmlParserEntityCheck(ctxt, nbchars, ent))
02699                 goto int_error;
02700                 growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
02701             }
02702             }
02703             xmlFree(rep);
02704             rep = NULL;
02705         }
02706         } else if (ent != NULL) {
02707         int i = xmlStrlen(ent->name);
02708         const xmlChar *cur = ent->name;
02709 
02710         buffer[nbchars++] = '&';
02711         if (nbchars > buffer_size - i - XML_PARSER_BUFFER_SIZE) {
02712             growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
02713         }
02714         for (;i > 0;i--)
02715             buffer[nbchars++] = *cur++;
02716         buffer[nbchars++] = ';';
02717         }
02718     } else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
02719         if (xmlParserDebugEntities)
02720         xmlGenericError(xmlGenericErrorContext,
02721             "String decoding PE Reference: %.30s\n", str);
02722         ent = xmlParseStringPEReference(ctxt, &str);
02723         if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
02724             goto int_error;
02725         if (ent != NULL)
02726             ctxt->nbentities += ent->checked;
02727         if (ent != NULL) {
02728                 if (ent->content == NULL) {
02729             xmlLoadEntityContent(ctxt, ent);
02730         }
02731         ctxt->depth++;
02732         rep = xmlStringDecodeEntities(ctxt, ent->content, what,
02733                                   0, 0, 0);
02734         ctxt->depth--;
02735         if (rep != NULL) {
02736             current = rep;
02737             while (*current != 0) { /* non input consuming loop */
02738             buffer[nbchars++] = *current++;
02739             if (nbchars >
02740                     buffer_size - XML_PARSER_BUFFER_SIZE) {
02741                 if (xmlParserEntityCheck(ctxt, nbchars, ent))
02742                     goto int_error;
02743                 growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
02744             }
02745             }
02746             xmlFree(rep);
02747             rep = NULL;
02748         }
02749         }
02750     } else {
02751         COPY_BUF(l,buffer,nbchars,c);
02752         str += l;
02753         if (nbchars > buffer_size - XML_PARSER_BUFFER_SIZE) {
02754           growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
02755         }
02756     }
02757     if (str < last)
02758         c = CUR_SCHAR(str, l);
02759     else
02760         c = 0;
02761     }
02762     buffer[nbchars] = 0;
02763     return(buffer);
02764 
02765 mem_error:
02766     xmlErrMemory(ctxt, NULL);
02767 int_error:
02768     if (rep != NULL)
02769         xmlFree(rep);
02770     if (buffer != NULL)
02771         xmlFree(buffer);
02772     return(NULL);
02773 }
02774 
02793 xmlChar *
02794 xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
02795                 xmlChar end, xmlChar  end2, xmlChar end3) {
02796     if ((ctxt == NULL) || (str == NULL)) return(NULL);
02797     return(xmlStringLenDecodeEntities(ctxt, str, xmlStrlen(str), what,
02798            end, end2, end3));
02799 }
02800 
02801 /************************************************************************
02802  *                                  *
02803  *      Commodity functions, cleanup needed ?           *
02804  *                                  *
02805  ************************************************************************/
02806 
02819 static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
02820                      int blank_chars) {
02821     int i, ret;
02822     xmlNodePtr lastChild;
02823 
02824     /*
02825      * Don't spend time trying to differentiate them, the same callback is
02826      * used !
02827      */
02828     if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
02829     return(0);
02830 
02831     /*
02832      * Check for xml:space value.
02833      */
02834     if ((ctxt->space == NULL) || (*(ctxt->space) == 1) ||
02835         (*(ctxt->space) == -2))
02836     return(0);
02837 
02838     /*
02839      * Check that the string is made of blanks
02840      */
02841     if (blank_chars == 0) {
02842     for (i = 0;i < len;i++)
02843         if (!(IS_BLANK_CH(str[i]))) return(0);
02844     }
02845 
02846     /*
02847      * Look if the element is mixed content in the DTD if available
02848      */
02849     if (ctxt->node == NULL) return(0);
02850     if (ctxt->myDoc != NULL) {
02851     ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
02852         if (ret == 0) return(1);
02853         if (ret == 1) return(0);
02854     }
02855 
02856     /*
02857      * Otherwise, heuristic :-\
02858      */
02859     if ((RAW != '<') && (RAW != 0xD)) return(0);
02860     if ((ctxt->node->children == NULL) &&
02861     (RAW == '<') && (NXT(1) == '/')) return(0);
02862 
02863     lastChild = xmlGetLastChild(ctxt->node);
02864     if (lastChild == NULL) {
02865         if ((ctxt->node->type != XML_ELEMENT_NODE) &&
02866             (ctxt->node->content != NULL)) return(0);
02867     } else if (xmlNodeIsText(lastChild))
02868         return(0);
02869     else if ((ctxt->node->children != NULL) &&
02870              (xmlNodeIsText(ctxt->node->children)))
02871         return(0);
02872     return(1);
02873 }
02874 
02875 /************************************************************************
02876  *                                  *
02877  *      Extra stuff for namespace support           *
02878  *  Relates to http://www.w3.org/TR/WD-xml-names            *
02879  *                                  *
02880  ************************************************************************/
02881 
02900 xmlChar *
02901 xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
02902     xmlChar buf[XML_MAX_NAMELEN + 5];
02903     xmlChar *buffer = NULL;
02904     int len = 0;
02905     int max = XML_MAX_NAMELEN;
02906     xmlChar *ret = NULL;
02907     const xmlChar *cur = name;
02908     int c;
02909 
02910     if (prefix == NULL) return(NULL);
02911     *prefix = NULL;
02912 
02913     if (cur == NULL) return(NULL);
02914 
02915 #ifndef XML_XML_NAMESPACE
02916     /* xml: prefix is not really a namespace */
02917     if ((cur[0] == 'x') && (cur[1] == 'm') &&
02918         (cur[2] == 'l') && (cur[3] == ':'))
02919     return(xmlStrdup(name));
02920 #endif
02921 
02922     /* nasty but well=formed */
02923     if (cur[0] == ':')
02924     return(xmlStrdup(name));
02925 
02926     c = *cur++;
02927     while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
02928     buf[len++] = c;
02929     c = *cur++;
02930     }
02931     if (len >= max) {
02932     /*
02933      * Okay someone managed to make a huge name, so he's ready to pay
02934      * for the processing speed.
02935      */
02936     max = len * 2;
02937 
02938     buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
02939     if (buffer == NULL) {
02940         xmlErrMemory(ctxt, NULL);
02941         return(NULL);
02942     }
02943     memcpy(buffer, buf, len);
02944     while ((c != 0) && (c != ':')) { /* tested bigname.xml */
02945         if (len + 10 > max) {
02946             xmlChar *tmp;
02947 
02948         max *= 2;
02949         tmp = (xmlChar *) xmlRealloc(buffer,
02950                         max * sizeof(xmlChar));
02951         if (tmp == NULL) {
02952             xmlFree(buffer);
02953             xmlErrMemory(ctxt, NULL);
02954             return(NULL);
02955         }
02956         buffer = tmp;
02957         }
02958         buffer[len++] = c;
02959         c = *cur++;
02960     }
02961     buffer[len] = 0;
02962     }
02963 
02964     if ((c == ':') && (*cur == 0)) {
02965         if (buffer != NULL)
02966         xmlFree(buffer);
02967     *prefix = NULL;
02968     return(xmlStrdup(name));
02969     }
02970 
02971     if (buffer == NULL)
02972     ret = xmlStrndup(buf, len);
02973     else {
02974     ret = buffer;
02975     buffer = NULL;
02976     max = XML_MAX_NAMELEN;
02977     }
02978 
02979 
02980     if (c == ':') {
02981     c = *cur;
02982         *prefix = ret;
02983     if (c == 0) {
02984         return(xmlStrndup(BAD_CAST "", 0));
02985     }
02986     len = 0;
02987 
02988     /*
02989      * Check that the first character is proper to start
02990      * a new name
02991      */
02992     if (!(((c >= 0x61) && (c <= 0x7A)) ||
02993           ((c >= 0x41) && (c <= 0x5A)) ||
02994           (c == '_') || (c == ':'))) {
02995         int l;
02996         int first = CUR_SCHAR(cur, l);
02997 
02998         if (!IS_LETTER(first) && (first != '_')) {
02999         xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME,
03000                 "Name %s is not XML Namespace compliant\n",
03001                   name);
03002         }
03003     }
03004     cur++;
03005 
03006     while ((c != 0) && (len < max)) { /* tested bigname2.xml */
03007         buf[len++] = c;
03008         c = *cur++;
03009     }
03010     if (len >= max) {
03011         /*
03012          * Okay someone managed to make a huge name, so he's ready to pay
03013          * for the processing speed.
03014          */
03015         max = len * 2;
03016 
03017         buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
03018         if (buffer == NULL) {
03019             xmlErrMemory(ctxt, NULL);
03020         return(NULL);
03021         }
03022         memcpy(buffer, buf, len);
03023         while (c != 0) { /* tested bigname2.xml */
03024         if (len + 10 > max) {
03025             xmlChar *tmp;
03026 
03027             max *= 2;
03028             tmp = (xmlChar *) xmlRealloc(buffer,
03029                             max * sizeof(xmlChar));
03030             if (tmp == NULL) {
03031             xmlErrMemory(ctxt, NULL);
03032             xmlFree(buffer);
03033             return(NULL);
03034             }
03035             buffer = tmp;
03036         }
03037         buffer[len++] = c;
03038         c = *cur++;
03039         }
03040         buffer[len] = 0;
03041     }
03042 
03043     if (buffer == NULL)
03044         ret = xmlStrndup(buf, len);
03045     else {
03046         ret = buffer;
03047     }
03048     }
03049 
03050     return(ret);
03051 }
03052 
03053 /************************************************************************
03054  *                                  *
03055  *          The parser itself               *
03056  *  Relates to http://www.w3.org/TR/REC-xml             *
03057  *                                  *
03058  ************************************************************************/
03059 
03060 /************************************************************************
03061  *                                  *
03062  *  Routines to parse Name, NCName and NmToken          *
03063  *                                  *
03064  ************************************************************************/
03065 #ifdef DEBUG
03066 static unsigned long nbParseName = 0;
03067 static unsigned long nbParseNmToken = 0;
03068 static unsigned long nbParseNCName = 0;
03069 static unsigned long nbParseNCNameComplex = 0;
03070 static unsigned long nbParseNameComplex = 0;
03071 static unsigned long nbParseStringName = 0;
03072 #endif
03073 
03074 /*
03075  * The two following functions are related to the change of accepted
03076  * characters for Name and NmToken in the Revision 5 of XML-1.0
03077  * They correspond to the modified production [4] and the new production [4a]
03078  * changes in that revision. Also note that the macros used for the
03079  * productions Letter, Digit, CombiningChar and Extender are not needed
03080  * anymore.
03081  * We still keep compatibility to pre-revision5 parsing semantic if the
03082  * new XML_PARSE_OLD10 option is given to the parser.
03083  */
03084 static int
03085 xmlIsNameStartChar(xmlParserCtxtPtr ctxt, int c) {
03086     if ((ctxt->options & XML_PARSE_OLD10) == 0) {
03087         /*
03088      * Use the new checks of production [4] [4a] amd [5] of the
03089      * Update 5 of XML-1.0
03090      */
03091     if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
03092         (((c >= 'a') && (c <= 'z')) ||
03093          ((c >= 'A') && (c <= 'Z')) ||
03094          (c == '_') || (c == ':') ||
03095          ((c >= 0xC0) && (c <= 0xD6)) ||
03096          ((c >= 0xD8) && (c <= 0xF6)) ||
03097          ((c >= 0xF8) && (c <= 0x2FF)) ||
03098          ((c >= 0x370) && (c <= 0x37D)) ||
03099          ((c >= 0x37F) && (c <= 0x1FFF)) ||
03100          ((c >= 0x200C) && (c <= 0x200D)) ||
03101          ((c >= 0x2070) && (c <= 0x218F)) ||
03102          ((c >= 0x2C00) && (c <= 0x2FEF)) ||
03103          ((c >= 0x3001) && (c <= 0xD7FF)) ||
03104          ((c >= 0xF900) && (c <= 0xFDCF)) ||
03105          ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
03106          ((c >= 0x10000) && (c <= 0xEFFFF))))
03107         return(1);
03108     } else {
03109         if (IS_LETTER(c) || (c == '_') || (c == ':'))
03110         return(1);
03111     }
03112     return(0);
03113 }
03114 
03115 static int
03116 xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) {
03117     if ((ctxt->options & XML_PARSE_OLD10) == 0) {
03118         /*
03119      * Use the new checks of production [4] [4a] amd [5] of the
03120      * Update 5 of XML-1.0
03121      */
03122     if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
03123         (((c >= 'a') && (c <= 'z')) ||
03124          ((c >= 'A') && (c <= 'Z')) ||
03125          ((c >= '0') && (c <= '9')) || /* !start */
03126          (c == '_') || (c == ':') ||
03127          (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
03128          ((c >= 0xC0) && (c <= 0xD6)) ||
03129          ((c >= 0xD8) && (c <= 0xF6)) ||
03130          ((c >= 0xF8) && (c <= 0x2FF)) ||
03131          ((c >= 0x300) && (c <= 0x36F)) || /* !start */
03132          ((c >= 0x370) && (c <= 0x37D)) ||
03133          ((c >= 0x37F) && (c <= 0x1FFF)) ||
03134          ((c >= 0x200C) && (c <= 0x200D)) ||
03135          ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
03136          ((c >= 0x2070) && (c <= 0x218F)) ||
03137          ((c >= 0x2C00) && (c <= 0x2FEF)) ||
03138          ((c >= 0x3001) && (c <= 0xD7FF)) ||
03139          ((c >= 0xF900) && (c <= 0xFDCF)) ||
03140          ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
03141          ((c >= 0x10000) && (c <= 0xEFFFF))))
03142          return(1);
03143     } else {
03144         if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
03145             (c == '.') || (c == '-') ||
03146         (c == '_') || (c == ':') || 
03147         (IS_COMBINING(c)) ||
03148         (IS_EXTENDER(c)))
03149         return(1);
03150     }
03151     return(0);
03152 }
03153 
03154 static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt,
03155                                           int *len, int *alloc, int normalize);
03156 
03157 static const xmlChar *
03158 xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
03159     int len = 0, l;
03160     int c;
03161     int count = 0;
03162 
03163 #ifdef DEBUG
03164     nbParseNameComplex++;
03165 #endif
03166 
03167     /*
03168      * Handler for more complex cases
03169      */
03170     GROW;
03171     c = CUR_CHAR(l);
03172     if ((ctxt->options & XML_PARSE_OLD10) == 0) {
03173         /*
03174      * Use the new checks of production [4] [4a] amd [5] of the
03175      * Update 5 of XML-1.0
03176      */
03177     if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
03178         (!(((c >= 'a') && (c <= 'z')) ||
03179            ((c >= 'A') && (c <= 'Z')) ||
03180            (c == '_') || (c == ':') ||
03181            ((c >= 0xC0) && (c <= 0xD6)) ||
03182            ((c >= 0xD8) && (c <= 0xF6)) ||
03183            ((c >= 0xF8) && (c <= 0x2FF)) ||
03184            ((c >= 0x370) && (c <= 0x37D)) ||
03185            ((c >= 0x37F) && (c <= 0x1FFF)) ||
03186            ((c >= 0x200C) && (c <= 0x200D)) ||
03187            ((c >= 0x2070) && (c <= 0x218F)) ||
03188            ((c >= 0x2C00) && (c <= 0x2FEF)) ||
03189            ((c >= 0x3001) && (c <= 0xD7FF)) ||
03190            ((c >= 0xF900) && (c <= 0xFDCF)) ||
03191            ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
03192            ((c >= 0x10000) && (c <= 0xEFFFF))))) {
03193         return(NULL);
03194     }
03195     len += l;
03196     NEXTL(l);
03197     c = CUR_CHAR(l);
03198     while ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
03199            (((c >= 'a') && (c <= 'z')) ||
03200             ((c >= 'A') && (c <= 'Z')) ||
03201             ((c >= '0') && (c <= '9')) || /* !start */
03202             (c == '_') || (c == ':') ||
03203             (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
03204             ((c >= 0xC0) && (c <= 0xD6)) ||
03205             ((c >= 0xD8) && (c <= 0xF6)) ||
03206             ((c >= 0xF8) && (c <= 0x2FF)) ||
03207             ((c >= 0x300) && (c <= 0x36F)) || /* !start */
03208             ((c >= 0x370) && (c <= 0x37D)) ||
03209             ((c >= 0x37F) && (c <= 0x1FFF)) ||
03210             ((c >= 0x200C) && (c <= 0x200D)) ||
03211             ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
03212             ((c >= 0x2070) && (c <= 0x218F)) ||
03213             ((c >= 0x2C00) && (c <= 0x2FEF)) ||
03214             ((c >= 0x3001) && (c <= 0xD7FF)) ||
03215             ((c >= 0xF900) && (c <= 0xFDCF)) ||
03216             ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
03217             ((c >= 0x10000) && (c <= 0xEFFFF))
03218         )) {
03219         if (count++ > 100) {
03220         count = 0;
03221         GROW;
03222         }
03223         len += l;
03224         NEXTL(l);
03225         c = CUR_CHAR(l);
03226     }
03227     } else {
03228     if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
03229         (!IS_LETTER(c) && (c != '_') &&
03230          (c != ':'))) {
03231         return(NULL);
03232     }
03233     len += l;
03234     NEXTL(l);
03235     c = CUR_CHAR(l);
03236 
03237     while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
03238            ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
03239         (c == '.') || (c == '-') ||
03240         (c == '_') || (c == ':') || 
03241         (IS_COMBINING(c)) ||
03242         (IS_EXTENDER(c)))) {
03243         if (count++ > 100) {
03244         count = 0;
03245         GROW;
03246         }
03247         len += l;
03248         NEXTL(l);
03249         c = CUR_CHAR(l);
03250     }
03251     }
03252     if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
03253         return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
03254     return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
03255 }
03256 
03273 const xmlChar *
03274 xmlParseName(xmlParserCtxtPtr ctxt) {
03275     const xmlChar *in;
03276     const xmlChar *ret;
03277     int count = 0;
03278 
03279     GROW;
03280 
03281 #ifdef DEBUG
03282     nbParseName++;
03283 #endif
03284 
03285     /*
03286      * Accelerator for simple ASCII names
03287      */
03288     in = ctxt->input->cur;
03289     if (((*in >= 0x61) && (*in <= 0x7A)) ||
03290     ((*in >= 0x41) && (*in <= 0x5A)) ||
03291     (*in == '_') || (*in == ':')) {
03292     in++;
03293     while (((*in >= 0x61) && (*in <= 0x7A)) ||
03294            ((*in >= 0x41) && (*in <= 0x5A)) ||
03295            ((*in >= 0x30) && (*in <= 0x39)) ||
03296            (*in == '_') || (*in == '-') ||
03297            (*in == ':') || (*in == '.'))
03298         in++;
03299     if ((*in > 0) && (*in < 0x80)) {
03300         count = in - ctxt->input->cur;
03301         ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
03302         ctxt->input->cur = in;
03303         ctxt->nbChars += count;
03304         ctxt->input->col += count;
03305         if (ret == NULL)
03306             xmlErrMemory(ctxt, NULL);
03307         return(ret);
03308     }
03309     }
03310     /* accelerator for special cases */
03311     return(xmlParseNameComplex(ctxt));
03312 }
03313 
03314 static const xmlChar *
03315 xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
03316     int len = 0, l;
03317     int c;
03318     int count = 0;
03319 
03320 #ifdef DEBUG
03321     nbParseNCNameComplex++;
03322 #endif
03323 
03324     /*
03325      * Handler for more complex cases
03326      */
03327     GROW;
03328     c = CUR_CHAR(l);
03329     if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
03330     (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
03331     return(NULL);
03332     }
03333 
03334     while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
03335        (xmlIsNameChar(ctxt, c) && (c != ':'))) {
03336     if (count++ > 100) {
03337         count = 0;
03338         GROW;
03339     }
03340     len += l;
03341     NEXTL(l);
03342     c = CUR_CHAR(l);
03343     }
03344     return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
03345 }
03346 
03362 static const xmlChar *
03363 xmlParseNCName(xmlParserCtxtPtr ctxt) {
03364     const xmlChar *in;
03365     const xmlChar *ret;
03366     int count = 0;
03367 
03368 #ifdef DEBUG
03369     nbParseNCName++;
03370 #endif
03371 
03372     /*
03373      * Accelerator for simple ASCII names
03374      */
03375     in = ctxt->input->cur;
03376     if (((*in >= 0x61) && (*in <= 0x7A)) ||
03377     ((*in >= 0x41) && (*in <= 0x5A)) ||
03378     (*in == '_')) {
03379     in++;
03380     while (((*in >= 0x61) && (*in <= 0x7A)) ||
03381            ((*in >= 0x41) && (*in <= 0x5A)) ||
03382            ((*in >= 0x30) && (*in <= 0x39)) ||
03383            (*in == '_') || (*in == '-') ||
03384            (*in == '.'))
03385         in++;
03386     if ((*in > 0) && (*in < 0x80)) {
03387         count = in - ctxt->input->cur;
03388         ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
03389         ctxt->input->cur = in;
03390         ctxt->nbChars += count;
03391         ctxt->input->col += count;
03392         if (ret == NULL) {
03393             xmlErrMemory(ctxt, NULL);
03394         }
03395         return(ret);
03396     }
03397     }
03398     return(xmlParseNCNameComplex(ctxt));
03399 }
03400 
03412 static const xmlChar *
03413 xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
03414     register const xmlChar *cmp = other;
03415     register const xmlChar *in;
03416     const xmlChar *ret;
03417 
03418     GROW;
03419 
03420     in = ctxt->input->cur;
03421     while (*in != 0 && *in == *cmp) {
03422     ++in;
03423     ++cmp;
03424     ctxt->input->col++;
03425     }
03426     if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
03427     /* success */
03428     ctxt->input->cur = in;
03429     return (const xmlChar*) 1;
03430     }
03431     /* failure (or end of input buffer), check with full function */
03432     ret = xmlParseName (ctxt);
03433     /* strings coming from the dictionnary direct compare possible */
03434     if (ret == other) {
03435     return (const xmlChar*) 1;
03436     }
03437     return ret;
03438 }
03439 
03458 static xmlChar *
03459 xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
03460     xmlChar buf[XML_MAX_NAMELEN + 5];
03461     const xmlChar *cur = *str;
03462     int len = 0, l;
03463     int c;
03464 
03465 #ifdef DEBUG
03466     nbParseStringName++;
03467 #endif
03468 
03469     c = CUR_SCHAR(cur, l);
03470     if (!xmlIsNameStartChar(ctxt, c)) {
03471     return(NULL);
03472     }
03473 
03474     COPY_BUF(l,buf,len,c);
03475     cur += l;
03476     c = CUR_SCHAR(cur, l);
03477     while (xmlIsNameChar(ctxt, c)) {
03478     COPY_BUF(l,buf,len,c);
03479     cur += l;
03480     c = CUR_SCHAR(cur, l);
03481     if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
03482         /*
03483          * Okay someone managed to make a huge name, so he's ready to pay
03484          * for the processing speed.
03485          */
03486         xmlChar *buffer;
03487         int max = len * 2;
03488 
03489         buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
03490         if (buffer == NULL) {
03491             xmlErrMemory(ctxt, NULL);
03492         return(NULL);
03493         }
03494         memcpy(buffer, buf, len);
03495         while (xmlIsNameChar(ctxt, c)) {
03496         if (len + 10 > max) {
03497             xmlChar *tmp;
03498             max *= 2;
03499             tmp = (xmlChar *) xmlRealloc(buffer,
03500                                         max * sizeof(xmlChar));
03501             if (tmp == NULL) {
03502             xmlErrMemory(ctxt, NULL);
03503             xmlFree(buffer);
03504             return(NULL);
03505             }
03506             buffer = tmp;
03507         }
03508         COPY_BUF(l,buffer,len,c);
03509         cur += l;
03510         c = CUR_SCHAR(cur, l);
03511         }
03512         buffer[len] = 0;
03513         *str = cur;
03514         return(buffer);
03515     }
03516     }
03517     *str = cur;
03518     return(xmlStrndup(buf, len));
03519 }
03520 
03534 xmlChar *
03535 xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
03536     xmlChar buf[XML_MAX_NAMELEN + 5];
03537     int len = 0, l;
03538     int c;
03539     int count = 0;
03540 
03541 #ifdef DEBUG
03542     nbParseNmToken++;
03543 #endif
03544 
03545     GROW;
03546     c = CUR_CHAR(l);
03547 
03548     while (xmlIsNameChar(ctxt, c)) {
03549     if (count++ > 100) {
03550         count = 0;
03551         GROW;
03552     }
03553     COPY_BUF(l,buf,len,c);
03554     NEXTL(l);
03555     c = CUR_CHAR(l);
03556     if (len >= XML_MAX_NAMELEN) {
03557         /*
03558          * Okay someone managed to make a huge token, so he's ready to pay
03559          * for the processing speed.
03560          */
03561         xmlChar *buffer;
03562         int max = len * 2;
03563 
03564         buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
03565         if (buffer == NULL) {
03566             xmlErrMemory(ctxt, NULL);
03567         return(NULL);
03568         }
03569         memcpy(buffer, buf, len);
03570         while (xmlIsNameChar(ctxt, c)) {
03571         if (count++ > 100) {
03572             count = 0;
03573             GROW;
03574         }
03575         if (len + 10 > max) {
03576             xmlChar *tmp;
03577 
03578             max *= 2;
03579             tmp = (xmlChar *) xmlRealloc(buffer,
03580                                         max * sizeof(xmlChar));
03581             if (tmp == NULL) {
03582             xmlErrMemory(ctxt, NULL);
03583             xmlFree(buffer);
03584             return(NULL);
03585             }
03586             buffer = tmp;
03587         }
03588         COPY_BUF(l,buffer,len,c);
03589         NEXTL(l);
03590         c = CUR_CHAR(l);
03591         }
03592         buffer[len] = 0;
03593         return(buffer);
03594     }
03595     }
03596     if (len == 0)
03597         return(NULL);
03598     return(xmlStrndup(buf, len));
03599 }
03600 
03614 xmlChar *
03615 xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
03616     xmlChar *buf = NULL;
03617     int len = 0;
03618     int size = XML_PARSER_BUFFER_SIZE;
03619     int c, l;
03620     xmlChar stop;
03621     xmlChar *ret = NULL;
03622     const xmlChar *cur = NULL;
03623     xmlParserInputPtr input;
03624 
03625     if (RAW == '"') stop = '"';
03626     else if (RAW == '\'') stop = '\'';
03627     else {
03628     xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL);
03629     return(NULL);
03630     }
03631     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
03632     if (buf == NULL) {
03633     xmlErrMemory(ctxt, NULL);
03634     return(NULL);
03635     }
03636 
03637     /*
03638      * The content of the entity definition is copied in a buffer.
03639      */
03640 
03641     ctxt->instate = XML_PARSER_ENTITY_VALUE;
03642     input = ctxt->input;
03643     GROW;
03644     NEXT;
03645     c = CUR_CHAR(l);
03646     /*
03647      * NOTE: 4.4.5 Included in Literal
03648      * When a parameter entity reference appears in a literal entity
03649      * value, ... a single or double quote character in the replacement
03650      * text is always treated as a normal data character and will not
03651      * terminate the literal. 
03652      * In practice it means we stop the loop only when back at parsing
03653      * the initial entity and the quote is found
03654      */
03655     while ((IS_CHAR(c)) && ((c != stop) || /* checked */
03656        (ctxt->input != input))) {
03657     if (len + 5 >= size) {
03658         xmlChar *tmp;
03659 
03660         size *= 2;
03661         tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
03662         if (tmp == NULL) {
03663         xmlErrMemory(ctxt, NULL);
03664         xmlFree(buf);
03665         return(NULL);
03666         }
03667         buf = tmp;
03668     }
03669     COPY_BUF(l,buf,len,c);
03670     NEXTL(l);
03671     /*
03672      * Pop-up of finished entities.
03673      */
03674     while ((RAW == 0) && (ctxt->inputNr > 1)) /* non input consuming */
03675         xmlPopInput(ctxt);
03676 
03677     GROW;
03678     c = CUR_CHAR(l);
03679     if (c == 0) {
03680         GROW;
03681         c = CUR_CHAR(l);
03682     }
03683     }
03684     buf[len] = 0;
03685 
03686     /*
03687      * Raise problem w.r.t. '&' and '%' being used in non-entities
03688      * reference constructs. Note Charref will be handled in
03689      * xmlStringDecodeEntities()
03690      */
03691     cur = buf;
03692     while (*cur != 0) { /* non input consuming */
03693     if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
03694         xmlChar *name;
03695         xmlChar tmp = *cur;
03696 
03697         cur++;
03698         name = xmlParseStringName(ctxt, &cur);
03699             if ((name == NULL) || (*cur != ';')) {
03700         xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
03701         "EntityValue: '%c' forbidden except for entities references\n",
03702                               tmp);
03703         }
03704         if ((tmp == '%') && (ctxt->inSubset == 1) &&
03705         (ctxt->inputNr == 1)) {
03706         xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
03707         }
03708         if (name != NULL)
03709         xmlFree(name);
03710         if (*cur == 0)
03711             break;
03712     }
03713     cur++;
03714     }
03715 
03716     /*
03717      * Then PEReference entities are substituted.
03718      */
03719     if (c != stop) {
03720     xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
03721     xmlFree(buf);
03722     } else {
03723     NEXT;
03724     /*
03725      * NOTE: 4.4.7 Bypassed
03726      * When a general entity reference appears in the EntityValue in
03727      * an entity declaration, it is bypassed and left as is.
03728      * so XML_SUBSTITUTE_REF is not set here.
03729      */
03730     ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
03731                       0, 0, 0);
03732     if (orig != NULL) 
03733         *orig = buf;
03734     else
03735         xmlFree(buf);
03736     }
03737     
03738     return(ret);
03739 }
03740 
03753 static xmlChar *
03754 xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
03755     xmlChar limit = 0;
03756     xmlChar *buf = NULL;
03757     xmlChar *rep = NULL;
03758     int len = 0;
03759     int buf_size = 0;
03760     int c, l, in_space = 0;
03761     xmlChar *current = NULL;
03762     xmlEntityPtr ent;
03763 
03764     if (NXT(0) == '"') {
03765     ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
03766     limit = '"';
03767         NEXT;
03768     } else if (NXT(0) == '\'') {
03769     limit = '\'';
03770     ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
03771         NEXT;
03772     } else {
03773     xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
03774     return(NULL);
03775     }
03776 
03777     /*
03778      * allocate a translation buffer.
03779      */
03780     buf_size = XML_PARSER_BUFFER_SIZE;
03781     buf = (xmlChar *) xmlMallocAtomic(buf_size * sizeof(xmlChar));
03782     if (buf == NULL) goto mem_error;
03783 
03784     /*
03785      * OK loop until we reach one of the ending char or a size limit.
03786      */
03787     c = CUR_CHAR(l);
03788     while ((NXT(0) != limit) && /* checked */
03789            (IS_CHAR(c)) && (c != '<')) {
03790     if (c == 0) break;
03791     if (c == '&') {
03792         in_space = 0;
03793         if (NXT(1) == '#') {
03794         int val = xmlParseCharRef(ctxt);
03795 
03796         if (val == '&') {
03797             if (ctxt->replaceEntities) {
03798             if (len > buf_size - 10) {
03799                 growBuffer(buf, 10);
03800             }
03801             buf[len++] = '&';
03802             } else {
03803             /*
03804              * The reparsing will be done in xmlStringGetNodeList()
03805              * called by the attribute() function in SAX.c
03806              */
03807             if (len > buf_size - 10) {
03808                 growBuffer(buf, 10);
03809             }
03810             buf[len++] = '&';
03811             buf[len++] = '#';
03812             buf[len++] = '3';
03813             buf[len++] = '8';
03814             buf[len++] = ';';
03815             }
03816         } else if (val != 0) {
03817             if (len > buf_size - 10) {
03818             growBuffer(buf, 10);
03819             }
03820             len += xmlCopyChar(0, &buf[len], val);
03821         }
03822         } else {
03823         ent = xmlParseEntityRef(ctxt);
03824         ctxt->nbentities++;
03825         if (ent != NULL)
03826             ctxt->nbentities += ent->owner;
03827         if ((ent != NULL) &&
03828             (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
03829             if (len > buf_size - 10) {
03830             growBuffer(buf, 10);
03831             }
03832             if ((ctxt->replaceEntities == 0) &&
03833                 (ent->content[0] == '&')) {
03834             buf[len++] = '&';
03835             buf[len++] = '#';
03836             buf[len++] = '3';
03837             buf[len++] = '8';
03838             buf[len++] = ';';
03839             } else {
03840             buf[len++] = ent->content[0];
03841             }
03842         } else if ((ent != NULL) && 
03843                    (ctxt->replaceEntities != 0)) {
03844             if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
03845             rep = xmlStringDecodeEntities(ctxt, ent->content,
03846                               XML_SUBSTITUTE_REF,
03847                               0, 0, 0);
03848             if (rep != NULL) {
03849                 current = rep;
03850                 while (*current != 0) { /* non input consuming */
03851                                 if ((*current == 0xD) || (*current == 0xA) ||
03852                                     (*current == 0x9)) {
03853                                     buf[len++] = 0x20;
03854                                     current++;
03855                                 } else
03856                                     buf[len++] = *current++;
03857                 if (len > buf_size - 10) {
03858                     growBuffer(buf, 10);
03859                 }
03860                 }
03861                 xmlFree(rep);
03862                 rep = NULL;
03863             }
03864             } else {
03865             if (len > buf_size - 10) {
03866                 growBuffer(buf, 10);
03867             }
03868             if (ent->content != NULL)
03869                 buf[len++] = ent->content[0];
03870             }
03871         } else if (ent != NULL) {
03872             int i = xmlStrlen(ent->name);
03873             const xmlChar *cur = ent->name;
03874 
03875             /*
03876              * This may look absurd but is needed to detect
03877              * entities problems
03878              */
03879             if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
03880             (ent->content != NULL)) {
03881             rep = xmlStringDecodeEntities(ctxt, ent->content,
03882                           XML_SUBSTITUTE_REF, 0, 0, 0);
03883             if (rep != NULL) {
03884                 xmlFree(rep);
03885                 rep = NULL;
03886             }
03887             }
03888 
03889             /*
03890              * Just output the reference
03891              */
03892             buf[len++] = '&';
03893             while (len > buf_size - i - 10) {
03894             growBuffer(buf, i + 10);
03895             }
03896             for (;i > 0;i--)
03897             buf[len++] = *cur++;
03898             buf[len++] = ';';
03899         }
03900         }
03901     } else {
03902         if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
03903             if ((len != 0) || (!normalize)) {
03904             if ((!normalize) || (!in_space)) {
03905             COPY_BUF(l,buf,len,0x20);
03906             while (len > buf_size - 10) {
03907                 growBuffer(buf, 10);
03908             }
03909             }
03910             in_space = 1;
03911         }
03912         } else {
03913             in_space = 0;
03914         COPY_BUF(l,buf,len,c);
03915         if (len > buf_size - 10) {
03916             growBuffer(buf, 10);
03917         }
03918         }
03919         NEXTL(l);
03920     }
03921     GROW;
03922     c = CUR_CHAR(l);
03923     }
03924     if ((in_space) && (normalize)) {
03925         while (buf[len - 1] == 0x20) len--;
03926     }
03927     buf[len] = 0;
03928     if (RAW == '<') {
03929     xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
03930     } else if (RAW != limit) {
03931     if ((c != 0) && (!IS_CHAR(c))) {
03932         xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
03933                "invalid character in attribute value\n");
03934     } else {
03935         xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
03936                "AttValue: ' expected\n");
03937         }
03938     } else
03939     NEXT;
03940     if (attlen != NULL) *attlen = len;
03941     return(buf);
03942 
03943 mem_error:
03944     xmlErrMemory(ctxt, NULL);
03945     if (buf != NULL)
03946         xmlFree(buf);
03947     if (rep != NULL)
03948         xmlFree(rep);
03949     return(NULL);
03950 }
03951 
03986 xmlChar *
03987 xmlParseAttValue(xmlParserCtxtPtr ctxt) {
03988     if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
03989     return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0));
03990 }
03991 
04003 xmlChar *
04004 xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
04005     xmlChar *buf = NULL;
04006     int len = 0;
04007     int size = XML_PARSER_BUFFER_SIZE;
04008     int cur, l;
04009     xmlChar stop;
04010     int state = ctxt->instate;
04011     int count = 0;
04012 
04013     SHRINK;
04014     if (RAW == '"') {
04015         NEXT;
04016     stop = '"';
04017     } else if (RAW == '\'') {
04018         NEXT;
04019     stop = '\'';
04020     } else {
04021     xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
04022     return(NULL);
04023     }
04024     
04025     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
04026     if (buf == NULL) {
04027         xmlErrMemory(ctxt, NULL);
04028     return(NULL);
04029     }
04030     ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
04031     cur = CUR_CHAR(l);
04032     while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
04033     if (len + 5 >= size) {
04034         xmlChar *tmp;
04035 
04036         size *= 2;
04037         tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
04038         if (tmp == NULL) {
04039             xmlFree(buf);
04040         xmlErrMemory(ctxt, NULL);
04041         ctxt->instate = (xmlParserInputState) state;
04042         return(NULL);
04043         }
04044         buf = tmp;
04045     }
04046     count++;
04047     if (count > 50) {
04048         GROW;
04049         count = 0;
04050     }
04051     COPY_BUF(l,buf,len,cur);
04052     NEXTL(l);
04053     cur = CUR_CHAR(l);
04054     if (cur == 0) {
04055         GROW;
04056         SHRINK;
04057         cur = CUR_CHAR(l);
04058     }
04059     }
04060     buf[len] = 0;
04061     ctxt->instate = (xmlParserInputState) state;
04062     if (!IS_CHAR(cur)) {
04063     xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
04064     } else {
04065     NEXT;
04066     }
04067     return(buf);
04068 }
04069 
04081 xmlChar *
04082 xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
04083     xmlChar *buf = NULL;
04084     int len = 0;
04085     int size = XML_PARSER_BUFFER_SIZE;
04086     xmlChar cur;
04087     xmlChar stop;
04088     int count = 0;
04089     xmlParserInputState oldstate = ctxt->instate;
04090 
04091     SHRINK;
04092     if (RAW == '"') {
04093         NEXT;
04094     stop = '"';
04095     } else if (RAW == '\'') {
04096         NEXT;
04097     stop = '\'';
04098     } else {
04099     xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
04100     return(NULL);
04101     }
04102     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
04103     if (buf == NULL) {
04104     xmlErrMemory(ctxt, NULL);
04105     return(NULL);
04106     }
04107     ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
04108     cur = CUR;
04109     while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */
04110     if (len + 1 >= size) {
04111         xmlChar *tmp;
04112 
04113         size *= 2;
04114         tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
04115         if (tmp == NULL) {
04116         xmlErrMemory(ctxt, NULL);
04117         xmlFree(buf);
04118         return(NULL);
04119         }
04120         buf = tmp;
04121     }
04122     buf[len++] = cur;
04123     count++;
04124     if (count > 50) {
04125         GROW;
04126         count = 0;
04127     }
04128     NEXT;
04129     cur = CUR;
04130     if (cur == 0) {
04131         GROW;
04132         SHRINK;
04133         cur = CUR;
04134     }
04135     }
04136     buf[len] = 0;
04137     if (cur != stop) {
04138     xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
04139     } else {
04140     NEXT;
04141     }
04142     ctxt->instate = oldstate;
04143     return(buf);
04144 }
04145 
04146 static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata);
04147 
04148 /*
04149  * used for the test in the inner loop of the char data testing
04150  */
04151 static const unsigned char test_char_data[256] = {
04152     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04153     0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */
04154     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04155     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04156     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */
04157     0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
04158     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
04159     0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */
04160     0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
04161     0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
04162     0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
04163     0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */
04164     0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
04165     0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
04166     0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
04167     0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
04168     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */
04169     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04170     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04171     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04172     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04173     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04174     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04175     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04176     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04177     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04178     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04179     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04180     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04181     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04182     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
04183     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
04184 };
04185 
04202 void
04203 xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
04204     const xmlChar *in;
04205     int nbchar = 0;
04206     int line = ctxt->input->line;
04207     int col = ctxt->input->col;
04208     int ccol;
04209 
04210     SHRINK;
04211     GROW;
04212     /*
04213      * Accelerated common case where input don't need to be
04214      * modified before passing it to the handler.
04215      */
04216     if (!cdata) {
04217     in = ctxt->input->cur;
04218     do {
04219 get_more_space:
04220         while (*in == 0x20) { in++; ctxt->input->col++; }
04221         if (*in == 0xA) {
04222         do {
04223             ctxt->input->line++; ctxt->input->col = 1;
04224             in++;
04225         } while (*in == 0xA);
04226         goto get_more_space;
04227         }
04228         if (*in == '<') {
04229         nbchar = in - ctxt->input->cur;
04230         if (nbchar > 0) {
04231             const xmlChar *tmp = ctxt->input->cur;
04232             ctxt->input->cur = in;
04233 
04234             if ((ctxt->sax != NULL) &&
04235                 (ctxt->sax->ignorableWhitespace !=
04236                  ctxt->sax->characters)) {
04237             if (areBlanks(ctxt, tmp, nbchar, 1)) {
04238                 if (ctxt->sax->ignorableWhitespace != NULL)
04239                 ctxt->sax->ignorableWhitespace(ctxt->userData,
04240                                tmp, nbchar);
04241             } else {
04242                 if (ctxt->sax->characters != NULL)
04243                 ctxt->sax->characters(ctxt->userData,
04244                               tmp, nbchar);
04245                 if (*ctxt->space == -1)
04246                     *ctxt->space = -2;
04247             }
04248             } else if ((ctxt->sax != NULL) &&
04249                        (ctxt->sax->characters != NULL)) {
04250             ctxt->sax->characters(ctxt->userData,
04251                           tmp, nbchar);
04252             }
04253         }
04254         return;
04255         }
04256 
04257 get_more:
04258             ccol = ctxt->input->col;
04259         while (test_char_data[*in]) {
04260         in++;
04261         ccol++;
04262         }
04263         ctxt->input->col = ccol;
04264         if (*in == 0xA) {
04265         do {
04266             ctxt->input->line++; ctxt->input->col = 1;
04267             in++;
04268         } while (*in == 0xA);
04269         goto get_more;
04270         }
04271         if (*in == ']') {
04272         if ((in[1] == ']') && (in[2] == '>')) {
04273             xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
04274             ctxt->input->cur = in;
04275             return;
04276         }
04277         in++;
04278         ctxt->input->col++;
04279         goto get_more;
04280         }
04281         nbchar = in - ctxt->input->cur;
04282         if (nbchar > 0) {
04283         if ((ctxt->sax != NULL) &&
04284             (ctxt->sax->ignorableWhitespace !=
04285              ctxt->sax->characters) &&
04286             (IS_BLANK_CH(*ctxt->input->cur))) {
04287             const xmlChar *tmp = ctxt->input->cur;
04288             ctxt->input->cur = in;
04289 
04290             if (areBlanks(ctxt, tmp, nbchar, 0)) {
04291                 if (ctxt->sax->ignorableWhitespace != NULL)
04292                 ctxt->sax->ignorableWhitespace(ctxt->userData,
04293                                tmp, nbchar);
04294             } else {
04295                 if (ctxt->sax->characters != NULL)
04296                 ctxt->sax->characters(ctxt->userData,
04297                           tmp, nbchar);
04298             if (*ctxt->space == -1)
04299                 *ctxt->space = -2;
04300             }
04301                     line = ctxt->input->line;
04302                     col = ctxt->input->col;
04303         } else if (ctxt->sax != NULL) {
04304             if (ctxt->sax->characters != NULL)
04305             ctxt->sax->characters(ctxt->userData,
04306                           ctxt->input->cur, nbchar);
04307                     line = ctxt->input->line;
04308                     col = ctxt->input->col;
04309         }
04310                 /* something really bad happened in the SAX callback */
04311                 if (ctxt->instate != XML_PARSER_CONTENT)
04312                     return;
04313         }
04314         ctxt->input->cur = in;
04315         if (*in == 0xD) {
04316         in++;
04317         if (*in == 0xA) {
04318             ctxt->input->cur = in;
04319             in++;
04320             ctxt->input->line++; ctxt->input->col = 1;
04321             continue; /* while */
04322         }
04323         in--;
04324         }
04325         if (*in == '<') {
04326         return;
04327         }
04328         if (*in == '&') {
04329         return;
04330         }
04331         SHRINK;
04332         GROW;
04333         in = ctxt->input->cur;
04334     } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
04335     nbchar = 0;
04336     }
04337     ctxt->input->line = line;
04338     ctxt->input->col = col;
04339     xmlParseCharDataComplex(ctxt, cdata);
04340 }
04341 
04351 static void
04352 xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
04353     xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
04354     int nbchar = 0;
04355     int cur, l;
04356     int count = 0;
04357 
04358     SHRINK;
04359     GROW;
04360     cur = CUR_CHAR(l);
04361     while ((cur != '<') && /* checked */
04362            (cur != '&') && 
04363        (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ {
04364     if ((cur == ']') && (NXT(1) == ']') &&
04365         (NXT(2) == '>')) {
04366         if (cdata) break;
04367         else {
04368         xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
04369         }
04370     }
04371     COPY_BUF(l,buf,nbchar,cur);
04372     if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
04373         buf[nbchar] = 0;
04374 
04375         /*
04376          * OK the segment is to be consumed as chars.
04377          */
04378         if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
04379         if (areBlanks(ctxt, buf, nbchar, 0)) {
04380             if (ctxt->sax->ignorableWhitespace != NULL)
04381             ctxt->sax->ignorableWhitespace(ctxt->userData,
04382                                            buf, nbchar);
04383         } else {
04384             if (ctxt->sax->characters != NULL)
04385             ctxt->sax->characters(ctxt->userData, buf, nbchar);
04386             if ((ctxt->sax->characters !=
04387                  ctxt->sax->ignorableWhitespace) &&
04388             (*ctxt->space == -1))
04389             *ctxt->space = -2;
04390         }
04391         }
04392         nbchar = 0;
04393             /* something really bad happened in the SAX callback */
04394             if (ctxt->instate != XML_PARSER_CONTENT)
04395                 return;
04396     }
04397     count++;
04398     if (count > 50) {
04399         GROW;
04400         count = 0;
04401     }
04402     NEXTL(l);
04403     cur = CUR_CHAR(l);
04404     }
04405     if (nbchar != 0) {
04406         buf[nbchar] = 0;
04407     /*
04408      * OK the segment is to be consumed as chars.
04409      */
04410     if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
04411         if (areBlanks(ctxt, buf, nbchar, 0)) {
04412         if (ctxt->sax->ignorableWhitespace != NULL)
04413             ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
04414         } else {
04415         if (ctxt->sax->characters != NULL)
04416             ctxt->sax->characters(ctxt->userData, buf, nbchar);
04417         if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) &&
04418             (*ctxt->space == -1))
04419             *ctxt->space = -2;
04420         }
04421     }
04422     }
04423     if ((cur != 0) && (!IS_CHAR(cur))) {
04424     /* Generate the error and skip the offending character */
04425         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
04426                           "PCDATA invalid Char value %d\n",
04427                       cur);
04428     NEXTL(l);
04429     }
04430 }
04431 
04454 xmlChar *
04455 xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
04456     xmlChar *URI = NULL;
04457 
04458     SHRINK;
04459 
04460     *publicID = NULL;
04461     if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
04462         SKIP(6);
04463     if (!IS_BLANK_CH(CUR)) {
04464         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
04465                        "Space required after 'SYSTEM'\n");
04466     }
04467         SKIP_BLANKS;
04468     URI = xmlParseSystemLiteral(ctxt);
04469     if (URI == NULL) {
04470         xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
04471         }
04472     } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
04473         SKIP(6);
04474     if (!IS_BLANK_CH(CUR)) {
04475         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
04476             "Space required after 'PUBLIC'\n");
04477     }
04478         SKIP_BLANKS;
04479     *publicID = xmlParsePubidLiteral(ctxt);
04480     if (*publicID == NULL) {
04481         xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
04482     }
04483     if (strict) {
04484         /*
04485          * We don't handle [83] so "S SystemLiteral" is required.
04486          */
04487         if (!IS_BLANK_CH(CUR)) {
04488         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
04489             "Space required after the Public Identifier\n");
04490         }
04491     } else {
04492         /*
04493          * We handle [83] so we return immediately, if 
04494          * "S SystemLiteral" is not detected. From a purely parsing
04495          * point of view that's a nice mess.
04496          */
04497         const xmlChar *ptr;
04498         GROW;
04499 
04500         ptr = CUR_PTR;
04501         if (!IS_BLANK_CH(*ptr)) return(NULL);
04502         
04503         while (IS_BLANK_CH(*ptr)) ptr++; /* TODO: dangerous, fix ! */
04504         if ((*ptr != '\'') && (*ptr != '"')) return(NULL);
04505     }
04506         SKIP_BLANKS;
04507     URI = xmlParseSystemLiteral(ctxt);
04508     if (URI == NULL) {
04509         xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
04510         }
04511     }
04512     return(URI);
04513 }
04514 
04529 static void
04530 xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf, int len, int size) {
04531     int q, ql;
04532     int r, rl;
04533     int cur, l;
04534     int count = 0;
04535     int inputid;
04536 
04537     inputid = ctxt->input->id;
04538 
04539     if (buf == NULL) {
04540         len = 0;
04541     size = XML_PARSER_BUFFER_SIZE;
04542     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
04543     if (buf == NULL) {
04544         xmlErrMemory(ctxt, NULL);
04545         return;
04546     }
04547     }
04548     GROW;   /* Assure there's enough input data */
04549     q = CUR_CHAR(ql);
04550     if (q == 0)
04551         goto not_terminated;
04552     if (!IS_CHAR(q)) {
04553         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
04554                           "xmlParseComment: invalid xmlChar value %d\n",
04555                       q);
04556     xmlFree (buf);
04557     return;
04558     }
04559     NEXTL(ql);
04560     r = CUR_CHAR(rl);
04561     if (r == 0)
04562         goto not_terminated;
04563     if (!IS_CHAR(r)) {
04564         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
04565                           "xmlParseComment: invalid xmlChar value %d\n",
04566                       q);
04567     xmlFree (buf);
04568     return;
04569     }
04570     NEXTL(rl);
04571     cur = CUR_CHAR(l);
04572     if (cur == 0)
04573         goto not_terminated;
04574     while (IS_CHAR(cur) && /* checked */
04575            ((cur != '>') ||
04576         (r != '-') || (q != '-'))) {
04577     if ((r == '-') && (q == '-')) {
04578         xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
04579     }
04580     if (len + 5 >= size) {
04581         xmlChar *new_buf;
04582         size *= 2;
04583         new_buf = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
04584         if (new_buf == NULL) {
04585         xmlFree (buf);
04586         xmlErrMemory(ctxt, NULL);
04587         return;
04588         }
04589         buf = new_buf;
04590     }
04591     COPY_BUF(ql,buf,len,q);
04592     q = r;
04593     ql = rl;
04594     r = cur;
04595     rl = l;
04596 
04597     count++;
04598     if (count > 50) {
04599         GROW;
04600         count = 0;
04601     }
04602     NEXTL(l);
04603     cur = CUR_CHAR(l);
04604     if (cur == 0) {
04605         SHRINK;
04606         GROW;
04607         cur = CUR_CHAR(l);
04608     }
04609     }
04610     buf[len] = 0;
04611     if (cur == 0) {
04612     xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
04613                          "Comment not terminated \n<!--%.50s\n", buf);
04614     } else if (!IS_CHAR(cur)) {
04615         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
04616                           "xmlParseComment: invalid xmlChar value %d\n",
04617                       cur);
04618     } else {
04619     if (inputid != ctxt->input->id) {
04620         xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
04621         "Comment doesn't start and stop in the same entity\n");
04622     }
04623         NEXT;
04624     if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
04625         (!ctxt->disableSAX))
04626         ctxt->sax->comment(ctxt->userData, buf);
04627     }
04628     xmlFree(buf);
04629     return;
04630 not_terminated:
04631     xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
04632              "Comment not terminated\n", NULL);
04633     xmlFree(buf);
04634     return;
04635 }
04636 
04647 void
04648 xmlParseComment(xmlParserCtxtPtr ctxt) {
04649     xmlChar *buf = NULL;
04650     int size = XML_PARSER_BUFFER_SIZE;
04651     int len = 0;
04652     xmlParserInputState state;
04653     const xmlChar *in;
04654     int nbchar = 0, ccol;
04655     int inputid;
04656 
04657     /*
04658      * Check that there is a comment right here.
04659      */
04660     if ((RAW != '<') || (NXT(1) != '!') ||
04661         (NXT(2) != '-') || (NXT(3) != '-')) return;
04662     state = ctxt->instate;
04663     ctxt->instate = XML_PARSER_COMMENT;
04664     inputid = ctxt->input->id;
04665     SKIP(4);
04666     SHRINK;
04667     GROW;
04668 
04669     /*
04670      * Accelerated common case where input don't need to be
04671      * modified before passing it to the handler.
04672      */
04673     in = ctxt->input->cur;
04674     do {
04675     if (*in == 0xA) {
04676         do {
04677         ctxt->input->line++; ctxt->input->col = 1;
04678         in++;
04679         } while (*in == 0xA);
04680     }
04681 get_more:
04682         ccol = ctxt->input->col;
04683     while (((*in > '-') && (*in <= 0x7F)) ||
04684            ((*in >= 0x20) && (*in < '-')) ||
04685            (*in == 0x09)) {
04686             in++;
04687             ccol++;
04688     }
04689     ctxt->input->col = ccol;
04690     if (*in == 0xA) {
04691         do {
04692         ctxt->input->line++; ctxt->input->col = 1;
04693         in++;
04694         } while (*in == 0xA);
04695         goto get_more;
04696     }
04697     nbchar = in - ctxt->input->cur;
04698     /*
04699      * save current set of data
04700      */
04701     if (nbchar > 0) {
04702         if ((ctxt->sax != NULL) &&
04703         (ctxt->sax->comment != NULL)) {
04704         if (buf == NULL) {
04705             if ((*in == '-') && (in[1] == '-'))
04706                 size = nbchar + 1;
04707             else
04708                 size = XML_PARSER_BUFFER_SIZE + nbchar;
04709             buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
04710             if (buf == NULL) {
04711                 xmlErrMemory(ctxt, NULL);
04712             ctxt->instate = state;
04713             return;
04714             }
04715             len = 0;
04716         } else if (len + nbchar + 1 >= size) {
04717             xmlChar *new_buf;
04718             size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
04719             new_buf = (xmlChar *) xmlRealloc(buf,
04720                                              size * sizeof(xmlChar));
04721             if (new_buf == NULL) {
04722                 xmlFree (buf);
04723             xmlErrMemory(ctxt, NULL);
04724             ctxt->instate = state;
04725             return;
04726             }
04727             buf = new_buf;
04728         }
04729         memcpy(&buf[len], ctxt->input->cur, nbchar);
04730         len += nbchar;
04731         buf[len] = 0;
04732         }
04733     }
04734     ctxt->input->cur = in;
04735     if (*in == 0xA) {
04736         in++;
04737         ctxt->input->line++; ctxt->input->col = 1;
04738     }
04739     if (*in == 0xD) {
04740         in++;
04741         if (*in == 0xA) {
04742         ctxt->input->cur = in;
04743         in++;
04744         ctxt->input->line++; ctxt->input->col = 1;
04745         continue; /* while */
04746         }
04747         in--;
04748     }
04749     SHRINK;
04750     GROW;
04751     in = ctxt->input->cur;
04752     if (*in == '-') {
04753         if (in[1] == '-') {
04754             if (in[2] == '>') {
04755             if (ctxt->input->id != inputid) {
04756             xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
04757             "comment doesn't start and stop in the same entity\n");
04758             }
04759             SKIP(3);
04760             if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
04761                 (!ctxt->disableSAX)) {
04762             if (buf != NULL)
04763                 ctxt->sax->comment(ctxt->userData, buf);
04764             else
04765                 ctxt->sax->comment(ctxt->userData, BAD_CAST "");
04766             }
04767             if (buf != NULL)
04768                 xmlFree(buf);
04769             ctxt->instate = state;
04770             return;
04771         }
04772         if (buf != NULL)
04773             xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
04774                               "Comment not terminated \n<!--%.50s\n",
04775                       buf);
04776         else
04777             xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
04778                               "Comment not terminated \n", NULL);
04779         in++;
04780         ctxt->input->col++;
04781         }
04782         in++;
04783         ctxt->input->col++;
04784         goto get_more;
04785     }
04786     } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
04787     xmlParseCommentComplex(ctxt, buf, len, size);
04788     ctxt->instate = state;
04789     return;
04790 }
04791 
04792 
04804 const xmlChar *
04805 xmlParsePITarget(xmlParserCtxtPtr ctxt) {
04806     const xmlChar *name;
04807 
04808     name = xmlParseName(ctxt);
04809     if ((name != NULL) &&
04810         ((name[0] == 'x') || (name[0] == 'X')) &&
04811         ((name[1] == 'm') || (name[1] == 'M')) &&
04812         ((name[2] == 'l') || (name[2] == 'L'))) {
04813     int i;
04814     if ((name[0] == 'x') && (name[1] == 'm') &&
04815         (name[2] == 'l') && (name[3] == 0)) {
04816         xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
04817          "XML declaration allowed only at the start of the document\n");
04818         return(name);
04819     } else if (name[3] == 0) {
04820         xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL);
04821         return(name);
04822     }
04823     for (i = 0;;i++) {
04824         if (xmlW3CPIs[i] == NULL) break;
04825         if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
04826             return(name);
04827     }
04828     xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
04829               "xmlParsePITarget: invalid name prefix 'xml'\n",
04830               NULL, NULL);
04831     }
04832     if ((name != NULL) && (xmlStrchr(name, ':') != NULL)) {
04833     xmlNsErr(ctxt, XML_NS_ERR_COLON, 
04834          "colon are forbidden from PI names '%s'\n", name, NULL, NULL);
04835     }
04836     return(name);
04837 }
04838 
04839 #ifdef LIBXML_CATALOG_ENABLED
04840 
04855 static void
04856 xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
04857     xmlChar *URL = NULL;
04858     const xmlChar *tmp, *base;
04859     xmlChar marker;
04860 
04861     tmp = catalog;
04862     while (IS_BLANK_CH(*tmp)) tmp++;
04863     if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
04864     goto error;
04865     tmp += 7;
04866     while (IS_BLANK_CH(*tmp)) tmp++;
04867     if (*tmp != '=') {
04868     return;
04869     }
04870     tmp++;
04871     while (IS_BLANK_CH(*tmp)) tmp++;
04872     marker = *tmp;
04873     if ((marker != '\'') && (marker != '"'))
04874     goto error;
04875     tmp++;
04876     base = tmp;
04877     while ((*tmp != 0) && (*tmp != marker)) tmp++;
04878     if (*tmp == 0)
04879     goto error;
04880     URL = xmlStrndup(base, tmp - base);
04881     tmp++;
04882     while (IS_BLANK_CH(*tmp)) tmp++;
04883     if (*tmp != 0)
04884     goto error;
04885 
04886     if (URL != NULL) {
04887     ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
04888     xmlFree(URL);
04889     }
04890     return;
04891 
04892 error:
04893     xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI,
04894               "Catalog PI syntax error: %s\n",
04895           catalog, NULL);
04896     if (URL != NULL)
04897     xmlFree(URL);
04898 }
04899 #endif
04900 
04912 void
04913 xmlParsePI(xmlParserCtxtPtr ctxt) {
04914     xmlChar *buf = NULL;
04915     int len = 0;
04916     int size = XML_PARSER_BUFFER_SIZE;
04917     int cur, l;
04918     const xmlChar *target;
04919     xmlParserInputState state;
04920     int count = 0;
04921 
04922     if ((RAW == '<') && (NXT(1) == '?')) {
04923     xmlParserInputPtr input = ctxt->input;
04924     state = ctxt->instate;
04925         ctxt->instate = XML_PARSER_PI;
04926     /*
04927      * this is a Processing Instruction.
04928      */
04929     SKIP(2);
04930     SHRINK;
04931 
04932     /*
04933      * Parse the target name and check for special support like
04934      * namespace.
04935      */
04936         target = xmlParsePITarget(ctxt);
04937     if (target != NULL) {
04938         if ((RAW == '?') && (NXT(1) == '>')) {
04939         if (input != ctxt->input) {
04940             xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
04941         "PI declaration doesn't start and stop in the same entity\n");
04942         }
04943         SKIP(2);
04944 
04945         /*
04946          * SAX: PI detected.
04947          */
04948         if ((ctxt->sax) && (!ctxt->disableSAX) &&
04949             (ctxt->sax->processingInstruction != NULL))
04950             ctxt->sax->processingInstruction(ctxt->userData,
04951                                              target, NULL);
04952         ctxt->instate = state;
04953         return;
04954         }
04955         buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
04956         if (buf == NULL) {
04957         xmlErrMemory(ctxt, NULL);
04958         ctxt->instate = state;
04959         return;
04960         }
04961         cur = CUR;
04962         if (!IS_BLANK(cur)) {
04963         xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
04964               "ParsePI: PI %s space expected\n", target);
04965         }
04966             SKIP_BLANKS;
04967         cur = CUR_CHAR(l);
04968         while (IS_CHAR(cur) && /* checked */
04969            ((cur != '?') || (NXT(1) != '>'))) {
04970         if (len + 5 >= size) {
04971             xmlChar *tmp;
04972 
04973             size *= 2;
04974             tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
04975             if (tmp == NULL) {
04976             xmlErrMemory(ctxt, NULL);
04977             xmlFree(buf);
04978             ctxt->instate = state;
04979             return;
04980             }
04981             buf = tmp;
04982         }
04983         count++;
04984         if (count > 50) {
04985             GROW;
04986             count = 0;
04987         }
04988         COPY_BUF(l,buf,len,cur);
04989         NEXTL(l);
04990         cur = CUR_CHAR(l);
04991         if (cur == 0) {
04992             SHRINK;
04993             GROW;
04994             cur = CUR_CHAR(l);
04995         }
04996         }
04997         buf[len] = 0;
04998         if (cur != '?') {
04999         xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
05000               "ParsePI: PI %s never end ...\n", target);
05001         } else {
05002         if (input != ctxt->input) {
05003             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05004         "PI declaration doesn't start and stop in the same entity\n");
05005         }
05006         SKIP(2);
05007 
05008 #ifdef LIBXML_CATALOG_ENABLED
05009         if (((state == XML_PARSER_MISC) ||
05010                  (state == XML_PARSER_START)) &&
05011             (xmlStrEqual(target, XML_CATALOG_PI))) {
05012             xmlCatalogAllow allow = xmlCatalogGetDefaults();
05013             if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
05014             (allow == XML_CATA_ALLOW_ALL))
05015             xmlParseCatalogPI(ctxt, buf);
05016         }
05017 #endif
05018 
05019 
05020         /*
05021          * SAX: PI detected.
05022          */
05023         if ((ctxt->sax) && (!ctxt->disableSAX) &&
05024             (ctxt->sax->processingInstruction != NULL))
05025             ctxt->sax->processingInstruction(ctxt->userData,
05026                                              target, buf);
05027         }
05028         xmlFree(buf);
05029     } else {
05030         xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
05031     }
05032     ctxt->instate = state;
05033     }
05034 }
05035 
05052 void
05053 xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
05054     const xmlChar *name;
05055     xmlChar *Pubid;
05056     xmlChar *Systemid;
05057     
05058     if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
05059     xmlParserInputPtr input = ctxt->input;
05060     SHRINK;
05061     SKIP(10);
05062     if (!IS_BLANK_CH(CUR)) {
05063         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05064                "Space required after '<!NOTATION'\n");
05065         return;
05066     }
05067     SKIP_BLANKS;
05068 
05069         name = xmlParseName(ctxt);
05070     if (name == NULL) {
05071         xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
05072         return;
05073     }
05074     if (!IS_BLANK_CH(CUR)) {
05075         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05076              "Space required after the NOTATION name'\n");
05077         return;
05078     }
05079     if (xmlStrchr(name, ':') != NULL) {
05080         xmlNsErr(ctxt, XML_NS_ERR_COLON, 
05081              "colon are forbidden from notation names '%s'\n",
05082              name, NULL, NULL);
05083     }
05084     SKIP_BLANKS;
05085 
05086     /*
05087      * Parse the IDs.
05088      */
05089     Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
05090     SKIP_BLANKS;
05091 
05092     if (RAW == '>') {
05093         if (input != ctxt->input) {
05094         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05095     "Notation declaration doesn't start and stop in the same entity\n");
05096         }
05097         NEXT;
05098         if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
05099         (ctxt->sax->notationDecl != NULL))
05100         ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
05101     } else {
05102         xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
05103     }
05104     if (Systemid != NULL) xmlFree(Systemid);
05105     if (Pubid != NULL) xmlFree(Pubid);
05106     }
05107 }
05108 
05131 void
05132 xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
05133     const xmlChar *name = NULL;
05134     xmlChar *value = NULL;
05135     xmlChar *URI = NULL, *literal = NULL;
05136     const xmlChar *ndata = NULL;
05137     int isParameter = 0;
05138     xmlChar *orig = NULL;
05139     int skipped;
05140     
05141     /* GROW; done in the caller */
05142     if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
05143     xmlParserInputPtr input = ctxt->input;
05144     SHRINK;
05145     SKIP(8);
05146     skipped = SKIP_BLANKS;
05147     if (skipped == 0) {
05148         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05149                "Space required after '<!ENTITY'\n");
05150     }
05151 
05152     if (RAW == '%') {
05153         NEXT;
05154         skipped = SKIP_BLANKS;
05155         if (skipped == 0) {
05156         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05157                    "Space required after '%'\n");
05158         }
05159         isParameter = 1;
05160     }
05161 
05162         name = xmlParseName(ctxt);
05163     if (name == NULL) {
05164         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
05165                        "xmlParseEntityDecl: no name\n");
05166             return;
05167     }
05168     if (xmlStrchr(name, ':') != NULL) {
05169         xmlNsErr(ctxt, XML_NS_ERR_COLON, 
05170              "colon are forbidden from entities names '%s'\n",
05171              name, NULL, NULL);
05172     }
05173         skipped = SKIP_BLANKS;
05174     if (skipped == 0) {
05175         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05176                "Space required after the entity name\n");
05177     }
05178 
05179     ctxt->instate = XML_PARSER_ENTITY_DECL;
05180     /*
05181      * handle the various case of definitions...
05182      */
05183     if (isParameter) {
05184         if ((RAW == '"') || (RAW == '\'')) {
05185             value = xmlParseEntityValue(ctxt, &orig);
05186         if (value) {
05187             if ((ctxt->sax != NULL) &&
05188             (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
05189             ctxt->sax->entityDecl(ctxt->userData, name,
05190                             XML_INTERNAL_PARAMETER_ENTITY,
05191                     NULL, NULL, value);
05192         }
05193         } else {
05194             URI = xmlParseExternalID(ctxt, &literal, 1);
05195         if ((URI == NULL) && (literal == NULL)) {
05196             xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
05197         }
05198         if (URI) {
05199             xmlURIPtr uri;
05200 
05201             uri = xmlParseURI((const char *) URI);
05202             if (uri == NULL) {
05203                 xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
05204                      "Invalid URI: %s\n", URI);
05205             /*
05206              * This really ought to be a well formedness error
05207              * but the XML Core WG decided otherwise c.f. issue
05208              * E26 of the XML erratas.
05209              */
05210             } else {
05211             if (uri->fragment != NULL) {
05212                 /*
05213                  * Okay this is foolish to block those but not
05214                  * invalid URIs.
05215                  */
05216                 xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
05217             } else {
05218                 if ((ctxt->sax != NULL) &&
05219                 (!ctxt->disableSAX) &&
05220                 (ctxt->sax->entityDecl != NULL))
05221                 ctxt->sax->entityDecl(ctxt->userData, name,
05222                         XML_EXTERNAL_PARAMETER_ENTITY,
05223                         literal, URI, NULL);
05224             }
05225             xmlFreeURI(uri);
05226             }
05227         }
05228         }
05229     } else {
05230         if ((RAW == '"') || (RAW == '\'')) {
05231             value = xmlParseEntityValue(ctxt, &orig);
05232         if ((ctxt->sax != NULL) &&
05233             (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
05234             ctxt->sax->entityDecl(ctxt->userData, name,
05235                 XML_INTERNAL_GENERAL_ENTITY,
05236                 NULL, NULL, value);
05237         /*
05238          * For expat compatibility in SAX mode.
05239          */
05240         if ((ctxt->myDoc == NULL) ||
05241             (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
05242             if (ctxt->myDoc == NULL) {
05243             ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
05244             if (ctxt->myDoc == NULL) {
05245                 xmlErrMemory(ctxt, "New Doc failed");
05246                 return;
05247             }
05248             ctxt->myDoc->properties = XML_DOC_INTERNAL;
05249             }
05250             if (ctxt->myDoc->intSubset == NULL)
05251             ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
05252                         BAD_CAST "fake", NULL, NULL);
05253 
05254             xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
05255                           NULL, NULL, value);
05256         }
05257         } else {
05258             URI = xmlParseExternalID(ctxt, &literal, 1);
05259         if ((URI == NULL) && (literal == NULL)) {
05260             xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
05261         }
05262         if (URI) {
05263             xmlURIPtr uri;
05264 
05265             uri = xmlParseURI((const char *)URI);
05266             if (uri == NULL) {
05267                 xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
05268                      "Invalid URI: %s\n", URI);
05269             /*
05270              * This really ought to be a well formedness error
05271              * but the XML Core WG decided otherwise c.f. issue
05272              * E26 of the XML erratas.
05273              */
05274             } else {
05275             if (uri->fragment != NULL) {
05276                 /*
05277                  * Okay this is foolish to block those but not
05278                  * invalid URIs.
05279                  */
05280                 xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
05281             }
05282             xmlFreeURI(uri);
05283             }
05284         }
05285         if ((RAW != '>') && (!IS_BLANK_CH(CUR))) {
05286             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05287                    "Space required before 'NDATA'\n");
05288         }
05289         SKIP_BLANKS;
05290         if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
05291             SKIP(5);
05292             if (!IS_BLANK_CH(CUR)) {
05293             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05294                        "Space required after 'NDATA'\n");
05295             }
05296             SKIP_BLANKS;
05297             ndata = xmlParseName(ctxt);
05298             if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
05299                 (ctxt->sax->unparsedEntityDecl != NULL))
05300             ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
05301                     literal, URI, ndata);
05302         } else {
05303             if ((ctxt->sax != NULL) &&
05304                 (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
05305             ctxt->sax->entityDecl(ctxt->userData, name,
05306                     XML_EXTERNAL_GENERAL_PARSED_ENTITY,
05307                     literal, URI, NULL);
05308             /*
05309              * For expat compatibility in SAX mode.
05310              * assuming the entity repalcement was asked for
05311              */
05312             if ((ctxt->replaceEntities != 0) &&
05313             ((ctxt->myDoc == NULL) ||
05314             (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
05315             if (ctxt->myDoc == NULL) {
05316                 ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
05317                 if (ctxt->myDoc == NULL) {
05318                     xmlErrMemory(ctxt, "New Doc failed");
05319                 return;
05320                 }
05321                 ctxt->myDoc->properties = XML_DOC_INTERNAL;
05322             }
05323 
05324             if (ctxt->myDoc->intSubset == NULL)
05325                 ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
05326                         BAD_CAST "fake", NULL, NULL);
05327             xmlSAX2EntityDecl(ctxt, name,
05328                           XML_EXTERNAL_GENERAL_PARSED_ENTITY,
05329                           literal, URI, NULL);
05330             }
05331         }
05332         }
05333     }
05334     SKIP_BLANKS;
05335     if (RAW != '>') {
05336         xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
05337                 "xmlParseEntityDecl: entity %s not terminated\n", name);
05338     } else {
05339         if (input != ctxt->input) {
05340         xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
05341     "Entity declaration doesn't start and stop in the same entity\n");
05342         }
05343         NEXT;
05344     }
05345     if (orig != NULL) {
05346         /*
05347          * Ugly mechanism to save the raw entity value.
05348          */
05349         xmlEntityPtr cur = NULL;
05350 
05351         if (isParameter) {
05352             if ((ctxt->sax != NULL) &&
05353             (ctxt->sax->getParameterEntity != NULL))
05354             cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
05355         } else {
05356             if ((ctxt->sax != NULL) &&
05357             (ctxt->sax->getEntity != NULL))
05358             cur = ctxt->sax->getEntity(ctxt->userData, name);
05359         if ((cur == NULL) && (ctxt->userData==ctxt)) {
05360             cur = xmlSAX2GetEntity(ctxt, name);
05361         }
05362         }
05363             if (cur != NULL) {
05364             if (cur->orig != NULL)
05365             xmlFree(orig);
05366         else
05367             cur->orig = orig;
05368         } else
05369         xmlFree(orig);
05370     }
05371     if (value != NULL) xmlFree(value);
05372     if (URI != NULL) xmlFree(URI);
05373     if (literal != NULL) xmlFree(literal);
05374     }
05375 }
05376 
05406 int
05407 xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
05408     int val;
05409     xmlChar *ret;
05410 
05411     *value = NULL;
05412     if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) {
05413     SKIP(9);
05414     return(XML_ATTRIBUTE_REQUIRED);
05415     }
05416     if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) {
05417     SKIP(8);
05418     return(XML_ATTRIBUTE_IMPLIED);
05419     }
05420     val = XML_ATTRIBUTE_NONE;
05421     if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
05422     SKIP(6);
05423     val = XML_ATTRIBUTE_FIXED;
05424     if (!IS_BLANK_CH(CUR)) {
05425         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05426                "Space required after '#FIXED'\n");
05427     }
05428     SKIP_BLANKS;
05429     }
05430     ret = xmlParseAttValue(ctxt);
05431     ctxt->instate = XML_PARSER_DTD;
05432     if (ret == NULL) {
05433     xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
05434                "Attribute default value declaration error\n");
05435     } else
05436         *value = ret;
05437     return(val);
05438 }
05439 
05457 xmlEnumerationPtr
05458 xmlParseNotationType(xmlParserCtxtPtr ctxt) {
05459     const xmlChar *name;
05460     xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
05461 
05462     if (RAW != '(') {
05463     xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
05464     return(NULL);
05465     }
05466     SHRINK;
05467     do {
05468         NEXT;
05469     SKIP_BLANKS;
05470         name = xmlParseName(ctxt);
05471     if (name == NULL) {
05472         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
05473                "Name expected in NOTATION declaration\n");
05474             xmlFreeEnumeration(ret);
05475         return(NULL);
05476     }
05477     tmp = ret;
05478     while (tmp != NULL) {
05479         if (xmlStrEqual(name, tmp->name)) {
05480         xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
05481       "standalone: attribute notation value token %s duplicated\n",
05482                  name, NULL);
05483         if (!xmlDictOwns(ctxt->dict, name))
05484             xmlFree((xmlChar *) name);
05485         break;
05486         }
05487         tmp = tmp->next;
05488     }
05489     if (tmp == NULL) {
05490         cur = xmlCreateEnumeration(name);
05491         if (cur == NULL) {
05492                 xmlFreeEnumeration(ret);
05493                 return(NULL);
05494             }
05495         if (last == NULL) ret = last = cur;
05496         else {
05497         last->next = cur;
05498         last = cur;
05499         }
05500     }
05501     SKIP_BLANKS;
05502     } while (RAW == '|');
05503     if (RAW != ')') {
05504     xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
05505         xmlFreeEnumeration(ret);
05506     return(NULL);
05507     }
05508     NEXT;
05509     return(ret);
05510 }
05511 
05527 xmlEnumerationPtr
05528 xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
05529     xmlChar *name;
05530     xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
05531 
05532     if (RAW != '(') {
05533     xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
05534     return(NULL);
05535     }
05536     SHRINK;
05537     do {
05538         NEXT;
05539     SKIP_BLANKS;
05540         name = xmlParseNmtoken(ctxt);
05541     if (name == NULL) {
05542         xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
05543         return(ret);
05544     }
05545     tmp = ret;
05546     while (tmp != NULL) {
05547         if (xmlStrEqual(name, tmp->name)) {
05548         xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
05549       "standalone: attribute enumeration value token %s duplicated\n",
05550                  name, NULL);
05551         if (!xmlDictOwns(ctxt->dict, name))
05552             xmlFree(name);
05553         break;
05554         }
05555         tmp = tmp->next;
05556     }
05557     if (tmp == NULL) {
05558         cur = xmlCreateEnumeration(name);
05559         if (!xmlDictOwns(ctxt->dict, name))
05560         xmlFree(name);
05561         if (cur == NULL) {
05562                 xmlFreeEnumeration(ret);
05563                 return(NULL);
05564             }
05565         if (last == NULL) ret = last = cur;
05566         else {
05567         last->next = cur;
05568         last = cur;
05569         }
05570     }
05571     SKIP_BLANKS;
05572     } while (RAW == '|');
05573     if (RAW != ')') {
05574     xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
05575     return(ret);
05576     }
05577     NEXT;
05578     return(ret);
05579 }
05580 
05596 int
05597 xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
05598     if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
05599     SKIP(8);
05600     if (!IS_BLANK_CH(CUR)) {
05601         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05602                "Space required after 'NOTATION'\n");
05603         return(0);
05604     }
05605         SKIP_BLANKS;
05606     *tree = xmlParseNotationType(ctxt);
05607     if (*tree == NULL) return(0);
05608     return(XML_ATTRIBUTE_NOTATION);
05609     }
05610     *tree = xmlParseEnumerationType(ctxt);
05611     if (*tree == NULL) return(0);
05612     return(XML_ATTRIBUTE_ENUMERATION);
05613 }
05614 
05660 int 
05661 xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
05662     SHRINK;
05663     if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
05664     SKIP(5);
05665     return(XML_ATTRIBUTE_CDATA);
05666      } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) {
05667     SKIP(6);
05668     return(XML_ATTRIBUTE_IDREFS);
05669      } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) {
05670     SKIP(5);
05671     return(XML_ATTRIBUTE_IDREF);
05672      } else if ((RAW == 'I') && (NXT(1) == 'D')) {
05673         SKIP(2);
05674     return(XML_ATTRIBUTE_ID);
05675      } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
05676     SKIP(6);
05677     return(XML_ATTRIBUTE_ENTITY);
05678      } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) {
05679     SKIP(8);
05680     return(XML_ATTRIBUTE_ENTITIES);
05681      } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) {
05682     SKIP(8);
05683     return(XML_ATTRIBUTE_NMTOKENS);
05684      } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) {
05685     SKIP(7);
05686     return(XML_ATTRIBUTE_NMTOKEN);
05687      }
05688      return(xmlParseEnumeratedType(ctxt, tree));
05689 }
05690 
05702 void
05703 xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
05704     const xmlChar *elemName;
05705     const xmlChar *attrName;
05706     xmlEnumerationPtr tree;
05707 
05708     if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
05709     xmlParserInputPtr input = ctxt->input;
05710 
05711     SKIP(9);
05712     if (!IS_BLANK_CH(CUR)) {
05713         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05714                          "Space required after '<!ATTLIST'\n");
05715     }
05716         SKIP_BLANKS;
05717         elemName = xmlParseName(ctxt);
05718     if (elemName == NULL) {
05719         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
05720                "ATTLIST: no name for Element\n");
05721         return;
05722     }
05723     SKIP_BLANKS;
05724     GROW;
05725     while (RAW != '>') {
05726         const xmlChar *check = CUR_PTR;
05727         int type;
05728         int def;
05729         xmlChar *defaultValue = NULL;
05730 
05731         GROW;
05732             tree = NULL;
05733         attrName = xmlParseName(ctxt);
05734         if (attrName == NULL) {
05735         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
05736                    "ATTLIST: no name for Attribute\n");
05737         break;
05738         }
05739         GROW;
05740         if (!IS_BLANK_CH(CUR)) {
05741         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05742                 "Space required after the attribute name\n");
05743         break;
05744         }
05745         SKIP_BLANKS;
05746 
05747         type = xmlParseAttributeType(ctxt, &tree);
05748         if (type <= 0) {
05749             break;
05750         }
05751 
05752         GROW;
05753         if (!IS_BLANK_CH(CUR)) {
05754         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05755                    "Space required after the attribute type\n");
05756             if (tree != NULL)
05757             xmlFreeEnumeration(tree);
05758         break;
05759         }
05760         SKIP_BLANKS;
05761 
05762         def = xmlParseDefaultDecl(ctxt, &defaultValue);
05763         if (def <= 0) {
05764                 if (defaultValue != NULL)
05765             xmlFree(defaultValue);
05766             if (tree != NULL)
05767             xmlFreeEnumeration(tree);
05768             break;
05769         }
05770         if ((type != XML_ATTRIBUTE_CDATA) && (defaultValue != NULL))
05771             xmlAttrNormalizeSpace(defaultValue, defaultValue);
05772 
05773         GROW;
05774             if (RAW != '>') {
05775         if (!IS_BLANK_CH(CUR)) {
05776             xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
05777             "Space required after the attribute default value\n");
05778             if (defaultValue != NULL)
05779             xmlFree(defaultValue);
05780             if (tree != NULL)
05781             xmlFreeEnumeration(tree);
05782             break;
05783         }
05784         SKIP_BLANKS;
05785         }
05786         if (check == CUR_PTR) {
05787         xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
05788                     "in xmlParseAttributeListDecl\n");
05789         if (defaultValue != NULL)
05790             xmlFree(defaultValue);
05791             if (tree != NULL)
05792             xmlFreeEnumeration(tree);
05793         break;
05794         }
05795         if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
05796         (ctxt->sax->attributeDecl != NULL))
05797         ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
05798                             type, def, defaultValue, tree);
05799         else if (tree != NULL)
05800         xmlFreeEnumeration(tree);
05801 
05802         if ((ctxt->sax2) && (defaultValue != NULL) &&
05803             (def != XML_ATTRIBUTE_IMPLIED) && 
05804         (def != XML_ATTRIBUTE_REQUIRED)) {
05805         xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue);
05806         }
05807         if (ctxt->sax2) {
05808         xmlAddSpecialAttr(ctxt, elemName, attrName, type);
05809         }
05810         if (defaultValue != NULL)
05811             xmlFree(defaultValue);
05812         GROW;
05813     }
05814     if (RAW == '>') {
05815         if (input != ctxt->input) {
05816         xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
05817     "Attribute list declaration doesn't start and stop in the same entity\n",
05818                                  NULL, NULL);
05819         }
05820         NEXT;
05821     }
05822     }
05823 }
05824 
05844 xmlElementContentPtr
05845 xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
05846     xmlElementContentPtr ret = NULL, cur = NULL, n;
05847     const xmlChar *elem = NULL;
05848 
05849     GROW;
05850     if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
05851     SKIP(7);
05852     SKIP_BLANKS;
05853     SHRINK;
05854     if (RAW == ')') {
05855         if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
05856         xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
05857 "Element content declaration doesn't start and stop in the same entity\n",
05858                                  NULL, NULL);
05859         }
05860         NEXT;
05861         ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
05862         if (ret == NULL)
05863             return(NULL);
05864         if (RAW == '*') {
05865         ret->ocur = XML_ELEMENT_CONTENT_MULT;
05866         NEXT;
05867         }
05868         return(ret);
05869     }
05870     if ((RAW == '(') || (RAW == '|')) {
05871         ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
05872         if (ret == NULL) return(NULL);
05873     }
05874     while (RAW == '|') {
05875         NEXT;
05876         if (elem == NULL) {
05877             ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
05878         if (ret == NULL) return(NULL);
05879         ret->c1 = cur;
05880         if (cur != NULL)
05881             cur->parent = ret;
05882         cur = ret;
05883         } else {
05884             n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
05885         if (n == NULL) return(NULL);
05886         n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
05887         if (n->c1 != NULL)
05888             n->c1->parent = n;
05889             cur->c2 = n;
05890         if (n != NULL)
05891             n->parent = cur;
05892         cur = n;
05893         }
05894         SKIP_BLANKS;
05895         elem = xmlParseName(ctxt);
05896         if (elem == NULL) {
05897         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
05898             "xmlParseElementMixedContentDecl : Name expected\n");
05899         xmlFreeDocElementContent(ctxt->myDoc, cur);
05900         return(NULL);
05901         }
05902         SKIP_BLANKS;
05903         GROW;
05904     }
05905     if ((RAW == ')') && (NXT(1) == '*')) {
05906         if (elem != NULL) {
05907         cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
05908                                        XML_ELEMENT_CONTENT_ELEMENT);
05909         if (cur->c2 != NULL)
05910             cur->c2->parent = cur;
05911             }
05912             if (ret != NULL)
05913                 ret->ocur = XML_ELEMENT_CONTENT_MULT;
05914         if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
05915         xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
05916 "Element content declaration doesn't start and stop in the same entity\n",
05917                  NULL, NULL);
05918         }
05919         SKIP(2);
05920     } else {
05921         xmlFreeDocElementContent(ctxt->myDoc, ret);
05922         xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL);
05923         return(NULL);
05924     }
05925 
05926     } else {
05927     xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
05928     }
05929     return(ret);
05930 }
05931 
05964 static xmlElementContentPtr
05965 xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
05966                                        int depth) {
05967     xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
05968     const xmlChar *elem;
05969     xmlChar type = 0;
05970 
05971     if (((depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
05972         (depth >  2048)) {
05973         xmlFatalErrMsgInt(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED,
05974 "xmlParseElementChildrenContentDecl : depth %d too deep, use XML_PARSE_HUGE\n",
05975                           depth);
05976     return(NULL);
05977     }
05978     SKIP_BLANKS;
05979     GROW;
05980     if (RAW == '(') {
05981     int inputid = ctxt->input->id;
05982 
05983         /* Recurse on first child */
05984     NEXT;
05985     SKIP_BLANKS;
05986         cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
05987                                                            depth + 1);
05988     SKIP_BLANKS;
05989     GROW;
05990     } else {
05991     elem = xmlParseName(ctxt);
05992     if (elem == NULL) {
05993         xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
05994         return(NULL);
05995     }
05996         cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
05997     if (cur == NULL) {
05998         xmlErrMemory(ctxt, NULL);
05999         return(NULL);
06000     }
06001     GROW;
06002     if (RAW == '?') {
06003         cur->ocur = XML_ELEMENT_CONTENT_OPT;
06004         NEXT;
06005     } else if (RAW == '*') {
06006         cur->ocur = XML_ELEMENT_CONTENT_MULT;
06007         NEXT;
06008     } else if (RAW == '+') {
06009         cur->ocur = XML_ELEMENT_CONTENT_PLUS;
06010         NEXT;
06011     } else {
06012         cur->ocur = XML_ELEMENT_CONTENT_ONCE;
06013     }
06014     GROW;
06015     }
06016     SKIP_BLANKS;
06017     SHRINK;
06018     while (RAW != ')') {
06019         /*
06020      * Each loop we parse one separator and one element.
06021      */
06022         if (RAW == ',') {
06023         if (type == 0) type = CUR;
06024 
06025         /*
06026          * Detect "Name | Name , Name" error
06027          */
06028         else if (type != CUR) {
06029         xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
06030             "xmlParseElementChildrenContentDecl : '%c' expected\n",
06031                           type);
06032         if ((last != NULL) && (last != ret))
06033             xmlFreeDocElementContent(ctxt->myDoc, last);
06034         if (ret != NULL)
06035             xmlFreeDocElementContent(ctxt->myDoc, ret);
06036         return(NULL);
06037         }
06038         NEXT;
06039 
06040         op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
06041         if (op == NULL) {
06042         if ((last != NULL) && (last != ret))
06043             xmlFreeDocElementContent(ctxt->myDoc, last);
06044             xmlFreeDocElementContent(ctxt->myDoc, ret);
06045         return(NULL);
06046         }
06047         if (last == NULL) {
06048         op->c1 = ret;
06049         if (ret != NULL)
06050             ret->parent = op;
06051         ret = cur = op;
06052         } else {
06053             cur->c2 = op;
06054         if (op != NULL)
06055             op->parent = cur;
06056         op->c1 = last;
06057         if (last != NULL)
06058             last->parent = op;
06059         cur =op;
06060         last = NULL;
06061         }
06062     } else if (RAW == '|') {
06063         if (type == 0) type = CUR;
06064 
06065         /*
06066          * Detect "Name , Name | Name" error
06067          */
06068         else if (type != CUR) {
06069         xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
06070             "xmlParseElementChildrenContentDecl : '%c' expected\n",
06071                   type);
06072         if ((last != NULL) && (last != ret))
06073             xmlFreeDocElementContent(ctxt->myDoc, last);
06074         if (ret != NULL)
06075             xmlFreeDocElementContent(ctxt->myDoc, ret);
06076         return(NULL);
06077         }
06078         NEXT;
06079 
06080         op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
06081         if (op == NULL) {
06082         if ((last != NULL) && (last != ret))
06083             xmlFreeDocElementContent(ctxt->myDoc, last);
06084         if (ret != NULL)
06085             xmlFreeDocElementContent(ctxt->myDoc, ret);
06086         return(NULL);
06087         }
06088         if (last == NULL) {
06089         op->c1 = ret;
06090         if (ret != NULL)
06091             ret->parent = op;
06092         ret = cur = op;
06093         } else {
06094             cur->c2 = op;
06095         if (op != NULL)
06096             op->parent = cur;
06097         op->c1 = last;
06098         if (last != NULL)
06099             last->parent = op;
06100         cur =op;
06101         last = NULL;
06102         }
06103     } else {
06104         xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL);
06105         if ((last != NULL) && (last != ret))
06106             xmlFreeDocElementContent(ctxt->myDoc, last);
06107         if (ret != NULL)
06108         xmlFreeDocElementContent(ctxt->myDoc, ret);
06109         return(NULL);
06110     }
06111     GROW;
06112     SKIP_BLANKS;
06113     GROW;
06114     if (RAW == '(') {
06115         int inputid = ctxt->input->id;
06116         /* Recurse on second child */
06117         NEXT;
06118         SKIP_BLANKS;
06119         last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
06120                                                           depth + 1);
06121         SKIP_BLANKS;
06122     } else {
06123         elem = xmlParseName(ctxt);
06124         if (elem == NULL) {
06125         xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
06126         if (ret != NULL)
06127             xmlFreeDocElementContent(ctxt->myDoc, ret);
06128         return(NULL);
06129         }
06130         last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
06131         if (last == NULL) {
06132         if (ret != NULL)
06133             xmlFreeDocElementContent(ctxt->myDoc, ret);
06134         return(NULL);
06135         }
06136         if (RAW == '?') {
06137         last->ocur = XML_ELEMENT_CONTENT_OPT;
06138         NEXT;
06139         } else if (RAW == '*') {
06140         last->ocur = XML_ELEMENT_CONTENT_MULT;
06141         NEXT;
06142         } else if (RAW == '+') {
06143         last->ocur = XML_ELEMENT_CONTENT_PLUS;
06144         NEXT;
06145         } else {
06146         last->ocur = XML_ELEMENT_CONTENT_ONCE;
06147         }
06148     }
06149     SKIP_BLANKS;
06150     GROW;
06151     }
06152     if ((cur != NULL) && (last != NULL)) {
06153         cur->c2 = last;
06154     if (last != NULL)
06155         last->parent = cur;
06156     }
06157     if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
06158     xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
06159 "Element content declaration doesn't start and stop in the same entity\n",
06160              NULL, NULL);
06161     }
06162     NEXT;
06163     if (RAW == '?') {
06164     if (ret != NULL) {
06165         if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) ||
06166             (ret->ocur == XML_ELEMENT_CONTENT_MULT))
06167             ret->ocur = XML_ELEMENT_CONTENT_MULT;
06168         else
06169             ret->ocur = XML_ELEMENT_CONTENT_OPT;
06170     }
06171     NEXT;
06172     } else if (RAW == '*') {
06173     if (ret != NULL) {
06174         ret->ocur = XML_ELEMENT_CONTENT_MULT;
06175         cur = ret;
06176         /*
06177          * Some normalization:
06178          * (a | b* | c?)* == (a | b | c)*
06179          */
06180         while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
06181         if ((cur->c1 != NULL) &&
06182                 ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
06183              (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
06184             cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
06185         if ((cur->c2 != NULL) &&
06186                 ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
06187              (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
06188             cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
06189         cur = cur->c2;
06190         }
06191     }
06192     NEXT;
06193     } else if (RAW == '+') {
06194     if (ret != NULL) {
06195         int found = 0;
06196 
06197         if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) ||
06198             (ret->ocur == XML_ELEMENT_CONTENT_MULT))
06199             ret->ocur = XML_ELEMENT_CONTENT_MULT;
06200         else
06201             ret->ocur = XML_ELEMENT_CONTENT_PLUS;
06202         /*
06203          * Some normalization:
06204          * (a | b*)+ == (a | b)*
06205          * (a | b?)+ == (a | b)*
06206          */
06207         while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
06208         if ((cur->c1 != NULL) &&
06209                 ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
06210              (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
06211             cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
06212             found = 1;
06213         }
06214         if ((cur->c2 != NULL) &&
06215                 ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
06216              (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
06217             cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
06218             found = 1;
06219         }
06220         cur = cur->c2;
06221         }
06222         if (found)
06223         ret->ocur = XML_ELEMENT_CONTENT_MULT;
06224     }
06225     NEXT;
06226     }
06227     return(ret);
06228 }
06229 
06260 xmlElementContentPtr
06261 xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
06262     /* stub left for API/ABI compat */
06263     return(xmlParseElementChildrenContentDeclPriv(ctxt, inputchk, 1));
06264 }
06265 
06280 int
06281 xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
06282                            xmlElementContentPtr *result) {
06283 
06284     xmlElementContentPtr tree = NULL;
06285     int inputid = ctxt->input->id;
06286     int res;
06287 
06288     *result = NULL;
06289 
06290     if (RAW != '(') {
06291     xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
06292         "xmlParseElementContentDecl : %s '(' expected\n", name);
06293     return(-1);
06294     }
06295     NEXT;
06296     GROW;
06297     SKIP_BLANKS;
06298     if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
06299         tree = xmlParseElementMixedContentDecl(ctxt, inputid);
06300     res = XML_ELEMENT_TYPE_MIXED;
06301     } else {
06302         tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1);
06303     res = XML_ELEMENT_TYPE_ELEMENT;
06304     }
06305     SKIP_BLANKS;
06306     *result = tree;
06307     return(res);
06308 }
06309 
06323 int
06324 xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
06325     const xmlChar *name;
06326     int ret = -1;
06327     xmlElementContentPtr content  = NULL;
06328 
06329     /* GROW; done in the caller */
06330     if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
06331     xmlParserInputPtr input = ctxt->input;
06332 
06333     SKIP(9);
06334     if (!IS_BLANK_CH(CUR)) {
06335         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
06336                    "Space required after 'ELEMENT'\n");
06337     }
06338         SKIP_BLANKS;
06339         name = xmlParseName(ctxt);
06340     if (name == NULL) {
06341         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
06342                "xmlParseElementDecl: no name for Element\n");
06343         return(-1);
06344     }
06345     while ((RAW == 0) && (ctxt->inputNr > 1))
06346         xmlPopInput(ctxt);
06347     if (!IS_BLANK_CH(CUR)) {
06348         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
06349                "Space required after the element name\n");
06350     }
06351         SKIP_BLANKS;
06352     if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
06353         SKIP(5);
06354         /*
06355          * Element must always be empty.
06356          */
06357         ret = XML_ELEMENT_TYPE_EMPTY;
06358     } else if ((RAW == 'A') && (NXT(1) == 'N') &&
06359                (NXT(2) == 'Y')) {
06360         SKIP(3);
06361         /*
06362          * Element is a generic container.
06363          */
06364         ret = XML_ELEMENT_TYPE_ANY;
06365     } else if (RAW == '(') {
06366         ret = xmlParseElementContentDecl(ctxt, name, &content);
06367     } else {
06368         /*
06369          * [ WFC: PEs in Internal Subset ] error handling.
06370          */
06371         if ((RAW == '%') && (ctxt->external == 0) &&
06372             (ctxt->inputNr == 1)) {
06373         xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET,
06374       "PEReference: forbidden within markup decl in internal subset\n");
06375         } else {
06376         xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
06377               "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
06378             }
06379         return(-1);
06380     }
06381 
06382     SKIP_BLANKS;
06383     /*
06384      * Pop-up of finished entities.
06385      */
06386     while ((RAW == 0) && (ctxt->inputNr > 1))
06387         xmlPopInput(ctxt);
06388     SKIP_BLANKS;
06389 
06390     if (RAW != '>') {
06391         xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
06392         if (content != NULL) {
06393         xmlFreeDocElementContent(ctxt->myDoc, content);
06394         }
06395     } else {
06396         if (input != ctxt->input) {
06397         xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
06398     "Element declaration doesn't start and stop in the same entity\n");
06399         }
06400         
06401         NEXT;
06402         if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
06403         (ctxt->sax->elementDecl != NULL)) {
06404         if (content != NULL)
06405             content->parent = NULL;
06406             ctxt->sax->elementDecl(ctxt->userData, name, ret,
06407                                content);
06408         if ((content != NULL) && (content->parent == NULL)) {
06409             /*
06410              * this is a trick: if xmlAddElementDecl is called,
06411              * instead of copying the full tree it is plugged directly
06412              * if called from the parser. Avoid duplicating the 
06413              * interfaces or change the API/ABI
06414              */
06415             xmlFreeDocElementContent(ctxt->myDoc, content);
06416         }
06417         } else if (content != NULL) {
06418         xmlFreeDocElementContent(ctxt->myDoc, content);
06419         }
06420     }
06421     }
06422     return(ret);
06423 }
06424 
06436 static void
06437 xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
06438     int id = ctxt->input->id;
06439 
06440     SKIP(3);
06441     SKIP_BLANKS;
06442     if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
06443     SKIP(7);
06444     SKIP_BLANKS;
06445     if (RAW != '[') {
06446         xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
06447     } else {
06448         if (ctxt->input->id != id) {
06449         xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
06450         "All markup of the conditional section is not in the same entity\n",
06451                      NULL, NULL);
06452         }
06453         NEXT;
06454     }
06455     if (xmlParserDebugEntities) {
06456         if ((ctxt->input != NULL) && (ctxt->input->filename))
06457         xmlGenericError(xmlGenericErrorContext,
06458             "%s(%d): ", ctxt->input->filename,
06459             ctxt->input->line);
06460         xmlGenericError(xmlGenericErrorContext,
06461             "Entering INCLUDE Conditional Section\n");
06462     }
06463 
06464     while ((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
06465            (NXT(2) != '>'))) {
06466         const xmlChar *check = CUR_PTR;
06467         unsigned int cons = ctxt->input->consumed;
06468 
06469         if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
06470         xmlParseConditionalSections(ctxt);
06471         } else if (IS_BLANK_CH(CUR)) {
06472         NEXT;
06473         } else if (RAW == '%') {
06474         xmlParsePEReference(ctxt);
06475         } else
06476         xmlParseMarkupDecl(ctxt);
06477 
06478         /*
06479          * Pop-up of finished entities.
06480          */
06481         while ((RAW == 0) && (ctxt->inputNr > 1))
06482         xmlPopInput(ctxt);
06483 
06484         if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
06485         xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
06486         break;
06487         }
06488     }
06489     if (xmlParserDebugEntities) {
06490         if ((ctxt->input != NULL) && (ctxt->input->filename))
06491         xmlGenericError(xmlGenericErrorContext,
06492             "%s(%d): ", ctxt->input->filename,
06493             ctxt->input->line);
06494         xmlGenericError(xmlGenericErrorContext,
06495             "Leaving INCLUDE Conditional Section\n");
06496     }
06497 
06498     } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
06499     int state;
06500     xmlParserInputState instate;
06501     int depth = 0;
06502 
06503     SKIP(6);
06504     SKIP_BLANKS;
06505     if (RAW != '[') {
06506         xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
06507     } else {
06508         if (ctxt->input->id != id) {
06509         xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
06510         "All markup of the conditional section is not in the same entity\n",
06511                      NULL, NULL);
06512         }
06513         NEXT;
06514     }
06515     if (xmlParserDebugEntities) {
06516         if ((ctxt->input != NULL) && (ctxt->input->filename))
06517         xmlGenericError(xmlGenericErrorContext,
06518             "%s(%d): ", ctxt->input->filename,
06519             ctxt->input->line);
06520         xmlGenericError(xmlGenericErrorContext,
06521             "Entering IGNORE Conditional Section\n");
06522     }
06523 
06524     /*
06525      * Parse up to the end of the conditional section
06526      * But disable SAX event generating DTD building in the meantime
06527      */
06528     state = ctxt->disableSAX;
06529     instate = ctxt->instate;
06530     if (ctxt->recovery == 0) ctxt->disableSAX = 1;
06531     ctxt->instate = XML_PARSER_IGNORE;
06532 
06533     while ((depth >= 0) && (RAW != 0)) {
06534       if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
06535         depth++;
06536         SKIP(3);
06537         continue;
06538       }
06539       if ((RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
06540         if (--depth >= 0) SKIP(3);
06541         continue;
06542       }
06543       NEXT;
06544       continue;
06545     }
06546 
06547     ctxt->disableSAX = state;
06548     ctxt->instate = instate;
06549 
06550     if (xmlParserDebugEntities) {
06551         if ((ctxt->input != NULL) && (ctxt->input->filename))
06552         xmlGenericError(xmlGenericErrorContext,
06553             "%s(%d): ", ctxt->input->filename,
06554             ctxt->input->line);
06555         xmlGenericError(xmlGenericErrorContext,
06556             "Leaving IGNORE Conditional Section\n");
06557     }
06558 
06559     } else {
06560     xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
06561     }
06562 
06563     if (RAW == 0)
06564         SHRINK;
06565 
06566     if (RAW == 0) {
06567     xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
06568     } else {
06569     if (ctxt->input->id != id) {
06570         xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
06571     "All markup of the conditional section is not in the same entity\n",
06572                  NULL, NULL);
06573     }
06574         SKIP(3);
06575     }
06576 }
06577 
06600 void
06601 xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
06602     GROW;
06603     if (CUR == '<') {
06604         if (NXT(1) == '!') {
06605         switch (NXT(2)) {
06606             case 'E':
06607             if (NXT(3) == 'L')
06608             xmlParseElementDecl(ctxt);
06609             else if (NXT(3) == 'N')
06610             xmlParseEntityDecl(ctxt);
06611             break;
06612             case 'A':
06613             xmlParseAttributeListDecl(ctxt);
06614             break;
06615             case 'N':
06616             xmlParseNotationDecl(ctxt);
06617             break;
06618             case '-':
06619             xmlParseComment(ctxt);
06620             break;
06621         default:
06622             /* there is an error but it will be detected later */
06623             break;
06624         }
06625     } else if (NXT(1) == '?') {
06626         xmlParsePI(ctxt);
06627     }
06628     }
06629     /*
06630      * This is only for internal subset. On external entities,
06631      * the replacement is done before parsing stage
06632      */
06633     if ((ctxt->external == 0) && (ctxt->inputNr == 1))
06634     xmlParsePEReference(ctxt);
06635 
06636     /*
06637      * Conditional sections are allowed from entities included
06638      * by PE References in the internal subset.
06639      */
06640     if ((ctxt->external == 0) && (ctxt->inputNr > 1)) {
06641         if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
06642         xmlParseConditionalSections(ctxt);
06643     }
06644     }
06645 
06646     ctxt->instate = XML_PARSER_DTD;
06647 }
06648 
06658 void
06659 xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
06660     xmlChar *version;
06661     const xmlChar *encoding;
06662 
06663     /*
06664      * We know that '<?xml' is here.
06665      */
06666     if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
06667     SKIP(5);
06668     } else {
06669     xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL);
06670     return;
06671     }
06672 
06673     if (!IS_BLANK_CH(CUR)) {
06674     xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
06675                "Space needed after '<?xml'\n");
06676     }
06677     SKIP_BLANKS;
06678 
06679     /*
06680      * We may have the VersionInfo here.
06681      */
06682     version = xmlParseVersionInfo(ctxt);
06683     if (version == NULL)
06684     version = xmlCharStrdup(XML_DEFAULT_VERSION);
06685     else {
06686     if (!IS_BLANK_CH(CUR)) {
06687         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
06688                    "Space needed here\n");
06689     }
06690     }
06691     ctxt->input->version = version;
06692 
06693     /*
06694      * We must have the encoding declaration
06695      */
06696     encoding = xmlParseEncodingDecl(ctxt);
06697     if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
06698     /*
06699      * The XML REC instructs us to stop parsing right here
06700      */
06701         return;
06702     }
06703     if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
06704     xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING,
06705                "Missing encoding in text declaration\n");
06706     }
06707 
06708     SKIP_BLANKS;
06709     if ((RAW == '?') && (NXT(1) == '>')) {
06710         SKIP(2);
06711     } else if (RAW == '>') {
06712         /* Deprecated old WD ... */
06713     xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
06714     NEXT;
06715     } else {
06716     xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
06717     MOVETO_ENDTAG(CUR_PTR);
06718     NEXT;
06719     }
06720 }
06721 
06734 void
06735 xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
06736                        const xmlChar *SystemID) {
06737     xmlDetectSAX2(ctxt);
06738     GROW;
06739 
06740     if ((ctxt->encoding == NULL) &&
06741         (ctxt->input->end - ctxt->input->cur >= 4)) {
06742         xmlChar start[4];
06743     xmlCharEncoding enc;
06744 
06745     start[0] = RAW;
06746     start[1] = NXT(1);
06747     start[2] = NXT(2);
06748     start[3] = NXT(3);
06749     enc = xmlDetectCharEncoding(start, 4);
06750     if (enc != XML_CHAR_ENCODING_NONE)
06751         xmlSwitchEncoding(ctxt, enc);
06752     }
06753 
06754     if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
06755     xmlParseTextDecl(ctxt);
06756     if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
06757         /*
06758          * The XML REC instructs us to stop parsing right here
06759          */
06760         ctxt->instate = XML_PARSER_EOF;
06761         return;
06762     }
06763     }
06764     if (ctxt->myDoc == NULL) {
06765         ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
06766     if (ctxt->myDoc == NULL) {
06767         xmlErrMemory(ctxt, "New Doc failed");
06768         return;
06769     }
06770     ctxt->myDoc->properties = XML_DOC_INTERNAL;
06771     }
06772     if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
06773         xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
06774 
06775     ctxt->instate = XML_PARSER_DTD;
06776     ctxt->external = 1;
06777     while (((RAW == '<') && (NXT(1) == '?')) ||
06778            ((RAW == '<') && (NXT(1) == '!')) ||
06779        (RAW == '%') || IS_BLANK_CH(CUR)) {
06780     const xmlChar *check = CUR_PTR;
06781     unsigned int cons = ctxt->input->consumed;
06782 
06783     GROW;
06784         if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
06785         xmlParseConditionalSections(ctxt);
06786     } else if (IS_BLANK_CH(CUR)) {
06787         NEXT;
06788     } else if (RAW == '%') {
06789             xmlParsePEReference(ctxt);
06790     } else
06791         xmlParseMarkupDecl(ctxt);
06792 
06793     /*
06794      * Pop-up of finished entities.
06795      */
06796     while ((RAW == 0) && (ctxt->inputNr > 1))
06797         xmlPopInput(ctxt);
06798 
06799     if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
06800         xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
06801         break;
06802     }
06803     }
06804     
06805     if (RAW != 0) {
06806     xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
06807     }
06808 
06809 }
06810 
06822 void
06823 xmlParseReference(xmlParserCtxtPtr ctxt) {
06824     xmlEntityPtr ent;
06825     xmlChar *val;
06826     int was_checked;
06827     xmlNodePtr list = NULL;
06828     xmlParserErrors ret = XML_ERR_OK;
06829 
06830 
06831     if (RAW != '&')
06832         return;
06833 
06834     /*
06835      * Simple case of a CharRef
06836      */
06837     if (NXT(1) == '#') {
06838     int i = 0;
06839     xmlChar out[10];
06840     int hex = NXT(2);
06841     int value = xmlParseCharRef(ctxt);
06842 
06843     if (value == 0)
06844         return;
06845     if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
06846         /*
06847          * So we are using non-UTF-8 buffers
06848          * Check that the char fit on 8bits, if not
06849          * generate a CharRef.
06850          */
06851         if (value <= 0xFF) {
06852         out[0] = value;
06853         out[1] = 0;
06854         if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
06855             (!ctxt->disableSAX))
06856             ctxt->sax->characters(ctxt->userData, out, 1);
06857         } else {
06858         if ((hex == 'x') || (hex == 'X'))
06859             snprintf((char *)out, sizeof(out), "#x%X", value);
06860         else
06861             snprintf((char *)out, sizeof(out), "#%d", value);
06862         if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
06863             (!ctxt->disableSAX))
06864             ctxt->sax->reference(ctxt->userData, out);
06865         }
06866     } else {
06867         /*
06868          * Just encode the value in UTF-8
06869          */
06870         COPY_BUF(0 ,out, i, value);
06871         out[i] = 0;
06872         if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
06873         (!ctxt->disableSAX))
06874         ctxt->sax->characters(ctxt->userData, out, i);
06875     }
06876     return;
06877     }
06878 
06879     /*
06880      * We are seeing an entity reference
06881      */
06882     ent = xmlParseEntityRef(ctxt);
06883     if (ent == NULL) return;
06884     if (!ctxt->wellFormed)
06885     return;
06886     was_checked = ent->checked;
06887 
06888     /* special case of predefined entities */
06889     if ((ent->name == NULL) ||
06890         (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
06891     val = ent->content;
06892     if (val == NULL) return;
06893     /*
06894      * inline the entity.
06895      */
06896     if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
06897         (!ctxt->disableSAX))
06898         ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
06899     return;
06900     }
06901 
06902     /*
06903      * The first reference to the entity trigger a parsing phase
06904      * where the ent->children is filled with the result from
06905      * the parsing.
06906      */
06907     if (ent->checked == 0) {
06908     unsigned long oldnbent = ctxt->nbentities;
06909 
06910     /*
06911      * This is a bit hackish but this seems the best
06912      * way to make sure both SAX and DOM entity support
06913      * behaves okay.
06914      */
06915     void *user_data;
06916     if (ctxt->userData == ctxt)
06917         user_data = NULL;
06918     else
06919         user_data = ctxt->userData;
06920 
06921     /*
06922      * Check that this entity is well formed
06923      * 4.3.2: An internal general parsed entity is well-formed
06924      * if its replacement text matches the production labeled
06925      * content.
06926      */
06927     if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
06928         ctxt->depth++;
06929         ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content,
06930                                                   user_data, &list);
06931         ctxt->depth--;
06932 
06933     } else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
06934         ctxt->depth++;
06935         ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax,
06936                                        user_data, ctxt->depth, ent->URI,
06937                        ent->ExternalID, &list);
06938         ctxt->depth--;
06939     } else {
06940         ret = XML_ERR_ENTITY_PE_INTERNAL;
06941         xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
06942              "invalid entity type found\n", NULL);
06943     }
06944 
06945     /*
06946      * Store the number of entities needing parsing for this entity
06947      * content and do checkings
06948      */
06949     ent->checked = ctxt->nbentities - oldnbent;
06950     if (ret == XML_ERR_ENTITY_LOOP) {
06951         xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
06952         xmlFreeNodeList(list);
06953         return;
06954     }
06955     if (xmlParserEntityCheck(ctxt, 0, ent)) {
06956         xmlFreeNodeList(list);
06957         return;
06958     }
06959 
06960     if ((ret == XML_ERR_OK) && (list != NULL)) {
06961         if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
06962          (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
06963         (ent->children == NULL)) {
06964         ent->children = list;
06965         if (ctxt->replaceEntities) {
06966             /*
06967              * Prune it directly in the generated document
06968              * except for single text nodes.
06969              */
06970             if (((list->type == XML_TEXT_NODE) &&
06971              (list->next == NULL)) ||
06972             (ctxt->parseMode == XML_PARSE_READER)) {
06973             list->parent = (xmlNodePtr) ent;
06974             list = NULL;
06975             ent->owner = 1;
06976             } else {
06977             ent->owner = 0;
06978             while (list != NULL) {
06979                 list->parent = (xmlNodePtr) ctxt->node;
06980                 list->doc = ctxt->myDoc;
06981                 if (list->next == NULL)
06982                 ent->last = list;
06983                 list = list->next;
06984             }
06985             list = ent->children;
06986 #ifdef LIBXML_LEGACY_ENABLED
06987             if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
06988               xmlAddEntityReference(ent, list, NULL);
06989 #endif /* LIBXML_LEGACY_ENABLED */
06990             }
06991         } else {
06992             ent->owner = 1;
06993             while (list != NULL) {
06994             list->parent = (xmlNodePtr) ent;
06995             if (list->next == NULL)
06996                 ent->last = list;
06997             list = list->next;
06998             }
06999         }
07000         } else {
07001         xmlFreeNodeList(list);
07002         list = NULL;
07003         }
07004     } else if ((ret != XML_ERR_OK) &&
07005            (ret != XML_WAR_UNDECLARED_ENTITY)) {
07006         xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
07007              "Entity '%s' failed to parse\n", ent->name);
07008     } else if (list != NULL) {
07009         xmlFreeNodeList(list);
07010         list = NULL;
07011     }
07012     if (ent->checked == 0)
07013         ent->checked = 1;
07014     } else if (ent->checked != 1) {
07015     ctxt->nbentities += ent->checked;
07016     }
07017 
07018     /*
07019      * Now that the entity content has been gathered
07020      * provide it to the application, this can take different forms based
07021      * on the parsing modes.
07022      */
07023     if (ent->children == NULL) {
07024     /*
07025      * Probably running in SAX mode and the callbacks don't
07026      * build the entity content. So unless we already went
07027      * though parsing for first checking go though the entity
07028      * content to generate callbacks associated to the entity
07029      */
07030     if (was_checked != 0) {
07031         void *user_data;
07032         /*
07033          * This is a bit hackish but this seems the best
07034          * way to make sure both SAX and DOM entity support
07035          * behaves okay.
07036          */
07037         if (ctxt->userData == ctxt)
07038         user_data = NULL;
07039         else
07040         user_data = ctxt->userData;
07041 
07042         if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
07043         ctxt->depth++;
07044         ret = xmlParseBalancedChunkMemoryInternal(ctxt,
07045                    ent->content, user_data, NULL);
07046         ctxt->depth--;
07047         } else if (ent->etype ==
07048                XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
07049         ctxt->depth++;
07050         ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
07051                ctxt->sax, user_data, ctxt->depth,
07052                ent->URI, ent->ExternalID, NULL);
07053         ctxt->depth--;
07054         } else {
07055         ret = XML_ERR_ENTITY_PE_INTERNAL;
07056         xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
07057                  "invalid entity type found\n", NULL);
07058         }
07059         if (ret == XML_ERR_ENTITY_LOOP) {
07060         xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
07061         return;
07062         }
07063     }
07064     if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
07065         (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
07066         /*
07067          * Entity reference callback comes second, it's somewhat
07068          * superfluous but a compatibility to historical behaviour
07069          */
07070         ctxt->sax->reference(ctxt->userData, ent->name);
07071     }
07072     return;
07073     }
07074 
07075     /*
07076      * If we didn't get any children for the entity being built
07077      */
07078     if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
07079     (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
07080     /*
07081      * Create a node.
07082      */
07083     ctxt->sax->reference(ctxt->userData, ent->name);
07084     return;
07085     }
07086 
07087     if ((ctxt->replaceEntities) || (ent->children == NULL))  {
07088     /*
07089      * There is a problem on the handling of _private for entities
07090      * (bug 155816): Should we copy the content of the field from
07091      * the entity (possibly overwriting some value set by the user
07092      * when a copy is created), should we leave it alone, or should
07093      * we try to take care of different situations?  The problem
07094      * is exacerbated by the usage of this field by the xmlReader.
07095      * To fix this bug, we look at _private on the created node
07096      * and, if it's NULL, we copy in whatever was in the entity.
07097      * If it's not NULL we leave it alone.  This is somewhat of a
07098      * hack - maybe we should have further tests to determine
07099      * what to do.
07100      */
07101     if ((ctxt->node != NULL) && (ent->children != NULL)) {
07102         /*
07103          * Seems we are generating the DOM content, do
07104          * a simple tree copy for all references except the first
07105          * In the first occurrence list contains the replacement.
07106          * progressive == 2 means we are operating on the Reader
07107          * and since nodes are discarded we must copy all the time.
07108          */
07109         if (((list == NULL) && (ent->owner == 0)) ||
07110         (ctxt->parseMode == XML_PARSE_READER)) {
07111         xmlNodePtr nw = NULL, cur, firstChild = NULL;
07112 
07113         /*
07114          * when operating on a reader, the entities definitions
07115          * are always owning the entities subtree.
07116         if (ctxt->parseMode == XML_PARSE_READER)
07117             ent->owner = 1;
07118          */
07119 
07120         cur = ent->children;
07121         while (cur != NULL) {
07122             nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
07123             if (nw != NULL) {
07124             if (nw->_private == NULL)
07125                 nw->_private = cur->_private;
07126             if (firstChild == NULL){
07127                 firstChild = nw;
07128             }
07129             nw = xmlAddChild(ctxt->node, nw);
07130             }
07131             if (cur == ent->last) {
07132             /*
07133              * needed to detect some strange empty
07134              * node cases in the reader tests
07135              */
07136             if ((ctxt->parseMode == XML_PARSE_READER) &&
07137                 (nw != NULL) &&
07138                 (nw->type == XML_ELEMENT_NODE) &&
07139                 (nw->children == NULL))
07140                 nw->extra = 1;
07141 
07142             break;
07143             }
07144             cur = cur->next;
07145         }
07146 #ifdef LIBXML_LEGACY_ENABLED
07147         if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
07148           xmlAddEntityReference(ent, firstChild, nw);
07149 #endif /* LIBXML_LEGACY_ENABLED */
07150         } else if (list == NULL) {
07151         xmlNodePtr nw = NULL, cur, next, last,
07152                firstChild = NULL;
07153         /*
07154          * Copy the entity child list and make it the new
07155          * entity child list. The goal is to make sure any
07156          * ID or REF referenced will be the one from the
07157          * document content and not the entity copy.
07158          */
07159         cur = ent->children;
07160         ent->children = NULL;
07161         last = ent->last;
07162         ent->last = NULL;
07163         while (cur != NULL) {
07164             next = cur->next;
07165             cur->next = NULL;
07166             cur->parent = NULL;
07167             nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
07168             if (nw != NULL) {
07169             if (nw->_private == NULL)
07170                 nw->_private = cur->_private;
07171             if (firstChild == NULL){
07172                 firstChild = cur;
07173             }
07174             xmlAddChild((xmlNodePtr) ent, nw);
07175             xmlAddChild(ctxt->node, cur);
07176             }
07177             if (cur == last)
07178             break;
07179             cur = next;
07180         }
07181         if (ent->owner == 0)
07182             ent->owner = 1;
07183 #ifdef LIBXML_LEGACY_ENABLED
07184         if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
07185           xmlAddEntityReference(ent, firstChild, nw);
07186 #endif /* LIBXML_LEGACY_ENABLED */
07187         } else {
07188         const xmlChar *nbktext;
07189 
07190         /*
07191          * the name change is to avoid coalescing of the
07192          * node with a possible previous text one which
07193          * would make ent->children a dangling pointer
07194          */
07195         nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
07196                     -1);
07197         if (ent->children->type == XML_TEXT_NODE)
07198             ent->children->name = nbktext;
07199         if ((ent->last != ent->children) &&
07200             (ent->last->type == XML_TEXT_NODE))
07201             ent->last->name = nbktext;
07202         xmlAddChildList(ctxt->node, ent->children);
07203         }
07204 
07205         /*
07206          * This is to avoid a nasty side effect, see
07207          * characters() in SAX.c
07208          */
07209         ctxt->nodemem = 0;
07210         ctxt->nodelen = 0;
07211         return;
07212     }
07213     }
07214 }
07215 
07244 xmlEntityPtr
07245 xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
07246     const xmlChar *name;
07247     xmlEntityPtr ent = NULL;
07248 
07249     GROW;
07250 
07251     if (RAW != '&')
07252         return(NULL);
07253     NEXT;
07254     name = xmlParseName(ctxt);
07255     if (name == NULL) {
07256     xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
07257                "xmlParseEntityRef: no name\n");
07258         return(NULL);
07259     }
07260     if (RAW != ';') {
07261     xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
07262     return(NULL);
07263     }
07264     NEXT;
07265 
07266     /*
07267      * Predefined entites override any extra definition
07268      */
07269     if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
07270         ent = xmlGetPredefinedEntity(name);
07271         if (ent != NULL)
07272             return(ent);
07273     }
07274 
07275     /*
07276      * Increate the number of entity references parsed
07277      */
07278     ctxt->nbentities++;
07279 
07280     /*
07281      * Ask first SAX for entity resolution, otherwise try the
07282      * entities which may have stored in the parser context.
07283      */
07284     if (ctxt->sax != NULL) {
07285     if (ctxt->sax->getEntity != NULL)
07286         ent = ctxt->sax->getEntity(ctxt->userData, name);
07287     if ((ctxt->wellFormed == 1 ) && (ent == NULL) && 
07288         (ctxt->options & XML_PARSE_OLDSAX))
07289         ent = xmlGetPredefinedEntity(name);
07290     if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
07291         (ctxt->userData==ctxt)) {
07292         ent = xmlSAX2GetEntity(ctxt, name);
07293     }
07294     }
07295     /*
07296      * [ WFC: Entity Declared ]
07297      * In a document without any DTD, a document with only an
07298      * internal DTD subset which contains no parameter entity
07299      * references, or a document with "standalone='yes'", the
07300      * Name given in the entity reference must match that in an
07301      * entity declaration, except that well-formed documents
07302      * need not declare any of the following entities: amp, lt,
07303      * gt, apos, quot.
07304      * The declaration of a parameter entity must precede any
07305      * reference to it.
07306      * Similarly, the declaration of a general entity must
07307      * precede any reference to it which appears in a default
07308      * value in an attribute-list declaration. Note that if
07309      * entities are declared in the external subset or in
07310      * external parameter entities, a non-validating processor
07311      * is not obligated to read and process their declarations;
07312      * for such documents, the rule that an entity must be
07313      * declared is a well-formedness constraint only if
07314      * standalone='yes'.
07315      */
07316     if (ent == NULL) {
07317     if ((ctxt->standalone == 1) ||
07318         ((ctxt->hasExternalSubset == 0) &&
07319          (ctxt->hasPErefs == 0))) {
07320         xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
07321              "Entity '%s' not defined\n", name);
07322     } else {
07323         xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
07324              "Entity '%s' not defined\n", name);
07325         if ((ctxt->inSubset == 0) &&
07326         (ctxt->sax != NULL) &&
07327         (ctxt->sax->reference != NULL)) {
07328         ctxt->sax->reference(ctxt->userData, name);
07329         }
07330     }
07331     ctxt->valid = 0;
07332     }
07333 
07334     /*
07335      * [ WFC: Parsed Entity ]
07336      * An entity reference must not contain the name of an
07337      * unparsed entity
07338      */
07339     else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
07340     xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
07341          "Entity reference to unparsed entity %s\n", name);
07342     }
07343 
07344     /*
07345      * [ WFC: No External Entity References ]
07346      * Attribute values cannot contain direct or indirect
07347      * entity references to external entities.
07348      */
07349     else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
07350          (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
07351     xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
07352          "Attribute references external entity '%s'\n", name);
07353     }
07354     /*
07355      * [ WFC: No < in Attribute Values ]
07356      * The replacement text of any entity referred to directly or
07357      * indirectly in an attribute value (other than "&lt;") must
07358      * not contain a <. 
07359      */
07360     else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
07361          (ent != NULL) && (ent->content != NULL) &&
07362          (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
07363          (xmlStrchr(ent->content, '<'))) {
07364     xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
07365     "'<' in entity '%s' is not allowed in attributes values\n", name);
07366     }
07367 
07368     /*
07369      * Internal check, no parameter entities here ...
07370      */
07371     else {
07372     switch (ent->etype) {
07373         case XML_INTERNAL_PARAMETER_ENTITY:
07374         case XML_EXTERNAL_PARAMETER_ENTITY:
07375         xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
07376          "Attempt to reference the parameter entity '%s'\n",
07377                   name);
07378         break;
07379         default:
07380         break;
07381     }
07382     }
07383 
07384     /*
07385      * [ WFC: No Recursion ]
07386      * A parsed entity must not contain a recursive reference
07387      * to itself, either directly or indirectly. 
07388      * Done somewhere else
07389      */
07390     return(ent);
07391 }
07392 
07424 static xmlEntityPtr
07425 xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
07426     xmlChar *name;
07427     const xmlChar *ptr;
07428     xmlChar cur;
07429     xmlEntityPtr ent = NULL;
07430 
07431     if ((str == NULL) || (*str == NULL))
07432         return(NULL);
07433     ptr = *str;
07434     cur = *ptr;
07435     if (cur != '&')
07436     return(NULL);
07437 
07438     ptr++;
07439     name = xmlParseStringName(ctxt, &ptr);
07440     if (name == NULL) {
07441     xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
07442                "xmlParseStringEntityRef: no name\n");
07443     *str = ptr;
07444     return(NULL);
07445     }
07446     if (*ptr != ';') {
07447     xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
07448         xmlFree(name);
07449     *str = ptr;
07450     return(NULL);
07451     }
07452     ptr++;
07453 
07454 
07455     /*
07456      * Predefined entites override any extra definition
07457      */
07458     if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
07459         ent = xmlGetPredefinedEntity(name);
07460         if (ent != NULL) {
07461             xmlFree(name);
07462             *str = ptr;
07463             return(ent);
07464         }
07465     }
07466 
07467     /*
07468      * Increate the number of entity references parsed
07469      */
07470     ctxt->nbentities++;
07471 
07472     /*
07473      * Ask first SAX for entity resolution, otherwise try the
07474      * entities which may have stored in the parser context.
07475      */
07476     if (ctxt->sax != NULL) {
07477     if (ctxt->sax->getEntity != NULL)
07478         ent = ctxt->sax->getEntity(ctxt->userData, name);
07479     if ((ent == NULL) && (ctxt->options & XML_PARSE_OLDSAX))
07480         ent = xmlGetPredefinedEntity(name);
07481     if ((ent == NULL) && (ctxt->userData==ctxt)) {
07482         ent = xmlSAX2GetEntity(ctxt, name);
07483     }
07484     }
07485 
07486     /*
07487      * [ WFC: Entity Declared ]
07488      * In a document without any DTD, a document with only an
07489      * internal DTD subset which contains no parameter entity
07490      * references, or a document with "standalone='yes'", the
07491      * Name given in the entity reference must match that in an
07492      * entity declaration, except that well-formed documents
07493      * need not declare any of the following entities: amp, lt,
07494      * gt, apos, quot.
07495      * The declaration of a parameter entity must precede any
07496      * reference to it.
07497      * Similarly, the declaration of a general entity must
07498      * precede any reference to it which appears in a default
07499      * value in an attribute-list declaration. Note that if
07500      * entities are declared in the external subset or in
07501      * external parameter entities, a non-validating processor
07502      * is not obligated to read and process their declarations;
07503      * for such documents, the rule that an entity must be
07504      * declared is a well-formedness constraint only if
07505      * standalone='yes'. 
07506      */
07507     if (ent == NULL) {
07508     if ((ctxt->standalone == 1) ||
07509         ((ctxt->hasExternalSubset == 0) &&
07510          (ctxt->hasPErefs == 0))) {
07511         xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
07512              "Entity '%s' not defined\n", name);
07513     } else {
07514         xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
07515               "Entity '%s' not defined\n",
07516               name);
07517     }
07518     /* TODO ? check regressions ctxt->valid = 0; */
07519     }
07520 
07521     /*
07522      * [ WFC: Parsed Entity ]
07523      * An entity reference must not contain the name of an
07524      * unparsed entity
07525      */
07526     else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
07527     xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
07528          "Entity reference to unparsed entity %s\n", name);
07529     }
07530 
07531     /*
07532      * [ WFC: No External Entity References ]
07533      * Attribute values cannot contain direct or indirect
07534      * entity references to external entities.
07535      */
07536     else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
07537          (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
07538     xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
07539      "Attribute references external entity '%s'\n", name);
07540     }
07541     /*
07542      * [ WFC: No < in Attribute Values ]
07543      * The replacement text of any entity referred to directly or
07544      * indirectly in an attribute value (other than "&lt;") must
07545      * not contain a <.
07546      */
07547     else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
07548          (ent != NULL) && (ent->content != NULL) &&
07549          (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
07550          (xmlStrchr(ent->content, '<'))) {
07551     xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
07552      "'<' in entity '%s' is not allowed in attributes values\n",
07553               name);
07554     }
07555 
07556     /*
07557      * Internal check, no parameter entities here ...
07558      */
07559     else {
07560     switch (ent->etype) {
07561         case XML_INTERNAL_PARAMETER_ENTITY:
07562         case XML_EXTERNAL_PARAMETER_ENTITY:
07563         xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
07564          "Attempt to reference the parameter entity '%s'\n",
07565                   name);
07566         break;
07567         default:
07568         break;
07569     }
07570     }
07571 
07572     /*
07573      * [ WFC: No Recursion ]
07574      * A parsed entity must not contain a recursive reference
07575      * to itself, either directly or indirectly.
07576      * Done somewhere else
07577      */
07578 
07579     xmlFree(name);
07580     *str = ptr;
07581     return(ent);
07582 }
07583 
07613 void
07614 xmlParsePEReference(xmlParserCtxtPtr ctxt)
07615 {
07616     const xmlChar *name;
07617     xmlEntityPtr entity = NULL;
07618     xmlParserInputPtr input;
07619 
07620     if (RAW != '%')
07621         return;
07622     NEXT;
07623     name = xmlParseName(ctxt);
07624     if (name == NULL) {
07625     xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
07626                "xmlParsePEReference: no name\n");
07627     return;
07628     }
07629     if (RAW != ';') {
07630     xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
07631         return;
07632     }
07633 
07634     NEXT;
07635 
07636     /*
07637      * Increate the number of entity references parsed
07638      */
07639     ctxt->nbentities++;
07640 
07641     /*
07642      * Request the entity from SAX
07643      */
07644     if ((ctxt->sax != NULL) &&
07645     (ctxt->sax->getParameterEntity != NULL))
07646     entity = ctxt->sax->getParameterEntity(ctxt->userData,
07647                            name);
07648     if (entity == NULL) {
07649     /*
07650      * [ WFC: Entity Declared ]
07651      * In a document without any DTD, a document with only an
07652      * internal DTD subset which contains no parameter entity
07653      * references, or a document with "standalone='yes'", ...
07654      * ... The declaration of a parameter entity must precede
07655      * any reference to it...
07656      */
07657     if ((ctxt->standalone == 1) ||
07658         ((ctxt->hasExternalSubset == 0) &&
07659          (ctxt->hasPErefs == 0))) {
07660         xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
07661                   "PEReference: %%%s; not found\n",
07662                   name);
07663     } else {
07664         /*
07665          * [ VC: Entity Declared ]
07666          * In a document with an external subset or external
07667          * parameter entities with "standalone='no'", ...
07668          * ... The declaration of a parameter entity must
07669          * precede any reference to it...
07670          */
07671         xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
07672               "PEReference: %%%s; not found\n",
07673               name, NULL);
07674         ctxt->valid = 0;
07675     }
07676     } else {
07677     /*
07678      * Internal checking in case the entity quest barfed
07679      */
07680     if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
07681         (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
07682         xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
07683           "Internal: %%%s; is not a parameter entity\n",
07684               name, NULL);
07685     } else if (ctxt->input->free != deallocblankswrapper) {
07686         input = xmlNewBlanksWrapperInputStream(ctxt, entity);
07687         if (xmlPushInput(ctxt, input) < 0)
07688         return;
07689     } else {
07690         /*
07691          * TODO !!!
07692          * handle the extra spaces added before and after
07693          * c.f. http://www.w3.org/TR/REC-xml#as-PE
07694          */
07695         input = xmlNewEntityInputStream(ctxt, entity);
07696         if (xmlPushInput(ctxt, input) < 0)
07697         return;
07698         if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
07699         (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
07700         (IS_BLANK_CH(NXT(5)))) {
07701         xmlParseTextDecl(ctxt);
07702         if (ctxt->errNo ==
07703             XML_ERR_UNSUPPORTED_ENCODING) {
07704             /*
07705              * The XML REC instructs us to stop parsing
07706              * right here
07707              */
07708             ctxt->instate = XML_PARSER_EOF;
07709             return;
07710         }
07711         }
07712     }
07713     }
07714     ctxt->hasPErefs = 1;
07715 }
07716 
07728 static int
07729 xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
07730     xmlParserInputPtr input;
07731     xmlBufferPtr buf;
07732     int l, c;
07733     int count = 0;
07734 
07735     if ((ctxt == NULL) || (entity == NULL) ||
07736         ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
07737      (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
07738     (entity->content != NULL)) {
07739     xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
07740                 "xmlLoadEntityContent parameter error");
07741         return(-1);
07742     }
07743 
07744     if (xmlParserDebugEntities)
07745     xmlGenericError(xmlGenericErrorContext,
07746         "Reading %s entity content input\n", entity->name);
07747 
07748     buf = xmlBufferCreate();
07749     if (buf == NULL) {
07750     xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
07751                 "xmlLoadEntityContent parameter error");
07752         return(-1);
07753     }
07754 
07755     input = xmlNewEntityInputStream(ctxt, entity);
07756     if (input == NULL) {
07757     xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
07758                 "xmlLoadEntityContent input error");
07759     xmlBufferFree(buf);
07760         return(-1);
07761     }
07762 
07763     /*
07764      * Push the entity as the current input, read char by char
07765      * saving to the buffer until the end of the entity or an error
07766      */
07767     if (xmlPushInput(ctxt, input) < 0) {
07768         xmlBufferFree(buf);
07769     return(-1);
07770     }
07771 
07772     GROW;
07773     c = CUR_CHAR(l);
07774     while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) &&
07775            (IS_CHAR(c))) {
07776         xmlBufferAdd(buf, ctxt->input->cur, l);
07777     if (count++ > 100) {
07778         count = 0;
07779         GROW;
07780     }
07781     NEXTL(l);
07782     c = CUR_CHAR(l);
07783     }
07784 
07785     if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) {
07786         xmlPopInput(ctxt);
07787     } else if (!IS_CHAR(c)) {
07788         xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
07789                           "xmlLoadEntityContent: invalid char value %d\n",
07790                       c);
07791     xmlBufferFree(buf);
07792     return(-1);
07793     }
07794     entity->content = buf->content;
07795     buf->content = NULL;
07796     xmlBufferFree(buf);
07797 
07798     return(0);
07799 }
07800 
07832 static xmlEntityPtr
07833 xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
07834     const xmlChar *ptr;
07835     xmlChar cur;
07836     xmlChar *name;
07837     xmlEntityPtr entity = NULL;
07838 
07839     if ((str == NULL) || (*str == NULL)) return(NULL);
07840     ptr = *str;
07841     cur = *ptr;
07842     if (cur != '%')
07843         return(NULL);
07844     ptr++;
07845     name = xmlParseStringName(ctxt, &ptr);
07846     if (name == NULL) {
07847     xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
07848                "xmlParseStringPEReference: no name\n");
07849     *str = ptr;
07850     return(NULL);
07851     }
07852     cur = *ptr;
07853     if (cur != ';') {
07854     xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
07855     xmlFree(name);
07856     *str = ptr;
07857     return(NULL);
07858     }
07859     ptr++;
07860 
07861     /*
07862      * Increate the number of entity references parsed
07863      */
07864     ctxt->nbentities++;
07865 
07866     /*
07867      * Request the entity from SAX
07868      */
07869     if ((ctxt->sax != NULL) &&
07870     (ctxt->sax->getParameterEntity != NULL))
07871     entity = ctxt->sax->getParameterEntity(ctxt->userData,
07872                            name);
07873     if (entity == NULL) {
07874     /*
07875      * [ WFC: Entity Declared ]
07876      * In a document without any DTD, a document with only an
07877      * internal DTD subset which contains no parameter entity
07878      * references, or a document with "standalone='yes'", ...
07879      * ... The declaration of a parameter entity must precede
07880      * any reference to it...
07881      */
07882     if ((ctxt->standalone == 1) ||
07883         ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) {
07884         xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
07885          "PEReference: %%%s; not found\n", name);
07886     } else {
07887         /*
07888          * [ VC: Entity Declared ]
07889          * In a document with an external subset or external
07890          * parameter entities with "standalone='no'", ...
07891          * ... The declaration of a parameter entity must
07892          * precede any reference to it...
07893          */
07894         xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
07895               "PEReference: %%%s; not found\n",
07896               name, NULL);
07897         ctxt->valid = 0;
07898     }
07899     } else {
07900     /*
07901      * Internal checking in case the entity quest barfed
07902      */
07903     if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
07904         (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
07905         xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
07906               "%%%s; is not a parameter entity\n",
07907               name, NULL);
07908     }
07909     }
07910     ctxt->hasPErefs = 1;
07911     xmlFree(name);
07912     *str = ptr;
07913     return(entity);
07914 }
07915 
07930 void
07931 xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
07932     const xmlChar *name = NULL;
07933     xmlChar *ExternalID = NULL;
07934     xmlChar *URI = NULL;
07935 
07936     /*
07937      * We know that '<!DOCTYPE' has been detected.
07938      */
07939     SKIP(9);
07940 
07941     SKIP_BLANKS;
07942 
07943     /*
07944      * Parse the DOCTYPE name.
07945      */
07946     name = xmlParseName(ctxt);
07947     if (name == NULL) {
07948     xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
07949                "xmlParseDocTypeDecl : no DOCTYPE name !\n");
07950     }
07951     ctxt->intSubName = name;
07952 
07953     SKIP_BLANKS;
07954 
07955     /*
07956      * Check for SystemID and ExternalID
07957      */
07958     URI = xmlParseExternalID(ctxt, &ExternalID, 1);
07959 
07960     if ((URI != NULL) || (ExternalID != NULL)) {
07961         ctxt->hasExternalSubset = 1;
07962     }
07963     ctxt->extSubURI = URI;
07964     ctxt->extSubSystem = ExternalID;
07965 
07966     SKIP_BLANKS;
07967 
07968     /*
07969      * Create and update the internal subset.
07970      */
07971     if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
07972     (!ctxt->disableSAX))
07973     ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
07974 
07975     /*
07976      * Is there any internal subset declarations ?
07977      * they are handled separately in xmlParseInternalSubset()
07978      */
07979     if (RAW == '[')
07980     return;
07981 
07982     /*
07983      * We should be at the end of the DOCTYPE declaration.
07984      */
07985     if (RAW != '>') {
07986     xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
07987     }
07988     NEXT;
07989 }
07990 
08000 static void
08001 xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
08002     /*
08003      * Is there any DTD definition ?
08004      */
08005     if (RAW == '[') {
08006         ctxt->instate = XML_PARSER_DTD;
08007         NEXT;
08008     /*
08009      * Parse the succession of Markup declarations and 
08010      * PEReferences.
08011      * Subsequence (markupdecl | PEReference | S)*
08012      */
08013     while (RAW != ']') {
08014         const xmlChar *check = CUR_PTR;
08015         unsigned int cons = ctxt->input->consumed;
08016 
08017         SKIP_BLANKS;
08018         xmlParseMarkupDecl(ctxt);
08019         xmlParsePEReference(ctxt);
08020 
08021         /*
08022          * Pop-up of finished entities.
08023          */
08024         while ((RAW == 0) && (ctxt->inputNr > 1))
08025         xmlPopInput(ctxt);
08026 
08027         if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
08028         xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
08029          "xmlParseInternalSubset: error detected in Markup declaration\n");
08030         break;
08031         }
08032     }
08033     if (RAW == ']') { 
08034         NEXT;
08035         SKIP_BLANKS;
08036     }
08037     }
08038 
08039     /*
08040      * We should be at the end of the DOCTYPE declaration.
08041      */
08042     if (RAW != '>') {
08043     xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
08044     }
08045     NEXT;
08046 }
08047 
08048 #ifdef LIBXML_SAX1_ENABLED
08049 
08082 const xmlChar *
08083 xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
08084     const xmlChar *name;
08085     xmlChar *val;
08086 
08087     *value = NULL;
08088     GROW;
08089     name = xmlParseName(ctxt);
08090     if (name == NULL) {
08091     xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
08092                    "error parsing attribute name\n");
08093         return(NULL);
08094     }
08095 
08096     /*
08097      * read the value
08098      */
08099     SKIP_BLANKS;
08100     if (RAW == '=') {
08101         NEXT;
08102     SKIP_BLANKS;
08103     val = xmlParseAttValue(ctxt);
08104     ctxt->instate = XML_PARSER_CONTENT;
08105     } else {
08106     xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
08107            "Specification mandate value for attribute %s\n", name);
08108     return(NULL);
08109     }
08110 
08111     /*
08112      * Check that xml:lang conforms to the specification
08113      * No more registered as an error, just generate a warning now
08114      * since this was deprecated in XML second edition
08115      */
08116     if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
08117     if (!xmlCheckLanguageID(val)) {
08118         xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
08119                   "Malformed value for xml:lang : %s\n",
08120               val, NULL);
08121     }
08122     }
08123 
08124     /*
08125      * Check that xml:space conforms to the specification
08126      */
08127     if (xmlStrEqual(name, BAD_CAST "xml:space")) {
08128     if (xmlStrEqual(val, BAD_CAST "default"))
08129         *(ctxt->space) = 0;
08130     else if (xmlStrEqual(val, BAD_CAST "preserve"))
08131         *(ctxt->space) = 1;
08132     else {
08133         xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
08134 "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
08135                                  val, NULL);
08136     }
08137     }
08138 
08139     *value = val;
08140     return(name);
08141 }
08142 
08171 const xmlChar *
08172 xmlParseStartTag(xmlParserCtxtPtr ctxt) {
08173     const xmlChar *name;
08174     const xmlChar *attname;
08175     xmlChar *attvalue;
08176     const xmlChar **atts = ctxt->atts;
08177     int nbatts = 0;
08178     int maxatts = ctxt->maxatts;
08179     int i;
08180 
08181     if (RAW != '<') return(NULL);
08182     NEXT1;
08183 
08184     name = xmlParseName(ctxt);
08185     if (name == NULL) {
08186     xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
08187          "xmlParseStartTag: invalid element name\n");
08188         return(NULL);
08189     }
08190 
08191     /*
08192      * Now parse the attributes, it ends up with the ending
08193      *
08194      * (S Attribute)* S?
08195      */
08196     SKIP_BLANKS;
08197     GROW;
08198 
08199     while ((RAW != '>') && 
08200        ((RAW != '/') || (NXT(1) != '>')) &&
08201        (IS_BYTE_CHAR(RAW))) {
08202     const xmlChar *q = CUR_PTR;
08203     unsigned int cons = ctxt->input->consumed;
08204 
08205     attname = xmlParseAttribute(ctxt, &attvalue);
08206         if ((attname != NULL) && (attvalue != NULL)) {
08207         /*
08208          * [ WFC: Unique Att Spec ]
08209          * No attribute name may appear more than once in the same
08210          * start-tag or empty-element tag. 
08211          */
08212         for (i = 0; i < nbatts;i += 2) {
08213             if (xmlStrEqual(atts[i], attname)) {
08214             xmlErrAttributeDup(ctxt, NULL, attname);
08215             xmlFree(attvalue);
08216             goto failed;
08217         }
08218         }
08219         /*
08220          * Add the pair to atts
08221          */
08222         if (atts == NULL) {
08223             maxatts = 22; /* allow for 10 attrs by default */
08224             atts = (const xmlChar **)
08225                xmlMalloc(maxatts * sizeof(xmlChar *));
08226         if (atts == NULL) {
08227             xmlErrMemory(ctxt, NULL);
08228             if (attvalue != NULL)
08229             xmlFree(attvalue);
08230             goto failed;
08231         }
08232         ctxt->atts = atts;
08233         ctxt->maxatts = maxatts;
08234         } else if (nbatts + 4 > maxatts) {
08235             const xmlChar **n;
08236 
08237             maxatts *= 2;
08238             n = (const xmlChar **) xmlRealloc((void *) atts,
08239                          maxatts * sizeof(const xmlChar *));
08240         if (n == NULL) {
08241             xmlErrMemory(ctxt, NULL);
08242             if (attvalue != NULL)
08243             xmlFree(attvalue);
08244             goto failed;
08245         }
08246         atts = n;
08247         ctxt->atts = atts;
08248         ctxt->maxatts = maxatts;
08249         }
08250         atts[nbatts++] = attname;
08251         atts[nbatts++] = attvalue;
08252         atts[nbatts] = NULL;
08253         atts[nbatts + 1] = NULL;
08254     } else {
08255         if (attvalue != NULL)
08256         xmlFree(attvalue);
08257     }
08258 
08259 failed:     
08260 
08261     GROW
08262     if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
08263         break;
08264     if (!IS_BLANK_CH(RAW)) {
08265         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
08266                "attributes construct error\n");
08267     }
08268     SKIP_BLANKS;
08269         if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
08270             (attname == NULL) && (attvalue == NULL)) {
08271         xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
08272                "xmlParseStartTag: problem parsing attributes\n");
08273         break;
08274     }
08275     SHRINK;
08276         GROW;
08277     }
08278 
08279     /*
08280      * SAX: Start of Element !
08281      */
08282     if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
08283     (!ctxt->disableSAX)) {
08284     if (nbatts > 0)
08285         ctxt->sax->startElement(ctxt->userData, name, atts);
08286     else
08287         ctxt->sax->startElement(ctxt->userData, name, NULL);
08288     }
08289 
08290     if (atts != NULL) {
08291         /* Free only the content strings */
08292         for (i = 1;i < nbatts;i+=2)
08293         if (atts[i] != NULL)
08294            xmlFree((xmlChar *) atts[i]);
08295     }
08296     return(name);
08297 }
08298 
08314 static void
08315 xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
08316     const xmlChar *name;
08317 
08318     GROW;
08319     if ((RAW != '<') || (NXT(1) != '/')) {
08320     xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED,
08321                "xmlParseEndTag: '</' not found\n");
08322     return;
08323     }
08324     SKIP(2);
08325 
08326     name = xmlParseNameAndCompare(ctxt,ctxt->name);
08327 
08328     /*
08329      * We should definitely be at the ending "S? '>'" part
08330      */
08331     GROW;
08332     SKIP_BLANKS;
08333     if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
08334     xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
08335     } else
08336     NEXT1;
08337 
08338     /*
08339      * [ WFC: Element Type Match ]
08340      * The Name in an element's end-tag must match the element type in the
08341      * start-tag. 
08342      *
08343      */
08344     if (name != (xmlChar*)1) {
08345         if (name == NULL) name = BAD_CAST "unparseable";
08346         xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
08347              "Opening and ending tag mismatch: %s line %d and %s\n",
08348                         ctxt->name, line, name);
08349     }
08350 
08351     /*
08352      * SAX: End of Tag
08353      */
08354     if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
08355     (!ctxt->disableSAX))
08356         ctxt->sax->endElement(ctxt->userData, ctxt->name);
08357 
08358     namePop(ctxt);
08359     spacePop(ctxt);
08360     return;
08361 }
08362 
08376 void
08377 xmlParseEndTag(xmlParserCtxtPtr ctxt) {
08378     xmlParseEndTag1(ctxt, 0);
08379 }
08380 #endif /* LIBXML_SAX1_ENABLED */
08381 
08382 /************************************************************************
08383  *                                  *
08384  *            SAX 2 specific operations             *
08385  *                                  *
08386  ************************************************************************/
08387 
08388 /*
08389  * xmlGetNamespace:
08390  * @ctxt:  an XML parser context
08391  * @prefix:  the prefix to lookup
08392  *
08393  * Lookup the namespace name for the @prefix (which ca be NULL)
08394  * The prefix must come from the @ctxt->dict dictionnary
08395  *
08396  * Returns the namespace name or NULL if not bound
08397  */
08398 static const xmlChar *
08399 xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
08400     int i;
08401 
08402     if (prefix == ctxt->str_xml) return(ctxt->str_xml_ns);
08403     for (i = ctxt->nsNr - 2;i >= 0;i-=2)
08404         if (ctxt->nsTab[i] == prefix) {
08405         if ((prefix == NULL) && (*ctxt->nsTab[i + 1] == 0))
08406             return(NULL);
08407         return(ctxt->nsTab[i + 1]);
08408     }
08409     return(NULL);
08410 }
08411 
08426 static const xmlChar *
08427 xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
08428     const xmlChar *l, *p;
08429 
08430     GROW;
08431 
08432     l = xmlParseNCName(ctxt);
08433     if (l == NULL) {
08434         if (CUR == ':') {
08435         l = xmlParseName(ctxt);
08436         if (l != NULL) {
08437             xmlNsErr(ctxt, XML_NS_ERR_QNAME, 
08438                  "Failed to parse QName '%s'\n", l, NULL, NULL);
08439         *prefix = NULL;
08440         return(l);
08441         }
08442     }
08443         return(NULL);
08444     }
08445     if (CUR == ':') {
08446         NEXT;
08447     p = l;
08448     l = xmlParseNCName(ctxt);
08449     if (l == NULL) {
08450         xmlChar *tmp;
08451 
08452             xmlNsErr(ctxt, XML_NS_ERR_QNAME,
08453                  "Failed to parse QName '%s:'\n", p, NULL, NULL);
08454         l = xmlParseNmtoken(ctxt);
08455         if (l == NULL)
08456         tmp = xmlBuildQName(BAD_CAST "", p, NULL, 0);
08457         else {
08458         tmp = xmlBuildQName(l, p, NULL, 0);
08459         xmlFree((char *)l);
08460         }
08461         p = xmlDictLookup(ctxt->dict, tmp, -1);
08462         if (tmp != NULL) xmlFree(tmp);
08463         *prefix = NULL;
08464         return(p);
08465     }
08466     if (CUR == ':') {
08467         xmlChar *tmp;
08468 
08469             xmlNsErr(ctxt, XML_NS_ERR_QNAME,
08470                  "Failed to parse QName '%s:%s:'\n", p, l, NULL);
08471         NEXT;
08472         tmp = (xmlChar *) xmlParseName(ctxt);
08473         if (tmp != NULL) {
08474             tmp = xmlBuildQName(tmp, l, NULL, 0);
08475         l = xmlDictLookup(ctxt->dict, tmp, -1);
08476         if (tmp != NULL) xmlFree(tmp);
08477         *prefix = p;
08478         return(l);
08479         }
08480         tmp = xmlBuildQName(BAD_CAST "", l, NULL, 0);
08481         l = xmlDictLookup(ctxt->dict, tmp, -1);
08482         if (tmp != NULL) xmlFree(tmp);
08483         *prefix = p;
08484         return(l);
08485     }
08486     *prefix = p;
08487     } else
08488         *prefix = NULL;
08489     return(l);
08490 }
08491 
08505 static const xmlChar *
08506 xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
08507                         xmlChar const *prefix) {
08508     const xmlChar *cmp;
08509     const xmlChar *in;
08510     const xmlChar *ret;
08511     const xmlChar *prefix2;
08512 
08513     if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name));
08514 
08515     GROW;
08516     in = ctxt->input->cur;
08517 
08518     cmp = prefix;
08519     while (*in != 0 && *in == *cmp) {
08520         ++in;
08521     ++cmp;
08522     }
08523     if ((*cmp == 0) && (*in == ':')) {
08524         in++;
08525     cmp = name;
08526     while (*in != 0 && *in == *cmp) {
08527         ++in;
08528         ++cmp;
08529     }
08530     if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
08531         /* success */
08532         ctxt->input->cur = in;
08533         return((const xmlChar*) 1);
08534     }
08535     }
08536     /*
08537      * all strings coms from the dictionary, equality can be done directly
08538      */
08539     ret = xmlParseQName (ctxt, &prefix2);
08540     if ((ret == name) && (prefix == prefix2))
08541     return((const xmlChar*) 1);
08542     return ret;
08543 }
08544 
08579 static xmlChar *
08580 xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
08581                          int normalize)
08582 {
08583     xmlChar limit = 0;
08584     const xmlChar *in = NULL, *start, *end, *last;
08585     xmlChar *ret = NULL;
08586 
08587     GROW;
08588     in = (xmlChar *) CUR_PTR;
08589     if (*in != '"' && *in != '\'') {
08590         xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
08591         return (NULL);
08592     }
08593     ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
08594 
08595     /*
08596      * try to handle in this routine the most common case where no
08597      * allocation of a new string is required and where content is
08598      * pure ASCII.
08599      */
08600     limit = *in++;
08601     end = ctxt->input->end;
08602     start = in;
08603     if (in >= end) {
08604         const xmlChar *oldbase = ctxt->input->base;
08605     GROW;
08606     if (oldbase != ctxt->input->base) {
08607         long delta = ctxt->input->base - oldbase;
08608         start = start + delta;
08609         in = in + delta;
08610     }
08611     end = ctxt->input->end;
08612     }
08613     if (normalize) {
08614         /*
08615      * Skip any leading spaces
08616      */
08617     while ((in < end) && (*in != limit) && 
08618            ((*in == 0x20) || (*in == 0x9) ||
08619             (*in == 0xA) || (*in == 0xD))) {
08620         in++;
08621         start = in;
08622         if (in >= end) {
08623         const xmlChar *oldbase = ctxt->input->base;
08624         GROW;
08625         if (oldbase != ctxt->input->base) {
08626             long delta = ctxt->input->base - oldbase;
08627             start = start + delta;
08628             in = in + delta;
08629         }
08630         end = ctxt->input->end;
08631         }
08632     }
08633     while ((in < end) && (*in != limit) && (*in >= 0x20) &&
08634            (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
08635         if ((*in++ == 0x20) && (*in == 0x20)) break;
08636         if (in >= end) {
08637         const xmlChar *oldbase = ctxt->input->base;
08638         GROW;
08639         if (oldbase != ctxt->input->base) {
08640             long delta = ctxt->input->base - oldbase;
08641             start = start + delta;
08642             in = in + delta;
08643         }
08644         end = ctxt->input->end;
08645         }
08646     }
08647     last = in;
08648     /*
08649      * skip the trailing blanks
08650      */
08651     while ((last[-1] == 0x20) && (last > start)) last--;
08652     while ((in < end) && (*in != limit) && 
08653            ((*in == 0x20) || (*in == 0x9) ||
08654             (*in == 0xA) || (*in == 0xD))) {
08655         in++;
08656         if (in >= end) {
08657         const xmlChar *oldbase = ctxt->input->base;
08658         GROW;
08659         if (oldbase != ctxt->input->base) {
08660             long delta = ctxt->input->base - oldbase;
08661             start = start + delta;
08662             in = in + delta;
08663             last = last + delta;
08664         }
08665         end = ctxt->input->end;
08666         }
08667     }
08668     if (*in != limit) goto need_complex;
08669     } else {
08670     while ((in < end) && (*in != limit) && (*in >= 0x20) &&
08671            (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
08672         in++;
08673         if (in >= end) {
08674         const xmlChar *oldbase = ctxt->input->base;
08675         GROW;
08676         if (oldbase != ctxt->input->base) {
08677             long delta = ctxt->input->base - oldbase;
08678             start = start + delta;
08679             in = in + delta;
08680         }
08681         end = ctxt->input->end;
08682         }
08683     }
08684     last = in;
08685     if (*in != limit) goto need_complex;
08686     }
08687     in++;
08688     if (len != NULL) {
08689         *len = last - start;
08690         ret = (xmlChar *) start;
08691     } else {
08692         if (alloc) *alloc = 1;
08693         ret = xmlStrndup(start, last - start);
08694     }
08695     CUR_PTR = in;
08696     if (alloc) *alloc = 0;
08697     return ret;
08698 need_complex:
08699     if (alloc) *alloc = 1;
08700     return xmlParseAttValueComplex(ctxt, len, normalize);
08701 }
08702 
08718 static const xmlChar *
08719 xmlParseAttribute2(xmlParserCtxtPtr ctxt,
08720                    const xmlChar * pref, const xmlChar * elem,
08721                    const xmlChar ** prefix, xmlChar ** value,
08722                    int *len, int *alloc)
08723 {
08724     const xmlChar *name;
08725     xmlChar *val, *internal_val = NULL;
08726     int normalize = 0;
08727 
08728     *value = NULL;
08729     GROW;
08730     name = xmlParseQName(ctxt, prefix);
08731     if (name == NULL) {
08732         xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
08733                        "error parsing attribute name\n");
08734         return (NULL);
08735     }
08736 
08737     /*
08738      * get the type if needed
08739      */
08740     if (ctxt->attsSpecial != NULL) {
08741         int type;
08742 
08743         type = (int) (long) xmlHashQLookup2(ctxt->attsSpecial,
08744                                             pref, elem, *prefix, name);
08745         if (type != 0)
08746             normalize = 1;
08747     }
08748 
08749     /*
08750      * read the value
08751      */
08752     SKIP_BLANKS;
08753     if (RAW == '=') {
08754         NEXT;
08755         SKIP_BLANKS;
08756         val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
08757     if (normalize) {
08758         /*
08759          * Sometimes a second normalisation pass for spaces is needed
08760          * but that only happens if charrefs or entities refernces
08761          * have been used in the attribute value, i.e. the attribute
08762          * value have been extracted in an allocated string already.
08763          */
08764         if (*alloc) {
08765             const xmlChar *val2;
08766 
08767             val2 = xmlAttrNormalizeSpace2(ctxt, val, len);
08768         if ((val2 != NULL) && (val2 != val)) {
08769             xmlFree(val);
08770             val = (xmlChar *) val2;
08771         }
08772         }
08773     }
08774         ctxt->instate = XML_PARSER_CONTENT;
08775     } else {
08776         xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
08777                           "Specification mandate value for attribute %s\n",
08778                           name);
08779         return (NULL);
08780     }
08781 
08782     if (*prefix == ctxt->str_xml) {
08783         /*
08784          * Check that xml:lang conforms to the specification
08785          * No more registered as an error, just generate a warning now
08786          * since this was deprecated in XML second edition
08787          */
08788         if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
08789             internal_val = xmlStrndup(val, *len);
08790             if (!xmlCheckLanguageID(internal_val)) {
08791                 xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
08792                               "Malformed value for xml:lang : %s\n",
08793                               internal_val, NULL);
08794             }
08795         }
08796 
08797         /*
08798          * Check that xml:space conforms to the specification
08799          */
08800         if (xmlStrEqual(name, BAD_CAST "space")) {
08801             internal_val = xmlStrndup(val, *len);
08802             if (xmlStrEqual(internal_val, BAD_CAST "default"))
08803                 *(ctxt->space) = 0;
08804             else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
08805                 *(ctxt->space) = 1;
08806             else {
08807                 xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
08808                               "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
08809                               internal_val, NULL);
08810             }
08811         }
08812         if (internal_val) {
08813             xmlFree(internal_val);
08814         }
08815     }
08816 
08817     *value = val;
08818     return (name);
08819 }
08849 static const xmlChar *
08850 xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
08851                   const xmlChar **URI, int *tlen) {
08852     const xmlChar *localname;
08853     const xmlChar *prefix;
08854     const xmlChar *attname;
08855     const xmlChar *aprefix;
08856     const xmlChar *nsname;
08857     xmlChar *attvalue;
08858     const xmlChar **atts = ctxt->atts;
08859     int maxatts = ctxt->maxatts;
08860     int nratts, nbatts, nbdef;
08861     int i, j, nbNs, attval, oldline, oldcol;
08862     const xmlChar *base;
08863     unsigned long cur;
08864     int nsNr = ctxt->nsNr;
08865 
08866     if (RAW != '<') return(NULL);
08867     NEXT1;
08868 
08869     /*
08870      * NOTE: it is crucial with the SAX2 API to never call SHRINK beyond that
08871      *       point since the attribute values may be stored as pointers to
08872      *       the buffer and calling SHRINK would destroy them !
08873      *       The Shrinking is only possible once the full set of attribute
08874      *       callbacks have been done.
08875      */
08876 reparse:
08877     SHRINK;
08878     base = ctxt->input->base;
08879     cur = ctxt->input->cur - ctxt->input->base;
08880     oldline = ctxt->input->line;
08881     oldcol = ctxt->input->col;
08882     nbatts = 0;
08883     nratts = 0;
08884     nbdef = 0;
08885     nbNs = 0;
08886     attval = 0;
08887     /* Forget any namespaces added during an earlier parse of this element. */
08888     ctxt->nsNr = nsNr;
08889 
08890     localname = xmlParseQName(ctxt, &prefix);
08891     if (localname == NULL) {
08892     xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
08893                "StartTag: invalid element name\n");
08894         return(NULL);
08895     }
08896     *tlen = ctxt->input->cur - ctxt->input->base - cur;
08897 
08898     /*
08899      * Now parse the attributes, it ends up with the ending
08900      *
08901      * (S Attribute)* S?
08902      */
08903     SKIP_BLANKS;
08904     GROW;
08905     if (ctxt->input->base != base) goto base_changed;
08906 
08907     while ((RAW != '>') && 
08908        ((RAW != '/') || (NXT(1) != '>')) &&
08909        (IS_BYTE_CHAR(RAW))) {
08910     const xmlChar *q = CUR_PTR;
08911     unsigned int cons = ctxt->input->consumed;
08912     int len = -1, alloc = 0;
08913 
08914     attname = xmlParseAttribute2(ctxt, prefix, localname,
08915                                  &aprefix, &attvalue, &len, &alloc);
08916     if (ctxt->input->base != base) {
08917         if ((attvalue != NULL) && (alloc != 0))
08918             xmlFree(attvalue);
08919         attvalue = NULL;
08920         goto base_changed;
08921     }
08922         if ((attname != NULL) && (attvalue != NULL)) {
08923         if (len < 0) len = xmlStrlen(attvalue);
08924             if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
08925             const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
08926         xmlURIPtr uri;
08927 
08928                 if (*URL != 0) {
08929             uri = xmlParseURI((const char *) URL);
08930             if (uri == NULL) {
08931             xmlNsErr(ctxt, XML_WAR_NS_URI,
08932                      "xmlns: '%s' is not a valid URI\n",
08933                        URL, NULL, NULL);
08934             } else {
08935             if (uri->scheme == NULL) {
08936                 xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
08937                       "xmlns: URI %s is not absolute\n",
08938                       URL, NULL, NULL);
08939             }
08940             xmlFreeURI(uri);
08941             }
08942             if (URL == ctxt->str_xml_ns) {
08943             if (attname != ctxt->str_xml) {
08944                 xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
08945              "xml namespace URI cannot be the default namespace\n",
08946                      NULL, NULL, NULL);
08947             }
08948             goto skip_default_ns;
08949             }
08950             if ((len == 29) &&
08951             (xmlStrEqual(URL,
08952                  BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
08953             xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
08954                  "reuse of the xmlns namespace name is forbidden\n",
08955                  NULL, NULL, NULL);
08956             goto skip_default_ns;
08957             }
08958         }
08959         /*
08960          * check that it's not a defined namespace
08961          */
08962         for (j = 1;j <= nbNs;j++)
08963             if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
08964             break;
08965         if (j <= nbNs)
08966             xmlErrAttributeDup(ctxt, NULL, attname);
08967         else
08968             if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
08969 skip_default_ns:
08970         if (alloc != 0) xmlFree(attvalue);
08971         SKIP_BLANKS;
08972         continue;
08973         }
08974             if (aprefix == ctxt->str_xmlns) {
08975             const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
08976         xmlURIPtr uri;
08977 
08978                 if (attname == ctxt->str_xml) {
08979             if (URL != ctxt->str_xml_ns) {
08980                 xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
08981                      "xml namespace prefix mapped to wrong URI\n",
08982                      NULL, NULL, NULL);
08983             }
08984             /*
08985              * Do not keep a namespace definition node
08986              */
08987             goto skip_ns;
08988         }
08989                 if (URL == ctxt->str_xml_ns) {
08990             if (attname != ctxt->str_xml) {
08991                 xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
08992                      "xml namespace URI mapped to wrong prefix\n",
08993                      NULL, NULL, NULL);
08994             }
08995             goto skip_ns;
08996         }
08997                 if (attname == ctxt->str_xmlns) {
08998             xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
08999                  "redefinition of the xmlns prefix is forbidden\n",
09000                  NULL, NULL, NULL);
09001             goto skip_ns;
09002         }
09003         if ((len == 29) &&
09004             (xmlStrEqual(URL,
09005                          BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
09006             xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
09007                  "reuse of the xmlns namespace name is forbidden\n",
09008                  NULL, NULL, NULL);
09009             goto skip_ns;
09010         }
09011         if ((URL == NULL) || (URL[0] == 0)) {
09012             xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
09013                      "xmlns:%s: Empty XML namespace is not allowed\n",
09014                       attname, NULL, NULL);
09015             goto skip_ns;
09016         } else {
09017             uri = xmlParseURI((const char *) URL);
09018             if (uri == NULL) {
09019             xmlNsErr(ctxt, XML_WAR_NS_URI,
09020                  "xmlns:%s: '%s' is not a valid URI\n",
09021                        attname, URL, NULL);
09022             } else {
09023             if ((ctxt->pedantic) && (uri->scheme == NULL)) {
09024                 xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
09025                       "xmlns:%s: URI %s is not absolute\n",
09026                       attname, URL, NULL);
09027             }
09028             xmlFreeURI(uri);
09029             }
09030         }
09031 
09032         /*
09033          * check that it's not a defined namespace
09034          */
09035         for (j = 1;j <= nbNs;j++)
09036             if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
09037             break;
09038         if (j <= nbNs)
09039             xmlErrAttributeDup(ctxt, aprefix, attname);
09040         else
09041             if (nsPush(ctxt, attname, URL) > 0) nbNs++;
09042 skip_ns:
09043         if (alloc != 0) xmlFree(attvalue);
09044         SKIP_BLANKS;
09045         if (ctxt->input->base != base) goto base_changed;
09046         continue;
09047         }
09048 
09049         /*
09050          * Add the pair to atts
09051          */
09052         if ((atts == NULL) || (nbatts + 5 > maxatts)) {
09053             if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
09054             if (attvalue[len] == 0)
09055             xmlFree(attvalue);
09056             goto failed;
09057         }
09058             maxatts = ctxt->maxatts;
09059         atts = ctxt->atts;
09060         }
09061         ctxt->attallocs[nratts++] = alloc;
09062         atts[nbatts++] = attname;
09063         atts[nbatts++] = aprefix;
09064         atts[nbatts++] = NULL; /* the URI will be fetched later */
09065         atts[nbatts++] = attvalue;
09066         attvalue += len;
09067         atts[nbatts++] = attvalue;
09068         /*
09069          * tag if some deallocation is needed
09070          */
09071         if (alloc != 0) attval = 1;
09072     } else {
09073         if ((attvalue != NULL) && (attvalue[len] == 0))
09074         xmlFree(attvalue);
09075     }
09076 
09077 failed:
09078 
09079     GROW
09080     if (ctxt->input->base != base) goto base_changed;
09081     if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
09082         break;
09083     if (!IS_BLANK_CH(RAW)) {
09084         xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
09085                "attributes construct error\n");
09086         break;
09087     }
09088     SKIP_BLANKS;
09089         if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
09090             (attname == NULL) && (attvalue == NULL)) {
09091         xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
09092              "xmlParseStartTag: problem parsing attributes\n");
09093         break;
09094     }
09095         GROW;
09096     if (ctxt->input->base != base) goto base_changed;
09097     }
09098 
09099     /*
09100      * The attributes defaulting
09101      */
09102     if (ctxt->attsDefault != NULL) {
09103         xmlDefAttrsPtr defaults;
09104 
09105     defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
09106     if (defaults != NULL) {
09107         for (i = 0;i < defaults->nbAttrs;i++) {
09108             attname = defaults->values[5 * i];
09109         aprefix = defaults->values[5 * i + 1];
09110 
09111                 /*
09112          * special work for namespaces defaulted defs
09113          */
09114         if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
09115             /*
09116              * check that it's not a defined namespace
09117              */
09118             for (j = 1;j <= nbNs;j++)
09119                 if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
09120                 break;
09121                 if (j <= nbNs) continue;
09122 
09123             nsname = xmlGetNamespace(ctxt, NULL);
09124             if (nsname != defaults->values[5 * i + 2]) {
09125             if (nsPush(ctxt, NULL,
09126                        defaults->values[5 * i + 2]) > 0)
09127                 nbNs++;
09128             }
09129         } else if (aprefix == ctxt->str_xmlns) {
09130             /*
09131              * check that it's not a defined namespace
09132              */
09133             for (j = 1;j <= nbNs;j++)
09134                 if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
09135                 break;
09136                 if (j <= nbNs) continue;
09137 
09138             nsname = xmlGetNamespace(ctxt, attname);
09139             if (nsname != defaults->values[2]) {
09140             if (nsPush(ctxt, attname,
09141                        defaults->values[5 * i + 2]) > 0)
09142                 nbNs++;
09143             }
09144         } else {
09145             /*
09146              * check that it's not a defined attribute
09147              */
09148             for (j = 0;j < nbatts;j+=5) {
09149             if ((attname == atts[j]) && (aprefix == atts[j+1]))
09150                 break;
09151             }
09152             if (j < nbatts) continue;
09153 
09154             if ((atts == NULL) || (nbatts + 5 > maxatts)) {
09155             if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
09156                 return(NULL);
09157             }
09158             maxatts = ctxt->maxatts;
09159             atts = ctxt->atts;
09160             }
09161             atts[nbatts++] = attname;
09162             atts[nbatts++] = aprefix;
09163             if (aprefix == NULL)
09164             atts[nbatts++] = NULL;
09165             else
09166                 atts[nbatts++] = xmlGetNamespace(ctxt, aprefix);
09167             atts[nbatts++] = defaults->values[5 * i + 2];
09168             atts[nbatts++] = defaults->values[5 * i + 3];
09169             if ((ctxt->standalone == 1) &&
09170                 (defaults->values[5 * i + 4] != NULL)) {
09171             xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED, 
09172       "standalone: attribute %s on %s defaulted from external subset\n",
09173                                      attname, localname);
09174             }
09175             nbdef++;
09176         }
09177         }
09178     }
09179     }
09180 
09181     /*
09182      * The attributes checkings
09183      */
09184     for (i = 0; i < nbatts;i += 5) {
09185         /*
09186     * The default namespace does not apply to attribute names.
09187     */
09188     if (atts[i + 1] != NULL) {
09189         nsname = xmlGetNamespace(ctxt, atts[i + 1]);
09190         if (nsname == NULL) {
09191         xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
09192             "Namespace prefix %s for %s on %s is not defined\n",
09193             atts[i + 1], atts[i], localname);
09194         }
09195         atts[i + 2] = nsname;
09196     } else
09197         nsname = NULL;
09198     /*
09199      * [ WFC: Unique Att Spec ]
09200      * No attribute name may appear more than once in the same
09201      * start-tag or empty-element tag. 
09202      * As extended by the Namespace in XML REC.
09203      */
09204         for (j = 0; j < i;j += 5) {
09205         if (atts[i] == atts[j]) {
09206             if (atts[i+1] == atts[j+1]) {
09207             xmlErrAttributeDup(ctxt, atts[i+1], atts[i]);
09208             break;
09209         }
09210         if ((nsname != NULL) && (atts[j + 2] == nsname)) {
09211             xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
09212                  "Namespaced Attribute %s in '%s' redefined\n",
09213                  atts[i], nsname, NULL);
09214             break;
09215         }
09216         }
09217     }
09218     }
09219 
09220     nsname = xmlGetNamespace(ctxt, prefix);
09221     if ((prefix != NULL) && (nsname == NULL)) {
09222     xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
09223              "Namespace prefix %s on %s is not defined\n",
09224          prefix, localname, NULL);
09225     }
09226     *pref = prefix;
09227     *URI = nsname;
09228 
09229     /*
09230      * SAX: Start of Element !
09231      */
09232     if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
09233     (!ctxt->disableSAX)) {
09234     if (nbNs > 0)
09235         ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
09236               nsname, nbNs, &ctxt->nsTab[ctxt->nsNr - 2 * nbNs],
09237               nbatts / 5, nbdef, atts);
09238     else
09239         ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
09240                       nsname, 0, NULL, nbatts / 5, nbdef, atts);
09241     }
09242 
09243     /*
09244      * Free up attribute allocated strings if needed
09245      */
09246     if (attval != 0) {
09247     for (i = 3,j = 0; j < nratts;i += 5,j++)
09248         if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
09249             xmlFree((xmlChar *) atts[i]);
09250     }
09251 
09252     return(localname);
09253 
09254 base_changed:
09255     /*
09256      * the attribute strings are valid iif the base didn't changed
09257      */
09258     if (attval != 0) {
09259     for (i = 3,j = 0; j < nratts;i += 5,j++)
09260         if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
09261             xmlFree((xmlChar *) atts[i]);
09262     }
09263     ctxt->input->cur = ctxt->input->base + cur;
09264     ctxt->input->line = oldline;
09265     ctxt->input->col = oldcol;
09266     if (ctxt->wellFormed == 1) {
09267     goto reparse;
09268     }
09269     return(NULL);
09270 }
09271 
09287 static void
09288 xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
09289                 const xmlChar *URI, int line, int nsNr, int tlen) {
09290     const xmlChar *name;
09291 
09292     GROW;
09293     if ((RAW != '<') || (NXT(1) != '/')) {
09294     xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL);
09295     return;
09296     }
09297     SKIP(2);
09298 
09299     if ((tlen > 0) && (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
09300         if (ctxt->input->cur[tlen] == '>') {
09301         ctxt->input->cur += tlen + 1;
09302         goto done;
09303     }
09304     ctxt->input->cur += tlen;
09305     name = (xmlChar*)1;
09306     } else {
09307     if (prefix == NULL)
09308         name = xmlParseNameAndCompare(ctxt, ctxt->name);
09309     else
09310         name = xmlParseQNameAndCompare(ctxt, ctxt->name, prefix);
09311     }
09312 
09313     /*
09314      * We should definitely be at the ending "S? '>'" part
09315      */
09316     GROW;
09317     SKIP_BLANKS;
09318     if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
09319     xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
09320     } else
09321     NEXT1;
09322 
09323     /*
09324      * [ WFC: Element Type Match ]
09325      * The Name in an element's end-tag must match the element type in the
09326      * start-tag. 
09327      *
09328      */
09329     if (name != (xmlChar*)1) {
09330         if (name == NULL) name = BAD_CAST "unparseable";
09331         if ((line == 0) && (ctxt->node != NULL))
09332             line = ctxt->node->line;
09333         xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
09334              "Opening and ending tag mismatch: %s line %d and %s\n",
09335                         ctxt->name, line, name);
09336     }
09337 
09338     /*
09339      * SAX: End of Tag
09340      */
09341 done:
09342     if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
09343     (!ctxt->disableSAX))
09344     ctxt->sax->endElementNs(ctxt->userData, ctxt->name, prefix, URI);
09345 
09346     spacePop(ctxt);
09347     if (nsNr != 0)
09348     nsPop(ctxt, nsNr);
09349     return;
09350 }
09351 
09366 void
09367 xmlParseCDSect(xmlParserCtxtPtr ctxt) {
09368     xmlChar *buf = NULL;
09369     int len = 0;
09370     int size = XML_PARSER_BUFFER_SIZE;
09371     int r, rl;
09372     int s, sl;
09373     int cur, l;
09374     int count = 0;
09375 
09376     /* Check 2.6.0 was NXT(0) not RAW */
09377     if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
09378     SKIP(9);
09379     } else
09380         return;
09381 
09382     ctxt->instate = XML_PARSER_CDATA_SECTION;
09383     r = CUR_CHAR(rl);
09384     if (!IS_CHAR(r)) {
09385     xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
09386     ctxt->instate = XML_PARSER_CONTENT;
09387         return;
09388     }
09389     NEXTL(rl);
09390     s = CUR_CHAR(sl);
09391     if (!IS_CHAR(s)) {
09392     xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
09393     ctxt->instate = XML_PARSER_CONTENT;
09394         return;
09395     }
09396     NEXTL(sl);
09397     cur = CUR_CHAR(l);
09398     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
09399     if (buf == NULL) {
09400     xmlErrMemory(ctxt, NULL);
09401     return;
09402     }
09403     while (IS_CHAR(cur) &&
09404            ((r != ']') || (s != ']') || (cur != '>'))) {
09405     if (len + 5 >= size) {
09406         xmlChar *tmp;
09407 
09408         size *= 2;
09409         tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
09410         if (tmp == NULL) {
09411             xmlFree(buf);
09412         xmlErrMemory(ctxt, NULL);
09413         return;
09414         }
09415         buf = tmp;
09416     }
09417     COPY_BUF(rl,buf,len,r);
09418     r = s;
09419     rl = sl;
09420     s = cur;
09421     sl = l;
09422     count++;
09423     if (count > 50) {
09424         GROW;
09425         count = 0;
09426     }
09427     NEXTL(l);
09428     cur = CUR_CHAR(l);
09429     }
09430     buf[len] = 0;
09431     ctxt->instate = XML_PARSER_CONTENT;
09432     if (cur != '>') {
09433     xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
09434                          "CData section not finished\n%.50s\n", buf);
09435     xmlFree(buf);
09436         return;
09437     }
09438     NEXTL(l);
09439 
09440     /*
09441      * OK the buffer is to be consumed as cdata.
09442      */
09443     if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
09444     if (ctxt->sax->cdataBlock != NULL)
09445         ctxt->sax->cdataBlock(ctxt->userData, buf, len);
09446     else if (ctxt->sax->characters != NULL)
09447         ctxt->sax->characters(ctxt->userData, buf, len);
09448     }
09449     xmlFree(buf);
09450 }
09451 
09461 void
09462 xmlParseContent(xmlParserCtxtPtr ctxt) {
09463     GROW;
09464     while ((RAW != 0) &&
09465        ((RAW != '<') || (NXT(1) != '/')) &&
09466        (ctxt->instate != XML_PARSER_EOF)) {
09467     const xmlChar *test = CUR_PTR;
09468     unsigned int cons = ctxt->input->consumed;
09469     const xmlChar *cur = ctxt->input->cur;
09470 
09471     /*
09472      * First case : a Processing Instruction.
09473      */
09474     if ((*cur == '<') && (cur[1] == '?')) {
09475         xmlParsePI(ctxt);
09476     }
09477 
09478     /*
09479      * Second case : a CDSection
09480      */
09481     /* 2.6.0 test was *cur not RAW */
09482     else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
09483         xmlParseCDSect(ctxt);
09484     }
09485 
09486     /*
09487      * Third case :  a comment
09488      */
09489     else if ((*cur == '<') && (NXT(1) == '!') &&
09490          (NXT(2) == '-') && (NXT(3) == '-')) {
09491         xmlParseComment(ctxt);
09492         ctxt->instate = XML_PARSER_CONTENT;
09493     }
09494 
09495     /*
09496      * Fourth case :  a sub-element.
09497      */
09498     else if (*cur == '<') {
09499         xmlParseElement(ctxt);
09500     }
09501 
09502     /*
09503      * Fifth case : a reference. If if has not been resolved,
09504      *    parsing returns it's Name, create the node 
09505      */
09506 
09507     else if (*cur == '&') {
09508         xmlParseReference(ctxt);
09509     }
09510 
09511     /*
09512      * Last case, text. Note that References are handled directly.
09513      */
09514     else {
09515         xmlParseCharData(ctxt, 0);
09516     }
09517 
09518     GROW;
09519     /*
09520      * Pop-up of finished entities.
09521      */
09522     while ((RAW == 0) && (ctxt->inputNr > 1))
09523         xmlPopInput(ctxt);
09524     SHRINK;
09525 
09526     if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
09527         xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
09528                     "detected an error in element content\n");
09529         ctxt->instate = XML_PARSER_EOF;
09530             break;
09531     }
09532     }
09533 }
09534 
09549 void
09550 xmlParseElement(xmlParserCtxtPtr ctxt) {
09551     const xmlChar *name;
09552     const xmlChar *prefix = NULL;
09553     const xmlChar *URI = NULL;
09554     xmlParserNodeInfo node_info;
09555     int line, tlen;
09556     xmlNodePtr ret;
09557     int nsNr = ctxt->nsNr;
09558 
09559     if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) &&
09560         ((ctxt->options & XML_PARSE_HUGE) == 0)) {
09561     xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
09562          "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
09563               xmlParserMaxDepth);
09564     ctxt->instate = XML_PARSER_EOF;
09565     return;
09566     }
09567 
09568     /* Capture start position */
09569     if (ctxt->record_info) {
09570         node_info.begin_pos = ctxt->input->consumed +
09571                           (CUR_PTR - ctxt->input->base);
09572     node_info.begin_line = ctxt->input->line;
09573     }
09574 
09575     if (ctxt->spaceNr == 0)
09576     spacePush(ctxt, -1);
09577     else if (*ctxt->space == -2)
09578     spacePush(ctxt, -1);
09579     else
09580     spacePush(ctxt, *ctxt->space);
09581 
09582     line = ctxt->input->line;
09583 #ifdef LIBXML_SAX1_ENABLED
09584     if (ctxt->sax2)
09585 #endif /* LIBXML_SAX1_ENABLED */
09586         name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
09587 #ifdef LIBXML_SAX1_ENABLED
09588     else
09589     name = xmlParseStartTag(ctxt);
09590 #endif /* LIBXML_SAX1_ENABLED */
09591     if (name == NULL) {
09592     spacePop(ctxt);
09593         return;
09594     }
09595     namePush(ctxt, name);
09596     ret = ctxt->node;
09597 
09598 #ifdef LIBXML_VALID_ENABLED
09599     /*
09600      * [ VC: Root Element Type ]
09601      * The Name in the document type declaration must match the element
09602      * type of the root element. 
09603      */
09604     if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
09605         ctxt->node && (ctxt->node == ctxt->myDoc->children))
09606         ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
09607 #endif /* LIBXML_VALID_ENABLED */
09608 
09609     /*
09610      * Check for an Empty Element.
09611      */
09612     if ((RAW == '/') && (NXT(1) == '>')) {
09613         SKIP(2);
09614     if (ctxt->sax2) {
09615         if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
09616         (!ctxt->disableSAX))
09617         ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI);
09618 #ifdef LIBXML_SAX1_ENABLED
09619     } else {
09620         if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
09621         (!ctxt->disableSAX))
09622         ctxt->sax->endElement(ctxt->userData, name);
09623 #endif /* LIBXML_SAX1_ENABLED */
09624     }
09625     namePop(ctxt);
09626     spacePop(ctxt);
09627     if (nsNr != ctxt->nsNr)
09628         nsPop(ctxt, ctxt->nsNr - nsNr);
09629     if ( ret != NULL && ctxt->record_info ) {
09630        node_info.end_pos = ctxt->input->consumed +
09631                   (CUR_PTR - ctxt->input->base);
09632        node_info.end_line = ctxt->input->line;
09633        node_info.node = ret;
09634        xmlParserAddNodeInfo(ctxt, &node_info);
09635     }
09636     return;
09637     }
09638     if (RAW == '>') {
09639         NEXT1;
09640     } else {
09641         xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
09642              "Couldn't find end of Start Tag %s line %d\n",
09643                         name, line, NULL);
09644 
09645     /*
09646      * end of parsing of this node.
09647      */
09648     nodePop(ctxt);
09649     namePop(ctxt);
09650     spacePop(ctxt);
09651     if (nsNr != ctxt->nsNr)
09652         nsPop(ctxt, ctxt->nsNr - nsNr);
09653 
09654     /*
09655      * Capture end position and add node
09656      */
09657     if ( ret != NULL && ctxt->record_info ) {
09658        node_info.end_pos = ctxt->input->consumed +
09659                   (CUR_PTR - ctxt->input->base);
09660        node_info.end_line = ctxt->input->line;
09661        node_info.node = ret;
09662        xmlParserAddNodeInfo(ctxt, &node_info);
09663     }
09664     return;
09665     }
09666 
09667     /*
09668      * Parse the content of the element:
09669      */
09670     xmlParseContent(ctxt);
09671     if (!IS_BYTE_CHAR(RAW)) {
09672         xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
09673      "Premature end of data in tag %s line %d\n",
09674                         name, line, NULL);
09675 
09676     /*
09677      * end of parsing of this node.
09678      */
09679     nodePop(ctxt);
09680     namePop(ctxt);
09681     spacePop(ctxt);
09682     if (nsNr != ctxt->nsNr)
09683         nsPop(ctxt, ctxt->nsNr - nsNr);
09684     return;
09685     }
09686 
09687     /*
09688      * parse the end of tag: '</' should be here.
09689      */
09690     if (ctxt->sax2) {
09691     xmlParseEndTag2(ctxt, prefix, URI, line, ctxt->nsNr - nsNr, tlen);
09692     namePop(ctxt);
09693     }
09694 #ifdef LIBXML_SAX1_ENABLED
09695       else
09696     xmlParseEndTag1(ctxt, line);
09697 #endif /* LIBXML_SAX1_ENABLED */
09698 
09699     /*
09700      * Capture end position and add node
09701      */
09702     if ( ret != NULL && ctxt->record_info ) {
09703        node_info.end_pos = ctxt->input->consumed +
09704                           (CUR_PTR - ctxt->input->base);
09705        node_info.end_line = ctxt->input->line;
09706        node_info.node = ret;
09707        xmlParserAddNodeInfo(ctxt, &node_info);
09708     }
09709 }
09710 
09723 xmlChar *
09724 xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
09725     xmlChar *buf = NULL;
09726     int len = 0;
09727     int size = 10;
09728     xmlChar cur;
09729 
09730     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
09731     if (buf == NULL) {
09732     xmlErrMemory(ctxt, NULL);
09733     return(NULL);
09734     }
09735     cur = CUR;
09736     if (!((cur >= '0') && (cur <= '9'))) {
09737     xmlFree(buf);
09738     return(NULL);
09739     }
09740     buf[len++] = cur;
09741     NEXT;
09742     cur=CUR;
09743     if (cur != '.') {
09744     xmlFree(buf);
09745     return(NULL);
09746     }
09747     buf[len++] = cur;
09748     NEXT;
09749     cur=CUR;
09750     while ((cur >= '0') && (cur <= '9')) {
09751     if (len + 1 >= size) {
09752         xmlChar *tmp;
09753 
09754         size *= 2;
09755         tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
09756         if (tmp == NULL) {
09757             xmlFree(buf);
09758         xmlErrMemory(ctxt, NULL);
09759         return(NULL);
09760         }
09761         buf = tmp;
09762     }
09763     buf[len++] = cur;
09764     NEXT;
09765     cur=CUR;
09766     }
09767     buf[len] = 0;
09768     return(buf);
09769 }
09770 
09784 xmlChar *
09785 xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
09786     xmlChar *version = NULL;
09787 
09788     if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
09789     SKIP(7);
09790     SKIP_BLANKS;
09791     if (RAW != '=') {
09792         xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
09793         return(NULL);
09794         }
09795     NEXT;
09796     SKIP_BLANKS;
09797     if (RAW == '"') {
09798         NEXT;
09799         version = xmlParseVersionNum(ctxt);
09800         if (RAW != '"') {
09801         xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
09802         } else
09803             NEXT;
09804     } else if (RAW == '\''){
09805         NEXT;
09806         version = xmlParseVersionNum(ctxt);
09807         if (RAW != '\'') {
09808         xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
09809         } else
09810             NEXT;
09811     } else {
09812         xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
09813     }
09814     }
09815     return(version);
09816 }
09817 
09828 xmlChar *
09829 xmlParseEncName(xmlParserCtxtPtr ctxt) {
09830     xmlChar *buf = NULL;
09831     int len = 0;
09832     int size = 10;
09833     xmlChar cur;
09834 
09835     cur = CUR;
09836     if (((cur >= 'a') && (cur <= 'z')) ||
09837         ((cur >= 'A') && (cur <= 'Z'))) {
09838     buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
09839     if (buf == NULL) {
09840         xmlErrMemory(ctxt, NULL);
09841         return(NULL);
09842     }
09843 
09844     buf[len++] = cur;
09845     NEXT;
09846     cur = CUR;
09847     while (((cur >= 'a') && (cur <= 'z')) ||
09848            ((cur >= 'A') && (cur <= 'Z')) ||
09849            ((cur >= '0') && (cur <= '9')) ||
09850            (cur == '.') || (cur == '_') ||
09851            (cur == '-')) {
09852         if (len + 1 >= size) {
09853             xmlChar *tmp;
09854 
09855         size *= 2;
09856         tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
09857         if (tmp == NULL) {
09858             xmlErrMemory(ctxt, NULL);
09859             xmlFree(buf);
09860             return(NULL);
09861         }
09862         buf = tmp;
09863         }
09864         buf[len++] = cur;
09865         NEXT;
09866         cur = CUR;
09867         if (cur == 0) {
09868             SHRINK;
09869         GROW;
09870         cur = CUR;
09871         }
09872         }
09873     buf[len] = 0;
09874     } else {
09875     xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL);
09876     }
09877     return(buf);
09878 }
09879 
09893 const xmlChar *
09894 xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
09895     xmlChar *encoding = NULL;
09896 
09897     SKIP_BLANKS;
09898     if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) {
09899     SKIP(8);
09900     SKIP_BLANKS;
09901     if (RAW != '=') {
09902         xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
09903         return(NULL);
09904         }
09905     NEXT;
09906     SKIP_BLANKS;
09907     if (RAW == '"') {
09908         NEXT;
09909         encoding = xmlParseEncName(ctxt);
09910         if (RAW != '"') {
09911         xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
09912         } else
09913             NEXT;
09914     } else if (RAW == '\''){
09915         NEXT;
09916         encoding = xmlParseEncName(ctxt);
09917         if (RAW != '\'') {
09918         xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
09919         } else
09920             NEXT;
09921     } else {
09922         xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
09923     }
09924     /*
09925      * UTF-16 encoding stwich has already taken place at this stage,
09926      * more over the little-endian/big-endian selection is already done
09927      */
09928         if ((encoding != NULL) &&
09929         ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) ||
09930          (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) {
09931         /*
09932          * If no encoding was passed to the parser, that we are
09933          * using UTF-16 and no decoder is present i.e. the 
09934          * document is apparently UTF-8 compatible, then raise an
09935          * encoding mismatch fatal error
09936          */
09937         if ((ctxt->encoding == NULL) &&
09938             (ctxt->input->buf != NULL) &&
09939             (ctxt->input->buf->encoder == NULL)) {
09940         xmlFatalErrMsg(ctxt, XML_ERR_INVALID_ENCODING,
09941           "Document labelled UTF-16 but has UTF-8 content\n");
09942         }
09943         if (ctxt->encoding != NULL)
09944         xmlFree((xmlChar *) ctxt->encoding);
09945         ctxt->encoding = encoding;
09946     }
09947     /*
09948      * UTF-8 encoding is handled natively
09949      */
09950         else if ((encoding != NULL) &&
09951         ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) ||
09952          (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) {
09953         if (ctxt->encoding != NULL)
09954         xmlFree((xmlChar *) ctxt->encoding);
09955         ctxt->encoding = encoding;
09956     }
09957     else if (encoding != NULL) {
09958         xmlCharEncodingHandlerPtr handler;
09959 
09960         if (ctxt->input->encoding != NULL)
09961         xmlFree((xmlChar *) ctxt->input->encoding);
09962         ctxt->input->encoding = encoding;
09963 
09964             handler = xmlFindCharEncodingHandler((const char *) encoding);
09965         if (handler != NULL) {
09966         xmlSwitchToEncoding(ctxt, handler);
09967         } else {
09968         xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
09969             "Unsupported encoding %s\n", encoding);
09970         return(NULL);
09971         }
09972     }
09973     }
09974     return(encoding);
09975 }
09976 
10008 int
10009 xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
10010     int standalone = -2;
10011 
10012     SKIP_BLANKS;
10013     if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) {
10014     SKIP(10);
10015         SKIP_BLANKS;
10016     if (RAW != '=') {
10017         xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10018         return(standalone);
10019         }
10020     NEXT;
10021     SKIP_BLANKS;
10022         if (RAW == '\''){
10023         NEXT;
10024         if ((RAW == 'n') && (NXT(1) == 'o')) {
10025             standalone = 0;
10026                 SKIP(2);
10027         } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10028                    (NXT(2) == 's')) {
10029             standalone = 1;
10030         SKIP(3);
10031             } else {
10032         xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10033         }
10034         if (RAW != '\'') {
10035         xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10036         } else
10037             NEXT;
10038     } else if (RAW == '"'){
10039         NEXT;
10040         if ((RAW == 'n') && (NXT(1) == 'o')) {
10041             standalone = 0;
10042         SKIP(2);
10043         } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10044                    (NXT(2) == 's')) {
10045             standalone = 1;
10046                 SKIP(3);
10047             } else {
10048         xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10049         }
10050         if (RAW != '"') {
10051         xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10052         } else
10053             NEXT;
10054     } else {
10055         xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10056         }
10057     }
10058     return(standalone);
10059 }
10060 
10070 void
10071 xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
10072     xmlChar *version;
10073 
10074     /*
10075      * This value for standalone indicates that the document has an
10076      * XML declaration but it does not have a standalone attribute.
10077      * It will be overwritten later if a standalone attribute is found.
10078      */
10079     ctxt->input->standalone = -2;
10080 
10081     /*
10082      * We know that '<?xml' is here.
10083      */
10084     SKIP(5);
10085 
10086     if (!IS_BLANK_CH(RAW)) {
10087     xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
10088                    "Blank needed after '<?xml'\n");
10089     }
10090     SKIP_BLANKS;
10091 
10092     /*
10093      * We must have the VersionInfo here.
10094      */
10095     version = xmlParseVersionInfo(ctxt);
10096     if (version == NULL) {
10097     xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL);
10098     } else {
10099     if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
10100         /*
10101          * Changed here for XML-1.0 5th edition
10102          */
10103         if (ctxt->options & XML_PARSE_OLD10) {
10104         xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10105                       "Unsupported version '%s'\n",
10106                       version);
10107         } else {
10108             if ((version[0] == '1') && ((version[1] == '.'))) {
10109             xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION,
10110                           "Unsupported version '%s'\n",
10111                   version, NULL);
10112         } else {
10113             xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10114                       "Unsupported version '%s'\n",
10115                       version);
10116         }
10117         }
10118     }
10119     if (ctxt->version != NULL)
10120         xmlFree((void *) ctxt->version);
10121     ctxt->version = version;
10122     }
10123 
10124     /*
10125      * We may have the encoding declaration
10126      */
10127     if (!IS_BLANK_CH(RAW)) {
10128         if ((RAW == '?') && (NXT(1) == '>')) {
10129         SKIP(2);
10130         return;
10131     }
10132     xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10133     }
10134     xmlParseEncodingDecl(ctxt);
10135     if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
10136     /*
10137      * The XML REC instructs us to stop parsing right here
10138      */
10139         return;
10140     }
10141 
10142     /*
10143      * We may have the standalone status.
10144      */
10145     if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
10146         if ((RAW == '?') && (NXT(1) == '>')) {
10147         SKIP(2);
10148         return;
10149     }
10150     xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10151     }
10152 
10153     /*
10154      * We can grow the input buffer freely at that point
10155      */
10156     GROW;
10157 
10158     SKIP_BLANKS;
10159     ctxt->input->standalone = xmlParseSDDecl(ctxt);
10160 
10161     SKIP_BLANKS;
10162     if ((RAW == '?') && (NXT(1) == '>')) {
10163         SKIP(2);
10164     } else if (RAW == '>') {
10165         /* Deprecated old WD ... */
10166     xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10167     NEXT;
10168     } else {
10169     xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10170     MOVETO_ENDTAG(CUR_PTR);
10171     NEXT;
10172     }
10173 }
10174 
10184 void
10185 xmlParseMisc(xmlParserCtxtPtr ctxt) {
10186     while (((RAW == '<') && (NXT(1) == '?')) ||
10187            (CMP4(CUR_PTR, '<', '!', '-', '-')) ||
10188            IS_BLANK_CH(CUR)) {
10189         if ((RAW == '<') && (NXT(1) == '?')) {
10190         xmlParsePI(ctxt);
10191     } else if (IS_BLANK_CH(CUR)) {
10192         NEXT;
10193     } else
10194         xmlParseComment(ctxt);
10195     }
10196 }
10197 
10213 int
10214 xmlParseDocument(xmlParserCtxtPtr ctxt) {
10215     xmlChar start[4];
10216     xmlCharEncoding enc;
10217 
10218     xmlInitParser();
10219 
10220     if ((ctxt == NULL) || (ctxt->input == NULL))
10221         return(-1);
10222 
10223     GROW;
10224 
10225     /*
10226      * SAX: detecting the level.
10227      */
10228     xmlDetectSAX2(ctxt);
10229 
10230     /*
10231      * SAX: beginning of the document processing.
10232      */
10233     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10234         ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
10235 
10236     if ((ctxt->encoding == NULL) &&
10237         ((ctxt->input->end - ctxt->input->cur) >= 4)) {
10238     /* 
10239      * Get the 4 first bytes and decode the charset
10240      * if enc != XML_CHAR_ENCODING_NONE
10241      * plug some encoding conversion routines.
10242      */
10243     start[0] = RAW;
10244     start[1] = NXT(1);
10245     start[2] = NXT(2);
10246     start[3] = NXT(3);
10247     enc = xmlDetectCharEncoding(&start[0], 4);
10248     if (enc != XML_CHAR_ENCODING_NONE) {
10249         xmlSwitchEncoding(ctxt, enc);
10250     }
10251     }
10252 
10253 
10254     if (CUR == 0) {
10255     xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10256     }
10257 
10258     /*
10259      * Check for the XMLDecl in the Prolog.
10260      * do not GROW here to avoid the detected encoder to decode more
10261      * than just the first line, unless the amount of data is really
10262      * too small to hold "<?xml version="1.0" encoding="foo"
10263      */
10264     if ((ctxt->input->end - ctxt->input->cur) < 35) {
10265        GROW;
10266     }
10267     if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
10268 
10269     /*
10270      * Note that we will switch encoding on the fly.
10271      */
10272     xmlParseXMLDecl(ctxt);
10273     if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
10274         /*
10275          * The XML REC instructs us to stop parsing right here
10276          */
10277         return(-1);
10278     }
10279     ctxt->standalone = ctxt->input->standalone;
10280     SKIP_BLANKS;
10281     } else {
10282     ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10283     }
10284     if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
10285         ctxt->sax->startDocument(ctxt->userData);
10286 
10287     /*
10288      * The Misc part of the Prolog
10289      */
10290     GROW;
10291     xmlParseMisc(ctxt);
10292 
10293     /*
10294      * Then possibly doc type declaration(s) and more Misc
10295      * (doctypedecl Misc*)?
10296      */
10297     GROW;
10298     if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) {
10299 
10300     ctxt->inSubset = 1;
10301     xmlParseDocTypeDecl(ctxt);
10302     if (RAW == '[') {
10303         ctxt->instate = XML_PARSER_DTD;
10304         xmlParseInternalSubset(ctxt);
10305     }
10306 
10307     /*
10308      * Create and update the external subset.
10309      */
10310     ctxt->inSubset = 2;
10311     if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
10312         (!ctxt->disableSAX))
10313         ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
10314                                   ctxt->extSubSystem, ctxt->extSubURI);
10315     ctxt->inSubset = 0;
10316 
10317         xmlCleanSpecialAttr(ctxt);
10318 
10319     ctxt->instate = XML_PARSER_PROLOG;
10320     xmlParseMisc(ctxt);
10321     }
10322 
10323     /*
10324      * Time to start parsing the tree itself
10325      */
10326     GROW;
10327     if (RAW != '<') {
10328     xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
10329                "Start tag expected, '<' not found\n");
10330     } else {
10331     ctxt->instate = XML_PARSER_CONTENT;
10332     xmlParseElement(ctxt);
10333     ctxt->instate = XML_PARSER_EPILOG;
10334 
10335 
10336     /*
10337      * The Misc part at the end
10338      */
10339     xmlParseMisc(ctxt);
10340 
10341     if (RAW != 0) {
10342         xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
10343     }
10344     ctxt->instate = XML_PARSER_EOF;
10345     }
10346 
10347     /*
10348      * SAX: end of the document processing.
10349      */
10350     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10351         ctxt->sax->endDocument(ctxt->userData);
10352 
10353     /*
10354      * Remove locally kept entity definitions if the tree was not built
10355      */
10356     if ((ctxt->myDoc != NULL) &&
10357     (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
10358     xmlFreeDoc(ctxt->myDoc);
10359     ctxt->myDoc = NULL;
10360     }
10361 
10362     if ((ctxt->wellFormed) && (ctxt->myDoc != NULL)) {
10363         ctxt->myDoc->properties |= XML_DOC_WELLFORMED;
10364     if (ctxt->valid)
10365         ctxt->myDoc->properties |= XML_DOC_DTDVALID;
10366     if (ctxt->nsWellFormed)
10367         ctxt->myDoc->properties |= XML_DOC_NSVALID;
10368     if (ctxt->options & XML_PARSE_OLD10)
10369         ctxt->myDoc->properties |= XML_DOC_OLD10;
10370     }
10371     if (! ctxt->wellFormed) {
10372     ctxt->valid = 0;
10373     return(-1);
10374     }
10375     return(0);
10376 }
10377 
10392 int
10393 xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
10394     xmlChar start[4];
10395     xmlCharEncoding enc;
10396 
10397     if ((ctxt == NULL) || (ctxt->input == NULL))
10398         return(-1);
10399 
10400     xmlDefaultSAXHandlerInit();
10401 
10402     xmlDetectSAX2(ctxt);
10403 
10404     GROW;
10405 
10406     /*
10407      * SAX: beginning of the document processing.
10408      */
10409     if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10410         ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
10411 
10412     /* 
10413      * Get the 4 first bytes and decode the charset
10414      * if enc != XML_CHAR_ENCODING_NONE
10415      * plug some encoding conversion routines.
10416      */
10417     if ((ctxt->input->end - ctxt->input->cur) >= 4) {
10418     start[0] = RAW;
10419     start[1] = NXT(1);
10420     start[2] = NXT(2);
10421     start[3] = NXT(3);
10422     enc = xmlDetectCharEncoding(start, 4);
10423     if (enc != XML_CHAR_ENCODING_NONE) {
10424         xmlSwitchEncoding(ctxt, enc);
10425     }
10426     }
10427 
10428 
10429     if (CUR == 0) {
10430     xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10431     }
10432 
10433     /*
10434      * Check for the XMLDecl in the Prolog.
10435      */
10436     GROW;
10437     if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
10438 
10439     /*
10440      * Note that we will switch encoding on the fly.
10441      */
10442     xmlParseXMLDecl(ctxt);
10443     if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
10444         /*
10445          * The XML REC instructs us to stop parsing right here
10446          */
10447         return(-1);
10448     }
10449     SKIP_BLANKS;
10450     } else {
10451     ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10452     }
10453     if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
10454         ctxt->sax->startDocument(ctxt->userData);
10455 
10456     /*
10457      * Doing validity checking on chunk doesn't make sense
10458      */
10459     ctxt->instate = XML_PARSER_CONTENT;
10460     ctxt->validate = 0;
10461     ctxt->loadsubset = 0;
10462     ctxt->depth = 0;
10463 
10464     xmlParseContent(ctxt);
10465    
10466     if ((RAW == '<') && (NXT(1) == '/')) {
10467     xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
10468     } else if (RAW != 0) {
10469     xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
10470     }
10471 
10472     /*
10473      * SAX: end of the document processing.
10474      */
10475     if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10476         ctxt->sax->endDocument(ctxt->userData);
10477 
10478     if (! ctxt->wellFormed) return(-1);
10479     return(0);
10480 }
10481 
10482 #ifdef LIBXML_PUSH_ENABLED
10483 /************************************************************************
10484  *                                  *
10485  *      Progressive parsing interfaces              *
10486  *                                  *
10487  ************************************************************************/
10488 
10505 static int
10506 xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
10507                        xmlChar next, xmlChar third) {
10508     int base, len;
10509     xmlParserInputPtr in;
10510     const xmlChar *buf;
10511 
10512     in = ctxt->input;
10513     if (in == NULL) return(-1);
10514     base = in->cur - in->base;
10515     if (base < 0) return(-1);
10516     if (ctxt->checkIndex > base)
10517         base = ctxt->checkIndex;
10518     if (in->buf == NULL) {
10519     buf = in->base;
10520     len = in->length;
10521     } else {
10522     buf = in->buf->buffer->content;
10523     len = in->buf->buffer->use;
10524     }
10525     /* take into account the sequence length */
10526     if (third) len -= 2;
10527     else if (next) len --;
10528     for (;base < len;base++) {
10529         if (buf[base] == first) {
10530         if (third != 0) {
10531         if ((buf[base + 1] != next) ||
10532             (buf[base + 2] != third)) continue;
10533         } else if (next != 0) {
10534         if (buf[base + 1] != next) continue;
10535         }
10536         ctxt->checkIndex = 0;
10537 #ifdef DEBUG_PUSH
10538         if (next == 0)
10539         xmlGenericError(xmlGenericErrorContext,
10540             "PP: lookup '%c' found at %d\n",
10541             first, base);
10542         else if (third == 0)
10543         xmlGenericError(xmlGenericErrorContext,
10544             "PP: lookup '%c%c' found at %d\n",
10545             first, next, base);
10546         else 
10547         xmlGenericError(xmlGenericErrorContext,
10548             "PP: lookup '%c%c%c' found at %d\n",
10549             first, next, third, base);
10550 #endif
10551         return(base - (in->cur - in->base));
10552     }
10553     }
10554     ctxt->checkIndex = base;
10555 #ifdef DEBUG_PUSH
10556     if (next == 0)
10557     xmlGenericError(xmlGenericErrorContext,
10558         "PP: lookup '%c' failed\n", first);
10559     else if (third == 0)
10560     xmlGenericError(xmlGenericErrorContext,
10561         "PP: lookup '%c%c' failed\n", first, next);
10562     else    
10563     xmlGenericError(xmlGenericErrorContext,
10564         "PP: lookup '%c%c%c' failed\n", first, next, third);
10565 #endif
10566     return(-1);
10567 }
10568 
10577 static void
10578 xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt,
10579                  const xmlChar **lastgt) {
10580     const xmlChar *tmp;
10581 
10582     if ((ctxt == NULL) || (lastlt == NULL) || (lastgt == NULL)) {
10583     xmlGenericError(xmlGenericErrorContext,
10584             "Internal error: xmlParseGetLasts\n");
10585     return;
10586     }
10587     if ((ctxt->progressive != 0) && (ctxt->inputNr == 1)) {
10588         tmp = ctxt->input->end;
10589     tmp--;
10590     while ((tmp >= ctxt->input->base) && (*tmp != '<')) tmp--;
10591     if (tmp < ctxt->input->base) {
10592         *lastlt = NULL;
10593         *lastgt = NULL;
10594     } else {
10595         *lastlt = tmp;
10596         tmp++;
10597         while ((tmp < ctxt->input->end) && (*tmp != '>')) {
10598             if (*tmp == '\'') {
10599             tmp++;
10600             while ((tmp < ctxt->input->end) && (*tmp != '\'')) tmp++;
10601             if (tmp < ctxt->input->end) tmp++;
10602         } else if (*tmp == '"') {
10603             tmp++;
10604             while ((tmp < ctxt->input->end) && (*tmp != '"')) tmp++;
10605             if (tmp < ctxt->input->end) tmp++;
10606         } else
10607             tmp++;
10608         }
10609         if (tmp < ctxt->input->end)
10610             *lastgt = tmp;
10611         else {
10612             tmp = *lastlt;
10613         tmp--;
10614         while ((tmp >= ctxt->input->base) && (*tmp != '>')) tmp--;
10615         if (tmp >= ctxt->input->base)
10616             *lastgt = tmp;
10617         else
10618             *lastgt = NULL;
10619         }
10620     }
10621     } else {
10622         *lastlt = NULL;
10623     *lastgt = NULL;
10624     }
10625 }
10636 static int
10637 xmlCheckCdataPush(const xmlChar *utf, int len) {
10638     int ix;
10639     unsigned char c;
10640     int codepoint;
10641 
10642     if ((utf == NULL) || (len <= 0))
10643         return(0);
10644     
10645     for (ix = 0; ix < len;) {      /* string is 0-terminated */
10646         c = utf[ix];
10647         if ((c & 0x80) == 0x00) {   /* 1-byte code, starts with 10 */
10648         if (c >= 0x20)
10649         ix++;
10650         else if ((c == 0xA) || (c == 0xD) || (c == 0x9))
10651             ix++;
10652         else
10653             return(-ix);
10654     } else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
10655         if (ix + 2 > len) return(ix);
10656         if ((utf[ix+1] & 0xc0 ) != 0x80)
10657             return(-ix);
10658         codepoint = (utf[ix] & 0x1f) << 6;
10659         codepoint |= utf[ix+1] & 0x3f;
10660         if (!xmlIsCharQ(codepoint))
10661             return(-ix);
10662         ix += 2;
10663     } else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
10664         if (ix + 3 > len) return(ix);
10665         if (((utf[ix+1] & 0xc0) != 0x80) ||
10666             ((utf[ix+2] & 0xc0) != 0x80))
10667             return(-ix);
10668         codepoint = (utf[ix] & 0xf) << 12;
10669         codepoint |= (utf[ix+1] & 0x3f) << 6;
10670         codepoint |= utf[ix+2] & 0x3f;
10671         if (!xmlIsCharQ(codepoint))
10672             return(-ix);
10673         ix += 3;
10674     } else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
10675         if (ix + 4 > len) return(ix);
10676         if (((utf[ix+1] & 0xc0) != 0x80) ||
10677             ((utf[ix+2] & 0xc0) != 0x80) ||
10678         ((utf[ix+3] & 0xc0) != 0x80))
10679             return(-ix);
10680         codepoint = (utf[ix] & 0x7) << 18;
10681         codepoint |= (utf[ix+1] & 0x3f) << 12;
10682         codepoint |= (utf[ix+2] & 0x3f) << 6;
10683         codepoint |= utf[ix+3] & 0x3f;
10684         if (!xmlIsCharQ(codepoint))
10685             return(-ix);
10686         ix += 4;
10687     } else              /* unknown encoding */
10688         return(-ix);
10689       }
10690       return(ix);
10691 }
10692 
10702 static int
10703 xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
10704     int ret = 0;
10705     int avail, tlen;
10706     xmlChar cur, next;
10707     const xmlChar *lastlt, *lastgt;
10708 
10709     if (ctxt->input == NULL)
10710         return(0);
10711 
10712 #ifdef DEBUG_PUSH
10713     switch (ctxt->instate) {
10714     case XML_PARSER_EOF:
10715         xmlGenericError(xmlGenericErrorContext,
10716             "PP: try EOF\n"); break;
10717     case XML_PARSER_START:
10718         xmlGenericError(xmlGenericErrorContext,
10719             "PP: try START\n"); break;
10720     case XML_PARSER_MISC:
10721         xmlGenericError(xmlGenericErrorContext,
10722             "PP: try MISC\n");break;
10723     case XML_PARSER_COMMENT:
10724         xmlGenericError(xmlGenericErrorContext,
10725             "PP: try COMMENT\n");break;
10726     case XML_PARSER_PROLOG:
10727         xmlGenericError(xmlGenericErrorContext,
10728             "PP: try PROLOG\n");break;
10729     case XML_PARSER_START_TAG:
10730         xmlGenericError(xmlGenericErrorContext,
10731             "PP: try START_TAG\n");break;
10732     case XML_PARSER_CONTENT:
10733         xmlGenericError(xmlGenericErrorContext,
10734             "PP: try CONTENT\n");break;
10735     case XML_PARSER_CDATA_SECTION:
10736         xmlGenericError(xmlGenericErrorContext,
10737             "PP: try CDATA_SECTION\n");break;
10738     case XML_PARSER_END_TAG:
10739         xmlGenericError(xmlGenericErrorContext,
10740             "PP: try END_TAG\n");break;
10741     case XML_PARSER_ENTITY_DECL:
10742         xmlGenericError(xmlGenericErrorContext,
10743             "PP: try ENTITY_DECL\n");break;
10744     case XML_PARSER_ENTITY_VALUE:
10745         xmlGenericError(xmlGenericErrorContext,
10746             "PP: try ENTITY_VALUE\n");break;
10747     case XML_PARSER_ATTRIBUTE_VALUE:
10748         xmlGenericError(xmlGenericErrorContext,
10749             "PP: try ATTRIBUTE_VALUE\n");break;
10750     case XML_PARSER_DTD:
10751         xmlGenericError(xmlGenericErrorContext,
10752             "PP: try DTD\n");break;
10753     case XML_PARSER_EPILOG:
10754         xmlGenericError(xmlGenericErrorContext,
10755             "PP: try EPILOG\n");break;
10756     case XML_PARSER_PI:
10757         xmlGenericError(xmlGenericErrorContext,
10758             "PP: try PI\n");break;
10759         case XML_PARSER_IGNORE:
10760             xmlGenericError(xmlGenericErrorContext,
10761             "PP: try IGNORE\n");break;
10762     }
10763 #endif
10764 
10765     if ((ctxt->input != NULL) &&
10766         (ctxt->input->cur - ctxt->input->base > 4096)) {
10767     xmlSHRINK(ctxt);
10768     ctxt->checkIndex = 0;
10769     }
10770     xmlParseGetLasts(ctxt, &lastlt, &lastgt);
10771 
10772     while (1) {
10773     if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
10774         return(0);
10775 
10776         
10777     /*
10778      * Pop-up of finished entities.
10779      */
10780     while ((RAW == 0) && (ctxt->inputNr > 1))
10781         xmlPopInput(ctxt);
10782 
10783     if (ctxt->input == NULL) break;
10784     if (ctxt->input->buf == NULL)
10785         avail = ctxt->input->length -
10786                 (ctxt->input->cur - ctxt->input->base);
10787     else {
10788         /*
10789          * If we are operating on converted input, try to flush
10790          * remainng chars to avoid them stalling in the non-converted
10791          * buffer.
10792          */
10793         if ((ctxt->input->buf->raw != NULL) &&
10794         (ctxt->input->buf->raw->use > 0)) {
10795         int base = ctxt->input->base -
10796                    ctxt->input->buf->buffer->content;
10797         int current = ctxt->input->cur - ctxt->input->base;
10798 
10799         xmlParserInputBufferPush(ctxt->input->buf, 0, "");
10800         ctxt->input->base = ctxt->input->buf->buffer->content + base;
10801         ctxt->input->cur = ctxt->input->base + current;
10802         ctxt->input->end =
10803             &ctxt->input->buf->buffer->content[
10804                                ctxt->input->buf->buffer->use];
10805         }
10806         avail = ctxt->input->buf->buffer->use -
10807             (ctxt->input->cur - ctxt->input->base);
10808     }
10809         if (avail < 1)
10810         goto done;
10811         switch (ctxt->instate) {
10812             case XML_PARSER_EOF:
10813             /*
10814          * Document parsing is done !
10815          */
10816             goto done;
10817             case XML_PARSER_START:
10818         if (ctxt->charset == XML_CHAR_ENCODING_NONE) {
10819             xmlChar start[4];
10820             xmlCharEncoding enc;
10821 
10822             /*
10823              * Very first chars read from the document flow.
10824              */
10825             if (avail < 4)
10826             goto done;
10827 
10828             /* 
10829              * Get the 4 first bytes and decode the charset
10830              * if enc != XML_CHAR_ENCODING_NONE
10831              * plug some encoding conversion routines,
10832              * else xmlSwitchEncoding will set to (default)
10833              * UTF8.
10834              */
10835             start[0] = RAW;
10836             start[1] = NXT(1);
10837             start[2] = NXT(2);
10838             start[3] = NXT(3);
10839             enc = xmlDetectCharEncoding(start, 4);
10840             xmlSwitchEncoding(ctxt, enc);
10841             break;
10842         }
10843 
10844         if (avail < 2)
10845             goto done;
10846         cur = ctxt->input->cur[0];
10847         next = ctxt->input->cur[1];
10848         if (cur == 0) {
10849             if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10850             ctxt->sax->setDocumentLocator(ctxt->userData,
10851                               &xmlDefaultSAXLocator);
10852             xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10853             ctxt->instate = XML_PARSER_EOF;
10854 #ifdef DEBUG_PUSH
10855             xmlGenericError(xmlGenericErrorContext,
10856                 "PP: entering EOF\n");
10857 #endif
10858             if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10859             ctxt->sax->endDocument(ctxt->userData);
10860             goto done;
10861         }
10862             if ((cur == '<') && (next == '?')) {
10863             /* PI or XML decl */
10864             if (avail < 5) return(ret);
10865             if ((!terminate) &&
10866                 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
10867             return(ret);
10868             if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10869             ctxt->sax->setDocumentLocator(ctxt->userData,
10870                               &xmlDefaultSAXLocator);
10871             if ((ctxt->input->cur[2] == 'x') &&
10872             (ctxt->input->cur[3] == 'm') &&
10873             (ctxt->input->cur[4] == 'l') &&
10874             (IS_BLANK_CH(ctxt->input->cur[5]))) {
10875             ret += 5;
10876 #ifdef DEBUG_PUSH
10877             xmlGenericError(xmlGenericErrorContext,
10878                 "PP: Parsing XML Decl\n");
10879 #endif
10880             xmlParseXMLDecl(ctxt);
10881             if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
10882                 /*
10883                  * The XML REC instructs us to stop parsing right
10884                  * here
10885                  */
10886                 ctxt->instate = XML_PARSER_EOF;
10887                 return(0);
10888             }
10889             ctxt->standalone = ctxt->input->standalone;
10890             if ((ctxt->encoding == NULL) &&
10891                 (ctxt->input->encoding != NULL))
10892                 ctxt->encoding = xmlStrdup(ctxt->input->encoding);
10893             if ((ctxt->sax) && (ctxt->sax->startDocument) &&
10894                 (!ctxt->disableSAX))
10895                 ctxt->sax->startDocument(ctxt->userData);
10896             ctxt->instate = XML_PARSER_MISC;
10897 #ifdef DEBUG_PUSH
10898             xmlGenericError(xmlGenericErrorContext,
10899                 "PP: entering MISC\n");
10900 #endif
10901             } else {
10902             ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10903             if ((ctxt->sax) && (ctxt->sax->startDocument) &&
10904                 (!ctxt->disableSAX))
10905                 ctxt->sax->startDocument(ctxt->userData);
10906             ctxt->instate = XML_PARSER_MISC;
10907 #ifdef DEBUG_PUSH
10908             xmlGenericError(xmlGenericErrorContext,
10909                 "PP: entering MISC\n");
10910 #endif
10911             }
10912         } else {
10913             if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10914             ctxt->sax->setDocumentLocator(ctxt->userData,
10915                               &xmlDefaultSAXLocator);
10916             ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10917             if (ctxt->version == NULL) {
10918                 xmlErrMemory(ctxt, NULL);
10919             break;
10920             }
10921             if ((ctxt->sax) && (ctxt->sax->startDocument) &&
10922                 (!ctxt->disableSAX))
10923             ctxt->sax->startDocument(ctxt->userData);
10924             ctxt->instate = XML_PARSER_MISC;
10925 #ifdef DEBUG_PUSH
10926             xmlGenericError(xmlGenericErrorContext,
10927                 "PP: entering MISC\n");
10928 #endif
10929         }
10930         break;
10931             case XML_PARSER_START_TAG: {
10932             const xmlChar *name;
10933         const xmlChar *prefix = NULL;
10934         const xmlChar *URI = NULL;
10935         int nsNr = ctxt->nsNr;
10936 
10937         if ((avail < 2) && (ctxt->inputNr == 1))
10938             goto done;
10939         cur = ctxt->input->cur[0];
10940             if (cur != '<') {
10941             xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10942             ctxt->instate = XML_PARSER_EOF;
10943             if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10944             ctxt->sax->endDocument(ctxt->userData);
10945             goto done;
10946         }
10947         if (!terminate) {
10948             if (ctxt->progressive) {
10949                 /* > can be found unescaped in attribute values */
10950                 if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
10951                 goto done;
10952             } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
10953             goto done;
10954             }
10955         }
10956         if (ctxt->spaceNr == 0)
10957             spacePush(ctxt, -1);
10958         else if (*ctxt->space == -2)
10959             spacePush(ctxt, -1);
10960         else
10961             spacePush(ctxt, *ctxt->space);
10962 #ifdef LIBXML_SAX1_ENABLED
10963         if (ctxt->sax2)
10964 #endif /* LIBXML_SAX1_ENABLED */
10965             name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
10966 #ifdef LIBXML_SAX1_ENABLED
10967         else
10968             name = xmlParseStartTag(ctxt);
10969 #endif /* LIBXML_SAX1_ENABLED */
10970         if (name == NULL) {
10971             spacePop(ctxt);
10972             ctxt->instate = XML_PARSER_EOF;
10973             if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10974             ctxt->sax->endDocument(ctxt->userData);
10975             goto done;
10976         }
10977 #ifdef LIBXML_VALID_ENABLED
10978         /*
10979          * [ VC: Root Element Type ]
10980          * The Name in the document type declaration must match
10981          * the element type of the root element. 
10982          */
10983         if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
10984             ctxt->node && (ctxt->node == ctxt->myDoc->children))
10985             ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
10986 #endif /* LIBXML_VALID_ENABLED */
10987 
10988         /*
10989          * Check for an Empty Element.
10990          */
10991         if ((RAW == '/') && (NXT(1) == '>')) {
10992             SKIP(2);
10993 
10994             if (ctxt->sax2) {
10995             if ((ctxt->sax != NULL) &&
10996                 (ctxt->sax->endElementNs != NULL) &&
10997                 (!ctxt->disableSAX))
10998                 ctxt->sax->endElementNs(ctxt->userData, name,
10999                                         prefix, URI);
11000             if (ctxt->nsNr - nsNr > 0)
11001                 nsPop(ctxt, ctxt->nsNr - nsNr);
11002 #ifdef LIBXML_SAX1_ENABLED
11003             } else {
11004             if ((ctxt->sax != NULL) &&
11005                 (ctxt->sax->endElement != NULL) &&
11006                 (!ctxt->disableSAX))
11007                 ctxt->sax->endElement(ctxt->userData, name);
11008 #endif /* LIBXML_SAX1_ENABLED */
11009             }
11010             spacePop(ctxt);
11011             if (ctxt->nameNr == 0) {
11012             ctxt->instate = XML_PARSER_EPILOG;
11013             } else {
11014             ctxt->instate = XML_PARSER_CONTENT;
11015             }
11016             break;
11017         }
11018         if (RAW == '>') {
11019             NEXT;
11020         } else {
11021             xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
11022                      "Couldn't find end of Start Tag %s\n",
11023                      name);
11024             nodePop(ctxt);
11025             spacePop(ctxt);
11026         }
11027         if (ctxt->sax2)
11028             nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
11029 #ifdef LIBXML_SAX1_ENABLED
11030         else
11031             namePush(ctxt, name);
11032 #endif /* LIBXML_SAX1_ENABLED */
11033 
11034         ctxt->instate = XML_PARSER_CONTENT;
11035                 break;
11036         }
11037             case XML_PARSER_CONTENT: {
11038         const xmlChar *test;
11039         unsigned int cons;
11040         if ((avail < 2) && (ctxt->inputNr == 1))
11041             goto done;
11042         cur = ctxt->input->cur[0];
11043         next = ctxt->input->cur[1];
11044 
11045         test = CUR_PTR;
11046             cons = ctxt->input->consumed;
11047         if ((cur == '<') && (next == '/')) {
11048             ctxt->instate = XML_PARSER_END_TAG;
11049             break;
11050             } else if ((cur == '<') && (next == '?')) {
11051             if ((!terminate) &&
11052                 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
11053             goto done;
11054             xmlParsePI(ctxt);
11055         } else if ((cur == '<') && (next != '!')) {
11056             ctxt->instate = XML_PARSER_START_TAG;
11057             break;
11058         } else if ((cur == '<') && (next == '!') &&
11059                    (ctxt->input->cur[2] == '-') &&
11060                (ctxt->input->cur[3] == '-')) {
11061             int term;
11062 
11063                 if (avail < 4)
11064                 goto done;
11065             ctxt->input->cur += 4;
11066             term = xmlParseLookupSequence(ctxt, '-', '-', '>');
11067             ctxt->input->cur -= 4;
11068             if ((!terminate) && (term < 0))
11069             goto done;
11070             xmlParseComment(ctxt);
11071             ctxt->instate = XML_PARSER_CONTENT;
11072         } else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
11073             (ctxt->input->cur[2] == '[') &&
11074             (ctxt->input->cur[3] == 'C') &&
11075             (ctxt->input->cur[4] == 'D') &&
11076             (ctxt->input->cur[5] == 'A') &&
11077             (ctxt->input->cur[6] == 'T') &&
11078             (ctxt->input->cur[7] == 'A') &&
11079             (ctxt->input->cur[8] == '[')) {
11080             SKIP(9);
11081             ctxt->instate = XML_PARSER_CDATA_SECTION;
11082             break;
11083         } else if ((cur == '<') && (next == '!') &&
11084                    (avail < 9)) {
11085             goto done;
11086         } else if (cur == '&') {
11087             if ((!terminate) &&
11088                 (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
11089             goto done;
11090             xmlParseReference(ctxt);
11091         } else {
11092             /* TODO Avoid the extra copy, handle directly !!! */
11093             /*
11094              * Goal of the following test is:
11095              *  - minimize calls to the SAX 'character' callback
11096              *    when they are mergeable
11097              *  - handle an problem for isBlank when we only parse
11098              *    a sequence of blank chars and the next one is
11099              *    not available to check against '<' presence.
11100              *  - tries to homogenize the differences in SAX
11101              *    callbacks between the push and pull versions
11102              *    of the parser.
11103              */
11104             if ((ctxt->inputNr == 1) &&
11105                 (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
11106             if (!terminate) {
11107                 if (ctxt->progressive) {
11108                 if ((lastlt == NULL) ||
11109                     (ctxt->input->cur > lastlt))
11110                     goto done;
11111                 } else if (xmlParseLookupSequence(ctxt,
11112                                                   '<', 0, 0) < 0) {
11113                 goto done;
11114                 }
11115             }
11116                     }
11117             ctxt->checkIndex = 0;
11118             xmlParseCharData(ctxt, 0);
11119         }
11120         /*
11121          * Pop-up of finished entities.
11122          */
11123         while ((RAW == 0) && (ctxt->inputNr > 1))
11124             xmlPopInput(ctxt);
11125         if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
11126             xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
11127                         "detected an error in element content\n");
11128             ctxt->instate = XML_PARSER_EOF;
11129             break;
11130         }
11131         break;
11132         }
11133             case XML_PARSER_END_TAG:
11134         if (avail < 2)
11135             goto done;
11136         if (!terminate) {
11137             if (ctxt->progressive) {
11138                 /* > can be found unescaped in attribute values */
11139                 if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
11140                 goto done;
11141             } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
11142             goto done;
11143             }
11144         }
11145         if (ctxt->sax2) {
11146             xmlParseEndTag2(ctxt,
11147                    (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3],
11148                    (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0,
11149                (int) (long) ctxt->pushTab[ctxt->nameNr * 3 - 1], 0);
11150             nameNsPop(ctxt);
11151         }
11152 #ifdef LIBXML_SAX1_ENABLED
11153           else
11154             xmlParseEndTag1(ctxt, 0);
11155 #endif /* LIBXML_SAX1_ENABLED */
11156         if (ctxt->nameNr == 0) {
11157             ctxt->instate = XML_PARSER_EPILOG;
11158         } else {
11159             ctxt->instate = XML_PARSER_CONTENT;
11160         }
11161         break;
11162             case XML_PARSER_CDATA_SECTION: {
11163             /*
11164          * The Push mode need to have the SAX callback for 
11165          * cdataBlock merge back contiguous callbacks.
11166          */
11167         int base;
11168 
11169         base = xmlParseLookupSequence(ctxt, ']', ']', '>');
11170         if (base < 0) {
11171             if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
11172                 int tmp;
11173 
11174             tmp = xmlCheckCdataPush(ctxt->input->cur, 
11175                                     XML_PARSER_BIG_BUFFER_SIZE);
11176             if (tmp < 0) {
11177                 tmp = -tmp;
11178                 ctxt->input->cur += tmp;
11179                 goto encoding_error;
11180             }
11181             if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
11182                 if (ctxt->sax->cdataBlock != NULL)
11183                 ctxt->sax->cdataBlock(ctxt->userData,
11184                                       ctxt->input->cur, tmp);
11185                 else if (ctxt->sax->characters != NULL)
11186                 ctxt->sax->characters(ctxt->userData,
11187                                       ctxt->input->cur, tmp);
11188             }
11189             SKIPL(tmp);
11190             ctxt->checkIndex = 0;
11191             }
11192             goto done;
11193         } else {
11194             int tmp;
11195 
11196             tmp = xmlCheckCdataPush(ctxt->input->cur, base);
11197             if ((tmp < 0) || (tmp != base)) {
11198             tmp = -tmp;
11199             ctxt->input->cur += tmp;
11200             goto encoding_error;
11201             }
11202             if ((ctxt->sax != NULL) && (base == 0) &&
11203                 (ctxt->sax->cdataBlock != NULL) &&
11204                 (!ctxt->disableSAX)) {
11205             /*
11206              * Special case to provide identical behaviour
11207              * between pull and push parsers on enpty CDATA
11208              * sections
11209              */
11210              if ((ctxt->input->cur - ctxt->input->base >= 9) &&
11211                  (!strncmp((const char *)&ctxt->input->cur[-9],
11212                            "<![CDATA[", 9)))
11213                  ctxt->sax->cdataBlock(ctxt->userData,
11214                                        BAD_CAST "", 0);
11215             } else if ((ctxt->sax != NULL) && (base > 0) &&
11216             (!ctxt->disableSAX)) {
11217             if (ctxt->sax->cdataBlock != NULL)
11218                 ctxt->sax->cdataBlock(ctxt->userData,
11219                           ctxt->input->cur, base);
11220             else if (ctxt->sax->characters != NULL)
11221                 ctxt->sax->characters(ctxt->userData,
11222                           ctxt->input->cur, base);
11223             }
11224             SKIPL(base + 3);
11225             ctxt->checkIndex = 0;
11226             ctxt->instate = XML_PARSER_CONTENT;
11227 #ifdef DEBUG_PUSH
11228             xmlGenericError(xmlGenericErrorContext,
11229                 "PP: entering CONTENT\n");
11230 #endif
11231         }
11232         break;
11233         }
11234             case XML_PARSER_MISC:
11235         SKIP_BLANKS;
11236         if (ctxt->input->buf == NULL)
11237             avail = ctxt->input->length -
11238                     (ctxt->input->cur - ctxt->input->base);
11239         else
11240             avail = ctxt->input->buf->buffer->use -
11241                     (ctxt->input->cur - ctxt->input->base);
11242         if (avail < 2)
11243             goto done;
11244         cur = ctxt->input->cur[0];
11245         next = ctxt->input->cur[1];
11246             if ((cur == '<') && (next == '?')) {
11247             if ((!terminate) &&
11248                 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
11249             goto done;
11250 #ifdef DEBUG_PUSH
11251             xmlGenericError(xmlGenericErrorContext,
11252                 "PP: Parsing PI\n");
11253 #endif
11254             xmlParsePI(ctxt);
11255             ctxt->checkIndex = 0;
11256         } else if ((cur == '<') && (next == '!') &&
11257             (ctxt->input->cur[2] == '-') &&
11258             (ctxt->input->cur[3] == '-')) {
11259             if ((!terminate) &&
11260                 (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
11261             goto done;
11262 #ifdef DEBUG_PUSH
11263             xmlGenericError(xmlGenericErrorContext,
11264                 "PP: Parsing Comment\n");
11265 #endif
11266             xmlParseComment(ctxt);
11267             ctxt->instate = XML_PARSER_MISC;
11268             ctxt->checkIndex = 0;
11269         } else if ((cur == '<') && (next == '!') &&
11270             (ctxt->input->cur[2] == 'D') &&
11271             (ctxt->input->cur[3] == 'O') &&
11272             (ctxt->input->cur[4] == 'C') &&
11273             (ctxt->input->cur[5] == 'T') &&
11274             (ctxt->input->cur[6] == 'Y') &&
11275             (ctxt->input->cur[7] == 'P') &&
11276             (ctxt->input->cur[8] == 'E')) {
11277             if ((!terminate) &&
11278                 (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0))
11279             goto done;
11280 #ifdef DEBUG_PUSH
11281             xmlGenericError(xmlGenericErrorContext,
11282                 "PP: Parsing internal subset\n");
11283 #endif
11284             ctxt->inSubset = 1;
11285             xmlParseDocTypeDecl(ctxt);
11286             if (RAW == '[') {
11287             ctxt->instate = XML_PARSER_DTD;
11288 #ifdef DEBUG_PUSH
11289             xmlGenericError(xmlGenericErrorContext,
11290                 "PP: entering DTD\n");
11291 #endif
11292             } else {
11293             /*
11294              * Create and update the external subset.
11295              */
11296             ctxt->inSubset = 2;
11297             if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
11298                 (ctxt->sax->externalSubset != NULL))
11299                 ctxt->sax->externalSubset(ctxt->userData,
11300                     ctxt->intSubName, ctxt->extSubSystem,
11301                     ctxt->extSubURI);
11302             ctxt->inSubset = 0;
11303             xmlCleanSpecialAttr(ctxt);
11304             ctxt->instate = XML_PARSER_PROLOG;
11305 #ifdef DEBUG_PUSH
11306             xmlGenericError(xmlGenericErrorContext,
11307                 "PP: entering PROLOG\n");
11308 #endif
11309             }
11310         } else if ((cur == '<') && (next == '!') &&
11311                    (avail < 9)) {
11312             goto done;
11313         } else {
11314             ctxt->instate = XML_PARSER_START_TAG;
11315             ctxt->progressive = 1;
11316             xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11317 #ifdef DEBUG_PUSH
11318             xmlGenericError(xmlGenericErrorContext,
11319                 "PP: entering START_TAG\n");
11320 #endif
11321         }
11322         break;
11323             case XML_PARSER_PROLOG:
11324         SKIP_BLANKS;
11325         if (ctxt->input->buf == NULL)
11326             avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
11327         else
11328             avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
11329         if (avail < 2) 
11330             goto done;
11331         cur = ctxt->input->cur[0];
11332         next = ctxt->input->cur[1];
11333             if ((cur == '<') && (next == '?')) {
11334             if ((!terminate) &&
11335                 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
11336             goto done;
11337 #ifdef DEBUG_PUSH
11338             xmlGenericError(xmlGenericErrorContext,
11339                 "PP: Parsing PI\n");
11340 #endif
11341             xmlParsePI(ctxt);
11342         } else if ((cur == '<') && (next == '!') &&
11343             (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
11344             if ((!terminate) &&
11345                 (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
11346             goto done;
11347 #ifdef DEBUG_PUSH
11348             xmlGenericError(xmlGenericErrorContext,
11349                 "PP: Parsing Comment\n");
11350 #endif
11351             xmlParseComment(ctxt);
11352             ctxt->instate = XML_PARSER_PROLOG;
11353         } else if ((cur == '<') && (next == '!') &&
11354                    (avail < 4)) {
11355             goto done;
11356         } else {
11357             ctxt->instate = XML_PARSER_START_TAG;
11358             if (ctxt->progressive == 0)
11359             ctxt->progressive = 1;
11360             xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11361 #ifdef DEBUG_PUSH
11362             xmlGenericError(xmlGenericErrorContext,
11363                 "PP: entering START_TAG\n");
11364 #endif
11365         }
11366         break;
11367             case XML_PARSER_EPILOG:
11368         SKIP_BLANKS;
11369         if (ctxt->input->buf == NULL)
11370             avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
11371         else
11372             avail = ctxt->input->buf->buffer->use - (ctxt->input->cur - ctxt->input->base);
11373         if (avail < 2)
11374             goto done;
11375         cur = ctxt->input->cur[0];
11376         next = ctxt->input->cur[1];
11377             if ((cur == '<') && (next == '?')) {
11378             if ((!terminate) &&
11379                 (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
11380             goto done;
11381 #ifdef DEBUG_PUSH
11382             xmlGenericError(xmlGenericErrorContext,
11383                 "PP: Parsing PI\n");
11384 #endif
11385             xmlParsePI(ctxt);
11386             ctxt->instate = XML_PARSER_EPILOG;
11387         } else if ((cur == '<') && (next == '!') &&
11388             (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
11389             if ((!terminate) &&
11390                 (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0))
11391             goto done;
11392 #ifdef DEBUG_PUSH
11393             xmlGenericError(xmlGenericErrorContext,
11394                 "PP: Parsing Comment\n");
11395 #endif
11396             xmlParseComment(ctxt);
11397             ctxt->instate = XML_PARSER_EPILOG;
11398         } else if ((cur == '<') && (next == '!') &&
11399                    (avail < 4)) {
11400             goto done;
11401         } else {
11402             xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
11403             ctxt->instate = XML_PARSER_EOF;
11404 #ifdef DEBUG_PUSH
11405             xmlGenericError(xmlGenericErrorContext,
11406                 "PP: entering EOF\n");
11407 #endif
11408             if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11409             ctxt->sax->endDocument(ctxt->userData);
11410             goto done;
11411         }
11412         break;
11413             case XML_PARSER_DTD: {
11414             /*
11415          * Sorry but progressive parsing of the internal subset
11416          * is not expected to be supported. We first check that
11417          * the full content of the internal subset is available and
11418          * the parsing is launched only at that point.
11419          * Internal subset ends up with "']' S? '>'" in an unescaped
11420          * section and not in a ']]>' sequence which are conditional
11421          * sections (whoever argued to keep that crap in XML deserve
11422          * a place in hell !).
11423          */
11424         int base, i;
11425         xmlChar *buf;
11426             xmlChar quote = 0;
11427 
11428         base = ctxt->input->cur - ctxt->input->base;
11429         if (base < 0) return(0);
11430         if (ctxt->checkIndex > base)
11431             base = ctxt->checkIndex;
11432         buf = ctxt->input->buf->buffer->content;
11433         for (;(unsigned int) base < ctxt->input->buf->buffer->use;
11434              base++) {
11435             if (quote != 0) {
11436                 if (buf[base] == quote)
11437                 quote = 0;
11438             continue;    
11439             }
11440             if ((quote == 0) && (buf[base] == '<')) {
11441                 int found  = 0;
11442             /* special handling of comments */
11443                 if (((unsigned int) base + 4 <
11444                  ctxt->input->buf->buffer->use) &&
11445                 (buf[base + 1] == '!') &&
11446                 (buf[base + 2] == '-') &&
11447                 (buf[base + 3] == '-')) {
11448                 for (;(unsigned int) base + 3 <
11449                       ctxt->input->buf->buffer->use; base++) {
11450                 if ((buf[base] == '-') &&
11451                     (buf[base + 1] == '-') &&
11452                     (buf[base + 2] == '>')) {
11453                     found = 1;
11454                     base += 2;
11455                     break;
11456                 }
11457                     }
11458                 if (!found) {
11459 #if 0
11460                     fprintf(stderr, "unfinished comment\n");
11461 #endif
11462                     break; /* for */
11463                     }
11464                     continue;
11465             }
11466             }
11467             if (buf[base] == '"') {
11468                 quote = '"';
11469             continue;
11470             }
11471             if (buf[base] == '\'') {
11472                 quote = '\'';
11473             continue;
11474             }
11475             if (buf[base] == ']') {
11476 #if 0
11477                 fprintf(stderr, "%c%c%c%c: ", buf[base],
11478                     buf[base + 1], buf[base + 2], buf[base + 3]);
11479 #endif
11480                 if ((unsigned int) base +1 >=
11481                     ctxt->input->buf->buffer->use)
11482                 break;
11483             if (buf[base + 1] == ']') {
11484                 /* conditional crap, skip both ']' ! */
11485                 base++;
11486                 continue;
11487             }
11488                 for (i = 1;
11489              (unsigned int) base + i < ctxt->input->buf->buffer->use;
11490                      i++) {
11491                 if (buf[base + i] == '>') {
11492 #if 0
11493                     fprintf(stderr, "found\n");
11494 #endif
11495                     goto found_end_int_subset;
11496                 }
11497                 if (!IS_BLANK_CH(buf[base + i])) {
11498 #if 0
11499                     fprintf(stderr, "not found\n");
11500 #endif
11501                     goto not_end_of_int_subset;
11502                 }
11503             }
11504 #if 0
11505             fprintf(stderr, "end of stream\n");
11506 #endif
11507                 break;
11508                         
11509             }
11510 not_end_of_int_subset:
11511                     continue; /* for */
11512         }
11513         /*
11514          * We didn't found the end of the Internal subset
11515          */
11516 #ifdef DEBUG_PUSH
11517         if (next == 0)
11518             xmlGenericError(xmlGenericErrorContext,
11519                 "PP: lookup of int subset end filed\n");
11520 #endif
11521             goto done;
11522 
11523 found_end_int_subset:
11524         xmlParseInternalSubset(ctxt);
11525         ctxt->inSubset = 2;
11526         if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
11527             (ctxt->sax->externalSubset != NULL))
11528             ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
11529                 ctxt->extSubSystem, ctxt->extSubURI);
11530         ctxt->inSubset = 0;
11531         xmlCleanSpecialAttr(ctxt);
11532         ctxt->instate = XML_PARSER_PROLOG;
11533         ctxt->checkIndex = 0;
11534 #ifdef DEBUG_PUSH
11535         xmlGenericError(xmlGenericErrorContext,
11536             "PP: entering PROLOG\n");
11537 #endif
11538                 break;
11539         }
11540             case XML_PARSER_COMMENT:
11541         xmlGenericError(xmlGenericErrorContext,
11542             "PP: internal error, state == COMMENT\n");
11543         ctxt->instate = XML_PARSER_CONTENT;
11544 #ifdef DEBUG_PUSH
11545         xmlGenericError(xmlGenericErrorContext,
11546             "PP: entering CONTENT\n");
11547 #endif
11548         break;
11549             case XML_PARSER_IGNORE:
11550         xmlGenericError(xmlGenericErrorContext,
11551             "PP: internal error, state == IGNORE");
11552             ctxt->instate = XML_PARSER_DTD;
11553 #ifdef DEBUG_PUSH
11554         xmlGenericError(xmlGenericErrorContext,
11555             "PP: entering DTD\n");
11556 #endif
11557             break;
11558             case XML_PARSER_PI:
11559         xmlGenericError(xmlGenericErrorContext,
11560             "PP: internal error, state == PI\n");
11561         ctxt->instate = XML_PARSER_CONTENT;
11562 #ifdef DEBUG_PUSH
11563         xmlGenericError(xmlGenericErrorContext,
11564             "PP: entering CONTENT\n");
11565 #endif
11566         break;
11567             case XML_PARSER_ENTITY_DECL:
11568         xmlGenericError(xmlGenericErrorContext,
11569             "PP: internal error, state == ENTITY_DECL\n");
11570         ctxt->instate = XML_PARSER_DTD;
11571 #ifdef DEBUG_PUSH
11572         xmlGenericError(xmlGenericErrorContext,
11573             "PP: entering DTD\n");
11574 #endif
11575         break;
11576             case XML_PARSER_ENTITY_VALUE:
11577         xmlGenericError(xmlGenericErrorContext,
11578             "PP: internal error, state == ENTITY_VALUE\n");
11579         ctxt->instate = XML_PARSER_CONTENT;
11580 #ifdef DEBUG_PUSH
11581         xmlGenericError(xmlGenericErrorContext,
11582             "PP: entering DTD\n");
11583 #endif
11584         break;
11585             case XML_PARSER_ATTRIBUTE_VALUE:
11586         xmlGenericError(xmlGenericErrorContext,
11587             "PP: internal error, state == ATTRIBUTE_VALUE\n");
11588         ctxt->instate = XML_PARSER_START_TAG;
11589 #ifdef DEBUG_PUSH
11590         xmlGenericError(xmlGenericErrorContext,
11591             "PP: entering START_TAG\n");
11592 #endif
11593         break;
11594             case XML_PARSER_SYSTEM_LITERAL:
11595         xmlGenericError(xmlGenericErrorContext,
11596             "PP: internal error, state == SYSTEM_LITERAL\n");
11597         ctxt->instate = XML_PARSER_START_TAG;
11598 #ifdef DEBUG_PUSH
11599         xmlGenericError(xmlGenericErrorContext,
11600             "PP: entering START_TAG\n");
11601 #endif
11602         break;
11603             case XML_PARSER_PUBLIC_LITERAL:
11604         xmlGenericError(xmlGenericErrorContext,
11605             "PP: internal error, state == PUBLIC_LITERAL\n");
11606         ctxt->instate = XML_PARSER_START_TAG;
11607 #ifdef DEBUG_PUSH
11608         xmlGenericError(xmlGenericErrorContext,
11609             "PP: entering START_TAG\n");
11610 #endif
11611         break;
11612     }
11613     }
11614 done:    
11615 #ifdef DEBUG_PUSH
11616     xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
11617 #endif
11618     return(ret);
11619 encoding_error:
11620     {
11621         char buffer[150];
11622 
11623     snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
11624             ctxt->input->cur[0], ctxt->input->cur[1],
11625             ctxt->input->cur[2], ctxt->input->cur[3]);
11626     __xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
11627              "Input is not proper UTF-8, indicate encoding !\n%s",
11628              BAD_CAST buffer, NULL);
11629     }
11630     return(0);
11631 }
11632 
11644 int
11645 xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
11646               int terminate) {
11647     int end_in_lf = 0;
11648     int remain = 0;
11649 
11650     if (ctxt == NULL)
11651         return(XML_ERR_INTERNAL_ERROR);
11652     if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
11653         return(ctxt->errNo);
11654     if (ctxt->instate == XML_PARSER_START)
11655         xmlDetectSAX2(ctxt);
11656     if ((size > 0) && (chunk != NULL) && (!terminate) &&
11657         (chunk[size - 1] == '\r')) {
11658     end_in_lf = 1;
11659     size--;
11660     }
11661 
11662 xmldecl_done:
11663 
11664     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
11665         (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
11666     int base = ctxt->input->base - ctxt->input->buf->buffer->content;
11667     int cur = ctxt->input->cur - ctxt->input->base;
11668     int res;
11669 
11670         /*
11671          * Specific handling if we autodetected an encoding, we should not
11672          * push more than the first line ... which depend on the encoding
11673          * And only push the rest once the final encoding was detected
11674          */
11675         if ((ctxt->instate == XML_PARSER_START) && (ctxt->input != NULL) &&
11676             (ctxt->input->buf != NULL) && (ctxt->input->buf->encoder != NULL)) {
11677             unsigned int len = 45;
11678 
11679             if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
11680                                BAD_CAST "UTF-16")) ||
11681                 (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
11682                                BAD_CAST "UTF16")))
11683                 len = 90;
11684             else if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
11685                                     BAD_CAST "UCS-4")) ||
11686                      (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
11687                                     BAD_CAST "UCS4")))
11688                 len = 180;
11689 
11690             if (ctxt->input->buf->rawconsumed < len)
11691                 len -= ctxt->input->buf->rawconsumed;
11692 
11693             /*
11694              * Change size for reading the initial declaration only
11695              * if size is greater than len. Otherwise, memmove in xmlBufferAdd
11696              * will blindly copy extra bytes from memory.
11697              */
11698             if ((unsigned int) size > len) {
11699                 remain = size - len;
11700                 size = len;
11701             } else {
11702                 remain = 0;
11703             }
11704         }
11705     res =xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
11706     if (res < 0) {
11707         ctxt->errNo = XML_PARSER_EOF;
11708         ctxt->disableSAX = 1;
11709         return (XML_PARSER_EOF);
11710     }
11711     ctxt->input->base = ctxt->input->buf->buffer->content + base;
11712     ctxt->input->cur = ctxt->input->base + cur;
11713     ctxt->input->end =
11714         &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use];
11715 #ifdef DEBUG_PUSH
11716     xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
11717 #endif
11718 
11719     } else if (ctxt->instate != XML_PARSER_EOF) {
11720     if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
11721         xmlParserInputBufferPtr in = ctxt->input->buf;
11722         if ((in->encoder != NULL) && (in->buffer != NULL) &&
11723             (in->raw != NULL)) {
11724         int nbchars;
11725 
11726         nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
11727         if (nbchars < 0) {
11728             /* TODO 2.6.0 */
11729             xmlGenericError(xmlGenericErrorContext,
11730                     "xmlParseChunk: encoder error\n");
11731             return(XML_ERR_INVALID_ENCODING);
11732         }
11733         }
11734     }
11735     }
11736     if (remain != 0)
11737         xmlParseTryOrFinish(ctxt, 0);
11738     else
11739         xmlParseTryOrFinish(ctxt, terminate);
11740     if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
11741         return(ctxt->errNo);
11742 
11743     if (remain != 0) {
11744         chunk += size;
11745         size = remain;
11746         remain = 0;
11747         goto xmldecl_done;
11748     }
11749     if ((end_in_lf == 1) && (ctxt->input != NULL) &&
11750         (ctxt->input->buf != NULL)) {
11751     xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
11752     }
11753     if (terminate) {
11754     /*
11755      * Check for termination
11756      */
11757     int avail = 0;
11758 
11759     if (ctxt->input != NULL) {
11760         if (ctxt->input->buf == NULL)
11761         avail = ctxt->input->length -
11762             (ctxt->input->cur - ctxt->input->base);
11763         else
11764         avail = ctxt->input->buf->buffer->use -
11765             (ctxt->input->cur - ctxt->input->base);
11766     }
11767                 
11768     if ((ctxt->instate != XML_PARSER_EOF) &&
11769         (ctxt->instate != XML_PARSER_EPILOG)) {
11770         xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
11771     } 
11772     if ((ctxt->instate == XML_PARSER_EPILOG) && (avail > 0)) {
11773         xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
11774     }
11775     if (ctxt->instate != XML_PARSER_EOF) {
11776         if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11777         ctxt->sax->endDocument(ctxt->userData);
11778     }
11779     ctxt->instate = XML_PARSER_EOF;
11780     }
11781     return((xmlParserErrors) ctxt->errNo);        
11782 }
11783 
11784 /************************************************************************
11785  *                                  *
11786  *      I/O front end functions to the parser           *
11787  *                                  *
11788  ************************************************************************/
11789 
11809 xmlParserCtxtPtr
11810 xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data, 
11811                         const char *chunk, int size, const char *filename) {
11812     xmlParserCtxtPtr ctxt;
11813     xmlParserInputPtr inputStream;
11814     xmlParserInputBufferPtr buf;
11815     xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
11816 
11817     /*
11818      * plug some encoding conversion routines
11819      */
11820     if ((chunk != NULL) && (size >= 4))
11821     enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
11822 
11823     buf = xmlAllocParserInputBuffer(enc);
11824     if (buf == NULL) return(NULL);
11825 
11826     ctxt = xmlNewParserCtxt();
11827     if (ctxt == NULL) {
11828         xmlErrMemory(NULL, "creating parser: out of memory\n");
11829     xmlFreeParserInputBuffer(buf);
11830     return(NULL);
11831     }
11832     ctxt->dictNames = 1;
11833     ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 * sizeof(xmlChar *));
11834     if (ctxt->pushTab == NULL) {
11835         xmlErrMemory(ctxt, NULL);
11836     xmlFreeParserInputBuffer(buf);
11837     xmlFreeParserCtxt(ctxt);
11838     return(NULL);
11839     }
11840     if (sax != NULL) {
11841 #ifdef LIBXML_SAX1_ENABLED
11842     if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
11843 #endif /* LIBXML_SAX1_ENABLED */
11844         xmlFree(ctxt->sax);
11845     ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
11846     if (ctxt->sax == NULL) {
11847         xmlErrMemory(ctxt, NULL);
11848         xmlFreeParserInputBuffer(buf);
11849         xmlFreeParserCtxt(ctxt);
11850         return(NULL);
11851     }
11852     memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
11853     if (sax->initialized == XML_SAX2_MAGIC)
11854         memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
11855     else
11856         memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
11857     if (user_data != NULL)
11858         ctxt->userData = user_data;
11859     }   
11860     if (filename == NULL) {
11861     ctxt->directory = NULL;
11862     } else {
11863         ctxt->directory = xmlParserGetDirectory(filename);
11864     }
11865 
11866     inputStream = xmlNewInputStream(ctxt);
11867     if (inputStream == NULL) {
11868     xmlFreeParserCtxt(ctxt);
11869     xmlFreeParserInputBuffer(buf);
11870     return(NULL);
11871     }
11872 
11873     if (filename == NULL)
11874     inputStream->filename = NULL;
11875     else {
11876     inputStream->filename = (char *)
11877         xmlCanonicPath((const xmlChar *) filename);
11878     if (inputStream->filename == NULL) {
11879         xmlFreeParserCtxt(ctxt);
11880         xmlFreeParserInputBuffer(buf);
11881         return(NULL);
11882     }
11883     }
11884     inputStream->buf = buf;
11885     inputStream->base = inputStream->buf->buffer->content;
11886     inputStream->cur = inputStream->buf->buffer->content;
11887     inputStream->end = 
11888     &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
11889 
11890     inputPush(ctxt, inputStream);
11891 
11892     /*
11893      * If the caller didn't provide an initial 'chunk' for determining
11894      * the encoding, we set the context to XML_CHAR_ENCODING_NONE so
11895      * that it can be automatically determined later
11896      */
11897     if ((size == 0) || (chunk == NULL)) {
11898     ctxt->charset = XML_CHAR_ENCODING_NONE;
11899     } else if ((ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
11900     int base = ctxt->input->base - ctxt->input->buf->buffer->content;
11901     int cur = ctxt->input->cur - ctxt->input->base;
11902 
11903     xmlParserInputBufferPush(ctxt->input->buf, size, chunk);          
11904 
11905     ctxt->input->base = ctxt->input->buf->buffer->content + base;
11906     ctxt->input->cur = ctxt->input->base + cur;
11907     ctxt->input->end =
11908         &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->use];
11909 #ifdef DEBUG_PUSH
11910     xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
11911 #endif
11912     }
11913 
11914     if (enc != XML_CHAR_ENCODING_NONE) {
11915         xmlSwitchEncoding(ctxt, enc);
11916     }
11917 
11918     return(ctxt);
11919 }
11920 #endif /* LIBXML_PUSH_ENABLED */
11921 
11928 void           
11929 xmlStopParser(xmlParserCtxtPtr ctxt) {
11930     if (ctxt == NULL)
11931         return;
11932     ctxt->instate = XML_PARSER_EOF;
11933     ctxt->disableSAX = 1;
11934     if (ctxt->input != NULL) {
11935     ctxt->input->cur = BAD_CAST"";
11936     ctxt->input->base = ctxt->input->cur;
11937     }
11938 }
11939 
11954 xmlParserCtxtPtr
11955 xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
11956     xmlInputReadCallback   ioread, xmlInputCloseCallback  ioclose,
11957     void *ioctx, xmlCharEncoding enc) {
11958     xmlParserCtxtPtr ctxt;
11959     xmlParserInputPtr inputStream;
11960     xmlParserInputBufferPtr buf;
11961     
11962     if (ioread == NULL) return(NULL);
11963 
11964     buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
11965     if (buf == NULL) return(NULL);
11966 
11967     ctxt = xmlNewParserCtxt();
11968     if (ctxt == NULL) {
11969     xmlFreeParserInputBuffer(buf);
11970     return(NULL);
11971     }
11972     if (sax != NULL) {
11973 #ifdef LIBXML_SAX1_ENABLED
11974     if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
11975 #endif /* LIBXML_SAX1_ENABLED */
11976         xmlFree(ctxt->sax);
11977     ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
11978     if (ctxt->sax == NULL) {
11979         xmlErrMemory(ctxt, NULL);
11980         xmlFreeParserCtxt(ctxt);
11981         return(NULL);
11982     }
11983     memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
11984     if (sax->initialized == XML_SAX2_MAGIC)
11985         memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
11986     else
11987         memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
11988     if (user_data != NULL)
11989         ctxt->userData = user_data;
11990     }   
11991 
11992     inputStream = xmlNewIOInputStream(ctxt, buf, enc);
11993     if (inputStream == NULL) {
11994     xmlFreeParserCtxt(ctxt);
11995     return(NULL);
11996     }
11997     inputPush(ctxt, inputStream);
11998 
11999     return(ctxt);
12000 }
12001 
12002 #ifdef LIBXML_VALID_ENABLED
12003 /************************************************************************
12004  *                                  *
12005  *      Front ends when parsing a DTD               *
12006  *                                  *
12007  ************************************************************************/
12008 
12021 xmlDtdPtr
12022 xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
12023           xmlCharEncoding enc) {
12024     xmlDtdPtr ret = NULL;
12025     xmlParserCtxtPtr ctxt;
12026     xmlParserInputPtr pinput = NULL;
12027     xmlChar start[4];
12028 
12029     if (input == NULL)
12030     return(NULL);
12031 
12032     ctxt = xmlNewParserCtxt();
12033     if (ctxt == NULL) {
12034         xmlFreeParserInputBuffer(input);
12035     return(NULL);
12036     }
12037 
12038     /*
12039      * Set-up the SAX context
12040      */
12041     if (sax != NULL) { 
12042     if (ctxt->sax != NULL)
12043         xmlFree(ctxt->sax);
12044         ctxt->sax = sax;
12045         ctxt->userData = ctxt;
12046     }
12047     xmlDetectSAX2(ctxt);
12048 
12049     /*
12050      * generate a parser input from the I/O handler
12051      */
12052 
12053     pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
12054     if (pinput == NULL) {
12055         if (sax != NULL) ctxt->sax = NULL;
12056         xmlFreeParserInputBuffer(input);
12057     xmlFreeParserCtxt(ctxt);
12058     return(NULL);
12059     }
12060 
12061     /*
12062      * plug some encoding conversion routines here.
12063      */
12064     if (xmlPushInput(ctxt, pinput) < 0) {
12065         if (sax != NULL) ctxt->sax = NULL;
12066     xmlFreeParserCtxt(ctxt);
12067     return(NULL);
12068     }
12069     if (enc != XML_CHAR_ENCODING_NONE) {
12070         xmlSwitchEncoding(ctxt, enc);
12071     }
12072 
12073     pinput->filename = NULL;
12074     pinput->line = 1;
12075     pinput->col = 1;
12076     pinput->base = ctxt->input->cur;
12077     pinput->cur = ctxt->input->cur;
12078     pinput->free = NULL;
12079 
12080     /*
12081      * let's parse that entity knowing it's an external subset.
12082      */
12083     ctxt->inSubset = 2;
12084     ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12085     if (ctxt->myDoc == NULL) {
12086     xmlErrMemory(ctxt, "New Doc failed");
12087     return(NULL);
12088     }
12089     ctxt->myDoc->properties = XML_DOC_INTERNAL;
12090     ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12091                                    BAD_CAST "none", BAD_CAST "none");
12092 
12093     if ((enc == XML_CHAR_ENCODING_NONE) &&
12094         ((ctxt->input->end - ctxt->input->cur) >= 4)) {
12095     /* 
12096      * Get the 4 first bytes and decode the charset
12097      * if enc != XML_CHAR_ENCODING_NONE
12098      * plug some encoding conversion routines.
12099      */
12100     start[0] = RAW;
12101     start[1] = NXT(1);
12102     start[2] = NXT(2);
12103     start[3] = NXT(3);
12104     enc = xmlDetectCharEncoding(start, 4);
12105     if (enc != XML_CHAR_ENCODING_NONE) {
12106         xmlSwitchEncoding(ctxt, enc);
12107     }
12108     }
12109 
12110     xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
12111 
12112     if (ctxt->myDoc != NULL) {
12113     if (ctxt->wellFormed) {
12114         ret = ctxt->myDoc->extSubset;
12115         ctxt->myDoc->extSubset = NULL;
12116         if (ret != NULL) {
12117         xmlNodePtr tmp;
12118 
12119         ret->doc = NULL;
12120         tmp = ret->children;
12121         while (tmp != NULL) {
12122             tmp->doc = NULL;
12123             tmp = tmp->next;
12124         }
12125         }
12126     } else {
12127         ret = NULL;
12128     }
12129         xmlFreeDoc(ctxt->myDoc);
12130         ctxt->myDoc = NULL;
12131     }
12132     if (sax != NULL) ctxt->sax = NULL;
12133     xmlFreeParserCtxt(ctxt);
12134     
12135     return(ret);
12136 }
12137 
12149 xmlDtdPtr
12150 xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
12151                           const xmlChar *SystemID) {
12152     xmlDtdPtr ret = NULL;
12153     xmlParserCtxtPtr ctxt;
12154     xmlParserInputPtr input = NULL;
12155     xmlCharEncoding enc;
12156     xmlChar* systemIdCanonic;
12157 
12158     if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
12159 
12160     ctxt = xmlNewParserCtxt();
12161     if (ctxt == NULL) {
12162     return(NULL);
12163     }
12164 
12165     /*
12166      * Set-up the SAX context
12167      */
12168     if (sax != NULL) { 
12169     if (ctxt->sax != NULL)
12170         xmlFree(ctxt->sax);
12171         ctxt->sax = sax;
12172         ctxt->userData = ctxt;
12173     }
12174     
12175     /*
12176      * Canonicalise the system ID
12177      */
12178     systemIdCanonic = xmlCanonicPath(SystemID);
12179     if ((SystemID != NULL) && (systemIdCanonic == NULL)) {
12180     xmlFreeParserCtxt(ctxt);
12181     return(NULL);
12182     }
12183 
12184     /*
12185      * Ask the Entity resolver to load the damn thing
12186      */
12187 
12188     if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
12189     input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
12190                                      systemIdCanonic);
12191     if (input == NULL) {
12192         if (sax != NULL) ctxt->sax = NULL;
12193     xmlFreeParserCtxt(ctxt);
12194     if (systemIdCanonic != NULL)
12195         xmlFree(systemIdCanonic);
12196     return(NULL);
12197     }
12198 
12199     /*
12200      * plug some encoding conversion routines here.
12201      */
12202     if (xmlPushInput(ctxt, input) < 0) {
12203         if (sax != NULL) ctxt->sax = NULL;
12204     xmlFreeParserCtxt(ctxt);
12205     if (systemIdCanonic != NULL)
12206         xmlFree(systemIdCanonic);
12207     return(NULL);
12208     }
12209     if ((ctxt->input->end - ctxt->input->cur) >= 4) {
12210     enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
12211     xmlSwitchEncoding(ctxt, enc);
12212     }
12213 
12214     if (input->filename == NULL)
12215     input->filename = (char *) systemIdCanonic;
12216     else
12217     xmlFree(systemIdCanonic);
12218     input->line = 1;
12219     input->col = 1;
12220     input->base = ctxt->input->cur;
12221     input->cur = ctxt->input->cur;
12222     input->free = NULL;
12223 
12224     /*
12225      * let's parse that entity knowing it's an external subset.
12226      */
12227     ctxt->inSubset = 2;
12228     ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12229     if (ctxt->myDoc == NULL) {
12230     xmlErrMemory(ctxt, "New Doc failed");
12231         if (sax != NULL) ctxt->sax = NULL;
12232     xmlFreeParserCtxt(ctxt);
12233     return(NULL);
12234     }
12235     ctxt->myDoc->properties = XML_DOC_INTERNAL;
12236     ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12237                                    ExternalID, SystemID);
12238     xmlParseExternalSubset(ctxt, ExternalID, SystemID);
12239 
12240     if (ctxt->myDoc != NULL) {
12241     if (ctxt->wellFormed) {
12242         ret = ctxt->myDoc->extSubset;
12243         ctxt->myDoc->extSubset = NULL;
12244         if (ret != NULL) {
12245         xmlNodePtr tmp;
12246 
12247         ret->doc = NULL;
12248         tmp = ret->children;
12249         while (tmp != NULL) {
12250             tmp->doc = NULL;
12251             tmp = tmp->next;
12252         }
12253         }
12254     } else {
12255         ret = NULL;
12256     }
12257         xmlFreeDoc(ctxt->myDoc);
12258         ctxt->myDoc = NULL;
12259     }
12260     if (sax != NULL) ctxt->sax = NULL;
12261     xmlFreeParserCtxt(ctxt);
12262 
12263     return(ret);
12264 }
12265 
12266 
12277 xmlDtdPtr
12278 xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
12279     return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
12280 }
12281 #endif /* LIBXML_VALID_ENABLED */
12282 
12283 /************************************************************************
12284  *                                  *
12285  *      Front ends when parsing an Entity           *
12286  *                                  *
12287  ************************************************************************/
12288 
12306 int
12307 xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
12308                    const xmlChar *ID, xmlNodePtr *lst) {
12309     xmlParserCtxtPtr ctxt;
12310     xmlDocPtr newDoc;
12311     xmlNodePtr newRoot;
12312     xmlSAXHandlerPtr oldsax = NULL;
12313     int ret = 0;
12314     xmlChar start[4];
12315     xmlCharEncoding enc;
12316 
12317     if (ctx == NULL) return(-1);
12318 
12319     if (((ctx->depth > 40) && ((ctx->options & XML_PARSE_HUGE) == 0)) ||
12320         (ctx->depth > 1024)) {
12321     return(XML_ERR_ENTITY_LOOP);
12322     }
12323 
12324     if (lst != NULL)
12325         *lst = NULL;
12326     if ((URL == NULL) && (ID == NULL))
12327     return(-1);
12328     if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */
12329     return(-1);
12330 
12331     ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, ctx);
12332     if (ctxt == NULL) {
12333     return(-1);
12334     }
12335 
12336     oldsax = ctxt->sax;
12337     ctxt->sax = ctx->sax;
12338     xmlDetectSAX2(ctxt);
12339     newDoc = xmlNewDoc(BAD_CAST "1.0");
12340     if (newDoc == NULL) {
12341     xmlFreeParserCtxt(ctxt);
12342     return(-1);
12343     }
12344     newDoc->properties = XML_DOC_INTERNAL;
12345     if (ctx->myDoc->dict) {
12346     newDoc->dict = ctx->myDoc->dict;
12347     xmlDictReference(newDoc->dict);
12348     }
12349     if (ctx->myDoc != NULL) {
12350     newDoc->intSubset = ctx->myDoc->intSubset;
12351     newDoc->extSubset = ctx->myDoc->extSubset;
12352     }
12353     if (ctx->myDoc->URL != NULL) {
12354     newDoc->URL = xmlStrdup(ctx->myDoc->URL);
12355     }
12356     newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
12357     if (newRoot == NULL) {
12358     ctxt->sax = oldsax;
12359     xmlFreeParserCtxt(ctxt);
12360     newDoc->intSubset = NULL;
12361     newDoc->extSubset = NULL;
12362         xmlFreeDoc(newDoc);
12363     return(-1);
12364     }
12365     xmlAddChild((xmlNodePtr) newDoc, newRoot);
12366     nodePush(ctxt, newDoc->children);
12367     if (ctx->myDoc == NULL) {
12368     ctxt->myDoc = newDoc;
12369     } else {
12370     ctxt->myDoc = ctx->myDoc;
12371     newDoc->children->doc = ctx->myDoc;
12372     }
12373 
12374     /*
12375      * Get the 4 first bytes and decode the charset
12376      * if enc != XML_CHAR_ENCODING_NONE
12377      * plug some encoding conversion routines.
12378      */
12379     GROW
12380     if ((ctxt->input->end - ctxt->input->cur) >= 4) {
12381     start[0] = RAW;
12382     start[1] = NXT(1);
12383     start[2] = NXT(2);
12384     start[3] = NXT(3);
12385     enc = xmlDetectCharEncoding(start, 4);
12386     if (enc != XML_CHAR_ENCODING_NONE) {
12387         xmlSwitchEncoding(ctxt, enc);
12388     }
12389     }
12390 
12391     /*
12392      * Parse a possible text declaration first
12393      */
12394     if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
12395     xmlParseTextDecl(ctxt);
12396     /*
12397      * An XML-1.0 document can't reference an entity not XML-1.0
12398      */
12399     if ((xmlStrEqual(ctx->version, BAD_CAST "1.0")) &&
12400         (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
12401         xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH, 
12402                        "Version mismatch between document and entity\n");
12403     }
12404     }
12405 
12406     /*
12407      * Doing validity checking on chunk doesn't make sense
12408      */
12409     ctxt->instate = XML_PARSER_CONTENT;
12410     ctxt->validate = ctx->validate;
12411     ctxt->valid = ctx->valid;
12412     ctxt->loadsubset = ctx->loadsubset;
12413     ctxt->depth = ctx->depth + 1;
12414     ctxt->replaceEntities = ctx->replaceEntities;
12415     if (ctxt->validate) {
12416     ctxt->vctxt.error = ctx->vctxt.error;
12417     ctxt->vctxt.warning = ctx->vctxt.warning;
12418     } else {
12419     ctxt->vctxt.error = NULL;
12420     ctxt->vctxt.warning = NULL;
12421     }
12422     ctxt->vctxt.nodeTab = NULL;
12423     ctxt->vctxt.nodeNr = 0;
12424     ctxt->vctxt.nodeMax = 0;
12425     ctxt->vctxt.node = NULL;
12426     if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
12427     ctxt->dict = ctx->dict;
12428     ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
12429     ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
12430     ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
12431     ctxt->dictNames = ctx->dictNames;
12432     ctxt->attsDefault = ctx->attsDefault;
12433     ctxt->attsSpecial = ctx->attsSpecial;
12434     ctxt->linenumbers = ctx->linenumbers;
12435 
12436     xmlParseContent(ctxt);
12437 
12438     ctx->validate = ctxt->validate;
12439     ctx->valid = ctxt->valid;
12440     if ((RAW == '<') && (NXT(1) == '/')) {
12441     xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12442     } else if (RAW != 0) {
12443     xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
12444     }
12445     if (ctxt->node != newDoc->children) {
12446     xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12447     }
12448 
12449     if (!ctxt->wellFormed) {
12450         if (ctxt->errNo == 0)
12451         ret = 1;
12452     else
12453         ret = ctxt->errNo;
12454     } else {
12455     if (lst != NULL) {
12456         xmlNodePtr cur;
12457 
12458         /*
12459          * Return the newly created nodeset after unlinking it from
12460          * they pseudo parent.
12461          */
12462         cur = newDoc->children->children;
12463         *lst = cur;
12464         while (cur != NULL) {
12465         cur->parent = NULL;
12466         cur = cur->next;
12467         }
12468             newDoc->children->children = NULL;
12469     }
12470     ret = 0;
12471     }
12472     ctxt->sax = oldsax;
12473     ctxt->dict = NULL;
12474     ctxt->attsDefault = NULL;
12475     ctxt->attsSpecial = NULL;
12476     xmlFreeParserCtxt(ctxt);
12477     newDoc->intSubset = NULL;
12478     newDoc->extSubset = NULL;
12479     xmlFreeDoc(newDoc);
12480 
12481     return(ret);
12482 }
12483 
12501 static xmlParserErrors
12502 xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
12503                   xmlSAXHandlerPtr sax,
12504               void *user_data, int depth, const xmlChar *URL,
12505               const xmlChar *ID, xmlNodePtr *list) {
12506     xmlParserCtxtPtr ctxt;
12507     xmlDocPtr newDoc;
12508     xmlNodePtr newRoot;
12509     xmlSAXHandlerPtr oldsax = NULL;
12510     xmlParserErrors ret = XML_ERR_OK;
12511     xmlChar start[4];
12512     xmlCharEncoding enc;
12513 
12514     if (((depth > 40) &&
12515     ((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) ||
12516     (depth > 1024)) {
12517     return(XML_ERR_ENTITY_LOOP);
12518     }
12519 
12520     if (list != NULL)
12521         *list = NULL;
12522     if ((URL == NULL) && (ID == NULL))
12523     return(XML_ERR_INTERNAL_ERROR);
12524     if (doc == NULL)
12525     return(XML_ERR_INTERNAL_ERROR);
12526 
12527 
12528     ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, oldctxt);
12529     if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
12530     ctxt->userData = ctxt;
12531     if (oldctxt != NULL) {
12532     ctxt->_private = oldctxt->_private;
12533     ctxt->loadsubset = oldctxt->loadsubset;
12534     ctxt->validate = oldctxt->validate;
12535     ctxt->external = oldctxt->external;
12536     ctxt->record_info = oldctxt->record_info;
12537     ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
12538     ctxt->node_seq.length = oldctxt->node_seq.length;
12539     ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
12540     } else {
12541     /*
12542      * Doing validity checking on chunk without context
12543      * doesn't make sense
12544      */
12545     ctxt->_private = NULL;
12546     ctxt->validate = 0;
12547     ctxt->external = 2;
12548     ctxt->loadsubset = 0;
12549     }
12550     if (sax != NULL) {
12551     oldsax = ctxt->sax;
12552         ctxt->sax = sax;
12553     if (user_data != NULL)
12554         ctxt->userData = user_data;
12555     }
12556     xmlDetectSAX2(ctxt);
12557     newDoc = xmlNewDoc(BAD_CAST "1.0");
12558     if (newDoc == NULL) {
12559     ctxt->node_seq.maximum = 0;
12560     ctxt->node_seq.length = 0;
12561     ctxt->node_seq.buffer = NULL;
12562     xmlFreeParserCtxt(ctxt);
12563     return(XML_ERR_INTERNAL_ERROR);
12564     }
12565     newDoc->properties = XML_DOC_INTERNAL;
12566     newDoc->intSubset = doc->intSubset;
12567     newDoc->extSubset = doc->extSubset;
12568     newDoc->dict = doc->dict;
12569     xmlDictReference(newDoc->dict);
12570 
12571     if (doc->URL != NULL) {
12572     newDoc->URL = xmlStrdup(doc->URL);
12573     }
12574     newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
12575     if (newRoot == NULL) {
12576     if (sax != NULL)
12577         ctxt->sax = oldsax;
12578     ctxt->node_seq.maximum = 0;
12579     ctxt->node_seq.length = 0;
12580     ctxt->node_seq.buffer = NULL;
12581     xmlFreeParserCtxt(ctxt);
12582     newDoc->intSubset = NULL;
12583     newDoc->extSubset = NULL;
12584         xmlFreeDoc(newDoc);
12585     return(XML_ERR_INTERNAL_ERROR);
12586     }
12587     xmlAddChild((xmlNodePtr) newDoc, newRoot);
12588     nodePush(ctxt, newDoc->children);
12589     ctxt->myDoc = doc;
12590     newRoot->doc = doc;
12591 
12592     /*
12593      * Get the 4 first bytes and decode the charset
12594      * if enc != XML_CHAR_ENCODING_NONE
12595      * plug some encoding conversion routines.
12596      */
12597     GROW;
12598     if ((ctxt->input->end - ctxt->input->cur) >= 4) {
12599     start[0] = RAW;
12600     start[1] = NXT(1);
12601     start[2] = NXT(2);
12602     start[3] = NXT(3);
12603     enc = xmlDetectCharEncoding(start, 4);
12604     if (enc != XML_CHAR_ENCODING_NONE) {
12605         xmlSwitchEncoding(ctxt, enc);
12606     }
12607     }
12608 
12609     /*
12610      * Parse a possible text declaration first
12611      */
12612     if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
12613     xmlParseTextDecl(ctxt);
12614     }
12615 
12616     ctxt->instate = XML_PARSER_CONTENT;
12617     ctxt->depth = depth;
12618 
12619     xmlParseContent(ctxt);
12620 
12621     if ((RAW == '<') && (NXT(1) == '/')) {
12622     xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12623     } else if (RAW != 0) {
12624     xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
12625     }
12626     if (ctxt->node != newDoc->children) {
12627     xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12628     }
12629 
12630     if (!ctxt->wellFormed) {
12631         if (ctxt->errNo == 0)
12632         ret = XML_ERR_INTERNAL_ERROR;
12633     else
12634         ret = (xmlParserErrors)ctxt->errNo;
12635     } else {
12636     if (list != NULL) {
12637         xmlNodePtr cur;
12638 
12639         /*
12640          * Return the newly created nodeset after unlinking it from
12641          * they pseudo parent.
12642          */
12643         cur = newDoc->children->children;
12644         *list = cur;
12645         while (cur != NULL) {
12646         cur->parent = NULL;
12647         cur = cur->next;
12648         }
12649             newDoc->children->children = NULL;
12650     }
12651     ret = XML_ERR_OK;
12652     }
12653 
12654     /*
12655      * Record in the parent context the number of entities replacement
12656      * done when parsing that reference.
12657      */
12658     if (oldctxt != NULL)
12659         oldctxt->nbentities += ctxt->nbentities;
12660 
12661     /*
12662      * Also record the size of the entity parsed
12663      */
12664     if (ctxt->input != NULL) {
12665     oldctxt->sizeentities += ctxt->input->consumed;
12666     oldctxt->sizeentities += (ctxt->input->cur - ctxt->input->base);
12667     }
12668     /*
12669      * And record the last error if any
12670      */
12671     if (ctxt->lastError.code != XML_ERR_OK)
12672         xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
12673 
12674     if (sax != NULL) 
12675     ctxt->sax = oldsax;
12676     oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
12677     oldctxt->node_seq.length = ctxt->node_seq.length;
12678     oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
12679     ctxt->node_seq.maximum = 0;
12680     ctxt->node_seq.length = 0;
12681     ctxt->node_seq.buffer = NULL;
12682     xmlFreeParserCtxt(ctxt);
12683     newDoc->intSubset = NULL;
12684     newDoc->extSubset = NULL;
12685     xmlFreeDoc(newDoc);
12686 
12687     return(ret);
12688 }
12689 
12690 #ifdef LIBXML_SAX1_ENABLED
12691 
12711 int
12712 xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
12713       int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
12714     return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
12715                                ID, lst));
12716 }
12717 
12738 int
12739 xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
12740      void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
12741     return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
12742                                                 depth, string, lst, 0 );
12743 }
12744 #endif /* LIBXML_SAX1_ENABLED */
12745 
12767 static xmlParserErrors
12768 xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
12769     const xmlChar *string, void *user_data, xmlNodePtr *lst) {
12770     xmlParserCtxtPtr ctxt;
12771     xmlDocPtr newDoc = NULL;
12772     xmlNodePtr newRoot;
12773     xmlSAXHandlerPtr oldsax = NULL;
12774     xmlNodePtr content = NULL;
12775     xmlNodePtr last = NULL;
12776     int size;
12777     xmlParserErrors ret = XML_ERR_OK;
12778 #ifdef SAX2
12779     int i;
12780 #endif
12781 
12782     if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) ||
12783         (oldctxt->depth >  1024)) {
12784     return(XML_ERR_ENTITY_LOOP);
12785     }
12786 
12787 
12788     if (lst != NULL)
12789         *lst = NULL;
12790     if (string == NULL)
12791         return(XML_ERR_INTERNAL_ERROR);
12792 
12793     size = xmlStrlen(string);
12794 
12795     ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
12796     if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
12797     if (user_data != NULL)
12798     ctxt->userData = user_data;
12799     else
12800     ctxt->userData = ctxt;
12801     if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
12802     ctxt->dict = oldctxt->dict;
12803     ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
12804     ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
12805     ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
12806 
12807 #ifdef SAX2
12808     /* propagate namespaces down the entity */
12809     for (i = 0;i < oldctxt->nsNr;i += 2) {
12810         nsPush(ctxt, oldctxt->nsTab[i], oldctxt->nsTab[i+1]);
12811     }
12812 #endif
12813 
12814     oldsax = ctxt->sax;
12815     ctxt->sax = oldctxt->sax;
12816     xmlDetectSAX2(ctxt);
12817     ctxt->replaceEntities = oldctxt->replaceEntities;
12818     ctxt->options = oldctxt->options;
12819 
12820     ctxt->_private = oldctxt->_private;
12821     if (oldctxt->myDoc == NULL) {
12822     newDoc = xmlNewDoc(BAD_CAST "1.0");
12823     if (newDoc == NULL) {
12824         ctxt->sax = oldsax;
12825         ctxt->dict = NULL;
12826         xmlFreeParserCtxt(ctxt);
12827         return(XML_ERR_INTERNAL_ERROR);
12828     }
12829     newDoc->properties = XML_DOC_INTERNAL;
12830     newDoc->dict = ctxt->dict;
12831     xmlDictReference(newDoc->dict);
12832     ctxt->myDoc = newDoc;
12833     } else {
12834     ctxt->myDoc = oldctxt->myDoc;
12835         content = ctxt->myDoc->children;
12836     last = ctxt->myDoc->last;
12837     }
12838     newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
12839     if (newRoot == NULL) {
12840     ctxt->sax = oldsax;
12841     ctxt->dict = NULL;
12842     xmlFreeParserCtxt(ctxt);
12843     if (newDoc != NULL) {
12844         xmlFreeDoc(newDoc);
12845     }
12846     return(XML_ERR_INTERNAL_ERROR);
12847     }
12848     ctxt->myDoc->children = NULL;
12849     ctxt->myDoc->last = NULL;
12850     xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
12851     nodePush(ctxt, ctxt->myDoc->children);
12852     ctxt->instate = XML_PARSER_CONTENT;
12853     ctxt->depth = oldctxt->depth + 1;
12854 
12855     ctxt->validate = 0;
12856     ctxt->loadsubset = oldctxt->loadsubset;
12857     if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) {
12858     /*
12859      * ID/IDREF registration will be done in xmlValidateElement below
12860      */
12861     ctxt->loadsubset |= XML_SKIP_IDS;
12862     }
12863     ctxt->dictNames = oldctxt->dictNames;
12864     ctxt->attsDefault = oldctxt->attsDefault;
12865     ctxt->attsSpecial = oldctxt->attsSpecial;
12866 
12867     xmlParseContent(ctxt);
12868     if ((RAW == '<') && (NXT(1) == '/')) {
12869     xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12870     } else if (RAW != 0) {
12871     xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
12872     }
12873     if (ctxt->node != ctxt->myDoc->children) {
12874     xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
12875     }
12876 
12877     if (!ctxt->wellFormed) {
12878         if (ctxt->errNo == 0)
12879         ret = XML_ERR_INTERNAL_ERROR;
12880     else
12881         ret = (xmlParserErrors)ctxt->errNo;
12882     } else {
12883       ret = XML_ERR_OK;
12884     }
12885 
12886     if ((lst != NULL) && (ret == XML_ERR_OK)) {
12887     xmlNodePtr cur;
12888 
12889     /*
12890      * Return the newly created nodeset after unlinking it from
12891      * they pseudo parent.
12892      */
12893     cur = ctxt->myDoc->children->children;
12894     *lst = cur;
12895     while (cur != NULL) {
12896 #ifdef LIBXML_VALID_ENABLED
12897         if ((oldctxt->validate) && (oldctxt->wellFormed) &&
12898         (oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
12899         (cur->type == XML_ELEMENT_NODE)) {
12900         oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
12901             oldctxt->myDoc, cur);
12902         }
12903 #endif /* LIBXML_VALID_ENABLED */
12904         cur->parent = NULL;
12905         cur = cur->next;
12906     }
12907     ctxt->myDoc->children->children = NULL;
12908     }
12909     if (ctxt->myDoc != NULL) {
12910     xmlFreeNode(ctxt->myDoc->children);
12911         ctxt->myDoc->children = content;
12912         ctxt->myDoc->last = last;
12913     }
12914 
12915     /*
12916      * Record in the parent context the number of entities replacement
12917      * done when parsing that reference.
12918      */
12919     if (oldctxt != NULL)
12920         oldctxt->nbentities += ctxt->nbentities;
12921 
12922     /*
12923      * Also record the last error if any
12924      */
12925     if (ctxt->lastError.code != XML_ERR_OK)
12926         xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
12927 
12928     ctxt->sax = oldsax;
12929     ctxt->dict = NULL;
12930     ctxt->attsDefault = NULL;
12931     ctxt->attsSpecial = NULL;
12932     xmlFreeParserCtxt(ctxt);
12933     if (newDoc != NULL) {
12934     xmlFreeDoc(newDoc);
12935     }
12936 
12937     return(ret);
12938 }
12939 
12959 xmlParserErrors
12960 xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
12961                       int options, xmlNodePtr *lst) {
12962 #ifdef SAX2
12963     xmlParserCtxtPtr ctxt;
12964     xmlDocPtr doc = NULL;
12965     xmlNodePtr fake, cur;
12966     int nsnr = 0;
12967 
12968     xmlParserErrors ret = XML_ERR_OK;
12969 
12970     /*
12971      * check all input parameters, grab the document
12972      */
12973     if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
12974         return(XML_ERR_INTERNAL_ERROR);
12975     switch (node->type) {
12976         case XML_ELEMENT_NODE:
12977         case XML_ATTRIBUTE_NODE:
12978         case XML_TEXT_NODE:
12979         case XML_CDATA_SECTION_NODE:
12980         case XML_ENTITY_REF_NODE:
12981         case XML_PI_NODE:
12982         case XML_COMMENT_NODE:
12983         case XML_DOCUMENT_NODE:
12984         case XML_HTML_DOCUMENT_NODE:
12985         break;
12986     default:
12987         return(XML_ERR_INTERNAL_ERROR);
12988 
12989     }
12990     while ((node != NULL) && (node->type != XML_ELEMENT_NODE) &&
12991            (node->type != XML_DOCUMENT_NODE) &&
12992        (node->type != XML_HTML_DOCUMENT_NODE))
12993     node = node->parent;
12994     if (node == NULL)
12995     return(XML_ERR_INTERNAL_ERROR);
12996     if (node->type == XML_ELEMENT_NODE)
12997     doc = node->doc;
12998     else
12999         doc = (xmlDocPtr) node;
13000     if (doc == NULL)
13001     return(XML_ERR_INTERNAL_ERROR);
13002 
13003     /*
13004      * allocate a context and set-up everything not related to the
13005      * node position in the tree
13006      */
13007     if (doc->type == XML_DOCUMENT_NODE)
13008     ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen);
13009 #ifdef LIBXML_HTML_ENABLED
13010     else if (doc->type == XML_HTML_DOCUMENT_NODE) {
13011     ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen);
13012         /*
13013          * When parsing in context, it makes no sense to add implied
13014          * elements like html/body/etc...
13015          */
13016         options |= HTML_PARSE_NOIMPLIED;
13017     }
13018 #endif
13019     else
13020         return(XML_ERR_INTERNAL_ERROR);
13021 
13022     if (ctxt == NULL)
13023         return(XML_ERR_NO_MEMORY);
13024 
13025     /*
13026      * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
13027      * We need a dictionary for xmlDetectSAX2, so if there's no doc dict
13028      * we must wait until the last moment to free the original one.
13029      */
13030     if (doc->dict != NULL) {
13031         if (ctxt->dict != NULL)
13032         xmlDictFree(ctxt->dict);
13033     ctxt->dict = doc->dict;
13034     } else
13035         options |= XML_PARSE_NODICT;
13036 
13037     if (doc->encoding != NULL) {
13038         xmlCharEncodingHandlerPtr hdlr;
13039 
13040         if (ctxt->encoding != NULL)
13041         xmlFree((xmlChar *) ctxt->encoding);
13042         ctxt->encoding = xmlStrdup((const xmlChar *) doc->encoding);
13043 
13044         hdlr = xmlFindCharEncodingHandler(doc->encoding);
13045         if (hdlr != NULL) {
13046             xmlSwitchToEncoding(ctxt, hdlr);
13047     } else {
13048             return(XML_ERR_UNSUPPORTED_ENCODING);
13049         }
13050     }
13051 
13052     xmlCtxtUseOptionsInternal(ctxt, options, NULL);
13053     xmlDetectSAX2(ctxt);
13054     ctxt->myDoc = doc;
13055 
13056     fake = xmlNewComment(NULL);
13057     if (fake == NULL) {
13058         xmlFreeParserCtxt(ctxt);
13059     return(XML_ERR_NO_MEMORY);
13060     }
13061     xmlAddChild(node, fake);
13062 
13063     if (node->type == XML_ELEMENT_NODE) {
13064     nodePush(ctxt, node);
13065     /*
13066      * initialize the SAX2 namespaces stack
13067      */
13068     cur = node;
13069     while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
13070         xmlNsPtr ns = cur->nsDef;
13071         const xmlChar *iprefix, *ihref;
13072 
13073         while (ns != NULL) {
13074         if (ctxt->dict) {
13075             iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1);
13076             ihref = xmlDictLookup(ctxt->dict, ns->href, -1);
13077         } else {
13078             iprefix = ns->prefix;
13079             ihref = ns->href;
13080         }
13081 
13082             if (xmlGetNamespace(ctxt, iprefix) == NULL) {
13083             nsPush(ctxt, iprefix, ihref);
13084             nsnr++;
13085         }
13086         ns = ns->next;
13087         }
13088         cur = cur->parent;
13089     }
13090     ctxt->instate = XML_PARSER_CONTENT;
13091     }
13092 
13093     if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
13094     /*
13095      * ID/IDREF registration will be done in xmlValidateElement below
13096      */
13097     ctxt->loadsubset |= XML_SKIP_IDS;
13098     }
13099 
13100 #ifdef LIBXML_HTML_ENABLED
13101     if (doc->type == XML_HTML_DOCUMENT_NODE)
13102         __htmlParseContent(ctxt);
13103     else
13104 #endif
13105     xmlParseContent(ctxt);
13106 
13107     nsPop(ctxt, nsnr);
13108     if ((RAW == '<') && (NXT(1) == '/')) {
13109     xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13110     } else if (RAW != 0) {
13111     xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13112     }
13113     if ((ctxt->node != NULL) && (ctxt->node != node)) {
13114     xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13115     ctxt->wellFormed = 0;
13116     }
13117 
13118     if (!ctxt->wellFormed) {
13119         if (ctxt->errNo == 0)
13120         ret = XML_ERR_INTERNAL_ERROR;
13121     else
13122         ret = (xmlParserErrors)ctxt->errNo;
13123     } else {
13124         ret = XML_ERR_OK;
13125     }
13126 
13127     /*
13128      * Return the newly created nodeset after unlinking it from
13129      * the pseudo sibling.
13130      */
13131 
13132     cur = fake->next;
13133     fake->next = NULL;
13134     node->last = fake;
13135 
13136     if (cur != NULL) {
13137     cur->prev = NULL;
13138     }
13139 
13140     *lst = cur;
13141 
13142     while (cur != NULL) {
13143     cur->parent = NULL;
13144     cur = cur->next;
13145     }
13146 
13147     xmlUnlinkNode(fake);
13148     xmlFreeNode(fake);
13149 
13150 
13151     if (ret != XML_ERR_OK) {
13152         xmlFreeNodeList(*lst);
13153     *lst = NULL;
13154     }
13155 
13156     if (doc->dict != NULL)
13157         ctxt->dict = NULL;
13158     xmlFreeParserCtxt(ctxt);
13159 
13160     return(ret);
13161 #else /* !SAX2 */
13162     return(XML_ERR_INTERNAL_ERROR);
13163 #endif
13164 }
13165 
13166 #ifdef LIBXML_SAX1_ENABLED
13167 
13192 int
13193 xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
13194      void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
13195      int recover) {
13196     xmlParserCtxtPtr ctxt;
13197     xmlDocPtr newDoc;
13198     xmlSAXHandlerPtr oldsax = NULL;
13199     xmlNodePtr content, newRoot;
13200     int size;
13201     int ret = 0;
13202 
13203     if (depth > 40) {
13204     return(XML_ERR_ENTITY_LOOP);
13205     }
13206 
13207 
13208     if (lst != NULL)
13209         *lst = NULL;
13210     if (string == NULL)
13211         return(-1);
13212 
13213     size = xmlStrlen(string);
13214 
13215     ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
13216     if (ctxt == NULL) return(-1);
13217     ctxt->userData = ctxt;
13218     if (sax != NULL) {
13219     oldsax = ctxt->sax;
13220         ctxt->sax = sax;
13221     if (user_data != NULL)
13222         ctxt->userData = user_data;
13223     }
13224     newDoc = xmlNewDoc(BAD_CAST "1.0");
13225     if (newDoc == NULL) {
13226     xmlFreeParserCtxt(ctxt);
13227     return(-1);
13228     }
13229     newDoc->properties = XML_DOC_INTERNAL;
13230     if ((doc != NULL) && (doc->dict != NULL)) {
13231         xmlDictFree(ctxt->dict);
13232     ctxt->dict = doc->dict;
13233     xmlDictReference(ctxt->dict);
13234     ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13235     ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13236     ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13237     ctxt->dictNames = 1;
13238     } else {
13239     xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT, NULL);
13240     }
13241     if (doc != NULL) {
13242     newDoc->intSubset = doc->intSubset;
13243     newDoc->extSubset = doc->extSubset;
13244     }
13245     newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
13246     if (newRoot == NULL) {
13247     if (sax != NULL)
13248         ctxt->sax = oldsax;
13249     xmlFreeParserCtxt(ctxt);
13250     newDoc->intSubset = NULL;
13251     newDoc->extSubset = NULL;
13252         xmlFreeDoc(newDoc);
13253     return(-1);
13254     }
13255     xmlAddChild((xmlNodePtr) newDoc, newRoot);
13256     nodePush(ctxt, newRoot);
13257     if (doc == NULL) {
13258     ctxt->myDoc = newDoc;
13259     } else {
13260     ctxt->myDoc = newDoc;
13261     newDoc->children->doc = doc;
13262     /* Ensure that doc has XML spec namespace */
13263     xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
13264     newDoc->oldNs = doc->oldNs;
13265     }
13266     ctxt->instate = XML_PARSER_CONTENT;
13267     ctxt->depth = depth;
13268 
13269     /*
13270      * Doing validity checking on chunk doesn't make sense
13271      */
13272     ctxt->validate = 0;
13273     ctxt->loadsubset = 0;
13274     xmlDetectSAX2(ctxt);
13275 
13276     if ( doc != NULL ){
13277         content = doc->children;
13278         doc->children = NULL;
13279         xmlParseContent(ctxt);
13280         doc->children = content;
13281     }
13282     else {
13283         xmlParseContent(ctxt);
13284     }
13285     if ((RAW == '<') && (NXT(1) == '/')) {
13286     xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13287     } else if (RAW != 0) {
13288     xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13289     }
13290     if (ctxt->node != newDoc->children) {
13291     xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13292     }
13293 
13294     if (!ctxt->wellFormed) {
13295         if (ctxt->errNo == 0)
13296         ret = 1;
13297     else
13298         ret = ctxt->errNo;
13299     } else {
13300       ret = 0;
13301     }
13302 
13303     if ((lst != NULL) && ((ret == 0) || (recover == 1))) {
13304     xmlNodePtr cur;
13305 
13306     /*
13307      * Return the newly created nodeset after unlinking it from
13308      * they pseudo parent.
13309      */
13310     cur = newDoc->children->children;
13311     *lst = cur;
13312     while (cur != NULL) {
13313         xmlSetTreeDoc(cur, doc);
13314         cur->parent = NULL;
13315         cur = cur->next;
13316     }
13317     newDoc->children->children = NULL;
13318     }
13319 
13320     if (sax != NULL)
13321     ctxt->sax = oldsax;
13322     xmlFreeParserCtxt(ctxt);
13323     newDoc->intSubset = NULL;
13324     newDoc->extSubset = NULL;
13325     newDoc->oldNs = NULL;
13326     xmlFreeDoc(newDoc);
13327 
13328     return(ret);
13329 }
13330 
13347 xmlDocPtr
13348 xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
13349     xmlDocPtr ret;
13350     xmlParserCtxtPtr ctxt;
13351 
13352     ctxt = xmlCreateFileParserCtxt(filename);
13353     if (ctxt == NULL) {
13354     return(NULL);
13355     }
13356     if (sax != NULL) {
13357     if (ctxt->sax != NULL)
13358         xmlFree(ctxt->sax);
13359         ctxt->sax = sax;
13360         ctxt->userData = NULL;
13361     }
13362 
13363     xmlParseExtParsedEnt(ctxt);
13364 
13365     if (ctxt->wellFormed)
13366     ret = ctxt->myDoc;
13367     else {
13368         ret = NULL;
13369         xmlFreeDoc(ctxt->myDoc);
13370         ctxt->myDoc = NULL;
13371     }
13372     if (sax != NULL)
13373         ctxt->sax = NULL;
13374     xmlFreeParserCtxt(ctxt);
13375 
13376     return(ret);
13377 }
13378 
13392 xmlDocPtr
13393 xmlParseEntity(const char *filename) {
13394     return(xmlSAXParseEntity(NULL, filename));
13395 }
13396 #endif /* LIBXML_SAX1_ENABLED */
13397 
13411 static xmlParserCtxtPtr
13412 xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
13413                       const xmlChar *base, xmlParserCtxtPtr pctx) {
13414     xmlParserCtxtPtr ctxt;
13415     xmlParserInputPtr inputStream;
13416     char *directory = NULL;
13417     xmlChar *uri;
13418 
13419     ctxt = xmlNewParserCtxt();
13420     if (ctxt == NULL) {
13421     return(NULL);
13422     }
13423 
13424     if (pctx != NULL) {
13425         ctxt->options = pctx->options;
13426         ctxt->_private = pctx->_private;
13427     }
13428 
13429     uri = xmlBuildURI(URL, base);
13430 
13431     if (uri == NULL) {
13432     inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
13433     if (inputStream == NULL) {
13434         xmlFreeParserCtxt(ctxt);
13435         return(NULL);
13436     }
13437 
13438     inputPush(ctxt, inputStream);
13439 
13440     if ((ctxt->directory == NULL) && (directory == NULL))
13441         directory = xmlParserGetDirectory((char *)URL);
13442     if ((ctxt->directory == NULL) && (directory != NULL))
13443         ctxt->directory = directory;
13444     } else {
13445     inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
13446     if (inputStream == NULL) {
13447         xmlFree(uri);
13448         xmlFreeParserCtxt(ctxt);
13449         return(NULL);
13450     }
13451 
13452     inputPush(ctxt, inputStream);
13453 
13454     if ((ctxt->directory == NULL) && (directory == NULL))
13455         directory = xmlParserGetDirectory((char *)uri);
13456     if ((ctxt->directory == NULL) && (directory != NULL))
13457         ctxt->directory = directory;
13458     xmlFree(uri);
13459     }
13460     return(ctxt);
13461 }
13462 
13475 xmlParserCtxtPtr
13476 xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
13477                       const xmlChar *base) {
13478     return xmlCreateEntityParserCtxtInternal(URL, ID, base, NULL);
13479 
13480 }
13481 
13482 /************************************************************************
13483  *                                  *
13484  *      Front ends when parsing from a file         *
13485  *                                  *
13486  ************************************************************************/
13487 
13499 xmlParserCtxtPtr
13500 xmlCreateURLParserCtxt(const char *filename, int options)
13501 {
13502     xmlParserCtxtPtr ctxt;
13503     xmlParserInputPtr inputStream;
13504     char *directory = NULL;
13505 
13506     ctxt = xmlNewParserCtxt();
13507     if (ctxt == NULL) {
13508     xmlErrMemory(NULL, "cannot allocate parser context");
13509     return(NULL);
13510     }
13511 
13512     if (options)
13513     xmlCtxtUseOptionsInternal(ctxt, options, NULL);
13514     ctxt->linenumbers = 1;
13515 
13516     inputStream = xmlLoadExternalEntity(filename, NULL, ctxt);
13517     if (inputStream == NULL) {
13518     xmlFreeParserCtxt(ctxt);
13519     return(NULL);
13520     }
13521 
13522     inputPush(ctxt, inputStream);
13523     if ((ctxt->directory == NULL) && (directory == NULL))
13524         directory = xmlParserGetDirectory(filename);
13525     if ((ctxt->directory == NULL) && (directory != NULL))
13526         ctxt->directory = directory;
13527 
13528     return(ctxt);
13529 }
13530 
13541 xmlParserCtxtPtr
13542 xmlCreateFileParserCtxt(const char *filename)
13543 {
13544     return(xmlCreateURLParserCtxt(filename, 0));
13545 }
13546 
13547 #ifdef LIBXML_SAX1_ENABLED
13548 
13567 xmlDocPtr
13568 xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
13569                         int recovery, void *data) {
13570     xmlDocPtr ret;
13571     xmlParserCtxtPtr ctxt;
13572 
13573     xmlInitParser();
13574 
13575     ctxt = xmlCreateFileParserCtxt(filename);
13576     if (ctxt == NULL) {
13577     return(NULL);
13578     }
13579     if (sax != NULL) {
13580     if (ctxt->sax != NULL)
13581         xmlFree(ctxt->sax);
13582         ctxt->sax = sax;
13583     }
13584     xmlDetectSAX2(ctxt);
13585     if (data!=NULL) {
13586     ctxt->_private = data;
13587     }
13588 
13589     if (ctxt->directory == NULL)
13590         ctxt->directory = xmlParserGetDirectory(filename);
13591 
13592     ctxt->recovery = recovery;
13593 
13594     xmlParseDocument(ctxt);
13595 
13596     if ((ctxt->wellFormed) || recovery) {
13597         ret = ctxt->myDoc;
13598     if (ret != NULL) {
13599         if (ctxt->input->buf->compressed > 0)
13600         ret->compression = 9;
13601         else
13602         ret->compression = ctxt->input->buf->compressed;
13603     }
13604     }
13605     else {
13606        ret = NULL;
13607        xmlFreeDoc(ctxt->myDoc);
13608        ctxt->myDoc = NULL;
13609     }
13610     if (sax != NULL)
13611         ctxt->sax = NULL;
13612     xmlFreeParserCtxt(ctxt);
13613     
13614     return(ret);
13615 }
13616 
13632 xmlDocPtr
13633 xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
13634                           int recovery) {
13635     return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
13636 }
13637 
13649 xmlDocPtr
13650 xmlRecoverDoc(const xmlChar *cur) {
13651     return(xmlSAXParseDoc(NULL, cur, 1));
13652 }
13653 
13665 xmlDocPtr
13666 xmlParseFile(const char *filename) {
13667     return(xmlSAXParseFile(NULL, filename, 0));
13668 }
13669 
13682 xmlDocPtr
13683 xmlRecoverFile(const char *filename) {
13684     return(xmlSAXParseFile(NULL, filename, 1));
13685 }
13686 
13687 
13698 void
13699 xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
13700                              const char* filename)
13701 {
13702     xmlParserInputPtr input;
13703 
13704     if ((ctxt == NULL) || (buffer == NULL))
13705         return;
13706 
13707     input = xmlNewInputStream(ctxt);
13708     if (input == NULL) {
13709         xmlErrMemory(NULL, "parsing new buffer: out of memory\n");
13710         xmlClearParserCtxt(ctxt);
13711         return;
13712     }
13713   
13714     xmlClearParserCtxt(ctxt);
13715     if (filename != NULL)
13716         input->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
13717     input->base = buffer;
13718     input->cur = buffer;
13719     input->end = &buffer[xmlStrlen(buffer)];
13720     inputPush(ctxt, input);
13721 }
13722 
13734 int
13735 xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
13736                     const char *filename) {
13737     int ret = 0;
13738     xmlParserCtxtPtr ctxt;
13739     
13740     ctxt = xmlCreateFileParserCtxt(filename);
13741     if (ctxt == NULL) return -1;
13742     if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
13743     xmlFree(ctxt->sax);
13744     ctxt->sax = sax;
13745     xmlDetectSAX2(ctxt);
13746 
13747     if (user_data != NULL)
13748     ctxt->userData = user_data;
13749     
13750     xmlParseDocument(ctxt);
13751     
13752     if (ctxt->wellFormed)
13753     ret = 0;
13754     else {
13755         if (ctxt->errNo != 0)
13756         ret = ctxt->errNo;
13757     else
13758         ret = -1;
13759     }
13760     if (sax != NULL)
13761     ctxt->sax = NULL;
13762     if (ctxt->myDoc != NULL) {
13763         xmlFreeDoc(ctxt->myDoc);
13764     ctxt->myDoc = NULL;
13765     }
13766     xmlFreeParserCtxt(ctxt);
13767     
13768     return ret;
13769 }
13770 #endif /* LIBXML_SAX1_ENABLED */
13771 
13772 /************************************************************************
13773  *                                  *
13774  *      Front ends when parsing from memory         *
13775  *                                  *
13776  ************************************************************************/
13777 
13787 xmlParserCtxtPtr
13788 xmlCreateMemoryParserCtxt(const char *buffer, int size) {
13789     xmlParserCtxtPtr ctxt;
13790     xmlParserInputPtr input;
13791     xmlParserInputBufferPtr buf;
13792 
13793     if (buffer == NULL)
13794     return(NULL);
13795     if (size <= 0)
13796     return(NULL);
13797 
13798     ctxt = xmlNewParserCtxt();
13799     if (ctxt == NULL)
13800     return(NULL);
13801 
13802     /* TODO: xmlParserInputBufferCreateStatic, requires some serious changes */
13803     buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
13804     if (buf == NULL) {
13805     xmlFreeParserCtxt(ctxt);
13806     return(NULL);
13807     }
13808 
13809     input = xmlNewInputStream(ctxt);
13810     if (input == NULL) {
13811     xmlFreeParserInputBuffer(buf);
13812     xmlFreeParserCtxt(ctxt);
13813     return(NULL);
13814     }
13815 
13816     input->filename = NULL;
13817     input->buf = buf;
13818     input->base = input->buf->buffer->content;
13819     input->cur = input->buf->buffer->content;
13820     input->end = &input->buf->buffer->content[input->buf->buffer->use];
13821 
13822     inputPush(ctxt, input);
13823     return(ctxt);
13824 }
13825 
13826 #ifdef LIBXML_SAX1_ENABLED
13827 
13846 xmlDocPtr
13847 xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
13848               int size, int recovery, void *data) {
13849     xmlDocPtr ret;
13850     xmlParserCtxtPtr ctxt;
13851 
13852     xmlInitParser();
13853 
13854     ctxt = xmlCreateMemoryParserCtxt(buffer, size);
13855     if (ctxt == NULL) return(NULL);
13856     if (sax != NULL) {
13857     if (ctxt->sax != NULL)
13858         xmlFree(ctxt->sax);
13859         ctxt->sax = sax;
13860     }
13861     xmlDetectSAX2(ctxt);
13862     if (data!=NULL) {
13863     ctxt->_private=data;
13864     }
13865 
13866     ctxt->recovery = recovery;
13867 
13868     xmlParseDocument(ctxt);
13869 
13870     if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
13871     else {
13872        ret = NULL;
13873        xmlFreeDoc(ctxt->myDoc);
13874        ctxt->myDoc = NULL;
13875     }
13876     if (sax != NULL) 
13877     ctxt->sax = NULL;
13878     xmlFreeParserCtxt(ctxt);
13879 
13880     return(ret);
13881 }
13882 
13897 xmlDocPtr
13898 xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
13899               int size, int recovery) {
13900     return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
13901 }
13902 
13913 xmlDocPtr xmlParseMemory(const char *buffer, int size) {
13914    return(xmlSAXParseMemory(NULL, buffer, size, 0));
13915 }
13916 
13929 xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
13930    return(xmlSAXParseMemory(NULL, buffer, size, 1));
13931 }
13932 
13945 int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
13946               const char *buffer, int size) {
13947     int ret = 0;
13948     xmlParserCtxtPtr ctxt;
13949 
13950     xmlInitParser();
13951 
13952     ctxt = xmlCreateMemoryParserCtxt(buffer, size);
13953     if (ctxt == NULL) return -1;
13954     if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
13955         xmlFree(ctxt->sax);
13956     ctxt->sax = sax;
13957     xmlDetectSAX2(ctxt);
13958 
13959     if (user_data != NULL)
13960     ctxt->userData = user_data;
13961 
13962     xmlParseDocument(ctxt);
13963     
13964     if (ctxt->wellFormed)
13965     ret = 0;
13966     else {
13967         if (ctxt->errNo != 0)
13968         ret = ctxt->errNo;
13969     else
13970         ret = -1;
13971     }
13972     if (sax != NULL)
13973         ctxt->sax = NULL;
13974     if (ctxt->myDoc != NULL) {
13975         xmlFreeDoc(ctxt->myDoc);
13976     ctxt->myDoc = NULL;
13977     }
13978     xmlFreeParserCtxt(ctxt);
13979     
13980     return ret;
13981 }
13982 #endif /* LIBXML_SAX1_ENABLED */
13983 
13992 xmlParserCtxtPtr
13993 xmlCreateDocParserCtxt(const xmlChar *cur) {
13994     int len;
13995 
13996     if (cur == NULL)
13997     return(NULL);
13998     len = xmlStrlen(cur);
13999     return(xmlCreateMemoryParserCtxt((const char *)cur, len));
14000 }
14001 
14002 #ifdef LIBXML_SAX1_ENABLED
14003 
14017 xmlDocPtr
14018 xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
14019     xmlDocPtr ret;
14020     xmlParserCtxtPtr ctxt;
14021     xmlSAXHandlerPtr oldsax = NULL;
14022 
14023     if (cur == NULL) return(NULL);
14024 
14025 
14026     ctxt = xmlCreateDocParserCtxt(cur);
14027     if (ctxt == NULL) return(NULL);
14028     if (sax != NULL) { 
14029         oldsax = ctxt->sax;
14030         ctxt->sax = sax;
14031         ctxt->userData = NULL;
14032     }
14033     xmlDetectSAX2(ctxt);
14034 
14035     xmlParseDocument(ctxt);
14036     if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14037     else {
14038        ret = NULL;
14039        xmlFreeDoc(ctxt->myDoc);
14040        ctxt->myDoc = NULL;
14041     }
14042     if (sax != NULL)
14043     ctxt->sax = oldsax;
14044     xmlFreeParserCtxt(ctxt);
14045     
14046     return(ret);
14047 }
14048 
14058 xmlDocPtr
14059 xmlParseDoc(const xmlChar *cur) {
14060     return(xmlSAXParseDoc(NULL, cur, 0));
14061 }
14062 #endif /* LIBXML_SAX1_ENABLED */
14063 
14064 #ifdef LIBXML_LEGACY_ENABLED
14065 /************************************************************************
14066  *                                  *
14067  *  Specific function to keep track of entities references      *
14068  *  and used by the XSLT debugger                   *
14069  *                                  *
14070  ************************************************************************/
14071 
14072 static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
14073 
14082 static void
14083 xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
14084                       xmlNodePtr lastNode)
14085 {
14086     if (xmlEntityRefFunc != NULL) {
14087         (*xmlEntityRefFunc) (ent, firstNode, lastNode);
14088     }
14089 }
14090 
14091 
14098 void
14099 xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
14100 {
14101     xmlEntityRefFunc = func;
14102 }
14103 #endif /* LIBXML_LEGACY_ENABLED */
14104 
14105 /************************************************************************
14106  *                                  *
14107  *              Miscellaneous               *
14108  *                                  *
14109  ************************************************************************/
14110 
14111 #ifdef LIBXML_XPATH_ENABLED
14112 #include <libxml/xpath.h>
14113 #endif
14114 
14115 extern void XMLCDECL xmlGenericErrorDefaultFunc(void *ctx, const char *msg, ...);
14116 static int xmlParserInitialized = 0;
14117 
14126 void
14127 xmlInitParser(void) {
14128     if (xmlParserInitialized != 0)
14129     return;
14130 
14131 #ifdef LIBXML_THREAD_ENABLED
14132     __xmlGlobalInitMutexLock();
14133     if (xmlParserInitialized == 0) {
14134 #endif
14135     xmlInitThreads();
14136     xmlInitGlobals();
14137     if ((xmlGenericError == xmlGenericErrorDefaultFunc) ||
14138         (xmlGenericError == NULL))
14139         initGenericErrorDefaultFunc(NULL);
14140     xmlInitMemory();
14141     xmlInitCharEncodingHandlers();
14142     xmlDefaultSAXHandlerInit();
14143     xmlRegisterDefaultInputCallbacks();
14144 #ifdef LIBXML_OUTPUT_ENABLED
14145     xmlRegisterDefaultOutputCallbacks();
14146 #endif /* LIBXML_OUTPUT_ENABLED */
14147 #ifdef LIBXML_HTML_ENABLED
14148     htmlInitAutoClose();
14149     htmlDefaultSAXHandlerInit();
14150 #endif
14151 #ifdef LIBXML_XPATH_ENABLED
14152     xmlXPathInit();
14153 #endif
14154     xmlParserInitialized = 1;
14155 #ifdef LIBXML_THREAD_ENABLED
14156     }
14157     __xmlGlobalInitMutexUnlock();
14158 #endif
14159 }
14160 
14183 void
14184 xmlCleanupParser(void) {
14185     if (!xmlParserInitialized)
14186     return;
14187 
14188     xmlCleanupCharEncodingHandlers();
14189 #ifdef LIBXML_CATALOG_ENABLED
14190     xmlCatalogCleanup();
14191 #endif
14192     xmlDictCleanup();
14193     xmlCleanupInputCallbacks();
14194 #ifdef LIBXML_OUTPUT_ENABLED
14195     xmlCleanupOutputCallbacks();
14196 #endif
14197 #ifdef LIBXML_SCHEMAS_ENABLED
14198     xmlSchemaCleanupTypes();
14199     xmlRelaxNGCleanupTypes();
14200 #endif
14201     xmlCleanupGlobals();
14202     xmlResetLastError();
14203     xmlCleanupThreads(); /* must be last if called not from the main thread */
14204     xmlCleanupMemory();
14205     xmlParserInitialized = 0;
14206 }
14207 
14208 /************************************************************************
14209  *                                  *
14210  *  New set (2.6.0) of simpler and more flexible APIs       *
14211  *                                  *
14212  ************************************************************************/
14213 
14221 #define DICT_FREE(str)                      \
14222     if ((str) && ((!dict) ||                \
14223         (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))  \
14224         xmlFree((char *)(str));
14225 
14232 void
14233 xmlCtxtReset(xmlParserCtxtPtr ctxt)
14234 {
14235     xmlParserInputPtr input;
14236     xmlDictPtr dict;
14237     
14238     if (ctxt == NULL)
14239         return;
14240 
14241     dict = ctxt->dict;
14242 
14243     while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
14244         xmlFreeInputStream(input);
14245     }
14246     ctxt->inputNr = 0;
14247     ctxt->input = NULL;
14248 
14249     ctxt->spaceNr = 0;
14250     if (ctxt->spaceTab != NULL) {
14251     ctxt->spaceTab[0] = -1;
14252     ctxt->space = &ctxt->spaceTab[0];
14253     } else {
14254         ctxt->space = NULL;
14255     }
14256 
14257 
14258     ctxt->nodeNr = 0;
14259     ctxt->node = NULL;
14260 
14261     ctxt->nameNr = 0;
14262     ctxt->name = NULL;
14263 
14264     DICT_FREE(ctxt->version);
14265     ctxt->version = NULL;
14266     DICT_FREE(ctxt->encoding);
14267     ctxt->encoding = NULL;
14268     DICT_FREE(ctxt->directory);
14269     ctxt->directory = NULL;
14270     DICT_FREE(ctxt->extSubURI);
14271     ctxt->extSubURI = NULL;
14272     DICT_FREE(ctxt->extSubSystem);
14273     ctxt->extSubSystem = NULL;
14274     if (ctxt->myDoc != NULL)
14275         xmlFreeDoc(ctxt->myDoc);
14276     ctxt->myDoc = NULL;
14277 
14278     ctxt->standalone = -1;
14279     ctxt->hasExternalSubset = 0;
14280     ctxt->hasPErefs = 0;
14281     ctxt->html = 0;
14282     ctxt->external = 0;
14283     ctxt->instate = XML_PARSER_START;
14284     ctxt->token = 0;
14285 
14286     ctxt->wellFormed = 1;
14287     ctxt->nsWellFormed = 1;
14288     ctxt->disableSAX = 0;
14289     ctxt->valid = 1;
14290 #if 0
14291     ctxt->vctxt.userData = ctxt;
14292     ctxt->vctxt.error = xmlParserValidityError;
14293     ctxt->vctxt.warning = xmlParserValidityWarning;
14294 #endif
14295     ctxt->record_info = 0;
14296     ctxt->nbChars = 0;
14297     ctxt->checkIndex = 0;
14298     ctxt->inSubset = 0;
14299     ctxt->errNo = XML_ERR_OK;
14300     ctxt->depth = 0;
14301     ctxt->charset = XML_CHAR_ENCODING_UTF8;
14302     ctxt->catalogs = NULL;
14303     ctxt->nbentities = 0;
14304     ctxt->sizeentities = 0;
14305     xmlInitNodeInfoSeq(&ctxt->node_seq);
14306 
14307     if (ctxt->attsDefault != NULL) {
14308         xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree);
14309         ctxt->attsDefault = NULL;
14310     }
14311     if (ctxt->attsSpecial != NULL) {
14312         xmlHashFree(ctxt->attsSpecial, NULL);
14313         ctxt->attsSpecial = NULL;
14314     }
14315 
14316 #ifdef LIBXML_CATALOG_ENABLED
14317     if (ctxt->catalogs != NULL)
14318     xmlCatalogFreeLocal(ctxt->catalogs);
14319 #endif
14320     if (ctxt->lastError.code != XML_ERR_OK)
14321         xmlResetError(&ctxt->lastError);
14322 }
14323 
14336 int
14337 xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
14338                  int size, const char *filename, const char *encoding)
14339 {
14340     xmlParserInputPtr inputStream;
14341     xmlParserInputBufferPtr buf;
14342     xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
14343 
14344     if (ctxt == NULL)
14345         return(1);
14346 
14347     if ((encoding == NULL) && (chunk != NULL) && (size >= 4))
14348         enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
14349 
14350     buf = xmlAllocParserInputBuffer(enc);
14351     if (buf == NULL)
14352         return(1);
14353 
14354     if (ctxt == NULL) {
14355         xmlFreeParserInputBuffer(buf);
14356         return(1);
14357     }
14358 
14359     xmlCtxtReset(ctxt);
14360 
14361     if (ctxt->pushTab == NULL) {
14362         ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
14363                                         sizeof(xmlChar *));
14364         if (ctxt->pushTab == NULL) {
14365         xmlErrMemory(ctxt, NULL);
14366             xmlFreeParserInputBuffer(buf);
14367             return(1);
14368         }
14369     }
14370 
14371     if (filename == NULL) {
14372         ctxt->directory = NULL;
14373     } else {
14374         ctxt->directory = xmlParserGetDirectory(filename);
14375     }
14376 
14377     inputStream = xmlNewInputStream(ctxt);
14378     if (inputStream == NULL) {
14379         xmlFreeParserInputBuffer(buf);
14380         return(1);
14381     }
14382 
14383     if (filename == NULL)
14384         inputStream->filename = NULL;
14385     else
14386         inputStream->filename = (char *)
14387             xmlCanonicPath((const xmlChar *) filename);
14388     inputStream->buf = buf;
14389     inputStream->base = inputStream->buf->buffer->content;
14390     inputStream->cur = inputStream->buf->buffer->content;
14391     inputStream->end =
14392         &inputStream->buf->buffer->content[inputStream->buf->buffer->use];
14393 
14394     inputPush(ctxt, inputStream);
14395 
14396     if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
14397         (ctxt->input->buf != NULL)) {
14398         int base = ctxt->input->base - ctxt->input->buf->buffer->content;
14399         int cur = ctxt->input->cur - ctxt->input->base;
14400 
14401         xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
14402 
14403         ctxt->input->base = ctxt->input->buf->buffer->content + base;
14404         ctxt->input->cur = ctxt->input->base + cur;
14405         ctxt->input->end =
14406             &ctxt->input->buf->buffer->content[ctxt->input->buf->buffer->
14407                                                use];
14408 #ifdef DEBUG_PUSH
14409         xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
14410 #endif
14411     }
14412 
14413     if (encoding != NULL) {
14414         xmlCharEncodingHandlerPtr hdlr;
14415 
14416         if (ctxt->encoding != NULL)
14417         xmlFree((xmlChar *) ctxt->encoding);
14418         ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
14419 
14420         hdlr = xmlFindCharEncodingHandler(encoding);
14421         if (hdlr != NULL) {
14422             xmlSwitchToEncoding(ctxt, hdlr);
14423     } else {
14424         xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
14425                   "Unsupported encoding %s\n", BAD_CAST encoding);
14426         }
14427     } else if (enc != XML_CHAR_ENCODING_NONE) {
14428         xmlSwitchEncoding(ctxt, enc);
14429     }
14430 
14431     return(0);
14432 }
14433 
14434 
14446 static int
14447 xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encoding)
14448 {
14449     if (ctxt == NULL)
14450         return(-1);
14451     if (encoding != NULL) {
14452         if (ctxt->encoding != NULL)
14453         xmlFree((xmlChar *) ctxt->encoding);
14454         ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
14455     }
14456     if (options & XML_PARSE_RECOVER) {
14457         ctxt->recovery = 1;
14458         options -= XML_PARSE_RECOVER;
14459     ctxt->options |= XML_PARSE_RECOVER;
14460     } else
14461         ctxt->recovery = 0;
14462     if (options & XML_PARSE_DTDLOAD) {
14463         ctxt->loadsubset = XML_DETECT_IDS;
14464         options -= XML_PARSE_DTDLOAD;
14465     ctxt->options |= XML_PARSE_DTDLOAD;
14466     } else
14467         ctxt->loadsubset = 0;
14468     if (options & XML_PARSE_DTDATTR) {
14469         ctxt->loadsubset |= XML_COMPLETE_ATTRS;
14470         options -= XML_PARSE_DTDATTR;
14471     ctxt->options |= XML_PARSE_DTDATTR;
14472     }
14473     if (options & XML_PARSE_NOENT) {
14474         ctxt->replaceEntities = 1;
14475         /* ctxt->loadsubset |= XML_DETECT_IDS; */
14476         options -= XML_PARSE_NOENT;
14477     ctxt->options |= XML_PARSE_NOENT;
14478     } else
14479         ctxt->replaceEntities = 0;
14480     if (options & XML_PARSE_PEDANTIC) {
14481         ctxt->pedantic = 1;
14482         options -= XML_PARSE_PEDANTIC;
14483     ctxt->options |= XML_PARSE_PEDANTIC;
14484     } else
14485         ctxt->pedantic = 0;
14486     if (options & XML_PARSE_NOBLANKS) {
14487         ctxt->keepBlanks = 0;
14488         ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
14489         options -= XML_PARSE_NOBLANKS;
14490     ctxt->options |= XML_PARSE_NOBLANKS;
14491     } else
14492         ctxt->keepBlanks = 1;
14493     if (options & XML_PARSE_DTDVALID) {
14494         ctxt->validate = 1;
14495         if (options & XML_PARSE_NOWARNING)
14496             ctxt->vctxt.warning = NULL;
14497         if (options & XML_PARSE_NOERROR)
14498             ctxt->vctxt.error = NULL;
14499         options -= XML_PARSE_DTDVALID;
14500     ctxt->options |= XML_PARSE_DTDVALID;
14501     } else
14502         ctxt->validate = 0;
14503     if (options & XML_PARSE_NOWARNING) {
14504         ctxt->sax->warning = NULL;
14505         options -= XML_PARSE_NOWARNING;
14506     }
14507     if (options & XML_PARSE_NOERROR) {
14508         ctxt->sax->error = NULL;
14509         ctxt->sax->fatalError = NULL;
14510         options -= XML_PARSE_NOERROR;
14511     }
14512 #ifdef LIBXML_SAX1_ENABLED
14513     if (options & XML_PARSE_SAX1) {
14514         ctxt->sax->startElement = xmlSAX2StartElement;
14515         ctxt->sax->endElement = xmlSAX2EndElement;
14516         ctxt->sax->startElementNs = NULL;
14517         ctxt->sax->endElementNs = NULL;
14518         ctxt->sax->initialized = 1;
14519         options -= XML_PARSE_SAX1;
14520     ctxt->options |= XML_PARSE_SAX1;
14521     }
14522 #endif /* LIBXML_SAX1_ENABLED */
14523     if (options & XML_PARSE_NODICT) {
14524         ctxt->dictNames = 0;
14525         options -= XML_PARSE_NODICT;
14526     ctxt->options |= XML_PARSE_NODICT;
14527     } else {
14528         ctxt->dictNames = 1;
14529     }
14530     if (options & XML_PARSE_NOCDATA) {
14531         ctxt->sax->cdataBlock = NULL;
14532         options -= XML_PARSE_NOCDATA;
14533     ctxt->options |= XML_PARSE_NOCDATA;
14534     }
14535     if (options & XML_PARSE_NSCLEAN) {
14536     ctxt->options |= XML_PARSE_NSCLEAN;
14537         options -= XML_PARSE_NSCLEAN;
14538     }
14539     if (options & XML_PARSE_NONET) {
14540     ctxt->options |= XML_PARSE_NONET;
14541         options -= XML_PARSE_NONET;
14542     }
14543     if (options & XML_PARSE_COMPACT) {
14544     ctxt->options |= XML_PARSE_COMPACT;
14545         options -= XML_PARSE_COMPACT;
14546     }
14547     if (options & XML_PARSE_OLD10) {
14548     ctxt->options |= XML_PARSE_OLD10;
14549         options -= XML_PARSE_OLD10;
14550     }
14551     if (options & XML_PARSE_NOBASEFIX) {
14552     ctxt->options |= XML_PARSE_NOBASEFIX;
14553         options -= XML_PARSE_NOBASEFIX;
14554     }
14555     if (options & XML_PARSE_HUGE) {
14556     ctxt->options |= XML_PARSE_HUGE;
14557         options -= XML_PARSE_HUGE;
14558     }
14559     if (options & XML_PARSE_OLDSAX) {
14560     ctxt->options |= XML_PARSE_OLDSAX;
14561         options -= XML_PARSE_OLDSAX;
14562     }
14563     ctxt->linenumbers = 1;
14564     return (options);
14565 }
14566 
14577 int
14578 xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
14579 {
14580    return(xmlCtxtUseOptionsInternal(ctxt, options, NULL));
14581 }
14582 
14595 static xmlDocPtr
14596 xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
14597           int options, int reuse)
14598 {
14599     xmlDocPtr ret;
14600 
14601     xmlCtxtUseOptionsInternal(ctxt, options, encoding);
14602     if (encoding != NULL) {
14603         xmlCharEncodingHandlerPtr hdlr;
14604 
14605     hdlr = xmlFindCharEncodingHandler(encoding);
14606     if (hdlr != NULL)
14607         xmlSwitchToEncoding(ctxt, hdlr);
14608     }
14609     if ((URL != NULL) && (ctxt->input != NULL) &&
14610         (ctxt->input->filename == NULL))
14611         ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
14612     xmlParseDocument(ctxt);
14613     if ((ctxt->wellFormed) || ctxt->recovery)
14614         ret = ctxt->myDoc;
14615     else {
14616         ret = NULL;
14617     if (ctxt->myDoc != NULL) {
14618         xmlFreeDoc(ctxt->myDoc);
14619     }
14620     }
14621     ctxt->myDoc = NULL;
14622     if (!reuse) {
14623     xmlFreeParserCtxt(ctxt);
14624     }
14625 
14626     return (ret);
14627 }
14628 
14640 xmlDocPtr
14641 xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
14642 {
14643     xmlParserCtxtPtr ctxt;
14644 
14645     if (cur == NULL)
14646         return (NULL);
14647 
14648     ctxt = xmlCreateDocParserCtxt(cur);
14649     if (ctxt == NULL)
14650         return (NULL);
14651     return (xmlDoRead(ctxt, URL, encoding, options, 0));
14652 }
14653 
14664 xmlDocPtr
14665 xmlReadFile(const char *filename, const char *encoding, int options)
14666 {
14667     xmlParserCtxtPtr ctxt;
14668 
14669     ctxt = xmlCreateURLParserCtxt(filename, options);
14670     if (ctxt == NULL)
14671         return (NULL);
14672     return (xmlDoRead(ctxt, NULL, encoding, options, 0));
14673 }
14674 
14687 xmlDocPtr
14688 xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
14689 {
14690     xmlParserCtxtPtr ctxt;
14691 
14692     ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14693     if (ctxt == NULL)
14694         return (NULL);
14695     return (xmlDoRead(ctxt, URL, encoding, options, 0));
14696 }
14697 
14711 xmlDocPtr
14712 xmlReadFd(int fd, const char *URL, const char *encoding, int options)
14713 {
14714     xmlParserCtxtPtr ctxt;
14715     xmlParserInputBufferPtr input;
14716     xmlParserInputPtr stream;
14717 
14718     if (fd < 0)
14719         return (NULL);
14720 
14721     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
14722     if (input == NULL)
14723         return (NULL);
14724     input->closecallback = NULL;
14725     ctxt = xmlNewParserCtxt();
14726     if (ctxt == NULL) {
14727         xmlFreeParserInputBuffer(input);
14728         return (NULL);
14729     }
14730     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
14731     if (stream == NULL) {
14732         xmlFreeParserInputBuffer(input);
14733     xmlFreeParserCtxt(ctxt);
14734         return (NULL);
14735     }
14736     inputPush(ctxt, stream);
14737     return (xmlDoRead(ctxt, URL, encoding, options, 0));
14738 }
14739 
14753 xmlDocPtr
14754 xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
14755           void *ioctx, const char *URL, const char *encoding, int options)
14756 {
14757     xmlParserCtxtPtr ctxt;
14758     xmlParserInputBufferPtr input;
14759     xmlParserInputPtr stream;
14760 
14761     if (ioread == NULL)
14762         return (NULL);
14763 
14764     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
14765                                          XML_CHAR_ENCODING_NONE);
14766     if (input == NULL)
14767         return (NULL);
14768     ctxt = xmlNewParserCtxt();
14769     if (ctxt == NULL) {
14770         xmlFreeParserInputBuffer(input);
14771         return (NULL);
14772     }
14773     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
14774     if (stream == NULL) {
14775         xmlFreeParserInputBuffer(input);
14776     xmlFreeParserCtxt(ctxt);
14777         return (NULL);
14778     }
14779     inputPush(ctxt, stream);
14780     return (xmlDoRead(ctxt, URL, encoding, options, 0));
14781 }
14782 
14796 xmlDocPtr
14797 xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur,
14798                const char *URL, const char *encoding, int options)
14799 {
14800     xmlParserInputPtr stream;
14801 
14802     if (cur == NULL)
14803         return (NULL);
14804     if (ctxt == NULL)
14805         return (NULL);
14806 
14807     xmlCtxtReset(ctxt);
14808 
14809     stream = xmlNewStringInputStream(ctxt, cur);
14810     if (stream == NULL) {
14811         return (NULL);
14812     }
14813     inputPush(ctxt, stream);
14814     return (xmlDoRead(ctxt, URL, encoding, options, 1));
14815 }
14816 
14829 xmlDocPtr
14830 xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
14831                 const char *encoding, int options)
14832 {
14833     xmlParserInputPtr stream;
14834 
14835     if (filename == NULL)
14836         return (NULL);
14837     if (ctxt == NULL)
14838         return (NULL);
14839 
14840     xmlCtxtReset(ctxt);
14841 
14842     stream = xmlLoadExternalEntity(filename, NULL, ctxt);
14843     if (stream == NULL) {
14844         return (NULL);
14845     }
14846     inputPush(ctxt, stream);
14847     return (xmlDoRead(ctxt, NULL, encoding, options, 1));
14848 }
14849 
14864 xmlDocPtr
14865 xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
14866                   const char *URL, const char *encoding, int options)
14867 {
14868     xmlParserInputBufferPtr input;
14869     xmlParserInputPtr stream;
14870 
14871     if (ctxt == NULL)
14872         return (NULL);
14873     if (buffer == NULL)
14874         return (NULL);
14875 
14876     xmlCtxtReset(ctxt);
14877 
14878     input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
14879     if (input == NULL) {
14880     return(NULL);
14881     }
14882 
14883     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
14884     if (stream == NULL) {
14885     xmlFreeParserInputBuffer(input);
14886     return(NULL);
14887     }
14888 
14889     inputPush(ctxt, stream);
14890     return (xmlDoRead(ctxt, URL, encoding, options, 1));
14891 }
14892 
14908 xmlDocPtr
14909 xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
14910               const char *URL, const char *encoding, int options)
14911 {
14912     xmlParserInputBufferPtr input;
14913     xmlParserInputPtr stream;
14914 
14915     if (fd < 0)
14916         return (NULL);
14917     if (ctxt == NULL)
14918         return (NULL);
14919 
14920     xmlCtxtReset(ctxt);
14921 
14922 
14923     input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
14924     if (input == NULL)
14925         return (NULL);
14926     input->closecallback = NULL;
14927     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
14928     if (stream == NULL) {
14929         xmlFreeParserInputBuffer(input);
14930         return (NULL);
14931     }
14932     inputPush(ctxt, stream);
14933     return (xmlDoRead(ctxt, URL, encoding, options, 1));
14934 }
14935 
14951 xmlDocPtr
14952 xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
14953               xmlInputCloseCallback ioclose, void *ioctx,
14954           const char *URL,
14955               const char *encoding, int options)
14956 {
14957     xmlParserInputBufferPtr input;
14958     xmlParserInputPtr stream;
14959 
14960     if (ioread == NULL)
14961         return (NULL);
14962     if (ctxt == NULL)
14963         return (NULL);
14964 
14965     xmlCtxtReset(ctxt);
14966 
14967     input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
14968                                          XML_CHAR_ENCODING_NONE);
14969     if (input == NULL)
14970         return (NULL);
14971     stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
14972     if (stream == NULL) {
14973         xmlFreeParserInputBuffer(input);
14974         return (NULL);
14975     }
14976     inputPush(ctxt, stream);
14977     return (xmlDoRead(ctxt, URL, encoding, options, 1));
14978 }
14979 
14980 #define bottom_parser
14981 #include "elfgcchack.h"

Generated on Fri May 25 2012 04:15:42 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.