1/*
2 * parser.c : an XML 1.0 parser, namespaces and validity support are mostly
3 *            implemented on top of the SAX interfaces
4 *
5 * References:
6 *   The XML specification:
7 *     http://www.w3.org/TR/REC-xml
8 *   Original 1.0 version:
9 *     http://www.w3.org/TR/1998/REC-xml-19980210
10 *   XML second edition working draft
11 *     http://www.w3.org/TR/2000/WD-xml-2e-20000814
12 *
13 * Okay this is a big file, the parser core is around 7000 lines, then it
14 * is followed by the progressive parser top routines, then the various
15 * high level APIs to call the parser and a few miscellaneous functions.
16 * A number of helper functions and deprecated ones have been moved to
17 * parserInternals.c to reduce this file size.
18 * As much as possible the functions are associated with their relative
19 * production in the XML specification. A few productions defining the
20 * different ranges of character are actually implanted either in
21 * parserInternals.h or parserInternals.c
22 * The DOM tree build is realized from the default SAX callbacks in
23 * the module SAX.c.
24 * The routines doing the validation checks are in valid.c and called either
25 * from the SAX callbacks or as standalone functions using a preparsed
26 * document.
27 *
28 * See Copyright for the status of this software.
29 *
30 * daniel@veillard.com
31 */
32
33#define IN_LIBXML
34#include "libxml.h"
35
36#if defined(WIN32) && !defined (__CYGWIN__)
37#define XML_DIR_SEP '\\'
38#else
39#define XML_DIR_SEP '/'
40#endif
41
42#include <stdlib.h>
43#include <limits.h>
44#include <string.h>
45#include <stdarg.h>
46#include <libxml/xmlmemory.h>
47#include <libxml/threads.h>
48#include <libxml/globals.h>
49#include <libxml/tree.h>
50#include <libxml/parser.h>
51#include <libxml/parserInternals.h>
52#include <libxml/valid.h>
53#include <libxml/entities.h>
54#include <libxml/xmlerror.h>
55#include <libxml/encoding.h>
56#include <libxml/xmlIO.h>
57#include <libxml/uri.h>
58#ifdef LIBXML_CATALOG_ENABLED
59#include <libxml/catalog.h>
60#endif
61#ifdef LIBXML_SCHEMAS_ENABLED
62#include <libxml/xmlschemastypes.h>
63#include <libxml/relaxng.h>
64#endif
65#ifdef HAVE_CTYPE_H
66#include <ctype.h>
67#endif
68#ifdef HAVE_STDLIB_H
69#include <stdlib.h>
70#endif
71#ifdef HAVE_SYS_STAT_H
72#include <sys/stat.h>
73#endif
74#ifdef HAVE_FCNTL_H
75#include <fcntl.h>
76#endif
77#ifdef HAVE_UNISTD_H
78#include <unistd.h>
79#endif
80#ifdef HAVE_ZLIB_H
81#include <zlib.h>
82#endif
83#ifdef HAVE_LZMA_H
84#include <lzma.h>
85#endif
86
87#include "buf.h"
88#include "enc.h"
89
90static void
91xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info);
92
93static xmlParserCtxtPtr
94xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
95	                  const xmlChar *base, xmlParserCtxtPtr pctx);
96
97/************************************************************************
98 *									*
99 *	Arbitrary limits set in the parser. See XML_PARSE_HUGE		*
100 *									*
101 ************************************************************************/
102
103#define XML_PARSER_BIG_ENTITY 1000
104#define XML_PARSER_LOT_ENTITY 5000
105
106/*
107 * XML_PARSER_NON_LINEAR is the threshold where the ratio of parsed entity
108 *    replacement over the size in byte of the input indicates that you have
109 *    and eponential behaviour. A value of 10 correspond to at least 3 entity
110 *    replacement per byte of input.
111 */
112#define XML_PARSER_NON_LINEAR 10
113
114/*
115 * xmlParserEntityCheck
116 *
117 * Function to check non-linear entity expansion behaviour
118 * This is here to detect and stop exponential linear entity expansion
119 * This is not a limitation of the parser but a safety
120 * boundary feature. It can be disabled with the XML_PARSE_HUGE
121 * parser option.
122 */
123static int
124xmlParserEntityCheck(xmlParserCtxtPtr ctxt, size_t size,
125                     xmlEntityPtr ent, size_t replacement)
126{
127    size_t consumed = 0;
128
129    if ((ctxt == NULL) || (ctxt->options & XML_PARSE_HUGE))
130        return (0);
131    if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
132        return (1);
133
134    /*
135     * This may look absurd but is needed to detect
136     * entities problems
137     */
138    if ((ent != NULL) && (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
139	(ent->content != NULL) && (ent->checked == 0)) {
140	unsigned long oldnbent = ctxt->nbentities;
141	xmlChar *rep;
142
143	ent->checked = 1;
144
145	rep = xmlStringDecodeEntities(ctxt, ent->content,
146				  XML_SUBSTITUTE_REF, 0, 0, 0);
147
148	ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
149	if (rep != NULL) {
150	    if (xmlStrchr(rep, '<'))
151		ent->checked |= 1;
152	    xmlFree(rep);
153	    rep = NULL;
154	}
155    }
156    if (replacement != 0) {
157	if (replacement < XML_MAX_TEXT_LENGTH)
158	    return(0);
159
160        /*
161	 * If the volume of entity copy reaches 10 times the
162	 * amount of parsed data and over the large text threshold
163	 * then that's very likely to be an abuse.
164	 */
165        if (ctxt->input != NULL) {
166	    consumed = ctxt->input->consumed +
167	               (ctxt->input->cur - ctxt->input->base);
168	}
169        consumed += ctxt->sizeentities;
170
171        if (replacement < XML_PARSER_NON_LINEAR * consumed)
172	    return(0);
173    } else if (size != 0) {
174        /*
175         * Do the check based on the replacement size of the entity
176         */
177        if (size < XML_PARSER_BIG_ENTITY)
178	    return(0);
179
180        /*
181         * A limit on the amount of text data reasonably used
182         */
183        if (ctxt->input != NULL) {
184            consumed = ctxt->input->consumed +
185                (ctxt->input->cur - ctxt->input->base);
186        }
187        consumed += ctxt->sizeentities;
188
189        if ((size < XML_PARSER_NON_LINEAR * consumed) &&
190	    (ctxt->nbentities * 3 < XML_PARSER_NON_LINEAR * consumed))
191            return (0);
192    } else if (ent != NULL) {
193        /*
194         * use the number of parsed entities in the replacement
195         */
196        size = ent->checked / 2;
197
198        /*
199         * The amount of data parsed counting entities size only once
200         */
201        if (ctxt->input != NULL) {
202            consumed = ctxt->input->consumed +
203                (ctxt->input->cur - ctxt->input->base);
204        }
205        consumed += ctxt->sizeentities;
206
207        /*
208         * Check the density of entities for the amount of data
209	 * knowing an entity reference will take at least 3 bytes
210         */
211        if (size * 3 < consumed * XML_PARSER_NON_LINEAR)
212            return (0);
213    } else {
214        /*
215         * strange we got no data for checking
216         */
217	if (((ctxt->lastError.code != XML_ERR_UNDECLARED_ENTITY) &&
218	     (ctxt->lastError.code != XML_WAR_UNDECLARED_ENTITY)) ||
219	    (ctxt->nbentities <= 10000))
220	    return (0);
221    }
222    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
223    return (1);
224}
225
226/**
227 * xmlParserMaxDepth:
228 *
229 * arbitrary depth limit for the XML documents that we allow to
230 * process. This is not a limitation of the parser but a safety
231 * boundary feature. It can be disabled with the XML_PARSE_HUGE
232 * parser option.
233 */
234unsigned int xmlParserMaxDepth = 256;
235
236
237
238#define SAX2 1
239#define XML_PARSER_BIG_BUFFER_SIZE 300
240#define XML_PARSER_BUFFER_SIZE 100
241#define SAX_COMPAT_MODE BAD_CAST "SAX compatibility mode document"
242
243/**
244 * XML_PARSER_CHUNK_SIZE
245 *
246 * When calling GROW that's the minimal amount of data
247 * the parser expected to have received. It is not a hard
248 * limit but an optimization when reading strings like Names
249 * It is not strictly needed as long as inputs available characters
250 * are followed by 0, which should be provided by the I/O level
251 */
252#define XML_PARSER_CHUNK_SIZE 100
253
254/*
255 * List of XML prefixed PI allowed by W3C specs
256 */
257
258static const char *xmlW3CPIs[] = {
259    "xml-stylesheet",
260    "xml-model",
261    NULL
262};
263
264
265/* DEPR void xmlParserHandleReference(xmlParserCtxtPtr ctxt); */
266static xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
267                                              const xmlChar **str);
268
269static xmlParserErrors
270xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
271	              xmlSAXHandlerPtr sax,
272		      void *user_data, int depth, const xmlChar *URL,
273		      const xmlChar *ID, xmlNodePtr *list);
274
275static int
276xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options,
277                          const char *encoding);
278#ifdef LIBXML_LEGACY_ENABLED
279static void
280xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
281                      xmlNodePtr lastNode);
282#endif /* LIBXML_LEGACY_ENABLED */
283
284static xmlParserErrors
285xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
286		      const xmlChar *string, void *user_data, xmlNodePtr *lst);
287
288static int
289xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity);
290
291/************************************************************************
292 *									*
293 *		Some factorized error routines				*
294 *									*
295 ************************************************************************/
296
297/**
298 * xmlErrAttributeDup:
299 * @ctxt:  an XML parser context
300 * @prefix:  the attribute prefix
301 * @localname:  the attribute localname
302 *
303 * Handle a redefinition of attribute error
304 */
305static void
306xmlErrAttributeDup(xmlParserCtxtPtr ctxt, const xmlChar * prefix,
307                   const xmlChar * localname)
308{
309    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
310        (ctxt->instate == XML_PARSER_EOF))
311	return;
312    if (ctxt != NULL)
313	ctxt->errNo = XML_ERR_ATTRIBUTE_REDEFINED;
314
315    if (prefix == NULL)
316        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
317                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
318                        (const char *) localname, NULL, NULL, 0, 0,
319                        "Attribute %s redefined\n", localname);
320    else
321        __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER,
322                        XML_ERR_ATTRIBUTE_REDEFINED, XML_ERR_FATAL, NULL, 0,
323                        (const char *) prefix, (const char *) localname,
324                        NULL, 0, 0, "Attribute %s:%s redefined\n", prefix,
325                        localname);
326    if (ctxt != NULL) {
327	ctxt->wellFormed = 0;
328	if (ctxt->recovery == 0)
329	    ctxt->disableSAX = 1;
330    }
331}
332
333/**
334 * xmlFatalErr:
335 * @ctxt:  an XML parser context
336 * @error:  the error number
337 * @extra:  extra information string
338 *
339 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
340 */
341static void
342xmlFatalErr(xmlParserCtxtPtr ctxt, xmlParserErrors error, const char *info)
343{
344    const char *errmsg;
345    char errstr[129] = "";
346
347    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
348        (ctxt->instate == XML_PARSER_EOF))
349	return;
350    switch (error) {
351        case XML_ERR_INVALID_HEX_CHARREF:
352            errmsg = "CharRef: invalid hexadecimal value";
353            break;
354        case XML_ERR_INVALID_DEC_CHARREF:
355            errmsg = "CharRef: invalid decimal value";
356            break;
357        case XML_ERR_INVALID_CHARREF:
358            errmsg = "CharRef: invalid value";
359            break;
360        case XML_ERR_INTERNAL_ERROR:
361            errmsg = "internal error";
362            break;
363        case XML_ERR_PEREF_AT_EOF:
364            errmsg = "PEReference at end of document";
365            break;
366        case XML_ERR_PEREF_IN_PROLOG:
367            errmsg = "PEReference in prolog";
368            break;
369        case XML_ERR_PEREF_IN_EPILOG:
370            errmsg = "PEReference in epilog";
371            break;
372        case XML_ERR_PEREF_NO_NAME:
373            errmsg = "PEReference: no name";
374            break;
375        case XML_ERR_PEREF_SEMICOL_MISSING:
376            errmsg = "PEReference: expecting ';'";
377            break;
378        case XML_ERR_ENTITY_LOOP:
379            errmsg = "Detected an entity reference loop";
380            break;
381        case XML_ERR_ENTITY_NOT_STARTED:
382            errmsg = "EntityValue: \" or ' expected";
383            break;
384        case XML_ERR_ENTITY_PE_INTERNAL:
385            errmsg = "PEReferences forbidden in internal subset";
386            break;
387        case XML_ERR_ENTITY_NOT_FINISHED:
388            errmsg = "EntityValue: \" or ' expected";
389            break;
390        case XML_ERR_ATTRIBUTE_NOT_STARTED:
391            errmsg = "AttValue: \" or ' expected";
392            break;
393        case XML_ERR_LT_IN_ATTRIBUTE:
394            errmsg = "Unescaped '<' not allowed in attributes values";
395            break;
396        case XML_ERR_LITERAL_NOT_STARTED:
397            errmsg = "SystemLiteral \" or ' expected";
398            break;
399        case XML_ERR_LITERAL_NOT_FINISHED:
400            errmsg = "Unfinished System or Public ID \" or ' expected";
401            break;
402        case XML_ERR_MISPLACED_CDATA_END:
403            errmsg = "Sequence ']]>' not allowed in content";
404            break;
405        case XML_ERR_URI_REQUIRED:
406            errmsg = "SYSTEM or PUBLIC, the URI is missing";
407            break;
408        case XML_ERR_PUBID_REQUIRED:
409            errmsg = "PUBLIC, the Public Identifier is missing";
410            break;
411        case XML_ERR_HYPHEN_IN_COMMENT:
412            errmsg = "Comment must not contain '--' (double-hyphen)";
413            break;
414        case XML_ERR_PI_NOT_STARTED:
415            errmsg = "xmlParsePI : no target name";
416            break;
417        case XML_ERR_RESERVED_XML_NAME:
418            errmsg = "Invalid PI name";
419            break;
420        case XML_ERR_NOTATION_NOT_STARTED:
421            errmsg = "NOTATION: Name expected here";
422            break;
423        case XML_ERR_NOTATION_NOT_FINISHED:
424            errmsg = "'>' required to close NOTATION declaration";
425            break;
426        case XML_ERR_VALUE_REQUIRED:
427            errmsg = "Entity value required";
428            break;
429        case XML_ERR_URI_FRAGMENT:
430            errmsg = "Fragment not allowed";
431            break;
432        case XML_ERR_ATTLIST_NOT_STARTED:
433            errmsg = "'(' required to start ATTLIST enumeration";
434            break;
435        case XML_ERR_NMTOKEN_REQUIRED:
436            errmsg = "NmToken expected in ATTLIST enumeration";
437            break;
438        case XML_ERR_ATTLIST_NOT_FINISHED:
439            errmsg = "')' required to finish ATTLIST enumeration";
440            break;
441        case XML_ERR_MIXED_NOT_STARTED:
442            errmsg = "MixedContentDecl : '|' or ')*' expected";
443            break;
444        case XML_ERR_PCDATA_REQUIRED:
445            errmsg = "MixedContentDecl : '#PCDATA' expected";
446            break;
447        case XML_ERR_ELEMCONTENT_NOT_STARTED:
448            errmsg = "ContentDecl : Name or '(' expected";
449            break;
450        case XML_ERR_ELEMCONTENT_NOT_FINISHED:
451            errmsg = "ContentDecl : ',' '|' or ')' expected";
452            break;
453        case XML_ERR_PEREF_IN_INT_SUBSET:
454            errmsg =
455                "PEReference: forbidden within markup decl in internal subset";
456            break;
457        case XML_ERR_GT_REQUIRED:
458            errmsg = "expected '>'";
459            break;
460        case XML_ERR_CONDSEC_INVALID:
461            errmsg = "XML conditional section '[' expected";
462            break;
463        case XML_ERR_EXT_SUBSET_NOT_FINISHED:
464            errmsg = "Content error in the external subset";
465            break;
466        case XML_ERR_CONDSEC_INVALID_KEYWORD:
467            errmsg =
468                "conditional section INCLUDE or IGNORE keyword expected";
469            break;
470        case XML_ERR_CONDSEC_NOT_FINISHED:
471            errmsg = "XML conditional section not closed";
472            break;
473        case XML_ERR_XMLDECL_NOT_STARTED:
474            errmsg = "Text declaration '<?xml' required";
475            break;
476        case XML_ERR_XMLDECL_NOT_FINISHED:
477            errmsg = "parsing XML declaration: '?>' expected";
478            break;
479        case XML_ERR_EXT_ENTITY_STANDALONE:
480            errmsg = "external parsed entities cannot be standalone";
481            break;
482        case XML_ERR_ENTITYREF_SEMICOL_MISSING:
483            errmsg = "EntityRef: expecting ';'";
484            break;
485        case XML_ERR_DOCTYPE_NOT_FINISHED:
486            errmsg = "DOCTYPE improperly terminated";
487            break;
488        case XML_ERR_LTSLASH_REQUIRED:
489            errmsg = "EndTag: '</' not found";
490            break;
491        case XML_ERR_EQUAL_REQUIRED:
492            errmsg = "expected '='";
493            break;
494        case XML_ERR_STRING_NOT_CLOSED:
495            errmsg = "String not closed expecting \" or '";
496            break;
497        case XML_ERR_STRING_NOT_STARTED:
498            errmsg = "String not started expecting ' or \"";
499            break;
500        case XML_ERR_ENCODING_NAME:
501            errmsg = "Invalid XML encoding name";
502            break;
503        case XML_ERR_STANDALONE_VALUE:
504            errmsg = "standalone accepts only 'yes' or 'no'";
505            break;
506        case XML_ERR_DOCUMENT_EMPTY:
507            errmsg = "Document is empty";
508            break;
509        case XML_ERR_DOCUMENT_END:
510            errmsg = "Extra content at the end of the document";
511            break;
512        case XML_ERR_NOT_WELL_BALANCED:
513            errmsg = "chunk is not well balanced";
514            break;
515        case XML_ERR_EXTRA_CONTENT:
516            errmsg = "extra content at the end of well balanced chunk";
517            break;
518        case XML_ERR_VERSION_MISSING:
519            errmsg = "Malformed declaration expecting version";
520            break;
521        case XML_ERR_NAME_TOO_LONG:
522            errmsg = "Name too long use XML_PARSE_HUGE option";
523            break;
524#if 0
525        case:
526            errmsg = "";
527            break;
528#endif
529        default:
530            errmsg = "Unregistered error message";
531    }
532    if (info == NULL)
533        snprintf(errstr, 128, "%s\n", errmsg);
534    else
535        snprintf(errstr, 128, "%s: %%s\n", errmsg);
536    if (ctxt != NULL)
537	ctxt->errNo = error;
538    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
539                    XML_ERR_FATAL, NULL, 0, info, NULL, NULL, 0, 0, &errstr[0],
540                    info);
541    if (ctxt != NULL) {
542	ctxt->wellFormed = 0;
543	if (ctxt->recovery == 0)
544	    ctxt->disableSAX = 1;
545    }
546}
547
548/**
549 * xmlFatalErrMsg:
550 * @ctxt:  an XML parser context
551 * @error:  the error number
552 * @msg:  the error message
553 *
554 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
555 */
556static void
557xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
558               const char *msg)
559{
560    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
561        (ctxt->instate == XML_PARSER_EOF))
562	return;
563    if (ctxt != NULL)
564	ctxt->errNo = error;
565    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
566                    XML_ERR_FATAL, NULL, 0, NULL, NULL, NULL, 0, 0, "%s", msg);
567    if (ctxt != NULL) {
568	ctxt->wellFormed = 0;
569	if (ctxt->recovery == 0)
570	    ctxt->disableSAX = 1;
571    }
572}
573
574/**
575 * xmlWarningMsg:
576 * @ctxt:  an XML parser context
577 * @error:  the error number
578 * @msg:  the error message
579 * @str1:  extra data
580 * @str2:  extra data
581 *
582 * Handle a warning.
583 */
584static void
585xmlWarningMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
586              const char *msg, const xmlChar *str1, const xmlChar *str2)
587{
588    xmlStructuredErrorFunc schannel = NULL;
589
590    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
591        (ctxt->instate == XML_PARSER_EOF))
592	return;
593    if ((ctxt != NULL) && (ctxt->sax != NULL) &&
594        (ctxt->sax->initialized == XML_SAX2_MAGIC))
595        schannel = ctxt->sax->serror;
596    if (ctxt != NULL) {
597        __xmlRaiseError(schannel,
598                    (ctxt->sax) ? ctxt->sax->warning : NULL,
599                    ctxt->userData,
600                    ctxt, NULL, XML_FROM_PARSER, error,
601                    XML_ERR_WARNING, NULL, 0,
602		    (const char *) str1, (const char *) str2, NULL, 0, 0,
603		    msg, (const char *) str1, (const char *) str2);
604    } else {
605        __xmlRaiseError(schannel, NULL, NULL,
606                    ctxt, NULL, XML_FROM_PARSER, error,
607                    XML_ERR_WARNING, NULL, 0,
608		    (const char *) str1, (const char *) str2, NULL, 0, 0,
609		    msg, (const char *) str1, (const char *) str2);
610    }
611}
612
613/**
614 * xmlValidityError:
615 * @ctxt:  an XML parser context
616 * @error:  the error number
617 * @msg:  the error message
618 * @str1:  extra data
619 *
620 * Handle a validity error.
621 */
622static void
623xmlValidityError(xmlParserCtxtPtr ctxt, xmlParserErrors error,
624              const char *msg, const xmlChar *str1, const xmlChar *str2)
625{
626    xmlStructuredErrorFunc schannel = NULL;
627
628    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
629        (ctxt->instate == XML_PARSER_EOF))
630	return;
631    if (ctxt != NULL) {
632	ctxt->errNo = error;
633	if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
634	    schannel = ctxt->sax->serror;
635    }
636    if (ctxt != NULL) {
637        __xmlRaiseError(schannel,
638                    ctxt->vctxt.error, ctxt->vctxt.userData,
639                    ctxt, NULL, XML_FROM_DTD, error,
640                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
641		    (const char *) str2, NULL, 0, 0,
642		    msg, (const char *) str1, (const char *) str2);
643	ctxt->valid = 0;
644    } else {
645        __xmlRaiseError(schannel, NULL, NULL,
646                    ctxt, NULL, XML_FROM_DTD, error,
647                    XML_ERR_ERROR, NULL, 0, (const char *) str1,
648		    (const char *) str2, NULL, 0, 0,
649		    msg, (const char *) str1, (const char *) str2);
650    }
651}
652
653/**
654 * xmlFatalErrMsgInt:
655 * @ctxt:  an XML parser context
656 * @error:  the error number
657 * @msg:  the error message
658 * @val:  an integer value
659 *
660 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
661 */
662static void
663xmlFatalErrMsgInt(xmlParserCtxtPtr ctxt, xmlParserErrors error,
664                  const char *msg, int val)
665{
666    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
667        (ctxt->instate == XML_PARSER_EOF))
668	return;
669    if (ctxt != NULL)
670	ctxt->errNo = error;
671    __xmlRaiseError(NULL, NULL, NULL,
672                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
673                    NULL, 0, NULL, NULL, NULL, val, 0, msg, val);
674    if (ctxt != NULL) {
675	ctxt->wellFormed = 0;
676	if (ctxt->recovery == 0)
677	    ctxt->disableSAX = 1;
678    }
679}
680
681/**
682 * xmlFatalErrMsgStrIntStr:
683 * @ctxt:  an XML parser context
684 * @error:  the error number
685 * @msg:  the error message
686 * @str1:  an string info
687 * @val:  an integer value
688 * @str2:  an string info
689 *
690 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
691 */
692static void
693xmlFatalErrMsgStrIntStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
694                  const char *msg, const xmlChar *str1, int val,
695		  const xmlChar *str2)
696{
697    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
698        (ctxt->instate == XML_PARSER_EOF))
699	return;
700    if (ctxt != NULL)
701	ctxt->errNo = error;
702    __xmlRaiseError(NULL, NULL, NULL,
703                    ctxt, NULL, XML_FROM_PARSER, error, XML_ERR_FATAL,
704                    NULL, 0, (const char *) str1, (const char *) str2,
705		    NULL, val, 0, msg, str1, val, str2);
706    if (ctxt != NULL) {
707	ctxt->wellFormed = 0;
708	if (ctxt->recovery == 0)
709	    ctxt->disableSAX = 1;
710    }
711}
712
713/**
714 * xmlFatalErrMsgStr:
715 * @ctxt:  an XML parser context
716 * @error:  the error number
717 * @msg:  the error message
718 * @val:  a string value
719 *
720 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
721 */
722static void
723xmlFatalErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
724                  const char *msg, const xmlChar * val)
725{
726    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
727        (ctxt->instate == XML_PARSER_EOF))
728	return;
729    if (ctxt != NULL)
730	ctxt->errNo = error;
731    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
732                    XML_FROM_PARSER, error, XML_ERR_FATAL,
733                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
734                    val);
735    if (ctxt != NULL) {
736	ctxt->wellFormed = 0;
737	if (ctxt->recovery == 0)
738	    ctxt->disableSAX = 1;
739    }
740}
741
742/**
743 * xmlErrMsgStr:
744 * @ctxt:  an XML parser context
745 * @error:  the error number
746 * @msg:  the error message
747 * @val:  a string value
748 *
749 * Handle a non fatal parser error
750 */
751static void
752xmlErrMsgStr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
753                  const char *msg, const xmlChar * val)
754{
755    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
756        (ctxt->instate == XML_PARSER_EOF))
757	return;
758    if (ctxt != NULL)
759	ctxt->errNo = error;
760    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL,
761                    XML_FROM_PARSER, error, XML_ERR_ERROR,
762                    NULL, 0, (const char *) val, NULL, NULL, 0, 0, msg,
763                    val);
764}
765
766/**
767 * xmlNsErr:
768 * @ctxt:  an XML parser context
769 * @error:  the error number
770 * @msg:  the message
771 * @info1:  extra information string
772 * @info2:  extra information string
773 *
774 * Handle a fatal parser error, i.e. violating Well-Formedness constraints
775 */
776static void
777xmlNsErr(xmlParserCtxtPtr ctxt, xmlParserErrors error,
778         const char *msg,
779         const xmlChar * info1, const xmlChar * info2,
780         const xmlChar * info3)
781{
782    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
783        (ctxt->instate == XML_PARSER_EOF))
784	return;
785    if (ctxt != NULL)
786	ctxt->errNo = error;
787    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
788                    XML_ERR_ERROR, NULL, 0, (const char *) info1,
789                    (const char *) info2, (const char *) info3, 0, 0, msg,
790                    info1, info2, info3);
791    if (ctxt != NULL)
792	ctxt->nsWellFormed = 0;
793}
794
795/**
796 * xmlNsWarn
797 * @ctxt:  an XML parser context
798 * @error:  the error number
799 * @msg:  the message
800 * @info1:  extra information string
801 * @info2:  extra information string
802 *
803 * Handle a namespace warning error
804 */
805static void
806xmlNsWarn(xmlParserCtxtPtr ctxt, xmlParserErrors error,
807         const char *msg,
808         const xmlChar * info1, const xmlChar * info2,
809         const xmlChar * info3)
810{
811    if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
812        (ctxt->instate == XML_PARSER_EOF))
813	return;
814    __xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
815                    XML_ERR_WARNING, NULL, 0, (const char *) info1,
816                    (const char *) info2, (const char *) info3, 0, 0, msg,
817                    info1, info2, info3);
818}
819
820/************************************************************************
821 *									*
822 *		Library wide options					*
823 *									*
824 ************************************************************************/
825
826/**
827  * xmlHasFeature:
828  * @feature: the feature to be examined
829  *
830  * Examines if the library has been compiled with a given feature.
831  *
832  * Returns a non-zero value if the feature exist, otherwise zero.
833  * Returns zero (0) if the feature does not exist or an unknown
834  * unknown feature is requested, non-zero otherwise.
835  */
836int
837xmlHasFeature(xmlFeature feature)
838{
839    switch (feature) {
840	case XML_WITH_THREAD:
841#ifdef LIBXML_THREAD_ENABLED
842	    return(1);
843#else
844	    return(0);
845#endif
846        case XML_WITH_TREE:
847#ifdef LIBXML_TREE_ENABLED
848            return(1);
849#else
850            return(0);
851#endif
852        case XML_WITH_OUTPUT:
853#ifdef LIBXML_OUTPUT_ENABLED
854            return(1);
855#else
856            return(0);
857#endif
858        case XML_WITH_PUSH:
859#ifdef LIBXML_PUSH_ENABLED
860            return(1);
861#else
862            return(0);
863#endif
864        case XML_WITH_READER:
865#ifdef LIBXML_READER_ENABLED
866            return(1);
867#else
868            return(0);
869#endif
870        case XML_WITH_PATTERN:
871#ifdef LIBXML_PATTERN_ENABLED
872            return(1);
873#else
874            return(0);
875#endif
876        case XML_WITH_WRITER:
877#ifdef LIBXML_WRITER_ENABLED
878            return(1);
879#else
880            return(0);
881#endif
882        case XML_WITH_SAX1:
883#ifdef LIBXML_SAX1_ENABLED
884            return(1);
885#else
886            return(0);
887#endif
888        case XML_WITH_FTP:
889#ifdef LIBXML_FTP_ENABLED
890            return(1);
891#else
892            return(0);
893#endif
894        case XML_WITH_HTTP:
895#ifdef LIBXML_HTTP_ENABLED
896            return(1);
897#else
898            return(0);
899#endif
900        case XML_WITH_VALID:
901#ifdef LIBXML_VALID_ENABLED
902            return(1);
903#else
904            return(0);
905#endif
906        case XML_WITH_HTML:
907#ifdef LIBXML_HTML_ENABLED
908            return(1);
909#else
910            return(0);
911#endif
912        case XML_WITH_LEGACY:
913#ifdef LIBXML_LEGACY_ENABLED
914            return(1);
915#else
916            return(0);
917#endif
918        case XML_WITH_C14N:
919#ifdef LIBXML_C14N_ENABLED
920            return(1);
921#else
922            return(0);
923#endif
924        case XML_WITH_CATALOG:
925#ifdef LIBXML_CATALOG_ENABLED
926            return(1);
927#else
928            return(0);
929#endif
930        case XML_WITH_XPATH:
931#ifdef LIBXML_XPATH_ENABLED
932            return(1);
933#else
934            return(0);
935#endif
936        case XML_WITH_XPTR:
937#ifdef LIBXML_XPTR_ENABLED
938            return(1);
939#else
940            return(0);
941#endif
942        case XML_WITH_XINCLUDE:
943#ifdef LIBXML_XINCLUDE_ENABLED
944            return(1);
945#else
946            return(0);
947#endif
948        case XML_WITH_ICONV:
949#ifdef LIBXML_ICONV_ENABLED
950            return(1);
951#else
952            return(0);
953#endif
954        case XML_WITH_ISO8859X:
955#ifdef LIBXML_ISO8859X_ENABLED
956            return(1);
957#else
958            return(0);
959#endif
960        case XML_WITH_UNICODE:
961#ifdef LIBXML_UNICODE_ENABLED
962            return(1);
963#else
964            return(0);
965#endif
966        case XML_WITH_REGEXP:
967#ifdef LIBXML_REGEXP_ENABLED
968            return(1);
969#else
970            return(0);
971#endif
972        case XML_WITH_AUTOMATA:
973#ifdef LIBXML_AUTOMATA_ENABLED
974            return(1);
975#else
976            return(0);
977#endif
978        case XML_WITH_EXPR:
979#ifdef LIBXML_EXPR_ENABLED
980            return(1);
981#else
982            return(0);
983#endif
984        case XML_WITH_SCHEMAS:
985#ifdef LIBXML_SCHEMAS_ENABLED
986            return(1);
987#else
988            return(0);
989#endif
990        case XML_WITH_SCHEMATRON:
991#ifdef LIBXML_SCHEMATRON_ENABLED
992            return(1);
993#else
994            return(0);
995#endif
996        case XML_WITH_MODULES:
997#ifdef LIBXML_MODULES_ENABLED
998            return(1);
999#else
1000            return(0);
1001#endif
1002        case XML_WITH_DEBUG:
1003#ifdef LIBXML_DEBUG_ENABLED
1004            return(1);
1005#else
1006            return(0);
1007#endif
1008        case XML_WITH_DEBUG_MEM:
1009#ifdef DEBUG_MEMORY_LOCATION
1010            return(1);
1011#else
1012            return(0);
1013#endif
1014        case XML_WITH_DEBUG_RUN:
1015#ifdef LIBXML_DEBUG_RUNTIME
1016            return(1);
1017#else
1018            return(0);
1019#endif
1020        case XML_WITH_ZLIB:
1021#ifdef LIBXML_ZLIB_ENABLED
1022            return(1);
1023#else
1024            return(0);
1025#endif
1026        case XML_WITH_LZMA:
1027#ifdef LIBXML_LZMA_ENABLED
1028            return(1);
1029#else
1030            return(0);
1031#endif
1032        case XML_WITH_ICU:
1033#ifdef LIBXML_ICU_ENABLED
1034            return(1);
1035#else
1036            return(0);
1037#endif
1038        default:
1039	    break;
1040     }
1041     return(0);
1042}
1043
1044/************************************************************************
1045 *									*
1046 *		SAX2 defaulted attributes handling			*
1047 *									*
1048 ************************************************************************/
1049
1050/**
1051 * xmlDetectSAX2:
1052 * @ctxt:  an XML parser context
1053 *
1054 * Do the SAX2 detection and specific intialization
1055 */
1056static void
1057xmlDetectSAX2(xmlParserCtxtPtr ctxt) {
1058    if (ctxt == NULL) return;
1059#ifdef LIBXML_SAX1_ENABLED
1060    if ((ctxt->sax) &&  (ctxt->sax->initialized == XML_SAX2_MAGIC) &&
1061        ((ctxt->sax->startElementNs != NULL) ||
1062         (ctxt->sax->endElementNs != NULL))) ctxt->sax2 = 1;
1063#else
1064    ctxt->sax2 = 1;
1065#endif /* LIBXML_SAX1_ENABLED */
1066
1067    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
1068    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
1069    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
1070    if ((ctxt->str_xml==NULL) || (ctxt->str_xmlns==NULL) ||
1071		(ctxt->str_xml_ns == NULL)) {
1072        xmlErrMemory(ctxt, NULL);
1073    }
1074}
1075
1076typedef struct _xmlDefAttrs xmlDefAttrs;
1077typedef xmlDefAttrs *xmlDefAttrsPtr;
1078struct _xmlDefAttrs {
1079    int nbAttrs;	/* number of defaulted attributes on that element */
1080    int maxAttrs;       /* the size of the array */
1081    const xmlChar *values[5]; /* array of localname/prefix/values/external */
1082};
1083
1084/**
1085 * xmlAttrNormalizeSpace:
1086 * @src: the source string
1087 * @dst: the target string
1088 *
1089 * Normalize the space in non CDATA attribute values:
1090 * If the attribute type is not CDATA, then the XML processor MUST further
1091 * process the normalized attribute value by discarding any leading and
1092 * trailing space (#x20) characters, and by replacing sequences of space
1093 * (#x20) characters by a single space (#x20) character.
1094 * Note that the size of dst need to be at least src, and if one doesn't need
1095 * to preserve dst (and it doesn't come from a dictionary or read-only) then
1096 * passing src as dst is just fine.
1097 *
1098 * Returns a pointer to the normalized value (dst) or NULL if no conversion
1099 *         is needed.
1100 */
1101static xmlChar *
1102xmlAttrNormalizeSpace(const xmlChar *src, xmlChar *dst)
1103{
1104    if ((src == NULL) || (dst == NULL))
1105        return(NULL);
1106
1107    while (*src == 0x20) src++;
1108    while (*src != 0) {
1109	if (*src == 0x20) {
1110	    while (*src == 0x20) src++;
1111	    if (*src != 0)
1112		*dst++ = 0x20;
1113	} else {
1114	    *dst++ = *src++;
1115	}
1116    }
1117    *dst = 0;
1118    if (dst == src)
1119       return(NULL);
1120    return(dst);
1121}
1122
1123/**
1124 * xmlAttrNormalizeSpace2:
1125 * @src: the source string
1126 *
1127 * Normalize the space in non CDATA attribute values, a slightly more complex
1128 * front end to avoid allocation problems when running on attribute values
1129 * coming from the input.
1130 *
1131 * Returns a pointer to the normalized value (dst) or NULL if no conversion
1132 *         is needed.
1133 */
1134static const xmlChar *
1135xmlAttrNormalizeSpace2(xmlParserCtxtPtr ctxt, xmlChar *src, int *len)
1136{
1137    int i;
1138    int remove_head = 0;
1139    int need_realloc = 0;
1140    const xmlChar *cur;
1141
1142    if ((ctxt == NULL) || (src == NULL) || (len == NULL))
1143        return(NULL);
1144    i = *len;
1145    if (i <= 0)
1146        return(NULL);
1147
1148    cur = src;
1149    while (*cur == 0x20) {
1150        cur++;
1151	remove_head++;
1152    }
1153    while (*cur != 0) {
1154	if (*cur == 0x20) {
1155	    cur++;
1156	    if ((*cur == 0x20) || (*cur == 0)) {
1157	        need_realloc = 1;
1158		break;
1159	    }
1160	} else
1161	    cur++;
1162    }
1163    if (need_realloc) {
1164        xmlChar *ret;
1165
1166	ret = xmlStrndup(src + remove_head, i - remove_head + 1);
1167	if (ret == NULL) {
1168	    xmlErrMemory(ctxt, NULL);
1169	    return(NULL);
1170	}
1171	xmlAttrNormalizeSpace(ret, ret);
1172	*len = (int) strlen((const char *)ret);
1173        return(ret);
1174    } else if (remove_head) {
1175        *len -= remove_head;
1176        memmove(src, src + remove_head, 1 + *len);
1177	return(src);
1178    }
1179    return(NULL);
1180}
1181
1182/**
1183 * xmlAddDefAttrs:
1184 * @ctxt:  an XML parser context
1185 * @fullname:  the element fullname
1186 * @fullattr:  the attribute fullname
1187 * @value:  the attribute value
1188 *
1189 * Add a defaulted attribute for an element
1190 */
1191static void
1192xmlAddDefAttrs(xmlParserCtxtPtr ctxt,
1193               const xmlChar *fullname,
1194               const xmlChar *fullattr,
1195               const xmlChar *value) {
1196    xmlDefAttrsPtr defaults;
1197    int len;
1198    const xmlChar *name;
1199    const xmlChar *prefix;
1200
1201    /*
1202     * Allows to detect attribute redefinitions
1203     */
1204    if (ctxt->attsSpecial != NULL) {
1205        if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1206	    return;
1207    }
1208
1209    if (ctxt->attsDefault == NULL) {
1210        ctxt->attsDefault = xmlHashCreateDict(10, ctxt->dict);
1211	if (ctxt->attsDefault == NULL)
1212	    goto mem_error;
1213    }
1214
1215    /*
1216     * split the element name into prefix:localname , the string found
1217     * are within the DTD and then not associated to namespace names.
1218     */
1219    name = xmlSplitQName3(fullname, &len);
1220    if (name == NULL) {
1221        name = xmlDictLookup(ctxt->dict, fullname, -1);
1222	prefix = NULL;
1223    } else {
1224        name = xmlDictLookup(ctxt->dict, name, -1);
1225	prefix = xmlDictLookup(ctxt->dict, fullname, len);
1226    }
1227
1228    /*
1229     * make sure there is some storage
1230     */
1231    defaults = xmlHashLookup2(ctxt->attsDefault, name, prefix);
1232    if (defaults == NULL) {
1233        defaults = (xmlDefAttrsPtr) xmlMalloc(sizeof(xmlDefAttrs) +
1234	                   (4 * 5) * sizeof(const xmlChar *));
1235	if (defaults == NULL)
1236	    goto mem_error;
1237	defaults->nbAttrs = 0;
1238	defaults->maxAttrs = 4;
1239	if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
1240	                        defaults, NULL) < 0) {
1241	    xmlFree(defaults);
1242	    goto mem_error;
1243	}
1244    } else if (defaults->nbAttrs >= defaults->maxAttrs) {
1245        xmlDefAttrsPtr temp;
1246
1247        temp = (xmlDefAttrsPtr) xmlRealloc(defaults, sizeof(xmlDefAttrs) +
1248		       (2 * defaults->maxAttrs * 5) * sizeof(const xmlChar *));
1249	if (temp == NULL)
1250	    goto mem_error;
1251	defaults = temp;
1252	defaults->maxAttrs *= 2;
1253	if (xmlHashUpdateEntry2(ctxt->attsDefault, name, prefix,
1254	                        defaults, NULL) < 0) {
1255	    xmlFree(defaults);
1256	    goto mem_error;
1257	}
1258    }
1259
1260    /*
1261     * Split the element name into prefix:localname , the string found
1262     * are within the DTD and hen not associated to namespace names.
1263     */
1264    name = xmlSplitQName3(fullattr, &len);
1265    if (name == NULL) {
1266        name = xmlDictLookup(ctxt->dict, fullattr, -1);
1267	prefix = NULL;
1268    } else {
1269        name = xmlDictLookup(ctxt->dict, name, -1);
1270	prefix = xmlDictLookup(ctxt->dict, fullattr, len);
1271    }
1272
1273    defaults->values[5 * defaults->nbAttrs] = name;
1274    defaults->values[5 * defaults->nbAttrs + 1] = prefix;
1275    /* intern the string and precompute the end */
1276    len = xmlStrlen(value);
1277    value = xmlDictLookup(ctxt->dict, value, len);
1278    defaults->values[5 * defaults->nbAttrs + 2] = value;
1279    defaults->values[5 * defaults->nbAttrs + 3] = value + len;
1280    if (ctxt->external)
1281        defaults->values[5 * defaults->nbAttrs + 4] = BAD_CAST "external";
1282    else
1283        defaults->values[5 * defaults->nbAttrs + 4] = NULL;
1284    defaults->nbAttrs++;
1285
1286    return;
1287
1288mem_error:
1289    xmlErrMemory(ctxt, NULL);
1290    return;
1291}
1292
1293/**
1294 * xmlAddSpecialAttr:
1295 * @ctxt:  an XML parser context
1296 * @fullname:  the element fullname
1297 * @fullattr:  the attribute fullname
1298 * @type:  the attribute type
1299 *
1300 * Register this attribute type
1301 */
1302static void
1303xmlAddSpecialAttr(xmlParserCtxtPtr ctxt,
1304		  const xmlChar *fullname,
1305		  const xmlChar *fullattr,
1306		  int type)
1307{
1308    if (ctxt->attsSpecial == NULL) {
1309        ctxt->attsSpecial = xmlHashCreateDict(10, ctxt->dict);
1310	if (ctxt->attsSpecial == NULL)
1311	    goto mem_error;
1312    }
1313
1314    if (xmlHashLookup2(ctxt->attsSpecial, fullname, fullattr) != NULL)
1315        return;
1316
1317    xmlHashAddEntry2(ctxt->attsSpecial, fullname, fullattr,
1318                     (void *) (long) type);
1319    return;
1320
1321mem_error:
1322    xmlErrMemory(ctxt, NULL);
1323    return;
1324}
1325
1326/**
1327 * xmlCleanSpecialAttrCallback:
1328 *
1329 * Removes CDATA attributes from the special attribute table
1330 */
1331static void
1332xmlCleanSpecialAttrCallback(void *payload, void *data,
1333                            const xmlChar *fullname, const xmlChar *fullattr,
1334                            const xmlChar *unused ATTRIBUTE_UNUSED) {
1335    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) data;
1336
1337    if (((long) payload) == XML_ATTRIBUTE_CDATA) {
1338        xmlHashRemoveEntry2(ctxt->attsSpecial, fullname, fullattr, NULL);
1339    }
1340}
1341
1342/**
1343 * xmlCleanSpecialAttr:
1344 * @ctxt:  an XML parser context
1345 *
1346 * Trim the list of attributes defined to remove all those of type
1347 * CDATA as they are not special. This call should be done when finishing
1348 * to parse the DTD and before starting to parse the document root.
1349 */
1350static void
1351xmlCleanSpecialAttr(xmlParserCtxtPtr ctxt)
1352{
1353    if (ctxt->attsSpecial == NULL)
1354        return;
1355
1356    xmlHashScanFull(ctxt->attsSpecial, xmlCleanSpecialAttrCallback, ctxt);
1357
1358    if (xmlHashSize(ctxt->attsSpecial) == 0) {
1359        xmlHashFree(ctxt->attsSpecial, NULL);
1360        ctxt->attsSpecial = NULL;
1361    }
1362    return;
1363}
1364
1365/**
1366 * xmlCheckLanguageID:
1367 * @lang:  pointer to the string value
1368 *
1369 * Checks that the value conforms to the LanguageID production:
1370 *
1371 * NOTE: this is somewhat deprecated, those productions were removed from
1372 *       the XML Second edition.
1373 *
1374 * [33] LanguageID ::= Langcode ('-' Subcode)*
1375 * [34] Langcode ::= ISO639Code |  IanaCode |  UserCode
1376 * [35] ISO639Code ::= ([a-z] | [A-Z]) ([a-z] | [A-Z])
1377 * [36] IanaCode ::= ('i' | 'I') '-' ([a-z] | [A-Z])+
1378 * [37] UserCode ::= ('x' | 'X') '-' ([a-z] | [A-Z])+
1379 * [38] Subcode ::= ([a-z] | [A-Z])+
1380 *
1381 * The current REC reference the sucessors of RFC 1766, currently 5646
1382 *
1383 * http://www.rfc-editor.org/rfc/rfc5646.txt
1384 * langtag       = language
1385 *                 ["-" script]
1386 *                 ["-" region]
1387 *                 *("-" variant)
1388 *                 *("-" extension)
1389 *                 ["-" privateuse]
1390 * language      = 2*3ALPHA            ; shortest ISO 639 code
1391 *                 ["-" extlang]       ; sometimes followed by
1392 *                                     ; extended language subtags
1393 *               / 4ALPHA              ; or reserved for future use
1394 *               / 5*8ALPHA            ; or registered language subtag
1395 *
1396 * extlang       = 3ALPHA              ; selected ISO 639 codes
1397 *                 *2("-" 3ALPHA)      ; permanently reserved
1398 *
1399 * script        = 4ALPHA              ; ISO 15924 code
1400 *
1401 * region        = 2ALPHA              ; ISO 3166-1 code
1402 *               / 3DIGIT              ; UN M.49 code
1403 *
1404 * variant       = 5*8alphanum         ; registered variants
1405 *               / (DIGIT 3alphanum)
1406 *
1407 * extension     = singleton 1*("-" (2*8alphanum))
1408 *
1409 *                                     ; Single alphanumerics
1410 *                                     ; "x" reserved for private use
1411 * singleton     = DIGIT               ; 0 - 9
1412 *               / %x41-57             ; A - W
1413 *               / %x59-5A             ; Y - Z
1414 *               / %x61-77             ; a - w
1415 *               / %x79-7A             ; y - z
1416 *
1417 * it sounds right to still allow Irregular i-xxx IANA and user codes too
1418 * The parser below doesn't try to cope with extension or privateuse
1419 * that could be added but that's not interoperable anyway
1420 *
1421 * Returns 1 if correct 0 otherwise
1422 **/
1423int
1424xmlCheckLanguageID(const xmlChar * lang)
1425{
1426    const xmlChar *cur = lang, *nxt;
1427
1428    if (cur == NULL)
1429        return (0);
1430    if (((cur[0] == 'i') && (cur[1] == '-')) ||
1431        ((cur[0] == 'I') && (cur[1] == '-')) ||
1432        ((cur[0] == 'x') && (cur[1] == '-')) ||
1433        ((cur[0] == 'X') && (cur[1] == '-'))) {
1434        /*
1435         * Still allow IANA code and user code which were coming
1436         * from the previous version of the XML-1.0 specification
1437         * it's deprecated but we should not fail
1438         */
1439        cur += 2;
1440        while (((cur[0] >= 'A') && (cur[0] <= 'Z')) ||
1441               ((cur[0] >= 'a') && (cur[0] <= 'z')))
1442            cur++;
1443        return(cur[0] == 0);
1444    }
1445    nxt = cur;
1446    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1447           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1448           nxt++;
1449    if (nxt - cur >= 4) {
1450        /*
1451         * Reserved
1452         */
1453        if ((nxt - cur > 8) || (nxt[0] != 0))
1454            return(0);
1455        return(1);
1456    }
1457    if (nxt - cur < 2)
1458        return(0);
1459    /* we got an ISO 639 code */
1460    if (nxt[0] == 0)
1461        return(1);
1462    if (nxt[0] != '-')
1463        return(0);
1464
1465    nxt++;
1466    cur = nxt;
1467    /* now we can have extlang or script or region or variant */
1468    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1469        goto region_m49;
1470
1471    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1472           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1473           nxt++;
1474    if (nxt - cur == 4)
1475        goto script;
1476    if (nxt - cur == 2)
1477        goto region;
1478    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1479        goto variant;
1480    if (nxt - cur != 3)
1481        return(0);
1482    /* we parsed an extlang */
1483    if (nxt[0] == 0)
1484        return(1);
1485    if (nxt[0] != '-')
1486        return(0);
1487
1488    nxt++;
1489    cur = nxt;
1490    /* now we can have script or region or variant */
1491    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1492        goto region_m49;
1493
1494    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1495           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1496           nxt++;
1497    if (nxt - cur == 2)
1498        goto region;
1499    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1500        goto variant;
1501    if (nxt - cur != 4)
1502        return(0);
1503    /* we parsed a script */
1504script:
1505    if (nxt[0] == 0)
1506        return(1);
1507    if (nxt[0] != '-')
1508        return(0);
1509
1510    nxt++;
1511    cur = nxt;
1512    /* now we can have region or variant */
1513    if ((nxt[0] >= '0') && (nxt[0] <= '9'))
1514        goto region_m49;
1515
1516    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1517           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1518           nxt++;
1519
1520    if ((nxt - cur >= 5) && (nxt - cur <= 8))
1521        goto variant;
1522    if (nxt - cur != 2)
1523        return(0);
1524    /* we parsed a region */
1525region:
1526    if (nxt[0] == 0)
1527        return(1);
1528    if (nxt[0] != '-')
1529        return(0);
1530
1531    nxt++;
1532    cur = nxt;
1533    /* now we can just have a variant */
1534    while (((nxt[0] >= 'A') && (nxt[0] <= 'Z')) ||
1535           ((nxt[0] >= 'a') && (nxt[0] <= 'z')))
1536           nxt++;
1537
1538    if ((nxt - cur < 5) || (nxt - cur > 8))
1539        return(0);
1540
1541    /* we parsed a variant */
1542variant:
1543    if (nxt[0] == 0)
1544        return(1);
1545    if (nxt[0] != '-')
1546        return(0);
1547    /* extensions and private use subtags not checked */
1548    return (1);
1549
1550region_m49:
1551    if (((nxt[1] >= '0') && (nxt[1] <= '9')) &&
1552        ((nxt[2] >= '0') && (nxt[2] <= '9'))) {
1553        nxt += 3;
1554        goto region;
1555    }
1556    return(0);
1557}
1558
1559/************************************************************************
1560 *									*
1561 *		Parser stacks related functions and macros		*
1562 *									*
1563 ************************************************************************/
1564
1565static xmlEntityPtr xmlParseStringEntityRef(xmlParserCtxtPtr ctxt,
1566                                            const xmlChar ** str);
1567
1568#ifdef SAX2
1569/**
1570 * nsPush:
1571 * @ctxt:  an XML parser context
1572 * @prefix:  the namespace prefix or NULL
1573 * @URL:  the namespace name
1574 *
1575 * Pushes a new parser namespace on top of the ns stack
1576 *
1577 * Returns -1 in case of error, -2 if the namespace should be discarded
1578 *	   and the index in the stack otherwise.
1579 */
1580static int
1581nsPush(xmlParserCtxtPtr ctxt, const xmlChar *prefix, const xmlChar *URL)
1582{
1583    if (ctxt->options & XML_PARSE_NSCLEAN) {
1584        int i;
1585	for (i = ctxt->nsNr - 2;i >= 0;i -= 2) {
1586	    if (ctxt->nsTab[i] == prefix) {
1587		/* in scope */
1588	        if (ctxt->nsTab[i + 1] == URL)
1589		    return(-2);
1590		/* out of scope keep it */
1591		break;
1592	    }
1593	}
1594    }
1595    if ((ctxt->nsMax == 0) || (ctxt->nsTab == NULL)) {
1596	ctxt->nsMax = 10;
1597	ctxt->nsNr = 0;
1598	ctxt->nsTab = (const xmlChar **)
1599	              xmlMalloc(ctxt->nsMax * sizeof(xmlChar *));
1600	if (ctxt->nsTab == NULL) {
1601	    xmlErrMemory(ctxt, NULL);
1602	    ctxt->nsMax = 0;
1603            return (-1);
1604	}
1605    } else if (ctxt->nsNr >= ctxt->nsMax) {
1606        const xmlChar ** tmp;
1607        ctxt->nsMax *= 2;
1608        tmp = (const xmlChar **) xmlRealloc((char *) ctxt->nsTab,
1609				    ctxt->nsMax * sizeof(ctxt->nsTab[0]));
1610        if (tmp == NULL) {
1611            xmlErrMemory(ctxt, NULL);
1612	    ctxt->nsMax /= 2;
1613            return (-1);
1614        }
1615	ctxt->nsTab = tmp;
1616    }
1617    ctxt->nsTab[ctxt->nsNr++] = prefix;
1618    ctxt->nsTab[ctxt->nsNr++] = URL;
1619    return (ctxt->nsNr);
1620}
1621/**
1622 * nsPop:
1623 * @ctxt: an XML parser context
1624 * @nr:  the number to pop
1625 *
1626 * Pops the top @nr parser prefix/namespace from the ns stack
1627 *
1628 * Returns the number of namespaces removed
1629 */
1630static int
1631nsPop(xmlParserCtxtPtr ctxt, int nr)
1632{
1633    int i;
1634
1635    if (ctxt->nsTab == NULL) return(0);
1636    if (ctxt->nsNr < nr) {
1637        xmlGenericError(xmlGenericErrorContext, "Pbm popping %d NS\n", nr);
1638        nr = ctxt->nsNr;
1639    }
1640    if (ctxt->nsNr <= 0)
1641        return (0);
1642
1643    for (i = 0;i < nr;i++) {
1644         ctxt->nsNr--;
1645	 ctxt->nsTab[ctxt->nsNr] = NULL;
1646    }
1647    return(nr);
1648}
1649#endif
1650
1651static int
1652xmlCtxtGrowAttrs(xmlParserCtxtPtr ctxt, int nr) {
1653    const xmlChar **atts;
1654    int *attallocs;
1655    int maxatts;
1656
1657    if (ctxt->atts == NULL) {
1658	maxatts = 55; /* allow for 10 attrs by default */
1659	atts = (const xmlChar **)
1660	       xmlMalloc(maxatts * sizeof(xmlChar *));
1661	if (atts == NULL) goto mem_error;
1662	ctxt->atts = atts;
1663	attallocs = (int *) xmlMalloc((maxatts / 5) * sizeof(int));
1664	if (attallocs == NULL) goto mem_error;
1665	ctxt->attallocs = attallocs;
1666	ctxt->maxatts = maxatts;
1667    } else if (nr + 5 > ctxt->maxatts) {
1668	maxatts = (nr + 5) * 2;
1669	atts = (const xmlChar **) xmlRealloc((void *) ctxt->atts,
1670				     maxatts * sizeof(const xmlChar *));
1671	if (atts == NULL) goto mem_error;
1672	ctxt->atts = atts;
1673	attallocs = (int *) xmlRealloc((void *) ctxt->attallocs,
1674	                             (maxatts / 5) * sizeof(int));
1675	if (attallocs == NULL) goto mem_error;
1676	ctxt->attallocs = attallocs;
1677	ctxt->maxatts = maxatts;
1678    }
1679    return(ctxt->maxatts);
1680mem_error:
1681    xmlErrMemory(ctxt, NULL);
1682    return(-1);
1683}
1684
1685/**
1686 * inputPush:
1687 * @ctxt:  an XML parser context
1688 * @value:  the parser input
1689 *
1690 * Pushes a new parser input on top of the input stack
1691 *
1692 * Returns -1 in case of error, the index in the stack otherwise
1693 */
1694int
1695inputPush(xmlParserCtxtPtr ctxt, xmlParserInputPtr value)
1696{
1697    if ((ctxt == NULL) || (value == NULL))
1698        return(-1);
1699    if (ctxt->inputNr >= ctxt->inputMax) {
1700        ctxt->inputMax *= 2;
1701        ctxt->inputTab =
1702            (xmlParserInputPtr *) xmlRealloc(ctxt->inputTab,
1703                                             ctxt->inputMax *
1704                                             sizeof(ctxt->inputTab[0]));
1705        if (ctxt->inputTab == NULL) {
1706            xmlErrMemory(ctxt, NULL);
1707	    xmlFreeInputStream(value);
1708	    ctxt->inputMax /= 2;
1709	    value = NULL;
1710            return (-1);
1711        }
1712    }
1713    ctxt->inputTab[ctxt->inputNr] = value;
1714    ctxt->input = value;
1715    return (ctxt->inputNr++);
1716}
1717/**
1718 * inputPop:
1719 * @ctxt: an XML parser context
1720 *
1721 * Pops the top parser input from the input stack
1722 *
1723 * Returns the input just removed
1724 */
1725xmlParserInputPtr
1726inputPop(xmlParserCtxtPtr ctxt)
1727{
1728    xmlParserInputPtr ret;
1729
1730    if (ctxt == NULL)
1731        return(NULL);
1732    if (ctxt->inputNr <= 0)
1733        return (NULL);
1734    ctxt->inputNr--;
1735    if (ctxt->inputNr > 0)
1736        ctxt->input = ctxt->inputTab[ctxt->inputNr - 1];
1737    else
1738        ctxt->input = NULL;
1739    ret = ctxt->inputTab[ctxt->inputNr];
1740    ctxt->inputTab[ctxt->inputNr] = NULL;
1741    return (ret);
1742}
1743/**
1744 * nodePush:
1745 * @ctxt:  an XML parser context
1746 * @value:  the element node
1747 *
1748 * Pushes a new element node on top of the node stack
1749 *
1750 * Returns -1 in case of error, the index in the stack otherwise
1751 */
1752int
1753nodePush(xmlParserCtxtPtr ctxt, xmlNodePtr value)
1754{
1755    if (ctxt == NULL) return(0);
1756    if (ctxt->nodeNr >= ctxt->nodeMax) {
1757        xmlNodePtr *tmp;
1758
1759	tmp = (xmlNodePtr *) xmlRealloc(ctxt->nodeTab,
1760                                      ctxt->nodeMax * 2 *
1761                                      sizeof(ctxt->nodeTab[0]));
1762        if (tmp == NULL) {
1763            xmlErrMemory(ctxt, NULL);
1764            return (-1);
1765        }
1766        ctxt->nodeTab = tmp;
1767	ctxt->nodeMax *= 2;
1768    }
1769    if ((((unsigned int) ctxt->nodeNr) > xmlParserMaxDepth) &&
1770        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
1771	xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
1772		 "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
1773			  xmlParserMaxDepth);
1774	ctxt->instate = XML_PARSER_EOF;
1775	return(-1);
1776    }
1777    ctxt->nodeTab[ctxt->nodeNr] = value;
1778    ctxt->node = value;
1779    return (ctxt->nodeNr++);
1780}
1781
1782/**
1783 * nodePop:
1784 * @ctxt: an XML parser context
1785 *
1786 * Pops the top element node from the node stack
1787 *
1788 * Returns the node just removed
1789 */
1790xmlNodePtr
1791nodePop(xmlParserCtxtPtr ctxt)
1792{
1793    xmlNodePtr ret;
1794
1795    if (ctxt == NULL) return(NULL);
1796    if (ctxt->nodeNr <= 0)
1797        return (NULL);
1798    ctxt->nodeNr--;
1799    if (ctxt->nodeNr > 0)
1800        ctxt->node = ctxt->nodeTab[ctxt->nodeNr - 1];
1801    else
1802        ctxt->node = NULL;
1803    ret = ctxt->nodeTab[ctxt->nodeNr];
1804    ctxt->nodeTab[ctxt->nodeNr] = NULL;
1805    return (ret);
1806}
1807
1808#ifdef LIBXML_PUSH_ENABLED
1809/**
1810 * nameNsPush:
1811 * @ctxt:  an XML parser context
1812 * @value:  the element name
1813 * @prefix:  the element prefix
1814 * @URI:  the element namespace name
1815 *
1816 * Pushes a new element name/prefix/URL on top of the name stack
1817 *
1818 * Returns -1 in case of error, the index in the stack otherwise
1819 */
1820static int
1821nameNsPush(xmlParserCtxtPtr ctxt, const xmlChar * value,
1822           const xmlChar *prefix, const xmlChar *URI, int nsNr)
1823{
1824    if (ctxt->nameNr >= ctxt->nameMax) {
1825        const xmlChar * *tmp;
1826        void **tmp2;
1827        ctxt->nameMax *= 2;
1828        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
1829                                    ctxt->nameMax *
1830                                    sizeof(ctxt->nameTab[0]));
1831        if (tmp == NULL) {
1832	    ctxt->nameMax /= 2;
1833	    goto mem_error;
1834        }
1835	ctxt->nameTab = tmp;
1836        tmp2 = (void **) xmlRealloc((void * *)ctxt->pushTab,
1837                                    ctxt->nameMax * 3 *
1838                                    sizeof(ctxt->pushTab[0]));
1839        if (tmp2 == NULL) {
1840	    ctxt->nameMax /= 2;
1841	    goto mem_error;
1842        }
1843	ctxt->pushTab = tmp2;
1844    }
1845    ctxt->nameTab[ctxt->nameNr] = value;
1846    ctxt->name = value;
1847    ctxt->pushTab[ctxt->nameNr * 3] = (void *) prefix;
1848    ctxt->pushTab[ctxt->nameNr * 3 + 1] = (void *) URI;
1849    ctxt->pushTab[ctxt->nameNr * 3 + 2] = (void *) (long) nsNr;
1850    return (ctxt->nameNr++);
1851mem_error:
1852    xmlErrMemory(ctxt, NULL);
1853    return (-1);
1854}
1855/**
1856 * nameNsPop:
1857 * @ctxt: an XML parser context
1858 *
1859 * Pops the top element/prefix/URI name from the name stack
1860 *
1861 * Returns the name just removed
1862 */
1863static const xmlChar *
1864nameNsPop(xmlParserCtxtPtr ctxt)
1865{
1866    const xmlChar *ret;
1867
1868    if (ctxt->nameNr <= 0)
1869        return (NULL);
1870    ctxt->nameNr--;
1871    if (ctxt->nameNr > 0)
1872        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
1873    else
1874        ctxt->name = NULL;
1875    ret = ctxt->nameTab[ctxt->nameNr];
1876    ctxt->nameTab[ctxt->nameNr] = NULL;
1877    return (ret);
1878}
1879#endif /* LIBXML_PUSH_ENABLED */
1880
1881/**
1882 * namePush:
1883 * @ctxt:  an XML parser context
1884 * @value:  the element name
1885 *
1886 * Pushes a new element name on top of the name stack
1887 *
1888 * Returns -1 in case of error, the index in the stack otherwise
1889 */
1890int
1891namePush(xmlParserCtxtPtr ctxt, const xmlChar * value)
1892{
1893    if (ctxt == NULL) return (-1);
1894
1895    if (ctxt->nameNr >= ctxt->nameMax) {
1896        const xmlChar * *tmp;
1897        tmp = (const xmlChar * *) xmlRealloc((xmlChar * *)ctxt->nameTab,
1898                                    ctxt->nameMax * 2 *
1899                                    sizeof(ctxt->nameTab[0]));
1900        if (tmp == NULL) {
1901	    goto mem_error;
1902        }
1903	ctxt->nameTab = tmp;
1904        ctxt->nameMax *= 2;
1905    }
1906    ctxt->nameTab[ctxt->nameNr] = value;
1907    ctxt->name = value;
1908    return (ctxt->nameNr++);
1909mem_error:
1910    xmlErrMemory(ctxt, NULL);
1911    return (-1);
1912}
1913/**
1914 * namePop:
1915 * @ctxt: an XML parser context
1916 *
1917 * Pops the top element name from the name stack
1918 *
1919 * Returns the name just removed
1920 */
1921const xmlChar *
1922namePop(xmlParserCtxtPtr ctxt)
1923{
1924    const xmlChar *ret;
1925
1926    if ((ctxt == NULL) || (ctxt->nameNr <= 0))
1927        return (NULL);
1928    ctxt->nameNr--;
1929    if (ctxt->nameNr > 0)
1930        ctxt->name = ctxt->nameTab[ctxt->nameNr - 1];
1931    else
1932        ctxt->name = NULL;
1933    ret = ctxt->nameTab[ctxt->nameNr];
1934    ctxt->nameTab[ctxt->nameNr] = NULL;
1935    return (ret);
1936}
1937
1938static int spacePush(xmlParserCtxtPtr ctxt, int val) {
1939    if (ctxt->spaceNr >= ctxt->spaceMax) {
1940        int *tmp;
1941
1942	ctxt->spaceMax *= 2;
1943        tmp = (int *) xmlRealloc(ctxt->spaceTab,
1944	                         ctxt->spaceMax * sizeof(ctxt->spaceTab[0]));
1945        if (tmp == NULL) {
1946	    xmlErrMemory(ctxt, NULL);
1947	    ctxt->spaceMax /=2;
1948	    return(-1);
1949	}
1950	ctxt->spaceTab = tmp;
1951    }
1952    ctxt->spaceTab[ctxt->spaceNr] = val;
1953    ctxt->space = &ctxt->spaceTab[ctxt->spaceNr];
1954    return(ctxt->spaceNr++);
1955}
1956
1957static int spacePop(xmlParserCtxtPtr ctxt) {
1958    int ret;
1959    if (ctxt->spaceNr <= 0) return(0);
1960    ctxt->spaceNr--;
1961    if (ctxt->spaceNr > 0)
1962	ctxt->space = &ctxt->spaceTab[ctxt->spaceNr - 1];
1963    else
1964        ctxt->space = &ctxt->spaceTab[0];
1965    ret = ctxt->spaceTab[ctxt->spaceNr];
1966    ctxt->spaceTab[ctxt->spaceNr] = -1;
1967    return(ret);
1968}
1969
1970/*
1971 * Macros for accessing the content. Those should be used only by the parser,
1972 * and not exported.
1973 *
1974 * Dirty macros, i.e. one often need to make assumption on the context to
1975 * use them
1976 *
1977 *   CUR_PTR return the current pointer to the xmlChar to be parsed.
1978 *           To be used with extreme caution since operations consuming
1979 *           characters may move the input buffer to a different location !
1980 *   CUR     returns the current xmlChar value, i.e. a 8 bit value if compiled
1981 *           This should be used internally by the parser
1982 *           only to compare to ASCII values otherwise it would break when
1983 *           running with UTF-8 encoding.
1984 *   RAW     same as CUR but in the input buffer, bypass any token
1985 *           extraction that may have been done
1986 *   NXT(n)  returns the n'th next xmlChar. Same as CUR is should be used only
1987 *           to compare on ASCII based substring.
1988 *   SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
1989 *           strings without newlines within the parser.
1990 *   NEXT1(l) Skip 1 xmlChar, and must also be used only to skip 1 non-newline ASCII
1991 *           defined char within the parser.
1992 * Clean macros, not dependent of an ASCII context, expect UTF-8 encoding
1993 *
1994 *   NEXT    Skip to the next character, this does the proper decoding
1995 *           in UTF-8 mode. It also pop-up unfinished entities on the fly.
1996 *   NEXTL(l) Skip the current unicode character of l xmlChars long.
1997 *   CUR_CHAR(l) returns the current unicode character (int), set l
1998 *           to the number of xmlChars used for the encoding [0-5].
1999 *   CUR_SCHAR  same but operate on a string instead of the context
2000 *   COPY_BUF  copy the current unicode char to the target buffer, increment
2001 *            the index
2002 *   GROW, SHRINK  handling of input buffers
2003 */
2004
2005#define RAW (*ctxt->input->cur)
2006#define CUR (*ctxt->input->cur)
2007#define NXT(val) ctxt->input->cur[(val)]
2008#define CUR_PTR ctxt->input->cur
2009
2010#define CMP4( s, c1, c2, c3, c4 ) \
2011  ( ((unsigned char *) s)[ 0 ] == c1 && ((unsigned char *) s)[ 1 ] == c2 && \
2012    ((unsigned char *) s)[ 2 ] == c3 && ((unsigned char *) s)[ 3 ] == c4 )
2013#define CMP5( s, c1, c2, c3, c4, c5 ) \
2014  ( CMP4( s, c1, c2, c3, c4 ) && ((unsigned char *) s)[ 4 ] == c5 )
2015#define CMP6( s, c1, c2, c3, c4, c5, c6 ) \
2016  ( CMP5( s, c1, c2, c3, c4, c5 ) && ((unsigned char *) s)[ 5 ] == c6 )
2017#define CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) \
2018  ( CMP6( s, c1, c2, c3, c4, c5, c6 ) && ((unsigned char *) s)[ 6 ] == c7 )
2019#define CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) \
2020  ( CMP7( s, c1, c2, c3, c4, c5, c6, c7 ) && ((unsigned char *) s)[ 7 ] == c8 )
2021#define CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) \
2022  ( CMP8( s, c1, c2, c3, c4, c5, c6, c7, c8 ) && \
2023    ((unsigned char *) s)[ 8 ] == c9 )
2024#define CMP10( s, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 ) \
2025  ( CMP9( s, c1, c2, c3, c4, c5, c6, c7, c8, c9 ) && \
2026    ((unsigned char *) s)[ 9 ] == c10 )
2027
2028#define SKIP(val) do {							\
2029    ctxt->nbChars += (val),ctxt->input->cur += (val),ctxt->input->col+=(val);			\
2030    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);	\
2031    if ((*ctxt->input->cur == 0) &&					\
2032        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))		\
2033	    xmlPopInput(ctxt);						\
2034  } while (0)
2035
2036#define SKIPL(val) do {							\
2037    int skipl;								\
2038    for(skipl=0; skipl<val; skipl++) {					\
2039	if (*(ctxt->input->cur) == '\n') {				\
2040	ctxt->input->line++; ctxt->input->col = 1;			\
2041	} else ctxt->input->col++;					\
2042	ctxt->nbChars++;						\
2043	ctxt->input->cur++;						\
2044    }									\
2045    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);	\
2046    if ((*ctxt->input->cur == 0) &&					\
2047        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))		\
2048	    xmlPopInput(ctxt);						\
2049  } while (0)
2050
2051#define SHRINK if ((ctxt->progressive == 0) &&				\
2052		   (ctxt->input->cur - ctxt->input->base > 2 * INPUT_CHUNK) && \
2053		   (ctxt->input->end - ctxt->input->cur < 2 * INPUT_CHUNK)) \
2054	xmlSHRINK (ctxt);
2055
2056static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
2057    xmlParserInputShrink(ctxt->input);
2058    if ((*ctxt->input->cur == 0) &&
2059        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
2060	    xmlPopInput(ctxt);
2061  }
2062
2063#define GROW if ((ctxt->progressive == 0) &&				\
2064		 (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK))	\
2065	xmlGROW (ctxt);
2066
2067static void xmlGROW (xmlParserCtxtPtr ctxt) {
2068    unsigned long curEnd = ctxt->input->end - ctxt->input->cur;
2069    unsigned long curBase = ctxt->input->cur - ctxt->input->base;
2070
2071    if (((curEnd > (unsigned long) XML_MAX_LOOKUP_LIMIT) ||
2072         (curBase > (unsigned long) XML_MAX_LOOKUP_LIMIT)) &&
2073         ((ctxt->input->buf) && (ctxt->input->buf->readcallback != (xmlInputReadCallback) xmlNop)) &&
2074        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
2075        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
2076        ctxt->instate = XML_PARSER_EOF;
2077    }
2078    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2079    if ((ctxt->input->cur != NULL) && (*ctxt->input->cur == 0) &&
2080        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
2081	    xmlPopInput(ctxt);
2082}
2083
2084#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
2085
2086#define NEXT xmlNextChar(ctxt)
2087
2088#define NEXT1 {								\
2089	ctxt->input->col++;						\
2090	ctxt->input->cur++;						\
2091	ctxt->nbChars++;						\
2092	if (*ctxt->input->cur == 0)					\
2093	    xmlParserInputGrow(ctxt->input, INPUT_CHUNK);		\
2094    }
2095
2096#define NEXTL(l) do {							\
2097    if (*(ctxt->input->cur) == '\n') {					\
2098	ctxt->input->line++; ctxt->input->col = 1;			\
2099    } else ctxt->input->col++;						\
2100    ctxt->input->cur += l;				\
2101    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);	\
2102  } while (0)
2103
2104#define CUR_CHAR(l) xmlCurrentChar(ctxt, &l)
2105#define CUR_SCHAR(s, l) xmlStringCurrentChar(ctxt, s, &l)
2106
2107#define COPY_BUF(l,b,i,v)						\
2108    if (l == 1) b[i++] = (xmlChar) v;					\
2109    else i += xmlCopyCharMultiByte(&b[i],v)
2110
2111/**
2112 * xmlSkipBlankChars:
2113 * @ctxt:  the XML parser context
2114 *
2115 * skip all blanks character found at that point in the input streams.
2116 * It pops up finished entities in the process if allowable at that point.
2117 *
2118 * Returns the number of space chars skipped
2119 */
2120
2121int
2122xmlSkipBlankChars(xmlParserCtxtPtr ctxt) {
2123    int res = 0;
2124
2125    /*
2126     * It's Okay to use CUR/NEXT here since all the blanks are on
2127     * the ASCII range.
2128     */
2129    if ((ctxt->inputNr == 1) && (ctxt->instate != XML_PARSER_DTD)) {
2130	const xmlChar *cur;
2131	/*
2132	 * if we are in the document content, go really fast
2133	 */
2134	cur = ctxt->input->cur;
2135	while (IS_BLANK_CH(*cur)) {
2136	    if (*cur == '\n') {
2137		ctxt->input->line++; ctxt->input->col = 1;
2138	    } else {
2139		ctxt->input->col++;
2140	    }
2141	    cur++;
2142	    res++;
2143	    if (*cur == 0) {
2144		ctxt->input->cur = cur;
2145		xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
2146		cur = ctxt->input->cur;
2147	    }
2148	}
2149	ctxt->input->cur = cur;
2150    } else {
2151	int cur;
2152	do {
2153	    cur = CUR;
2154	    while (IS_BLANK_CH(cur)) { /* CHECKED tstblanks.xml */
2155		NEXT;
2156		cur = CUR;
2157		res++;
2158	    }
2159	    while ((cur == 0) && (ctxt->inputNr > 1) &&
2160		   (ctxt->instate != XML_PARSER_COMMENT)) {
2161		xmlPopInput(ctxt);
2162		cur = CUR;
2163	    }
2164	    /*
2165	     * Need to handle support of entities branching here
2166	     */
2167	    if (*ctxt->input->cur == '%') xmlParserHandlePEReference(ctxt);
2168	} while (IS_BLANK(cur)); /* CHECKED tstblanks.xml */
2169    }
2170    return(res);
2171}
2172
2173/************************************************************************
2174 *									*
2175 *		Commodity functions to handle entities			*
2176 *									*
2177 ************************************************************************/
2178
2179/**
2180 * xmlPopInput:
2181 * @ctxt:  an XML parser context
2182 *
2183 * xmlPopInput: the current input pointed by ctxt->input came to an end
2184 *          pop it and return the next char.
2185 *
2186 * Returns the current xmlChar in the parser context
2187 */
2188xmlChar
2189xmlPopInput(xmlParserCtxtPtr ctxt) {
2190    if ((ctxt == NULL) || (ctxt->inputNr <= 1)) return(0);
2191    if (xmlParserDebugEntities)
2192	xmlGenericError(xmlGenericErrorContext,
2193		"Popping input %d\n", ctxt->inputNr);
2194    xmlFreeInputStream(inputPop(ctxt));
2195    if ((*ctxt->input->cur == 0) &&
2196        (xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
2197	    return(xmlPopInput(ctxt));
2198    return(CUR);
2199}
2200
2201/**
2202 * xmlPushInput:
2203 * @ctxt:  an XML parser context
2204 * @input:  an XML parser input fragment (entity, XML fragment ...).
2205 *
2206 * xmlPushInput: switch to a new input stream which is stacked on top
2207 *               of the previous one(s).
2208 * Returns -1 in case of error or the index in the input stack
2209 */
2210int
2211xmlPushInput(xmlParserCtxtPtr ctxt, xmlParserInputPtr input) {
2212    int ret;
2213    if (input == NULL) return(-1);
2214
2215    if (xmlParserDebugEntities) {
2216	if ((ctxt->input != NULL) && (ctxt->input->filename))
2217	    xmlGenericError(xmlGenericErrorContext,
2218		    "%s(%d): ", ctxt->input->filename,
2219		    ctxt->input->line);
2220	xmlGenericError(xmlGenericErrorContext,
2221		"Pushing input %d : %.30s\n", ctxt->inputNr+1, input->cur);
2222    }
2223    ret = inputPush(ctxt, input);
2224    if (ctxt->instate == XML_PARSER_EOF)
2225        return(-1);
2226    GROW;
2227    return(ret);
2228}
2229
2230/**
2231 * xmlParseCharRef:
2232 * @ctxt:  an XML parser context
2233 *
2234 * parse Reference declarations
2235 *
2236 * [66] CharRef ::= '&#' [0-9]+ ';' |
2237 *                  '&#x' [0-9a-fA-F]+ ';'
2238 *
2239 * [ WFC: Legal Character ]
2240 * Characters referred to using character references must match the
2241 * production for Char.
2242 *
2243 * Returns the value parsed (as an int), 0 in case of error
2244 */
2245int
2246xmlParseCharRef(xmlParserCtxtPtr ctxt) {
2247    unsigned int val = 0;
2248    int count = 0;
2249    unsigned int outofrange = 0;
2250
2251    /*
2252     * Using RAW/CUR/NEXT is okay since we are working on ASCII range here
2253     */
2254    if ((RAW == '&') && (NXT(1) == '#') &&
2255        (NXT(2) == 'x')) {
2256	SKIP(3);
2257	GROW;
2258	while (RAW != ';') { /* loop blocked by count */
2259	    if (count++ > 20) {
2260		count = 0;
2261		GROW;
2262                if (ctxt->instate == XML_PARSER_EOF)
2263                    return(0);
2264	    }
2265	    if ((RAW >= '0') && (RAW <= '9'))
2266	        val = val * 16 + (CUR - '0');
2267	    else if ((RAW >= 'a') && (RAW <= 'f') && (count < 20))
2268	        val = val * 16 + (CUR - 'a') + 10;
2269	    else if ((RAW >= 'A') && (RAW <= 'F') && (count < 20))
2270	        val = val * 16 + (CUR - 'A') + 10;
2271	    else {
2272		xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2273		val = 0;
2274		break;
2275	    }
2276	    if (val > 0x10FFFF)
2277	        outofrange = val;
2278
2279	    NEXT;
2280	    count++;
2281	}
2282	if (RAW == ';') {
2283	    /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2284	    ctxt->input->col++;
2285	    ctxt->nbChars ++;
2286	    ctxt->input->cur++;
2287	}
2288    } else if  ((RAW == '&') && (NXT(1) == '#')) {
2289	SKIP(2);
2290	GROW;
2291	while (RAW != ';') { /* loop blocked by count */
2292	    if (count++ > 20) {
2293		count = 0;
2294		GROW;
2295                if (ctxt->instate == XML_PARSER_EOF)
2296                    return(0);
2297	    }
2298	    if ((RAW >= '0') && (RAW <= '9'))
2299	        val = val * 10 + (CUR - '0');
2300	    else {
2301		xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2302		val = 0;
2303		break;
2304	    }
2305	    if (val > 0x10FFFF)
2306	        outofrange = val;
2307
2308	    NEXT;
2309	    count++;
2310	}
2311	if (RAW == ';') {
2312	    /* on purpose to avoid reentrancy problems with NEXT and SKIP */
2313	    ctxt->input->col++;
2314	    ctxt->nbChars ++;
2315	    ctxt->input->cur++;
2316	}
2317    } else {
2318        xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2319    }
2320
2321    /*
2322     * [ WFC: Legal Character ]
2323     * Characters referred to using character references must match the
2324     * production for Char.
2325     */
2326    if ((IS_CHAR(val) && (outofrange == 0))) {
2327        return(val);
2328    } else {
2329        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2330                          "xmlParseCharRef: invalid xmlChar value %d\n",
2331	                  val);
2332    }
2333    return(0);
2334}
2335
2336/**
2337 * xmlParseStringCharRef:
2338 * @ctxt:  an XML parser context
2339 * @str:  a pointer to an index in the string
2340 *
2341 * parse Reference declarations, variant parsing from a string rather
2342 * than an an input flow.
2343 *
2344 * [66] CharRef ::= '&#' [0-9]+ ';' |
2345 *                  '&#x' [0-9a-fA-F]+ ';'
2346 *
2347 * [ WFC: Legal Character ]
2348 * Characters referred to using character references must match the
2349 * production for Char.
2350 *
2351 * Returns the value parsed (as an int), 0 in case of error, str will be
2352 *         updated to the current value of the index
2353 */
2354static int
2355xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
2356    const xmlChar *ptr;
2357    xmlChar cur;
2358    unsigned int val = 0;
2359    unsigned int outofrange = 0;
2360
2361    if ((str == NULL) || (*str == NULL)) return(0);
2362    ptr = *str;
2363    cur = *ptr;
2364    if ((cur == '&') && (ptr[1] == '#') && (ptr[2] == 'x')) {
2365	ptr += 3;
2366	cur = *ptr;
2367	while (cur != ';') { /* Non input consuming loop */
2368	    if ((cur >= '0') && (cur <= '9'))
2369	        val = val * 16 + (cur - '0');
2370	    else if ((cur >= 'a') && (cur <= 'f'))
2371	        val = val * 16 + (cur - 'a') + 10;
2372	    else if ((cur >= 'A') && (cur <= 'F'))
2373	        val = val * 16 + (cur - 'A') + 10;
2374	    else {
2375		xmlFatalErr(ctxt, XML_ERR_INVALID_HEX_CHARREF, NULL);
2376		val = 0;
2377		break;
2378	    }
2379	    if (val > 0x10FFFF)
2380	        outofrange = val;
2381
2382	    ptr++;
2383	    cur = *ptr;
2384	}
2385	if (cur == ';')
2386	    ptr++;
2387    } else if  ((cur == '&') && (ptr[1] == '#')){
2388	ptr += 2;
2389	cur = *ptr;
2390	while (cur != ';') { /* Non input consuming loops */
2391	    if ((cur >= '0') && (cur <= '9'))
2392	        val = val * 10 + (cur - '0');
2393	    else {
2394		xmlFatalErr(ctxt, XML_ERR_INVALID_DEC_CHARREF, NULL);
2395		val = 0;
2396		break;
2397	    }
2398	    if (val > 0x10FFFF)
2399	        outofrange = val;
2400
2401	    ptr++;
2402	    cur = *ptr;
2403	}
2404	if (cur == ';')
2405	    ptr++;
2406    } else {
2407	xmlFatalErr(ctxt, XML_ERR_INVALID_CHARREF, NULL);
2408	return(0);
2409    }
2410    *str = ptr;
2411
2412    /*
2413     * [ WFC: Legal Character ]
2414     * Characters referred to using character references must match the
2415     * production for Char.
2416     */
2417    if ((IS_CHAR(val) && (outofrange == 0))) {
2418        return(val);
2419    } else {
2420        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
2421			  "xmlParseStringCharRef: invalid xmlChar value %d\n",
2422			  val);
2423    }
2424    return(0);
2425}
2426
2427/**
2428 * xmlNewBlanksWrapperInputStream:
2429 * @ctxt:  an XML parser context
2430 * @entity:  an Entity pointer
2431 *
2432 * Create a new input stream for wrapping
2433 * blanks around a PEReference
2434 *
2435 * Returns the new input stream or NULL
2436 */
2437
2438static void deallocblankswrapper (xmlChar *str) {xmlFree(str);}
2439
2440static xmlParserInputPtr
2441xmlNewBlanksWrapperInputStream(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
2442    xmlParserInputPtr input;
2443    xmlChar *buffer;
2444    size_t length;
2445    if (entity == NULL) {
2446	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
2447	            "xmlNewBlanksWrapperInputStream entity\n");
2448	return(NULL);
2449    }
2450    if (xmlParserDebugEntities)
2451	xmlGenericError(xmlGenericErrorContext,
2452		"new blanks wrapper for entity: %s\n", entity->name);
2453    input = xmlNewInputStream(ctxt);
2454    if (input == NULL) {
2455	return(NULL);
2456    }
2457    length = xmlStrlen(entity->name) + 5;
2458    buffer = xmlMallocAtomic(length);
2459    if (buffer == NULL) {
2460	xmlErrMemory(ctxt, NULL);
2461        xmlFree(input);
2462	return(NULL);
2463    }
2464    buffer [0] = ' ';
2465    buffer [1] = '%';
2466    buffer [length-3] = ';';
2467    buffer [length-2] = ' ';
2468    buffer [length-1] = 0;
2469    memcpy(buffer + 2, entity->name, length - 5);
2470    input->free = deallocblankswrapper;
2471    input->base = buffer;
2472    input->cur = buffer;
2473    input->length = length;
2474    input->end = &buffer[length];
2475    return(input);
2476}
2477
2478/**
2479 * xmlParserHandlePEReference:
2480 * @ctxt:  the parser context
2481 *
2482 * [69] PEReference ::= '%' Name ';'
2483 *
2484 * [ WFC: No Recursion ]
2485 * A parsed entity must not contain a recursive
2486 * reference to itself, either directly or indirectly.
2487 *
2488 * [ WFC: Entity Declared ]
2489 * In a document without any DTD, a document with only an internal DTD
2490 * subset which contains no parameter entity references, or a document
2491 * with "standalone='yes'", ...  ... The declaration of a parameter
2492 * entity must precede any reference to it...
2493 *
2494 * [ VC: Entity Declared ]
2495 * In a document with an external subset or external parameter entities
2496 * with "standalone='no'", ...  ... The declaration of a parameter entity
2497 * must precede any reference to it...
2498 *
2499 * [ WFC: In DTD ]
2500 * Parameter-entity references may only appear in the DTD.
2501 * NOTE: misleading but this is handled.
2502 *
2503 * A PEReference may have been detected in the current input stream
2504 * the handling is done accordingly to
2505 *      http://www.w3.org/TR/REC-xml#entproc
2506 * i.e.
2507 *   - Included in literal in entity values
2508 *   - Included as Parameter Entity reference within DTDs
2509 */
2510void
2511xmlParserHandlePEReference(xmlParserCtxtPtr ctxt) {
2512    const xmlChar *name;
2513    xmlEntityPtr entity = NULL;
2514    xmlParserInputPtr input;
2515
2516    if (RAW != '%') return;
2517    switch(ctxt->instate) {
2518	case XML_PARSER_CDATA_SECTION:
2519	    return;
2520        case XML_PARSER_COMMENT:
2521	    return;
2522	case XML_PARSER_START_TAG:
2523	    return;
2524	case XML_PARSER_END_TAG:
2525	    return;
2526        case XML_PARSER_EOF:
2527	    xmlFatalErr(ctxt, XML_ERR_PEREF_AT_EOF, NULL);
2528	    return;
2529        case XML_PARSER_PROLOG:
2530	case XML_PARSER_START:
2531	case XML_PARSER_MISC:
2532	    xmlFatalErr(ctxt, XML_ERR_PEREF_IN_PROLOG, NULL);
2533	    return;
2534	case XML_PARSER_ENTITY_DECL:
2535        case XML_PARSER_CONTENT:
2536        case XML_PARSER_ATTRIBUTE_VALUE:
2537        case XML_PARSER_PI:
2538	case XML_PARSER_SYSTEM_LITERAL:
2539	case XML_PARSER_PUBLIC_LITERAL:
2540	    /* we just ignore it there */
2541	    return;
2542        case XML_PARSER_EPILOG:
2543	    xmlFatalErr(ctxt, XML_ERR_PEREF_IN_EPILOG, NULL);
2544	    return;
2545	case XML_PARSER_ENTITY_VALUE:
2546	    /*
2547	     * NOTE: in the case of entity values, we don't do the
2548	     *       substitution here since we need the literal
2549	     *       entity value to be able to save the internal
2550	     *       subset of the document.
2551	     *       This will be handled by xmlStringDecodeEntities
2552	     */
2553	    return;
2554        case XML_PARSER_DTD:
2555	    /*
2556	     * [WFC: Well-Formedness Constraint: PEs in Internal Subset]
2557	     * In the internal DTD subset, parameter-entity references
2558	     * can occur only where markup declarations can occur, not
2559	     * within markup declarations.
2560	     * In that case this is handled in xmlParseMarkupDecl
2561	     */
2562	    if ((ctxt->external == 0) && (ctxt->inputNr == 1))
2563		return;
2564	    if (IS_BLANK_CH(NXT(1)) || NXT(1) == 0)
2565		return;
2566            break;
2567        case XML_PARSER_IGNORE:
2568            return;
2569    }
2570
2571    NEXT;
2572    name = xmlParseName(ctxt);
2573    if (xmlParserDebugEntities)
2574	xmlGenericError(xmlGenericErrorContext,
2575		"PEReference: %s\n", name);
2576    if (name == NULL) {
2577	xmlFatalErr(ctxt, XML_ERR_PEREF_NO_NAME, NULL);
2578    } else {
2579	if (RAW == ';') {
2580	    NEXT;
2581	    if ((ctxt->sax != NULL) && (ctxt->sax->getParameterEntity != NULL))
2582		entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
2583	    if (ctxt->instate == XML_PARSER_EOF)
2584	        return;
2585	    if (entity == NULL) {
2586
2587		/*
2588		 * [ WFC: Entity Declared ]
2589		 * In a document without any DTD, a document with only an
2590		 * internal DTD subset which contains no parameter entity
2591		 * references, or a document with "standalone='yes'", ...
2592		 * ... The declaration of a parameter entity must precede
2593		 * any reference to it...
2594		 */
2595		if ((ctxt->standalone == 1) ||
2596		    ((ctxt->hasExternalSubset == 0) &&
2597		     (ctxt->hasPErefs == 0))) {
2598		    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
2599			 "PEReference: %%%s; not found\n", name);
2600	        } else {
2601		    /*
2602		     * [ VC: Entity Declared ]
2603		     * In a document with an external subset or external
2604		     * parameter entities with "standalone='no'", ...
2605		     * ... The declaration of a parameter entity must precede
2606		     * any reference to it...
2607		     */
2608		    if ((ctxt->validate) && (ctxt->vctxt.error != NULL)) {
2609		        xmlValidityError(ctxt, XML_WAR_UNDECLARED_ENTITY,
2610			                 "PEReference: %%%s; not found\n",
2611				         name, NULL);
2612		    } else
2613		        xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
2614			              "PEReference: %%%s; not found\n",
2615				      name, NULL);
2616		    ctxt->valid = 0;
2617		}
2618		xmlParserEntityCheck(ctxt, 0, NULL, 0);
2619	    } else if (ctxt->input->free != deallocblankswrapper) {
2620		    input = xmlNewBlanksWrapperInputStream(ctxt, entity);
2621		    if (xmlPushInput(ctxt, input) < 0)
2622		        return;
2623	    } else {
2624	        if ((entity->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
2625		    (entity->etype == XML_EXTERNAL_PARAMETER_ENTITY)) {
2626		    xmlChar start[4];
2627		    xmlCharEncoding enc;
2628
2629		    /*
2630		     * Note: external parameter entities will not be loaded, it
2631		     * is not required for a non-validating parser, unless the
2632		     * option of validating, or substituting entities were
2633		     * given. Doing so is far more secure as the parser will
2634		     * only process data coming from the document entity by
2635		     * default.
2636		     */
2637                    if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
2638		        ((ctxt->options & XML_PARSE_NOENT) == 0) &&
2639			((ctxt->options & XML_PARSE_DTDVALID) == 0) &&
2640			((ctxt->options & XML_PARSE_DTDLOAD) == 0) &&
2641			((ctxt->options & XML_PARSE_DTDATTR) == 0) &&
2642			(ctxt->replaceEntities == 0) &&
2643			(ctxt->validate == 0))
2644			return;
2645
2646		    /*
2647		     * handle the extra spaces added before and after
2648		     * c.f. http://www.w3.org/TR/REC-xml#as-PE
2649		     * this is done independently.
2650		     */
2651		    input = xmlNewEntityInputStream(ctxt, entity);
2652		    if (xmlPushInput(ctxt, input) < 0)
2653		        return;
2654
2655		    /*
2656		     * Get the 4 first bytes and decode the charset
2657		     * if enc != XML_CHAR_ENCODING_NONE
2658		     * plug some encoding conversion routines.
2659		     * Note that, since we may have some non-UTF8
2660		     * encoding (like UTF16, bug 135229), the 'length'
2661		     * is not known, but we can calculate based upon
2662		     * the amount of data in the buffer.
2663		     */
2664		    GROW
2665                    if (ctxt->instate == XML_PARSER_EOF)
2666                        return;
2667		    if ((ctxt->input->end - ctxt->input->cur)>=4) {
2668			start[0] = RAW;
2669			start[1] = NXT(1);
2670			start[2] = NXT(2);
2671			start[3] = NXT(3);
2672			enc = xmlDetectCharEncoding(start, 4);
2673			if (enc != XML_CHAR_ENCODING_NONE) {
2674			    xmlSwitchEncoding(ctxt, enc);
2675			}
2676		    }
2677
2678		    if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
2679			(CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l' )) &&
2680			(IS_BLANK_CH(NXT(5)))) {
2681			xmlParseTextDecl(ctxt);
2682		    }
2683		} else {
2684		    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
2685			     "PEReference: %s is not a parameter entity\n",
2686				      name);
2687		}
2688	    }
2689	} else {
2690	    xmlFatalErr(ctxt, XML_ERR_PEREF_SEMICOL_MISSING, NULL);
2691	}
2692    }
2693}
2694
2695/*
2696 * Macro used to grow the current buffer.
2697 * buffer##_size is expected to be a size_t
2698 * mem_error: is expected to handle memory allocation failures
2699 */
2700#define growBuffer(buffer, n) {						\
2701    xmlChar *tmp;							\
2702    size_t new_size = buffer##_size * 2 + n;                            \
2703    if (new_size < buffer##_size) goto mem_error;                       \
2704    tmp = (xmlChar *) xmlRealloc(buffer, new_size);                     \
2705    if (tmp == NULL) goto mem_error;					\
2706    buffer = tmp;							\
2707    buffer##_size = new_size;                                           \
2708}
2709
2710/**
2711 * xmlStringLenDecodeEntities:
2712 * @ctxt:  the parser context
2713 * @str:  the input string
2714 * @len: the string length
2715 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2716 * @end:  an end marker xmlChar, 0 if none
2717 * @end2:  an end marker xmlChar, 0 if none
2718 * @end3:  an end marker xmlChar, 0 if none
2719 *
2720 * Takes a entity string content and process to do the adequate substitutions.
2721 *
2722 * [67] Reference ::= EntityRef | CharRef
2723 *
2724 * [69] PEReference ::= '%' Name ';'
2725 *
2726 * Returns A newly allocated string with the substitution done. The caller
2727 *      must deallocate it !
2728 */
2729xmlChar *
2730xmlStringLenDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2731		      int what, xmlChar end, xmlChar  end2, xmlChar end3) {
2732    xmlChar *buffer = NULL;
2733    size_t buffer_size = 0;
2734    size_t nbchars = 0;
2735
2736    xmlChar *current = NULL;
2737    xmlChar *rep = NULL;
2738    const xmlChar *last;
2739    xmlEntityPtr ent;
2740    int c,l;
2741
2742    if ((ctxt == NULL) || (str == NULL) || (len < 0))
2743	return(NULL);
2744    last = str + len;
2745
2746    if (((ctxt->depth > 40) &&
2747         ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
2748	(ctxt->depth > 1024)) {
2749	xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
2750	return(NULL);
2751    }
2752
2753    /*
2754     * allocate a translation buffer.
2755     */
2756    buffer_size = XML_PARSER_BIG_BUFFER_SIZE;
2757    buffer = (xmlChar *) xmlMallocAtomic(buffer_size);
2758    if (buffer == NULL) goto mem_error;
2759
2760    /*
2761     * OK loop until we reach one of the ending char or a size limit.
2762     * we are operating on already parsed values.
2763     */
2764    if (str < last)
2765	c = CUR_SCHAR(str, l);
2766    else
2767        c = 0;
2768    while ((c != 0) && (c != end) && /* non input consuming loop */
2769	   (c != end2) && (c != end3)) {
2770
2771	if (c == 0) break;
2772        if ((c == '&') && (str[1] == '#')) {
2773	    int val = xmlParseStringCharRef(ctxt, &str);
2774	    if (val != 0) {
2775		COPY_BUF(0,buffer,nbchars,val);
2776	    }
2777	    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2778	        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2779	    }
2780	} else if ((c == '&') && (what & XML_SUBSTITUTE_REF)) {
2781	    if (xmlParserDebugEntities)
2782		xmlGenericError(xmlGenericErrorContext,
2783			"String decoding Entity Reference: %.30s\n",
2784			str);
2785	    ent = xmlParseStringEntityRef(ctxt, &str);
2786	    if ((ctxt->lastError.code == XML_ERR_ENTITY_LOOP) ||
2787	        (ctxt->lastError.code == XML_ERR_INTERNAL_ERROR))
2788	        goto int_error;
2789	    xmlParserEntityCheck(ctxt, 0, ent, 0);
2790	    if (ent != NULL)
2791	        ctxt->nbentities += ent->checked / 2;
2792	    if ((ent != NULL) &&
2793		(ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
2794		if (ent->content != NULL) {
2795		    COPY_BUF(0,buffer,nbchars,ent->content[0]);
2796		    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2797			growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2798		    }
2799		} else {
2800		    xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
2801			    "predefined entity has no content\n");
2802		}
2803	    } else if ((ent != NULL) && (ent->content != NULL)) {
2804		ctxt->depth++;
2805		rep = xmlStringDecodeEntities(ctxt, ent->content, what,
2806			                      0, 0, 0);
2807		ctxt->depth--;
2808
2809		if (rep != NULL) {
2810		    current = rep;
2811		    while (*current != 0) { /* non input consuming loop */
2812			buffer[nbchars++] = *current++;
2813			if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2814			    if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
2815				goto int_error;
2816			    growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2817			}
2818		    }
2819		    xmlFree(rep);
2820		    rep = NULL;
2821		}
2822	    } else if (ent != NULL) {
2823		int i = xmlStrlen(ent->name);
2824		const xmlChar *cur = ent->name;
2825
2826		buffer[nbchars++] = '&';
2827		if (nbchars + i + XML_PARSER_BUFFER_SIZE > buffer_size) {
2828		    growBuffer(buffer, i + XML_PARSER_BUFFER_SIZE);
2829		}
2830		for (;i > 0;i--)
2831		    buffer[nbchars++] = *cur++;
2832		buffer[nbchars++] = ';';
2833	    }
2834	} else if (c == '%' && (what & XML_SUBSTITUTE_PEREF)) {
2835	    if (xmlParserDebugEntities)
2836		xmlGenericError(xmlGenericErrorContext,
2837			"String decoding PE Reference: %.30s\n", str);
2838	    ent = xmlParseStringPEReference(ctxt, &str);
2839	    if (ctxt->lastError.code == XML_ERR_ENTITY_LOOP)
2840	        goto int_error;
2841	    xmlParserEntityCheck(ctxt, 0, ent, 0);
2842	    if (ent != NULL)
2843	        ctxt->nbentities += ent->checked / 2;
2844	    if (ent != NULL) {
2845                if (ent->content == NULL) {
2846		    xmlLoadEntityContent(ctxt, ent);
2847		}
2848		ctxt->depth++;
2849		rep = xmlStringDecodeEntities(ctxt, ent->content, what,
2850			                      0, 0, 0);
2851		ctxt->depth--;
2852		if (rep != NULL) {
2853		    current = rep;
2854		    while (*current != 0) { /* non input consuming loop */
2855			buffer[nbchars++] = *current++;
2856			if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2857			    if (xmlParserEntityCheck(ctxt, nbchars, ent, 0))
2858			        goto int_error;
2859			    growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2860			}
2861		    }
2862		    xmlFree(rep);
2863		    rep = NULL;
2864		}
2865	    }
2866	} else {
2867	    COPY_BUF(l,buffer,nbchars,c);
2868	    str += l;
2869	    if (nbchars + XML_PARSER_BUFFER_SIZE > buffer_size) {
2870	        growBuffer(buffer, XML_PARSER_BUFFER_SIZE);
2871	    }
2872	}
2873	if (str < last)
2874	    c = CUR_SCHAR(str, l);
2875	else
2876	    c = 0;
2877    }
2878    buffer[nbchars] = 0;
2879    return(buffer);
2880
2881mem_error:
2882    xmlErrMemory(ctxt, NULL);
2883int_error:
2884    if (rep != NULL)
2885        xmlFree(rep);
2886    if (buffer != NULL)
2887        xmlFree(buffer);
2888    return(NULL);
2889}
2890
2891/**
2892 * xmlStringDecodeEntities:
2893 * @ctxt:  the parser context
2894 * @str:  the input string
2895 * @what:  combination of XML_SUBSTITUTE_REF and XML_SUBSTITUTE_PEREF
2896 * @end:  an end marker xmlChar, 0 if none
2897 * @end2:  an end marker xmlChar, 0 if none
2898 * @end3:  an end marker xmlChar, 0 if none
2899 *
2900 * Takes a entity string content and process to do the adequate substitutions.
2901 *
2902 * [67] Reference ::= EntityRef | CharRef
2903 *
2904 * [69] PEReference ::= '%' Name ';'
2905 *
2906 * Returns A newly allocated string with the substitution done. The caller
2907 *      must deallocate it !
2908 */
2909xmlChar *
2910xmlStringDecodeEntities(xmlParserCtxtPtr ctxt, const xmlChar *str, int what,
2911		        xmlChar end, xmlChar  end2, xmlChar end3) {
2912    if ((ctxt == NULL) || (str == NULL)) return(NULL);
2913    return(xmlStringLenDecodeEntities(ctxt, str, xmlStrlen(str), what,
2914           end, end2, end3));
2915}
2916
2917/************************************************************************
2918 *									*
2919 *		Commodity functions, cleanup needed ?			*
2920 *									*
2921 ************************************************************************/
2922
2923/**
2924 * areBlanks:
2925 * @ctxt:  an XML parser context
2926 * @str:  a xmlChar *
2927 * @len:  the size of @str
2928 * @blank_chars: we know the chars are blanks
2929 *
2930 * Is this a sequence of blank chars that one can ignore ?
2931 *
2932 * Returns 1 if ignorable 0 otherwise.
2933 */
2934
2935static int areBlanks(xmlParserCtxtPtr ctxt, const xmlChar *str, int len,
2936                     int blank_chars) {
2937    int i, ret;
2938    xmlNodePtr lastChild;
2939
2940    /*
2941     * Don't spend time trying to differentiate them, the same callback is
2942     * used !
2943     */
2944    if (ctxt->sax->ignorableWhitespace == ctxt->sax->characters)
2945	return(0);
2946
2947    /*
2948     * Check for xml:space value.
2949     */
2950    if ((ctxt->space == NULL) || (*(ctxt->space) == 1) ||
2951        (*(ctxt->space) == -2))
2952	return(0);
2953
2954    /*
2955     * Check that the string is made of blanks
2956     */
2957    if (blank_chars == 0) {
2958	for (i = 0;i < len;i++)
2959	    if (!(IS_BLANK_CH(str[i]))) return(0);
2960    }
2961
2962    /*
2963     * Look if the element is mixed content in the DTD if available
2964     */
2965    if (ctxt->node == NULL) return(0);
2966    if (ctxt->myDoc != NULL) {
2967	ret = xmlIsMixedElement(ctxt->myDoc, ctxt->node->name);
2968        if (ret == 0) return(1);
2969        if (ret == 1) return(0);
2970    }
2971
2972    /*
2973     * Otherwise, heuristic :-\
2974     */
2975    if ((RAW != '<') && (RAW != 0xD)) return(0);
2976    if ((ctxt->node->children == NULL) &&
2977	(RAW == '<') && (NXT(1) == '/')) return(0);
2978
2979    lastChild = xmlGetLastChild(ctxt->node);
2980    if (lastChild == NULL) {
2981        if ((ctxt->node->type != XML_ELEMENT_NODE) &&
2982            (ctxt->node->content != NULL)) return(0);
2983    } else if (xmlNodeIsText(lastChild))
2984        return(0);
2985    else if ((ctxt->node->children != NULL) &&
2986             (xmlNodeIsText(ctxt->node->children)))
2987        return(0);
2988    return(1);
2989}
2990
2991/************************************************************************
2992 *									*
2993 *		Extra stuff for namespace support			*
2994 *	Relates to http://www.w3.org/TR/WD-xml-names			*
2995 *									*
2996 ************************************************************************/
2997
2998/**
2999 * xmlSplitQName:
3000 * @ctxt:  an XML parser context
3001 * @name:  an XML parser context
3002 * @prefix:  a xmlChar **
3003 *
3004 * parse an UTF8 encoded XML qualified name string
3005 *
3006 * [NS 5] QName ::= (Prefix ':')? LocalPart
3007 *
3008 * [NS 6] Prefix ::= NCName
3009 *
3010 * [NS 7] LocalPart ::= NCName
3011 *
3012 * Returns the local part, and prefix is updated
3013 *   to get the Prefix if any.
3014 */
3015
3016xmlChar *
3017xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
3018    xmlChar buf[XML_MAX_NAMELEN + 5];
3019    xmlChar *buffer = NULL;
3020    int len = 0;
3021    int max = XML_MAX_NAMELEN;
3022    xmlChar *ret = NULL;
3023    const xmlChar *cur = name;
3024    int c;
3025
3026    if (prefix == NULL) return(NULL);
3027    *prefix = NULL;
3028
3029    if (cur == NULL) return(NULL);
3030
3031#ifndef XML_XML_NAMESPACE
3032    /* xml: prefix is not really a namespace */
3033    if ((cur[0] == 'x') && (cur[1] == 'm') &&
3034        (cur[2] == 'l') && (cur[3] == ':'))
3035	return(xmlStrdup(name));
3036#endif
3037
3038    /* nasty but well=formed */
3039    if (cur[0] == ':')
3040	return(xmlStrdup(name));
3041
3042    c = *cur++;
3043    while ((c != 0) && (c != ':') && (len < max)) { /* tested bigname.xml */
3044	buf[len++] = c;
3045	c = *cur++;
3046    }
3047    if (len >= max) {
3048	/*
3049	 * Okay someone managed to make a huge name, so he's ready to pay
3050	 * for the processing speed.
3051	 */
3052	max = len * 2;
3053
3054	buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
3055	if (buffer == NULL) {
3056	    xmlErrMemory(ctxt, NULL);
3057	    return(NULL);
3058	}
3059	memcpy(buffer, buf, len);
3060	while ((c != 0) && (c != ':')) { /* tested bigname.xml */
3061	    if (len + 10 > max) {
3062	        xmlChar *tmp;
3063
3064		max *= 2;
3065		tmp = (xmlChar *) xmlRealloc(buffer,
3066						max * sizeof(xmlChar));
3067		if (tmp == NULL) {
3068		    xmlFree(buffer);
3069		    xmlErrMemory(ctxt, NULL);
3070		    return(NULL);
3071		}
3072		buffer = tmp;
3073	    }
3074	    buffer[len++] = c;
3075	    c = *cur++;
3076	}
3077	buffer[len] = 0;
3078    }
3079
3080    if ((c == ':') && (*cur == 0)) {
3081        if (buffer != NULL)
3082	    xmlFree(buffer);
3083	*prefix = NULL;
3084	return(xmlStrdup(name));
3085    }
3086
3087    if (buffer == NULL)
3088	ret = xmlStrndup(buf, len);
3089    else {
3090	ret = buffer;
3091	buffer = NULL;
3092	max = XML_MAX_NAMELEN;
3093    }
3094
3095
3096    if (c == ':') {
3097	c = *cur;
3098        *prefix = ret;
3099	if (c == 0) {
3100	    return(xmlStrndup(BAD_CAST "", 0));
3101	}
3102	len = 0;
3103
3104	/*
3105	 * Check that the first character is proper to start
3106	 * a new name
3107	 */
3108	if (!(((c >= 0x61) && (c <= 0x7A)) ||
3109	      ((c >= 0x41) && (c <= 0x5A)) ||
3110	      (c == '_') || (c == ':'))) {
3111	    int l;
3112	    int first = CUR_SCHAR(cur, l);
3113
3114	    if (!IS_LETTER(first) && (first != '_')) {
3115		xmlFatalErrMsgStr(ctxt, XML_NS_ERR_QNAME,
3116			    "Name %s is not XML Namespace compliant\n",
3117				  name);
3118	    }
3119	}
3120	cur++;
3121
3122	while ((c != 0) && (len < max)) { /* tested bigname2.xml */
3123	    buf[len++] = c;
3124	    c = *cur++;
3125	}
3126	if (len >= max) {
3127	    /*
3128	     * Okay someone managed to make a huge name, so he's ready to pay
3129	     * for the processing speed.
3130	     */
3131	    max = len * 2;
3132
3133	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
3134	    if (buffer == NULL) {
3135	        xmlErrMemory(ctxt, NULL);
3136		return(NULL);
3137	    }
3138	    memcpy(buffer, buf, len);
3139	    while (c != 0) { /* tested bigname2.xml */
3140		if (len + 10 > max) {
3141		    xmlChar *tmp;
3142
3143		    max *= 2;
3144		    tmp = (xmlChar *) xmlRealloc(buffer,
3145						    max * sizeof(xmlChar));
3146		    if (tmp == NULL) {
3147			xmlErrMemory(ctxt, NULL);
3148			xmlFree(buffer);
3149			return(NULL);
3150		    }
3151		    buffer = tmp;
3152		}
3153		buffer[len++] = c;
3154		c = *cur++;
3155	    }
3156	    buffer[len] = 0;
3157	}
3158
3159	if (buffer == NULL)
3160	    ret = xmlStrndup(buf, len);
3161	else {
3162	    ret = buffer;
3163	}
3164    }
3165
3166    return(ret);
3167}
3168
3169/************************************************************************
3170 *									*
3171 *			The parser itself				*
3172 *	Relates to http://www.w3.org/TR/REC-xml				*
3173 *									*
3174 ************************************************************************/
3175
3176/************************************************************************
3177 *									*
3178 *	Routines to parse Name, NCName and NmToken			*
3179 *									*
3180 ************************************************************************/
3181#ifdef DEBUG
3182static unsigned long nbParseName = 0;
3183static unsigned long nbParseNmToken = 0;
3184static unsigned long nbParseNCName = 0;
3185static unsigned long nbParseNCNameComplex = 0;
3186static unsigned long nbParseNameComplex = 0;
3187static unsigned long nbParseStringName = 0;
3188#endif
3189
3190/*
3191 * The two following functions are related to the change of accepted
3192 * characters for Name and NmToken in the Revision 5 of XML-1.0
3193 * They correspond to the modified production [4] and the new production [4a]
3194 * changes in that revision. Also note that the macros used for the
3195 * productions Letter, Digit, CombiningChar and Extender are not needed
3196 * anymore.
3197 * We still keep compatibility to pre-revision5 parsing semantic if the
3198 * new XML_PARSE_OLD10 option is given to the parser.
3199 */
3200static int
3201xmlIsNameStartChar(xmlParserCtxtPtr ctxt, int c) {
3202    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3203        /*
3204	 * Use the new checks of production [4] [4a] amd [5] of the
3205	 * Update 5 of XML-1.0
3206	 */
3207	if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3208	    (((c >= 'a') && (c <= 'z')) ||
3209	     ((c >= 'A') && (c <= 'Z')) ||
3210	     (c == '_') || (c == ':') ||
3211	     ((c >= 0xC0) && (c <= 0xD6)) ||
3212	     ((c >= 0xD8) && (c <= 0xF6)) ||
3213	     ((c >= 0xF8) && (c <= 0x2FF)) ||
3214	     ((c >= 0x370) && (c <= 0x37D)) ||
3215	     ((c >= 0x37F) && (c <= 0x1FFF)) ||
3216	     ((c >= 0x200C) && (c <= 0x200D)) ||
3217	     ((c >= 0x2070) && (c <= 0x218F)) ||
3218	     ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3219	     ((c >= 0x3001) && (c <= 0xD7FF)) ||
3220	     ((c >= 0xF900) && (c <= 0xFDCF)) ||
3221	     ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3222	     ((c >= 0x10000) && (c <= 0xEFFFF))))
3223	    return(1);
3224    } else {
3225        if (IS_LETTER(c) || (c == '_') || (c == ':'))
3226	    return(1);
3227    }
3228    return(0);
3229}
3230
3231static int
3232xmlIsNameChar(xmlParserCtxtPtr ctxt, int c) {
3233    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3234        /*
3235	 * Use the new checks of production [4] [4a] amd [5] of the
3236	 * Update 5 of XML-1.0
3237	 */
3238	if ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3239	    (((c >= 'a') && (c <= 'z')) ||
3240	     ((c >= 'A') && (c <= 'Z')) ||
3241	     ((c >= '0') && (c <= '9')) || /* !start */
3242	     (c == '_') || (c == ':') ||
3243	     (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3244	     ((c >= 0xC0) && (c <= 0xD6)) ||
3245	     ((c >= 0xD8) && (c <= 0xF6)) ||
3246	     ((c >= 0xF8) && (c <= 0x2FF)) ||
3247	     ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3248	     ((c >= 0x370) && (c <= 0x37D)) ||
3249	     ((c >= 0x37F) && (c <= 0x1FFF)) ||
3250	     ((c >= 0x200C) && (c <= 0x200D)) ||
3251	     ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3252	     ((c >= 0x2070) && (c <= 0x218F)) ||
3253	     ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3254	     ((c >= 0x3001) && (c <= 0xD7FF)) ||
3255	     ((c >= 0xF900) && (c <= 0xFDCF)) ||
3256	     ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3257	     ((c >= 0x10000) && (c <= 0xEFFFF))))
3258	     return(1);
3259    } else {
3260        if ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3261            (c == '.') || (c == '-') ||
3262	    (c == '_') || (c == ':') ||
3263	    (IS_COMBINING(c)) ||
3264	    (IS_EXTENDER(c)))
3265	    return(1);
3266    }
3267    return(0);
3268}
3269
3270static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt,
3271                                          int *len, int *alloc, int normalize);
3272
3273static const xmlChar *
3274xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
3275    int len = 0, l;
3276    int c;
3277    int count = 0;
3278
3279#ifdef DEBUG
3280    nbParseNameComplex++;
3281#endif
3282
3283    /*
3284     * Handler for more complex cases
3285     */
3286    GROW;
3287    if (ctxt->instate == XML_PARSER_EOF)
3288        return(NULL);
3289    c = CUR_CHAR(l);
3290    if ((ctxt->options & XML_PARSE_OLD10) == 0) {
3291        /*
3292	 * Use the new checks of production [4] [4a] amd [5] of the
3293	 * Update 5 of XML-1.0
3294	 */
3295	if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3296	    (!(((c >= 'a') && (c <= 'z')) ||
3297	       ((c >= 'A') && (c <= 'Z')) ||
3298	       (c == '_') || (c == ':') ||
3299	       ((c >= 0xC0) && (c <= 0xD6)) ||
3300	       ((c >= 0xD8) && (c <= 0xF6)) ||
3301	       ((c >= 0xF8) && (c <= 0x2FF)) ||
3302	       ((c >= 0x370) && (c <= 0x37D)) ||
3303	       ((c >= 0x37F) && (c <= 0x1FFF)) ||
3304	       ((c >= 0x200C) && (c <= 0x200D)) ||
3305	       ((c >= 0x2070) && (c <= 0x218F)) ||
3306	       ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3307	       ((c >= 0x3001) && (c <= 0xD7FF)) ||
3308	       ((c >= 0xF900) && (c <= 0xFDCF)) ||
3309	       ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3310	       ((c >= 0x10000) && (c <= 0xEFFFF))))) {
3311	    return(NULL);
3312	}
3313	len += l;
3314	NEXTL(l);
3315	c = CUR_CHAR(l);
3316	while ((c != ' ') && (c != '>') && (c != '/') && /* accelerators */
3317	       (((c >= 'a') && (c <= 'z')) ||
3318	        ((c >= 'A') && (c <= 'Z')) ||
3319	        ((c >= '0') && (c <= '9')) || /* !start */
3320	        (c == '_') || (c == ':') ||
3321	        (c == '-') || (c == '.') || (c == 0xB7) || /* !start */
3322	        ((c >= 0xC0) && (c <= 0xD6)) ||
3323	        ((c >= 0xD8) && (c <= 0xF6)) ||
3324	        ((c >= 0xF8) && (c <= 0x2FF)) ||
3325	        ((c >= 0x300) && (c <= 0x36F)) || /* !start */
3326	        ((c >= 0x370) && (c <= 0x37D)) ||
3327	        ((c >= 0x37F) && (c <= 0x1FFF)) ||
3328	        ((c >= 0x200C) && (c <= 0x200D)) ||
3329	        ((c >= 0x203F) && (c <= 0x2040)) || /* !start */
3330	        ((c >= 0x2070) && (c <= 0x218F)) ||
3331	        ((c >= 0x2C00) && (c <= 0x2FEF)) ||
3332	        ((c >= 0x3001) && (c <= 0xD7FF)) ||
3333	        ((c >= 0xF900) && (c <= 0xFDCF)) ||
3334	        ((c >= 0xFDF0) && (c <= 0xFFFD)) ||
3335	        ((c >= 0x10000) && (c <= 0xEFFFF))
3336		)) {
3337	    if (count++ > XML_PARSER_CHUNK_SIZE) {
3338		count = 0;
3339		GROW;
3340                if (ctxt->instate == XML_PARSER_EOF)
3341                    return(NULL);
3342	    }
3343	    len += l;
3344	    NEXTL(l);
3345	    c = CUR_CHAR(l);
3346	}
3347    } else {
3348	if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3349	    (!IS_LETTER(c) && (c != '_') &&
3350	     (c != ':'))) {
3351	    return(NULL);
3352	}
3353	len += l;
3354	NEXTL(l);
3355	c = CUR_CHAR(l);
3356
3357	while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3358	       ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
3359		(c == '.') || (c == '-') ||
3360		(c == '_') || (c == ':') ||
3361		(IS_COMBINING(c)) ||
3362		(IS_EXTENDER(c)))) {
3363	    if (count++ > XML_PARSER_CHUNK_SIZE) {
3364		count = 0;
3365		GROW;
3366                if (ctxt->instate == XML_PARSER_EOF)
3367                    return(NULL);
3368	    }
3369	    len += l;
3370	    NEXTL(l);
3371	    c = CUR_CHAR(l);
3372	    if (c == 0) {
3373		count = 0;
3374		GROW;
3375                if (ctxt->instate == XML_PARSER_EOF)
3376                    return(NULL);
3377		c = CUR_CHAR(l);
3378	    }
3379	}
3380    }
3381    if ((len > XML_MAX_NAME_LENGTH) &&
3382        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3383        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3384        return(NULL);
3385    }
3386    if ((*ctxt->input->cur == '\n') && (ctxt->input->cur[-1] == '\r'))
3387        return(xmlDictLookup(ctxt->dict, ctxt->input->cur - (len + 1), len));
3388    return(xmlDictLookup(ctxt->dict, ctxt->input->cur - len, len));
3389}
3390
3391/**
3392 * xmlParseName:
3393 * @ctxt:  an XML parser context
3394 *
3395 * parse an XML name.
3396 *
3397 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3398 *                  CombiningChar | Extender
3399 *
3400 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3401 *
3402 * [6] Names ::= Name (#x20 Name)*
3403 *
3404 * Returns the Name parsed or NULL
3405 */
3406
3407const xmlChar *
3408xmlParseName(xmlParserCtxtPtr ctxt) {
3409    const xmlChar *in;
3410    const xmlChar *ret;
3411    int count = 0;
3412
3413    GROW;
3414
3415#ifdef DEBUG
3416    nbParseName++;
3417#endif
3418
3419    /*
3420     * Accelerator for simple ASCII names
3421     */
3422    in = ctxt->input->cur;
3423    if (((*in >= 0x61) && (*in <= 0x7A)) ||
3424	((*in >= 0x41) && (*in <= 0x5A)) ||
3425	(*in == '_') || (*in == ':')) {
3426	in++;
3427	while (((*in >= 0x61) && (*in <= 0x7A)) ||
3428	       ((*in >= 0x41) && (*in <= 0x5A)) ||
3429	       ((*in >= 0x30) && (*in <= 0x39)) ||
3430	       (*in == '_') || (*in == '-') ||
3431	       (*in == ':') || (*in == '.'))
3432	    in++;
3433	if ((*in > 0) && (*in < 0x80)) {
3434	    count = in - ctxt->input->cur;
3435            if ((count > XML_MAX_NAME_LENGTH) &&
3436                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3437                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Name");
3438                return(NULL);
3439            }
3440	    ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3441	    ctxt->input->cur = in;
3442	    ctxt->nbChars += count;
3443	    ctxt->input->col += count;
3444	    if (ret == NULL)
3445	        xmlErrMemory(ctxt, NULL);
3446	    return(ret);
3447	}
3448    }
3449    /* accelerator for special cases */
3450    return(xmlParseNameComplex(ctxt));
3451}
3452
3453static const xmlChar *
3454xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) {
3455    int len = 0, l;
3456    int c;
3457    int count = 0;
3458    const xmlChar *end; /* needed because CUR_CHAR() can move cur on \r\n */
3459
3460#ifdef DEBUG
3461    nbParseNCNameComplex++;
3462#endif
3463
3464    /*
3465     * Handler for more complex cases
3466     */
3467    GROW;
3468    end = ctxt->input->cur;
3469    c = CUR_CHAR(l);
3470    if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
3471	(!xmlIsNameStartChar(ctxt, c) || (c == ':'))) {
3472	return(NULL);
3473    }
3474
3475    while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
3476	   (xmlIsNameChar(ctxt, c) && (c != ':'))) {
3477	if (count++ > XML_PARSER_CHUNK_SIZE) {
3478            if ((len > XML_MAX_NAME_LENGTH) &&
3479                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3480                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3481                return(NULL);
3482            }
3483	    count = 0;
3484	    GROW;
3485            if (ctxt->instate == XML_PARSER_EOF)
3486                return(NULL);
3487	}
3488	len += l;
3489	NEXTL(l);
3490	end = ctxt->input->cur;
3491	c = CUR_CHAR(l);
3492	if (c == 0) {
3493	    count = 0;
3494	    GROW;
3495            if (ctxt->instate == XML_PARSER_EOF)
3496                return(NULL);
3497	    end = ctxt->input->cur;
3498	    c = CUR_CHAR(l);
3499	}
3500    }
3501    if ((len > XML_MAX_NAME_LENGTH) &&
3502        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3503        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3504        return(NULL);
3505    }
3506    return(xmlDictLookup(ctxt->dict, end - len, len));
3507}
3508
3509/**
3510 * xmlParseNCName:
3511 * @ctxt:  an XML parser context
3512 * @len:  length of the string parsed
3513 *
3514 * parse an XML name.
3515 *
3516 * [4NS] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
3517 *                      CombiningChar | Extender
3518 *
3519 * [5NS] NCName ::= (Letter | '_') (NCNameChar)*
3520 *
3521 * Returns the Name parsed or NULL
3522 */
3523
3524static const xmlChar *
3525xmlParseNCName(xmlParserCtxtPtr ctxt) {
3526    const xmlChar *in;
3527    const xmlChar *ret;
3528    int count = 0;
3529
3530#ifdef DEBUG
3531    nbParseNCName++;
3532#endif
3533
3534    /*
3535     * Accelerator for simple ASCII names
3536     */
3537    in = ctxt->input->cur;
3538    if (((*in >= 0x61) && (*in <= 0x7A)) ||
3539	((*in >= 0x41) && (*in <= 0x5A)) ||
3540	(*in == '_')) {
3541	in++;
3542	while (((*in >= 0x61) && (*in <= 0x7A)) ||
3543	       ((*in >= 0x41) && (*in <= 0x5A)) ||
3544	       ((*in >= 0x30) && (*in <= 0x39)) ||
3545	       (*in == '_') || (*in == '-') ||
3546	       (*in == '.'))
3547	    in++;
3548	if ((*in > 0) && (*in < 0x80)) {
3549	    count = in - ctxt->input->cur;
3550            if ((count > XML_MAX_NAME_LENGTH) &&
3551                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3552                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3553                return(NULL);
3554            }
3555	    ret = xmlDictLookup(ctxt->dict, ctxt->input->cur, count);
3556	    ctxt->input->cur = in;
3557	    ctxt->nbChars += count;
3558	    ctxt->input->col += count;
3559	    if (ret == NULL) {
3560	        xmlErrMemory(ctxt, NULL);
3561	    }
3562	    return(ret);
3563	}
3564    }
3565    return(xmlParseNCNameComplex(ctxt));
3566}
3567
3568/**
3569 * xmlParseNameAndCompare:
3570 * @ctxt:  an XML parser context
3571 *
3572 * parse an XML name and compares for match
3573 * (specialized for endtag parsing)
3574 *
3575 * Returns NULL for an illegal name, (xmlChar*) 1 for success
3576 * and the name for mismatch
3577 */
3578
3579static const xmlChar *
3580xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
3581    register const xmlChar *cmp = other;
3582    register const xmlChar *in;
3583    const xmlChar *ret;
3584
3585    GROW;
3586    if (ctxt->instate == XML_PARSER_EOF)
3587        return(NULL);
3588
3589    in = ctxt->input->cur;
3590    while (*in != 0 && *in == *cmp) {
3591	++in;
3592	++cmp;
3593	ctxt->input->col++;
3594    }
3595    if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
3596	/* success */
3597	ctxt->input->cur = in;
3598	return (const xmlChar*) 1;
3599    }
3600    /* failure (or end of input buffer), check with full function */
3601    ret = xmlParseName (ctxt);
3602    /* strings coming from the dictionnary direct compare possible */
3603    if (ret == other) {
3604	return (const xmlChar*) 1;
3605    }
3606    return ret;
3607}
3608
3609/**
3610 * xmlParseStringName:
3611 * @ctxt:  an XML parser context
3612 * @str:  a pointer to the string pointer (IN/OUT)
3613 *
3614 * parse an XML name.
3615 *
3616 * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
3617 *                  CombiningChar | Extender
3618 *
3619 * [5] Name ::= (Letter | '_' | ':') (NameChar)*
3620 *
3621 * [6] Names ::= Name (#x20 Name)*
3622 *
3623 * Returns the Name parsed or NULL. The @str pointer
3624 * is updated to the current location in the string.
3625 */
3626
3627static xmlChar *
3628xmlParseStringName(xmlParserCtxtPtr ctxt, const xmlChar** str) {
3629    xmlChar buf[XML_MAX_NAMELEN + 5];
3630    const xmlChar *cur = *str;
3631    int len = 0, l;
3632    int c;
3633
3634#ifdef DEBUG
3635    nbParseStringName++;
3636#endif
3637
3638    c = CUR_SCHAR(cur, l);
3639    if (!xmlIsNameStartChar(ctxt, c)) {
3640	return(NULL);
3641    }
3642
3643    COPY_BUF(l,buf,len,c);
3644    cur += l;
3645    c = CUR_SCHAR(cur, l);
3646    while (xmlIsNameChar(ctxt, c)) {
3647	COPY_BUF(l,buf,len,c);
3648	cur += l;
3649	c = CUR_SCHAR(cur, l);
3650	if (len >= XML_MAX_NAMELEN) { /* test bigentname.xml */
3651	    /*
3652	     * Okay someone managed to make a huge name, so he's ready to pay
3653	     * for the processing speed.
3654	     */
3655	    xmlChar *buffer;
3656	    int max = len * 2;
3657
3658	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
3659	    if (buffer == NULL) {
3660	        xmlErrMemory(ctxt, NULL);
3661		return(NULL);
3662	    }
3663	    memcpy(buffer, buf, len);
3664	    while (xmlIsNameChar(ctxt, c)) {
3665		if (len + 10 > max) {
3666		    xmlChar *tmp;
3667
3668                    if ((len > XML_MAX_NAME_LENGTH) &&
3669                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3670                        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3671			xmlFree(buffer);
3672                        return(NULL);
3673                    }
3674		    max *= 2;
3675		    tmp = (xmlChar *) xmlRealloc(buffer,
3676			                            max * sizeof(xmlChar));
3677		    if (tmp == NULL) {
3678			xmlErrMemory(ctxt, NULL);
3679			xmlFree(buffer);
3680			return(NULL);
3681		    }
3682		    buffer = tmp;
3683		}
3684		COPY_BUF(l,buffer,len,c);
3685		cur += l;
3686		c = CUR_SCHAR(cur, l);
3687	    }
3688	    buffer[len] = 0;
3689	    *str = cur;
3690	    return(buffer);
3691	}
3692    }
3693    if ((len > XML_MAX_NAME_LENGTH) &&
3694        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3695        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName");
3696        return(NULL);
3697    }
3698    *str = cur;
3699    return(xmlStrndup(buf, len));
3700}
3701
3702/**
3703 * xmlParseNmtoken:
3704 * @ctxt:  an XML parser context
3705 *
3706 * parse an XML Nmtoken.
3707 *
3708 * [7] Nmtoken ::= (NameChar)+
3709 *
3710 * [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
3711 *
3712 * Returns the Nmtoken parsed or NULL
3713 */
3714
3715xmlChar *
3716xmlParseNmtoken(xmlParserCtxtPtr ctxt) {
3717    xmlChar buf[XML_MAX_NAMELEN + 5];
3718    int len = 0, l;
3719    int c;
3720    int count = 0;
3721
3722#ifdef DEBUG
3723    nbParseNmToken++;
3724#endif
3725
3726    GROW;
3727    if (ctxt->instate == XML_PARSER_EOF)
3728        return(NULL);
3729    c = CUR_CHAR(l);
3730
3731    while (xmlIsNameChar(ctxt, c)) {
3732	if (count++ > XML_PARSER_CHUNK_SIZE) {
3733	    count = 0;
3734	    GROW;
3735	}
3736	COPY_BUF(l,buf,len,c);
3737	NEXTL(l);
3738	c = CUR_CHAR(l);
3739	if (c == 0) {
3740	    count = 0;
3741	    GROW;
3742	    if (ctxt->instate == XML_PARSER_EOF)
3743		return(NULL);
3744            c = CUR_CHAR(l);
3745	}
3746	if (len >= XML_MAX_NAMELEN) {
3747	    /*
3748	     * Okay someone managed to make a huge token, so he's ready to pay
3749	     * for the processing speed.
3750	     */
3751	    xmlChar *buffer;
3752	    int max = len * 2;
3753
3754	    buffer = (xmlChar *) xmlMallocAtomic(max * sizeof(xmlChar));
3755	    if (buffer == NULL) {
3756	        xmlErrMemory(ctxt, NULL);
3757		return(NULL);
3758	    }
3759	    memcpy(buffer, buf, len);
3760	    while (xmlIsNameChar(ctxt, c)) {
3761		if (count++ > XML_PARSER_CHUNK_SIZE) {
3762		    count = 0;
3763		    GROW;
3764                    if (ctxt->instate == XML_PARSER_EOF) {
3765                        xmlFree(buffer);
3766                        return(NULL);
3767                    }
3768		}
3769		if (len + 10 > max) {
3770		    xmlChar *tmp;
3771
3772                    if ((max > XML_MAX_NAME_LENGTH) &&
3773                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3774                        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3775                        xmlFree(buffer);
3776                        return(NULL);
3777                    }
3778		    max *= 2;
3779		    tmp = (xmlChar *) xmlRealloc(buffer,
3780			                            max * sizeof(xmlChar));
3781		    if (tmp == NULL) {
3782			xmlErrMemory(ctxt, NULL);
3783			xmlFree(buffer);
3784			return(NULL);
3785		    }
3786		    buffer = tmp;
3787		}
3788		COPY_BUF(l,buffer,len,c);
3789		NEXTL(l);
3790		c = CUR_CHAR(l);
3791	    }
3792	    buffer[len] = 0;
3793	    return(buffer);
3794	}
3795    }
3796    if (len == 0)
3797        return(NULL);
3798    if ((len > XML_MAX_NAME_LENGTH) &&
3799        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
3800        xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NmToken");
3801        return(NULL);
3802    }
3803    return(xmlStrndup(buf, len));
3804}
3805
3806/**
3807 * xmlParseEntityValue:
3808 * @ctxt:  an XML parser context
3809 * @orig:  if non-NULL store a copy of the original entity value
3810 *
3811 * parse a value for ENTITY declarations
3812 *
3813 * [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' |
3814 *	               "'" ([^%&'] | PEReference | Reference)* "'"
3815 *
3816 * Returns the EntityValue parsed with reference substituted or NULL
3817 */
3818
3819xmlChar *
3820xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
3821    xmlChar *buf = NULL;
3822    int len = 0;
3823    int size = XML_PARSER_BUFFER_SIZE;
3824    int c, l;
3825    xmlChar stop;
3826    xmlChar *ret = NULL;
3827    const xmlChar *cur = NULL;
3828    xmlParserInputPtr input;
3829
3830    if (RAW == '"') stop = '"';
3831    else if (RAW == '\'') stop = '\'';
3832    else {
3833	xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_STARTED, NULL);
3834	return(NULL);
3835    }
3836    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
3837    if (buf == NULL) {
3838	xmlErrMemory(ctxt, NULL);
3839	return(NULL);
3840    }
3841
3842    /*
3843     * The content of the entity definition is copied in a buffer.
3844     */
3845
3846    ctxt->instate = XML_PARSER_ENTITY_VALUE;
3847    input = ctxt->input;
3848    GROW;
3849    if (ctxt->instate == XML_PARSER_EOF) {
3850        xmlFree(buf);
3851        return(NULL);
3852    }
3853    NEXT;
3854    c = CUR_CHAR(l);
3855    /*
3856     * NOTE: 4.4.5 Included in Literal
3857     * When a parameter entity reference appears in a literal entity
3858     * value, ... a single or double quote character in the replacement
3859     * text is always treated as a normal data character and will not
3860     * terminate the literal.
3861     * In practice it means we stop the loop only when back at parsing
3862     * the initial entity and the quote is found
3863     */
3864    while (((IS_CHAR(c)) && ((c != stop) || /* checked */
3865	    (ctxt->input != input))) && (ctxt->instate != XML_PARSER_EOF)) {
3866	if (len + 5 >= size) {
3867	    xmlChar *tmp;
3868
3869	    size *= 2;
3870	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
3871	    if (tmp == NULL) {
3872		xmlErrMemory(ctxt, NULL);
3873		xmlFree(buf);
3874		return(NULL);
3875	    }
3876	    buf = tmp;
3877	}
3878	COPY_BUF(l,buf,len,c);
3879	NEXTL(l);
3880	/*
3881	 * Pop-up of finished entities.
3882	 */
3883	while ((RAW == 0) && (ctxt->inputNr > 1)) /* non input consuming */
3884	    xmlPopInput(ctxt);
3885
3886	GROW;
3887	c = CUR_CHAR(l);
3888	if (c == 0) {
3889	    GROW;
3890	    c = CUR_CHAR(l);
3891	}
3892    }
3893    buf[len] = 0;
3894    if (ctxt->instate == XML_PARSER_EOF) {
3895        xmlFree(buf);
3896        return(NULL);
3897    }
3898
3899    /*
3900     * Raise problem w.r.t. '&' and '%' being used in non-entities
3901     * reference constructs. Note Charref will be handled in
3902     * xmlStringDecodeEntities()
3903     */
3904    cur = buf;
3905    while (*cur != 0) { /* non input consuming */
3906	if ((*cur == '%') || ((*cur == '&') && (cur[1] != '#'))) {
3907	    xmlChar *name;
3908	    xmlChar tmp = *cur;
3909
3910	    cur++;
3911	    name = xmlParseStringName(ctxt, &cur);
3912            if ((name == NULL) || (*cur != ';')) {
3913		xmlFatalErrMsgInt(ctxt, XML_ERR_ENTITY_CHAR_ERROR,
3914	    "EntityValue: '%c' forbidden except for entities references\n",
3915	                          tmp);
3916	    }
3917	    if ((tmp == '%') && (ctxt->inSubset == 1) &&
3918		(ctxt->inputNr == 1)) {
3919		xmlFatalErr(ctxt, XML_ERR_ENTITY_PE_INTERNAL, NULL);
3920	    }
3921	    if (name != NULL)
3922		xmlFree(name);
3923	    if (*cur == 0)
3924	        break;
3925	}
3926	cur++;
3927    }
3928
3929    /*
3930     * Then PEReference entities are substituted.
3931     */
3932    if (c != stop) {
3933	xmlFatalErr(ctxt, XML_ERR_ENTITY_NOT_FINISHED, NULL);
3934	xmlFree(buf);
3935    } else {
3936	NEXT;
3937	/*
3938	 * NOTE: 4.4.7 Bypassed
3939	 * When a general entity reference appears in the EntityValue in
3940	 * an entity declaration, it is bypassed and left as is.
3941	 * so XML_SUBSTITUTE_REF is not set here.
3942	 */
3943	ret = xmlStringDecodeEntities(ctxt, buf, XML_SUBSTITUTE_PEREF,
3944				      0, 0, 0);
3945	if (orig != NULL)
3946	    *orig = buf;
3947	else
3948	    xmlFree(buf);
3949    }
3950
3951    return(ret);
3952}
3953
3954/**
3955 * xmlParseAttValueComplex:
3956 * @ctxt:  an XML parser context
3957 * @len:   the resulting attribute len
3958 * @normalize:  wether to apply the inner normalization
3959 *
3960 * parse a value for an attribute, this is the fallback function
3961 * of xmlParseAttValue() when the attribute parsing requires handling
3962 * of non-ASCII characters, or normalization compaction.
3963 *
3964 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
3965 */
3966static xmlChar *
3967xmlParseAttValueComplex(xmlParserCtxtPtr ctxt, int *attlen, int normalize) {
3968    xmlChar limit = 0;
3969    xmlChar *buf = NULL;
3970    xmlChar *rep = NULL;
3971    size_t len = 0;
3972    size_t buf_size = 0;
3973    int c, l, in_space = 0;
3974    xmlChar *current = NULL;
3975    xmlEntityPtr ent;
3976
3977    if (NXT(0) == '"') {
3978	ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
3979	limit = '"';
3980        NEXT;
3981    } else if (NXT(0) == '\'') {
3982	limit = '\'';
3983	ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
3984        NEXT;
3985    } else {
3986	xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
3987	return(NULL);
3988    }
3989
3990    /*
3991     * allocate a translation buffer.
3992     */
3993    buf_size = XML_PARSER_BUFFER_SIZE;
3994    buf = (xmlChar *) xmlMallocAtomic(buf_size);
3995    if (buf == NULL) goto mem_error;
3996
3997    /*
3998     * OK loop until we reach one of the ending char or a size limit.
3999     */
4000    c = CUR_CHAR(l);
4001    while (((NXT(0) != limit) && /* checked */
4002            (IS_CHAR(c)) && (c != '<')) &&
4003            (ctxt->instate != XML_PARSER_EOF)) {
4004        /*
4005         * Impose a reasonable limit on attribute size, unless XML_PARSE_HUGE
4006         * special option is given
4007         */
4008        if ((len > XML_MAX_TEXT_LENGTH) &&
4009            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
4010            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4011                           "AttValue length too long\n");
4012            goto mem_error;
4013        }
4014	if (c == 0) break;
4015	if (c == '&') {
4016	    in_space = 0;
4017	    if (NXT(1) == '#') {
4018		int val = xmlParseCharRef(ctxt);
4019
4020		if (val == '&') {
4021		    if (ctxt->replaceEntities) {
4022			if (len + 10 > buf_size) {
4023			    growBuffer(buf, 10);
4024			}
4025			buf[len++] = '&';
4026		    } else {
4027			/*
4028			 * The reparsing will be done in xmlStringGetNodeList()
4029			 * called by the attribute() function in SAX.c
4030			 */
4031			if (len + 10 > buf_size) {
4032			    growBuffer(buf, 10);
4033			}
4034			buf[len++] = '&';
4035			buf[len++] = '#';
4036			buf[len++] = '3';
4037			buf[len++] = '8';
4038			buf[len++] = ';';
4039		    }
4040		} else if (val != 0) {
4041		    if (len + 10 > buf_size) {
4042			growBuffer(buf, 10);
4043		    }
4044		    len += xmlCopyChar(0, &buf[len], val);
4045		}
4046	    } else {
4047		ent = xmlParseEntityRef(ctxt);
4048		ctxt->nbentities++;
4049		if (ent != NULL)
4050		    ctxt->nbentities += ent->owner;
4051		if ((ent != NULL) &&
4052		    (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
4053		    if (len + 10 > buf_size) {
4054			growBuffer(buf, 10);
4055		    }
4056		    if ((ctxt->replaceEntities == 0) &&
4057		        (ent->content[0] == '&')) {
4058			buf[len++] = '&';
4059			buf[len++] = '#';
4060			buf[len++] = '3';
4061			buf[len++] = '8';
4062			buf[len++] = ';';
4063		    } else {
4064			buf[len++] = ent->content[0];
4065		    }
4066		} else if ((ent != NULL) &&
4067		           (ctxt->replaceEntities != 0)) {
4068		    if (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) {
4069			rep = xmlStringDecodeEntities(ctxt, ent->content,
4070						      XML_SUBSTITUTE_REF,
4071						      0, 0, 0);
4072			if (rep != NULL) {
4073			    current = rep;
4074			    while (*current != 0) { /* non input consuming */
4075                                if ((*current == 0xD) || (*current == 0xA) ||
4076                                    (*current == 0x9)) {
4077                                    buf[len++] = 0x20;
4078                                    current++;
4079                                } else
4080                                    buf[len++] = *current++;
4081				if (len + 10 > buf_size) {
4082				    growBuffer(buf, 10);
4083				}
4084			    }
4085			    xmlFree(rep);
4086			    rep = NULL;
4087			}
4088		    } else {
4089			if (len + 10 > buf_size) {
4090			    growBuffer(buf, 10);
4091			}
4092			if (ent->content != NULL)
4093			    buf[len++] = ent->content[0];
4094		    }
4095		} else if (ent != NULL) {
4096		    int i = xmlStrlen(ent->name);
4097		    const xmlChar *cur = ent->name;
4098
4099		    /*
4100		     * This may look absurd but is needed to detect
4101		     * entities problems
4102		     */
4103		    if ((ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
4104			(ent->content != NULL) && (ent->checked == 0)) {
4105			unsigned long oldnbent = ctxt->nbentities;
4106
4107			rep = xmlStringDecodeEntities(ctxt, ent->content,
4108						  XML_SUBSTITUTE_REF, 0, 0, 0);
4109
4110			ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
4111			if (rep != NULL) {
4112			    if (xmlStrchr(rep, '<'))
4113			        ent->checked |= 1;
4114			    xmlFree(rep);
4115			    rep = NULL;
4116			}
4117		    }
4118
4119		    /*
4120		     * Just output the reference
4121		     */
4122		    buf[len++] = '&';
4123		    while (len + i + 10 > buf_size) {
4124			growBuffer(buf, i + 10);
4125		    }
4126		    for (;i > 0;i--)
4127			buf[len++] = *cur++;
4128		    buf[len++] = ';';
4129		}
4130	    }
4131	} else {
4132	    if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
4133	        if ((len != 0) || (!normalize)) {
4134		    if ((!normalize) || (!in_space)) {
4135			COPY_BUF(l,buf,len,0x20);
4136			while (len + 10 > buf_size) {
4137			    growBuffer(buf, 10);
4138			}
4139		    }
4140		    in_space = 1;
4141		}
4142	    } else {
4143	        in_space = 0;
4144		COPY_BUF(l,buf,len,c);
4145		if (len + 10 > buf_size) {
4146		    growBuffer(buf, 10);
4147		}
4148	    }
4149	    NEXTL(l);
4150	}
4151	GROW;
4152	c = CUR_CHAR(l);
4153    }
4154    if (ctxt->instate == XML_PARSER_EOF)
4155        goto error;
4156
4157    if ((in_space) && (normalize)) {
4158        while ((len > 0) && (buf[len - 1] == 0x20)) len--;
4159    }
4160    buf[len] = 0;
4161    if (RAW == '<') {
4162	xmlFatalErr(ctxt, XML_ERR_LT_IN_ATTRIBUTE, NULL);
4163    } else if (RAW != limit) {
4164	if ((c != 0) && (!IS_CHAR(c))) {
4165	    xmlFatalErrMsg(ctxt, XML_ERR_INVALID_CHAR,
4166			   "invalid character in attribute value\n");
4167	} else {
4168	    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4169			   "AttValue: ' expected\n");
4170        }
4171    } else
4172	NEXT;
4173
4174    /*
4175     * There we potentially risk an overflow, don't allow attribute value of
4176     * length more than INT_MAX it is a very reasonnable assumption !
4177     */
4178    if (len >= INT_MAX) {
4179        xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
4180                       "AttValue length too long\n");
4181        goto mem_error;
4182    }
4183
4184    if (attlen != NULL) *attlen = (int) len;
4185    return(buf);
4186
4187mem_error:
4188    xmlErrMemory(ctxt, NULL);
4189error:
4190    if (buf != NULL)
4191        xmlFree(buf);
4192    if (rep != NULL)
4193        xmlFree(rep);
4194    return(NULL);
4195}
4196
4197/**
4198 * xmlParseAttValue:
4199 * @ctxt:  an XML parser context
4200 *
4201 * parse a value for an attribute
4202 * Note: the parser won't do substitution of entities here, this
4203 * will be handled later in xmlStringGetNodeList
4204 *
4205 * [10] AttValue ::= '"' ([^<&"] | Reference)* '"' |
4206 *                   "'" ([^<&'] | Reference)* "'"
4207 *
4208 * 3.3.3 Attribute-Value Normalization:
4209 * Before the value of an attribute is passed to the application or
4210 * checked for validity, the XML processor must normalize it as follows:
4211 * - a character reference is processed by appending the referenced
4212 *   character to the attribute value
4213 * - an entity reference is processed by recursively processing the
4214 *   replacement text of the entity
4215 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
4216 *   appending #x20 to the normalized value, except that only a single
4217 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
4218 *   parsed entity or the literal entity value of an internal parsed entity
4219 * - other characters are processed by appending them to the normalized value
4220 * If the declared value is not CDATA, then the XML processor must further
4221 * process the normalized attribute value by discarding any leading and
4222 * trailing space (#x20) characters, and by replacing sequences of space
4223 * (#x20) characters by a single space (#x20) character.
4224 * All attributes for which no declaration has been read should be treated
4225 * by a non-validating parser as if declared CDATA.
4226 *
4227 * Returns the AttValue parsed or NULL. The value has to be freed by the caller.
4228 */
4229
4230
4231xmlChar *
4232xmlParseAttValue(xmlParserCtxtPtr ctxt) {
4233    if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL);
4234    return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0));
4235}
4236
4237/**
4238 * xmlParseSystemLiteral:
4239 * @ctxt:  an XML parser context
4240 *
4241 * parse an XML Literal
4242 *
4243 * [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
4244 *
4245 * Returns the SystemLiteral parsed or NULL
4246 */
4247
4248xmlChar *
4249xmlParseSystemLiteral(xmlParserCtxtPtr ctxt) {
4250    xmlChar *buf = NULL;
4251    int len = 0;
4252    int size = XML_PARSER_BUFFER_SIZE;
4253    int cur, l;
4254    xmlChar stop;
4255    int state = ctxt->instate;
4256    int count = 0;
4257
4258    SHRINK;
4259    if (RAW == '"') {
4260        NEXT;
4261	stop = '"';
4262    } else if (RAW == '\'') {
4263        NEXT;
4264	stop = '\'';
4265    } else {
4266	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4267	return(NULL);
4268    }
4269
4270    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
4271    if (buf == NULL) {
4272        xmlErrMemory(ctxt, NULL);
4273	return(NULL);
4274    }
4275    ctxt->instate = XML_PARSER_SYSTEM_LITERAL;
4276    cur = CUR_CHAR(l);
4277    while ((IS_CHAR(cur)) && (cur != stop)) { /* checked */
4278	if (len + 5 >= size) {
4279	    xmlChar *tmp;
4280
4281            if ((size > XML_MAX_NAME_LENGTH) &&
4282                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
4283                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "SystemLiteral");
4284                xmlFree(buf);
4285		ctxt->instate = (xmlParserInputState) state;
4286                return(NULL);
4287            }
4288	    size *= 2;
4289	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
4290	    if (tmp == NULL) {
4291	        xmlFree(buf);
4292		xmlErrMemory(ctxt, NULL);
4293		ctxt->instate = (xmlParserInputState) state;
4294		return(NULL);
4295	    }
4296	    buf = tmp;
4297	}
4298	count++;
4299	if (count > 50) {
4300	    GROW;
4301	    count = 0;
4302            if (ctxt->instate == XML_PARSER_EOF) {
4303	        xmlFree(buf);
4304		return(NULL);
4305            }
4306	}
4307	COPY_BUF(l,buf,len,cur);
4308	NEXTL(l);
4309	cur = CUR_CHAR(l);
4310	if (cur == 0) {
4311	    GROW;
4312	    SHRINK;
4313	    cur = CUR_CHAR(l);
4314	}
4315    }
4316    buf[len] = 0;
4317    ctxt->instate = (xmlParserInputState) state;
4318    if (!IS_CHAR(cur)) {
4319	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4320    } else {
4321	NEXT;
4322    }
4323    return(buf);
4324}
4325
4326/**
4327 * xmlParsePubidLiteral:
4328 * @ctxt:  an XML parser context
4329 *
4330 * parse an XML public literal
4331 *
4332 * [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
4333 *
4334 * Returns the PubidLiteral parsed or NULL.
4335 */
4336
4337xmlChar *
4338xmlParsePubidLiteral(xmlParserCtxtPtr ctxt) {
4339    xmlChar *buf = NULL;
4340    int len = 0;
4341    int size = XML_PARSER_BUFFER_SIZE;
4342    xmlChar cur;
4343    xmlChar stop;
4344    int count = 0;
4345    xmlParserInputState oldstate = ctxt->instate;
4346
4347    SHRINK;
4348    if (RAW == '"') {
4349        NEXT;
4350	stop = '"';
4351    } else if (RAW == '\'') {
4352        NEXT;
4353	stop = '\'';
4354    } else {
4355	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_STARTED, NULL);
4356	return(NULL);
4357    }
4358    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
4359    if (buf == NULL) {
4360	xmlErrMemory(ctxt, NULL);
4361	return(NULL);
4362    }
4363    ctxt->instate = XML_PARSER_PUBLIC_LITERAL;
4364    cur = CUR;
4365    while ((IS_PUBIDCHAR_CH(cur)) && (cur != stop)) { /* checked */
4366	if (len + 1 >= size) {
4367	    xmlChar *tmp;
4368
4369            if ((size > XML_MAX_NAME_LENGTH) &&
4370                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
4371                xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "Public ID");
4372                xmlFree(buf);
4373                return(NULL);
4374            }
4375	    size *= 2;
4376	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
4377	    if (tmp == NULL) {
4378		xmlErrMemory(ctxt, NULL);
4379		xmlFree(buf);
4380		return(NULL);
4381	    }
4382	    buf = tmp;
4383	}
4384	buf[len++] = cur;
4385	count++;
4386	if (count > 50) {
4387	    GROW;
4388	    count = 0;
4389            if (ctxt->instate == XML_PARSER_EOF) {
4390		xmlFree(buf);
4391		return(NULL);
4392            }
4393	}
4394	NEXT;
4395	cur = CUR;
4396	if (cur == 0) {
4397	    GROW;
4398	    SHRINK;
4399	    cur = CUR;
4400	}
4401    }
4402    buf[len] = 0;
4403    if (cur != stop) {
4404	xmlFatalErr(ctxt, XML_ERR_LITERAL_NOT_FINISHED, NULL);
4405    } else {
4406	NEXT;
4407    }
4408    ctxt->instate = oldstate;
4409    return(buf);
4410}
4411
4412static void xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata);
4413
4414/*
4415 * used for the test in the inner loop of the char data testing
4416 */
4417static const unsigned char test_char_data[256] = {
4418    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4419    0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9, CR/LF separated */
4420    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4421    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4422    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x00, 0x27, /* & */
4423    0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
4424    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
4425    0x38, 0x39, 0x3A, 0x3B, 0x00, 0x3D, 0x3E, 0x3F, /* < */
4426    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
4427    0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
4428    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
4429    0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x00, 0x5E, 0x5F, /* ] */
4430    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
4431    0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
4432    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
4433    0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
4434    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* non-ascii */
4435    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4436    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4437    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4438    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4439    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4440    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4441    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4442    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4443    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4444    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4445    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4446    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4447    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4448    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4449    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4450};
4451
4452/**
4453 * xmlParseCharData:
4454 * @ctxt:  an XML parser context
4455 * @cdata:  int indicating whether we are within a CDATA section
4456 *
4457 * parse a CharData section.
4458 * if we are within a CDATA section ']]>' marks an end of section.
4459 *
4460 * The right angle bracket (>) may be represented using the string "&gt;",
4461 * and must, for compatibility, be escaped using "&gt;" or a character
4462 * reference when it appears in the string "]]>" in content, when that
4463 * string is not marking the end of a CDATA section.
4464 *
4465 * [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
4466 */
4467
4468void
4469xmlParseCharData(xmlParserCtxtPtr ctxt, int cdata) {
4470    const xmlChar *in;
4471    int nbchar = 0;
4472    int line = ctxt->input->line;
4473    int col = ctxt->input->col;
4474    int ccol;
4475
4476    SHRINK;
4477    GROW;
4478    /*
4479     * Accelerated common case where input don't need to be
4480     * modified before passing it to the handler.
4481     */
4482    if (!cdata) {
4483	in = ctxt->input->cur;
4484	do {
4485get_more_space:
4486	    while (*in == 0x20) { in++; ctxt->input->col++; }
4487	    if (*in == 0xA) {
4488		do {
4489		    ctxt->input->line++; ctxt->input->col = 1;
4490		    in++;
4491		} while (*in == 0xA);
4492		goto get_more_space;
4493	    }
4494	    if (*in == '<') {
4495		nbchar = in - ctxt->input->cur;
4496		if (nbchar > 0) {
4497		    const xmlChar *tmp = ctxt->input->cur;
4498		    ctxt->input->cur = in;
4499
4500		    if ((ctxt->sax != NULL) &&
4501		        (ctxt->sax->ignorableWhitespace !=
4502		         ctxt->sax->characters)) {
4503			if (areBlanks(ctxt, tmp, nbchar, 1)) {
4504			    if (ctxt->sax->ignorableWhitespace != NULL)
4505				ctxt->sax->ignorableWhitespace(ctxt->userData,
4506						       tmp, nbchar);
4507			} else {
4508			    if (ctxt->sax->characters != NULL)
4509				ctxt->sax->characters(ctxt->userData,
4510						      tmp, nbchar);
4511			    if (*ctxt->space == -1)
4512			        *ctxt->space = -2;
4513			}
4514		    } else if ((ctxt->sax != NULL) &&
4515		               (ctxt->sax->characters != NULL)) {
4516			ctxt->sax->characters(ctxt->userData,
4517					      tmp, nbchar);
4518		    }
4519		}
4520		return;
4521	    }
4522
4523get_more:
4524            ccol = ctxt->input->col;
4525	    while (test_char_data[*in]) {
4526		in++;
4527		ccol++;
4528	    }
4529	    ctxt->input->col = ccol;
4530	    if (*in == 0xA) {
4531		do {
4532		    ctxt->input->line++; ctxt->input->col = 1;
4533		    in++;
4534		} while (*in == 0xA);
4535		goto get_more;
4536	    }
4537	    if (*in == ']') {
4538		if ((in[1] == ']') && (in[2] == '>')) {
4539		    xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4540		    ctxt->input->cur = in;
4541		    return;
4542		}
4543		in++;
4544		ctxt->input->col++;
4545		goto get_more;
4546	    }
4547	    nbchar = in - ctxt->input->cur;
4548	    if (nbchar > 0) {
4549		if ((ctxt->sax != NULL) &&
4550		    (ctxt->sax->ignorableWhitespace !=
4551		     ctxt->sax->characters) &&
4552		    (IS_BLANK_CH(*ctxt->input->cur))) {
4553		    const xmlChar *tmp = ctxt->input->cur;
4554		    ctxt->input->cur = in;
4555
4556		    if (areBlanks(ctxt, tmp, nbchar, 0)) {
4557		        if (ctxt->sax->ignorableWhitespace != NULL)
4558			    ctxt->sax->ignorableWhitespace(ctxt->userData,
4559							   tmp, nbchar);
4560		    } else {
4561		        if (ctxt->sax->characters != NULL)
4562			    ctxt->sax->characters(ctxt->userData,
4563						  tmp, nbchar);
4564			if (*ctxt->space == -1)
4565			    *ctxt->space = -2;
4566		    }
4567                    line = ctxt->input->line;
4568                    col = ctxt->input->col;
4569		} else if (ctxt->sax != NULL) {
4570		    if (ctxt->sax->characters != NULL)
4571			ctxt->sax->characters(ctxt->userData,
4572					      ctxt->input->cur, nbchar);
4573                    line = ctxt->input->line;
4574                    col = ctxt->input->col;
4575		}
4576                /* something really bad happened in the SAX callback */
4577                if (ctxt->instate != XML_PARSER_CONTENT)
4578                    return;
4579	    }
4580	    ctxt->input->cur = in;
4581	    if (*in == 0xD) {
4582		in++;
4583		if (*in == 0xA) {
4584		    ctxt->input->cur = in;
4585		    in++;
4586		    ctxt->input->line++; ctxt->input->col = 1;
4587		    continue; /* while */
4588		}
4589		in--;
4590	    }
4591	    if (*in == '<') {
4592		return;
4593	    }
4594	    if (*in == '&') {
4595		return;
4596	    }
4597	    SHRINK;
4598	    GROW;
4599            if (ctxt->instate == XML_PARSER_EOF)
4600		return;
4601	    in = ctxt->input->cur;
4602	} while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
4603	nbchar = 0;
4604    }
4605    ctxt->input->line = line;
4606    ctxt->input->col = col;
4607    xmlParseCharDataComplex(ctxt, cdata);
4608}
4609
4610/**
4611 * xmlParseCharDataComplex:
4612 * @ctxt:  an XML parser context
4613 * @cdata:  int indicating whether we are within a CDATA section
4614 *
4615 * parse a CharData section.this is the fallback function
4616 * of xmlParseCharData() when the parsing requires handling
4617 * of non-ASCII characters.
4618 */
4619static void
4620xmlParseCharDataComplex(xmlParserCtxtPtr ctxt, int cdata) {
4621    xmlChar buf[XML_PARSER_BIG_BUFFER_SIZE + 5];
4622    int nbchar = 0;
4623    int cur, l;
4624    int count = 0;
4625
4626    SHRINK;
4627    GROW;
4628    cur = CUR_CHAR(l);
4629    while ((cur != '<') && /* checked */
4630           (cur != '&') &&
4631	   (IS_CHAR(cur))) /* test also done in xmlCurrentChar() */ {
4632	if ((cur == ']') && (NXT(1) == ']') &&
4633	    (NXT(2) == '>')) {
4634	    if (cdata) break;
4635	    else {
4636		xmlFatalErr(ctxt, XML_ERR_MISPLACED_CDATA_END, NULL);
4637	    }
4638	}
4639	COPY_BUF(l,buf,nbchar,cur);
4640	if (nbchar >= XML_PARSER_BIG_BUFFER_SIZE) {
4641	    buf[nbchar] = 0;
4642
4643	    /*
4644	     * OK the segment is to be consumed as chars.
4645	     */
4646	    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4647		if (areBlanks(ctxt, buf, nbchar, 0)) {
4648		    if (ctxt->sax->ignorableWhitespace != NULL)
4649			ctxt->sax->ignorableWhitespace(ctxt->userData,
4650			                               buf, nbchar);
4651		} else {
4652		    if (ctxt->sax->characters != NULL)
4653			ctxt->sax->characters(ctxt->userData, buf, nbchar);
4654		    if ((ctxt->sax->characters !=
4655		         ctxt->sax->ignorableWhitespace) &&
4656			(*ctxt->space == -1))
4657			*ctxt->space = -2;
4658		}
4659	    }
4660	    nbchar = 0;
4661            /* something really bad happened in the SAX callback */
4662            if (ctxt->instate != XML_PARSER_CONTENT)
4663                return;
4664	}
4665	count++;
4666	if (count > 50) {
4667	    GROW;
4668	    count = 0;
4669            if (ctxt->instate == XML_PARSER_EOF)
4670		return;
4671	}
4672	NEXTL(l);
4673	cur = CUR_CHAR(l);
4674    }
4675    if (nbchar != 0) {
4676        buf[nbchar] = 0;
4677	/*
4678	 * OK the segment is to be consumed as chars.
4679	 */
4680	if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
4681	    if (areBlanks(ctxt, buf, nbchar, 0)) {
4682		if (ctxt->sax->ignorableWhitespace != NULL)
4683		    ctxt->sax->ignorableWhitespace(ctxt->userData, buf, nbchar);
4684	    } else {
4685		if (ctxt->sax->characters != NULL)
4686		    ctxt->sax->characters(ctxt->userData, buf, nbchar);
4687		if ((ctxt->sax->characters != ctxt->sax->ignorableWhitespace) &&
4688		    (*ctxt->space == -1))
4689		    *ctxt->space = -2;
4690	    }
4691	}
4692    }
4693    if ((cur != 0) && (!IS_CHAR(cur))) {
4694	/* Generate the error and skip the offending character */
4695        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4696                          "PCDATA invalid Char value %d\n",
4697	                  cur);
4698	NEXTL(l);
4699    }
4700}
4701
4702/**
4703 * xmlParseExternalID:
4704 * @ctxt:  an XML parser context
4705 * @publicID:  a xmlChar** receiving PubidLiteral
4706 * @strict: indicate whether we should restrict parsing to only
4707 *          production [75], see NOTE below
4708 *
4709 * Parse an External ID or a Public ID
4710 *
4711 * NOTE: Productions [75] and [83] interact badly since [75] can generate
4712 *       'PUBLIC' S PubidLiteral S SystemLiteral
4713 *
4714 * [75] ExternalID ::= 'SYSTEM' S SystemLiteral
4715 *                   | 'PUBLIC' S PubidLiteral S SystemLiteral
4716 *
4717 * [83] PublicID ::= 'PUBLIC' S PubidLiteral
4718 *
4719 * Returns the function returns SystemLiteral and in the second
4720 *                case publicID receives PubidLiteral, is strict is off
4721 *                it is possible to return NULL and have publicID set.
4722 */
4723
4724xmlChar *
4725xmlParseExternalID(xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict) {
4726    xmlChar *URI = NULL;
4727
4728    SHRINK;
4729
4730    *publicID = NULL;
4731    if (CMP6(CUR_PTR, 'S', 'Y', 'S', 'T', 'E', 'M')) {
4732        SKIP(6);
4733	if (!IS_BLANK_CH(CUR)) {
4734	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4735	                   "Space required after 'SYSTEM'\n");
4736	}
4737        SKIP_BLANKS;
4738	URI = xmlParseSystemLiteral(ctxt);
4739	if (URI == NULL) {
4740	    xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4741        }
4742    } else if (CMP6(CUR_PTR, 'P', 'U', 'B', 'L', 'I', 'C')) {
4743        SKIP(6);
4744	if (!IS_BLANK_CH(CUR)) {
4745	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4746		    "Space required after 'PUBLIC'\n");
4747	}
4748        SKIP_BLANKS;
4749	*publicID = xmlParsePubidLiteral(ctxt);
4750	if (*publicID == NULL) {
4751	    xmlFatalErr(ctxt, XML_ERR_PUBID_REQUIRED, NULL);
4752	}
4753	if (strict) {
4754	    /*
4755	     * We don't handle [83] so "S SystemLiteral" is required.
4756	     */
4757	    if (!IS_BLANK_CH(CUR)) {
4758		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
4759			"Space required after the Public Identifier\n");
4760	    }
4761	} else {
4762	    /*
4763	     * We handle [83] so we return immediately, if
4764	     * "S SystemLiteral" is not detected. From a purely parsing
4765	     * point of view that's a nice mess.
4766	     */
4767	    const xmlChar *ptr;
4768	    GROW;
4769
4770	    ptr = CUR_PTR;
4771	    if (!IS_BLANK_CH(*ptr)) return(NULL);
4772
4773	    while (IS_BLANK_CH(*ptr)) ptr++; /* TODO: dangerous, fix ! */
4774	    if ((*ptr != '\'') && (*ptr != '"')) return(NULL);
4775	}
4776        SKIP_BLANKS;
4777	URI = xmlParseSystemLiteral(ctxt);
4778	if (URI == NULL) {
4779	    xmlFatalErr(ctxt, XML_ERR_URI_REQUIRED, NULL);
4780        }
4781    }
4782    return(URI);
4783}
4784
4785/**
4786 * xmlParseCommentComplex:
4787 * @ctxt:  an XML parser context
4788 * @buf:  the already parsed part of the buffer
4789 * @len:  number of bytes filles in the buffer
4790 * @size:  allocated size of the buffer
4791 *
4792 * Skip an XML (SGML) comment <!-- .... -->
4793 *  The spec says that "For compatibility, the string "--" (double-hyphen)
4794 *  must not occur within comments. "
4795 * This is the slow routine in case the accelerator for ascii didn't work
4796 *
4797 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
4798 */
4799static void
4800xmlParseCommentComplex(xmlParserCtxtPtr ctxt, xmlChar *buf,
4801                       size_t len, size_t size) {
4802    int q, ql;
4803    int r, rl;
4804    int cur, l;
4805    size_t count = 0;
4806    int inputid;
4807
4808    inputid = ctxt->input->id;
4809
4810    if (buf == NULL) {
4811        len = 0;
4812	size = XML_PARSER_BUFFER_SIZE;
4813	buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
4814	if (buf == NULL) {
4815	    xmlErrMemory(ctxt, NULL);
4816	    return;
4817	}
4818    }
4819    GROW;	/* Assure there's enough input data */
4820    q = CUR_CHAR(ql);
4821    if (q == 0)
4822        goto not_terminated;
4823    if (!IS_CHAR(q)) {
4824        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4825                          "xmlParseComment: invalid xmlChar value %d\n",
4826	                  q);
4827	xmlFree (buf);
4828	return;
4829    }
4830    NEXTL(ql);
4831    r = CUR_CHAR(rl);
4832    if (r == 0)
4833        goto not_terminated;
4834    if (!IS_CHAR(r)) {
4835        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4836                          "xmlParseComment: invalid xmlChar value %d\n",
4837	                  q);
4838	xmlFree (buf);
4839	return;
4840    }
4841    NEXTL(rl);
4842    cur = CUR_CHAR(l);
4843    if (cur == 0)
4844        goto not_terminated;
4845    while (IS_CHAR(cur) && /* checked */
4846           ((cur != '>') ||
4847	    (r != '-') || (q != '-'))) {
4848	if ((r == '-') && (q == '-')) {
4849	    xmlFatalErr(ctxt, XML_ERR_HYPHEN_IN_COMMENT, NULL);
4850	}
4851        if ((len > XML_MAX_TEXT_LENGTH) &&
4852            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
4853            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4854                         "Comment too big found", NULL);
4855            xmlFree (buf);
4856            return;
4857        }
4858	if (len + 5 >= size) {
4859	    xmlChar *new_buf;
4860            size_t new_size;
4861
4862	    new_size = size * 2;
4863	    new_buf = (xmlChar *) xmlRealloc(buf, new_size);
4864	    if (new_buf == NULL) {
4865		xmlFree (buf);
4866		xmlErrMemory(ctxt, NULL);
4867		return;
4868	    }
4869	    buf = new_buf;
4870            size = new_size;
4871	}
4872	COPY_BUF(ql,buf,len,q);
4873	q = r;
4874	ql = rl;
4875	r = cur;
4876	rl = l;
4877
4878	count++;
4879	if (count > 50) {
4880	    GROW;
4881	    count = 0;
4882            if (ctxt->instate == XML_PARSER_EOF) {
4883		xmlFree(buf);
4884		return;
4885            }
4886	}
4887	NEXTL(l);
4888	cur = CUR_CHAR(l);
4889	if (cur == 0) {
4890	    SHRINK;
4891	    GROW;
4892	    cur = CUR_CHAR(l);
4893	}
4894    }
4895    buf[len] = 0;
4896    if (cur == 0) {
4897	xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4898	                     "Comment not terminated \n<!--%.50s\n", buf);
4899    } else if (!IS_CHAR(cur)) {
4900        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
4901                          "xmlParseComment: invalid xmlChar value %d\n",
4902	                  cur);
4903    } else {
4904	if (inputid != ctxt->input->id) {
4905	    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
4906		"Comment doesn't start and stop in the same entity\n");
4907	}
4908        NEXT;
4909	if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
4910	    (!ctxt->disableSAX))
4911	    ctxt->sax->comment(ctxt->userData, buf);
4912    }
4913    xmlFree(buf);
4914    return;
4915not_terminated:
4916    xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
4917			 "Comment not terminated\n", NULL);
4918    xmlFree(buf);
4919    return;
4920}
4921
4922/**
4923 * xmlParseComment:
4924 * @ctxt:  an XML parser context
4925 *
4926 * Skip an XML (SGML) comment <!-- .... -->
4927 *  The spec says that "For compatibility, the string "--" (double-hyphen)
4928 *  must not occur within comments. "
4929 *
4930 * [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
4931 */
4932void
4933xmlParseComment(xmlParserCtxtPtr ctxt) {
4934    xmlChar *buf = NULL;
4935    size_t size = XML_PARSER_BUFFER_SIZE;
4936    size_t len = 0;
4937    xmlParserInputState state;
4938    const xmlChar *in;
4939    size_t nbchar = 0;
4940    int ccol;
4941    int inputid;
4942
4943    /*
4944     * Check that there is a comment right here.
4945     */
4946    if ((RAW != '<') || (NXT(1) != '!') ||
4947        (NXT(2) != '-') || (NXT(3) != '-')) return;
4948    state = ctxt->instate;
4949    ctxt->instate = XML_PARSER_COMMENT;
4950    inputid = ctxt->input->id;
4951    SKIP(4);
4952    SHRINK;
4953    GROW;
4954
4955    /*
4956     * Accelerated common case where input don't need to be
4957     * modified before passing it to the handler.
4958     */
4959    in = ctxt->input->cur;
4960    do {
4961	if (*in == 0xA) {
4962	    do {
4963		ctxt->input->line++; ctxt->input->col = 1;
4964		in++;
4965	    } while (*in == 0xA);
4966	}
4967get_more:
4968        ccol = ctxt->input->col;
4969	while (((*in > '-') && (*in <= 0x7F)) ||
4970	       ((*in >= 0x20) && (*in < '-')) ||
4971	       (*in == 0x09)) {
4972		    in++;
4973		    ccol++;
4974	}
4975	ctxt->input->col = ccol;
4976	if (*in == 0xA) {
4977	    do {
4978		ctxt->input->line++; ctxt->input->col = 1;
4979		in++;
4980	    } while (*in == 0xA);
4981	    goto get_more;
4982	}
4983	nbchar = in - ctxt->input->cur;
4984	/*
4985	 * save current set of data
4986	 */
4987	if (nbchar > 0) {
4988	    if ((ctxt->sax != NULL) &&
4989		(ctxt->sax->comment != NULL)) {
4990		if (buf == NULL) {
4991		    if ((*in == '-') && (in[1] == '-'))
4992		        size = nbchar + 1;
4993		    else
4994		        size = XML_PARSER_BUFFER_SIZE + nbchar;
4995		    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
4996		    if (buf == NULL) {
4997		        xmlErrMemory(ctxt, NULL);
4998			ctxt->instate = state;
4999			return;
5000		    }
5001		    len = 0;
5002		} else if (len + nbchar + 1 >= size) {
5003		    xmlChar *new_buf;
5004		    size  += len + nbchar + XML_PARSER_BUFFER_SIZE;
5005		    new_buf = (xmlChar *) xmlRealloc(buf,
5006		                                     size * sizeof(xmlChar));
5007		    if (new_buf == NULL) {
5008		        xmlFree (buf);
5009			xmlErrMemory(ctxt, NULL);
5010			ctxt->instate = state;
5011			return;
5012		    }
5013		    buf = new_buf;
5014		}
5015		memcpy(&buf[len], ctxt->input->cur, nbchar);
5016		len += nbchar;
5017		buf[len] = 0;
5018	    }
5019	}
5020        if ((len > XML_MAX_TEXT_LENGTH) &&
5021            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
5022            xmlFatalErrMsgStr(ctxt, XML_ERR_COMMENT_NOT_FINISHED,
5023                         "Comment too big found", NULL);
5024            xmlFree (buf);
5025            return;
5026        }
5027	ctxt->input->cur = in;
5028	if (*in == 0xA) {
5029	    in++;
5030	    ctxt->input->line++; ctxt->input->col = 1;
5031	}
5032	if (*in == 0xD) {
5033	    in++;
5034	    if (*in == 0xA) {
5035		ctxt->input->cur = in;
5036		in++;
5037		ctxt->input->line++; ctxt->input->col = 1;
5038		continue; /* while */
5039	    }
5040	    in--;
5041	}
5042	SHRINK;
5043	GROW;
5044        if (ctxt->instate == XML_PARSER_EOF) {
5045            xmlFree(buf);
5046            return;
5047        }
5048	in = ctxt->input->cur;
5049	if (*in == '-') {
5050	    if (in[1] == '-') {
5051	        if (in[2] == '>') {
5052		    if (ctxt->input->id != inputid) {
5053			xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5054			"comment doesn't start and stop in the same entity\n");
5055		    }
5056		    SKIP(3);
5057		    if ((ctxt->sax != NULL) && (ctxt->sax->comment != NULL) &&
5058		        (!ctxt->disableSAX)) {
5059			if (buf != NULL)
5060			    ctxt->sax->comment(ctxt->userData, buf);
5061			else
5062			    ctxt->sax->comment(ctxt->userData, BAD_CAST "");
5063		    }
5064		    if (buf != NULL)
5065		        xmlFree(buf);
5066		    if (ctxt->instate != XML_PARSER_EOF)
5067			ctxt->instate = state;
5068		    return;
5069		}
5070		if (buf != NULL) {
5071		    xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5072		                      "Double hyphen within comment: "
5073                                      "<!--%.50s\n",
5074				      buf);
5075		} else
5076		    xmlFatalErrMsgStr(ctxt, XML_ERR_HYPHEN_IN_COMMENT,
5077		                      "Double hyphen within comment\n", NULL);
5078		in++;
5079		ctxt->input->col++;
5080	    }
5081	    in++;
5082	    ctxt->input->col++;
5083	    goto get_more;
5084	}
5085    } while (((*in >= 0x20) && (*in <= 0x7F)) || (*in == 0x09));
5086    xmlParseCommentComplex(ctxt, buf, len, size);
5087    ctxt->instate = state;
5088    return;
5089}
5090
5091
5092/**
5093 * xmlParsePITarget:
5094 * @ctxt:  an XML parser context
5095 *
5096 * parse the name of a PI
5097 *
5098 * [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
5099 *
5100 * Returns the PITarget name or NULL
5101 */
5102
5103const xmlChar *
5104xmlParsePITarget(xmlParserCtxtPtr ctxt) {
5105    const xmlChar *name;
5106
5107    name = xmlParseName(ctxt);
5108    if ((name != NULL) &&
5109        ((name[0] == 'x') || (name[0] == 'X')) &&
5110        ((name[1] == 'm') || (name[1] == 'M')) &&
5111        ((name[2] == 'l') || (name[2] == 'L'))) {
5112	int i;
5113	if ((name[0] == 'x') && (name[1] == 'm') &&
5114	    (name[2] == 'l') && (name[3] == 0)) {
5115	    xmlFatalErrMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5116		 "XML declaration allowed only at the start of the document\n");
5117	    return(name);
5118	} else if (name[3] == 0) {
5119	    xmlFatalErr(ctxt, XML_ERR_RESERVED_XML_NAME, NULL);
5120	    return(name);
5121	}
5122	for (i = 0;;i++) {
5123	    if (xmlW3CPIs[i] == NULL) break;
5124	    if (xmlStrEqual(name, (const xmlChar *)xmlW3CPIs[i]))
5125	        return(name);
5126	}
5127	xmlWarningMsg(ctxt, XML_ERR_RESERVED_XML_NAME,
5128		      "xmlParsePITarget: invalid name prefix 'xml'\n",
5129		      NULL, NULL);
5130    }
5131    if ((name != NULL) && (xmlStrchr(name, ':') != NULL)) {
5132	xmlNsErr(ctxt, XML_NS_ERR_COLON,
5133		 "colons are forbidden from PI names '%s'\n", name, NULL, NULL);
5134    }
5135    return(name);
5136}
5137
5138#ifdef LIBXML_CATALOG_ENABLED
5139/**
5140 * xmlParseCatalogPI:
5141 * @ctxt:  an XML parser context
5142 * @catalog:  the PI value string
5143 *
5144 * parse an XML Catalog Processing Instruction.
5145 *
5146 * <?oasis-xml-catalog catalog="http://example.com/catalog.xml"?>
5147 *
5148 * Occurs only if allowed by the user and if happening in the Misc
5149 * part of the document before any doctype informations
5150 * This will add the given catalog to the parsing context in order
5151 * to be used if there is a resolution need further down in the document
5152 */
5153
5154static void
5155xmlParseCatalogPI(xmlParserCtxtPtr ctxt, const xmlChar *catalog) {
5156    xmlChar *URL = NULL;
5157    const xmlChar *tmp, *base;
5158    xmlChar marker;
5159
5160    tmp = catalog;
5161    while (IS_BLANK_CH(*tmp)) tmp++;
5162    if (xmlStrncmp(tmp, BAD_CAST"catalog", 7))
5163	goto error;
5164    tmp += 7;
5165    while (IS_BLANK_CH(*tmp)) tmp++;
5166    if (*tmp != '=') {
5167	return;
5168    }
5169    tmp++;
5170    while (IS_BLANK_CH(*tmp)) tmp++;
5171    marker = *tmp;
5172    if ((marker != '\'') && (marker != '"'))
5173	goto error;
5174    tmp++;
5175    base = tmp;
5176    while ((*tmp != 0) && (*tmp != marker)) tmp++;
5177    if (*tmp == 0)
5178	goto error;
5179    URL = xmlStrndup(base, tmp - base);
5180    tmp++;
5181    while (IS_BLANK_CH(*tmp)) tmp++;
5182    if (*tmp != 0)
5183	goto error;
5184
5185    if (URL != NULL) {
5186	ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
5187	xmlFree(URL);
5188    }
5189    return;
5190
5191error:
5192    xmlWarningMsg(ctxt, XML_WAR_CATALOG_PI,
5193	          "Catalog PI syntax error: %s\n",
5194		  catalog, NULL);
5195    if (URL != NULL)
5196	xmlFree(URL);
5197}
5198#endif
5199
5200/**
5201 * xmlParsePI:
5202 * @ctxt:  an XML parser context
5203 *
5204 * parse an XML Processing Instruction.
5205 *
5206 * [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
5207 *
5208 * The processing is transfered to SAX once parsed.
5209 */
5210
5211void
5212xmlParsePI(xmlParserCtxtPtr ctxt) {
5213    xmlChar *buf = NULL;
5214    size_t len = 0;
5215    size_t size = XML_PARSER_BUFFER_SIZE;
5216    int cur, l;
5217    const xmlChar *target;
5218    xmlParserInputState state;
5219    int count = 0;
5220
5221    if ((RAW == '<') && (NXT(1) == '?')) {
5222	xmlParserInputPtr input = ctxt->input;
5223	state = ctxt->instate;
5224        ctxt->instate = XML_PARSER_PI;
5225	/*
5226	 * this is a Processing Instruction.
5227	 */
5228	SKIP(2);
5229	SHRINK;
5230
5231	/*
5232	 * Parse the target name and check for special support like
5233	 * namespace.
5234	 */
5235        target = xmlParsePITarget(ctxt);
5236	if (target != NULL) {
5237	    if ((RAW == '?') && (NXT(1) == '>')) {
5238		if (input != ctxt->input) {
5239		    xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5240	    "PI declaration doesn't start and stop in the same entity\n");
5241		}
5242		SKIP(2);
5243
5244		/*
5245		 * SAX: PI detected.
5246		 */
5247		if ((ctxt->sax) && (!ctxt->disableSAX) &&
5248		    (ctxt->sax->processingInstruction != NULL))
5249		    ctxt->sax->processingInstruction(ctxt->userData,
5250		                                     target, NULL);
5251		if (ctxt->instate != XML_PARSER_EOF)
5252		    ctxt->instate = state;
5253		return;
5254	    }
5255	    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
5256	    if (buf == NULL) {
5257		xmlErrMemory(ctxt, NULL);
5258		ctxt->instate = state;
5259		return;
5260	    }
5261	    cur = CUR;
5262	    if (!IS_BLANK(cur)) {
5263		xmlFatalErrMsgStr(ctxt, XML_ERR_SPACE_REQUIRED,
5264			  "ParsePI: PI %s space expected\n", target);
5265	    }
5266            SKIP_BLANKS;
5267	    cur = CUR_CHAR(l);
5268	    while (IS_CHAR(cur) && /* checked */
5269		   ((cur != '?') || (NXT(1) != '>'))) {
5270		if (len + 5 >= size) {
5271		    xmlChar *tmp;
5272                    size_t new_size = size * 2;
5273		    tmp = (xmlChar *) xmlRealloc(buf, new_size);
5274		    if (tmp == NULL) {
5275			xmlErrMemory(ctxt, NULL);
5276			xmlFree(buf);
5277			ctxt->instate = state;
5278			return;
5279		    }
5280		    buf = tmp;
5281                    size = new_size;
5282		}
5283		count++;
5284		if (count > 50) {
5285		    GROW;
5286                    if (ctxt->instate == XML_PARSER_EOF) {
5287                        xmlFree(buf);
5288                        return;
5289                    }
5290		    count = 0;
5291                    if ((len > XML_MAX_TEXT_LENGTH) &&
5292                        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
5293                        xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5294                                          "PI %s too big found", target);
5295                        xmlFree(buf);
5296                        ctxt->instate = state;
5297                        return;
5298                    }
5299		}
5300		COPY_BUF(l,buf,len,cur);
5301		NEXTL(l);
5302		cur = CUR_CHAR(l);
5303		if (cur == 0) {
5304		    SHRINK;
5305		    GROW;
5306		    cur = CUR_CHAR(l);
5307		}
5308	    }
5309            if ((len > XML_MAX_TEXT_LENGTH) &&
5310                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
5311                xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5312                                  "PI %s too big found", target);
5313                xmlFree(buf);
5314                ctxt->instate = state;
5315                return;
5316            }
5317	    buf[len] = 0;
5318	    if (cur != '?') {
5319		xmlFatalErrMsgStr(ctxt, XML_ERR_PI_NOT_FINISHED,
5320		      "ParsePI: PI %s never end ...\n", target);
5321	    } else {
5322		if (input != ctxt->input) {
5323		    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5324	    "PI declaration doesn't start and stop in the same entity\n");
5325		}
5326		SKIP(2);
5327
5328#ifdef LIBXML_CATALOG_ENABLED
5329		if (((state == XML_PARSER_MISC) ||
5330	             (state == XML_PARSER_START)) &&
5331		    (xmlStrEqual(target, XML_CATALOG_PI))) {
5332		    xmlCatalogAllow allow = xmlCatalogGetDefaults();
5333		    if ((allow == XML_CATA_ALLOW_DOCUMENT) ||
5334			(allow == XML_CATA_ALLOW_ALL))
5335			xmlParseCatalogPI(ctxt, buf);
5336		}
5337#endif
5338
5339
5340		/*
5341		 * SAX: PI detected.
5342		 */
5343		if ((ctxt->sax) && (!ctxt->disableSAX) &&
5344		    (ctxt->sax->processingInstruction != NULL))
5345		    ctxt->sax->processingInstruction(ctxt->userData,
5346		                                     target, buf);
5347	    }
5348	    xmlFree(buf);
5349	} else {
5350	    xmlFatalErr(ctxt, XML_ERR_PI_NOT_STARTED, NULL);
5351	}
5352	if (ctxt->instate != XML_PARSER_EOF)
5353	    ctxt->instate = state;
5354    }
5355}
5356
5357/**
5358 * xmlParseNotationDecl:
5359 * @ctxt:  an XML parser context
5360 *
5361 * parse a notation declaration
5362 *
5363 * [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID |  PublicID) S? '>'
5364 *
5365 * Hence there is actually 3 choices:
5366 *     'PUBLIC' S PubidLiteral
5367 *     'PUBLIC' S PubidLiteral S SystemLiteral
5368 * and 'SYSTEM' S SystemLiteral
5369 *
5370 * See the NOTE on xmlParseExternalID().
5371 */
5372
5373void
5374xmlParseNotationDecl(xmlParserCtxtPtr ctxt) {
5375    const xmlChar *name;
5376    xmlChar *Pubid;
5377    xmlChar *Systemid;
5378
5379    if (CMP10(CUR_PTR, '<', '!', 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5380	xmlParserInputPtr input = ctxt->input;
5381	SHRINK;
5382	SKIP(10);
5383	if (!IS_BLANK_CH(CUR)) {
5384	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5385			   "Space required after '<!NOTATION'\n");
5386	    return;
5387	}
5388	SKIP_BLANKS;
5389
5390        name = xmlParseName(ctxt);
5391	if (name == NULL) {
5392	    xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5393	    return;
5394	}
5395	if (!IS_BLANK_CH(CUR)) {
5396	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5397		     "Space required after the NOTATION name'\n");
5398	    return;
5399	}
5400	if (xmlStrchr(name, ':') != NULL) {
5401	    xmlNsErr(ctxt, XML_NS_ERR_COLON,
5402		     "colons are forbidden from notation names '%s'\n",
5403		     name, NULL, NULL);
5404	}
5405	SKIP_BLANKS;
5406
5407	/*
5408	 * Parse the IDs.
5409	 */
5410	Systemid = xmlParseExternalID(ctxt, &Pubid, 0);
5411	SKIP_BLANKS;
5412
5413	if (RAW == '>') {
5414	    if (input != ctxt->input) {
5415		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5416	"Notation declaration doesn't start and stop in the same entity\n");
5417	    }
5418	    NEXT;
5419	    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5420		(ctxt->sax->notationDecl != NULL))
5421		ctxt->sax->notationDecl(ctxt->userData, name, Pubid, Systemid);
5422	} else {
5423	    xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5424	}
5425	if (Systemid != NULL) xmlFree(Systemid);
5426	if (Pubid != NULL) xmlFree(Pubid);
5427    }
5428}
5429
5430/**
5431 * xmlParseEntityDecl:
5432 * @ctxt:  an XML parser context
5433 *
5434 * parse <!ENTITY declarations
5435 *
5436 * [70] EntityDecl ::= GEDecl | PEDecl
5437 *
5438 * [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
5439 *
5440 * [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
5441 *
5442 * [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
5443 *
5444 * [74] PEDef ::= EntityValue | ExternalID
5445 *
5446 * [76] NDataDecl ::= S 'NDATA' S Name
5447 *
5448 * [ VC: Notation Declared ]
5449 * The Name must match the declared name of a notation.
5450 */
5451
5452void
5453xmlParseEntityDecl(xmlParserCtxtPtr ctxt) {
5454    const xmlChar *name = NULL;
5455    xmlChar *value = NULL;
5456    xmlChar *URI = NULL, *literal = NULL;
5457    const xmlChar *ndata = NULL;
5458    int isParameter = 0;
5459    xmlChar *orig = NULL;
5460    int skipped;
5461
5462    /* GROW; done in the caller */
5463    if (CMP8(CUR_PTR, '<', '!', 'E', 'N', 'T', 'I', 'T', 'Y')) {
5464	xmlParserInputPtr input = ctxt->input;
5465	SHRINK;
5466	SKIP(8);
5467	skipped = SKIP_BLANKS;
5468	if (skipped == 0) {
5469	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5470			   "Space required after '<!ENTITY'\n");
5471	}
5472
5473	if (RAW == '%') {
5474	    NEXT;
5475	    skipped = SKIP_BLANKS;
5476	    if (skipped == 0) {
5477		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5478			       "Space required after '%'\n");
5479	    }
5480	    isParameter = 1;
5481	}
5482
5483        name = xmlParseName(ctxt);
5484	if (name == NULL) {
5485	    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5486	                   "xmlParseEntityDecl: no name\n");
5487            return;
5488	}
5489	if (xmlStrchr(name, ':') != NULL) {
5490	    xmlNsErr(ctxt, XML_NS_ERR_COLON,
5491		     "colons are forbidden from entities names '%s'\n",
5492		     name, NULL, NULL);
5493	}
5494        skipped = SKIP_BLANKS;
5495	if (skipped == 0) {
5496	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5497			   "Space required after the entity name\n");
5498	}
5499
5500	ctxt->instate = XML_PARSER_ENTITY_DECL;
5501	/*
5502	 * handle the various case of definitions...
5503	 */
5504	if (isParameter) {
5505	    if ((RAW == '"') || (RAW == '\'')) {
5506	        value = xmlParseEntityValue(ctxt, &orig);
5507		if (value) {
5508		    if ((ctxt->sax != NULL) &&
5509			(!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5510			ctxt->sax->entityDecl(ctxt->userData, name,
5511		                    XML_INTERNAL_PARAMETER_ENTITY,
5512				    NULL, NULL, value);
5513		}
5514	    } else {
5515	        URI = xmlParseExternalID(ctxt, &literal, 1);
5516		if ((URI == NULL) && (literal == NULL)) {
5517		    xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5518		}
5519		if (URI) {
5520		    xmlURIPtr uri;
5521
5522		    uri = xmlParseURI((const char *) URI);
5523		    if (uri == NULL) {
5524		        xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5525				     "Invalid URI: %s\n", URI);
5526			/*
5527			 * This really ought to be a well formedness error
5528			 * but the XML Core WG decided otherwise c.f. issue
5529			 * E26 of the XML erratas.
5530			 */
5531		    } else {
5532			if (uri->fragment != NULL) {
5533			    /*
5534			     * Okay this is foolish to block those but not
5535			     * invalid URIs.
5536			     */
5537			    xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5538			} else {
5539			    if ((ctxt->sax != NULL) &&
5540				(!ctxt->disableSAX) &&
5541				(ctxt->sax->entityDecl != NULL))
5542				ctxt->sax->entityDecl(ctxt->userData, name,
5543					    XML_EXTERNAL_PARAMETER_ENTITY,
5544					    literal, URI, NULL);
5545			}
5546			xmlFreeURI(uri);
5547		    }
5548		}
5549	    }
5550	} else {
5551	    if ((RAW == '"') || (RAW == '\'')) {
5552	        value = xmlParseEntityValue(ctxt, &orig);
5553		if ((ctxt->sax != NULL) &&
5554		    (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5555		    ctxt->sax->entityDecl(ctxt->userData, name,
5556				XML_INTERNAL_GENERAL_ENTITY,
5557				NULL, NULL, value);
5558		/*
5559		 * For expat compatibility in SAX mode.
5560		 */
5561		if ((ctxt->myDoc == NULL) ||
5562		    (xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
5563		    if (ctxt->myDoc == NULL) {
5564			ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5565			if (ctxt->myDoc == NULL) {
5566			    xmlErrMemory(ctxt, "New Doc failed");
5567			    return;
5568			}
5569			ctxt->myDoc->properties = XML_DOC_INTERNAL;
5570		    }
5571		    if (ctxt->myDoc->intSubset == NULL)
5572			ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5573					    BAD_CAST "fake", NULL, NULL);
5574
5575		    xmlSAX2EntityDecl(ctxt, name, XML_INTERNAL_GENERAL_ENTITY,
5576			              NULL, NULL, value);
5577		}
5578	    } else {
5579	        URI = xmlParseExternalID(ctxt, &literal, 1);
5580		if ((URI == NULL) && (literal == NULL)) {
5581		    xmlFatalErr(ctxt, XML_ERR_VALUE_REQUIRED, NULL);
5582		}
5583		if (URI) {
5584		    xmlURIPtr uri;
5585
5586		    uri = xmlParseURI((const char *)URI);
5587		    if (uri == NULL) {
5588		        xmlErrMsgStr(ctxt, XML_ERR_INVALID_URI,
5589				     "Invalid URI: %s\n", URI);
5590			/*
5591			 * This really ought to be a well formedness error
5592			 * but the XML Core WG decided otherwise c.f. issue
5593			 * E26 of the XML erratas.
5594			 */
5595		    } else {
5596			if (uri->fragment != NULL) {
5597			    /*
5598			     * Okay this is foolish to block those but not
5599			     * invalid URIs.
5600			     */
5601			    xmlFatalErr(ctxt, XML_ERR_URI_FRAGMENT, NULL);
5602			}
5603			xmlFreeURI(uri);
5604		    }
5605		}
5606		if ((RAW != '>') && (!IS_BLANK_CH(CUR))) {
5607		    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5608				   "Space required before 'NDATA'\n");
5609		}
5610		SKIP_BLANKS;
5611		if (CMP5(CUR_PTR, 'N', 'D', 'A', 'T', 'A')) {
5612		    SKIP(5);
5613		    if (!IS_BLANK_CH(CUR)) {
5614			xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5615				       "Space required after 'NDATA'\n");
5616		    }
5617		    SKIP_BLANKS;
5618		    ndata = xmlParseName(ctxt);
5619		    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
5620		        (ctxt->sax->unparsedEntityDecl != NULL))
5621			ctxt->sax->unparsedEntityDecl(ctxt->userData, name,
5622				    literal, URI, ndata);
5623		} else {
5624		    if ((ctxt->sax != NULL) &&
5625		        (!ctxt->disableSAX) && (ctxt->sax->entityDecl != NULL))
5626			ctxt->sax->entityDecl(ctxt->userData, name,
5627				    XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5628				    literal, URI, NULL);
5629		    /*
5630		     * For expat compatibility in SAX mode.
5631		     * assuming the entity repalcement was asked for
5632		     */
5633		    if ((ctxt->replaceEntities != 0) &&
5634			((ctxt->myDoc == NULL) ||
5635			(xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE)))) {
5636			if (ctxt->myDoc == NULL) {
5637			    ctxt->myDoc = xmlNewDoc(SAX_COMPAT_MODE);
5638			    if (ctxt->myDoc == NULL) {
5639			        xmlErrMemory(ctxt, "New Doc failed");
5640				return;
5641			    }
5642			    ctxt->myDoc->properties = XML_DOC_INTERNAL;
5643			}
5644
5645			if (ctxt->myDoc->intSubset == NULL)
5646			    ctxt->myDoc->intSubset = xmlNewDtd(ctxt->myDoc,
5647						BAD_CAST "fake", NULL, NULL);
5648			xmlSAX2EntityDecl(ctxt, name,
5649				          XML_EXTERNAL_GENERAL_PARSED_ENTITY,
5650				          literal, URI, NULL);
5651		    }
5652		}
5653	    }
5654	}
5655	if (ctxt->instate == XML_PARSER_EOF)
5656	    return;
5657	SKIP_BLANKS;
5658	if (RAW != '>') {
5659	    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_NOT_FINISHED,
5660	            "xmlParseEntityDecl: entity %s not terminated\n", name);
5661	} else {
5662	    if (input != ctxt->input) {
5663		xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
5664	"Entity declaration doesn't start and stop in the same entity\n");
5665	    }
5666	    NEXT;
5667	}
5668	if (orig != NULL) {
5669	    /*
5670	     * Ugly mechanism to save the raw entity value.
5671	     */
5672	    xmlEntityPtr cur = NULL;
5673
5674	    if (isParameter) {
5675	        if ((ctxt->sax != NULL) &&
5676		    (ctxt->sax->getParameterEntity != NULL))
5677		    cur = ctxt->sax->getParameterEntity(ctxt->userData, name);
5678	    } else {
5679	        if ((ctxt->sax != NULL) &&
5680		    (ctxt->sax->getEntity != NULL))
5681		    cur = ctxt->sax->getEntity(ctxt->userData, name);
5682		if ((cur == NULL) && (ctxt->userData==ctxt)) {
5683		    cur = xmlSAX2GetEntity(ctxt, name);
5684		}
5685	    }
5686            if (cur != NULL) {
5687	        if (cur->orig != NULL)
5688		    xmlFree(orig);
5689		else
5690		    cur->orig = orig;
5691	    } else
5692		xmlFree(orig);
5693	}
5694	if (value != NULL) xmlFree(value);
5695	if (URI != NULL) xmlFree(URI);
5696	if (literal != NULL) xmlFree(literal);
5697    }
5698}
5699
5700/**
5701 * xmlParseDefaultDecl:
5702 * @ctxt:  an XML parser context
5703 * @value:  Receive a possible fixed default value for the attribute
5704 *
5705 * Parse an attribute default declaration
5706 *
5707 * [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
5708 *
5709 * [ VC: Required Attribute ]
5710 * if the default declaration is the keyword #REQUIRED, then the
5711 * attribute must be specified for all elements of the type in the
5712 * attribute-list declaration.
5713 *
5714 * [ VC: Attribute Default Legal ]
5715 * The declared default value must meet the lexical constraints of
5716 * the declared attribute type c.f. xmlValidateAttributeDecl()
5717 *
5718 * [ VC: Fixed Attribute Default ]
5719 * if an attribute has a default value declared with the #FIXED
5720 * keyword, instances of that attribute must match the default value.
5721 *
5722 * [ WFC: No < in Attribute Values ]
5723 * handled in xmlParseAttValue()
5724 *
5725 * returns: XML_ATTRIBUTE_NONE, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED
5726 *          or XML_ATTRIBUTE_FIXED.
5727 */
5728
5729int
5730xmlParseDefaultDecl(xmlParserCtxtPtr ctxt, xmlChar **value) {
5731    int val;
5732    xmlChar *ret;
5733
5734    *value = NULL;
5735    if (CMP9(CUR_PTR, '#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D')) {
5736	SKIP(9);
5737	return(XML_ATTRIBUTE_REQUIRED);
5738    }
5739    if (CMP8(CUR_PTR, '#', 'I', 'M', 'P', 'L', 'I', 'E', 'D')) {
5740	SKIP(8);
5741	return(XML_ATTRIBUTE_IMPLIED);
5742    }
5743    val = XML_ATTRIBUTE_NONE;
5744    if (CMP6(CUR_PTR, '#', 'F', 'I', 'X', 'E', 'D')) {
5745	SKIP(6);
5746	val = XML_ATTRIBUTE_FIXED;
5747	if (!IS_BLANK_CH(CUR)) {
5748	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5749			   "Space required after '#FIXED'\n");
5750	}
5751	SKIP_BLANKS;
5752    }
5753    ret = xmlParseAttValue(ctxt);
5754    ctxt->instate = XML_PARSER_DTD;
5755    if (ret == NULL) {
5756	xmlFatalErrMsg(ctxt, (xmlParserErrors)ctxt->errNo,
5757		       "Attribute default value declaration error\n");
5758    } else
5759        *value = ret;
5760    return(val);
5761}
5762
5763/**
5764 * xmlParseNotationType:
5765 * @ctxt:  an XML parser context
5766 *
5767 * parse an Notation attribute type.
5768 *
5769 * Note: the leading 'NOTATION' S part has already being parsed...
5770 *
5771 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
5772 *
5773 * [ VC: Notation Attributes ]
5774 * Values of this type must match one of the notation names included
5775 * in the declaration; all notation names in the declaration must be declared.
5776 *
5777 * Returns: the notation attribute tree built while parsing
5778 */
5779
5780xmlEnumerationPtr
5781xmlParseNotationType(xmlParserCtxtPtr ctxt) {
5782    const xmlChar *name;
5783    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5784
5785    if (RAW != '(') {
5786	xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_STARTED, NULL);
5787	return(NULL);
5788    }
5789    SHRINK;
5790    do {
5791        NEXT;
5792	SKIP_BLANKS;
5793        name = xmlParseName(ctxt);
5794	if (name == NULL) {
5795	    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
5796			   "Name expected in NOTATION declaration\n");
5797            xmlFreeEnumeration(ret);
5798	    return(NULL);
5799	}
5800	tmp = ret;
5801	while (tmp != NULL) {
5802	    if (xmlStrEqual(name, tmp->name)) {
5803		xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5804	  "standalone: attribute notation value token %s duplicated\n",
5805				 name, NULL);
5806		if (!xmlDictOwns(ctxt->dict, name))
5807		    xmlFree((xmlChar *) name);
5808		break;
5809	    }
5810	    tmp = tmp->next;
5811	}
5812	if (tmp == NULL) {
5813	    cur = xmlCreateEnumeration(name);
5814	    if (cur == NULL) {
5815                xmlFreeEnumeration(ret);
5816                return(NULL);
5817            }
5818	    if (last == NULL) ret = last = cur;
5819	    else {
5820		last->next = cur;
5821		last = cur;
5822	    }
5823	}
5824	SKIP_BLANKS;
5825    } while (RAW == '|');
5826    if (RAW != ')') {
5827	xmlFatalErr(ctxt, XML_ERR_NOTATION_NOT_FINISHED, NULL);
5828        xmlFreeEnumeration(ret);
5829	return(NULL);
5830    }
5831    NEXT;
5832    return(ret);
5833}
5834
5835/**
5836 * xmlParseEnumerationType:
5837 * @ctxt:  an XML parser context
5838 *
5839 * parse an Enumeration attribute type.
5840 *
5841 * [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
5842 *
5843 * [ VC: Enumeration ]
5844 * Values of this type must match one of the Nmtoken tokens in
5845 * the declaration
5846 *
5847 * Returns: the enumeration attribute tree built while parsing
5848 */
5849
5850xmlEnumerationPtr
5851xmlParseEnumerationType(xmlParserCtxtPtr ctxt) {
5852    xmlChar *name;
5853    xmlEnumerationPtr ret = NULL, last = NULL, cur, tmp;
5854
5855    if (RAW != '(') {
5856	xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_STARTED, NULL);
5857	return(NULL);
5858    }
5859    SHRINK;
5860    do {
5861        NEXT;
5862	SKIP_BLANKS;
5863        name = xmlParseNmtoken(ctxt);
5864	if (name == NULL) {
5865	    xmlFatalErr(ctxt, XML_ERR_NMTOKEN_REQUIRED, NULL);
5866	    return(ret);
5867	}
5868	tmp = ret;
5869	while (tmp != NULL) {
5870	    if (xmlStrEqual(name, tmp->name)) {
5871		xmlValidityError(ctxt, XML_DTD_DUP_TOKEN,
5872	  "standalone: attribute enumeration value token %s duplicated\n",
5873				 name, NULL);
5874		if (!xmlDictOwns(ctxt->dict, name))
5875		    xmlFree(name);
5876		break;
5877	    }
5878	    tmp = tmp->next;
5879	}
5880	if (tmp == NULL) {
5881	    cur = xmlCreateEnumeration(name);
5882	    if (!xmlDictOwns(ctxt->dict, name))
5883		xmlFree(name);
5884	    if (cur == NULL) {
5885                xmlFreeEnumeration(ret);
5886                return(NULL);
5887            }
5888	    if (last == NULL) ret = last = cur;
5889	    else {
5890		last->next = cur;
5891		last = cur;
5892	    }
5893	}
5894	SKIP_BLANKS;
5895    } while (RAW == '|');
5896    if (RAW != ')') {
5897	xmlFatalErr(ctxt, XML_ERR_ATTLIST_NOT_FINISHED, NULL);
5898	return(ret);
5899    }
5900    NEXT;
5901    return(ret);
5902}
5903
5904/**
5905 * xmlParseEnumeratedType:
5906 * @ctxt:  an XML parser context
5907 * @tree:  the enumeration tree built while parsing
5908 *
5909 * parse an Enumerated attribute type.
5910 *
5911 * [57] EnumeratedType ::= NotationType | Enumeration
5912 *
5913 * [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
5914 *
5915 *
5916 * Returns: XML_ATTRIBUTE_ENUMERATION or XML_ATTRIBUTE_NOTATION
5917 */
5918
5919int
5920xmlParseEnumeratedType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
5921    if (CMP8(CUR_PTR, 'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N')) {
5922	SKIP(8);
5923	if (!IS_BLANK_CH(CUR)) {
5924	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
5925			   "Space required after 'NOTATION'\n");
5926	    return(0);
5927	}
5928        SKIP_BLANKS;
5929	*tree = xmlParseNotationType(ctxt);
5930	if (*tree == NULL) return(0);
5931	return(XML_ATTRIBUTE_NOTATION);
5932    }
5933    *tree = xmlParseEnumerationType(ctxt);
5934    if (*tree == NULL) return(0);
5935    return(XML_ATTRIBUTE_ENUMERATION);
5936}
5937
5938/**
5939 * xmlParseAttributeType:
5940 * @ctxt:  an XML parser context
5941 * @tree:  the enumeration tree built while parsing
5942 *
5943 * parse the Attribute list def for an element
5944 *
5945 * [54] AttType ::= StringType | TokenizedType | EnumeratedType
5946 *
5947 * [55] StringType ::= 'CDATA'
5948 *
5949 * [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' |
5950 *                        'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
5951 *
5952 * Validity constraints for attribute values syntax are checked in
5953 * xmlValidateAttributeValue()
5954 *
5955 * [ VC: ID ]
5956 * Values of type ID must match the Name production. A name must not
5957 * appear more than once in an XML document as a value of this type;
5958 * i.e., ID values must uniquely identify the elements which bear them.
5959 *
5960 * [ VC: One ID per Element Type ]
5961 * No element type may have more than one ID attribute specified.
5962 *
5963 * [ VC: ID Attribute Default ]
5964 * An ID attribute must have a declared default of #IMPLIED or #REQUIRED.
5965 *
5966 * [ VC: IDREF ]
5967 * Values of type IDREF must match the Name production, and values
5968 * of type IDREFS must match Names; each IDREF Name must match the value
5969 * of an ID attribute on some element in the XML document; i.e. IDREF
5970 * values must match the value of some ID attribute.
5971 *
5972 * [ VC: Entity Name ]
5973 * Values of type ENTITY must match the Name production, values
5974 * of type ENTITIES must match Names; each Entity Name must match the
5975 * name of an unparsed entity declared in the DTD.
5976 *
5977 * [ VC: Name Token ]
5978 * Values of type NMTOKEN must match the Nmtoken production; values
5979 * of type NMTOKENS must match Nmtokens.
5980 *
5981 * Returns the attribute type
5982 */
5983int
5984xmlParseAttributeType(xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree) {
5985    SHRINK;
5986    if (CMP5(CUR_PTR, 'C', 'D', 'A', 'T', 'A')) {
5987	SKIP(5);
5988	return(XML_ATTRIBUTE_CDATA);
5989     } else if (CMP6(CUR_PTR, 'I', 'D', 'R', 'E', 'F', 'S')) {
5990	SKIP(6);
5991	return(XML_ATTRIBUTE_IDREFS);
5992     } else if (CMP5(CUR_PTR, 'I', 'D', 'R', 'E', 'F')) {
5993	SKIP(5);
5994	return(XML_ATTRIBUTE_IDREF);
5995     } else if ((RAW == 'I') && (NXT(1) == 'D')) {
5996        SKIP(2);
5997	return(XML_ATTRIBUTE_ID);
5998     } else if (CMP6(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'Y')) {
5999	SKIP(6);
6000	return(XML_ATTRIBUTE_ENTITY);
6001     } else if (CMP8(CUR_PTR, 'E', 'N', 'T', 'I', 'T', 'I', 'E', 'S')) {
6002	SKIP(8);
6003	return(XML_ATTRIBUTE_ENTITIES);
6004     } else if (CMP8(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N', 'S')) {
6005	SKIP(8);
6006	return(XML_ATTRIBUTE_NMTOKENS);
6007     } else if (CMP7(CUR_PTR, 'N', 'M', 'T', 'O', 'K', 'E', 'N')) {
6008	SKIP(7);
6009	return(XML_ATTRIBUTE_NMTOKEN);
6010     }
6011     return(xmlParseEnumeratedType(ctxt, tree));
6012}
6013
6014/**
6015 * xmlParseAttributeListDecl:
6016 * @ctxt:  an XML parser context
6017 *
6018 * : parse the Attribute list def for an element
6019 *
6020 * [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
6021 *
6022 * [53] AttDef ::= S Name S AttType S DefaultDecl
6023 *
6024 */
6025void
6026xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt) {
6027    const xmlChar *elemName;
6028    const xmlChar *attrName;
6029    xmlEnumerationPtr tree;
6030
6031    if (CMP9(CUR_PTR, '<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T')) {
6032	xmlParserInputPtr input = ctxt->input;
6033
6034	SKIP(9);
6035	if (!IS_BLANK_CH(CUR)) {
6036	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6037		                 "Space required after '<!ATTLIST'\n");
6038	}
6039        SKIP_BLANKS;
6040        elemName = xmlParseName(ctxt);
6041	if (elemName == NULL) {
6042	    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6043			   "ATTLIST: no name for Element\n");
6044	    return;
6045	}
6046	SKIP_BLANKS;
6047	GROW;
6048	while ((RAW != '>') && (ctxt->instate != XML_PARSER_EOF)) {
6049	    const xmlChar *check = CUR_PTR;
6050	    int type;
6051	    int def;
6052	    xmlChar *defaultValue = NULL;
6053
6054	    GROW;
6055            tree = NULL;
6056	    attrName = xmlParseName(ctxt);
6057	    if (attrName == NULL) {
6058		xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6059			       "ATTLIST: no name for Attribute\n");
6060		break;
6061	    }
6062	    GROW;
6063	    if (!IS_BLANK_CH(CUR)) {
6064		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6065		        "Space required after the attribute name\n");
6066		break;
6067	    }
6068	    SKIP_BLANKS;
6069
6070	    type = xmlParseAttributeType(ctxt, &tree);
6071	    if (type <= 0) {
6072	        break;
6073	    }
6074
6075	    GROW;
6076	    if (!IS_BLANK_CH(CUR)) {
6077		xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6078			       "Space required after the attribute type\n");
6079	        if (tree != NULL)
6080		    xmlFreeEnumeration(tree);
6081		break;
6082	    }
6083	    SKIP_BLANKS;
6084
6085	    def = xmlParseDefaultDecl(ctxt, &defaultValue);
6086	    if (def <= 0) {
6087                if (defaultValue != NULL)
6088		    xmlFree(defaultValue);
6089	        if (tree != NULL)
6090		    xmlFreeEnumeration(tree);
6091	        break;
6092	    }
6093	    if ((type != XML_ATTRIBUTE_CDATA) && (defaultValue != NULL))
6094	        xmlAttrNormalizeSpace(defaultValue, defaultValue);
6095
6096	    GROW;
6097            if (RAW != '>') {
6098		if (!IS_BLANK_CH(CUR)) {
6099		    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6100			"Space required after the attribute default value\n");
6101		    if (defaultValue != NULL)
6102			xmlFree(defaultValue);
6103		    if (tree != NULL)
6104			xmlFreeEnumeration(tree);
6105		    break;
6106		}
6107		SKIP_BLANKS;
6108	    }
6109	    if (check == CUR_PTR) {
6110		xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
6111		            "in xmlParseAttributeListDecl\n");
6112		if (defaultValue != NULL)
6113		    xmlFree(defaultValue);
6114	        if (tree != NULL)
6115		    xmlFreeEnumeration(tree);
6116		break;
6117	    }
6118	    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6119		(ctxt->sax->attributeDecl != NULL))
6120		ctxt->sax->attributeDecl(ctxt->userData, elemName, attrName,
6121	                        type, def, defaultValue, tree);
6122	    else if (tree != NULL)
6123		xmlFreeEnumeration(tree);
6124
6125	    if ((ctxt->sax2) && (defaultValue != NULL) &&
6126	        (def != XML_ATTRIBUTE_IMPLIED) &&
6127		(def != XML_ATTRIBUTE_REQUIRED)) {
6128		xmlAddDefAttrs(ctxt, elemName, attrName, defaultValue);
6129	    }
6130	    if (ctxt->sax2) {
6131		xmlAddSpecialAttr(ctxt, elemName, attrName, type);
6132	    }
6133	    if (defaultValue != NULL)
6134	        xmlFree(defaultValue);
6135	    GROW;
6136	}
6137	if (RAW == '>') {
6138	    if (input != ctxt->input) {
6139		xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6140    "Attribute list declaration doesn't start and stop in the same entity\n",
6141                                 NULL, NULL);
6142	    }
6143	    NEXT;
6144	}
6145    }
6146}
6147
6148/**
6149 * xmlParseElementMixedContentDecl:
6150 * @ctxt:  an XML parser context
6151 * @inputchk:  the input used for the current entity, needed for boundary checks
6152 *
6153 * parse the declaration for a Mixed Element content
6154 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6155 *
6156 * [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' |
6157 *                '(' S? '#PCDATA' S? ')'
6158 *
6159 * [ VC: Proper Group/PE Nesting ] applies to [51] too (see [49])
6160 *
6161 * [ VC: No Duplicate Types ]
6162 * The same name must not appear more than once in a single
6163 * mixed-content declaration.
6164 *
6165 * returns: the list of the xmlElementContentPtr describing the element choices
6166 */
6167xmlElementContentPtr
6168xmlParseElementMixedContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6169    xmlElementContentPtr ret = NULL, cur = NULL, n;
6170    const xmlChar *elem = NULL;
6171
6172    GROW;
6173    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6174	SKIP(7);
6175	SKIP_BLANKS;
6176	SHRINK;
6177	if (RAW == ')') {
6178	    if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
6179		xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6180"Element content declaration doesn't start and stop in the same entity\n",
6181                                 NULL, NULL);
6182	    }
6183	    NEXT;
6184	    ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6185	    if (ret == NULL)
6186	        return(NULL);
6187	    if (RAW == '*') {
6188		ret->ocur = XML_ELEMENT_CONTENT_MULT;
6189		NEXT;
6190	    }
6191	    return(ret);
6192	}
6193	if ((RAW == '(') || (RAW == '|')) {
6194	    ret = cur = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_PCDATA);
6195	    if (ret == NULL) return(NULL);
6196	}
6197	while ((RAW == '|') && (ctxt->instate != XML_PARSER_EOF)) {
6198	    NEXT;
6199	    if (elem == NULL) {
6200	        ret = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6201		if (ret == NULL) return(NULL);
6202		ret->c1 = cur;
6203		if (cur != NULL)
6204		    cur->parent = ret;
6205		cur = ret;
6206	    } else {
6207	        n = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6208		if (n == NULL) return(NULL);
6209		n->c1 = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6210		if (n->c1 != NULL)
6211		    n->c1->parent = n;
6212	        cur->c2 = n;
6213		if (n != NULL)
6214		    n->parent = cur;
6215		cur = n;
6216	    }
6217	    SKIP_BLANKS;
6218	    elem = xmlParseName(ctxt);
6219	    if (elem == NULL) {
6220		xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6221			"xmlParseElementMixedContentDecl : Name expected\n");
6222		xmlFreeDocElementContent(ctxt->myDoc, cur);
6223		return(NULL);
6224	    }
6225	    SKIP_BLANKS;
6226	    GROW;
6227	}
6228	if ((RAW == ')') && (NXT(1) == '*')) {
6229	    if (elem != NULL) {
6230		cur->c2 = xmlNewDocElementContent(ctxt->myDoc, elem,
6231		                               XML_ELEMENT_CONTENT_ELEMENT);
6232		if (cur->c2 != NULL)
6233		    cur->c2->parent = cur;
6234            }
6235            if (ret != NULL)
6236                ret->ocur = XML_ELEMENT_CONTENT_MULT;
6237	    if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
6238		xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6239"Element content declaration doesn't start and stop in the same entity\n",
6240				 NULL, NULL);
6241	    }
6242	    SKIP(2);
6243	} else {
6244	    xmlFreeDocElementContent(ctxt->myDoc, ret);
6245	    xmlFatalErr(ctxt, XML_ERR_MIXED_NOT_STARTED, NULL);
6246	    return(NULL);
6247	}
6248
6249    } else {
6250	xmlFatalErr(ctxt, XML_ERR_PCDATA_REQUIRED, NULL);
6251    }
6252    return(ret);
6253}
6254
6255/**
6256 * xmlParseElementChildrenContentDeclPriv:
6257 * @ctxt:  an XML parser context
6258 * @inputchk:  the input used for the current entity, needed for boundary checks
6259 * @depth: the level of recursion
6260 *
6261 * parse the declaration for a Mixed Element content
6262 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6263 *
6264 *
6265 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6266 *
6267 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6268 *
6269 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6270 *
6271 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6272 *
6273 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6274 * TODO Parameter-entity replacement text must be properly nested
6275 *	with parenthesized groups. That is to say, if either of the
6276 *	opening or closing parentheses in a choice, seq, or Mixed
6277 *	construct is contained in the replacement text for a parameter
6278 *	entity, both must be contained in the same replacement text. For
6279 *	interoperability, if a parameter-entity reference appears in a
6280 *	choice, seq, or Mixed construct, its replacement text should not
6281 *	be empty, and neither the first nor last non-blank character of
6282 *	the replacement text should be a connector (| or ,).
6283 *
6284 * Returns the tree of xmlElementContentPtr describing the element
6285 *          hierarchy.
6286 */
6287static xmlElementContentPtr
6288xmlParseElementChildrenContentDeclPriv(xmlParserCtxtPtr ctxt, int inputchk,
6289                                       int depth) {
6290    xmlElementContentPtr ret = NULL, cur = NULL, last = NULL, op = NULL;
6291    const xmlChar *elem;
6292    xmlChar type = 0;
6293
6294    if (((depth > 128) && ((ctxt->options & XML_PARSE_HUGE) == 0)) ||
6295        (depth >  2048)) {
6296        xmlFatalErrMsgInt(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED,
6297"xmlParseElementChildrenContentDecl : depth %d too deep, use XML_PARSE_HUGE\n",
6298                          depth);
6299	return(NULL);
6300    }
6301    SKIP_BLANKS;
6302    GROW;
6303    if (RAW == '(') {
6304	int inputid = ctxt->input->id;
6305
6306        /* Recurse on first child */
6307	NEXT;
6308	SKIP_BLANKS;
6309        cur = ret = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6310                                                           depth + 1);
6311	SKIP_BLANKS;
6312	GROW;
6313    } else {
6314	elem = xmlParseName(ctxt);
6315	if (elem == NULL) {
6316	    xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6317	    return(NULL);
6318	}
6319        cur = ret = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6320	if (cur == NULL) {
6321	    xmlErrMemory(ctxt, NULL);
6322	    return(NULL);
6323	}
6324	GROW;
6325	if (RAW == '?') {
6326	    cur->ocur = XML_ELEMENT_CONTENT_OPT;
6327	    NEXT;
6328	} else if (RAW == '*') {
6329	    cur->ocur = XML_ELEMENT_CONTENT_MULT;
6330	    NEXT;
6331	} else if (RAW == '+') {
6332	    cur->ocur = XML_ELEMENT_CONTENT_PLUS;
6333	    NEXT;
6334	} else {
6335	    cur->ocur = XML_ELEMENT_CONTENT_ONCE;
6336	}
6337	GROW;
6338    }
6339    SKIP_BLANKS;
6340    SHRINK;
6341    while ((RAW != ')') && (ctxt->instate != XML_PARSER_EOF)) {
6342        /*
6343	 * Each loop we parse one separator and one element.
6344	 */
6345        if (RAW == ',') {
6346	    if (type == 0) type = CUR;
6347
6348	    /*
6349	     * Detect "Name | Name , Name" error
6350	     */
6351	    else if (type != CUR) {
6352		xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6353		    "xmlParseElementChildrenContentDecl : '%c' expected\n",
6354		                  type);
6355		if ((last != NULL) && (last != ret))
6356		    xmlFreeDocElementContent(ctxt->myDoc, last);
6357		if (ret != NULL)
6358		    xmlFreeDocElementContent(ctxt->myDoc, ret);
6359		return(NULL);
6360	    }
6361	    NEXT;
6362
6363	    op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_SEQ);
6364	    if (op == NULL) {
6365		if ((last != NULL) && (last != ret))
6366		    xmlFreeDocElementContent(ctxt->myDoc, last);
6367	        xmlFreeDocElementContent(ctxt->myDoc, ret);
6368		return(NULL);
6369	    }
6370	    if (last == NULL) {
6371		op->c1 = ret;
6372		if (ret != NULL)
6373		    ret->parent = op;
6374		ret = cur = op;
6375	    } else {
6376	        cur->c2 = op;
6377		if (op != NULL)
6378		    op->parent = cur;
6379		op->c1 = last;
6380		if (last != NULL)
6381		    last->parent = op;
6382		cur =op;
6383		last = NULL;
6384	    }
6385	} else if (RAW == '|') {
6386	    if (type == 0) type = CUR;
6387
6388	    /*
6389	     * Detect "Name , Name | Name" error
6390	     */
6391	    else if (type != CUR) {
6392		xmlFatalErrMsgInt(ctxt, XML_ERR_SEPARATOR_REQUIRED,
6393		    "xmlParseElementChildrenContentDecl : '%c' expected\n",
6394				  type);
6395		if ((last != NULL) && (last != ret))
6396		    xmlFreeDocElementContent(ctxt->myDoc, last);
6397		if (ret != NULL)
6398		    xmlFreeDocElementContent(ctxt->myDoc, ret);
6399		return(NULL);
6400	    }
6401	    NEXT;
6402
6403	    op = xmlNewDocElementContent(ctxt->myDoc, NULL, XML_ELEMENT_CONTENT_OR);
6404	    if (op == NULL) {
6405		if ((last != NULL) && (last != ret))
6406		    xmlFreeDocElementContent(ctxt->myDoc, last);
6407		if (ret != NULL)
6408		    xmlFreeDocElementContent(ctxt->myDoc, ret);
6409		return(NULL);
6410	    }
6411	    if (last == NULL) {
6412		op->c1 = ret;
6413		if (ret != NULL)
6414		    ret->parent = op;
6415		ret = cur = op;
6416	    } else {
6417	        cur->c2 = op;
6418		if (op != NULL)
6419		    op->parent = cur;
6420		op->c1 = last;
6421		if (last != NULL)
6422		    last->parent = op;
6423		cur =op;
6424		last = NULL;
6425	    }
6426	} else {
6427	    xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_FINISHED, NULL);
6428	    if ((last != NULL) && (last != ret))
6429	        xmlFreeDocElementContent(ctxt->myDoc, last);
6430	    if (ret != NULL)
6431		xmlFreeDocElementContent(ctxt->myDoc, ret);
6432	    return(NULL);
6433	}
6434	GROW;
6435	SKIP_BLANKS;
6436	GROW;
6437	if (RAW == '(') {
6438	    int inputid = ctxt->input->id;
6439	    /* Recurse on second child */
6440	    NEXT;
6441	    SKIP_BLANKS;
6442	    last = xmlParseElementChildrenContentDeclPriv(ctxt, inputid,
6443                                                          depth + 1);
6444	    SKIP_BLANKS;
6445	} else {
6446	    elem = xmlParseName(ctxt);
6447	    if (elem == NULL) {
6448		xmlFatalErr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED, NULL);
6449		if (ret != NULL)
6450		    xmlFreeDocElementContent(ctxt->myDoc, ret);
6451		return(NULL);
6452	    }
6453	    last = xmlNewDocElementContent(ctxt->myDoc, elem, XML_ELEMENT_CONTENT_ELEMENT);
6454	    if (last == NULL) {
6455		if (ret != NULL)
6456		    xmlFreeDocElementContent(ctxt->myDoc, ret);
6457		return(NULL);
6458	    }
6459	    if (RAW == '?') {
6460		last->ocur = XML_ELEMENT_CONTENT_OPT;
6461		NEXT;
6462	    } else if (RAW == '*') {
6463		last->ocur = XML_ELEMENT_CONTENT_MULT;
6464		NEXT;
6465	    } else if (RAW == '+') {
6466		last->ocur = XML_ELEMENT_CONTENT_PLUS;
6467		NEXT;
6468	    } else {
6469		last->ocur = XML_ELEMENT_CONTENT_ONCE;
6470	    }
6471	}
6472	SKIP_BLANKS;
6473	GROW;
6474    }
6475    if ((cur != NULL) && (last != NULL)) {
6476        cur->c2 = last;
6477	if (last != NULL)
6478	    last->parent = cur;
6479    }
6480    if ((ctxt->validate) && (ctxt->input->id != inputchk)) {
6481	xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6482"Element content declaration doesn't start and stop in the same entity\n",
6483			 NULL, NULL);
6484    }
6485    NEXT;
6486    if (RAW == '?') {
6487	if (ret != NULL) {
6488	    if ((ret->ocur == XML_ELEMENT_CONTENT_PLUS) ||
6489	        (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6490	        ret->ocur = XML_ELEMENT_CONTENT_MULT;
6491	    else
6492	        ret->ocur = XML_ELEMENT_CONTENT_OPT;
6493	}
6494	NEXT;
6495    } else if (RAW == '*') {
6496	if (ret != NULL) {
6497	    ret->ocur = XML_ELEMENT_CONTENT_MULT;
6498	    cur = ret;
6499	    /*
6500	     * Some normalization:
6501	     * (a | b* | c?)* == (a | b | c)*
6502	     */
6503	    while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6504		if ((cur->c1 != NULL) &&
6505	            ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6506		     (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT)))
6507		    cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6508		if ((cur->c2 != NULL) &&
6509	            ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6510		     (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT)))
6511		    cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6512		cur = cur->c2;
6513	    }
6514	}
6515	NEXT;
6516    } else if (RAW == '+') {
6517	if (ret != NULL) {
6518	    int found = 0;
6519
6520	    if ((ret->ocur == XML_ELEMENT_CONTENT_OPT) ||
6521	        (ret->ocur == XML_ELEMENT_CONTENT_MULT))
6522	        ret->ocur = XML_ELEMENT_CONTENT_MULT;
6523	    else
6524	        ret->ocur = XML_ELEMENT_CONTENT_PLUS;
6525	    /*
6526	     * Some normalization:
6527	     * (a | b*)+ == (a | b)*
6528	     * (a | b?)+ == (a | b)*
6529	     */
6530	    while ((cur != NULL) && (cur->type == XML_ELEMENT_CONTENT_OR)) {
6531		if ((cur->c1 != NULL) &&
6532	            ((cur->c1->ocur == XML_ELEMENT_CONTENT_OPT) ||
6533		     (cur->c1->ocur == XML_ELEMENT_CONTENT_MULT))) {
6534		    cur->c1->ocur = XML_ELEMENT_CONTENT_ONCE;
6535		    found = 1;
6536		}
6537		if ((cur->c2 != NULL) &&
6538	            ((cur->c2->ocur == XML_ELEMENT_CONTENT_OPT) ||
6539		     (cur->c2->ocur == XML_ELEMENT_CONTENT_MULT))) {
6540		    cur->c2->ocur = XML_ELEMENT_CONTENT_ONCE;
6541		    found = 1;
6542		}
6543		cur = cur->c2;
6544	    }
6545	    if (found)
6546		ret->ocur = XML_ELEMENT_CONTENT_MULT;
6547	}
6548	NEXT;
6549    }
6550    return(ret);
6551}
6552
6553/**
6554 * xmlParseElementChildrenContentDecl:
6555 * @ctxt:  an XML parser context
6556 * @inputchk:  the input used for the current entity, needed for boundary checks
6557 *
6558 * parse the declaration for a Mixed Element content
6559 * The leading '(' and spaces have been skipped in xmlParseElementContentDecl
6560 *
6561 * [47] children ::= (choice | seq) ('?' | '*' | '+')?
6562 *
6563 * [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
6564 *
6565 * [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
6566 *
6567 * [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
6568 *
6569 * [ VC: Proper Group/PE Nesting ] applies to [49] and [50]
6570 * TODO Parameter-entity replacement text must be properly nested
6571 *	with parenthesized groups. That is to say, if either of the
6572 *	opening or closing parentheses in a choice, seq, or Mixed
6573 *	construct is contained in the replacement text for a parameter
6574 *	entity, both must be contained in the same replacement text. For
6575 *	interoperability, if a parameter-entity reference appears in a
6576 *	choice, seq, or Mixed construct, its replacement text should not
6577 *	be empty, and neither the first nor last non-blank character of
6578 *	the replacement text should be a connector (| or ,).
6579 *
6580 * Returns the tree of xmlElementContentPtr describing the element
6581 *          hierarchy.
6582 */
6583xmlElementContentPtr
6584xmlParseElementChildrenContentDecl(xmlParserCtxtPtr ctxt, int inputchk) {
6585    /* stub left for API/ABI compat */
6586    return(xmlParseElementChildrenContentDeclPriv(ctxt, inputchk, 1));
6587}
6588
6589/**
6590 * xmlParseElementContentDecl:
6591 * @ctxt:  an XML parser context
6592 * @name:  the name of the element being defined.
6593 * @result:  the Element Content pointer will be stored here if any
6594 *
6595 * parse the declaration for an Element content either Mixed or Children,
6596 * the cases EMPTY and ANY are handled directly in xmlParseElementDecl
6597 *
6598 * [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
6599 *
6600 * returns: the type of element content XML_ELEMENT_TYPE_xxx
6601 */
6602
6603int
6604xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name,
6605                           xmlElementContentPtr *result) {
6606
6607    xmlElementContentPtr tree = NULL;
6608    int inputid = ctxt->input->id;
6609    int res;
6610
6611    *result = NULL;
6612
6613    if (RAW != '(') {
6614	xmlFatalErrMsgStr(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6615		"xmlParseElementContentDecl : %s '(' expected\n", name);
6616	return(-1);
6617    }
6618    NEXT;
6619    GROW;
6620    if (ctxt->instate == XML_PARSER_EOF)
6621        return(-1);
6622    SKIP_BLANKS;
6623    if (CMP7(CUR_PTR, '#', 'P', 'C', 'D', 'A', 'T', 'A')) {
6624        tree = xmlParseElementMixedContentDecl(ctxt, inputid);
6625	res = XML_ELEMENT_TYPE_MIXED;
6626    } else {
6627        tree = xmlParseElementChildrenContentDeclPriv(ctxt, inputid, 1);
6628	res = XML_ELEMENT_TYPE_ELEMENT;
6629    }
6630    SKIP_BLANKS;
6631    *result = tree;
6632    return(res);
6633}
6634
6635/**
6636 * xmlParseElementDecl:
6637 * @ctxt:  an XML parser context
6638 *
6639 * parse an Element declaration.
6640 *
6641 * [45] elementdecl ::= '<!ELEMENT' S Name S contentspec S? '>'
6642 *
6643 * [ VC: Unique Element Type Declaration ]
6644 * No element type may be declared more than once
6645 *
6646 * Returns the type of the element, or -1 in case of error
6647 */
6648int
6649xmlParseElementDecl(xmlParserCtxtPtr ctxt) {
6650    const xmlChar *name;
6651    int ret = -1;
6652    xmlElementContentPtr content  = NULL;
6653
6654    /* GROW; done in the caller */
6655    if (CMP9(CUR_PTR, '<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T')) {
6656	xmlParserInputPtr input = ctxt->input;
6657
6658	SKIP(9);
6659	if (!IS_BLANK_CH(CUR)) {
6660	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6661		           "Space required after 'ELEMENT'\n");
6662	}
6663        SKIP_BLANKS;
6664        name = xmlParseName(ctxt);
6665	if (name == NULL) {
6666	    xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
6667			   "xmlParseElementDecl: no name for Element\n");
6668	    return(-1);
6669	}
6670	while ((RAW == 0) && (ctxt->inputNr > 1))
6671	    xmlPopInput(ctxt);
6672	if (!IS_BLANK_CH(CUR)) {
6673	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
6674			   "Space required after the element name\n");
6675	}
6676        SKIP_BLANKS;
6677	if (CMP5(CUR_PTR, 'E', 'M', 'P', 'T', 'Y')) {
6678	    SKIP(5);
6679	    /*
6680	     * Element must always be empty.
6681	     */
6682	    ret = XML_ELEMENT_TYPE_EMPTY;
6683	} else if ((RAW == 'A') && (NXT(1) == 'N') &&
6684	           (NXT(2) == 'Y')) {
6685	    SKIP(3);
6686	    /*
6687	     * Element is a generic container.
6688	     */
6689	    ret = XML_ELEMENT_TYPE_ANY;
6690	} else if (RAW == '(') {
6691	    ret = xmlParseElementContentDecl(ctxt, name, &content);
6692	} else {
6693	    /*
6694	     * [ WFC: PEs in Internal Subset ] error handling.
6695	     */
6696	    if ((RAW == '%') && (ctxt->external == 0) &&
6697	        (ctxt->inputNr == 1)) {
6698		xmlFatalErrMsg(ctxt, XML_ERR_PEREF_IN_INT_SUBSET,
6699	  "PEReference: forbidden within markup decl in internal subset\n");
6700	    } else {
6701		xmlFatalErrMsg(ctxt, XML_ERR_ELEMCONTENT_NOT_STARTED,
6702		      "xmlParseElementDecl: 'EMPTY', 'ANY' or '(' expected\n");
6703            }
6704	    return(-1);
6705	}
6706
6707	SKIP_BLANKS;
6708	/*
6709	 * Pop-up of finished entities.
6710	 */
6711	while ((RAW == 0) && (ctxt->inputNr > 1))
6712	    xmlPopInput(ctxt);
6713	SKIP_BLANKS;
6714
6715	if (RAW != '>') {
6716	    xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
6717	    if (content != NULL) {
6718		xmlFreeDocElementContent(ctxt->myDoc, content);
6719	    }
6720	} else {
6721	    if (input != ctxt->input) {
6722		xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_BOUNDARY,
6723    "Element declaration doesn't start and stop in the same entity\n");
6724	    }
6725
6726	    NEXT;
6727	    if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
6728		(ctxt->sax->elementDecl != NULL)) {
6729		if (content != NULL)
6730		    content->parent = NULL;
6731	        ctxt->sax->elementDecl(ctxt->userData, name, ret,
6732		                       content);
6733		if ((content != NULL) && (content->parent == NULL)) {
6734		    /*
6735		     * this is a trick: if xmlAddElementDecl is called,
6736		     * instead of copying the full tree it is plugged directly
6737		     * if called from the parser. Avoid duplicating the
6738		     * interfaces or change the API/ABI
6739		     */
6740		    xmlFreeDocElementContent(ctxt->myDoc, content);
6741		}
6742	    } else if (content != NULL) {
6743		xmlFreeDocElementContent(ctxt->myDoc, content);
6744	    }
6745	}
6746    }
6747    return(ret);
6748}
6749
6750/**
6751 * xmlParseConditionalSections
6752 * @ctxt:  an XML parser context
6753 *
6754 * [61] conditionalSect ::= includeSect | ignoreSect
6755 * [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
6756 * [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
6757 * [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
6758 * [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
6759 */
6760
6761static void
6762xmlParseConditionalSections(xmlParserCtxtPtr ctxt) {
6763    int id = ctxt->input->id;
6764
6765    SKIP(3);
6766    SKIP_BLANKS;
6767    if (CMP7(CUR_PTR, 'I', 'N', 'C', 'L', 'U', 'D', 'E')) {
6768	SKIP(7);
6769	SKIP_BLANKS;
6770	if (RAW != '[') {
6771	    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6772	} else {
6773	    if (ctxt->input->id != id) {
6774		xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6775	    "All markup of the conditional section is not in the same entity\n",
6776				     NULL, NULL);
6777	    }
6778	    NEXT;
6779	}
6780	if (xmlParserDebugEntities) {
6781	    if ((ctxt->input != NULL) && (ctxt->input->filename))
6782		xmlGenericError(xmlGenericErrorContext,
6783			"%s(%d): ", ctxt->input->filename,
6784			ctxt->input->line);
6785	    xmlGenericError(xmlGenericErrorContext,
6786		    "Entering INCLUDE Conditional Section\n");
6787	}
6788
6789	while (((RAW != 0) && ((RAW != ']') || (NXT(1) != ']') ||
6790	        (NXT(2) != '>'))) && (ctxt->instate != XML_PARSER_EOF)) {
6791	    const xmlChar *check = CUR_PTR;
6792	    unsigned int cons = ctxt->input->consumed;
6793
6794	    if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6795		xmlParseConditionalSections(ctxt);
6796	    } else if (IS_BLANK_CH(CUR)) {
6797		NEXT;
6798	    } else if (RAW == '%') {
6799		xmlParsePEReference(ctxt);
6800	    } else
6801		xmlParseMarkupDecl(ctxt);
6802
6803	    /*
6804	     * Pop-up of finished entities.
6805	     */
6806	    while ((RAW == 0) && (ctxt->inputNr > 1))
6807		xmlPopInput(ctxt);
6808
6809	    if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
6810		xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
6811		break;
6812	    }
6813	}
6814	if (xmlParserDebugEntities) {
6815	    if ((ctxt->input != NULL) && (ctxt->input->filename))
6816		xmlGenericError(xmlGenericErrorContext,
6817			"%s(%d): ", ctxt->input->filename,
6818			ctxt->input->line);
6819	    xmlGenericError(xmlGenericErrorContext,
6820		    "Leaving INCLUDE Conditional Section\n");
6821	}
6822
6823    } else if (CMP6(CUR_PTR, 'I', 'G', 'N', 'O', 'R', 'E')) {
6824	int state;
6825	xmlParserInputState instate;
6826	int depth = 0;
6827
6828	SKIP(6);
6829	SKIP_BLANKS;
6830	if (RAW != '[') {
6831	    xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID, NULL);
6832	} else {
6833	    if (ctxt->input->id != id) {
6834		xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6835	    "All markup of the conditional section is not in the same entity\n",
6836				     NULL, NULL);
6837	    }
6838	    NEXT;
6839	}
6840	if (xmlParserDebugEntities) {
6841	    if ((ctxt->input != NULL) && (ctxt->input->filename))
6842		xmlGenericError(xmlGenericErrorContext,
6843			"%s(%d): ", ctxt->input->filename,
6844			ctxt->input->line);
6845	    xmlGenericError(xmlGenericErrorContext,
6846		    "Entering IGNORE Conditional Section\n");
6847	}
6848
6849	/*
6850	 * Parse up to the end of the conditional section
6851	 * But disable SAX event generating DTD building in the meantime
6852	 */
6853	state = ctxt->disableSAX;
6854	instate = ctxt->instate;
6855	if (ctxt->recovery == 0) ctxt->disableSAX = 1;
6856	ctxt->instate = XML_PARSER_IGNORE;
6857
6858	while (((depth >= 0) && (RAW != 0)) &&
6859               (ctxt->instate != XML_PARSER_EOF)) {
6860	  if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6861	    depth++;
6862	    SKIP(3);
6863	    continue;
6864	  }
6865	  if ((RAW == ']') && (NXT(1) == ']') && (NXT(2) == '>')) {
6866	    if (--depth >= 0) SKIP(3);
6867	    continue;
6868	  }
6869	  NEXT;
6870	  continue;
6871	}
6872
6873	ctxt->disableSAX = state;
6874	ctxt->instate = instate;
6875
6876	if (xmlParserDebugEntities) {
6877	    if ((ctxt->input != NULL) && (ctxt->input->filename))
6878		xmlGenericError(xmlGenericErrorContext,
6879			"%s(%d): ", ctxt->input->filename,
6880			ctxt->input->line);
6881	    xmlGenericError(xmlGenericErrorContext,
6882		    "Leaving IGNORE Conditional Section\n");
6883	}
6884
6885    } else {
6886	xmlFatalErr(ctxt, XML_ERR_CONDSEC_INVALID_KEYWORD, NULL);
6887    }
6888
6889    if (RAW == 0)
6890        SHRINK;
6891
6892    if (RAW == 0) {
6893	xmlFatalErr(ctxt, XML_ERR_CONDSEC_NOT_FINISHED, NULL);
6894    } else {
6895	if (ctxt->input->id != id) {
6896	    xmlValidityError(ctxt, XML_ERR_ENTITY_BOUNDARY,
6897	"All markup of the conditional section is not in the same entity\n",
6898				 NULL, NULL);
6899	}
6900        SKIP(3);
6901    }
6902}
6903
6904/**
6905 * xmlParseMarkupDecl:
6906 * @ctxt:  an XML parser context
6907 *
6908 * parse Markup declarations
6909 *
6910 * [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl |
6911 *                     NotationDecl | PI | Comment
6912 *
6913 * [ VC: Proper Declaration/PE Nesting ]
6914 * Parameter-entity replacement text must be properly nested with
6915 * markup declarations. That is to say, if either the first character
6916 * or the last character of a markup declaration (markupdecl above) is
6917 * contained in the replacement text for a parameter-entity reference,
6918 * both must be contained in the same replacement text.
6919 *
6920 * [ WFC: PEs in Internal Subset ]
6921 * In the internal DTD subset, parameter-entity references can occur
6922 * only where markup declarations can occur, not within markup declarations.
6923 * (This does not apply to references that occur in external parameter
6924 * entities or to the external subset.)
6925 */
6926void
6927xmlParseMarkupDecl(xmlParserCtxtPtr ctxt) {
6928    GROW;
6929    if (CUR == '<') {
6930        if (NXT(1) == '!') {
6931	    switch (NXT(2)) {
6932	        case 'E':
6933		    if (NXT(3) == 'L')
6934			xmlParseElementDecl(ctxt);
6935		    else if (NXT(3) == 'N')
6936			xmlParseEntityDecl(ctxt);
6937		    break;
6938	        case 'A':
6939		    xmlParseAttributeListDecl(ctxt);
6940		    break;
6941	        case 'N':
6942		    xmlParseNotationDecl(ctxt);
6943		    break;
6944	        case '-':
6945		    xmlParseComment(ctxt);
6946		    break;
6947		default:
6948		    /* there is an error but it will be detected later */
6949		    break;
6950	    }
6951	} else if (NXT(1) == '?') {
6952	    xmlParsePI(ctxt);
6953	}
6954    }
6955    /*
6956     * This is only for internal subset. On external entities,
6957     * the replacement is done before parsing stage
6958     */
6959    if ((ctxt->external == 0) && (ctxt->inputNr == 1))
6960	xmlParsePEReference(ctxt);
6961
6962    /*
6963     * Conditional sections are allowed from entities included
6964     * by PE References in the internal subset.
6965     */
6966    if ((ctxt->external == 0) && (ctxt->inputNr > 1)) {
6967        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
6968	    xmlParseConditionalSections(ctxt);
6969	}
6970    }
6971
6972    ctxt->instate = XML_PARSER_DTD;
6973}
6974
6975/**
6976 * xmlParseTextDecl:
6977 * @ctxt:  an XML parser context
6978 *
6979 * parse an XML declaration header for external entities
6980 *
6981 * [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
6982 */
6983
6984void
6985xmlParseTextDecl(xmlParserCtxtPtr ctxt) {
6986    xmlChar *version;
6987    const xmlChar *encoding;
6988
6989    /*
6990     * We know that '<?xml' is here.
6991     */
6992    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
6993	SKIP(5);
6994    } else {
6995	xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_STARTED, NULL);
6996	return;
6997    }
6998
6999    if (!IS_BLANK_CH(CUR)) {
7000	xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
7001		       "Space needed after '<?xml'\n");
7002    }
7003    SKIP_BLANKS;
7004
7005    /*
7006     * We may have the VersionInfo here.
7007     */
7008    version = xmlParseVersionInfo(ctxt);
7009    if (version == NULL)
7010	version = xmlCharStrdup(XML_DEFAULT_VERSION);
7011    else {
7012	if (!IS_BLANK_CH(CUR)) {
7013	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
7014		           "Space needed here\n");
7015	}
7016    }
7017    ctxt->input->version = version;
7018
7019    /*
7020     * We must have the encoding declaration
7021     */
7022    encoding = xmlParseEncodingDecl(ctxt);
7023    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7024	/*
7025	 * The XML REC instructs us to stop parsing right here
7026	 */
7027        return;
7028    }
7029    if ((encoding == NULL) && (ctxt->errNo == XML_ERR_OK)) {
7030	xmlFatalErrMsg(ctxt, XML_ERR_MISSING_ENCODING,
7031		       "Missing encoding in text declaration\n");
7032    }
7033
7034    SKIP_BLANKS;
7035    if ((RAW == '?') && (NXT(1) == '>')) {
7036        SKIP(2);
7037    } else if (RAW == '>') {
7038        /* Deprecated old WD ... */
7039	xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
7040	NEXT;
7041    } else {
7042	xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
7043	MOVETO_ENDTAG(CUR_PTR);
7044	NEXT;
7045    }
7046}
7047
7048/**
7049 * xmlParseExternalSubset:
7050 * @ctxt:  an XML parser context
7051 * @ExternalID: the external identifier
7052 * @SystemID: the system identifier (or URL)
7053 *
7054 * parse Markup declarations from an external subset
7055 *
7056 * [30] extSubset ::= textDecl? extSubsetDecl
7057 *
7058 * [31] extSubsetDecl ::= (markupdecl | conditionalSect | PEReference | S) *
7059 */
7060void
7061xmlParseExternalSubset(xmlParserCtxtPtr ctxt, const xmlChar *ExternalID,
7062                       const xmlChar *SystemID) {
7063    xmlDetectSAX2(ctxt);
7064    GROW;
7065
7066    if ((ctxt->encoding == NULL) &&
7067        (ctxt->input->end - ctxt->input->cur >= 4)) {
7068        xmlChar start[4];
7069	xmlCharEncoding enc;
7070
7071	start[0] = RAW;
7072	start[1] = NXT(1);
7073	start[2] = NXT(2);
7074	start[3] = NXT(3);
7075	enc = xmlDetectCharEncoding(start, 4);
7076	if (enc != XML_CHAR_ENCODING_NONE)
7077	    xmlSwitchEncoding(ctxt, enc);
7078    }
7079
7080    if (CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) {
7081	xmlParseTextDecl(ctxt);
7082	if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
7083	    /*
7084	     * The XML REC instructs us to stop parsing right here
7085	     */
7086	    ctxt->instate = XML_PARSER_EOF;
7087	    return;
7088	}
7089    }
7090    if (ctxt->myDoc == NULL) {
7091        ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
7092	if (ctxt->myDoc == NULL) {
7093	    xmlErrMemory(ctxt, "New Doc failed");
7094	    return;
7095	}
7096	ctxt->myDoc->properties = XML_DOC_INTERNAL;
7097    }
7098    if ((ctxt->myDoc != NULL) && (ctxt->myDoc->intSubset == NULL))
7099        xmlCreateIntSubset(ctxt->myDoc, NULL, ExternalID, SystemID);
7100
7101    ctxt->instate = XML_PARSER_DTD;
7102    ctxt->external = 1;
7103    while (((RAW == '<') && (NXT(1) == '?')) ||
7104           ((RAW == '<') && (NXT(1) == '!')) ||
7105	   (RAW == '%') || IS_BLANK_CH(CUR)) {
7106	const xmlChar *check = CUR_PTR;
7107	unsigned int cons = ctxt->input->consumed;
7108
7109	GROW;
7110        if ((RAW == '<') && (NXT(1) == '!') && (NXT(2) == '[')) {
7111	    xmlParseConditionalSections(ctxt);
7112	} else if (IS_BLANK_CH(CUR)) {
7113	    NEXT;
7114	} else if (RAW == '%') {
7115            xmlParsePEReference(ctxt);
7116	} else
7117	    xmlParseMarkupDecl(ctxt);
7118
7119	/*
7120	 * Pop-up of finished entities.
7121	 */
7122	while ((RAW == 0) && (ctxt->inputNr > 1))
7123	    xmlPopInput(ctxt);
7124
7125	if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
7126	    xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7127	    break;
7128	}
7129    }
7130
7131    if (RAW != 0) {
7132	xmlFatalErr(ctxt, XML_ERR_EXT_SUBSET_NOT_FINISHED, NULL);
7133    }
7134
7135}
7136
7137/**
7138 * xmlParseReference:
7139 * @ctxt:  an XML parser context
7140 *
7141 * parse and handle entity references in content, depending on the SAX
7142 * interface, this may end-up in a call to character() if this is a
7143 * CharRef, a predefined entity, if there is no reference() callback.
7144 * or if the parser was asked to switch to that mode.
7145 *
7146 * [67] Reference ::= EntityRef | CharRef
7147 */
7148void
7149xmlParseReference(xmlParserCtxtPtr ctxt) {
7150    xmlEntityPtr ent;
7151    xmlChar *val;
7152    int was_checked;
7153    xmlNodePtr list = NULL;
7154    xmlParserErrors ret = XML_ERR_OK;
7155
7156
7157    if (RAW != '&')
7158        return;
7159
7160    /*
7161     * Simple case of a CharRef
7162     */
7163    if (NXT(1) == '#') {
7164	int i = 0;
7165	xmlChar out[10];
7166	int hex = NXT(2);
7167	int value = xmlParseCharRef(ctxt);
7168
7169	if (value == 0)
7170	    return;
7171	if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
7172	    /*
7173	     * So we are using non-UTF-8 buffers
7174	     * Check that the char fit on 8bits, if not
7175	     * generate a CharRef.
7176	     */
7177	    if (value <= 0xFF) {
7178		out[0] = value;
7179		out[1] = 0;
7180		if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7181		    (!ctxt->disableSAX))
7182		    ctxt->sax->characters(ctxt->userData, out, 1);
7183	    } else {
7184		if ((hex == 'x') || (hex == 'X'))
7185		    snprintf((char *)out, sizeof(out), "#x%X", value);
7186		else
7187		    snprintf((char *)out, sizeof(out), "#%d", value);
7188		if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7189		    (!ctxt->disableSAX))
7190		    ctxt->sax->reference(ctxt->userData, out);
7191	    }
7192	} else {
7193	    /*
7194	     * Just encode the value in UTF-8
7195	     */
7196	    COPY_BUF(0 ,out, i, value);
7197	    out[i] = 0;
7198	    if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7199		(!ctxt->disableSAX))
7200		ctxt->sax->characters(ctxt->userData, out, i);
7201	}
7202	return;
7203    }
7204
7205    /*
7206     * We are seeing an entity reference
7207     */
7208    ent = xmlParseEntityRef(ctxt);
7209    if (ent == NULL) return;
7210    if (!ctxt->wellFormed)
7211	return;
7212    was_checked = ent->checked;
7213
7214    /* special case of predefined entities */
7215    if ((ent->name == NULL) ||
7216        (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY)) {
7217	val = ent->content;
7218	if (val == NULL) return;
7219	/*
7220	 * inline the entity.
7221	 */
7222	if ((ctxt->sax != NULL) && (ctxt->sax->characters != NULL) &&
7223	    (!ctxt->disableSAX))
7224	    ctxt->sax->characters(ctxt->userData, val, xmlStrlen(val));
7225	return;
7226    }
7227
7228    /*
7229     * The first reference to the entity trigger a parsing phase
7230     * where the ent->children is filled with the result from
7231     * the parsing.
7232     * Note: external parsed entities will not be loaded, it is not
7233     * required for a non-validating parser, unless the parsing option
7234     * of validating, or substituting entities were given. Doing so is
7235     * far more secure as the parser will only process data coming from
7236     * the document entity by default.
7237     */
7238    if (((ent->checked == 0) ||
7239         ((ent->children == NULL) && (ctxt->options & XML_PARSE_NOENT))) &&
7240        ((ent->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY) ||
7241         (ctxt->options & (XML_PARSE_NOENT | XML_PARSE_DTDVALID)))) {
7242	unsigned long oldnbent = ctxt->nbentities;
7243
7244	/*
7245	 * This is a bit hackish but this seems the best
7246	 * way to make sure both SAX and DOM entity support
7247	 * behaves okay.
7248	 */
7249	void *user_data;
7250	if (ctxt->userData == ctxt)
7251	    user_data = NULL;
7252	else
7253	    user_data = ctxt->userData;
7254
7255	/*
7256	 * Check that this entity is well formed
7257	 * 4.3.2: An internal general parsed entity is well-formed
7258	 * if its replacement text matches the production labeled
7259	 * content.
7260	 */
7261	if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7262	    ctxt->depth++;
7263	    ret = xmlParseBalancedChunkMemoryInternal(ctxt, ent->content,
7264	                                              user_data, &list);
7265	    ctxt->depth--;
7266
7267	} else if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7268	    ctxt->depth++;
7269	    ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt, ctxt->sax,
7270	                                   user_data, ctxt->depth, ent->URI,
7271					   ent->ExternalID, &list);
7272	    ctxt->depth--;
7273	} else {
7274	    ret = XML_ERR_ENTITY_PE_INTERNAL;
7275	    xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7276			 "invalid entity type found\n", NULL);
7277	}
7278
7279	/*
7280	 * Store the number of entities needing parsing for this entity
7281	 * content and do checkings
7282	 */
7283	ent->checked = (ctxt->nbentities - oldnbent + 1) * 2;
7284	if ((ent->content != NULL) && (xmlStrchr(ent->content, '<')))
7285	    ent->checked |= 1;
7286	if (ret == XML_ERR_ENTITY_LOOP) {
7287	    xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7288	    xmlFreeNodeList(list);
7289	    return;
7290	}
7291	if (xmlParserEntityCheck(ctxt, 0, ent, 0)) {
7292	    xmlFreeNodeList(list);
7293	    return;
7294	}
7295
7296	if ((ret == XML_ERR_OK) && (list != NULL)) {
7297	    if (((ent->etype == XML_INTERNAL_GENERAL_ENTITY) ||
7298	     (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY))&&
7299		(ent->children == NULL)) {
7300		ent->children = list;
7301		if (ctxt->replaceEntities) {
7302		    /*
7303		     * Prune it directly in the generated document
7304		     * except for single text nodes.
7305		     */
7306		    if (((list->type == XML_TEXT_NODE) &&
7307			 (list->next == NULL)) ||
7308			(ctxt->parseMode == XML_PARSE_READER)) {
7309			list->parent = (xmlNodePtr) ent;
7310			list = NULL;
7311			ent->owner = 1;
7312		    } else {
7313			ent->owner = 0;
7314			while (list != NULL) {
7315			    list->parent = (xmlNodePtr) ctxt->node;
7316			    list->doc = ctxt->myDoc;
7317			    if (list->next == NULL)
7318				ent->last = list;
7319			    list = list->next;
7320			}
7321			list = ent->children;
7322#ifdef LIBXML_LEGACY_ENABLED
7323			if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7324			  xmlAddEntityReference(ent, list, NULL);
7325#endif /* LIBXML_LEGACY_ENABLED */
7326		    }
7327		} else {
7328		    ent->owner = 1;
7329		    while (list != NULL) {
7330			list->parent = (xmlNodePtr) ent;
7331			xmlSetTreeDoc(list, ent->doc);
7332			if (list->next == NULL)
7333			    ent->last = list;
7334			list = list->next;
7335		    }
7336		}
7337	    } else {
7338		xmlFreeNodeList(list);
7339		list = NULL;
7340	    }
7341	} else if ((ret != XML_ERR_OK) &&
7342		   (ret != XML_WAR_UNDECLARED_ENTITY)) {
7343	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7344		     "Entity '%s' failed to parse\n", ent->name);
7345	    xmlParserEntityCheck(ctxt, 0, ent, 0);
7346	} else if (list != NULL) {
7347	    xmlFreeNodeList(list);
7348	    list = NULL;
7349	}
7350	if (ent->checked == 0)
7351	    ent->checked = 2;
7352    } else if (ent->checked != 1) {
7353	ctxt->nbentities += ent->checked / 2;
7354    }
7355
7356    /*
7357     * Now that the entity content has been gathered
7358     * provide it to the application, this can take different forms based
7359     * on the parsing modes.
7360     */
7361    if (ent->children == NULL) {
7362	/*
7363	 * Probably running in SAX mode and the callbacks don't
7364	 * build the entity content. So unless we already went
7365	 * though parsing for first checking go though the entity
7366	 * content to generate callbacks associated to the entity
7367	 */
7368	if (was_checked != 0) {
7369	    void *user_data;
7370	    /*
7371	     * This is a bit hackish but this seems the best
7372	     * way to make sure both SAX and DOM entity support
7373	     * behaves okay.
7374	     */
7375	    if (ctxt->userData == ctxt)
7376		user_data = NULL;
7377	    else
7378		user_data = ctxt->userData;
7379
7380	    if (ent->etype == XML_INTERNAL_GENERAL_ENTITY) {
7381		ctxt->depth++;
7382		ret = xmlParseBalancedChunkMemoryInternal(ctxt,
7383				   ent->content, user_data, NULL);
7384		ctxt->depth--;
7385	    } else if (ent->etype ==
7386		       XML_EXTERNAL_GENERAL_PARSED_ENTITY) {
7387		ctxt->depth++;
7388		ret = xmlParseExternalEntityPrivate(ctxt->myDoc, ctxt,
7389			   ctxt->sax, user_data, ctxt->depth,
7390			   ent->URI, ent->ExternalID, NULL);
7391		ctxt->depth--;
7392	    } else {
7393		ret = XML_ERR_ENTITY_PE_INTERNAL;
7394		xmlErrMsgStr(ctxt, XML_ERR_INTERNAL_ERROR,
7395			     "invalid entity type found\n", NULL);
7396	    }
7397	    if (ret == XML_ERR_ENTITY_LOOP) {
7398		xmlFatalErr(ctxt, XML_ERR_ENTITY_LOOP, NULL);
7399		return;
7400	    }
7401	}
7402	if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7403	    (ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7404	    /*
7405	     * Entity reference callback comes second, it's somewhat
7406	     * superfluous but a compatibility to historical behaviour
7407	     */
7408	    ctxt->sax->reference(ctxt->userData, ent->name);
7409	}
7410	return;
7411    }
7412
7413    /*
7414     * If we didn't get any children for the entity being built
7415     */
7416    if ((ctxt->sax != NULL) && (ctxt->sax->reference != NULL) &&
7417	(ctxt->replaceEntities == 0) && (!ctxt->disableSAX)) {
7418	/*
7419	 * Create a node.
7420	 */
7421	ctxt->sax->reference(ctxt->userData, ent->name);
7422	return;
7423    }
7424
7425    if ((ctxt->replaceEntities) || (ent->children == NULL))  {
7426	/*
7427	 * There is a problem on the handling of _private for entities
7428	 * (bug 155816): Should we copy the content of the field from
7429	 * the entity (possibly overwriting some value set by the user
7430	 * when a copy is created), should we leave it alone, or should
7431	 * we try to take care of different situations?  The problem
7432	 * is exacerbated by the usage of this field by the xmlReader.
7433	 * To fix this bug, we look at _private on the created node
7434	 * and, if it's NULL, we copy in whatever was in the entity.
7435	 * If it's not NULL we leave it alone.  This is somewhat of a
7436	 * hack - maybe we should have further tests to determine
7437	 * what to do.
7438	 */
7439	if ((ctxt->node != NULL) && (ent->children != NULL)) {
7440	    /*
7441	     * Seems we are generating the DOM content, do
7442	     * a simple tree copy for all references except the first
7443	     * In the first occurrence list contains the replacement.
7444	     */
7445	    if (((list == NULL) && (ent->owner == 0)) ||
7446		(ctxt->parseMode == XML_PARSE_READER)) {
7447		xmlNodePtr nw = NULL, cur, firstChild = NULL;
7448
7449		/*
7450		 * We are copying here, make sure there is no abuse
7451		 */
7452		ctxt->sizeentcopy += ent->length + 5;
7453		if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
7454		    return;
7455
7456		/*
7457		 * when operating on a reader, the entities definitions
7458		 * are always owning the entities subtree.
7459		if (ctxt->parseMode == XML_PARSE_READER)
7460		    ent->owner = 1;
7461		 */
7462
7463		cur = ent->children;
7464		while (cur != NULL) {
7465		    nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7466		    if (nw != NULL) {
7467			if (nw->_private == NULL)
7468			    nw->_private = cur->_private;
7469			if (firstChild == NULL){
7470			    firstChild = nw;
7471			}
7472			nw = xmlAddChild(ctxt->node, nw);
7473		    }
7474		    if (cur == ent->last) {
7475			/*
7476			 * needed to detect some strange empty
7477			 * node cases in the reader tests
7478			 */
7479			if ((ctxt->parseMode == XML_PARSE_READER) &&
7480			    (nw != NULL) &&
7481			    (nw->type == XML_ELEMENT_NODE) &&
7482			    (nw->children == NULL))
7483			    nw->extra = 1;
7484
7485			break;
7486		    }
7487		    cur = cur->next;
7488		}
7489#ifdef LIBXML_LEGACY_ENABLED
7490		if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7491		  xmlAddEntityReference(ent, firstChild, nw);
7492#endif /* LIBXML_LEGACY_ENABLED */
7493	    } else if ((list == NULL) || (ctxt->inputNr > 0)) {
7494		xmlNodePtr nw = NULL, cur, next, last,
7495			   firstChild = NULL;
7496
7497		/*
7498		 * We are copying here, make sure there is no abuse
7499		 */
7500		ctxt->sizeentcopy += ent->length + 5;
7501		if (xmlParserEntityCheck(ctxt, 0, ent, ctxt->sizeentcopy))
7502		    return;
7503
7504		/*
7505		 * Copy the entity child list and make it the new
7506		 * entity child list. The goal is to make sure any
7507		 * ID or REF referenced will be the one from the
7508		 * document content and not the entity copy.
7509		 */
7510		cur = ent->children;
7511		ent->children = NULL;
7512		last = ent->last;
7513		ent->last = NULL;
7514		while (cur != NULL) {
7515		    next = cur->next;
7516		    cur->next = NULL;
7517		    cur->parent = NULL;
7518		    nw = xmlDocCopyNode(cur, ctxt->myDoc, 1);
7519		    if (nw != NULL) {
7520			if (nw->_private == NULL)
7521			    nw->_private = cur->_private;
7522			if (firstChild == NULL){
7523			    firstChild = cur;
7524			}
7525			xmlAddChild((xmlNodePtr) ent, nw);
7526			xmlAddChild(ctxt->node, cur);
7527		    }
7528		    if (cur == last)
7529			break;
7530		    cur = next;
7531		}
7532		if (ent->owner == 0)
7533		    ent->owner = 1;
7534#ifdef LIBXML_LEGACY_ENABLED
7535		if (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)
7536		  xmlAddEntityReference(ent, firstChild, nw);
7537#endif /* LIBXML_LEGACY_ENABLED */
7538	    } else {
7539		const xmlChar *nbktext;
7540
7541		/*
7542		 * the name change is to avoid coalescing of the
7543		 * node with a possible previous text one which
7544		 * would make ent->children a dangling pointer
7545		 */
7546		nbktext = xmlDictLookup(ctxt->dict, BAD_CAST "nbktext",
7547					-1);
7548		if (ent->children->type == XML_TEXT_NODE)
7549		    ent->children->name = nbktext;
7550		if ((ent->last != ent->children) &&
7551		    (ent->last->type == XML_TEXT_NODE))
7552		    ent->last->name = nbktext;
7553		xmlAddChildList(ctxt->node, ent->children);
7554	    }
7555
7556	    /*
7557	     * This is to avoid a nasty side effect, see
7558	     * characters() in SAX.c
7559	     */
7560	    ctxt->nodemem = 0;
7561	    ctxt->nodelen = 0;
7562	    return;
7563	}
7564    }
7565}
7566
7567/**
7568 * xmlParseEntityRef:
7569 * @ctxt:  an XML parser context
7570 *
7571 * parse ENTITY references declarations
7572 *
7573 * [68] EntityRef ::= '&' Name ';'
7574 *
7575 * [ WFC: Entity Declared ]
7576 * In a document without any DTD, a document with only an internal DTD
7577 * subset which contains no parameter entity references, or a document
7578 * with "standalone='yes'", the Name given in the entity reference
7579 * must match that in an entity declaration, except that well-formed
7580 * documents need not declare any of the following entities: amp, lt,
7581 * gt, apos, quot.  The declaration of a parameter entity must precede
7582 * any reference to it.  Similarly, the declaration of a general entity
7583 * must precede any reference to it which appears in a default value in an
7584 * attribute-list declaration. Note that if entities are declared in the
7585 * external subset or in external parameter entities, a non-validating
7586 * processor is not obligated to read and process their declarations;
7587 * for such documents, the rule that an entity must be declared is a
7588 * well-formedness constraint only if standalone='yes'.
7589 *
7590 * [ WFC: Parsed Entity ]
7591 * An entity reference must not contain the name of an unparsed entity
7592 *
7593 * Returns the xmlEntityPtr if found, or NULL otherwise.
7594 */
7595xmlEntityPtr
7596xmlParseEntityRef(xmlParserCtxtPtr ctxt) {
7597    const xmlChar *name;
7598    xmlEntityPtr ent = NULL;
7599
7600    GROW;
7601    if (ctxt->instate == XML_PARSER_EOF)
7602        return(NULL);
7603
7604    if (RAW != '&')
7605        return(NULL);
7606    NEXT;
7607    name = xmlParseName(ctxt);
7608    if (name == NULL) {
7609	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7610		       "xmlParseEntityRef: no name\n");
7611        return(NULL);
7612    }
7613    if (RAW != ';') {
7614	xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7615	return(NULL);
7616    }
7617    NEXT;
7618
7619    /*
7620     * Predefined entities override any extra definition
7621     */
7622    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7623        ent = xmlGetPredefinedEntity(name);
7624        if (ent != NULL)
7625            return(ent);
7626    }
7627
7628    /*
7629     * Increase the number of entity references parsed
7630     */
7631    ctxt->nbentities++;
7632
7633    /*
7634     * Ask first SAX for entity resolution, otherwise try the
7635     * entities which may have stored in the parser context.
7636     */
7637    if (ctxt->sax != NULL) {
7638	if (ctxt->sax->getEntity != NULL)
7639	    ent = ctxt->sax->getEntity(ctxt->userData, name);
7640	if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7641	    (ctxt->options & XML_PARSE_OLDSAX))
7642	    ent = xmlGetPredefinedEntity(name);
7643	if ((ctxt->wellFormed == 1 ) && (ent == NULL) &&
7644	    (ctxt->userData==ctxt)) {
7645	    ent = xmlSAX2GetEntity(ctxt, name);
7646	}
7647    }
7648    if (ctxt->instate == XML_PARSER_EOF)
7649	return(NULL);
7650    /*
7651     * [ WFC: Entity Declared ]
7652     * In a document without any DTD, a document with only an
7653     * internal DTD subset which contains no parameter entity
7654     * references, or a document with "standalone='yes'", the
7655     * Name given in the entity reference must match that in an
7656     * entity declaration, except that well-formed documents
7657     * need not declare any of the following entities: amp, lt,
7658     * gt, apos, quot.
7659     * The declaration of a parameter entity must precede any
7660     * reference to it.
7661     * Similarly, the declaration of a general entity must
7662     * precede any reference to it which appears in a default
7663     * value in an attribute-list declaration. Note that if
7664     * entities are declared in the external subset or in
7665     * external parameter entities, a non-validating processor
7666     * is not obligated to read and process their declarations;
7667     * for such documents, the rule that an entity must be
7668     * declared is a well-formedness constraint only if
7669     * standalone='yes'.
7670     */
7671    if (ent == NULL) {
7672	if ((ctxt->standalone == 1) ||
7673	    ((ctxt->hasExternalSubset == 0) &&
7674	     (ctxt->hasPErefs == 0))) {
7675	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7676		     "Entity '%s' not defined\n", name);
7677	} else {
7678	    xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7679		     "Entity '%s' not defined\n", name);
7680	    if ((ctxt->inSubset == 0) &&
7681		(ctxt->sax != NULL) &&
7682		(ctxt->sax->reference != NULL)) {
7683		ctxt->sax->reference(ctxt->userData, name);
7684	    }
7685	}
7686	xmlParserEntityCheck(ctxt, 0, ent, 0);
7687	ctxt->valid = 0;
7688    }
7689
7690    /*
7691     * [ WFC: Parsed Entity ]
7692     * An entity reference must not contain the name of an
7693     * unparsed entity
7694     */
7695    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7696	xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7697		 "Entity reference to unparsed entity %s\n", name);
7698    }
7699
7700    /*
7701     * [ WFC: No External Entity References ]
7702     * Attribute values cannot contain direct or indirect
7703     * entity references to external entities.
7704     */
7705    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7706	     (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7707	xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7708	     "Attribute references external entity '%s'\n", name);
7709    }
7710    /*
7711     * [ WFC: No < in Attribute Values ]
7712     * The replacement text of any entity referred to directly or
7713     * indirectly in an attribute value (other than "&lt;") must
7714     * not contain a <.
7715     */
7716    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7717	     (ent != NULL) &&
7718	     (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY)) {
7719	if (((ent->checked & 1) || (ent->checked == 0)) &&
7720	     (ent->content != NULL) && (xmlStrchr(ent->content, '<'))) {
7721	    xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7722	"'<' in entity '%s' is not allowed in attributes values\n", name);
7723        }
7724    }
7725
7726    /*
7727     * Internal check, no parameter entities here ...
7728     */
7729    else {
7730	switch (ent->etype) {
7731	    case XML_INTERNAL_PARAMETER_ENTITY:
7732	    case XML_EXTERNAL_PARAMETER_ENTITY:
7733	    xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
7734	     "Attempt to reference the parameter entity '%s'\n",
7735			      name);
7736	    break;
7737	    default:
7738	    break;
7739	}
7740    }
7741
7742    /*
7743     * [ WFC: No Recursion ]
7744     * A parsed entity must not contain a recursive reference
7745     * to itself, either directly or indirectly.
7746     * Done somewhere else
7747     */
7748    return(ent);
7749}
7750
7751/**
7752 * xmlParseStringEntityRef:
7753 * @ctxt:  an XML parser context
7754 * @str:  a pointer to an index in the string
7755 *
7756 * parse ENTITY references declarations, but this version parses it from
7757 * a string value.
7758 *
7759 * [68] EntityRef ::= '&' Name ';'
7760 *
7761 * [ WFC: Entity Declared ]
7762 * In a document without any DTD, a document with only an internal DTD
7763 * subset which contains no parameter entity references, or a document
7764 * with "standalone='yes'", the Name given in the entity reference
7765 * must match that in an entity declaration, except that well-formed
7766 * documents need not declare any of the following entities: amp, lt,
7767 * gt, apos, quot.  The declaration of a parameter entity must precede
7768 * any reference to it.  Similarly, the declaration of a general entity
7769 * must precede any reference to it which appears in a default value in an
7770 * attribute-list declaration. Note that if entities are declared in the
7771 * external subset or in external parameter entities, a non-validating
7772 * processor is not obligated to read and process their declarations;
7773 * for such documents, the rule that an entity must be declared is a
7774 * well-formedness constraint only if standalone='yes'.
7775 *
7776 * [ WFC: Parsed Entity ]
7777 * An entity reference must not contain the name of an unparsed entity
7778 *
7779 * Returns the xmlEntityPtr if found, or NULL otherwise. The str pointer
7780 * is updated to the current location in the string.
7781 */
7782static xmlEntityPtr
7783xmlParseStringEntityRef(xmlParserCtxtPtr ctxt, const xmlChar ** str) {
7784    xmlChar *name;
7785    const xmlChar *ptr;
7786    xmlChar cur;
7787    xmlEntityPtr ent = NULL;
7788
7789    if ((str == NULL) || (*str == NULL))
7790        return(NULL);
7791    ptr = *str;
7792    cur = *ptr;
7793    if (cur != '&')
7794	return(NULL);
7795
7796    ptr++;
7797    name = xmlParseStringName(ctxt, &ptr);
7798    if (name == NULL) {
7799	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7800		       "xmlParseStringEntityRef: no name\n");
7801	*str = ptr;
7802	return(NULL);
7803    }
7804    if (*ptr != ';') {
7805	xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7806        xmlFree(name);
7807	*str = ptr;
7808	return(NULL);
7809    }
7810    ptr++;
7811
7812
7813    /*
7814     * Predefined entities override any extra definition
7815     */
7816    if ((ctxt->options & XML_PARSE_OLDSAX) == 0) {
7817        ent = xmlGetPredefinedEntity(name);
7818        if (ent != NULL) {
7819            xmlFree(name);
7820            *str = ptr;
7821            return(ent);
7822        }
7823    }
7824
7825    /*
7826     * Increate the number of entity references parsed
7827     */
7828    ctxt->nbentities++;
7829
7830    /*
7831     * Ask first SAX for entity resolution, otherwise try the
7832     * entities which may have stored in the parser context.
7833     */
7834    if (ctxt->sax != NULL) {
7835	if (ctxt->sax->getEntity != NULL)
7836	    ent = ctxt->sax->getEntity(ctxt->userData, name);
7837	if ((ent == NULL) && (ctxt->options & XML_PARSE_OLDSAX))
7838	    ent = xmlGetPredefinedEntity(name);
7839	if ((ent == NULL) && (ctxt->userData==ctxt)) {
7840	    ent = xmlSAX2GetEntity(ctxt, name);
7841	}
7842    }
7843    if (ctxt->instate == XML_PARSER_EOF) {
7844	xmlFree(name);
7845	return(NULL);
7846    }
7847
7848    /*
7849     * [ WFC: Entity Declared ]
7850     * In a document without any DTD, a document with only an
7851     * internal DTD subset which contains no parameter entity
7852     * references, or a document with "standalone='yes'", the
7853     * Name given in the entity reference must match that in an
7854     * entity declaration, except that well-formed documents
7855     * need not declare any of the following entities: amp, lt,
7856     * gt, apos, quot.
7857     * The declaration of a parameter entity must precede any
7858     * reference to it.
7859     * Similarly, the declaration of a general entity must
7860     * precede any reference to it which appears in a default
7861     * value in an attribute-list declaration. Note that if
7862     * entities are declared in the external subset or in
7863     * external parameter entities, a non-validating processor
7864     * is not obligated to read and process their declarations;
7865     * for such documents, the rule that an entity must be
7866     * declared is a well-formedness constraint only if
7867     * standalone='yes'.
7868     */
7869    if (ent == NULL) {
7870	if ((ctxt->standalone == 1) ||
7871	    ((ctxt->hasExternalSubset == 0) &&
7872	     (ctxt->hasPErefs == 0))) {
7873	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
7874		     "Entity '%s' not defined\n", name);
7875	} else {
7876	    xmlErrMsgStr(ctxt, XML_WAR_UNDECLARED_ENTITY,
7877			  "Entity '%s' not defined\n",
7878			  name);
7879	}
7880	xmlParserEntityCheck(ctxt, 0, ent, 0);
7881	/* TODO ? check regressions ctxt->valid = 0; */
7882    }
7883
7884    /*
7885     * [ WFC: Parsed Entity ]
7886     * An entity reference must not contain the name of an
7887     * unparsed entity
7888     */
7889    else if (ent->etype == XML_EXTERNAL_GENERAL_UNPARSED_ENTITY) {
7890	xmlFatalErrMsgStr(ctxt, XML_ERR_UNPARSED_ENTITY,
7891		 "Entity reference to unparsed entity %s\n", name);
7892    }
7893
7894    /*
7895     * [ WFC: No External Entity References ]
7896     * Attribute values cannot contain direct or indirect
7897     * entity references to external entities.
7898     */
7899    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7900	     (ent->etype == XML_EXTERNAL_GENERAL_PARSED_ENTITY)) {
7901	xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_EXTERNAL,
7902	 "Attribute references external entity '%s'\n", name);
7903    }
7904    /*
7905     * [ WFC: No < in Attribute Values ]
7906     * The replacement text of any entity referred to directly or
7907     * indirectly in an attribute value (other than "&lt;") must
7908     * not contain a <.
7909     */
7910    else if ((ctxt->instate == XML_PARSER_ATTRIBUTE_VALUE) &&
7911	     (ent != NULL) && (ent->content != NULL) &&
7912	     (ent->etype != XML_INTERNAL_PREDEFINED_ENTITY) &&
7913	     (xmlStrchr(ent->content, '<'))) {
7914	xmlFatalErrMsgStr(ctxt, XML_ERR_LT_IN_ATTRIBUTE,
7915     "'<' in entity '%s' is not allowed in attributes values\n",
7916			  name);
7917    }
7918
7919    /*
7920     * Internal check, no parameter entities here ...
7921     */
7922    else {
7923	switch (ent->etype) {
7924	    case XML_INTERNAL_PARAMETER_ENTITY:
7925	    case XML_EXTERNAL_PARAMETER_ENTITY:
7926		xmlFatalErrMsgStr(ctxt, XML_ERR_ENTITY_IS_PARAMETER,
7927	     "Attempt to reference the parameter entity '%s'\n",
7928				  name);
7929	    break;
7930	    default:
7931	    break;
7932	}
7933    }
7934
7935    /*
7936     * [ WFC: No Recursion ]
7937     * A parsed entity must not contain a recursive reference
7938     * to itself, either directly or indirectly.
7939     * Done somewhere else
7940     */
7941
7942    xmlFree(name);
7943    *str = ptr;
7944    return(ent);
7945}
7946
7947/**
7948 * xmlParsePEReference:
7949 * @ctxt:  an XML parser context
7950 *
7951 * parse PEReference declarations
7952 * The entity content is handled directly by pushing it's content as
7953 * a new input stream.
7954 *
7955 * [69] PEReference ::= '%' Name ';'
7956 *
7957 * [ WFC: No Recursion ]
7958 * A parsed entity must not contain a recursive
7959 * reference to itself, either directly or indirectly.
7960 *
7961 * [ WFC: Entity Declared ]
7962 * In a document without any DTD, a document with only an internal DTD
7963 * subset which contains no parameter entity references, or a document
7964 * with "standalone='yes'", ...  ... The declaration of a parameter
7965 * entity must precede any reference to it...
7966 *
7967 * [ VC: Entity Declared ]
7968 * In a document with an external subset or external parameter entities
7969 * with "standalone='no'", ...  ... The declaration of a parameter entity
7970 * must precede any reference to it...
7971 *
7972 * [ WFC: In DTD ]
7973 * Parameter-entity references may only appear in the DTD.
7974 * NOTE: misleading but this is handled.
7975 */
7976void
7977xmlParsePEReference(xmlParserCtxtPtr ctxt)
7978{
7979    const xmlChar *name;
7980    xmlEntityPtr entity = NULL;
7981    xmlParserInputPtr input;
7982
7983    if (RAW != '%')
7984        return;
7985    NEXT;
7986    name = xmlParseName(ctxt);
7987    if (name == NULL) {
7988	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
7989		       "xmlParsePEReference: no name\n");
7990	return;
7991    }
7992    if (RAW != ';') {
7993	xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
7994        return;
7995    }
7996
7997    NEXT;
7998
7999    /*
8000     * Increate the number of entity references parsed
8001     */
8002    ctxt->nbentities++;
8003
8004    /*
8005     * Request the entity from SAX
8006     */
8007    if ((ctxt->sax != NULL) &&
8008	(ctxt->sax->getParameterEntity != NULL))
8009	entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
8010    if (ctxt->instate == XML_PARSER_EOF)
8011	return;
8012    if (entity == NULL) {
8013	/*
8014	 * [ WFC: Entity Declared ]
8015	 * In a document without any DTD, a document with only an
8016	 * internal DTD subset which contains no parameter entity
8017	 * references, or a document with "standalone='yes'", ...
8018	 * ... The declaration of a parameter entity must precede
8019	 * any reference to it...
8020	 */
8021	if ((ctxt->standalone == 1) ||
8022	    ((ctxt->hasExternalSubset == 0) &&
8023	     (ctxt->hasPErefs == 0))) {
8024	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
8025			      "PEReference: %%%s; not found\n",
8026			      name);
8027	} else {
8028	    /*
8029	     * [ VC: Entity Declared ]
8030	     * In a document with an external subset or external
8031	     * parameter entities with "standalone='no'", ...
8032	     * ... The declaration of a parameter entity must
8033	     * precede any reference to it...
8034	     */
8035	    xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8036			  "PEReference: %%%s; not found\n",
8037			  name, NULL);
8038	    ctxt->valid = 0;
8039	}
8040	xmlParserEntityCheck(ctxt, 0, NULL, 0);
8041    } else {
8042	/*
8043	 * Internal checking in case the entity quest barfed
8044	 */
8045	if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
8046	    (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
8047	    xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8048		  "Internal: %%%s; is not a parameter entity\n",
8049			  name, NULL);
8050	} else if (ctxt->input->free != deallocblankswrapper) {
8051	    input = xmlNewBlanksWrapperInputStream(ctxt, entity);
8052	    if (xmlPushInput(ctxt, input) < 0)
8053		return;
8054	} else {
8055	    /*
8056	     * TODO !!!
8057	     * handle the extra spaces added before and after
8058	     * c.f. http://www.w3.org/TR/REC-xml#as-PE
8059	     */
8060	    input = xmlNewEntityInputStream(ctxt, entity);
8061	    if (xmlPushInput(ctxt, input) < 0)
8062		return;
8063	    if ((entity->etype == XML_EXTERNAL_PARAMETER_ENTITY) &&
8064		(CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) &&
8065		(IS_BLANK_CH(NXT(5)))) {
8066		xmlParseTextDecl(ctxt);
8067		if (ctxt->errNo ==
8068		    XML_ERR_UNSUPPORTED_ENCODING) {
8069		    /*
8070		     * The XML REC instructs us to stop parsing
8071		     * right here
8072		     */
8073		    ctxt->instate = XML_PARSER_EOF;
8074		    return;
8075		}
8076	    }
8077	}
8078    }
8079    ctxt->hasPErefs = 1;
8080}
8081
8082/**
8083 * xmlLoadEntityContent:
8084 * @ctxt:  an XML parser context
8085 * @entity: an unloaded system entity
8086 *
8087 * Load the original content of the given system entity from the
8088 * ExternalID/SystemID given. This is to be used for Included in Literal
8089 * http://www.w3.org/TR/REC-xml/#inliteral processing of entities references
8090 *
8091 * Returns 0 in case of success and -1 in case of failure
8092 */
8093static int
8094xmlLoadEntityContent(xmlParserCtxtPtr ctxt, xmlEntityPtr entity) {
8095    xmlParserInputPtr input;
8096    xmlBufferPtr buf;
8097    int l, c;
8098    int count = 0;
8099
8100    if ((ctxt == NULL) || (entity == NULL) ||
8101        ((entity->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
8102	 (entity->etype != XML_EXTERNAL_GENERAL_PARSED_ENTITY)) ||
8103	(entity->content != NULL)) {
8104	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8105	            "xmlLoadEntityContent parameter error");
8106        return(-1);
8107    }
8108
8109    if (xmlParserDebugEntities)
8110	xmlGenericError(xmlGenericErrorContext,
8111		"Reading %s entity content input\n", entity->name);
8112
8113    buf = xmlBufferCreate();
8114    if (buf == NULL) {
8115	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8116	            "xmlLoadEntityContent parameter error");
8117        return(-1);
8118    }
8119
8120    input = xmlNewEntityInputStream(ctxt, entity);
8121    if (input == NULL) {
8122	xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8123	            "xmlLoadEntityContent input error");
8124	xmlBufferFree(buf);
8125        return(-1);
8126    }
8127
8128    /*
8129     * Push the entity as the current input, read char by char
8130     * saving to the buffer until the end of the entity or an error
8131     */
8132    if (xmlPushInput(ctxt, input) < 0) {
8133        xmlBufferFree(buf);
8134	return(-1);
8135    }
8136
8137    GROW;
8138    c = CUR_CHAR(l);
8139    while ((ctxt->input == input) && (ctxt->input->cur < ctxt->input->end) &&
8140           (IS_CHAR(c))) {
8141        xmlBufferAdd(buf, ctxt->input->cur, l);
8142	if (count++ > XML_PARSER_CHUNK_SIZE) {
8143	    count = 0;
8144	    GROW;
8145            if (ctxt->instate == XML_PARSER_EOF) {
8146                xmlBufferFree(buf);
8147                return(-1);
8148            }
8149	}
8150	NEXTL(l);
8151	c = CUR_CHAR(l);
8152	if (c == 0) {
8153	    count = 0;
8154	    GROW;
8155            if (ctxt->instate == XML_PARSER_EOF) {
8156                xmlBufferFree(buf);
8157                return(-1);
8158            }
8159	    c = CUR_CHAR(l);
8160	}
8161    }
8162
8163    if ((ctxt->input == input) && (ctxt->input->cur >= ctxt->input->end)) {
8164        xmlPopInput(ctxt);
8165    } else if (!IS_CHAR(c)) {
8166        xmlFatalErrMsgInt(ctxt, XML_ERR_INVALID_CHAR,
8167                          "xmlLoadEntityContent: invalid char value %d\n",
8168	                  c);
8169	xmlBufferFree(buf);
8170	return(-1);
8171    }
8172    entity->content = buf->content;
8173    buf->content = NULL;
8174    xmlBufferFree(buf);
8175
8176    return(0);
8177}
8178
8179/**
8180 * xmlParseStringPEReference:
8181 * @ctxt:  an XML parser context
8182 * @str:  a pointer to an index in the string
8183 *
8184 * parse PEReference declarations
8185 *
8186 * [69] PEReference ::= '%' Name ';'
8187 *
8188 * [ WFC: No Recursion ]
8189 * A parsed entity must not contain a recursive
8190 * reference to itself, either directly or indirectly.
8191 *
8192 * [ WFC: Entity Declared ]
8193 * In a document without any DTD, a document with only an internal DTD
8194 * subset which contains no parameter entity references, or a document
8195 * with "standalone='yes'", ...  ... The declaration of a parameter
8196 * entity must precede any reference to it...
8197 *
8198 * [ VC: Entity Declared ]
8199 * In a document with an external subset or external parameter entities
8200 * with "standalone='no'", ...  ... The declaration of a parameter entity
8201 * must precede any reference to it...
8202 *
8203 * [ WFC: In DTD ]
8204 * Parameter-entity references may only appear in the DTD.
8205 * NOTE: misleading but this is handled.
8206 *
8207 * Returns the string of the entity content.
8208 *         str is updated to the current value of the index
8209 */
8210static xmlEntityPtr
8211xmlParseStringPEReference(xmlParserCtxtPtr ctxt, const xmlChar **str) {
8212    const xmlChar *ptr;
8213    xmlChar cur;
8214    xmlChar *name;
8215    xmlEntityPtr entity = NULL;
8216
8217    if ((str == NULL) || (*str == NULL)) return(NULL);
8218    ptr = *str;
8219    cur = *ptr;
8220    if (cur != '%')
8221        return(NULL);
8222    ptr++;
8223    name = xmlParseStringName(ctxt, &ptr);
8224    if (name == NULL) {
8225	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8226		       "xmlParseStringPEReference: no name\n");
8227	*str = ptr;
8228	return(NULL);
8229    }
8230    cur = *ptr;
8231    if (cur != ';') {
8232	xmlFatalErr(ctxt, XML_ERR_ENTITYREF_SEMICOL_MISSING, NULL);
8233	xmlFree(name);
8234	*str = ptr;
8235	return(NULL);
8236    }
8237    ptr++;
8238
8239    /*
8240     * Increate the number of entity references parsed
8241     */
8242    ctxt->nbentities++;
8243
8244    /*
8245     * Request the entity from SAX
8246     */
8247    if ((ctxt->sax != NULL) &&
8248	(ctxt->sax->getParameterEntity != NULL))
8249	entity = ctxt->sax->getParameterEntity(ctxt->userData, name);
8250    if (ctxt->instate == XML_PARSER_EOF) {
8251	xmlFree(name);
8252	return(NULL);
8253    }
8254    if (entity == NULL) {
8255	/*
8256	 * [ WFC: Entity Declared ]
8257	 * In a document without any DTD, a document with only an
8258	 * internal DTD subset which contains no parameter entity
8259	 * references, or a document with "standalone='yes'", ...
8260	 * ... The declaration of a parameter entity must precede
8261	 * any reference to it...
8262	 */
8263	if ((ctxt->standalone == 1) ||
8264	    ((ctxt->hasExternalSubset == 0) && (ctxt->hasPErefs == 0))) {
8265	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNDECLARED_ENTITY,
8266		 "PEReference: %%%s; not found\n", name);
8267	} else {
8268	    /*
8269	     * [ VC: Entity Declared ]
8270	     * In a document with an external subset or external
8271	     * parameter entities with "standalone='no'", ...
8272	     * ... The declaration of a parameter entity must
8273	     * precede any reference to it...
8274	     */
8275	    xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8276			  "PEReference: %%%s; not found\n",
8277			  name, NULL);
8278	    ctxt->valid = 0;
8279	}
8280	xmlParserEntityCheck(ctxt, 0, NULL, 0);
8281    } else {
8282	/*
8283	 * Internal checking in case the entity quest barfed
8284	 */
8285	if ((entity->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
8286	    (entity->etype != XML_EXTERNAL_PARAMETER_ENTITY)) {
8287	    xmlWarningMsg(ctxt, XML_WAR_UNDECLARED_ENTITY,
8288			  "%%%s; is not a parameter entity\n",
8289			  name, NULL);
8290	}
8291    }
8292    ctxt->hasPErefs = 1;
8293    xmlFree(name);
8294    *str = ptr;
8295    return(entity);
8296}
8297
8298/**
8299 * xmlParseDocTypeDecl:
8300 * @ctxt:  an XML parser context
8301 *
8302 * parse a DOCTYPE declaration
8303 *
8304 * [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S?
8305 *                      ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8306 *
8307 * [ VC: Root Element Type ]
8308 * The Name in the document type declaration must match the element
8309 * type of the root element.
8310 */
8311
8312void
8313xmlParseDocTypeDecl(xmlParserCtxtPtr ctxt) {
8314    const xmlChar *name = NULL;
8315    xmlChar *ExternalID = NULL;
8316    xmlChar *URI = NULL;
8317
8318    /*
8319     * We know that '<!DOCTYPE' has been detected.
8320     */
8321    SKIP(9);
8322
8323    SKIP_BLANKS;
8324
8325    /*
8326     * Parse the DOCTYPE name.
8327     */
8328    name = xmlParseName(ctxt);
8329    if (name == NULL) {
8330	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8331		       "xmlParseDocTypeDecl : no DOCTYPE name !\n");
8332    }
8333    ctxt->intSubName = name;
8334
8335    SKIP_BLANKS;
8336
8337    /*
8338     * Check for SystemID and ExternalID
8339     */
8340    URI = xmlParseExternalID(ctxt, &ExternalID, 1);
8341
8342    if ((URI != NULL) || (ExternalID != NULL)) {
8343        ctxt->hasExternalSubset = 1;
8344    }
8345    ctxt->extSubURI = URI;
8346    ctxt->extSubSystem = ExternalID;
8347
8348    SKIP_BLANKS;
8349
8350    /*
8351     * Create and update the internal subset.
8352     */
8353    if ((ctxt->sax != NULL) && (ctxt->sax->internalSubset != NULL) &&
8354	(!ctxt->disableSAX))
8355	ctxt->sax->internalSubset(ctxt->userData, name, ExternalID, URI);
8356    if (ctxt->instate == XML_PARSER_EOF)
8357	return;
8358
8359    /*
8360     * Is there any internal subset declarations ?
8361     * they are handled separately in xmlParseInternalSubset()
8362     */
8363    if (RAW == '[')
8364	return;
8365
8366    /*
8367     * We should be at the end of the DOCTYPE declaration.
8368     */
8369    if (RAW != '>') {
8370	xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8371    }
8372    NEXT;
8373}
8374
8375/**
8376 * xmlParseInternalSubset:
8377 * @ctxt:  an XML parser context
8378 *
8379 * parse the internal subset declaration
8380 *
8381 * [28 end] ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
8382 */
8383
8384static void
8385xmlParseInternalSubset(xmlParserCtxtPtr ctxt) {
8386    /*
8387     * Is there any DTD definition ?
8388     */
8389    if (RAW == '[') {
8390        ctxt->instate = XML_PARSER_DTD;
8391        NEXT;
8392	/*
8393	 * Parse the succession of Markup declarations and
8394	 * PEReferences.
8395	 * Subsequence (markupdecl | PEReference | S)*
8396	 */
8397	while ((RAW != ']') && (ctxt->instate != XML_PARSER_EOF)) {
8398	    const xmlChar *check = CUR_PTR;
8399	    unsigned int cons = ctxt->input->consumed;
8400
8401	    SKIP_BLANKS;
8402	    xmlParseMarkupDecl(ctxt);
8403	    xmlParsePEReference(ctxt);
8404
8405	    /*
8406	     * Pop-up of finished entities.
8407	     */
8408	    while ((RAW == 0) && (ctxt->inputNr > 1))
8409		xmlPopInput(ctxt);
8410
8411	    if ((CUR_PTR == check) && (cons == ctxt->input->consumed)) {
8412		xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
8413	     "xmlParseInternalSubset: error detected in Markup declaration\n");
8414		break;
8415	    }
8416	}
8417	if (RAW == ']') {
8418	    NEXT;
8419	    SKIP_BLANKS;
8420	}
8421    }
8422
8423    /*
8424     * We should be at the end of the DOCTYPE declaration.
8425     */
8426    if (RAW != '>') {
8427	xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL);
8428    }
8429    NEXT;
8430}
8431
8432#ifdef LIBXML_SAX1_ENABLED
8433/**
8434 * xmlParseAttribute:
8435 * @ctxt:  an XML parser context
8436 * @value:  a xmlChar ** used to store the value of the attribute
8437 *
8438 * parse an attribute
8439 *
8440 * [41] Attribute ::= Name Eq AttValue
8441 *
8442 * [ WFC: No External Entity References ]
8443 * Attribute values cannot contain direct or indirect entity references
8444 * to external entities.
8445 *
8446 * [ WFC: No < in Attribute Values ]
8447 * The replacement text of any entity referred to directly or indirectly in
8448 * an attribute value (other than "&lt;") must not contain a <.
8449 *
8450 * [ VC: Attribute Value Type ]
8451 * The attribute must have been declared; the value must be of the type
8452 * declared for it.
8453 *
8454 * [25] Eq ::= S? '=' S?
8455 *
8456 * With namespace:
8457 *
8458 * [NS 11] Attribute ::= QName Eq AttValue
8459 *
8460 * Also the case QName == xmlns:??? is handled independently as a namespace
8461 * definition.
8462 *
8463 * Returns the attribute name, and the value in *value.
8464 */
8465
8466const xmlChar *
8467xmlParseAttribute(xmlParserCtxtPtr ctxt, xmlChar **value) {
8468    const xmlChar *name;
8469    xmlChar *val;
8470
8471    *value = NULL;
8472    GROW;
8473    name = xmlParseName(ctxt);
8474    if (name == NULL) {
8475	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8476	               "error parsing attribute name\n");
8477        return(NULL);
8478    }
8479
8480    /*
8481     * read the value
8482     */
8483    SKIP_BLANKS;
8484    if (RAW == '=') {
8485        NEXT;
8486	SKIP_BLANKS;
8487	val = xmlParseAttValue(ctxt);
8488	ctxt->instate = XML_PARSER_CONTENT;
8489    } else {
8490	xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
8491	       "Specification mandate value for attribute %s\n", name);
8492	return(NULL);
8493    }
8494
8495    /*
8496     * Check that xml:lang conforms to the specification
8497     * No more registered as an error, just generate a warning now
8498     * since this was deprecated in XML second edition
8499     */
8500    if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "xml:lang"))) {
8501	if (!xmlCheckLanguageID(val)) {
8502	    xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
8503		          "Malformed value for xml:lang : %s\n",
8504			  val, NULL);
8505	}
8506    }
8507
8508    /*
8509     * Check that xml:space conforms to the specification
8510     */
8511    if (xmlStrEqual(name, BAD_CAST "xml:space")) {
8512	if (xmlStrEqual(val, BAD_CAST "default"))
8513	    *(ctxt->space) = 0;
8514	else if (xmlStrEqual(val, BAD_CAST "preserve"))
8515	    *(ctxt->space) = 1;
8516	else {
8517		xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
8518"Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
8519                                 val, NULL);
8520	}
8521    }
8522
8523    *value = val;
8524    return(name);
8525}
8526
8527/**
8528 * xmlParseStartTag:
8529 * @ctxt:  an XML parser context
8530 *
8531 * parse a start of tag either for rule element or
8532 * EmptyElement. In both case we don't parse the tag closing chars.
8533 *
8534 * [40] STag ::= '<' Name (S Attribute)* S? '>'
8535 *
8536 * [ WFC: Unique Att Spec ]
8537 * No attribute name may appear more than once in the same start-tag or
8538 * empty-element tag.
8539 *
8540 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
8541 *
8542 * [ WFC: Unique Att Spec ]
8543 * No attribute name may appear more than once in the same start-tag or
8544 * empty-element tag.
8545 *
8546 * With namespace:
8547 *
8548 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
8549 *
8550 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
8551 *
8552 * Returns the element name parsed
8553 */
8554
8555const xmlChar *
8556xmlParseStartTag(xmlParserCtxtPtr ctxt) {
8557    const xmlChar *name;
8558    const xmlChar *attname;
8559    xmlChar *attvalue;
8560    const xmlChar **atts = ctxt->atts;
8561    int nbatts = 0;
8562    int maxatts = ctxt->maxatts;
8563    int i;
8564
8565    if (RAW != '<') return(NULL);
8566    NEXT1;
8567
8568    name = xmlParseName(ctxt);
8569    if (name == NULL) {
8570	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
8571	     "xmlParseStartTag: invalid element name\n");
8572        return(NULL);
8573    }
8574
8575    /*
8576     * Now parse the attributes, it ends up with the ending
8577     *
8578     * (S Attribute)* S?
8579     */
8580    SKIP_BLANKS;
8581    GROW;
8582
8583    while (((RAW != '>') &&
8584	   ((RAW != '/') || (NXT(1) != '>')) &&
8585	   (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
8586	const xmlChar *q = CUR_PTR;
8587	unsigned int cons = ctxt->input->consumed;
8588
8589	attname = xmlParseAttribute(ctxt, &attvalue);
8590        if ((attname != NULL) && (attvalue != NULL)) {
8591	    /*
8592	     * [ WFC: Unique Att Spec ]
8593	     * No attribute name may appear more than once in the same
8594	     * start-tag or empty-element tag.
8595	     */
8596	    for (i = 0; i < nbatts;i += 2) {
8597	        if (xmlStrEqual(atts[i], attname)) {
8598		    xmlErrAttributeDup(ctxt, NULL, attname);
8599		    xmlFree(attvalue);
8600		    goto failed;
8601		}
8602	    }
8603	    /*
8604	     * Add the pair to atts
8605	     */
8606	    if (atts == NULL) {
8607	        maxatts = 22; /* allow for 10 attrs by default */
8608	        atts = (const xmlChar **)
8609		       xmlMalloc(maxatts * sizeof(xmlChar *));
8610		if (atts == NULL) {
8611		    xmlErrMemory(ctxt, NULL);
8612		    if (attvalue != NULL)
8613			xmlFree(attvalue);
8614		    goto failed;
8615		}
8616		ctxt->atts = atts;
8617		ctxt->maxatts = maxatts;
8618	    } else if (nbatts + 4 > maxatts) {
8619	        const xmlChar **n;
8620
8621	        maxatts *= 2;
8622	        n = (const xmlChar **) xmlRealloc((void *) atts,
8623					     maxatts * sizeof(const xmlChar *));
8624		if (n == NULL) {
8625		    xmlErrMemory(ctxt, NULL);
8626		    if (attvalue != NULL)
8627			xmlFree(attvalue);
8628		    goto failed;
8629		}
8630		atts = n;
8631		ctxt->atts = atts;
8632		ctxt->maxatts = maxatts;
8633	    }
8634	    atts[nbatts++] = attname;
8635	    atts[nbatts++] = attvalue;
8636	    atts[nbatts] = NULL;
8637	    atts[nbatts + 1] = NULL;
8638	} else {
8639	    if (attvalue != NULL)
8640		xmlFree(attvalue);
8641	}
8642
8643failed:
8644
8645	GROW
8646	if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
8647	    break;
8648	if (!IS_BLANK_CH(RAW)) {
8649	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
8650			   "attributes construct error\n");
8651	}
8652	SKIP_BLANKS;
8653        if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
8654            (attname == NULL) && (attvalue == NULL)) {
8655	    xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
8656			   "xmlParseStartTag: problem parsing attributes\n");
8657	    break;
8658	}
8659	SHRINK;
8660        GROW;
8661    }
8662
8663    /*
8664     * SAX: Start of Element !
8665     */
8666    if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL) &&
8667	(!ctxt->disableSAX)) {
8668	if (nbatts > 0)
8669	    ctxt->sax->startElement(ctxt->userData, name, atts);
8670	else
8671	    ctxt->sax->startElement(ctxt->userData, name, NULL);
8672    }
8673
8674    if (atts != NULL) {
8675        /* Free only the content strings */
8676        for (i = 1;i < nbatts;i+=2)
8677	    if (atts[i] != NULL)
8678	       xmlFree((xmlChar *) atts[i]);
8679    }
8680    return(name);
8681}
8682
8683/**
8684 * xmlParseEndTag1:
8685 * @ctxt:  an XML parser context
8686 * @line:  line of the start tag
8687 * @nsNr:  number of namespaces on the start tag
8688 *
8689 * parse an end of tag
8690 *
8691 * [42] ETag ::= '</' Name S? '>'
8692 *
8693 * With namespace
8694 *
8695 * [NS 9] ETag ::= '</' QName S? '>'
8696 */
8697
8698static void
8699xmlParseEndTag1(xmlParserCtxtPtr ctxt, int line) {
8700    const xmlChar *name;
8701
8702    GROW;
8703    if ((RAW != '<') || (NXT(1) != '/')) {
8704	xmlFatalErrMsg(ctxt, XML_ERR_LTSLASH_REQUIRED,
8705		       "xmlParseEndTag: '</' not found\n");
8706	return;
8707    }
8708    SKIP(2);
8709
8710    name = xmlParseNameAndCompare(ctxt,ctxt->name);
8711
8712    /*
8713     * We should definitely be at the ending "S? '>'" part
8714     */
8715    GROW;
8716    SKIP_BLANKS;
8717    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
8718	xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
8719    } else
8720	NEXT1;
8721
8722    /*
8723     * [ WFC: Element Type Match ]
8724     * The Name in an element's end-tag must match the element type in the
8725     * start-tag.
8726     *
8727     */
8728    if (name != (xmlChar*)1) {
8729        if (name == NULL) name = BAD_CAST "unparseable";
8730        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
8731		     "Opening and ending tag mismatch: %s line %d and %s\n",
8732		                ctxt->name, line, name);
8733    }
8734
8735    /*
8736     * SAX: End of Tag
8737     */
8738    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
8739	(!ctxt->disableSAX))
8740        ctxt->sax->endElement(ctxt->userData, ctxt->name);
8741
8742    namePop(ctxt);
8743    spacePop(ctxt);
8744    return;
8745}
8746
8747/**
8748 * xmlParseEndTag:
8749 * @ctxt:  an XML parser context
8750 *
8751 * parse an end of tag
8752 *
8753 * [42] ETag ::= '</' Name S? '>'
8754 *
8755 * With namespace
8756 *
8757 * [NS 9] ETag ::= '</' QName S? '>'
8758 */
8759
8760void
8761xmlParseEndTag(xmlParserCtxtPtr ctxt) {
8762    xmlParseEndTag1(ctxt, 0);
8763}
8764#endif /* LIBXML_SAX1_ENABLED */
8765
8766/************************************************************************
8767 *									*
8768 *		      SAX 2 specific operations				*
8769 *									*
8770 ************************************************************************/
8771
8772/*
8773 * xmlGetNamespace:
8774 * @ctxt:  an XML parser context
8775 * @prefix:  the prefix to lookup
8776 *
8777 * Lookup the namespace name for the @prefix (which ca be NULL)
8778 * The prefix must come from the @ctxt->dict dictionnary
8779 *
8780 * Returns the namespace name or NULL if not bound
8781 */
8782static const xmlChar *
8783xmlGetNamespace(xmlParserCtxtPtr ctxt, const xmlChar *prefix) {
8784    int i;
8785
8786    if (prefix == ctxt->str_xml) return(ctxt->str_xml_ns);
8787    for (i = ctxt->nsNr - 2;i >= 0;i-=2)
8788        if (ctxt->nsTab[i] == prefix) {
8789	    if ((prefix == NULL) && (*ctxt->nsTab[i + 1] == 0))
8790	        return(NULL);
8791	    return(ctxt->nsTab[i + 1]);
8792	}
8793    return(NULL);
8794}
8795
8796/**
8797 * xmlParseQName:
8798 * @ctxt:  an XML parser context
8799 * @prefix:  pointer to store the prefix part
8800 *
8801 * parse an XML Namespace QName
8802 *
8803 * [6]  QName  ::= (Prefix ':')? LocalPart
8804 * [7]  Prefix  ::= NCName
8805 * [8]  LocalPart  ::= NCName
8806 *
8807 * Returns the Name parsed or NULL
8808 */
8809
8810static const xmlChar *
8811xmlParseQName(xmlParserCtxtPtr ctxt, const xmlChar **prefix) {
8812    const xmlChar *l, *p;
8813
8814    GROW;
8815
8816    l = xmlParseNCName(ctxt);
8817    if (l == NULL) {
8818        if (CUR == ':') {
8819	    l = xmlParseName(ctxt);
8820	    if (l != NULL) {
8821	        xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8822		         "Failed to parse QName '%s'\n", l, NULL, NULL);
8823		*prefix = NULL;
8824		return(l);
8825	    }
8826	}
8827        return(NULL);
8828    }
8829    if (CUR == ':') {
8830        NEXT;
8831	p = l;
8832	l = xmlParseNCName(ctxt);
8833	if (l == NULL) {
8834	    xmlChar *tmp;
8835
8836            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8837	             "Failed to parse QName '%s:'\n", p, NULL, NULL);
8838	    l = xmlParseNmtoken(ctxt);
8839	    if (l == NULL)
8840		tmp = xmlBuildQName(BAD_CAST "", p, NULL, 0);
8841	    else {
8842		tmp = xmlBuildQName(l, p, NULL, 0);
8843		xmlFree((char *)l);
8844	    }
8845	    p = xmlDictLookup(ctxt->dict, tmp, -1);
8846	    if (tmp != NULL) xmlFree(tmp);
8847	    *prefix = NULL;
8848	    return(p);
8849	}
8850	if (CUR == ':') {
8851	    xmlChar *tmp;
8852
8853            xmlNsErr(ctxt, XML_NS_ERR_QNAME,
8854	             "Failed to parse QName '%s:%s:'\n", p, l, NULL);
8855	    NEXT;
8856	    tmp = (xmlChar *) xmlParseName(ctxt);
8857	    if (tmp != NULL) {
8858	        tmp = xmlBuildQName(tmp, l, NULL, 0);
8859		l = xmlDictLookup(ctxt->dict, tmp, -1);
8860		if (tmp != NULL) xmlFree(tmp);
8861		*prefix = p;
8862		return(l);
8863	    }
8864	    tmp = xmlBuildQName(BAD_CAST "", l, NULL, 0);
8865	    l = xmlDictLookup(ctxt->dict, tmp, -1);
8866	    if (tmp != NULL) xmlFree(tmp);
8867	    *prefix = p;
8868	    return(l);
8869	}
8870	*prefix = p;
8871    } else
8872        *prefix = NULL;
8873    return(l);
8874}
8875
8876/**
8877 * xmlParseQNameAndCompare:
8878 * @ctxt:  an XML parser context
8879 * @name:  the localname
8880 * @prefix:  the prefix, if any.
8881 *
8882 * parse an XML name and compares for match
8883 * (specialized for endtag parsing)
8884 *
8885 * Returns NULL for an illegal name, (xmlChar*) 1 for success
8886 * and the name for mismatch
8887 */
8888
8889static const xmlChar *
8890xmlParseQNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *name,
8891                        xmlChar const *prefix) {
8892    const xmlChar *cmp;
8893    const xmlChar *in;
8894    const xmlChar *ret;
8895    const xmlChar *prefix2;
8896
8897    if (prefix == NULL) return(xmlParseNameAndCompare(ctxt, name));
8898
8899    GROW;
8900    in = ctxt->input->cur;
8901
8902    cmp = prefix;
8903    while (*in != 0 && *in == *cmp) {
8904	++in;
8905	++cmp;
8906    }
8907    if ((*cmp == 0) && (*in == ':')) {
8908        in++;
8909	cmp = name;
8910	while (*in != 0 && *in == *cmp) {
8911	    ++in;
8912	    ++cmp;
8913	}
8914	if (*cmp == 0 && (*in == '>' || IS_BLANK_CH (*in))) {
8915	    /* success */
8916	    ctxt->input->cur = in;
8917	    return((const xmlChar*) 1);
8918	}
8919    }
8920    /*
8921     * all strings coms from the dictionary, equality can be done directly
8922     */
8923    ret = xmlParseQName (ctxt, &prefix2);
8924    if ((ret == name) && (prefix == prefix2))
8925	return((const xmlChar*) 1);
8926    return ret;
8927}
8928
8929/**
8930 * xmlParseAttValueInternal:
8931 * @ctxt:  an XML parser context
8932 * @len:  attribute len result
8933 * @alloc:  whether the attribute was reallocated as a new string
8934 * @normalize:  if 1 then further non-CDATA normalization must be done
8935 *
8936 * parse a value for an attribute.
8937 * NOTE: if no normalization is needed, the routine will return pointers
8938 *       directly from the data buffer.
8939 *
8940 * 3.3.3 Attribute-Value Normalization:
8941 * Before the value of an attribute is passed to the application or
8942 * checked for validity, the XML processor must normalize it as follows:
8943 * - a character reference is processed by appending the referenced
8944 *   character to the attribute value
8945 * - an entity reference is processed by recursively processing the
8946 *   replacement text of the entity
8947 * - a whitespace character (#x20, #xD, #xA, #x9) is processed by
8948 *   appending #x20 to the normalized value, except that only a single
8949 *   #x20 is appended for a "#xD#xA" sequence that is part of an external
8950 *   parsed entity or the literal entity value of an internal parsed entity
8951 * - other characters are processed by appending them to the normalized value
8952 * If the declared value is not CDATA, then the XML processor must further
8953 * process the normalized attribute value by discarding any leading and
8954 * trailing space (#x20) characters, and by replacing sequences of space
8955 * (#x20) characters by a single space (#x20) character.
8956 * All attributes for which no declaration has been read should be treated
8957 * by a non-validating parser as if declared CDATA.
8958 *
8959 * Returns the AttValue parsed or NULL. The value has to be freed by the
8960 *     caller if it was copied, this can be detected by val[*len] == 0.
8961 */
8962
8963static xmlChar *
8964xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *len, int *alloc,
8965                         int normalize)
8966{
8967    xmlChar limit = 0;
8968    const xmlChar *in = NULL, *start, *end, *last;
8969    xmlChar *ret = NULL;
8970    int line, col;
8971
8972    GROW;
8973    in = (xmlChar *) CUR_PTR;
8974    line = ctxt->input->line;
8975    col = ctxt->input->col;
8976    if (*in != '"' && *in != '\'') {
8977        xmlFatalErr(ctxt, XML_ERR_ATTRIBUTE_NOT_STARTED, NULL);
8978        return (NULL);
8979    }
8980    ctxt->instate = XML_PARSER_ATTRIBUTE_VALUE;
8981
8982    /*
8983     * try to handle in this routine the most common case where no
8984     * allocation of a new string is required and where content is
8985     * pure ASCII.
8986     */
8987    limit = *in++;
8988    col++;
8989    end = ctxt->input->end;
8990    start = in;
8991    if (in >= end) {
8992        const xmlChar *oldbase = ctxt->input->base;
8993	GROW;
8994	if (oldbase != ctxt->input->base) {
8995	    long delta = ctxt->input->base - oldbase;
8996	    start = start + delta;
8997	    in = in + delta;
8998	}
8999	end = ctxt->input->end;
9000    }
9001    if (normalize) {
9002        /*
9003	 * Skip any leading spaces
9004	 */
9005	while ((in < end) && (*in != limit) &&
9006	       ((*in == 0x20) || (*in == 0x9) ||
9007	        (*in == 0xA) || (*in == 0xD))) {
9008	    if (*in == 0xA) {
9009	        line++; col = 1;
9010	    } else {
9011	        col++;
9012	    }
9013	    in++;
9014	    start = in;
9015	    if (in >= end) {
9016		const xmlChar *oldbase = ctxt->input->base;
9017		GROW;
9018                if (ctxt->instate == XML_PARSER_EOF)
9019                    return(NULL);
9020		if (oldbase != ctxt->input->base) {
9021		    long delta = ctxt->input->base - oldbase;
9022		    start = start + delta;
9023		    in = in + delta;
9024		}
9025		end = ctxt->input->end;
9026                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
9027                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
9028                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9029                                   "AttValue length too long\n");
9030                    return(NULL);
9031                }
9032	    }
9033	}
9034	while ((in < end) && (*in != limit) && (*in >= 0x20) &&
9035	       (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
9036	    col++;
9037	    if ((*in++ == 0x20) && (*in == 0x20)) break;
9038	    if (in >= end) {
9039		const xmlChar *oldbase = ctxt->input->base;
9040		GROW;
9041                if (ctxt->instate == XML_PARSER_EOF)
9042                    return(NULL);
9043		if (oldbase != ctxt->input->base) {
9044		    long delta = ctxt->input->base - oldbase;
9045		    start = start + delta;
9046		    in = in + delta;
9047		}
9048		end = ctxt->input->end;
9049                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
9050                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
9051                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9052                                   "AttValue length too long\n");
9053                    return(NULL);
9054                }
9055	    }
9056	}
9057	last = in;
9058	/*
9059	 * skip the trailing blanks
9060	 */
9061	while ((last[-1] == 0x20) && (last > start)) last--;
9062	while ((in < end) && (*in != limit) &&
9063	       ((*in == 0x20) || (*in == 0x9) ||
9064	        (*in == 0xA) || (*in == 0xD))) {
9065	    if (*in == 0xA) {
9066	        line++, col = 1;
9067	    } else {
9068	        col++;
9069	    }
9070	    in++;
9071	    if (in >= end) {
9072		const xmlChar *oldbase = ctxt->input->base;
9073		GROW;
9074                if (ctxt->instate == XML_PARSER_EOF)
9075                    return(NULL);
9076		if (oldbase != ctxt->input->base) {
9077		    long delta = ctxt->input->base - oldbase;
9078		    start = start + delta;
9079		    in = in + delta;
9080		    last = last + delta;
9081		}
9082		end = ctxt->input->end;
9083                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
9084                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
9085                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9086                                   "AttValue length too long\n");
9087                    return(NULL);
9088                }
9089	    }
9090	}
9091        if (((in - start) > XML_MAX_TEXT_LENGTH) &&
9092            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
9093            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9094                           "AttValue length too long\n");
9095            return(NULL);
9096        }
9097	if (*in != limit) goto need_complex;
9098    } else {
9099	while ((in < end) && (*in != limit) && (*in >= 0x20) &&
9100	       (*in <= 0x7f) && (*in != '&') && (*in != '<')) {
9101	    in++;
9102	    col++;
9103	    if (in >= end) {
9104		const xmlChar *oldbase = ctxt->input->base;
9105		GROW;
9106                if (ctxt->instate == XML_PARSER_EOF)
9107                    return(NULL);
9108		if (oldbase != ctxt->input->base) {
9109		    long delta = ctxt->input->base - oldbase;
9110		    start = start + delta;
9111		    in = in + delta;
9112		}
9113		end = ctxt->input->end;
9114                if (((in - start) > XML_MAX_TEXT_LENGTH) &&
9115                    ((ctxt->options & XML_PARSE_HUGE) == 0)) {
9116                    xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9117                                   "AttValue length too long\n");
9118                    return(NULL);
9119                }
9120	    }
9121	}
9122	last = in;
9123        if (((in - start) > XML_MAX_TEXT_LENGTH) &&
9124            ((ctxt->options & XML_PARSE_HUGE) == 0)) {
9125            xmlFatalErrMsg(ctxt, XML_ERR_ATTRIBUTE_NOT_FINISHED,
9126                           "AttValue length too long\n");
9127            return(NULL);
9128        }
9129	if (*in != limit) goto need_complex;
9130    }
9131    in++;
9132    col++;
9133    if (len != NULL) {
9134        *len = last - start;
9135        ret = (xmlChar *) start;
9136    } else {
9137        if (alloc) *alloc = 1;
9138        ret = xmlStrndup(start, last - start);
9139    }
9140    CUR_PTR = in;
9141    ctxt->input->line = line;
9142    ctxt->input->col = col;
9143    if (alloc) *alloc = 0;
9144    return ret;
9145need_complex:
9146    if (alloc) *alloc = 1;
9147    return xmlParseAttValueComplex(ctxt, len, normalize);
9148}
9149
9150/**
9151 * xmlParseAttribute2:
9152 * @ctxt:  an XML parser context
9153 * @pref:  the element prefix
9154 * @elem:  the element name
9155 * @prefix:  a xmlChar ** used to store the value of the attribute prefix
9156 * @value:  a xmlChar ** used to store the value of the attribute
9157 * @len:  an int * to save the length of the attribute
9158 * @alloc:  an int * to indicate if the attribute was allocated
9159 *
9160 * parse an attribute in the new SAX2 framework.
9161 *
9162 * Returns the attribute name, and the value in *value, .
9163 */
9164
9165static const xmlChar *
9166xmlParseAttribute2(xmlParserCtxtPtr ctxt,
9167                   const xmlChar * pref, const xmlChar * elem,
9168                   const xmlChar ** prefix, xmlChar ** value,
9169                   int *len, int *alloc)
9170{
9171    const xmlChar *name;
9172    xmlChar *val, *internal_val = NULL;
9173    int normalize = 0;
9174
9175    *value = NULL;
9176    GROW;
9177    name = xmlParseQName(ctxt, prefix);
9178    if (name == NULL) {
9179        xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
9180                       "error parsing attribute name\n");
9181        return (NULL);
9182    }
9183
9184    /*
9185     * get the type if needed
9186     */
9187    if (ctxt->attsSpecial != NULL) {
9188        int type;
9189
9190        type = (int) (long) xmlHashQLookup2(ctxt->attsSpecial,
9191                                            pref, elem, *prefix, name);
9192        if (type != 0)
9193            normalize = 1;
9194    }
9195
9196    /*
9197     * read the value
9198     */
9199    SKIP_BLANKS;
9200    if (RAW == '=') {
9201        NEXT;
9202        SKIP_BLANKS;
9203        val = xmlParseAttValueInternal(ctxt, len, alloc, normalize);
9204	if (normalize) {
9205	    /*
9206	     * Sometimes a second normalisation pass for spaces is needed
9207	     * but that only happens if charrefs or entities refernces
9208	     * have been used in the attribute value, i.e. the attribute
9209	     * value have been extracted in an allocated string already.
9210	     */
9211	    if (*alloc) {
9212	        const xmlChar *val2;
9213
9214	        val2 = xmlAttrNormalizeSpace2(ctxt, val, len);
9215		if ((val2 != NULL) && (val2 != val)) {
9216		    xmlFree(val);
9217		    val = (xmlChar *) val2;
9218		}
9219	    }
9220	}
9221        ctxt->instate = XML_PARSER_CONTENT;
9222    } else {
9223        xmlFatalErrMsgStr(ctxt, XML_ERR_ATTRIBUTE_WITHOUT_VALUE,
9224                          "Specification mandate value for attribute %s\n",
9225                          name);
9226        return (NULL);
9227    }
9228
9229    if (*prefix == ctxt->str_xml) {
9230        /*
9231         * Check that xml:lang conforms to the specification
9232         * No more registered as an error, just generate a warning now
9233         * since this was deprecated in XML second edition
9234         */
9235        if ((ctxt->pedantic) && (xmlStrEqual(name, BAD_CAST "lang"))) {
9236            internal_val = xmlStrndup(val, *len);
9237            if (!xmlCheckLanguageID(internal_val)) {
9238                xmlWarningMsg(ctxt, XML_WAR_LANG_VALUE,
9239                              "Malformed value for xml:lang : %s\n",
9240                              internal_val, NULL);
9241            }
9242        }
9243
9244        /*
9245         * Check that xml:space conforms to the specification
9246         */
9247        if (xmlStrEqual(name, BAD_CAST "space")) {
9248            internal_val = xmlStrndup(val, *len);
9249            if (xmlStrEqual(internal_val, BAD_CAST "default"))
9250                *(ctxt->space) = 0;
9251            else if (xmlStrEqual(internal_val, BAD_CAST "preserve"))
9252                *(ctxt->space) = 1;
9253            else {
9254                xmlWarningMsg(ctxt, XML_WAR_SPACE_VALUE,
9255                              "Invalid value \"%s\" for xml:space : \"default\" or \"preserve\" expected\n",
9256                              internal_val, NULL);
9257            }
9258        }
9259        if (internal_val) {
9260            xmlFree(internal_val);
9261        }
9262    }
9263
9264    *value = val;
9265    return (name);
9266}
9267/**
9268 * xmlParseStartTag2:
9269 * @ctxt:  an XML parser context
9270 *
9271 * parse a start of tag either for rule element or
9272 * EmptyElement. In both case we don't parse the tag closing chars.
9273 * This routine is called when running SAX2 parsing
9274 *
9275 * [40] STag ::= '<' Name (S Attribute)* S? '>'
9276 *
9277 * [ WFC: Unique Att Spec ]
9278 * No attribute name may appear more than once in the same start-tag or
9279 * empty-element tag.
9280 *
9281 * [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>'
9282 *
9283 * [ WFC: Unique Att Spec ]
9284 * No attribute name may appear more than once in the same start-tag or
9285 * empty-element tag.
9286 *
9287 * With namespace:
9288 *
9289 * [NS 8] STag ::= '<' QName (S Attribute)* S? '>'
9290 *
9291 * [NS 10] EmptyElement ::= '<' QName (S Attribute)* S? '/>'
9292 *
9293 * Returns the element name parsed
9294 */
9295
9296static const xmlChar *
9297xmlParseStartTag2(xmlParserCtxtPtr ctxt, const xmlChar **pref,
9298                  const xmlChar **URI, int *tlen) {
9299    const xmlChar *localname;
9300    const xmlChar *prefix;
9301    const xmlChar *attname;
9302    const xmlChar *aprefix;
9303    const xmlChar *nsname;
9304    xmlChar *attvalue;
9305    const xmlChar **atts = ctxt->atts;
9306    int maxatts = ctxt->maxatts;
9307    int nratts, nbatts, nbdef;
9308    int i, j, nbNs, attval, oldline, oldcol;
9309    const xmlChar *base;
9310    unsigned long cur;
9311    int nsNr = ctxt->nsNr;
9312
9313    if (RAW != '<') return(NULL);
9314    NEXT1;
9315
9316    /*
9317     * NOTE: it is crucial with the SAX2 API to never call SHRINK beyond that
9318     *       point since the attribute values may be stored as pointers to
9319     *       the buffer and calling SHRINK would destroy them !
9320     *       The Shrinking is only possible once the full set of attribute
9321     *       callbacks have been done.
9322     */
9323reparse:
9324    SHRINK;
9325    base = ctxt->input->base;
9326    cur = ctxt->input->cur - ctxt->input->base;
9327    oldline = ctxt->input->line;
9328    oldcol = ctxt->input->col;
9329    nbatts = 0;
9330    nratts = 0;
9331    nbdef = 0;
9332    nbNs = 0;
9333    attval = 0;
9334    /* Forget any namespaces added during an earlier parse of this element. */
9335    ctxt->nsNr = nsNr;
9336
9337    localname = xmlParseQName(ctxt, &prefix);
9338    if (localname == NULL) {
9339	xmlFatalErrMsg(ctxt, XML_ERR_NAME_REQUIRED,
9340		       "StartTag: invalid element name\n");
9341        return(NULL);
9342    }
9343    *tlen = ctxt->input->cur - ctxt->input->base - cur;
9344
9345    /*
9346     * Now parse the attributes, it ends up with the ending
9347     *
9348     * (S Attribute)* S?
9349     */
9350    SKIP_BLANKS;
9351    GROW;
9352    if (ctxt->input->base != base) goto base_changed;
9353
9354    while (((RAW != '>') &&
9355	   ((RAW != '/') || (NXT(1) != '>')) &&
9356	   (IS_BYTE_CHAR(RAW))) && (ctxt->instate != XML_PARSER_EOF)) {
9357	const xmlChar *q = CUR_PTR;
9358	unsigned int cons = ctxt->input->consumed;
9359	int len = -1, alloc = 0;
9360
9361	attname = xmlParseAttribute2(ctxt, prefix, localname,
9362	                             &aprefix, &attvalue, &len, &alloc);
9363	if (ctxt->input->base != base) {
9364	    if ((attvalue != NULL) && (alloc != 0))
9365	        xmlFree(attvalue);
9366	    attvalue = NULL;
9367	    goto base_changed;
9368	}
9369        if ((attname != NULL) && (attvalue != NULL)) {
9370	    if (len < 0) len = xmlStrlen(attvalue);
9371            if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9372	        const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
9373		xmlURIPtr uri;
9374
9375                if (URL == NULL) {
9376		    xmlErrMemory(ctxt, "dictionary allocation failure");
9377		    if ((attvalue != NULL) && (alloc != 0))
9378			xmlFree(attvalue);
9379		    return(NULL);
9380		}
9381                if (*URL != 0) {
9382		    uri = xmlParseURI((const char *) URL);
9383		    if (uri == NULL) {
9384			xmlNsErr(ctxt, XML_WAR_NS_URI,
9385			         "xmlns: '%s' is not a valid URI\n",
9386					   URL, NULL, NULL);
9387		    } else {
9388			if (uri->scheme == NULL) {
9389			    xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9390				      "xmlns: URI %s is not absolute\n",
9391				      URL, NULL, NULL);
9392			}
9393			xmlFreeURI(uri);
9394		    }
9395		    if (URL == ctxt->str_xml_ns) {
9396			if (attname != ctxt->str_xml) {
9397			    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9398			 "xml namespace URI cannot be the default namespace\n",
9399				     NULL, NULL, NULL);
9400			}
9401			goto skip_default_ns;
9402		    }
9403		    if ((len == 29) &&
9404			(xmlStrEqual(URL,
9405				 BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9406			xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9407			     "reuse of the xmlns namespace name is forbidden\n",
9408				 NULL, NULL, NULL);
9409			goto skip_default_ns;
9410		    }
9411		}
9412		/*
9413		 * check that it's not a defined namespace
9414		 */
9415		for (j = 1;j <= nbNs;j++)
9416		    if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
9417			break;
9418		if (j <= nbNs)
9419		    xmlErrAttributeDup(ctxt, NULL, attname);
9420		else
9421		    if (nsPush(ctxt, NULL, URL) > 0) nbNs++;
9422skip_default_ns:
9423		if (alloc != 0) xmlFree(attvalue);
9424		if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
9425		    break;
9426		if (!IS_BLANK_CH(RAW)) {
9427		    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
9428				   "attributes construct error\n");
9429		    break;
9430		}
9431		SKIP_BLANKS;
9432		continue;
9433	    }
9434            if (aprefix == ctxt->str_xmlns) {
9435	        const xmlChar *URL = xmlDictLookup(ctxt->dict, attvalue, len);
9436		xmlURIPtr uri;
9437
9438                if (attname == ctxt->str_xml) {
9439		    if (URL != ctxt->str_xml_ns) {
9440		        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9441			         "xml namespace prefix mapped to wrong URI\n",
9442			         NULL, NULL, NULL);
9443		    }
9444		    /*
9445		     * Do not keep a namespace definition node
9446		     */
9447		    goto skip_ns;
9448		}
9449                if (URL == ctxt->str_xml_ns) {
9450		    if (attname != ctxt->str_xml) {
9451		        xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9452			         "xml namespace URI mapped to wrong prefix\n",
9453			         NULL, NULL, NULL);
9454		    }
9455		    goto skip_ns;
9456		}
9457                if (attname == ctxt->str_xmlns) {
9458		    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9459			     "redefinition of the xmlns prefix is forbidden\n",
9460			     NULL, NULL, NULL);
9461		    goto skip_ns;
9462		}
9463		if ((len == 29) &&
9464		    (xmlStrEqual(URL,
9465		                 BAD_CAST "http://www.w3.org/2000/xmlns/"))) {
9466		    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9467			     "reuse of the xmlns namespace name is forbidden\n",
9468			     NULL, NULL, NULL);
9469		    goto skip_ns;
9470		}
9471		if ((URL == NULL) || (URL[0] == 0)) {
9472		    xmlNsErr(ctxt, XML_NS_ERR_XML_NAMESPACE,
9473		             "xmlns:%s: Empty XML namespace is not allowed\n",
9474			          attname, NULL, NULL);
9475		    goto skip_ns;
9476		} else {
9477		    uri = xmlParseURI((const char *) URL);
9478		    if (uri == NULL) {
9479			xmlNsErr(ctxt, XML_WAR_NS_URI,
9480			     "xmlns:%s: '%s' is not a valid URI\n",
9481					   attname, URL, NULL);
9482		    } else {
9483			if ((ctxt->pedantic) && (uri->scheme == NULL)) {
9484			    xmlNsWarn(ctxt, XML_WAR_NS_URI_RELATIVE,
9485				      "xmlns:%s: URI %s is not absolute\n",
9486				      attname, URL, NULL);
9487			}
9488			xmlFreeURI(uri);
9489		    }
9490		}
9491
9492		/*
9493		 * check that it's not a defined namespace
9494		 */
9495		for (j = 1;j <= nbNs;j++)
9496		    if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
9497			break;
9498		if (j <= nbNs)
9499		    xmlErrAttributeDup(ctxt, aprefix, attname);
9500		else
9501		    if (nsPush(ctxt, attname, URL) > 0) nbNs++;
9502skip_ns:
9503		if (alloc != 0) xmlFree(attvalue);
9504		if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
9505		    break;
9506		if (!IS_BLANK_CH(RAW)) {
9507		    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
9508				   "attributes construct error\n");
9509		    break;
9510		}
9511		SKIP_BLANKS;
9512		if (ctxt->input->base != base) goto base_changed;
9513		continue;
9514	    }
9515
9516	    /*
9517	     * Add the pair to atts
9518	     */
9519	    if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9520	        if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9521		    if (attvalue[len] == 0)
9522			xmlFree(attvalue);
9523		    goto failed;
9524		}
9525	        maxatts = ctxt->maxatts;
9526		atts = ctxt->atts;
9527	    }
9528	    ctxt->attallocs[nratts++] = alloc;
9529	    atts[nbatts++] = attname;
9530	    atts[nbatts++] = aprefix;
9531	    atts[nbatts++] = NULL; /* the URI will be fetched later */
9532	    atts[nbatts++] = attvalue;
9533	    attvalue += len;
9534	    atts[nbatts++] = attvalue;
9535	    /*
9536	     * tag if some deallocation is needed
9537	     */
9538	    if (alloc != 0) attval = 1;
9539	} else {
9540	    if ((attvalue != NULL) && (attvalue[len] == 0))
9541		xmlFree(attvalue);
9542	}
9543
9544failed:
9545
9546	GROW
9547        if (ctxt->instate == XML_PARSER_EOF)
9548            break;
9549	if (ctxt->input->base != base) goto base_changed;
9550	if ((RAW == '>') || (((RAW == '/') && (NXT(1) == '>'))))
9551	    break;
9552	if (!IS_BLANK_CH(RAW)) {
9553	    xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
9554			   "attributes construct error\n");
9555	    break;
9556	}
9557	SKIP_BLANKS;
9558        if ((cons == ctxt->input->consumed) && (q == CUR_PTR) &&
9559            (attname == NULL) && (attvalue == NULL)) {
9560	    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
9561	         "xmlParseStartTag: problem parsing attributes\n");
9562	    break;
9563	}
9564        GROW;
9565	if (ctxt->input->base != base) goto base_changed;
9566    }
9567
9568    /*
9569     * The attributes defaulting
9570     */
9571    if (ctxt->attsDefault != NULL) {
9572        xmlDefAttrsPtr defaults;
9573
9574	defaults = xmlHashLookup2(ctxt->attsDefault, localname, prefix);
9575	if (defaults != NULL) {
9576	    for (i = 0;i < defaults->nbAttrs;i++) {
9577	        attname = defaults->values[5 * i];
9578		aprefix = defaults->values[5 * i + 1];
9579
9580                /*
9581		 * special work for namespaces defaulted defs
9582		 */
9583		if ((attname == ctxt->str_xmlns) && (aprefix == NULL)) {
9584		    /*
9585		     * check that it's not a defined namespace
9586		     */
9587		    for (j = 1;j <= nbNs;j++)
9588		        if (ctxt->nsTab[ctxt->nsNr - 2 * j] == NULL)
9589			    break;
9590	            if (j <= nbNs) continue;
9591
9592		    nsname = xmlGetNamespace(ctxt, NULL);
9593		    if (nsname != defaults->values[5 * i + 2]) {
9594			if (nsPush(ctxt, NULL,
9595			           defaults->values[5 * i + 2]) > 0)
9596			    nbNs++;
9597		    }
9598		} else if (aprefix == ctxt->str_xmlns) {
9599		    /*
9600		     * check that it's not a defined namespace
9601		     */
9602		    for (j = 1;j <= nbNs;j++)
9603		        if (ctxt->nsTab[ctxt->nsNr - 2 * j] == attname)
9604			    break;
9605	            if (j <= nbNs) continue;
9606
9607		    nsname = xmlGetNamespace(ctxt, attname);
9608		    if (nsname != defaults->values[2]) {
9609			if (nsPush(ctxt, attname,
9610			           defaults->values[5 * i + 2]) > 0)
9611			    nbNs++;
9612		    }
9613		} else {
9614		    /*
9615		     * check that it's not a defined attribute
9616		     */
9617		    for (j = 0;j < nbatts;j+=5) {
9618			if ((attname == atts[j]) && (aprefix == atts[j+1]))
9619			    break;
9620		    }
9621		    if (j < nbatts) continue;
9622
9623		    if ((atts == NULL) || (nbatts + 5 > maxatts)) {
9624			if (xmlCtxtGrowAttrs(ctxt, nbatts + 5) < 0) {
9625			    return(NULL);
9626			}
9627			maxatts = ctxt->maxatts;
9628			atts = ctxt->atts;
9629		    }
9630		    atts[nbatts++] = attname;
9631		    atts[nbatts++] = aprefix;
9632		    if (aprefix == NULL)
9633			atts[nbatts++] = NULL;
9634		    else
9635		        atts[nbatts++] = xmlGetNamespace(ctxt, aprefix);
9636		    atts[nbatts++] = defaults->values[5 * i + 2];
9637		    atts[nbatts++] = defaults->values[5 * i + 3];
9638		    if ((ctxt->standalone == 1) &&
9639		        (defaults->values[5 * i + 4] != NULL)) {
9640			xmlValidityError(ctxt, XML_DTD_STANDALONE_DEFAULTED,
9641	  "standalone: attribute %s on %s defaulted from external subset\n",
9642	                                 attname, localname);
9643		    }
9644		    nbdef++;
9645		}
9646	    }
9647	}
9648    }
9649
9650    /*
9651     * The attributes checkings
9652     */
9653    for (i = 0; i < nbatts;i += 5) {
9654        /*
9655	* The default namespace does not apply to attribute names.
9656	*/
9657	if (atts[i + 1] != NULL) {
9658	    nsname = xmlGetNamespace(ctxt, atts[i + 1]);
9659	    if (nsname == NULL) {
9660		xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9661		    "Namespace prefix %s for %s on %s is not defined\n",
9662		    atts[i + 1], atts[i], localname);
9663	    }
9664	    atts[i + 2] = nsname;
9665	} else
9666	    nsname = NULL;
9667	/*
9668	 * [ WFC: Unique Att Spec ]
9669	 * No attribute name may appear more than once in the same
9670	 * start-tag or empty-element tag.
9671	 * As extended by the Namespace in XML REC.
9672	 */
9673        for (j = 0; j < i;j += 5) {
9674	    if (atts[i] == atts[j]) {
9675	        if (atts[i+1] == atts[j+1]) {
9676		    xmlErrAttributeDup(ctxt, atts[i+1], atts[i]);
9677		    break;
9678		}
9679		if ((nsname != NULL) && (atts[j + 2] == nsname)) {
9680		    xmlNsErr(ctxt, XML_NS_ERR_ATTRIBUTE_REDEFINED,
9681			     "Namespaced Attribute %s in '%s' redefined\n",
9682			     atts[i], nsname, NULL);
9683		    break;
9684		}
9685	    }
9686	}
9687    }
9688
9689    nsname = xmlGetNamespace(ctxt, prefix);
9690    if ((prefix != NULL) && (nsname == NULL)) {
9691	xmlNsErr(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
9692	         "Namespace prefix %s on %s is not defined\n",
9693		 prefix, localname, NULL);
9694    }
9695    *pref = prefix;
9696    *URI = nsname;
9697
9698    /*
9699     * SAX: Start of Element !
9700     */
9701    if ((ctxt->sax != NULL) && (ctxt->sax->startElementNs != NULL) &&
9702	(!ctxt->disableSAX)) {
9703	if (nbNs > 0)
9704	    ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
9705			  nsname, nbNs, &ctxt->nsTab[ctxt->nsNr - 2 * nbNs],
9706			  nbatts / 5, nbdef, atts);
9707	else
9708	    ctxt->sax->startElementNs(ctxt->userData, localname, prefix,
9709	                  nsname, 0, NULL, nbatts / 5, nbdef, atts);
9710    }
9711
9712    /*
9713     * Free up attribute allocated strings if needed
9714     */
9715    if (attval != 0) {
9716	for (i = 3,j = 0; j < nratts;i += 5,j++)
9717	    if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
9718	        xmlFree((xmlChar *) atts[i]);
9719    }
9720
9721    return(localname);
9722
9723base_changed:
9724    /*
9725     * the attribute strings are valid iif the base didn't changed
9726     */
9727    if (attval != 0) {
9728	for (i = 3,j = 0; j < nratts;i += 5,j++)
9729	    if ((ctxt->attallocs[j] != 0) && (atts[i] != NULL))
9730	        xmlFree((xmlChar *) atts[i]);
9731    }
9732    ctxt->input->cur = ctxt->input->base + cur;
9733    ctxt->input->line = oldline;
9734    ctxt->input->col = oldcol;
9735    if (ctxt->wellFormed == 1) {
9736	goto reparse;
9737    }
9738    return(NULL);
9739}
9740
9741/**
9742 * xmlParseEndTag2:
9743 * @ctxt:  an XML parser context
9744 * @line:  line of the start tag
9745 * @nsNr:  number of namespaces on the start tag
9746 *
9747 * parse an end of tag
9748 *
9749 * [42] ETag ::= '</' Name S? '>'
9750 *
9751 * With namespace
9752 *
9753 * [NS 9] ETag ::= '</' QName S? '>'
9754 */
9755
9756static void
9757xmlParseEndTag2(xmlParserCtxtPtr ctxt, const xmlChar *prefix,
9758                const xmlChar *URI, int line, int nsNr, int tlen) {
9759    const xmlChar *name;
9760
9761    GROW;
9762    if ((RAW != '<') || (NXT(1) != '/')) {
9763	xmlFatalErr(ctxt, XML_ERR_LTSLASH_REQUIRED, NULL);
9764	return;
9765    }
9766    SKIP(2);
9767
9768    if ((tlen > 0) && (xmlStrncmp(ctxt->input->cur, ctxt->name, tlen) == 0)) {
9769        if (ctxt->input->cur[tlen] == '>') {
9770	    ctxt->input->cur += tlen + 1;
9771	    ctxt->input->col += tlen + 1;
9772	    goto done;
9773	}
9774	ctxt->input->cur += tlen;
9775	ctxt->input->col += tlen;
9776	name = (xmlChar*)1;
9777    } else {
9778	if (prefix == NULL)
9779	    name = xmlParseNameAndCompare(ctxt, ctxt->name);
9780	else
9781	    name = xmlParseQNameAndCompare(ctxt, ctxt->name, prefix);
9782    }
9783
9784    /*
9785     * We should definitely be at the ending "S? '>'" part
9786     */
9787    GROW;
9788    if (ctxt->instate == XML_PARSER_EOF)
9789        return;
9790    SKIP_BLANKS;
9791    if ((!IS_BYTE_CHAR(RAW)) || (RAW != '>')) {
9792	xmlFatalErr(ctxt, XML_ERR_GT_REQUIRED, NULL);
9793    } else
9794	NEXT1;
9795
9796    /*
9797     * [ WFC: Element Type Match ]
9798     * The Name in an element's end-tag must match the element type in the
9799     * start-tag.
9800     *
9801     */
9802    if (name != (xmlChar*)1) {
9803        if (name == NULL) name = BAD_CAST "unparseable";
9804        if ((line == 0) && (ctxt->node != NULL))
9805            line = ctxt->node->line;
9806        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NAME_MISMATCH,
9807		     "Opening and ending tag mismatch: %s line %d and %s\n",
9808		                ctxt->name, line, name);
9809    }
9810
9811    /*
9812     * SAX: End of Tag
9813     */
9814done:
9815    if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
9816	(!ctxt->disableSAX))
9817	ctxt->sax->endElementNs(ctxt->userData, ctxt->name, prefix, URI);
9818
9819    spacePop(ctxt);
9820    if (nsNr != 0)
9821	nsPop(ctxt, nsNr);
9822    return;
9823}
9824
9825/**
9826 * xmlParseCDSect:
9827 * @ctxt:  an XML parser context
9828 *
9829 * Parse escaped pure raw content.
9830 *
9831 * [18] CDSect ::= CDStart CData CDEnd
9832 *
9833 * [19] CDStart ::= '<![CDATA['
9834 *
9835 * [20] Data ::= (Char* - (Char* ']]>' Char*))
9836 *
9837 * [21] CDEnd ::= ']]>'
9838 */
9839void
9840xmlParseCDSect(xmlParserCtxtPtr ctxt) {
9841    xmlChar *buf = NULL;
9842    int len = 0;
9843    int size = XML_PARSER_BUFFER_SIZE;
9844    int r, rl;
9845    int	s, sl;
9846    int cur, l;
9847    int count = 0;
9848
9849    /* Check 2.6.0 was NXT(0) not RAW */
9850    if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
9851	SKIP(9);
9852    } else
9853        return;
9854
9855    ctxt->instate = XML_PARSER_CDATA_SECTION;
9856    r = CUR_CHAR(rl);
9857    if (!IS_CHAR(r)) {
9858	xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
9859	ctxt->instate = XML_PARSER_CONTENT;
9860        return;
9861    }
9862    NEXTL(rl);
9863    s = CUR_CHAR(sl);
9864    if (!IS_CHAR(s)) {
9865	xmlFatalErr(ctxt, XML_ERR_CDATA_NOT_FINISHED, NULL);
9866	ctxt->instate = XML_PARSER_CONTENT;
9867        return;
9868    }
9869    NEXTL(sl);
9870    cur = CUR_CHAR(l);
9871    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
9872    if (buf == NULL) {
9873	xmlErrMemory(ctxt, NULL);
9874	return;
9875    }
9876    while (IS_CHAR(cur) &&
9877           ((r != ']') || (s != ']') || (cur != '>'))) {
9878	if (len + 5 >= size) {
9879	    xmlChar *tmp;
9880
9881            if ((size > XML_MAX_TEXT_LENGTH) &&
9882                ((ctxt->options & XML_PARSE_HUGE) == 0)) {
9883                xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
9884                             "CData section too big found", NULL);
9885                xmlFree (buf);
9886                return;
9887            }
9888	    tmp = (xmlChar *) xmlRealloc(buf, size * 2 * sizeof(xmlChar));
9889	    if (tmp == NULL) {
9890	        xmlFree(buf);
9891		xmlErrMemory(ctxt, NULL);
9892		return;
9893	    }
9894	    buf = tmp;
9895	    size *= 2;
9896	}
9897	COPY_BUF(rl,buf,len,r);
9898	r = s;
9899	rl = sl;
9900	s = cur;
9901	sl = l;
9902	count++;
9903	if (count > 50) {
9904	    GROW;
9905            if (ctxt->instate == XML_PARSER_EOF) {
9906		xmlFree(buf);
9907		return;
9908            }
9909	    count = 0;
9910	}
9911	NEXTL(l);
9912	cur = CUR_CHAR(l);
9913    }
9914    buf[len] = 0;
9915    ctxt->instate = XML_PARSER_CONTENT;
9916    if (cur != '>') {
9917	xmlFatalErrMsgStr(ctxt, XML_ERR_CDATA_NOT_FINISHED,
9918	                     "CData section not finished\n%.50s\n", buf);
9919	xmlFree(buf);
9920        return;
9921    }
9922    NEXTL(l);
9923
9924    /*
9925     * OK the buffer is to be consumed as cdata.
9926     */
9927    if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
9928	if (ctxt->sax->cdataBlock != NULL)
9929	    ctxt->sax->cdataBlock(ctxt->userData, buf, len);
9930	else if (ctxt->sax->characters != NULL)
9931	    ctxt->sax->characters(ctxt->userData, buf, len);
9932    }
9933    xmlFree(buf);
9934}
9935
9936/**
9937 * xmlParseContent:
9938 * @ctxt:  an XML parser context
9939 *
9940 * Parse a content:
9941 *
9942 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
9943 */
9944
9945void
9946xmlParseContent(xmlParserCtxtPtr ctxt) {
9947    GROW;
9948    while ((RAW != 0) &&
9949	   ((RAW != '<') || (NXT(1) != '/')) &&
9950	   (ctxt->instate != XML_PARSER_EOF)) {
9951	const xmlChar *test = CUR_PTR;
9952	unsigned int cons = ctxt->input->consumed;
9953	const xmlChar *cur = ctxt->input->cur;
9954
9955	/*
9956	 * First case : a Processing Instruction.
9957	 */
9958	if ((*cur == '<') && (cur[1] == '?')) {
9959	    xmlParsePI(ctxt);
9960	}
9961
9962	/*
9963	 * Second case : a CDSection
9964	 */
9965	/* 2.6.0 test was *cur not RAW */
9966	else if (CMP9(CUR_PTR, '<', '!', '[', 'C', 'D', 'A', 'T', 'A', '[')) {
9967	    xmlParseCDSect(ctxt);
9968	}
9969
9970	/*
9971	 * Third case :  a comment
9972	 */
9973	else if ((*cur == '<') && (NXT(1) == '!') &&
9974		 (NXT(2) == '-') && (NXT(3) == '-')) {
9975	    xmlParseComment(ctxt);
9976	    ctxt->instate = XML_PARSER_CONTENT;
9977	}
9978
9979	/*
9980	 * Fourth case :  a sub-element.
9981	 */
9982	else if (*cur == '<') {
9983	    xmlParseElement(ctxt);
9984	}
9985
9986	/*
9987	 * Fifth case : a reference. If if has not been resolved,
9988	 *    parsing returns it's Name, create the node
9989	 */
9990
9991	else if (*cur == '&') {
9992	    xmlParseReference(ctxt);
9993	}
9994
9995	/*
9996	 * Last case, text. Note that References are handled directly.
9997	 */
9998	else {
9999	    xmlParseCharData(ctxt, 0);
10000	}
10001
10002	GROW;
10003	/*
10004	 * Pop-up of finished entities.
10005	 */
10006	while ((RAW == 0) && (ctxt->inputNr > 1))
10007	    xmlPopInput(ctxt);
10008	SHRINK;
10009
10010	if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
10011	    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
10012	                "detected an error in element content\n");
10013	    ctxt->instate = XML_PARSER_EOF;
10014            break;
10015	}
10016    }
10017}
10018
10019/**
10020 * xmlParseElement:
10021 * @ctxt:  an XML parser context
10022 *
10023 * parse an XML element, this is highly recursive
10024 *
10025 * [39] element ::= EmptyElemTag | STag content ETag
10026 *
10027 * [ WFC: Element Type Match ]
10028 * The Name in an element's end-tag must match the element type in the
10029 * start-tag.
10030 *
10031 */
10032
10033void
10034xmlParseElement(xmlParserCtxtPtr ctxt) {
10035    const xmlChar *name;
10036    const xmlChar *prefix = NULL;
10037    const xmlChar *URI = NULL;
10038    xmlParserNodeInfo node_info;
10039    int line, tlen = 0;
10040    xmlNodePtr ret;
10041    int nsNr = ctxt->nsNr;
10042
10043    if (((unsigned int) ctxt->nameNr > xmlParserMaxDepth) &&
10044        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
10045	xmlFatalErrMsgInt(ctxt, XML_ERR_INTERNAL_ERROR,
10046		 "Excessive depth in document: %d use XML_PARSE_HUGE option\n",
10047			  xmlParserMaxDepth);
10048	ctxt->instate = XML_PARSER_EOF;
10049	return;
10050    }
10051
10052    /* Capture start position */
10053    if (ctxt->record_info) {
10054        node_info.begin_pos = ctxt->input->consumed +
10055                          (CUR_PTR - ctxt->input->base);
10056	node_info.begin_line = ctxt->input->line;
10057    }
10058
10059    if (ctxt->spaceNr == 0)
10060	spacePush(ctxt, -1);
10061    else if (*ctxt->space == -2)
10062	spacePush(ctxt, -1);
10063    else
10064	spacePush(ctxt, *ctxt->space);
10065
10066    line = ctxt->input->line;
10067#ifdef LIBXML_SAX1_ENABLED
10068    if (ctxt->sax2)
10069#endif /* LIBXML_SAX1_ENABLED */
10070        name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
10071#ifdef LIBXML_SAX1_ENABLED
10072    else
10073	name = xmlParseStartTag(ctxt);
10074#endif /* LIBXML_SAX1_ENABLED */
10075    if (ctxt->instate == XML_PARSER_EOF)
10076	return;
10077    if (name == NULL) {
10078	spacePop(ctxt);
10079        return;
10080    }
10081    namePush(ctxt, name);
10082    ret = ctxt->node;
10083
10084#ifdef LIBXML_VALID_ENABLED
10085    /*
10086     * [ VC: Root Element Type ]
10087     * The Name in the document type declaration must match the element
10088     * type of the root element.
10089     */
10090    if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
10091        ctxt->node && (ctxt->node == ctxt->myDoc->children))
10092        ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
10093#endif /* LIBXML_VALID_ENABLED */
10094
10095    /*
10096     * Check for an Empty Element.
10097     */
10098    if ((RAW == '/') && (NXT(1) == '>')) {
10099        SKIP(2);
10100	if (ctxt->sax2) {
10101	    if ((ctxt->sax != NULL) && (ctxt->sax->endElementNs != NULL) &&
10102		(!ctxt->disableSAX))
10103		ctxt->sax->endElementNs(ctxt->userData, name, prefix, URI);
10104#ifdef LIBXML_SAX1_ENABLED
10105	} else {
10106	    if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
10107		(!ctxt->disableSAX))
10108		ctxt->sax->endElement(ctxt->userData, name);
10109#endif /* LIBXML_SAX1_ENABLED */
10110	}
10111	namePop(ctxt);
10112	spacePop(ctxt);
10113	if (nsNr != ctxt->nsNr)
10114	    nsPop(ctxt, ctxt->nsNr - nsNr);
10115	if ( ret != NULL && ctxt->record_info ) {
10116	   node_info.end_pos = ctxt->input->consumed +
10117			      (CUR_PTR - ctxt->input->base);
10118	   node_info.end_line = ctxt->input->line;
10119	   node_info.node = ret;
10120	   xmlParserAddNodeInfo(ctxt, &node_info);
10121	}
10122	return;
10123    }
10124    if (RAW == '>') {
10125        NEXT1;
10126    } else {
10127        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_GT_REQUIRED,
10128		     "Couldn't find end of Start Tag %s line %d\n",
10129		                name, line, NULL);
10130
10131	/*
10132	 * end of parsing of this node.
10133	 */
10134	nodePop(ctxt);
10135	namePop(ctxt);
10136	spacePop(ctxt);
10137	if (nsNr != ctxt->nsNr)
10138	    nsPop(ctxt, ctxt->nsNr - nsNr);
10139
10140	/*
10141	 * Capture end position and add node
10142	 */
10143	if ( ret != NULL && ctxt->record_info ) {
10144	   node_info.end_pos = ctxt->input->consumed +
10145			      (CUR_PTR - ctxt->input->base);
10146	   node_info.end_line = ctxt->input->line;
10147	   node_info.node = ret;
10148	   xmlParserAddNodeInfo(ctxt, &node_info);
10149	}
10150	return;
10151    }
10152
10153    /*
10154     * Parse the content of the element:
10155     */
10156    xmlParseContent(ctxt);
10157    if (ctxt->instate == XML_PARSER_EOF)
10158	return;
10159    if (!IS_BYTE_CHAR(RAW)) {
10160        xmlFatalErrMsgStrIntStr(ctxt, XML_ERR_TAG_NOT_FINISHED,
10161	 "Premature end of data in tag %s line %d\n",
10162		                name, line, NULL);
10163
10164	/*
10165	 * end of parsing of this node.
10166	 */
10167	nodePop(ctxt);
10168	namePop(ctxt);
10169	spacePop(ctxt);
10170	if (nsNr != ctxt->nsNr)
10171	    nsPop(ctxt, ctxt->nsNr - nsNr);
10172	return;
10173    }
10174
10175    /*
10176     * parse the end of tag: '</' should be here.
10177     */
10178    if (ctxt->sax2) {
10179	xmlParseEndTag2(ctxt, prefix, URI, line, ctxt->nsNr - nsNr, tlen);
10180	namePop(ctxt);
10181    }
10182#ifdef LIBXML_SAX1_ENABLED
10183      else
10184	xmlParseEndTag1(ctxt, line);
10185#endif /* LIBXML_SAX1_ENABLED */
10186
10187    /*
10188     * Capture end position and add node
10189     */
10190    if ( ret != NULL && ctxt->record_info ) {
10191       node_info.end_pos = ctxt->input->consumed +
10192                          (CUR_PTR - ctxt->input->base);
10193       node_info.end_line = ctxt->input->line;
10194       node_info.node = ret;
10195       xmlParserAddNodeInfo(ctxt, &node_info);
10196    }
10197}
10198
10199/**
10200 * xmlParseVersionNum:
10201 * @ctxt:  an XML parser context
10202 *
10203 * parse the XML version value.
10204 *
10205 * [26] VersionNum ::= '1.' [0-9]+
10206 *
10207 * In practice allow [0-9].[0-9]+ at that level
10208 *
10209 * Returns the string giving the XML version number, or NULL
10210 */
10211xmlChar *
10212xmlParseVersionNum(xmlParserCtxtPtr ctxt) {
10213    xmlChar *buf = NULL;
10214    int len = 0;
10215    int size = 10;
10216    xmlChar cur;
10217
10218    buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
10219    if (buf == NULL) {
10220	xmlErrMemory(ctxt, NULL);
10221	return(NULL);
10222    }
10223    cur = CUR;
10224    if (!((cur >= '0') && (cur <= '9'))) {
10225	xmlFree(buf);
10226	return(NULL);
10227    }
10228    buf[len++] = cur;
10229    NEXT;
10230    cur=CUR;
10231    if (cur != '.') {
10232	xmlFree(buf);
10233	return(NULL);
10234    }
10235    buf[len++] = cur;
10236    NEXT;
10237    cur=CUR;
10238    while ((cur >= '0') && (cur <= '9')) {
10239	if (len + 1 >= size) {
10240	    xmlChar *tmp;
10241
10242	    size *= 2;
10243	    tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
10244	    if (tmp == NULL) {
10245	        xmlFree(buf);
10246		xmlErrMemory(ctxt, NULL);
10247		return(NULL);
10248	    }
10249	    buf = tmp;
10250	}
10251	buf[len++] = cur;
10252	NEXT;
10253	cur=CUR;
10254    }
10255    buf[len] = 0;
10256    return(buf);
10257}
10258
10259/**
10260 * xmlParseVersionInfo:
10261 * @ctxt:  an XML parser context
10262 *
10263 * parse the XML version.
10264 *
10265 * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
10266 *
10267 * [25] Eq ::= S? '=' S?
10268 *
10269 * Returns the version string, e.g. "1.0"
10270 */
10271
10272xmlChar *
10273xmlParseVersionInfo(xmlParserCtxtPtr ctxt) {
10274    xmlChar *version = NULL;
10275
10276    if (CMP7(CUR_PTR, 'v', 'e', 'r', 's', 'i', 'o', 'n')) {
10277	SKIP(7);
10278	SKIP_BLANKS;
10279	if (RAW != '=') {
10280	    xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10281	    return(NULL);
10282        }
10283	NEXT;
10284	SKIP_BLANKS;
10285	if (RAW == '"') {
10286	    NEXT;
10287	    version = xmlParseVersionNum(ctxt);
10288	    if (RAW != '"') {
10289		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10290	    } else
10291	        NEXT;
10292	} else if (RAW == '\''){
10293	    NEXT;
10294	    version = xmlParseVersionNum(ctxt);
10295	    if (RAW != '\'') {
10296		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10297	    } else
10298	        NEXT;
10299	} else {
10300	    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10301	}
10302    }
10303    return(version);
10304}
10305
10306/**
10307 * xmlParseEncName:
10308 * @ctxt:  an XML parser context
10309 *
10310 * parse the XML encoding name
10311 *
10312 * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
10313 *
10314 * Returns the encoding name value or NULL
10315 */
10316xmlChar *
10317xmlParseEncName(xmlParserCtxtPtr ctxt) {
10318    xmlChar *buf = NULL;
10319    int len = 0;
10320    int size = 10;
10321    xmlChar cur;
10322
10323    cur = CUR;
10324    if (((cur >= 'a') && (cur <= 'z')) ||
10325        ((cur >= 'A') && (cur <= 'Z'))) {
10326	buf = (xmlChar *) xmlMallocAtomic(size * sizeof(xmlChar));
10327	if (buf == NULL) {
10328	    xmlErrMemory(ctxt, NULL);
10329	    return(NULL);
10330	}
10331
10332	buf[len++] = cur;
10333	NEXT;
10334	cur = CUR;
10335	while (((cur >= 'a') && (cur <= 'z')) ||
10336	       ((cur >= 'A') && (cur <= 'Z')) ||
10337	       ((cur >= '0') && (cur <= '9')) ||
10338	       (cur == '.') || (cur == '_') ||
10339	       (cur == '-')) {
10340	    if (len + 1 >= size) {
10341	        xmlChar *tmp;
10342
10343		size *= 2;
10344		tmp = (xmlChar *) xmlRealloc(buf, size * sizeof(xmlChar));
10345		if (tmp == NULL) {
10346		    xmlErrMemory(ctxt, NULL);
10347		    xmlFree(buf);
10348		    return(NULL);
10349		}
10350		buf = tmp;
10351	    }
10352	    buf[len++] = cur;
10353	    NEXT;
10354	    cur = CUR;
10355	    if (cur == 0) {
10356	        SHRINK;
10357		GROW;
10358		cur = CUR;
10359	    }
10360        }
10361	buf[len] = 0;
10362    } else {
10363	xmlFatalErr(ctxt, XML_ERR_ENCODING_NAME, NULL);
10364    }
10365    return(buf);
10366}
10367
10368/**
10369 * xmlParseEncodingDecl:
10370 * @ctxt:  an XML parser context
10371 *
10372 * parse the XML encoding declaration
10373 *
10374 * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'")
10375 *
10376 * this setups the conversion filters.
10377 *
10378 * Returns the encoding value or NULL
10379 */
10380
10381const xmlChar *
10382xmlParseEncodingDecl(xmlParserCtxtPtr ctxt) {
10383    xmlChar *encoding = NULL;
10384
10385    SKIP_BLANKS;
10386    if (CMP8(CUR_PTR, 'e', 'n', 'c', 'o', 'd', 'i', 'n', 'g')) {
10387	SKIP(8);
10388	SKIP_BLANKS;
10389	if (RAW != '=') {
10390	    xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10391	    return(NULL);
10392        }
10393	NEXT;
10394	SKIP_BLANKS;
10395	if (RAW == '"') {
10396	    NEXT;
10397	    encoding = xmlParseEncName(ctxt);
10398	    if (RAW != '"') {
10399		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10400	    } else
10401	        NEXT;
10402	} else if (RAW == '\''){
10403	    NEXT;
10404	    encoding = xmlParseEncName(ctxt);
10405	    if (RAW != '\'') {
10406		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10407	    } else
10408	        NEXT;
10409	} else {
10410	    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10411	}
10412
10413        /*
10414         * Non standard parsing, allowing the user to ignore encoding
10415         */
10416        if (ctxt->options & XML_PARSE_IGNORE_ENC) {
10417	    xmlFree((xmlChar *) encoding);
10418            return(NULL);
10419	}
10420
10421	/*
10422	 * UTF-16 encoding stwich has already taken place at this stage,
10423	 * more over the little-endian/big-endian selection is already done
10424	 */
10425        if ((encoding != NULL) &&
10426	    ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-16")) ||
10427	     (!xmlStrcasecmp(encoding, BAD_CAST "UTF16")))) {
10428	    /*
10429	     * If no encoding was passed to the parser, that we are
10430	     * using UTF-16 and no decoder is present i.e. the
10431	     * document is apparently UTF-8 compatible, then raise an
10432	     * encoding mismatch fatal error
10433	     */
10434	    if ((ctxt->encoding == NULL) &&
10435	        (ctxt->input->buf != NULL) &&
10436	        (ctxt->input->buf->encoder == NULL)) {
10437		xmlFatalErrMsg(ctxt, XML_ERR_INVALID_ENCODING,
10438		  "Document labelled UTF-16 but has UTF-8 content\n");
10439	    }
10440	    if (ctxt->encoding != NULL)
10441		xmlFree((xmlChar *) ctxt->encoding);
10442	    ctxt->encoding = encoding;
10443	}
10444	/*
10445	 * UTF-8 encoding is handled natively
10446	 */
10447        else if ((encoding != NULL) &&
10448	    ((!xmlStrcasecmp(encoding, BAD_CAST "UTF-8")) ||
10449	     (!xmlStrcasecmp(encoding, BAD_CAST "UTF8")))) {
10450	    if (ctxt->encoding != NULL)
10451		xmlFree((xmlChar *) ctxt->encoding);
10452	    ctxt->encoding = encoding;
10453	}
10454	else if (encoding != NULL) {
10455	    xmlCharEncodingHandlerPtr handler;
10456
10457	    if (ctxt->input->encoding != NULL)
10458		xmlFree((xmlChar *) ctxt->input->encoding);
10459	    ctxt->input->encoding = encoding;
10460
10461            handler = xmlFindCharEncodingHandler((const char *) encoding);
10462	    if (handler != NULL) {
10463		xmlSwitchToEncoding(ctxt, handler);
10464	    } else {
10465		xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
10466			"Unsupported encoding %s\n", encoding);
10467		return(NULL);
10468	    }
10469	}
10470    }
10471    return(encoding);
10472}
10473
10474/**
10475 * xmlParseSDDecl:
10476 * @ctxt:  an XML parser context
10477 *
10478 * parse the XML standalone declaration
10479 *
10480 * [32] SDDecl ::= S 'standalone' Eq
10481 *                 (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no')'"'))
10482 *
10483 * [ VC: Standalone Document Declaration ]
10484 * TODO The standalone document declaration must have the value "no"
10485 * if any external markup declarations contain declarations of:
10486 *  - attributes with default values, if elements to which these
10487 *    attributes apply appear in the document without specifications
10488 *    of values for these attributes, or
10489 *  - entities (other than amp, lt, gt, apos, quot), if references
10490 *    to those entities appear in the document, or
10491 *  - attributes with values subject to normalization, where the
10492 *    attribute appears in the document with a value which will change
10493 *    as a result of normalization, or
10494 *  - element types with element content, if white space occurs directly
10495 *    within any instance of those types.
10496 *
10497 * Returns:
10498 *   1 if standalone="yes"
10499 *   0 if standalone="no"
10500 *  -2 if standalone attribute is missing or invalid
10501 *	  (A standalone value of -2 means that the XML declaration was found,
10502 *	   but no value was specified for the standalone attribute).
10503 */
10504
10505int
10506xmlParseSDDecl(xmlParserCtxtPtr ctxt) {
10507    int standalone = -2;
10508
10509    SKIP_BLANKS;
10510    if (CMP10(CUR_PTR, 's', 't', 'a', 'n', 'd', 'a', 'l', 'o', 'n', 'e')) {
10511	SKIP(10);
10512        SKIP_BLANKS;
10513	if (RAW != '=') {
10514	    xmlFatalErr(ctxt, XML_ERR_EQUAL_REQUIRED, NULL);
10515	    return(standalone);
10516        }
10517	NEXT;
10518	SKIP_BLANKS;
10519        if (RAW == '\''){
10520	    NEXT;
10521	    if ((RAW == 'n') && (NXT(1) == 'o')) {
10522	        standalone = 0;
10523                SKIP(2);
10524	    } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10525	               (NXT(2) == 's')) {
10526	        standalone = 1;
10527		SKIP(3);
10528            } else {
10529		xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10530	    }
10531	    if (RAW != '\'') {
10532		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10533	    } else
10534	        NEXT;
10535	} else if (RAW == '"'){
10536	    NEXT;
10537	    if ((RAW == 'n') && (NXT(1) == 'o')) {
10538	        standalone = 0;
10539		SKIP(2);
10540	    } else if ((RAW == 'y') && (NXT(1) == 'e') &&
10541	               (NXT(2) == 's')) {
10542	        standalone = 1;
10543                SKIP(3);
10544            } else {
10545		xmlFatalErr(ctxt, XML_ERR_STANDALONE_VALUE, NULL);
10546	    }
10547	    if (RAW != '"') {
10548		xmlFatalErr(ctxt, XML_ERR_STRING_NOT_CLOSED, NULL);
10549	    } else
10550	        NEXT;
10551	} else {
10552	    xmlFatalErr(ctxt, XML_ERR_STRING_NOT_STARTED, NULL);
10553        }
10554    }
10555    return(standalone);
10556}
10557
10558/**
10559 * xmlParseXMLDecl:
10560 * @ctxt:  an XML parser context
10561 *
10562 * parse an XML declaration header
10563 *
10564 * [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
10565 */
10566
10567void
10568xmlParseXMLDecl(xmlParserCtxtPtr ctxt) {
10569    xmlChar *version;
10570
10571    /*
10572     * This value for standalone indicates that the document has an
10573     * XML declaration but it does not have a standalone attribute.
10574     * It will be overwritten later if a standalone attribute is found.
10575     */
10576    ctxt->input->standalone = -2;
10577
10578    /*
10579     * We know that '<?xml' is here.
10580     */
10581    SKIP(5);
10582
10583    if (!IS_BLANK_CH(RAW)) {
10584	xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED,
10585	               "Blank needed after '<?xml'\n");
10586    }
10587    SKIP_BLANKS;
10588
10589    /*
10590     * We must have the VersionInfo here.
10591     */
10592    version = xmlParseVersionInfo(ctxt);
10593    if (version == NULL) {
10594	xmlFatalErr(ctxt, XML_ERR_VERSION_MISSING, NULL);
10595    } else {
10596	if (!xmlStrEqual(version, (const xmlChar *) XML_DEFAULT_VERSION)) {
10597	    /*
10598	     * Changed here for XML-1.0 5th edition
10599	     */
10600	    if (ctxt->options & XML_PARSE_OLD10) {
10601		xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10602			          "Unsupported version '%s'\n",
10603			          version);
10604	    } else {
10605	        if ((version[0] == '1') && ((version[1] == '.'))) {
10606		    xmlWarningMsg(ctxt, XML_WAR_UNKNOWN_VERSION,
10607		                  "Unsupported version '%s'\n",
10608				  version, NULL);
10609		} else {
10610		    xmlFatalErrMsgStr(ctxt, XML_ERR_UNKNOWN_VERSION,
10611				      "Unsupported version '%s'\n",
10612				      version);
10613		}
10614	    }
10615	}
10616	if (ctxt->version != NULL)
10617	    xmlFree((void *) ctxt->version);
10618	ctxt->version = version;
10619    }
10620
10621    /*
10622     * We may have the encoding declaration
10623     */
10624    if (!IS_BLANK_CH(RAW)) {
10625        if ((RAW == '?') && (NXT(1) == '>')) {
10626	    SKIP(2);
10627	    return;
10628	}
10629	xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10630    }
10631    xmlParseEncodingDecl(ctxt);
10632    if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
10633	/*
10634	 * The XML REC instructs us to stop parsing right here
10635	 */
10636        return;
10637    }
10638
10639    /*
10640     * We may have the standalone status.
10641     */
10642    if ((ctxt->input->encoding != NULL) && (!IS_BLANK_CH(RAW))) {
10643        if ((RAW == '?') && (NXT(1) == '>')) {
10644	    SKIP(2);
10645	    return;
10646	}
10647	xmlFatalErrMsg(ctxt, XML_ERR_SPACE_REQUIRED, "Blank needed here\n");
10648    }
10649
10650    /*
10651     * We can grow the input buffer freely at that point
10652     */
10653    GROW;
10654
10655    SKIP_BLANKS;
10656    ctxt->input->standalone = xmlParseSDDecl(ctxt);
10657
10658    SKIP_BLANKS;
10659    if ((RAW == '?') && (NXT(1) == '>')) {
10660        SKIP(2);
10661    } else if (RAW == '>') {
10662        /* Deprecated old WD ... */
10663	xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10664	NEXT;
10665    } else {
10666	xmlFatalErr(ctxt, XML_ERR_XMLDECL_NOT_FINISHED, NULL);
10667	MOVETO_ENDTAG(CUR_PTR);
10668	NEXT;
10669    }
10670}
10671
10672/**
10673 * xmlParseMisc:
10674 * @ctxt:  an XML parser context
10675 *
10676 * parse an XML Misc* optional field.
10677 *
10678 * [27] Misc ::= Comment | PI |  S
10679 */
10680
10681void
10682xmlParseMisc(xmlParserCtxtPtr ctxt) {
10683    while ((ctxt->instate != XML_PARSER_EOF) &&
10684           (((RAW == '<') && (NXT(1) == '?')) ||
10685            (CMP4(CUR_PTR, '<', '!', '-', '-')) ||
10686            IS_BLANK_CH(CUR))) {
10687        if ((RAW == '<') && (NXT(1) == '?')) {
10688	    xmlParsePI(ctxt);
10689	} else if (IS_BLANK_CH(CUR)) {
10690	    NEXT;
10691	} else
10692	    xmlParseComment(ctxt);
10693    }
10694}
10695
10696/**
10697 * xmlParseDocument:
10698 * @ctxt:  an XML parser context
10699 *
10700 * parse an XML document (and build a tree if using the standard SAX
10701 * interface).
10702 *
10703 * [1] document ::= prolog element Misc*
10704 *
10705 * [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
10706 *
10707 * Returns 0, -1 in case of error. the parser context is augmented
10708 *                as a result of the parsing.
10709 */
10710
10711int
10712xmlParseDocument(xmlParserCtxtPtr ctxt) {
10713    xmlChar start[4];
10714    xmlCharEncoding enc;
10715
10716    xmlInitParser();
10717
10718    if ((ctxt == NULL) || (ctxt->input == NULL))
10719        return(-1);
10720
10721    GROW;
10722
10723    /*
10724     * SAX: detecting the level.
10725     */
10726    xmlDetectSAX2(ctxt);
10727
10728    /*
10729     * SAX: beginning of the document processing.
10730     */
10731    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10732        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
10733    if (ctxt->instate == XML_PARSER_EOF)
10734	return(-1);
10735
10736    if ((ctxt->encoding == NULL) &&
10737        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
10738	/*
10739	 * Get the 4 first bytes and decode the charset
10740	 * if enc != XML_CHAR_ENCODING_NONE
10741	 * plug some encoding conversion routines.
10742	 */
10743	start[0] = RAW;
10744	start[1] = NXT(1);
10745	start[2] = NXT(2);
10746	start[3] = NXT(3);
10747	enc = xmlDetectCharEncoding(&start[0], 4);
10748	if (enc != XML_CHAR_ENCODING_NONE) {
10749	    xmlSwitchEncoding(ctxt, enc);
10750	}
10751    }
10752
10753
10754    if (CUR == 0) {
10755	xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10756    }
10757
10758    /*
10759     * Check for the XMLDecl in the Prolog.
10760     * do not GROW here to avoid the detected encoder to decode more
10761     * than just the first line, unless the amount of data is really
10762     * too small to hold "<?xml version="1.0" encoding="foo"
10763     */
10764    if ((ctxt->input->end - ctxt->input->cur) < 35) {
10765       GROW;
10766    }
10767    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
10768
10769	/*
10770	 * Note that we will switch encoding on the fly.
10771	 */
10772	xmlParseXMLDecl(ctxt);
10773	if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
10774	    /*
10775	     * The XML REC instructs us to stop parsing right here
10776	     */
10777	    return(-1);
10778	}
10779	ctxt->standalone = ctxt->input->standalone;
10780	SKIP_BLANKS;
10781    } else {
10782	ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10783    }
10784    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
10785        ctxt->sax->startDocument(ctxt->userData);
10786    if (ctxt->instate == XML_PARSER_EOF)
10787	return(-1);
10788    if ((ctxt->myDoc != NULL) && (ctxt->input != NULL) &&
10789        (ctxt->input->buf != NULL) && (ctxt->input->buf->compressed >= 0)) {
10790	ctxt->myDoc->compression = ctxt->input->buf->compressed;
10791    }
10792
10793    /*
10794     * The Misc part of the Prolog
10795     */
10796    GROW;
10797    xmlParseMisc(ctxt);
10798
10799    /*
10800     * Then possibly doc type declaration(s) and more Misc
10801     * (doctypedecl Misc*)?
10802     */
10803    GROW;
10804    if (CMP9(CUR_PTR, '<', '!', 'D', 'O', 'C', 'T', 'Y', 'P', 'E')) {
10805
10806	ctxt->inSubset = 1;
10807	xmlParseDocTypeDecl(ctxt);
10808	if (RAW == '[') {
10809	    ctxt->instate = XML_PARSER_DTD;
10810	    xmlParseInternalSubset(ctxt);
10811	    if (ctxt->instate == XML_PARSER_EOF)
10812		return(-1);
10813	}
10814
10815	/*
10816	 * Create and update the external subset.
10817	 */
10818	ctxt->inSubset = 2;
10819	if ((ctxt->sax != NULL) && (ctxt->sax->externalSubset != NULL) &&
10820	    (!ctxt->disableSAX))
10821	    ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
10822	                              ctxt->extSubSystem, ctxt->extSubURI);
10823	if (ctxt->instate == XML_PARSER_EOF)
10824	    return(-1);
10825	ctxt->inSubset = 0;
10826
10827        xmlCleanSpecialAttr(ctxt);
10828
10829	ctxt->instate = XML_PARSER_PROLOG;
10830	xmlParseMisc(ctxt);
10831    }
10832
10833    /*
10834     * Time to start parsing the tree itself
10835     */
10836    GROW;
10837    if (RAW != '<') {
10838	xmlFatalErrMsg(ctxt, XML_ERR_DOCUMENT_EMPTY,
10839		       "Start tag expected, '<' not found\n");
10840    } else {
10841	ctxt->instate = XML_PARSER_CONTENT;
10842	xmlParseElement(ctxt);
10843	ctxt->instate = XML_PARSER_EPILOG;
10844
10845
10846	/*
10847	 * The Misc part at the end
10848	 */
10849	xmlParseMisc(ctxt);
10850
10851	if (RAW != 0) {
10852	    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
10853	}
10854	ctxt->instate = XML_PARSER_EOF;
10855    }
10856
10857    /*
10858     * SAX: end of the document processing.
10859     */
10860    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10861        ctxt->sax->endDocument(ctxt->userData);
10862
10863    /*
10864     * Remove locally kept entity definitions if the tree was not built
10865     */
10866    if ((ctxt->myDoc != NULL) &&
10867	(xmlStrEqual(ctxt->myDoc->version, SAX_COMPAT_MODE))) {
10868	xmlFreeDoc(ctxt->myDoc);
10869	ctxt->myDoc = NULL;
10870    }
10871
10872    if ((ctxt->wellFormed) && (ctxt->myDoc != NULL)) {
10873        ctxt->myDoc->properties |= XML_DOC_WELLFORMED;
10874	if (ctxt->valid)
10875	    ctxt->myDoc->properties |= XML_DOC_DTDVALID;
10876	if (ctxt->nsWellFormed)
10877	    ctxt->myDoc->properties |= XML_DOC_NSVALID;
10878	if (ctxt->options & XML_PARSE_OLD10)
10879	    ctxt->myDoc->properties |= XML_DOC_OLD10;
10880    }
10881    if (! ctxt->wellFormed) {
10882	ctxt->valid = 0;
10883	return(-1);
10884    }
10885    return(0);
10886}
10887
10888/**
10889 * xmlParseExtParsedEnt:
10890 * @ctxt:  an XML parser context
10891 *
10892 * parse a general parsed entity
10893 * An external general parsed entity is well-formed if it matches the
10894 * production labeled extParsedEnt.
10895 *
10896 * [78] extParsedEnt ::= TextDecl? content
10897 *
10898 * Returns 0, -1 in case of error. the parser context is augmented
10899 *                as a result of the parsing.
10900 */
10901
10902int
10903xmlParseExtParsedEnt(xmlParserCtxtPtr ctxt) {
10904    xmlChar start[4];
10905    xmlCharEncoding enc;
10906
10907    if ((ctxt == NULL) || (ctxt->input == NULL))
10908        return(-1);
10909
10910    xmlDefaultSAXHandlerInit();
10911
10912    xmlDetectSAX2(ctxt);
10913
10914    GROW;
10915
10916    /*
10917     * SAX: beginning of the document processing.
10918     */
10919    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
10920        ctxt->sax->setDocumentLocator(ctxt->userData, &xmlDefaultSAXLocator);
10921
10922    /*
10923     * Get the 4 first bytes and decode the charset
10924     * if enc != XML_CHAR_ENCODING_NONE
10925     * plug some encoding conversion routines.
10926     */
10927    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
10928	start[0] = RAW;
10929	start[1] = NXT(1);
10930	start[2] = NXT(2);
10931	start[3] = NXT(3);
10932	enc = xmlDetectCharEncoding(start, 4);
10933	if (enc != XML_CHAR_ENCODING_NONE) {
10934	    xmlSwitchEncoding(ctxt, enc);
10935	}
10936    }
10937
10938
10939    if (CUR == 0) {
10940	xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
10941    }
10942
10943    /*
10944     * Check for the XMLDecl in the Prolog.
10945     */
10946    GROW;
10947    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
10948
10949	/*
10950	 * Note that we will switch encoding on the fly.
10951	 */
10952	xmlParseXMLDecl(ctxt);
10953	if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
10954	    /*
10955	     * The XML REC instructs us to stop parsing right here
10956	     */
10957	    return(-1);
10958	}
10959	SKIP_BLANKS;
10960    } else {
10961	ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
10962    }
10963    if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
10964        ctxt->sax->startDocument(ctxt->userData);
10965    if (ctxt->instate == XML_PARSER_EOF)
10966	return(-1);
10967
10968    /*
10969     * Doing validity checking on chunk doesn't make sense
10970     */
10971    ctxt->instate = XML_PARSER_CONTENT;
10972    ctxt->validate = 0;
10973    ctxt->loadsubset = 0;
10974    ctxt->depth = 0;
10975
10976    xmlParseContent(ctxt);
10977    if (ctxt->instate == XML_PARSER_EOF)
10978	return(-1);
10979
10980    if ((RAW == '<') && (NXT(1) == '/')) {
10981	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
10982    } else if (RAW != 0) {
10983	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
10984    }
10985
10986    /*
10987     * SAX: end of the document processing.
10988     */
10989    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
10990        ctxt->sax->endDocument(ctxt->userData);
10991
10992    if (! ctxt->wellFormed) return(-1);
10993    return(0);
10994}
10995
10996#ifdef LIBXML_PUSH_ENABLED
10997/************************************************************************
10998 *									*
10999 *		Progressive parsing interfaces				*
11000 *									*
11001 ************************************************************************/
11002
11003/**
11004 * xmlParseLookupSequence:
11005 * @ctxt:  an XML parser context
11006 * @first:  the first char to lookup
11007 * @next:  the next char to lookup or zero
11008 * @third:  the next char to lookup or zero
11009 *
11010 * Try to find if a sequence (first, next, third) or  just (first next) or
11011 * (first) is available in the input stream.
11012 * This function has a side effect of (possibly) incrementing ctxt->checkIndex
11013 * to avoid rescanning sequences of bytes, it DOES change the state of the
11014 * parser, do not use liberally.
11015 *
11016 * Returns the index to the current parsing point if the full sequence
11017 *      is available, -1 otherwise.
11018 */
11019static int
11020xmlParseLookupSequence(xmlParserCtxtPtr ctxt, xmlChar first,
11021                       xmlChar next, xmlChar third) {
11022    int base, len;
11023    xmlParserInputPtr in;
11024    const xmlChar *buf;
11025
11026    in = ctxt->input;
11027    if (in == NULL) return(-1);
11028    base = in->cur - in->base;
11029    if (base < 0) return(-1);
11030    if (ctxt->checkIndex > base)
11031        base = ctxt->checkIndex;
11032    if (in->buf == NULL) {
11033	buf = in->base;
11034	len = in->length;
11035    } else {
11036	buf = xmlBufContent(in->buf->buffer);
11037	len = xmlBufUse(in->buf->buffer);
11038    }
11039    /* take into account the sequence length */
11040    if (third) len -= 2;
11041    else if (next) len --;
11042    for (;base < len;base++) {
11043        if (buf[base] == first) {
11044	    if (third != 0) {
11045		if ((buf[base + 1] != next) ||
11046		    (buf[base + 2] != third)) continue;
11047	    } else if (next != 0) {
11048		if (buf[base + 1] != next) continue;
11049	    }
11050	    ctxt->checkIndex = 0;
11051#ifdef DEBUG_PUSH
11052	    if (next == 0)
11053		xmlGenericError(xmlGenericErrorContext,
11054			"PP: lookup '%c' found at %d\n",
11055			first, base);
11056	    else if (third == 0)
11057		xmlGenericError(xmlGenericErrorContext,
11058			"PP: lookup '%c%c' found at %d\n",
11059			first, next, base);
11060	    else
11061		xmlGenericError(xmlGenericErrorContext,
11062			"PP: lookup '%c%c%c' found at %d\n",
11063			first, next, third, base);
11064#endif
11065	    return(base - (in->cur - in->base));
11066	}
11067    }
11068    ctxt->checkIndex = base;
11069#ifdef DEBUG_PUSH
11070    if (next == 0)
11071	xmlGenericError(xmlGenericErrorContext,
11072		"PP: lookup '%c' failed\n", first);
11073    else if (third == 0)
11074	xmlGenericError(xmlGenericErrorContext,
11075		"PP: lookup '%c%c' failed\n", first, next);
11076    else
11077	xmlGenericError(xmlGenericErrorContext,
11078		"PP: lookup '%c%c%c' failed\n", first, next, third);
11079#endif
11080    return(-1);
11081}
11082
11083/**
11084 * xmlParseGetLasts:
11085 * @ctxt:  an XML parser context
11086 * @lastlt:  pointer to store the last '<' from the input
11087 * @lastgt:  pointer to store the last '>' from the input
11088 *
11089 * Lookup the last < and > in the current chunk
11090 */
11091static void
11092xmlParseGetLasts(xmlParserCtxtPtr ctxt, const xmlChar **lastlt,
11093                 const xmlChar **lastgt) {
11094    const xmlChar *tmp;
11095
11096    if ((ctxt == NULL) || (lastlt == NULL) || (lastgt == NULL)) {
11097	xmlGenericError(xmlGenericErrorContext,
11098		    "Internal error: xmlParseGetLasts\n");
11099	return;
11100    }
11101    if ((ctxt->progressive != 0) && (ctxt->inputNr == 1)) {
11102        tmp = ctxt->input->end;
11103	tmp--;
11104	while ((tmp >= ctxt->input->base) && (*tmp != '<')) tmp--;
11105	if (tmp < ctxt->input->base) {
11106	    *lastlt = NULL;
11107	    *lastgt = NULL;
11108	} else {
11109	    *lastlt = tmp;
11110	    tmp++;
11111	    while ((tmp < ctxt->input->end) && (*tmp != '>')) {
11112	        if (*tmp == '\'') {
11113		    tmp++;
11114		    while ((tmp < ctxt->input->end) && (*tmp != '\'')) tmp++;
11115		    if (tmp < ctxt->input->end) tmp++;
11116		} else if (*tmp == '"') {
11117		    tmp++;
11118		    while ((tmp < ctxt->input->end) && (*tmp != '"')) tmp++;
11119		    if (tmp < ctxt->input->end) tmp++;
11120		} else
11121		    tmp++;
11122	    }
11123	    if (tmp < ctxt->input->end)
11124	        *lastgt = tmp;
11125	    else {
11126	        tmp = *lastlt;
11127		tmp--;
11128		while ((tmp >= ctxt->input->base) && (*tmp != '>')) tmp--;
11129		if (tmp >= ctxt->input->base)
11130		    *lastgt = tmp;
11131		else
11132		    *lastgt = NULL;
11133	    }
11134	}
11135    } else {
11136        *lastlt = NULL;
11137	*lastgt = NULL;
11138    }
11139}
11140/**
11141 * xmlCheckCdataPush:
11142 * @cur: pointer to the bock of characters
11143 * @len: length of the block in bytes
11144 *
11145 * Check that the block of characters is okay as SCdata content [20]
11146 *
11147 * Returns the number of bytes to pass if okay, a negative index where an
11148 *         UTF-8 error occured otherwise
11149 */
11150static int
11151xmlCheckCdataPush(const xmlChar *utf, int len) {
11152    int ix;
11153    unsigned char c;
11154    int codepoint;
11155
11156    if ((utf == NULL) || (len <= 0))
11157        return(0);
11158
11159    for (ix = 0; ix < len;) {      /* string is 0-terminated */
11160        c = utf[ix];
11161        if ((c & 0x80) == 0x00) {	/* 1-byte code, starts with 10 */
11162	    if (c >= 0x20)
11163		ix++;
11164	    else if ((c == 0xA) || (c == 0xD) || (c == 0x9))
11165	        ix++;
11166	    else
11167	        return(-ix);
11168	} else if ((c & 0xe0) == 0xc0) {/* 2-byte code, starts with 110 */
11169	    if (ix + 2 > len) return(ix);
11170	    if ((utf[ix+1] & 0xc0 ) != 0x80)
11171	        return(-ix);
11172	    codepoint = (utf[ix] & 0x1f) << 6;
11173	    codepoint |= utf[ix+1] & 0x3f;
11174	    if (!xmlIsCharQ(codepoint))
11175	        return(-ix);
11176	    ix += 2;
11177	} else if ((c & 0xf0) == 0xe0) {/* 3-byte code, starts with 1110 */
11178	    if (ix + 3 > len) return(ix);
11179	    if (((utf[ix+1] & 0xc0) != 0x80) ||
11180	        ((utf[ix+2] & 0xc0) != 0x80))
11181		    return(-ix);
11182	    codepoint = (utf[ix] & 0xf) << 12;
11183	    codepoint |= (utf[ix+1] & 0x3f) << 6;
11184	    codepoint |= utf[ix+2] & 0x3f;
11185	    if (!xmlIsCharQ(codepoint))
11186	        return(-ix);
11187	    ix += 3;
11188	} else if ((c & 0xf8) == 0xf0) {/* 4-byte code, starts with 11110 */
11189	    if (ix + 4 > len) return(ix);
11190	    if (((utf[ix+1] & 0xc0) != 0x80) ||
11191	        ((utf[ix+2] & 0xc0) != 0x80) ||
11192		((utf[ix+3] & 0xc0) != 0x80))
11193		    return(-ix);
11194	    codepoint = (utf[ix] & 0x7) << 18;
11195	    codepoint |= (utf[ix+1] & 0x3f) << 12;
11196	    codepoint |= (utf[ix+2] & 0x3f) << 6;
11197	    codepoint |= utf[ix+3] & 0x3f;
11198	    if (!xmlIsCharQ(codepoint))
11199	        return(-ix);
11200	    ix += 4;
11201	} else				/* unknown encoding */
11202	    return(-ix);
11203      }
11204      return(ix);
11205}
11206
11207/**
11208 * xmlParseTryOrFinish:
11209 * @ctxt:  an XML parser context
11210 * @terminate:  last chunk indicator
11211 *
11212 * Try to progress on parsing
11213 *
11214 * Returns zero if no parsing was possible
11215 */
11216static int
11217xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) {
11218    int ret = 0;
11219    int avail, tlen;
11220    xmlChar cur, next;
11221    const xmlChar *lastlt, *lastgt;
11222
11223    if (ctxt->input == NULL)
11224        return(0);
11225
11226#ifdef DEBUG_PUSH
11227    switch (ctxt->instate) {
11228	case XML_PARSER_EOF:
11229	    xmlGenericError(xmlGenericErrorContext,
11230		    "PP: try EOF\n"); break;
11231	case XML_PARSER_START:
11232	    xmlGenericError(xmlGenericErrorContext,
11233		    "PP: try START\n"); break;
11234	case XML_PARSER_MISC:
11235	    xmlGenericError(xmlGenericErrorContext,
11236		    "PP: try MISC\n");break;
11237	case XML_PARSER_COMMENT:
11238	    xmlGenericError(xmlGenericErrorContext,
11239		    "PP: try COMMENT\n");break;
11240	case XML_PARSER_PROLOG:
11241	    xmlGenericError(xmlGenericErrorContext,
11242		    "PP: try PROLOG\n");break;
11243	case XML_PARSER_START_TAG:
11244	    xmlGenericError(xmlGenericErrorContext,
11245		    "PP: try START_TAG\n");break;
11246	case XML_PARSER_CONTENT:
11247	    xmlGenericError(xmlGenericErrorContext,
11248		    "PP: try CONTENT\n");break;
11249	case XML_PARSER_CDATA_SECTION:
11250	    xmlGenericError(xmlGenericErrorContext,
11251		    "PP: try CDATA_SECTION\n");break;
11252	case XML_PARSER_END_TAG:
11253	    xmlGenericError(xmlGenericErrorContext,
11254		    "PP: try END_TAG\n");break;
11255	case XML_PARSER_ENTITY_DECL:
11256	    xmlGenericError(xmlGenericErrorContext,
11257		    "PP: try ENTITY_DECL\n");break;
11258	case XML_PARSER_ENTITY_VALUE:
11259	    xmlGenericError(xmlGenericErrorContext,
11260		    "PP: try ENTITY_VALUE\n");break;
11261	case XML_PARSER_ATTRIBUTE_VALUE:
11262	    xmlGenericError(xmlGenericErrorContext,
11263		    "PP: try ATTRIBUTE_VALUE\n");break;
11264	case XML_PARSER_DTD:
11265	    xmlGenericError(xmlGenericErrorContext,
11266		    "PP: try DTD\n");break;
11267	case XML_PARSER_EPILOG:
11268	    xmlGenericError(xmlGenericErrorContext,
11269		    "PP: try EPILOG\n");break;
11270	case XML_PARSER_PI:
11271	    xmlGenericError(xmlGenericErrorContext,
11272		    "PP: try PI\n");break;
11273        case XML_PARSER_IGNORE:
11274            xmlGenericError(xmlGenericErrorContext,
11275		    "PP: try IGNORE\n");break;
11276    }
11277#endif
11278
11279    if ((ctxt->input != NULL) &&
11280        (ctxt->input->cur - ctxt->input->base > 4096)) {
11281	xmlSHRINK(ctxt);
11282	ctxt->checkIndex = 0;
11283    }
11284    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11285
11286    while (ctxt->instate != XML_PARSER_EOF) {
11287	if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
11288	    return(0);
11289
11290
11291	/*
11292	 * Pop-up of finished entities.
11293	 */
11294	while ((RAW == 0) && (ctxt->inputNr > 1))
11295	    xmlPopInput(ctxt);
11296
11297	if (ctxt->input == NULL) break;
11298	if (ctxt->input->buf == NULL)
11299	    avail = ctxt->input->length -
11300	            (ctxt->input->cur - ctxt->input->base);
11301	else {
11302	    /*
11303	     * If we are operating on converted input, try to flush
11304	     * remainng chars to avoid them stalling in the non-converted
11305	     * buffer. But do not do this in document start where
11306	     * encoding="..." may not have been read and we work on a
11307	     * guessed encoding.
11308	     */
11309	    if ((ctxt->instate != XML_PARSER_START) &&
11310	        (ctxt->input->buf->raw != NULL) &&
11311		(xmlBufIsEmpty(ctxt->input->buf->raw) == 0)) {
11312                size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
11313                                                 ctxt->input);
11314		size_t current = ctxt->input->cur - ctxt->input->base;
11315
11316		xmlParserInputBufferPush(ctxt->input->buf, 0, "");
11317                xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
11318                                      base, current);
11319	    }
11320	    avail = xmlBufUse(ctxt->input->buf->buffer) -
11321		    (ctxt->input->cur - ctxt->input->base);
11322	}
11323        if (avail < 1)
11324	    goto done;
11325        switch (ctxt->instate) {
11326            case XML_PARSER_EOF:
11327	        /*
11328		 * Document parsing is done !
11329		 */
11330	        goto done;
11331            case XML_PARSER_START:
11332		if (ctxt->charset == XML_CHAR_ENCODING_NONE) {
11333		    xmlChar start[4];
11334		    xmlCharEncoding enc;
11335
11336		    /*
11337		     * Very first chars read from the document flow.
11338		     */
11339		    if (avail < 4)
11340			goto done;
11341
11342		    /*
11343		     * Get the 4 first bytes and decode the charset
11344		     * if enc != XML_CHAR_ENCODING_NONE
11345		     * plug some encoding conversion routines,
11346		     * else xmlSwitchEncoding will set to (default)
11347		     * UTF8.
11348		     */
11349		    start[0] = RAW;
11350		    start[1] = NXT(1);
11351		    start[2] = NXT(2);
11352		    start[3] = NXT(3);
11353		    enc = xmlDetectCharEncoding(start, 4);
11354		    xmlSwitchEncoding(ctxt, enc);
11355		    break;
11356		}
11357
11358		if (avail < 2)
11359		    goto done;
11360		cur = ctxt->input->cur[0];
11361		next = ctxt->input->cur[1];
11362		if (cur == 0) {
11363		    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11364			ctxt->sax->setDocumentLocator(ctxt->userData,
11365						      &xmlDefaultSAXLocator);
11366		    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11367		    ctxt->instate = XML_PARSER_EOF;
11368#ifdef DEBUG_PUSH
11369		    xmlGenericError(xmlGenericErrorContext,
11370			    "PP: entering EOF\n");
11371#endif
11372		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11373			ctxt->sax->endDocument(ctxt->userData);
11374		    goto done;
11375		}
11376	        if ((cur == '<') && (next == '?')) {
11377		    /* PI or XML decl */
11378		    if (avail < 5) return(ret);
11379		    if ((!terminate) &&
11380		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0))
11381			return(ret);
11382		    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11383			ctxt->sax->setDocumentLocator(ctxt->userData,
11384						      &xmlDefaultSAXLocator);
11385		    if ((ctxt->input->cur[2] == 'x') &&
11386			(ctxt->input->cur[3] == 'm') &&
11387			(ctxt->input->cur[4] == 'l') &&
11388			(IS_BLANK_CH(ctxt->input->cur[5]))) {
11389			ret += 5;
11390#ifdef DEBUG_PUSH
11391			xmlGenericError(xmlGenericErrorContext,
11392				"PP: Parsing XML Decl\n");
11393#endif
11394			xmlParseXMLDecl(ctxt);
11395			if (ctxt->errNo == XML_ERR_UNSUPPORTED_ENCODING) {
11396			    /*
11397			     * The XML REC instructs us to stop parsing right
11398			     * here
11399			     */
11400			    ctxt->instate = XML_PARSER_EOF;
11401			    return(0);
11402			}
11403			ctxt->standalone = ctxt->input->standalone;
11404			if ((ctxt->encoding == NULL) &&
11405			    (ctxt->input->encoding != NULL))
11406			    ctxt->encoding = xmlStrdup(ctxt->input->encoding);
11407			if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11408			    (!ctxt->disableSAX))
11409			    ctxt->sax->startDocument(ctxt->userData);
11410			ctxt->instate = XML_PARSER_MISC;
11411#ifdef DEBUG_PUSH
11412			xmlGenericError(xmlGenericErrorContext,
11413				"PP: entering MISC\n");
11414#endif
11415		    } else {
11416			ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11417			if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11418			    (!ctxt->disableSAX))
11419			    ctxt->sax->startDocument(ctxt->userData);
11420			ctxt->instate = XML_PARSER_MISC;
11421#ifdef DEBUG_PUSH
11422			xmlGenericError(xmlGenericErrorContext,
11423				"PP: entering MISC\n");
11424#endif
11425		    }
11426		} else {
11427		    if ((ctxt->sax) && (ctxt->sax->setDocumentLocator))
11428			ctxt->sax->setDocumentLocator(ctxt->userData,
11429						      &xmlDefaultSAXLocator);
11430		    ctxt->version = xmlCharStrdup(XML_DEFAULT_VERSION);
11431		    if (ctxt->version == NULL) {
11432		        xmlErrMemory(ctxt, NULL);
11433			break;
11434		    }
11435		    if ((ctxt->sax) && (ctxt->sax->startDocument) &&
11436		        (!ctxt->disableSAX))
11437			ctxt->sax->startDocument(ctxt->userData);
11438		    ctxt->instate = XML_PARSER_MISC;
11439#ifdef DEBUG_PUSH
11440		    xmlGenericError(xmlGenericErrorContext,
11441			    "PP: entering MISC\n");
11442#endif
11443		}
11444		break;
11445            case XML_PARSER_START_TAG: {
11446	        const xmlChar *name;
11447		const xmlChar *prefix = NULL;
11448		const xmlChar *URI = NULL;
11449		int nsNr = ctxt->nsNr;
11450
11451		if ((avail < 2) && (ctxt->inputNr == 1))
11452		    goto done;
11453		cur = ctxt->input->cur[0];
11454	        if (cur != '<') {
11455		    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_EMPTY, NULL);
11456		    ctxt->instate = XML_PARSER_EOF;
11457		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11458			ctxt->sax->endDocument(ctxt->userData);
11459		    goto done;
11460		}
11461		if (!terminate) {
11462		    if (ctxt->progressive) {
11463		        /* > can be found unescaped in attribute values */
11464		        if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
11465			    goto done;
11466		    } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
11467			goto done;
11468		    }
11469		}
11470		if (ctxt->spaceNr == 0)
11471		    spacePush(ctxt, -1);
11472		else if (*ctxt->space == -2)
11473		    spacePush(ctxt, -1);
11474		else
11475		    spacePush(ctxt, *ctxt->space);
11476#ifdef LIBXML_SAX1_ENABLED
11477		if (ctxt->sax2)
11478#endif /* LIBXML_SAX1_ENABLED */
11479		    name = xmlParseStartTag2(ctxt, &prefix, &URI, &tlen);
11480#ifdef LIBXML_SAX1_ENABLED
11481		else
11482		    name = xmlParseStartTag(ctxt);
11483#endif /* LIBXML_SAX1_ENABLED */
11484		if (ctxt->instate == XML_PARSER_EOF)
11485		    goto done;
11486		if (name == NULL) {
11487		    spacePop(ctxt);
11488		    ctxt->instate = XML_PARSER_EOF;
11489		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11490			ctxt->sax->endDocument(ctxt->userData);
11491		    goto done;
11492		}
11493#ifdef LIBXML_VALID_ENABLED
11494		/*
11495		 * [ VC: Root Element Type ]
11496		 * The Name in the document type declaration must match
11497		 * the element type of the root element.
11498		 */
11499		if (ctxt->validate && ctxt->wellFormed && ctxt->myDoc &&
11500		    ctxt->node && (ctxt->node == ctxt->myDoc->children))
11501		    ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
11502#endif /* LIBXML_VALID_ENABLED */
11503
11504		/*
11505		 * Check for an Empty Element.
11506		 */
11507		if ((RAW == '/') && (NXT(1) == '>')) {
11508		    SKIP(2);
11509
11510		    if (ctxt->sax2) {
11511			if ((ctxt->sax != NULL) &&
11512			    (ctxt->sax->endElementNs != NULL) &&
11513			    (!ctxt->disableSAX))
11514			    ctxt->sax->endElementNs(ctxt->userData, name,
11515			                            prefix, URI);
11516			if (ctxt->nsNr - nsNr > 0)
11517			    nsPop(ctxt, ctxt->nsNr - nsNr);
11518#ifdef LIBXML_SAX1_ENABLED
11519		    } else {
11520			if ((ctxt->sax != NULL) &&
11521			    (ctxt->sax->endElement != NULL) &&
11522			    (!ctxt->disableSAX))
11523			    ctxt->sax->endElement(ctxt->userData, name);
11524#endif /* LIBXML_SAX1_ENABLED */
11525		    }
11526		    if (ctxt->instate == XML_PARSER_EOF)
11527			goto done;
11528		    spacePop(ctxt);
11529		    if (ctxt->nameNr == 0) {
11530			ctxt->instate = XML_PARSER_EPILOG;
11531		    } else {
11532			ctxt->instate = XML_PARSER_CONTENT;
11533		    }
11534                    ctxt->progressive = 1;
11535		    break;
11536		}
11537		if (RAW == '>') {
11538		    NEXT;
11539		} else {
11540		    xmlFatalErrMsgStr(ctxt, XML_ERR_GT_REQUIRED,
11541					 "Couldn't find end of Start Tag %s\n",
11542					 name);
11543		    nodePop(ctxt);
11544		    spacePop(ctxt);
11545		}
11546		if (ctxt->sax2)
11547		    nameNsPush(ctxt, name, prefix, URI, ctxt->nsNr - nsNr);
11548#ifdef LIBXML_SAX1_ENABLED
11549		else
11550		    namePush(ctxt, name);
11551#endif /* LIBXML_SAX1_ENABLED */
11552
11553		ctxt->instate = XML_PARSER_CONTENT;
11554                ctxt->progressive = 1;
11555                break;
11556	    }
11557            case XML_PARSER_CONTENT: {
11558		const xmlChar *test;
11559		unsigned int cons;
11560		if ((avail < 2) && (ctxt->inputNr == 1))
11561		    goto done;
11562		cur = ctxt->input->cur[0];
11563		next = ctxt->input->cur[1];
11564
11565		test = CUR_PTR;
11566	        cons = ctxt->input->consumed;
11567		if ((cur == '<') && (next == '/')) {
11568		    ctxt->instate = XML_PARSER_END_TAG;
11569		    break;
11570	        } else if ((cur == '<') && (next == '?')) {
11571		    if ((!terminate) &&
11572		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
11573                        ctxt->progressive = XML_PARSER_PI;
11574			goto done;
11575                    }
11576		    xmlParsePI(ctxt);
11577		    ctxt->instate = XML_PARSER_CONTENT;
11578                    ctxt->progressive = 1;
11579		} else if ((cur == '<') && (next != '!')) {
11580		    ctxt->instate = XML_PARSER_START_TAG;
11581		    break;
11582		} else if ((cur == '<') && (next == '!') &&
11583		           (ctxt->input->cur[2] == '-') &&
11584			   (ctxt->input->cur[3] == '-')) {
11585		    int term;
11586
11587	            if (avail < 4)
11588		        goto done;
11589		    ctxt->input->cur += 4;
11590		    term = xmlParseLookupSequence(ctxt, '-', '-', '>');
11591		    ctxt->input->cur -= 4;
11592		    if ((!terminate) && (term < 0)) {
11593                        ctxt->progressive = XML_PARSER_COMMENT;
11594			goto done;
11595                    }
11596		    xmlParseComment(ctxt);
11597		    ctxt->instate = XML_PARSER_CONTENT;
11598                    ctxt->progressive = 1;
11599		} else if ((cur == '<') && (ctxt->input->cur[1] == '!') &&
11600		    (ctxt->input->cur[2] == '[') &&
11601		    (ctxt->input->cur[3] == 'C') &&
11602		    (ctxt->input->cur[4] == 'D') &&
11603		    (ctxt->input->cur[5] == 'A') &&
11604		    (ctxt->input->cur[6] == 'T') &&
11605		    (ctxt->input->cur[7] == 'A') &&
11606		    (ctxt->input->cur[8] == '[')) {
11607		    SKIP(9);
11608		    ctxt->instate = XML_PARSER_CDATA_SECTION;
11609		    break;
11610		} else if ((cur == '<') && (next == '!') &&
11611		           (avail < 9)) {
11612		    goto done;
11613		} else if (cur == '&') {
11614		    if ((!terminate) &&
11615		        (xmlParseLookupSequence(ctxt, ';', 0, 0) < 0))
11616			goto done;
11617		    xmlParseReference(ctxt);
11618		} else {
11619		    /* TODO Avoid the extra copy, handle directly !!! */
11620		    /*
11621		     * Goal of the following test is:
11622		     *  - minimize calls to the SAX 'character' callback
11623		     *    when they are mergeable
11624		     *  - handle an problem for isBlank when we only parse
11625		     *    a sequence of blank chars and the next one is
11626		     *    not available to check against '<' presence.
11627		     *  - tries to homogenize the differences in SAX
11628		     *    callbacks between the push and pull versions
11629		     *    of the parser.
11630		     */
11631		    if ((ctxt->inputNr == 1) &&
11632		        (avail < XML_PARSER_BIG_BUFFER_SIZE)) {
11633			if (!terminate) {
11634			    if (ctxt->progressive) {
11635				if ((lastlt == NULL) ||
11636				    (ctxt->input->cur > lastlt))
11637				    goto done;
11638			    } else if (xmlParseLookupSequence(ctxt,
11639			                                      '<', 0, 0) < 0) {
11640				goto done;
11641			    }
11642			}
11643                    }
11644		    ctxt->checkIndex = 0;
11645		    xmlParseCharData(ctxt, 0);
11646		}
11647		/*
11648		 * Pop-up of finished entities.
11649		 */
11650		while ((RAW == 0) && (ctxt->inputNr > 1))
11651		    xmlPopInput(ctxt);
11652		if ((cons == ctxt->input->consumed) && (test == CUR_PTR)) {
11653		    xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR,
11654		                "detected an error in element content\n");
11655		    ctxt->instate = XML_PARSER_EOF;
11656		    break;
11657		}
11658		break;
11659	    }
11660            case XML_PARSER_END_TAG:
11661		if (avail < 2)
11662		    goto done;
11663		if (!terminate) {
11664		    if (ctxt->progressive) {
11665		        /* > can be found unescaped in attribute values */
11666		        if ((lastgt == NULL) || (ctxt->input->cur >= lastgt))
11667			    goto done;
11668		    } else if (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0) {
11669			goto done;
11670		    }
11671		}
11672		if (ctxt->sax2) {
11673		    xmlParseEndTag2(ctxt,
11674		           (void *) ctxt->pushTab[ctxt->nameNr * 3 - 3],
11675		           (void *) ctxt->pushTab[ctxt->nameNr * 3 - 2], 0,
11676		       (int) (long) ctxt->pushTab[ctxt->nameNr * 3 - 1], 0);
11677		    nameNsPop(ctxt);
11678		}
11679#ifdef LIBXML_SAX1_ENABLED
11680		  else
11681		    xmlParseEndTag1(ctxt, 0);
11682#endif /* LIBXML_SAX1_ENABLED */
11683		if (ctxt->instate == XML_PARSER_EOF) {
11684		    /* Nothing */
11685		} else if (ctxt->nameNr == 0) {
11686		    ctxt->instate = XML_PARSER_EPILOG;
11687		} else {
11688		    ctxt->instate = XML_PARSER_CONTENT;
11689		}
11690		break;
11691            case XML_PARSER_CDATA_SECTION: {
11692	        /*
11693		 * The Push mode need to have the SAX callback for
11694		 * cdataBlock merge back contiguous callbacks.
11695		 */
11696		int base;
11697
11698		base = xmlParseLookupSequence(ctxt, ']', ']', '>');
11699		if (base < 0) {
11700		    if (avail >= XML_PARSER_BIG_BUFFER_SIZE + 2) {
11701		        int tmp;
11702
11703			tmp = xmlCheckCdataPush(ctxt->input->cur,
11704			                        XML_PARSER_BIG_BUFFER_SIZE);
11705			if (tmp < 0) {
11706			    tmp = -tmp;
11707			    ctxt->input->cur += tmp;
11708			    goto encoding_error;
11709			}
11710			if ((ctxt->sax != NULL) && (!ctxt->disableSAX)) {
11711			    if (ctxt->sax->cdataBlock != NULL)
11712				ctxt->sax->cdataBlock(ctxt->userData,
11713				                      ctxt->input->cur, tmp);
11714			    else if (ctxt->sax->characters != NULL)
11715				ctxt->sax->characters(ctxt->userData,
11716				                      ctxt->input->cur, tmp);
11717			}
11718			if (ctxt->instate == XML_PARSER_EOF)
11719			    goto done;
11720			SKIPL(tmp);
11721			ctxt->checkIndex = 0;
11722		    }
11723		    goto done;
11724		} else {
11725		    int tmp;
11726
11727		    tmp = xmlCheckCdataPush(ctxt->input->cur, base);
11728		    if ((tmp < 0) || (tmp != base)) {
11729			tmp = -tmp;
11730			ctxt->input->cur += tmp;
11731			goto encoding_error;
11732		    }
11733		    if ((ctxt->sax != NULL) && (base == 0) &&
11734		        (ctxt->sax->cdataBlock != NULL) &&
11735		        (!ctxt->disableSAX)) {
11736			/*
11737			 * Special case to provide identical behaviour
11738			 * between pull and push parsers on enpty CDATA
11739			 * sections
11740			 */
11741			 if ((ctxt->input->cur - ctxt->input->base >= 9) &&
11742			     (!strncmp((const char *)&ctxt->input->cur[-9],
11743			               "<![CDATA[", 9)))
11744			     ctxt->sax->cdataBlock(ctxt->userData,
11745			                           BAD_CAST "", 0);
11746		    } else if ((ctxt->sax != NULL) && (base > 0) &&
11747			(!ctxt->disableSAX)) {
11748			if (ctxt->sax->cdataBlock != NULL)
11749			    ctxt->sax->cdataBlock(ctxt->userData,
11750						  ctxt->input->cur, base);
11751			else if (ctxt->sax->characters != NULL)
11752			    ctxt->sax->characters(ctxt->userData,
11753						  ctxt->input->cur, base);
11754		    }
11755		    if (ctxt->instate == XML_PARSER_EOF)
11756			goto done;
11757		    SKIPL(base + 3);
11758		    ctxt->checkIndex = 0;
11759		    ctxt->instate = XML_PARSER_CONTENT;
11760#ifdef DEBUG_PUSH
11761		    xmlGenericError(xmlGenericErrorContext,
11762			    "PP: entering CONTENT\n");
11763#endif
11764		}
11765		break;
11766	    }
11767            case XML_PARSER_MISC:
11768		SKIP_BLANKS;
11769		if (ctxt->input->buf == NULL)
11770		    avail = ctxt->input->length -
11771		            (ctxt->input->cur - ctxt->input->base);
11772		else
11773		    avail = xmlBufUse(ctxt->input->buf->buffer) -
11774		            (ctxt->input->cur - ctxt->input->base);
11775		if (avail < 2)
11776		    goto done;
11777		cur = ctxt->input->cur[0];
11778		next = ctxt->input->cur[1];
11779	        if ((cur == '<') && (next == '?')) {
11780		    if ((!terminate) &&
11781		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
11782                        ctxt->progressive = XML_PARSER_PI;
11783			goto done;
11784                    }
11785#ifdef DEBUG_PUSH
11786		    xmlGenericError(xmlGenericErrorContext,
11787			    "PP: Parsing PI\n");
11788#endif
11789		    xmlParsePI(ctxt);
11790		    if (ctxt->instate == XML_PARSER_EOF)
11791			goto done;
11792		    ctxt->instate = XML_PARSER_MISC;
11793                    ctxt->progressive = 1;
11794		    ctxt->checkIndex = 0;
11795		} else if ((cur == '<') && (next == '!') &&
11796		    (ctxt->input->cur[2] == '-') &&
11797		    (ctxt->input->cur[3] == '-')) {
11798		    if ((!terminate) &&
11799		        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
11800                        ctxt->progressive = XML_PARSER_COMMENT;
11801			goto done;
11802                    }
11803#ifdef DEBUG_PUSH
11804		    xmlGenericError(xmlGenericErrorContext,
11805			    "PP: Parsing Comment\n");
11806#endif
11807		    xmlParseComment(ctxt);
11808		    if (ctxt->instate == XML_PARSER_EOF)
11809			goto done;
11810		    ctxt->instate = XML_PARSER_MISC;
11811                    ctxt->progressive = 1;
11812		    ctxt->checkIndex = 0;
11813		} else if ((cur == '<') && (next == '!') &&
11814		    (ctxt->input->cur[2] == 'D') &&
11815		    (ctxt->input->cur[3] == 'O') &&
11816		    (ctxt->input->cur[4] == 'C') &&
11817		    (ctxt->input->cur[5] == 'T') &&
11818		    (ctxt->input->cur[6] == 'Y') &&
11819		    (ctxt->input->cur[7] == 'P') &&
11820		    (ctxt->input->cur[8] == 'E')) {
11821		    if ((!terminate) &&
11822		        (xmlParseLookupSequence(ctxt, '>', 0, 0) < 0)) {
11823                        ctxt->progressive = XML_PARSER_DTD;
11824			goto done;
11825                    }
11826#ifdef DEBUG_PUSH
11827		    xmlGenericError(xmlGenericErrorContext,
11828			    "PP: Parsing internal subset\n");
11829#endif
11830		    ctxt->inSubset = 1;
11831                    ctxt->progressive = 0;
11832		    ctxt->checkIndex = 0;
11833		    xmlParseDocTypeDecl(ctxt);
11834		    if (ctxt->instate == XML_PARSER_EOF)
11835			goto done;
11836		    if (RAW == '[') {
11837			ctxt->instate = XML_PARSER_DTD;
11838#ifdef DEBUG_PUSH
11839			xmlGenericError(xmlGenericErrorContext,
11840				"PP: entering DTD\n");
11841#endif
11842		    } else {
11843			/*
11844			 * Create and update the external subset.
11845			 */
11846			ctxt->inSubset = 2;
11847			if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
11848			    (ctxt->sax->externalSubset != NULL))
11849			    ctxt->sax->externalSubset(ctxt->userData,
11850				    ctxt->intSubName, ctxt->extSubSystem,
11851				    ctxt->extSubURI);
11852			ctxt->inSubset = 0;
11853			xmlCleanSpecialAttr(ctxt);
11854			ctxt->instate = XML_PARSER_PROLOG;
11855#ifdef DEBUG_PUSH
11856			xmlGenericError(xmlGenericErrorContext,
11857				"PP: entering PROLOG\n");
11858#endif
11859		    }
11860		} else if ((cur == '<') && (next == '!') &&
11861		           (avail < 9)) {
11862		    goto done;
11863		} else {
11864		    ctxt->instate = XML_PARSER_START_TAG;
11865		    ctxt->progressive = XML_PARSER_START_TAG;
11866		    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11867#ifdef DEBUG_PUSH
11868		    xmlGenericError(xmlGenericErrorContext,
11869			    "PP: entering START_TAG\n");
11870#endif
11871		}
11872		break;
11873            case XML_PARSER_PROLOG:
11874		SKIP_BLANKS;
11875		if (ctxt->input->buf == NULL)
11876		    avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
11877		else
11878		    avail = xmlBufUse(ctxt->input->buf->buffer) -
11879                            (ctxt->input->cur - ctxt->input->base);
11880		if (avail < 2)
11881		    goto done;
11882		cur = ctxt->input->cur[0];
11883		next = ctxt->input->cur[1];
11884	        if ((cur == '<') && (next == '?')) {
11885		    if ((!terminate) &&
11886		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
11887                        ctxt->progressive = XML_PARSER_PI;
11888			goto done;
11889                    }
11890#ifdef DEBUG_PUSH
11891		    xmlGenericError(xmlGenericErrorContext,
11892			    "PP: Parsing PI\n");
11893#endif
11894		    xmlParsePI(ctxt);
11895		    if (ctxt->instate == XML_PARSER_EOF)
11896			goto done;
11897		    ctxt->instate = XML_PARSER_PROLOG;
11898                    ctxt->progressive = 1;
11899		} else if ((cur == '<') && (next == '!') &&
11900		    (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
11901		    if ((!terminate) &&
11902		        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
11903                        ctxt->progressive = XML_PARSER_COMMENT;
11904			goto done;
11905                    }
11906#ifdef DEBUG_PUSH
11907		    xmlGenericError(xmlGenericErrorContext,
11908			    "PP: Parsing Comment\n");
11909#endif
11910		    xmlParseComment(ctxt);
11911		    if (ctxt->instate == XML_PARSER_EOF)
11912			goto done;
11913		    ctxt->instate = XML_PARSER_PROLOG;
11914                    ctxt->progressive = 1;
11915		} else if ((cur == '<') && (next == '!') &&
11916		           (avail < 4)) {
11917		    goto done;
11918		} else {
11919		    ctxt->instate = XML_PARSER_START_TAG;
11920		    if (ctxt->progressive == 0)
11921			ctxt->progressive = XML_PARSER_START_TAG;
11922		    xmlParseGetLasts(ctxt, &lastlt, &lastgt);
11923#ifdef DEBUG_PUSH
11924		    xmlGenericError(xmlGenericErrorContext,
11925			    "PP: entering START_TAG\n");
11926#endif
11927		}
11928		break;
11929            case XML_PARSER_EPILOG:
11930		SKIP_BLANKS;
11931		if (ctxt->input->buf == NULL)
11932		    avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base);
11933		else
11934		    avail = xmlBufUse(ctxt->input->buf->buffer) -
11935                            (ctxt->input->cur - ctxt->input->base);
11936		if (avail < 2)
11937		    goto done;
11938		cur = ctxt->input->cur[0];
11939		next = ctxt->input->cur[1];
11940	        if ((cur == '<') && (next == '?')) {
11941		    if ((!terminate) &&
11942		        (xmlParseLookupSequence(ctxt, '?', '>', 0) < 0)) {
11943                        ctxt->progressive = XML_PARSER_PI;
11944			goto done;
11945                    }
11946#ifdef DEBUG_PUSH
11947		    xmlGenericError(xmlGenericErrorContext,
11948			    "PP: Parsing PI\n");
11949#endif
11950		    xmlParsePI(ctxt);
11951		    if (ctxt->instate == XML_PARSER_EOF)
11952			goto done;
11953		    ctxt->instate = XML_PARSER_EPILOG;
11954                    ctxt->progressive = 1;
11955		} else if ((cur == '<') && (next == '!') &&
11956		    (ctxt->input->cur[2] == '-') && (ctxt->input->cur[3] == '-')) {
11957		    if ((!terminate) &&
11958		        (xmlParseLookupSequence(ctxt, '-', '-', '>') < 0)) {
11959                        ctxt->progressive = XML_PARSER_COMMENT;
11960			goto done;
11961                    }
11962#ifdef DEBUG_PUSH
11963		    xmlGenericError(xmlGenericErrorContext,
11964			    "PP: Parsing Comment\n");
11965#endif
11966		    xmlParseComment(ctxt);
11967		    if (ctxt->instate == XML_PARSER_EOF)
11968			goto done;
11969		    ctxt->instate = XML_PARSER_EPILOG;
11970                    ctxt->progressive = 1;
11971		} else if ((cur == '<') && (next == '!') &&
11972		           (avail < 4)) {
11973		    goto done;
11974		} else {
11975		    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
11976		    ctxt->instate = XML_PARSER_EOF;
11977#ifdef DEBUG_PUSH
11978		    xmlGenericError(xmlGenericErrorContext,
11979			    "PP: entering EOF\n");
11980#endif
11981		    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
11982			ctxt->sax->endDocument(ctxt->userData);
11983		    goto done;
11984		}
11985		break;
11986            case XML_PARSER_DTD: {
11987	        /*
11988		 * Sorry but progressive parsing of the internal subset
11989		 * is not expected to be supported. We first check that
11990		 * the full content of the internal subset is available and
11991		 * the parsing is launched only at that point.
11992		 * Internal subset ends up with "']' S? '>'" in an unescaped
11993		 * section and not in a ']]>' sequence which are conditional
11994		 * sections (whoever argued to keep that crap in XML deserve
11995		 * a place in hell !).
11996		 */
11997		int base, i;
11998		xmlChar *buf;
11999	        xmlChar quote = 0;
12000                size_t use;
12001
12002		base = ctxt->input->cur - ctxt->input->base;
12003		if (base < 0) return(0);
12004		if (ctxt->checkIndex > base)
12005		    base = ctxt->checkIndex;
12006		buf = xmlBufContent(ctxt->input->buf->buffer);
12007                use = xmlBufUse(ctxt->input->buf->buffer);
12008		for (;(unsigned int) base < use; base++) {
12009		    if (quote != 0) {
12010		        if (buf[base] == quote)
12011			    quote = 0;
12012			continue;
12013		    }
12014		    if ((quote == 0) && (buf[base] == '<')) {
12015		        int found  = 0;
12016			/* special handling of comments */
12017		        if (((unsigned int) base + 4 < use) &&
12018			    (buf[base + 1] == '!') &&
12019			    (buf[base + 2] == '-') &&
12020			    (buf[base + 3] == '-')) {
12021			    for (;(unsigned int) base + 3 < use; base++) {
12022				if ((buf[base] == '-') &&
12023				    (buf[base + 1] == '-') &&
12024				    (buf[base + 2] == '>')) {
12025				    found = 1;
12026				    base += 2;
12027				    break;
12028				}
12029		            }
12030			    if (!found) {
12031#if 0
12032			        fprintf(stderr, "unfinished comment\n");
12033#endif
12034			        break; /* for */
12035		            }
12036		            continue;
12037			}
12038		    }
12039		    if (buf[base] == '"') {
12040		        quote = '"';
12041			continue;
12042		    }
12043		    if (buf[base] == '\'') {
12044		        quote = '\'';
12045			continue;
12046		    }
12047		    if (buf[base] == ']') {
12048#if 0
12049		        fprintf(stderr, "%c%c%c%c: ", buf[base],
12050			        buf[base + 1], buf[base + 2], buf[base + 3]);
12051#endif
12052		        if ((unsigned int) base +1 >= use)
12053			    break;
12054			if (buf[base + 1] == ']') {
12055			    /* conditional crap, skip both ']' ! */
12056			    base++;
12057			    continue;
12058			}
12059		        for (i = 1; (unsigned int) base + i < use; i++) {
12060			    if (buf[base + i] == '>') {
12061#if 0
12062			        fprintf(stderr, "found\n");
12063#endif
12064			        goto found_end_int_subset;
12065			    }
12066			    if (!IS_BLANK_CH(buf[base + i])) {
12067#if 0
12068			        fprintf(stderr, "not found\n");
12069#endif
12070			        goto not_end_of_int_subset;
12071			    }
12072			}
12073#if 0
12074			fprintf(stderr, "end of stream\n");
12075#endif
12076		        break;
12077
12078		    }
12079not_end_of_int_subset:
12080                    continue; /* for */
12081		}
12082		/*
12083		 * We didn't found the end of the Internal subset
12084		 */
12085                if (quote == 0)
12086                    ctxt->checkIndex = base;
12087                else
12088                    ctxt->checkIndex = 0;
12089#ifdef DEBUG_PUSH
12090		if (next == 0)
12091		    xmlGenericError(xmlGenericErrorContext,
12092			    "PP: lookup of int subset end filed\n");
12093#endif
12094	        goto done;
12095
12096found_end_int_subset:
12097                ctxt->checkIndex = 0;
12098		xmlParseInternalSubset(ctxt);
12099		if (ctxt->instate == XML_PARSER_EOF)
12100		    goto done;
12101		ctxt->inSubset = 2;
12102		if ((ctxt->sax != NULL) && (!ctxt->disableSAX) &&
12103		    (ctxt->sax->externalSubset != NULL))
12104		    ctxt->sax->externalSubset(ctxt->userData, ctxt->intSubName,
12105			    ctxt->extSubSystem, ctxt->extSubURI);
12106		ctxt->inSubset = 0;
12107		xmlCleanSpecialAttr(ctxt);
12108		if (ctxt->instate == XML_PARSER_EOF)
12109		    goto done;
12110		ctxt->instate = XML_PARSER_PROLOG;
12111		ctxt->checkIndex = 0;
12112#ifdef DEBUG_PUSH
12113		xmlGenericError(xmlGenericErrorContext,
12114			"PP: entering PROLOG\n");
12115#endif
12116                break;
12117	    }
12118            case XML_PARSER_COMMENT:
12119		xmlGenericError(xmlGenericErrorContext,
12120			"PP: internal error, state == COMMENT\n");
12121		ctxt->instate = XML_PARSER_CONTENT;
12122#ifdef DEBUG_PUSH
12123		xmlGenericError(xmlGenericErrorContext,
12124			"PP: entering CONTENT\n");
12125#endif
12126		break;
12127            case XML_PARSER_IGNORE:
12128		xmlGenericError(xmlGenericErrorContext,
12129			"PP: internal error, state == IGNORE");
12130	        ctxt->instate = XML_PARSER_DTD;
12131#ifdef DEBUG_PUSH
12132		xmlGenericError(xmlGenericErrorContext,
12133			"PP: entering DTD\n");
12134#endif
12135	        break;
12136            case XML_PARSER_PI:
12137		xmlGenericError(xmlGenericErrorContext,
12138			"PP: internal error, state == PI\n");
12139		ctxt->instate = XML_PARSER_CONTENT;
12140#ifdef DEBUG_PUSH
12141		xmlGenericError(xmlGenericErrorContext,
12142			"PP: entering CONTENT\n");
12143#endif
12144		break;
12145            case XML_PARSER_ENTITY_DECL:
12146		xmlGenericError(xmlGenericErrorContext,
12147			"PP: internal error, state == ENTITY_DECL\n");
12148		ctxt->instate = XML_PARSER_DTD;
12149#ifdef DEBUG_PUSH
12150		xmlGenericError(xmlGenericErrorContext,
12151			"PP: entering DTD\n");
12152#endif
12153		break;
12154            case XML_PARSER_ENTITY_VALUE:
12155		xmlGenericError(xmlGenericErrorContext,
12156			"PP: internal error, state == ENTITY_VALUE\n");
12157		ctxt->instate = XML_PARSER_CONTENT;
12158#ifdef DEBUG_PUSH
12159		xmlGenericError(xmlGenericErrorContext,
12160			"PP: entering DTD\n");
12161#endif
12162		break;
12163            case XML_PARSER_ATTRIBUTE_VALUE:
12164		xmlGenericError(xmlGenericErrorContext,
12165			"PP: internal error, state == ATTRIBUTE_VALUE\n");
12166		ctxt->instate = XML_PARSER_START_TAG;
12167#ifdef DEBUG_PUSH
12168		xmlGenericError(xmlGenericErrorContext,
12169			"PP: entering START_TAG\n");
12170#endif
12171		break;
12172            case XML_PARSER_SYSTEM_LITERAL:
12173		xmlGenericError(xmlGenericErrorContext,
12174			"PP: internal error, state == SYSTEM_LITERAL\n");
12175		ctxt->instate = XML_PARSER_START_TAG;
12176#ifdef DEBUG_PUSH
12177		xmlGenericError(xmlGenericErrorContext,
12178			"PP: entering START_TAG\n");
12179#endif
12180		break;
12181            case XML_PARSER_PUBLIC_LITERAL:
12182		xmlGenericError(xmlGenericErrorContext,
12183			"PP: internal error, state == PUBLIC_LITERAL\n");
12184		ctxt->instate = XML_PARSER_START_TAG;
12185#ifdef DEBUG_PUSH
12186		xmlGenericError(xmlGenericErrorContext,
12187			"PP: entering START_TAG\n");
12188#endif
12189		break;
12190	}
12191    }
12192done:
12193#ifdef DEBUG_PUSH
12194    xmlGenericError(xmlGenericErrorContext, "PP: done %d\n", ret);
12195#endif
12196    return(ret);
12197encoding_error:
12198    {
12199        char buffer[150];
12200
12201	snprintf(buffer, 149, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
12202			ctxt->input->cur[0], ctxt->input->cur[1],
12203			ctxt->input->cur[2], ctxt->input->cur[3]);
12204	__xmlErrEncoding(ctxt, XML_ERR_INVALID_CHAR,
12205		     "Input is not proper UTF-8, indicate encoding !\n%s",
12206		     BAD_CAST buffer, NULL);
12207    }
12208    return(0);
12209}
12210
12211/**
12212 * xmlParseCheckTransition:
12213 * @ctxt:  an XML parser context
12214 * @chunk:  a char array
12215 * @size:  the size in byte of the chunk
12216 *
12217 * Check depending on the current parser state if the chunk given must be
12218 * processed immediately or one need more data to advance on parsing.
12219 *
12220 * Returns -1 in case of error, 0 if the push is not needed and 1 if needed
12221 */
12222static int
12223xmlParseCheckTransition(xmlParserCtxtPtr ctxt, const char *chunk, int size) {
12224    if ((ctxt == NULL) || (chunk == NULL) || (size < 0))
12225        return(-1);
12226    if (ctxt->instate == XML_PARSER_START_TAG) {
12227        if (memchr(chunk, '>', size) != NULL)
12228            return(1);
12229        return(0);
12230    }
12231    if (ctxt->progressive == XML_PARSER_COMMENT) {
12232        if (memchr(chunk, '>', size) != NULL)
12233            return(1);
12234        return(0);
12235    }
12236    if (ctxt->instate == XML_PARSER_CDATA_SECTION) {
12237        if (memchr(chunk, '>', size) != NULL)
12238            return(1);
12239        return(0);
12240    }
12241    if (ctxt->progressive == XML_PARSER_PI) {
12242        if (memchr(chunk, '>', size) != NULL)
12243            return(1);
12244        return(0);
12245    }
12246    if (ctxt->instate == XML_PARSER_END_TAG) {
12247        if (memchr(chunk, '>', size) != NULL)
12248            return(1);
12249        return(0);
12250    }
12251    if ((ctxt->progressive == XML_PARSER_DTD) ||
12252        (ctxt->instate == XML_PARSER_DTD)) {
12253        if (memchr(chunk, '>', size) != NULL)
12254            return(1);
12255        return(0);
12256    }
12257    return(1);
12258}
12259
12260/**
12261 * xmlParseChunk:
12262 * @ctxt:  an XML parser context
12263 * @chunk:  an char array
12264 * @size:  the size in byte of the chunk
12265 * @terminate:  last chunk indicator
12266 *
12267 * Parse a Chunk of memory
12268 *
12269 * Returns zero if no error, the xmlParserErrors otherwise.
12270 */
12271int
12272xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
12273              int terminate) {
12274    int end_in_lf = 0;
12275    int remain = 0;
12276    size_t old_avail = 0;
12277    size_t avail = 0;
12278
12279    if (ctxt == NULL)
12280        return(XML_ERR_INTERNAL_ERROR);
12281    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
12282        return(ctxt->errNo);
12283    if (ctxt->instate == XML_PARSER_EOF)
12284        return(-1);
12285    if (ctxt->instate == XML_PARSER_START)
12286        xmlDetectSAX2(ctxt);
12287    if ((size > 0) && (chunk != NULL) && (!terminate) &&
12288        (chunk[size - 1] == '\r')) {
12289	end_in_lf = 1;
12290	size--;
12291    }
12292
12293xmldecl_done:
12294
12295    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
12296        (ctxt->input->buf != NULL) && (ctxt->instate != XML_PARSER_EOF))  {
12297	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
12298	size_t cur = ctxt->input->cur - ctxt->input->base;
12299	int res;
12300
12301        old_avail = xmlBufUse(ctxt->input->buf->buffer);
12302        /*
12303         * Specific handling if we autodetected an encoding, we should not
12304         * push more than the first line ... which depend on the encoding
12305         * And only push the rest once the final encoding was detected
12306         */
12307        if ((ctxt->instate == XML_PARSER_START) && (ctxt->input != NULL) &&
12308            (ctxt->input->buf != NULL) && (ctxt->input->buf->encoder != NULL)) {
12309            unsigned int len = 45;
12310
12311            if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12312                               BAD_CAST "UTF-16")) ||
12313                (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12314                               BAD_CAST "UTF16")))
12315                len = 90;
12316            else if ((xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12317                                    BAD_CAST "UCS-4")) ||
12318                     (xmlStrcasestr(BAD_CAST ctxt->input->buf->encoder->name,
12319                                    BAD_CAST "UCS4")))
12320                len = 180;
12321
12322            if (ctxt->input->buf->rawconsumed < len)
12323                len -= ctxt->input->buf->rawconsumed;
12324
12325            /*
12326             * Change size for reading the initial declaration only
12327             * if size is greater than len. Otherwise, memmove in xmlBufferAdd
12328             * will blindly copy extra bytes from memory.
12329             */
12330            if ((unsigned int) size > len) {
12331                remain = size - len;
12332                size = len;
12333            } else {
12334                remain = 0;
12335            }
12336        }
12337	res = xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
12338	if (res < 0) {
12339	    ctxt->errNo = XML_PARSER_EOF;
12340	    ctxt->disableSAX = 1;
12341	    return (XML_PARSER_EOF);
12342	}
12343        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
12344#ifdef DEBUG_PUSH
12345	xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
12346#endif
12347
12348    } else if (ctxt->instate != XML_PARSER_EOF) {
12349	if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
12350	    xmlParserInputBufferPtr in = ctxt->input->buf;
12351	    if ((in->encoder != NULL) && (in->buffer != NULL) &&
12352		    (in->raw != NULL)) {
12353		int nbchars;
12354		size_t base = xmlBufGetInputBase(in->buffer, ctxt->input);
12355		size_t current = ctxt->input->cur - ctxt->input->base;
12356
12357		nbchars = xmlCharEncInput(in, terminate);
12358		if (nbchars < 0) {
12359		    /* TODO 2.6.0 */
12360		    xmlGenericError(xmlGenericErrorContext,
12361				    "xmlParseChunk: encoder error\n");
12362		    return(XML_ERR_INVALID_ENCODING);
12363		}
12364		xmlBufSetInputBaseCur(in->buffer, ctxt->input, base, current);
12365	    }
12366	}
12367    }
12368    if (remain != 0) {
12369        xmlParseTryOrFinish(ctxt, 0);
12370    } else {
12371        if ((ctxt->input != NULL) && (ctxt->input->buf != NULL))
12372            avail = xmlBufUse(ctxt->input->buf->buffer);
12373        /*
12374         * Depending on the current state it may not be such
12375         * a good idea to try parsing if there is nothing in the chunk
12376         * which would be worth doing a parser state transition and we
12377         * need to wait for more data
12378         */
12379        if ((terminate) || (avail > XML_MAX_TEXT_LENGTH) ||
12380            (old_avail == 0) || (avail == 0) ||
12381            (xmlParseCheckTransition(ctxt,
12382                       (const char *)&ctxt->input->base[old_avail],
12383                                     avail - old_avail)))
12384            xmlParseTryOrFinish(ctxt, terminate);
12385    }
12386    if (ctxt->instate == XML_PARSER_EOF)
12387        return(ctxt->errNo);
12388
12389    if ((ctxt->input != NULL) &&
12390         (((ctxt->input->end - ctxt->input->cur) > XML_MAX_LOOKUP_LIMIT) ||
12391         ((ctxt->input->cur - ctxt->input->base) > XML_MAX_LOOKUP_LIMIT)) &&
12392        ((ctxt->options & XML_PARSE_HUGE) == 0)) {
12393        xmlFatalErr(ctxt, XML_ERR_INTERNAL_ERROR, "Huge input lookup");
12394        ctxt->instate = XML_PARSER_EOF;
12395    }
12396    if ((ctxt->errNo != XML_ERR_OK) && (ctxt->disableSAX == 1))
12397        return(ctxt->errNo);
12398
12399    if (remain != 0) {
12400        chunk += size;
12401        size = remain;
12402        remain = 0;
12403        goto xmldecl_done;
12404    }
12405    if ((end_in_lf == 1) && (ctxt->input != NULL) &&
12406        (ctxt->input->buf != NULL)) {
12407	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer,
12408					 ctxt->input);
12409	size_t current = ctxt->input->cur - ctxt->input->base;
12410
12411	xmlParserInputBufferPush(ctxt->input->buf, 1, "\r");
12412
12413	xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input,
12414			      base, current);
12415    }
12416    if (terminate) {
12417	/*
12418	 * Check for termination
12419	 */
12420	int cur_avail = 0;
12421
12422	if (ctxt->input != NULL) {
12423	    if (ctxt->input->buf == NULL)
12424		cur_avail = ctxt->input->length -
12425			    (ctxt->input->cur - ctxt->input->base);
12426	    else
12427		cur_avail = xmlBufUse(ctxt->input->buf->buffer) -
12428			              (ctxt->input->cur - ctxt->input->base);
12429	}
12430
12431	if ((ctxt->instate != XML_PARSER_EOF) &&
12432	    (ctxt->instate != XML_PARSER_EPILOG)) {
12433	    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
12434	}
12435	if ((ctxt->instate == XML_PARSER_EPILOG) && (cur_avail > 0)) {
12436	    xmlFatalErr(ctxt, XML_ERR_DOCUMENT_END, NULL);
12437	}
12438	if (ctxt->instate != XML_PARSER_EOF) {
12439	    if ((ctxt->sax) && (ctxt->sax->endDocument != NULL))
12440		ctxt->sax->endDocument(ctxt->userData);
12441	}
12442	ctxt->instate = XML_PARSER_EOF;
12443    }
12444    if (ctxt->wellFormed == 0)
12445	return((xmlParserErrors) ctxt->errNo);
12446    else
12447        return(0);
12448}
12449
12450/************************************************************************
12451 *									*
12452 *		I/O front end functions to the parser			*
12453 *									*
12454 ************************************************************************/
12455
12456/**
12457 * xmlCreatePushParserCtxt:
12458 * @sax:  a SAX handler
12459 * @user_data:  The user data returned on SAX callbacks
12460 * @chunk:  a pointer to an array of chars
12461 * @size:  number of chars in the array
12462 * @filename:  an optional file name or URI
12463 *
12464 * Create a parser context for using the XML parser in push mode.
12465 * If @buffer and @size are non-NULL, the data is used to detect
12466 * the encoding.  The remaining characters will be parsed so they
12467 * don't need to be fed in again through xmlParseChunk.
12468 * To allow content encoding detection, @size should be >= 4
12469 * The value of @filename is used for fetching external entities
12470 * and error/warning reports.
12471 *
12472 * Returns the new parser context or NULL
12473 */
12474
12475xmlParserCtxtPtr
12476xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
12477                        const char *chunk, int size, const char *filename) {
12478    xmlParserCtxtPtr ctxt;
12479    xmlParserInputPtr inputStream;
12480    xmlParserInputBufferPtr buf;
12481    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
12482
12483    /*
12484     * plug some encoding conversion routines
12485     */
12486    if ((chunk != NULL) && (size >= 4))
12487	enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
12488
12489    buf = xmlAllocParserInputBuffer(enc);
12490    if (buf == NULL) return(NULL);
12491
12492    ctxt = xmlNewParserCtxt();
12493    if (ctxt == NULL) {
12494        xmlErrMemory(NULL, "creating parser: out of memory\n");
12495	xmlFreeParserInputBuffer(buf);
12496	return(NULL);
12497    }
12498    ctxt->dictNames = 1;
12499    ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 * sizeof(xmlChar *));
12500    if (ctxt->pushTab == NULL) {
12501        xmlErrMemory(ctxt, NULL);
12502	xmlFreeParserInputBuffer(buf);
12503	xmlFreeParserCtxt(ctxt);
12504	return(NULL);
12505    }
12506    if (sax != NULL) {
12507#ifdef LIBXML_SAX1_ENABLED
12508	if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
12509#endif /* LIBXML_SAX1_ENABLED */
12510	    xmlFree(ctxt->sax);
12511	ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
12512	if (ctxt->sax == NULL) {
12513	    xmlErrMemory(ctxt, NULL);
12514	    xmlFreeParserInputBuffer(buf);
12515	    xmlFreeParserCtxt(ctxt);
12516	    return(NULL);
12517	}
12518	memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
12519	if (sax->initialized == XML_SAX2_MAGIC)
12520	    memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
12521	else
12522	    memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
12523	if (user_data != NULL)
12524	    ctxt->userData = user_data;
12525    }
12526    if (filename == NULL) {
12527	ctxt->directory = NULL;
12528    } else {
12529        ctxt->directory = xmlParserGetDirectory(filename);
12530    }
12531
12532    inputStream = xmlNewInputStream(ctxt);
12533    if (inputStream == NULL) {
12534	xmlFreeParserCtxt(ctxt);
12535	xmlFreeParserInputBuffer(buf);
12536	return(NULL);
12537    }
12538
12539    if (filename == NULL)
12540	inputStream->filename = NULL;
12541    else {
12542	inputStream->filename = (char *)
12543	    xmlCanonicPath((const xmlChar *) filename);
12544	if (inputStream->filename == NULL) {
12545	    xmlFreeParserCtxt(ctxt);
12546	    xmlFreeParserInputBuffer(buf);
12547	    return(NULL);
12548	}
12549    }
12550    inputStream->buf = buf;
12551    xmlBufResetInput(inputStream->buf->buffer, inputStream);
12552    inputPush(ctxt, inputStream);
12553
12554    /*
12555     * If the caller didn't provide an initial 'chunk' for determining
12556     * the encoding, we set the context to XML_CHAR_ENCODING_NONE so
12557     * that it can be automatically determined later
12558     */
12559    if ((size == 0) || (chunk == NULL)) {
12560	ctxt->charset = XML_CHAR_ENCODING_NONE;
12561    } else if ((ctxt->input != NULL) && (ctxt->input->buf != NULL)) {
12562	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
12563	size_t cur = ctxt->input->cur - ctxt->input->base;
12564
12565	xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
12566
12567        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
12568#ifdef DEBUG_PUSH
12569	xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
12570#endif
12571    }
12572
12573    if (enc != XML_CHAR_ENCODING_NONE) {
12574        xmlSwitchEncoding(ctxt, enc);
12575    }
12576
12577    return(ctxt);
12578}
12579#endif /* LIBXML_PUSH_ENABLED */
12580
12581/**
12582 * xmlStopParser:
12583 * @ctxt:  an XML parser context
12584 *
12585 * Blocks further parser processing
12586 */
12587void
12588xmlStopParser(xmlParserCtxtPtr ctxt) {
12589    if (ctxt == NULL)
12590        return;
12591    ctxt->instate = XML_PARSER_EOF;
12592    ctxt->errNo = XML_ERR_USER_STOP;
12593    ctxt->disableSAX = 1;
12594    if (ctxt->input != NULL) {
12595	ctxt->input->cur = BAD_CAST"";
12596	ctxt->input->base = ctxt->input->cur;
12597    }
12598}
12599
12600/**
12601 * xmlCreateIOParserCtxt:
12602 * @sax:  a SAX handler
12603 * @user_data:  The user data returned on SAX callbacks
12604 * @ioread:  an I/O read function
12605 * @ioclose:  an I/O close function
12606 * @ioctx:  an I/O handler
12607 * @enc:  the charset encoding if known
12608 *
12609 * Create a parser context for using the XML parser with an existing
12610 * I/O stream
12611 *
12612 * Returns the new parser context or NULL
12613 */
12614xmlParserCtxtPtr
12615xmlCreateIOParserCtxt(xmlSAXHandlerPtr sax, void *user_data,
12616	xmlInputReadCallback   ioread, xmlInputCloseCallback  ioclose,
12617	void *ioctx, xmlCharEncoding enc) {
12618    xmlParserCtxtPtr ctxt;
12619    xmlParserInputPtr inputStream;
12620    xmlParserInputBufferPtr buf;
12621
12622    if (ioread == NULL) return(NULL);
12623
12624    buf = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, enc);
12625    if (buf == NULL) {
12626        if (ioclose != NULL)
12627            ioclose(ioctx);
12628        return (NULL);
12629    }
12630
12631    ctxt = xmlNewParserCtxt();
12632    if (ctxt == NULL) {
12633	xmlFreeParserInputBuffer(buf);
12634	return(NULL);
12635    }
12636    if (sax != NULL) {
12637#ifdef LIBXML_SAX1_ENABLED
12638	if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
12639#endif /* LIBXML_SAX1_ENABLED */
12640	    xmlFree(ctxt->sax);
12641	ctxt->sax = (xmlSAXHandlerPtr) xmlMalloc(sizeof(xmlSAXHandler));
12642	if (ctxt->sax == NULL) {
12643	    xmlErrMemory(ctxt, NULL);
12644	    xmlFreeParserCtxt(ctxt);
12645	    return(NULL);
12646	}
12647	memset(ctxt->sax, 0, sizeof(xmlSAXHandler));
12648	if (sax->initialized == XML_SAX2_MAGIC)
12649	    memcpy(ctxt->sax, sax, sizeof(xmlSAXHandler));
12650	else
12651	    memcpy(ctxt->sax, sax, sizeof(xmlSAXHandlerV1));
12652	if (user_data != NULL)
12653	    ctxt->userData = user_data;
12654    }
12655
12656    inputStream = xmlNewIOInputStream(ctxt, buf, enc);
12657    if (inputStream == NULL) {
12658	xmlFreeParserCtxt(ctxt);
12659	return(NULL);
12660    }
12661    inputPush(ctxt, inputStream);
12662
12663    return(ctxt);
12664}
12665
12666#ifdef LIBXML_VALID_ENABLED
12667/************************************************************************
12668 *									*
12669 *		Front ends when parsing a DTD				*
12670 *									*
12671 ************************************************************************/
12672
12673/**
12674 * xmlIOParseDTD:
12675 * @sax:  the SAX handler block or NULL
12676 * @input:  an Input Buffer
12677 * @enc:  the charset encoding if known
12678 *
12679 * Load and parse a DTD
12680 *
12681 * Returns the resulting xmlDtdPtr or NULL in case of error.
12682 * @input will be freed by the function in any case.
12683 */
12684
12685xmlDtdPtr
12686xmlIOParseDTD(xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input,
12687	      xmlCharEncoding enc) {
12688    xmlDtdPtr ret = NULL;
12689    xmlParserCtxtPtr ctxt;
12690    xmlParserInputPtr pinput = NULL;
12691    xmlChar start[4];
12692
12693    if (input == NULL)
12694	return(NULL);
12695
12696    ctxt = xmlNewParserCtxt();
12697    if (ctxt == NULL) {
12698        xmlFreeParserInputBuffer(input);
12699	return(NULL);
12700    }
12701
12702    /* We are loading a DTD */
12703    ctxt->options |= XML_PARSE_DTDLOAD;
12704
12705    /*
12706     * Set-up the SAX context
12707     */
12708    if (sax != NULL) {
12709	if (ctxt->sax != NULL)
12710	    xmlFree(ctxt->sax);
12711        ctxt->sax = sax;
12712        ctxt->userData = ctxt;
12713    }
12714    xmlDetectSAX2(ctxt);
12715
12716    /*
12717     * generate a parser input from the I/O handler
12718     */
12719
12720    pinput = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
12721    if (pinput == NULL) {
12722        if (sax != NULL) ctxt->sax = NULL;
12723        xmlFreeParserInputBuffer(input);
12724	xmlFreeParserCtxt(ctxt);
12725	return(NULL);
12726    }
12727
12728    /*
12729     * plug some encoding conversion routines here.
12730     */
12731    if (xmlPushInput(ctxt, pinput) < 0) {
12732        if (sax != NULL) ctxt->sax = NULL;
12733	xmlFreeParserCtxt(ctxt);
12734	return(NULL);
12735    }
12736    if (enc != XML_CHAR_ENCODING_NONE) {
12737        xmlSwitchEncoding(ctxt, enc);
12738    }
12739
12740    pinput->filename = NULL;
12741    pinput->line = 1;
12742    pinput->col = 1;
12743    pinput->base = ctxt->input->cur;
12744    pinput->cur = ctxt->input->cur;
12745    pinput->free = NULL;
12746
12747    /*
12748     * let's parse that entity knowing it's an external subset.
12749     */
12750    ctxt->inSubset = 2;
12751    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12752    if (ctxt->myDoc == NULL) {
12753	xmlErrMemory(ctxt, "New Doc failed");
12754	return(NULL);
12755    }
12756    ctxt->myDoc->properties = XML_DOC_INTERNAL;
12757    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12758	                               BAD_CAST "none", BAD_CAST "none");
12759
12760    if ((enc == XML_CHAR_ENCODING_NONE) &&
12761        ((ctxt->input->end - ctxt->input->cur) >= 4)) {
12762	/*
12763	 * Get the 4 first bytes and decode the charset
12764	 * if enc != XML_CHAR_ENCODING_NONE
12765	 * plug some encoding conversion routines.
12766	 */
12767	start[0] = RAW;
12768	start[1] = NXT(1);
12769	start[2] = NXT(2);
12770	start[3] = NXT(3);
12771	enc = xmlDetectCharEncoding(start, 4);
12772	if (enc != XML_CHAR_ENCODING_NONE) {
12773	    xmlSwitchEncoding(ctxt, enc);
12774	}
12775    }
12776
12777    xmlParseExternalSubset(ctxt, BAD_CAST "none", BAD_CAST "none");
12778
12779    if (ctxt->myDoc != NULL) {
12780	if (ctxt->wellFormed) {
12781	    ret = ctxt->myDoc->extSubset;
12782	    ctxt->myDoc->extSubset = NULL;
12783	    if (ret != NULL) {
12784		xmlNodePtr tmp;
12785
12786		ret->doc = NULL;
12787		tmp = ret->children;
12788		while (tmp != NULL) {
12789		    tmp->doc = NULL;
12790		    tmp = tmp->next;
12791		}
12792	    }
12793	} else {
12794	    ret = NULL;
12795	}
12796        xmlFreeDoc(ctxt->myDoc);
12797        ctxt->myDoc = NULL;
12798    }
12799    if (sax != NULL) ctxt->sax = NULL;
12800    xmlFreeParserCtxt(ctxt);
12801
12802    return(ret);
12803}
12804
12805/**
12806 * xmlSAXParseDTD:
12807 * @sax:  the SAX handler block
12808 * @ExternalID:  a NAME* containing the External ID of the DTD
12809 * @SystemID:  a NAME* containing the URL to the DTD
12810 *
12811 * Load and parse an external subset.
12812 *
12813 * Returns the resulting xmlDtdPtr or NULL in case of error.
12814 */
12815
12816xmlDtdPtr
12817xmlSAXParseDTD(xmlSAXHandlerPtr sax, const xmlChar *ExternalID,
12818                          const xmlChar *SystemID) {
12819    xmlDtdPtr ret = NULL;
12820    xmlParserCtxtPtr ctxt;
12821    xmlParserInputPtr input = NULL;
12822    xmlCharEncoding enc;
12823    xmlChar* systemIdCanonic;
12824
12825    if ((ExternalID == NULL) && (SystemID == NULL)) return(NULL);
12826
12827    ctxt = xmlNewParserCtxt();
12828    if (ctxt == NULL) {
12829	return(NULL);
12830    }
12831
12832    /* We are loading a DTD */
12833    ctxt->options |= XML_PARSE_DTDLOAD;
12834
12835    /*
12836     * Set-up the SAX context
12837     */
12838    if (sax != NULL) {
12839	if (ctxt->sax != NULL)
12840	    xmlFree(ctxt->sax);
12841        ctxt->sax = sax;
12842        ctxt->userData = ctxt;
12843    }
12844
12845    /*
12846     * Canonicalise the system ID
12847     */
12848    systemIdCanonic = xmlCanonicPath(SystemID);
12849    if ((SystemID != NULL) && (systemIdCanonic == NULL)) {
12850	xmlFreeParserCtxt(ctxt);
12851	return(NULL);
12852    }
12853
12854    /*
12855     * Ask the Entity resolver to load the damn thing
12856     */
12857
12858    if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
12859	input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
12860	                                 systemIdCanonic);
12861    if (input == NULL) {
12862        if (sax != NULL) ctxt->sax = NULL;
12863	xmlFreeParserCtxt(ctxt);
12864	if (systemIdCanonic != NULL)
12865	    xmlFree(systemIdCanonic);
12866	return(NULL);
12867    }
12868
12869    /*
12870     * plug some encoding conversion routines here.
12871     */
12872    if (xmlPushInput(ctxt, input) < 0) {
12873        if (sax != NULL) ctxt->sax = NULL;
12874	xmlFreeParserCtxt(ctxt);
12875	if (systemIdCanonic != NULL)
12876	    xmlFree(systemIdCanonic);
12877	return(NULL);
12878    }
12879    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
12880	enc = xmlDetectCharEncoding(ctxt->input->cur, 4);
12881	xmlSwitchEncoding(ctxt, enc);
12882    }
12883
12884    if (input->filename == NULL)
12885	input->filename = (char *) systemIdCanonic;
12886    else
12887	xmlFree(systemIdCanonic);
12888    input->line = 1;
12889    input->col = 1;
12890    input->base = ctxt->input->cur;
12891    input->cur = ctxt->input->cur;
12892    input->free = NULL;
12893
12894    /*
12895     * let's parse that entity knowing it's an external subset.
12896     */
12897    ctxt->inSubset = 2;
12898    ctxt->myDoc = xmlNewDoc(BAD_CAST "1.0");
12899    if (ctxt->myDoc == NULL) {
12900	xmlErrMemory(ctxt, "New Doc failed");
12901        if (sax != NULL) ctxt->sax = NULL;
12902	xmlFreeParserCtxt(ctxt);
12903	return(NULL);
12904    }
12905    ctxt->myDoc->properties = XML_DOC_INTERNAL;
12906    ctxt->myDoc->extSubset = xmlNewDtd(ctxt->myDoc, BAD_CAST "none",
12907	                               ExternalID, SystemID);
12908    xmlParseExternalSubset(ctxt, ExternalID, SystemID);
12909
12910    if (ctxt->myDoc != NULL) {
12911	if (ctxt->wellFormed) {
12912	    ret = ctxt->myDoc->extSubset;
12913	    ctxt->myDoc->extSubset = NULL;
12914	    if (ret != NULL) {
12915		xmlNodePtr tmp;
12916
12917		ret->doc = NULL;
12918		tmp = ret->children;
12919		while (tmp != NULL) {
12920		    tmp->doc = NULL;
12921		    tmp = tmp->next;
12922		}
12923	    }
12924	} else {
12925	    ret = NULL;
12926	}
12927        xmlFreeDoc(ctxt->myDoc);
12928        ctxt->myDoc = NULL;
12929    }
12930    if (sax != NULL) ctxt->sax = NULL;
12931    xmlFreeParserCtxt(ctxt);
12932
12933    return(ret);
12934}
12935
12936
12937/**
12938 * xmlParseDTD:
12939 * @ExternalID:  a NAME* containing the External ID of the DTD
12940 * @SystemID:  a NAME* containing the URL to the DTD
12941 *
12942 * Load and parse an external subset.
12943 *
12944 * Returns the resulting xmlDtdPtr or NULL in case of error.
12945 */
12946
12947xmlDtdPtr
12948xmlParseDTD(const xmlChar *ExternalID, const xmlChar *SystemID) {
12949    return(xmlSAXParseDTD(NULL, ExternalID, SystemID));
12950}
12951#endif /* LIBXML_VALID_ENABLED */
12952
12953/************************************************************************
12954 *									*
12955 *		Front ends when parsing an Entity			*
12956 *									*
12957 ************************************************************************/
12958
12959/**
12960 * xmlParseCtxtExternalEntity:
12961 * @ctx:  the existing parsing context
12962 * @URL:  the URL for the entity to load
12963 * @ID:  the System ID for the entity to load
12964 * @lst:  the return value for the set of parsed nodes
12965 *
12966 * Parse an external general entity within an existing parsing context
12967 * An external general parsed entity is well-formed if it matches the
12968 * production labeled extParsedEnt.
12969 *
12970 * [78] extParsedEnt ::= TextDecl? content
12971 *
12972 * Returns 0 if the entity is well formed, -1 in case of args problem and
12973 *    the parser error code otherwise
12974 */
12975
12976int
12977xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL,
12978	               const xmlChar *ID, xmlNodePtr *lst) {
12979    xmlParserCtxtPtr ctxt;
12980    xmlDocPtr newDoc;
12981    xmlNodePtr newRoot;
12982    xmlSAXHandlerPtr oldsax = NULL;
12983    int ret = 0;
12984    xmlChar start[4];
12985    xmlCharEncoding enc;
12986
12987    if (ctx == NULL) return(-1);
12988
12989    if (((ctx->depth > 40) && ((ctx->options & XML_PARSE_HUGE) == 0)) ||
12990        (ctx->depth > 1024)) {
12991	return(XML_ERR_ENTITY_LOOP);
12992    }
12993
12994    if (lst != NULL)
12995        *lst = NULL;
12996    if ((URL == NULL) && (ID == NULL))
12997	return(-1);
12998    if (ctx->myDoc == NULL) /* @@ relax but check for dereferences */
12999	return(-1);
13000
13001    ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, ctx);
13002    if (ctxt == NULL) {
13003	return(-1);
13004    }
13005
13006    oldsax = ctxt->sax;
13007    ctxt->sax = ctx->sax;
13008    xmlDetectSAX2(ctxt);
13009    newDoc = xmlNewDoc(BAD_CAST "1.0");
13010    if (newDoc == NULL) {
13011	xmlFreeParserCtxt(ctxt);
13012	return(-1);
13013    }
13014    newDoc->properties = XML_DOC_INTERNAL;
13015    if (ctx->myDoc->dict) {
13016	newDoc->dict = ctx->myDoc->dict;
13017	xmlDictReference(newDoc->dict);
13018    }
13019    if (ctx->myDoc != NULL) {
13020	newDoc->intSubset = ctx->myDoc->intSubset;
13021	newDoc->extSubset = ctx->myDoc->extSubset;
13022    }
13023    if (ctx->myDoc->URL != NULL) {
13024	newDoc->URL = xmlStrdup(ctx->myDoc->URL);
13025    }
13026    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
13027    if (newRoot == NULL) {
13028	ctxt->sax = oldsax;
13029	xmlFreeParserCtxt(ctxt);
13030	newDoc->intSubset = NULL;
13031	newDoc->extSubset = NULL;
13032        xmlFreeDoc(newDoc);
13033	return(-1);
13034    }
13035    xmlAddChild((xmlNodePtr) newDoc, newRoot);
13036    nodePush(ctxt, newDoc->children);
13037    if (ctx->myDoc == NULL) {
13038	ctxt->myDoc = newDoc;
13039    } else {
13040	ctxt->myDoc = ctx->myDoc;
13041	newDoc->children->doc = ctx->myDoc;
13042    }
13043
13044    /*
13045     * Get the 4 first bytes and decode the charset
13046     * if enc != XML_CHAR_ENCODING_NONE
13047     * plug some encoding conversion routines.
13048     */
13049    GROW
13050    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
13051	start[0] = RAW;
13052	start[1] = NXT(1);
13053	start[2] = NXT(2);
13054	start[3] = NXT(3);
13055	enc = xmlDetectCharEncoding(start, 4);
13056	if (enc != XML_CHAR_ENCODING_NONE) {
13057	    xmlSwitchEncoding(ctxt, enc);
13058	}
13059    }
13060
13061    /*
13062     * Parse a possible text declaration first
13063     */
13064    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
13065	xmlParseTextDecl(ctxt);
13066	/*
13067	 * An XML-1.0 document can't reference an entity not XML-1.0
13068	 */
13069	if ((xmlStrEqual(ctx->version, BAD_CAST "1.0")) &&
13070	    (!xmlStrEqual(ctxt->input->version, BAD_CAST "1.0"))) {
13071	    xmlFatalErrMsg(ctxt, XML_ERR_VERSION_MISMATCH,
13072	                   "Version mismatch between document and entity\n");
13073	}
13074    }
13075
13076    /*
13077     * If the user provided its own SAX callbacks then reuse the
13078     * useData callback field, otherwise the expected setup in a
13079     * DOM builder is to have userData == ctxt
13080     */
13081    if (ctx->userData == ctx)
13082        ctxt->userData = ctxt;
13083    else
13084        ctxt->userData = ctx->userData;
13085
13086    /*
13087     * Doing validity checking on chunk doesn't make sense
13088     */
13089    ctxt->instate = XML_PARSER_CONTENT;
13090    ctxt->validate = ctx->validate;
13091    ctxt->valid = ctx->valid;
13092    ctxt->loadsubset = ctx->loadsubset;
13093    ctxt->depth = ctx->depth + 1;
13094    ctxt->replaceEntities = ctx->replaceEntities;
13095    if (ctxt->validate) {
13096	ctxt->vctxt.error = ctx->vctxt.error;
13097	ctxt->vctxt.warning = ctx->vctxt.warning;
13098    } else {
13099	ctxt->vctxt.error = NULL;
13100	ctxt->vctxt.warning = NULL;
13101    }
13102    ctxt->vctxt.nodeTab = NULL;
13103    ctxt->vctxt.nodeNr = 0;
13104    ctxt->vctxt.nodeMax = 0;
13105    ctxt->vctxt.node = NULL;
13106    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
13107    ctxt->dict = ctx->dict;
13108    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13109    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13110    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13111    ctxt->dictNames = ctx->dictNames;
13112    ctxt->attsDefault = ctx->attsDefault;
13113    ctxt->attsSpecial = ctx->attsSpecial;
13114    ctxt->linenumbers = ctx->linenumbers;
13115
13116    xmlParseContent(ctxt);
13117
13118    ctx->validate = ctxt->validate;
13119    ctx->valid = ctxt->valid;
13120    if ((RAW == '<') && (NXT(1) == '/')) {
13121	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13122    } else if (RAW != 0) {
13123	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13124    }
13125    if (ctxt->node != newDoc->children) {
13126	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13127    }
13128
13129    if (!ctxt->wellFormed) {
13130        if (ctxt->errNo == 0)
13131	    ret = 1;
13132	else
13133	    ret = ctxt->errNo;
13134    } else {
13135	if (lst != NULL) {
13136	    xmlNodePtr cur;
13137
13138	    /*
13139	     * Return the newly created nodeset after unlinking it from
13140	     * they pseudo parent.
13141	     */
13142	    cur = newDoc->children->children;
13143	    *lst = cur;
13144	    while (cur != NULL) {
13145		cur->parent = NULL;
13146		cur = cur->next;
13147	    }
13148            newDoc->children->children = NULL;
13149	}
13150	ret = 0;
13151    }
13152    ctxt->sax = oldsax;
13153    ctxt->dict = NULL;
13154    ctxt->attsDefault = NULL;
13155    ctxt->attsSpecial = NULL;
13156    xmlFreeParserCtxt(ctxt);
13157    newDoc->intSubset = NULL;
13158    newDoc->extSubset = NULL;
13159    xmlFreeDoc(newDoc);
13160
13161    return(ret);
13162}
13163
13164/**
13165 * xmlParseExternalEntityPrivate:
13166 * @doc:  the document the chunk pertains to
13167 * @oldctxt:  the previous parser context if available
13168 * @sax:  the SAX handler bloc (possibly NULL)
13169 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13170 * @depth:  Used for loop detection, use 0
13171 * @URL:  the URL for the entity to load
13172 * @ID:  the System ID for the entity to load
13173 * @list:  the return value for the set of parsed nodes
13174 *
13175 * Private version of xmlParseExternalEntity()
13176 *
13177 * Returns 0 if the entity is well formed, -1 in case of args problem and
13178 *    the parser error code otherwise
13179 */
13180
13181static xmlParserErrors
13182xmlParseExternalEntityPrivate(xmlDocPtr doc, xmlParserCtxtPtr oldctxt,
13183	              xmlSAXHandlerPtr sax,
13184		      void *user_data, int depth, const xmlChar *URL,
13185		      const xmlChar *ID, xmlNodePtr *list) {
13186    xmlParserCtxtPtr ctxt;
13187    xmlDocPtr newDoc;
13188    xmlNodePtr newRoot;
13189    xmlSAXHandlerPtr oldsax = NULL;
13190    xmlParserErrors ret = XML_ERR_OK;
13191    xmlChar start[4];
13192    xmlCharEncoding enc;
13193
13194    if (((depth > 40) &&
13195	((oldctxt == NULL) || (oldctxt->options & XML_PARSE_HUGE) == 0)) ||
13196	(depth > 1024)) {
13197	return(XML_ERR_ENTITY_LOOP);
13198    }
13199
13200    if (list != NULL)
13201        *list = NULL;
13202    if ((URL == NULL) && (ID == NULL))
13203	return(XML_ERR_INTERNAL_ERROR);
13204    if (doc == NULL)
13205	return(XML_ERR_INTERNAL_ERROR);
13206
13207
13208    ctxt = xmlCreateEntityParserCtxtInternal(URL, ID, NULL, oldctxt);
13209    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
13210    ctxt->userData = ctxt;
13211    if (oldctxt != NULL) {
13212	ctxt->_private = oldctxt->_private;
13213	ctxt->loadsubset = oldctxt->loadsubset;
13214	ctxt->validate = oldctxt->validate;
13215	ctxt->external = oldctxt->external;
13216	ctxt->record_info = oldctxt->record_info;
13217	ctxt->node_seq.maximum = oldctxt->node_seq.maximum;
13218	ctxt->node_seq.length = oldctxt->node_seq.length;
13219	ctxt->node_seq.buffer = oldctxt->node_seq.buffer;
13220    } else {
13221	/*
13222	 * Doing validity checking on chunk without context
13223	 * doesn't make sense
13224	 */
13225	ctxt->_private = NULL;
13226	ctxt->validate = 0;
13227	ctxt->external = 2;
13228	ctxt->loadsubset = 0;
13229    }
13230    if (sax != NULL) {
13231	oldsax = ctxt->sax;
13232        ctxt->sax = sax;
13233	if (user_data != NULL)
13234	    ctxt->userData = user_data;
13235    }
13236    xmlDetectSAX2(ctxt);
13237    newDoc = xmlNewDoc(BAD_CAST "1.0");
13238    if (newDoc == NULL) {
13239	ctxt->node_seq.maximum = 0;
13240	ctxt->node_seq.length = 0;
13241	ctxt->node_seq.buffer = NULL;
13242	xmlFreeParserCtxt(ctxt);
13243	return(XML_ERR_INTERNAL_ERROR);
13244    }
13245    newDoc->properties = XML_DOC_INTERNAL;
13246    newDoc->intSubset = doc->intSubset;
13247    newDoc->extSubset = doc->extSubset;
13248    newDoc->dict = doc->dict;
13249    xmlDictReference(newDoc->dict);
13250
13251    if (doc->URL != NULL) {
13252	newDoc->URL = xmlStrdup(doc->URL);
13253    }
13254    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
13255    if (newRoot == NULL) {
13256	if (sax != NULL)
13257	    ctxt->sax = oldsax;
13258	ctxt->node_seq.maximum = 0;
13259	ctxt->node_seq.length = 0;
13260	ctxt->node_seq.buffer = NULL;
13261	xmlFreeParserCtxt(ctxt);
13262	newDoc->intSubset = NULL;
13263	newDoc->extSubset = NULL;
13264        xmlFreeDoc(newDoc);
13265	return(XML_ERR_INTERNAL_ERROR);
13266    }
13267    xmlAddChild((xmlNodePtr) newDoc, newRoot);
13268    nodePush(ctxt, newDoc->children);
13269    ctxt->myDoc = doc;
13270    newRoot->doc = doc;
13271
13272    /*
13273     * Get the 4 first bytes and decode the charset
13274     * if enc != XML_CHAR_ENCODING_NONE
13275     * plug some encoding conversion routines.
13276     */
13277    GROW;
13278    if ((ctxt->input->end - ctxt->input->cur) >= 4) {
13279	start[0] = RAW;
13280	start[1] = NXT(1);
13281	start[2] = NXT(2);
13282	start[3] = NXT(3);
13283	enc = xmlDetectCharEncoding(start, 4);
13284	if (enc != XML_CHAR_ENCODING_NONE) {
13285	    xmlSwitchEncoding(ctxt, enc);
13286	}
13287    }
13288
13289    /*
13290     * Parse a possible text declaration first
13291     */
13292    if ((CMP5(CUR_PTR, '<', '?', 'x', 'm', 'l')) && (IS_BLANK_CH(NXT(5)))) {
13293	xmlParseTextDecl(ctxt);
13294    }
13295
13296    ctxt->instate = XML_PARSER_CONTENT;
13297    ctxt->depth = depth;
13298
13299    xmlParseContent(ctxt);
13300
13301    if ((RAW == '<') && (NXT(1) == '/')) {
13302	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13303    } else if (RAW != 0) {
13304	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13305    }
13306    if (ctxt->node != newDoc->children) {
13307	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13308    }
13309
13310    if (!ctxt->wellFormed) {
13311        if (ctxt->errNo == 0)
13312	    ret = XML_ERR_INTERNAL_ERROR;
13313	else
13314	    ret = (xmlParserErrors)ctxt->errNo;
13315    } else {
13316	if (list != NULL) {
13317	    xmlNodePtr cur;
13318
13319	    /*
13320	     * Return the newly created nodeset after unlinking it from
13321	     * they pseudo parent.
13322	     */
13323	    cur = newDoc->children->children;
13324	    *list = cur;
13325	    while (cur != NULL) {
13326		cur->parent = NULL;
13327		cur = cur->next;
13328	    }
13329            newDoc->children->children = NULL;
13330	}
13331	ret = XML_ERR_OK;
13332    }
13333
13334    /*
13335     * Record in the parent context the number of entities replacement
13336     * done when parsing that reference.
13337     */
13338    if (oldctxt != NULL)
13339        oldctxt->nbentities += ctxt->nbentities;
13340
13341    /*
13342     * Also record the size of the entity parsed
13343     */
13344    if (ctxt->input != NULL) {
13345	oldctxt->sizeentities += ctxt->input->consumed;
13346	oldctxt->sizeentities += (ctxt->input->cur - ctxt->input->base);
13347    }
13348    /*
13349     * And record the last error if any
13350     */
13351    if (ctxt->lastError.code != XML_ERR_OK)
13352        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
13353
13354    if (sax != NULL)
13355	ctxt->sax = oldsax;
13356    oldctxt->node_seq.maximum = ctxt->node_seq.maximum;
13357    oldctxt->node_seq.length = ctxt->node_seq.length;
13358    oldctxt->node_seq.buffer = ctxt->node_seq.buffer;
13359    ctxt->node_seq.maximum = 0;
13360    ctxt->node_seq.length = 0;
13361    ctxt->node_seq.buffer = NULL;
13362    xmlFreeParserCtxt(ctxt);
13363    newDoc->intSubset = NULL;
13364    newDoc->extSubset = NULL;
13365    xmlFreeDoc(newDoc);
13366
13367    return(ret);
13368}
13369
13370#ifdef LIBXML_SAX1_ENABLED
13371/**
13372 * xmlParseExternalEntity:
13373 * @doc:  the document the chunk pertains to
13374 * @sax:  the SAX handler bloc (possibly NULL)
13375 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13376 * @depth:  Used for loop detection, use 0
13377 * @URL:  the URL for the entity to load
13378 * @ID:  the System ID for the entity to load
13379 * @lst:  the return value for the set of parsed nodes
13380 *
13381 * Parse an external general entity
13382 * An external general parsed entity is well-formed if it matches the
13383 * production labeled extParsedEnt.
13384 *
13385 * [78] extParsedEnt ::= TextDecl? content
13386 *
13387 * Returns 0 if the entity is well formed, -1 in case of args problem and
13388 *    the parser error code otherwise
13389 */
13390
13391int
13392xmlParseExternalEntity(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data,
13393	  int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst) {
13394    return(xmlParseExternalEntityPrivate(doc, NULL, sax, user_data, depth, URL,
13395		                       ID, lst));
13396}
13397
13398/**
13399 * xmlParseBalancedChunkMemory:
13400 * @doc:  the document the chunk pertains to
13401 * @sax:  the SAX handler bloc (possibly NULL)
13402 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13403 * @depth:  Used for loop detection, use 0
13404 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13405 * @lst:  the return value for the set of parsed nodes
13406 *
13407 * Parse a well-balanced chunk of an XML document
13408 * called by the parser
13409 * The allowed sequence for the Well Balanced Chunk is the one defined by
13410 * the content production in the XML grammar:
13411 *
13412 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13413 *
13414 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
13415 *    the parser error code otherwise
13416 */
13417
13418int
13419xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax,
13420     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst) {
13421    return xmlParseBalancedChunkMemoryRecover( doc, sax, user_data,
13422                                                depth, string, lst, 0 );
13423}
13424#endif /* LIBXML_SAX1_ENABLED */
13425
13426/**
13427 * xmlParseBalancedChunkMemoryInternal:
13428 * @oldctxt:  the existing parsing context
13429 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13430 * @user_data:  the user data field for the parser context
13431 * @lst:  the return value for the set of parsed nodes
13432 *
13433 *
13434 * Parse a well-balanced chunk of an XML document
13435 * called by the parser
13436 * The allowed sequence for the Well Balanced Chunk is the one defined by
13437 * the content production in the XML grammar:
13438 *
13439 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13440 *
13441 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
13442 * error code otherwise
13443 *
13444 * In case recover is set to 1, the nodelist will not be empty even if
13445 * the parsed chunk is not well balanced.
13446 */
13447static xmlParserErrors
13448xmlParseBalancedChunkMemoryInternal(xmlParserCtxtPtr oldctxt,
13449	const xmlChar *string, void *user_data, xmlNodePtr *lst) {
13450    xmlParserCtxtPtr ctxt;
13451    xmlDocPtr newDoc = NULL;
13452    xmlNodePtr newRoot;
13453    xmlSAXHandlerPtr oldsax = NULL;
13454    xmlNodePtr content = NULL;
13455    xmlNodePtr last = NULL;
13456    int size;
13457    xmlParserErrors ret = XML_ERR_OK;
13458#ifdef SAX2
13459    int i;
13460#endif
13461
13462    if (((oldctxt->depth > 40) && ((oldctxt->options & XML_PARSE_HUGE) == 0)) ||
13463        (oldctxt->depth >  1024)) {
13464	return(XML_ERR_ENTITY_LOOP);
13465    }
13466
13467
13468    if (lst != NULL)
13469        *lst = NULL;
13470    if (string == NULL)
13471        return(XML_ERR_INTERNAL_ERROR);
13472
13473    size = xmlStrlen(string);
13474
13475    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
13476    if (ctxt == NULL) return(XML_WAR_UNDECLARED_ENTITY);
13477    if (user_data != NULL)
13478	ctxt->userData = user_data;
13479    else
13480	ctxt->userData = ctxt;
13481    if (ctxt->dict != NULL) xmlDictFree(ctxt->dict);
13482    ctxt->dict = oldctxt->dict;
13483    ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13484    ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13485    ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13486
13487#ifdef SAX2
13488    /* propagate namespaces down the entity */
13489    for (i = 0;i < oldctxt->nsNr;i += 2) {
13490        nsPush(ctxt, oldctxt->nsTab[i], oldctxt->nsTab[i+1]);
13491    }
13492#endif
13493
13494    oldsax = ctxt->sax;
13495    ctxt->sax = oldctxt->sax;
13496    xmlDetectSAX2(ctxt);
13497    ctxt->replaceEntities = oldctxt->replaceEntities;
13498    ctxt->options = oldctxt->options;
13499
13500    ctxt->_private = oldctxt->_private;
13501    if (oldctxt->myDoc == NULL) {
13502	newDoc = xmlNewDoc(BAD_CAST "1.0");
13503	if (newDoc == NULL) {
13504	    ctxt->sax = oldsax;
13505	    ctxt->dict = NULL;
13506	    xmlFreeParserCtxt(ctxt);
13507	    return(XML_ERR_INTERNAL_ERROR);
13508	}
13509	newDoc->properties = XML_DOC_INTERNAL;
13510	newDoc->dict = ctxt->dict;
13511	xmlDictReference(newDoc->dict);
13512	ctxt->myDoc = newDoc;
13513    } else {
13514	ctxt->myDoc = oldctxt->myDoc;
13515        content = ctxt->myDoc->children;
13516	last = ctxt->myDoc->last;
13517    }
13518    newRoot = xmlNewDocNode(ctxt->myDoc, NULL, BAD_CAST "pseudoroot", NULL);
13519    if (newRoot == NULL) {
13520	ctxt->sax = oldsax;
13521	ctxt->dict = NULL;
13522	xmlFreeParserCtxt(ctxt);
13523	if (newDoc != NULL) {
13524	    xmlFreeDoc(newDoc);
13525	}
13526	return(XML_ERR_INTERNAL_ERROR);
13527    }
13528    ctxt->myDoc->children = NULL;
13529    ctxt->myDoc->last = NULL;
13530    xmlAddChild((xmlNodePtr) ctxt->myDoc, newRoot);
13531    nodePush(ctxt, ctxt->myDoc->children);
13532    ctxt->instate = XML_PARSER_CONTENT;
13533    ctxt->depth = oldctxt->depth + 1;
13534
13535    ctxt->validate = 0;
13536    ctxt->loadsubset = oldctxt->loadsubset;
13537    if ((oldctxt->validate) || (oldctxt->replaceEntities != 0)) {
13538	/*
13539	 * ID/IDREF registration will be done in xmlValidateElement below
13540	 */
13541	ctxt->loadsubset |= XML_SKIP_IDS;
13542    }
13543    ctxt->dictNames = oldctxt->dictNames;
13544    ctxt->attsDefault = oldctxt->attsDefault;
13545    ctxt->attsSpecial = oldctxt->attsSpecial;
13546
13547    xmlParseContent(ctxt);
13548    if ((RAW == '<') && (NXT(1) == '/')) {
13549	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13550    } else if (RAW != 0) {
13551	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13552    }
13553    if (ctxt->node != ctxt->myDoc->children) {
13554	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13555    }
13556
13557    if (!ctxt->wellFormed) {
13558        if (ctxt->errNo == 0)
13559	    ret = XML_ERR_INTERNAL_ERROR;
13560	else
13561	    ret = (xmlParserErrors)ctxt->errNo;
13562    } else {
13563      ret = XML_ERR_OK;
13564    }
13565
13566    if ((lst != NULL) && (ret == XML_ERR_OK)) {
13567	xmlNodePtr cur;
13568
13569	/*
13570	 * Return the newly created nodeset after unlinking it from
13571	 * they pseudo parent.
13572	 */
13573	cur = ctxt->myDoc->children->children;
13574	*lst = cur;
13575	while (cur != NULL) {
13576#ifdef LIBXML_VALID_ENABLED
13577	    if ((oldctxt->validate) && (oldctxt->wellFormed) &&
13578		(oldctxt->myDoc) && (oldctxt->myDoc->intSubset) &&
13579		(cur->type == XML_ELEMENT_NODE)) {
13580		oldctxt->valid &= xmlValidateElement(&oldctxt->vctxt,
13581			oldctxt->myDoc, cur);
13582	    }
13583#endif /* LIBXML_VALID_ENABLED */
13584	    cur->parent = NULL;
13585	    cur = cur->next;
13586	}
13587	ctxt->myDoc->children->children = NULL;
13588    }
13589    if (ctxt->myDoc != NULL) {
13590	xmlFreeNode(ctxt->myDoc->children);
13591        ctxt->myDoc->children = content;
13592        ctxt->myDoc->last = last;
13593    }
13594
13595    /*
13596     * Record in the parent context the number of entities replacement
13597     * done when parsing that reference.
13598     */
13599    if (oldctxt != NULL)
13600        oldctxt->nbentities += ctxt->nbentities;
13601
13602    /*
13603     * Also record the last error if any
13604     */
13605    if (ctxt->lastError.code != XML_ERR_OK)
13606        xmlCopyError(&ctxt->lastError, &oldctxt->lastError);
13607
13608    ctxt->sax = oldsax;
13609    ctxt->dict = NULL;
13610    ctxt->attsDefault = NULL;
13611    ctxt->attsSpecial = NULL;
13612    xmlFreeParserCtxt(ctxt);
13613    if (newDoc != NULL) {
13614	xmlFreeDoc(newDoc);
13615    }
13616
13617    return(ret);
13618}
13619
13620/**
13621 * xmlParseInNodeContext:
13622 * @node:  the context node
13623 * @data:  the input string
13624 * @datalen:  the input string length in bytes
13625 * @options:  a combination of xmlParserOption
13626 * @lst:  the return value for the set of parsed nodes
13627 *
13628 * Parse a well-balanced chunk of an XML document
13629 * within the context (DTD, namespaces, etc ...) of the given node.
13630 *
13631 * The allowed sequence for the data is a Well Balanced Chunk defined by
13632 * the content production in the XML grammar:
13633 *
13634 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13635 *
13636 * Returns XML_ERR_OK if the chunk is well balanced, and the parser
13637 * error code otherwise
13638 */
13639xmlParserErrors
13640xmlParseInNodeContext(xmlNodePtr node, const char *data, int datalen,
13641                      int options, xmlNodePtr *lst) {
13642#ifdef SAX2
13643    xmlParserCtxtPtr ctxt;
13644    xmlDocPtr doc = NULL;
13645    xmlNodePtr fake, cur;
13646    int nsnr = 0;
13647
13648    xmlParserErrors ret = XML_ERR_OK;
13649
13650    /*
13651     * check all input parameters, grab the document
13652     */
13653    if ((lst == NULL) || (node == NULL) || (data == NULL) || (datalen < 0))
13654        return(XML_ERR_INTERNAL_ERROR);
13655    switch (node->type) {
13656        case XML_ELEMENT_NODE:
13657        case XML_ATTRIBUTE_NODE:
13658        case XML_TEXT_NODE:
13659        case XML_CDATA_SECTION_NODE:
13660        case XML_ENTITY_REF_NODE:
13661        case XML_PI_NODE:
13662        case XML_COMMENT_NODE:
13663        case XML_DOCUMENT_NODE:
13664        case XML_HTML_DOCUMENT_NODE:
13665	    break;
13666	default:
13667	    return(XML_ERR_INTERNAL_ERROR);
13668
13669    }
13670    while ((node != NULL) && (node->type != XML_ELEMENT_NODE) &&
13671           (node->type != XML_DOCUMENT_NODE) &&
13672	   (node->type != XML_HTML_DOCUMENT_NODE))
13673	node = node->parent;
13674    if (node == NULL)
13675	return(XML_ERR_INTERNAL_ERROR);
13676    if (node->type == XML_ELEMENT_NODE)
13677	doc = node->doc;
13678    else
13679        doc = (xmlDocPtr) node;
13680    if (doc == NULL)
13681	return(XML_ERR_INTERNAL_ERROR);
13682
13683    /*
13684     * allocate a context and set-up everything not related to the
13685     * node position in the tree
13686     */
13687    if (doc->type == XML_DOCUMENT_NODE)
13688	ctxt = xmlCreateMemoryParserCtxt((char *) data, datalen);
13689#ifdef LIBXML_HTML_ENABLED
13690    else if (doc->type == XML_HTML_DOCUMENT_NODE) {
13691	ctxt = htmlCreateMemoryParserCtxt((char *) data, datalen);
13692        /*
13693         * When parsing in context, it makes no sense to add implied
13694         * elements like html/body/etc...
13695         */
13696        options |= HTML_PARSE_NOIMPLIED;
13697    }
13698#endif
13699    else
13700        return(XML_ERR_INTERNAL_ERROR);
13701
13702    if (ctxt == NULL)
13703        return(XML_ERR_NO_MEMORY);
13704
13705    /*
13706     * Use input doc's dict if present, else assure XML_PARSE_NODICT is set.
13707     * We need a dictionary for xmlDetectSAX2, so if there's no doc dict
13708     * we must wait until the last moment to free the original one.
13709     */
13710    if (doc->dict != NULL) {
13711        if (ctxt->dict != NULL)
13712	    xmlDictFree(ctxt->dict);
13713	ctxt->dict = doc->dict;
13714    } else
13715        options |= XML_PARSE_NODICT;
13716
13717    if (doc->encoding != NULL) {
13718        xmlCharEncodingHandlerPtr hdlr;
13719
13720        if (ctxt->encoding != NULL)
13721	    xmlFree((xmlChar *) ctxt->encoding);
13722        ctxt->encoding = xmlStrdup((const xmlChar *) doc->encoding);
13723
13724        hdlr = xmlFindCharEncodingHandler((const char *) doc->encoding);
13725        if (hdlr != NULL) {
13726            xmlSwitchToEncoding(ctxt, hdlr);
13727	} else {
13728            return(XML_ERR_UNSUPPORTED_ENCODING);
13729        }
13730    }
13731
13732    xmlCtxtUseOptionsInternal(ctxt, options, NULL);
13733    xmlDetectSAX2(ctxt);
13734    ctxt->myDoc = doc;
13735    /* parsing in context, i.e. as within existing content */
13736    ctxt->instate = XML_PARSER_CONTENT;
13737
13738    fake = xmlNewComment(NULL);
13739    if (fake == NULL) {
13740        xmlFreeParserCtxt(ctxt);
13741	return(XML_ERR_NO_MEMORY);
13742    }
13743    xmlAddChild(node, fake);
13744
13745    if (node->type == XML_ELEMENT_NODE) {
13746	nodePush(ctxt, node);
13747	/*
13748	 * initialize the SAX2 namespaces stack
13749	 */
13750	cur = node;
13751	while ((cur != NULL) && (cur->type == XML_ELEMENT_NODE)) {
13752	    xmlNsPtr ns = cur->nsDef;
13753	    const xmlChar *iprefix, *ihref;
13754
13755	    while (ns != NULL) {
13756		if (ctxt->dict) {
13757		    iprefix = xmlDictLookup(ctxt->dict, ns->prefix, -1);
13758		    ihref = xmlDictLookup(ctxt->dict, ns->href, -1);
13759		} else {
13760		    iprefix = ns->prefix;
13761		    ihref = ns->href;
13762		}
13763
13764	        if (xmlGetNamespace(ctxt, iprefix) == NULL) {
13765		    nsPush(ctxt, iprefix, ihref);
13766		    nsnr++;
13767		}
13768		ns = ns->next;
13769	    }
13770	    cur = cur->parent;
13771	}
13772    }
13773
13774    if ((ctxt->validate) || (ctxt->replaceEntities != 0)) {
13775	/*
13776	 * ID/IDREF registration will be done in xmlValidateElement below
13777	 */
13778	ctxt->loadsubset |= XML_SKIP_IDS;
13779    }
13780
13781#ifdef LIBXML_HTML_ENABLED
13782    if (doc->type == XML_HTML_DOCUMENT_NODE)
13783        __htmlParseContent(ctxt);
13784    else
13785#endif
13786	xmlParseContent(ctxt);
13787
13788    nsPop(ctxt, nsnr);
13789    if ((RAW == '<') && (NXT(1) == '/')) {
13790	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13791    } else if (RAW != 0) {
13792	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13793    }
13794    if ((ctxt->node != NULL) && (ctxt->node != node)) {
13795	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13796	ctxt->wellFormed = 0;
13797    }
13798
13799    if (!ctxt->wellFormed) {
13800        if (ctxt->errNo == 0)
13801	    ret = XML_ERR_INTERNAL_ERROR;
13802	else
13803	    ret = (xmlParserErrors)ctxt->errNo;
13804    } else {
13805        ret = XML_ERR_OK;
13806    }
13807
13808    /*
13809     * Return the newly created nodeset after unlinking it from
13810     * the pseudo sibling.
13811     */
13812
13813    cur = fake->next;
13814    fake->next = NULL;
13815    node->last = fake;
13816
13817    if (cur != NULL) {
13818	cur->prev = NULL;
13819    }
13820
13821    *lst = cur;
13822
13823    while (cur != NULL) {
13824	cur->parent = NULL;
13825	cur = cur->next;
13826    }
13827
13828    xmlUnlinkNode(fake);
13829    xmlFreeNode(fake);
13830
13831
13832    if (ret != XML_ERR_OK) {
13833        xmlFreeNodeList(*lst);
13834	*lst = NULL;
13835    }
13836
13837    if (doc->dict != NULL)
13838        ctxt->dict = NULL;
13839    xmlFreeParserCtxt(ctxt);
13840
13841    return(ret);
13842#else /* !SAX2 */
13843    return(XML_ERR_INTERNAL_ERROR);
13844#endif
13845}
13846
13847#ifdef LIBXML_SAX1_ENABLED
13848/**
13849 * xmlParseBalancedChunkMemoryRecover:
13850 * @doc:  the document the chunk pertains to
13851 * @sax:  the SAX handler bloc (possibly NULL)
13852 * @user_data:  The user data returned on SAX callbacks (possibly NULL)
13853 * @depth:  Used for loop detection, use 0
13854 * @string:  the input string in UTF8 or ISO-Latin (zero terminated)
13855 * @lst:  the return value for the set of parsed nodes
13856 * @recover: return nodes even if the data is broken (use 0)
13857 *
13858 *
13859 * Parse a well-balanced chunk of an XML document
13860 * called by the parser
13861 * The allowed sequence for the Well Balanced Chunk is the one defined by
13862 * the content production in the XML grammar:
13863 *
13864 * [43] content ::= (element | CharData | Reference | CDSect | PI | Comment)*
13865 *
13866 * Returns 0 if the chunk is well balanced, -1 in case of args problem and
13867 *    the parser error code otherwise
13868 *
13869 * In case recover is set to 1, the nodelist will not be empty even if
13870 * the parsed chunk is not well balanced, assuming the parsing succeeded to
13871 * some extent.
13872 */
13873int
13874xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax,
13875     void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst,
13876     int recover) {
13877    xmlParserCtxtPtr ctxt;
13878    xmlDocPtr newDoc;
13879    xmlSAXHandlerPtr oldsax = NULL;
13880    xmlNodePtr content, newRoot;
13881    int size;
13882    int ret = 0;
13883
13884    if (depth > 40) {
13885	return(XML_ERR_ENTITY_LOOP);
13886    }
13887
13888
13889    if (lst != NULL)
13890        *lst = NULL;
13891    if (string == NULL)
13892        return(-1);
13893
13894    size = xmlStrlen(string);
13895
13896    ctxt = xmlCreateMemoryParserCtxt((char *) string, size);
13897    if (ctxt == NULL) return(-1);
13898    ctxt->userData = ctxt;
13899    if (sax != NULL) {
13900	oldsax = ctxt->sax;
13901        ctxt->sax = sax;
13902	if (user_data != NULL)
13903	    ctxt->userData = user_data;
13904    }
13905    newDoc = xmlNewDoc(BAD_CAST "1.0");
13906    if (newDoc == NULL) {
13907	xmlFreeParserCtxt(ctxt);
13908	return(-1);
13909    }
13910    newDoc->properties = XML_DOC_INTERNAL;
13911    if ((doc != NULL) && (doc->dict != NULL)) {
13912        xmlDictFree(ctxt->dict);
13913	ctxt->dict = doc->dict;
13914	xmlDictReference(ctxt->dict);
13915	ctxt->str_xml = xmlDictLookup(ctxt->dict, BAD_CAST "xml", 3);
13916	ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5);
13917	ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36);
13918	ctxt->dictNames = 1;
13919    } else {
13920	xmlCtxtUseOptionsInternal(ctxt, XML_PARSE_NODICT, NULL);
13921    }
13922    if (doc != NULL) {
13923	newDoc->intSubset = doc->intSubset;
13924	newDoc->extSubset = doc->extSubset;
13925    }
13926    newRoot = xmlNewDocNode(newDoc, NULL, BAD_CAST "pseudoroot", NULL);
13927    if (newRoot == NULL) {
13928	if (sax != NULL)
13929	    ctxt->sax = oldsax;
13930	xmlFreeParserCtxt(ctxt);
13931	newDoc->intSubset = NULL;
13932	newDoc->extSubset = NULL;
13933        xmlFreeDoc(newDoc);
13934	return(-1);
13935    }
13936    xmlAddChild((xmlNodePtr) newDoc, newRoot);
13937    nodePush(ctxt, newRoot);
13938    if (doc == NULL) {
13939	ctxt->myDoc = newDoc;
13940    } else {
13941	ctxt->myDoc = newDoc;
13942	newDoc->children->doc = doc;
13943	/* Ensure that doc has XML spec namespace */
13944	xmlSearchNsByHref(doc, (xmlNodePtr)doc, XML_XML_NAMESPACE);
13945	newDoc->oldNs = doc->oldNs;
13946    }
13947    ctxt->instate = XML_PARSER_CONTENT;
13948    ctxt->depth = depth;
13949
13950    /*
13951     * Doing validity checking on chunk doesn't make sense
13952     */
13953    ctxt->validate = 0;
13954    ctxt->loadsubset = 0;
13955    xmlDetectSAX2(ctxt);
13956
13957    if ( doc != NULL ){
13958        content = doc->children;
13959        doc->children = NULL;
13960        xmlParseContent(ctxt);
13961        doc->children = content;
13962    }
13963    else {
13964        xmlParseContent(ctxt);
13965    }
13966    if ((RAW == '<') && (NXT(1) == '/')) {
13967	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13968    } else if (RAW != 0) {
13969	xmlFatalErr(ctxt, XML_ERR_EXTRA_CONTENT, NULL);
13970    }
13971    if (ctxt->node != newDoc->children) {
13972	xmlFatalErr(ctxt, XML_ERR_NOT_WELL_BALANCED, NULL);
13973    }
13974
13975    if (!ctxt->wellFormed) {
13976        if (ctxt->errNo == 0)
13977	    ret = 1;
13978	else
13979	    ret = ctxt->errNo;
13980    } else {
13981      ret = 0;
13982    }
13983
13984    if ((lst != NULL) && ((ret == 0) || (recover == 1))) {
13985	xmlNodePtr cur;
13986
13987	/*
13988	 * Return the newly created nodeset after unlinking it from
13989	 * they pseudo parent.
13990	 */
13991	cur = newDoc->children->children;
13992	*lst = cur;
13993	while (cur != NULL) {
13994	    xmlSetTreeDoc(cur, doc);
13995	    cur->parent = NULL;
13996	    cur = cur->next;
13997	}
13998	newDoc->children->children = NULL;
13999    }
14000
14001    if (sax != NULL)
14002	ctxt->sax = oldsax;
14003    xmlFreeParserCtxt(ctxt);
14004    newDoc->intSubset = NULL;
14005    newDoc->extSubset = NULL;
14006    newDoc->oldNs = NULL;
14007    xmlFreeDoc(newDoc);
14008
14009    return(ret);
14010}
14011
14012/**
14013 * xmlSAXParseEntity:
14014 * @sax:  the SAX handler block
14015 * @filename:  the filename
14016 *
14017 * parse an XML external entity out of context and build a tree.
14018 * It use the given SAX function block to handle the parsing callback.
14019 * If sax is NULL, fallback to the default DOM tree building routines.
14020 *
14021 * [78] extParsedEnt ::= TextDecl? content
14022 *
14023 * This correspond to a "Well Balanced" chunk
14024 *
14025 * Returns the resulting document tree
14026 */
14027
14028xmlDocPtr
14029xmlSAXParseEntity(xmlSAXHandlerPtr sax, const char *filename) {
14030    xmlDocPtr ret;
14031    xmlParserCtxtPtr ctxt;
14032
14033    ctxt = xmlCreateFileParserCtxt(filename);
14034    if (ctxt == NULL) {
14035	return(NULL);
14036    }
14037    if (sax != NULL) {
14038	if (ctxt->sax != NULL)
14039	    xmlFree(ctxt->sax);
14040        ctxt->sax = sax;
14041        ctxt->userData = NULL;
14042    }
14043
14044    xmlParseExtParsedEnt(ctxt);
14045
14046    if (ctxt->wellFormed)
14047	ret = ctxt->myDoc;
14048    else {
14049        ret = NULL;
14050        xmlFreeDoc(ctxt->myDoc);
14051        ctxt->myDoc = NULL;
14052    }
14053    if (sax != NULL)
14054        ctxt->sax = NULL;
14055    xmlFreeParserCtxt(ctxt);
14056
14057    return(ret);
14058}
14059
14060/**
14061 * xmlParseEntity:
14062 * @filename:  the filename
14063 *
14064 * parse an XML external entity out of context and build a tree.
14065 *
14066 * [78] extParsedEnt ::= TextDecl? content
14067 *
14068 * This correspond to a "Well Balanced" chunk
14069 *
14070 * Returns the resulting document tree
14071 */
14072
14073xmlDocPtr
14074xmlParseEntity(const char *filename) {
14075    return(xmlSAXParseEntity(NULL, filename));
14076}
14077#endif /* LIBXML_SAX1_ENABLED */
14078
14079/**
14080 * xmlCreateEntityParserCtxtInternal:
14081 * @URL:  the entity URL
14082 * @ID:  the entity PUBLIC ID
14083 * @base:  a possible base for the target URI
14084 * @pctx:  parser context used to set options on new context
14085 *
14086 * Create a parser context for an external entity
14087 * Automatic support for ZLIB/Compress compressed document is provided
14088 * by default if found at compile-time.
14089 *
14090 * Returns the new parser context or NULL
14091 */
14092static xmlParserCtxtPtr
14093xmlCreateEntityParserCtxtInternal(const xmlChar *URL, const xmlChar *ID,
14094	                  const xmlChar *base, xmlParserCtxtPtr pctx) {
14095    xmlParserCtxtPtr ctxt;
14096    xmlParserInputPtr inputStream;
14097    char *directory = NULL;
14098    xmlChar *uri;
14099
14100    ctxt = xmlNewParserCtxt();
14101    if (ctxt == NULL) {
14102	return(NULL);
14103    }
14104
14105    if (pctx != NULL) {
14106        ctxt->options = pctx->options;
14107        ctxt->_private = pctx->_private;
14108    }
14109
14110    uri = xmlBuildURI(URL, base);
14111
14112    if (uri == NULL) {
14113	inputStream = xmlLoadExternalEntity((char *)URL, (char *)ID, ctxt);
14114	if (inputStream == NULL) {
14115	    xmlFreeParserCtxt(ctxt);
14116	    return(NULL);
14117	}
14118
14119	inputPush(ctxt, inputStream);
14120
14121	if ((ctxt->directory == NULL) && (directory == NULL))
14122	    directory = xmlParserGetDirectory((char *)URL);
14123	if ((ctxt->directory == NULL) && (directory != NULL))
14124	    ctxt->directory = directory;
14125    } else {
14126	inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
14127	if (inputStream == NULL) {
14128	    xmlFree(uri);
14129	    xmlFreeParserCtxt(ctxt);
14130	    return(NULL);
14131	}
14132
14133	inputPush(ctxt, inputStream);
14134
14135	if ((ctxt->directory == NULL) && (directory == NULL))
14136	    directory = xmlParserGetDirectory((char *)uri);
14137	if ((ctxt->directory == NULL) && (directory != NULL))
14138	    ctxt->directory = directory;
14139	xmlFree(uri);
14140    }
14141    return(ctxt);
14142}
14143
14144/**
14145 * xmlCreateEntityParserCtxt:
14146 * @URL:  the entity URL
14147 * @ID:  the entity PUBLIC ID
14148 * @base:  a possible base for the target URI
14149 *
14150 * Create a parser context for an external entity
14151 * Automatic support for ZLIB/Compress compressed document is provided
14152 * by default if found at compile-time.
14153 *
14154 * Returns the new parser context or NULL
14155 */
14156xmlParserCtxtPtr
14157xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID,
14158	                  const xmlChar *base) {
14159    return xmlCreateEntityParserCtxtInternal(URL, ID, base, NULL);
14160
14161}
14162
14163/************************************************************************
14164 *									*
14165 *		Front ends when parsing from a file			*
14166 *									*
14167 ************************************************************************/
14168
14169/**
14170 * xmlCreateURLParserCtxt:
14171 * @filename:  the filename or URL
14172 * @options:  a combination of xmlParserOption
14173 *
14174 * Create a parser context for a file or URL content.
14175 * Automatic support for ZLIB/Compress compressed document is provided
14176 * by default if found at compile-time and for file accesses
14177 *
14178 * Returns the new parser context or NULL
14179 */
14180xmlParserCtxtPtr
14181xmlCreateURLParserCtxt(const char *filename, int options)
14182{
14183    xmlParserCtxtPtr ctxt;
14184    xmlParserInputPtr inputStream;
14185    char *directory = NULL;
14186
14187    ctxt = xmlNewParserCtxt();
14188    if (ctxt == NULL) {
14189	xmlErrMemory(NULL, "cannot allocate parser context");
14190	return(NULL);
14191    }
14192
14193    if (options)
14194	xmlCtxtUseOptionsInternal(ctxt, options, NULL);
14195    ctxt->linenumbers = 1;
14196
14197    inputStream = xmlLoadExternalEntity(filename, NULL, ctxt);
14198    if (inputStream == NULL) {
14199	xmlFreeParserCtxt(ctxt);
14200	return(NULL);
14201    }
14202
14203    inputPush(ctxt, inputStream);
14204    if ((ctxt->directory == NULL) && (directory == NULL))
14205        directory = xmlParserGetDirectory(filename);
14206    if ((ctxt->directory == NULL) && (directory != NULL))
14207        ctxt->directory = directory;
14208
14209    return(ctxt);
14210}
14211
14212/**
14213 * xmlCreateFileParserCtxt:
14214 * @filename:  the filename
14215 *
14216 * Create a parser context for a file content.
14217 * Automatic support for ZLIB/Compress compressed document is provided
14218 * by default if found at compile-time.
14219 *
14220 * Returns the new parser context or NULL
14221 */
14222xmlParserCtxtPtr
14223xmlCreateFileParserCtxt(const char *filename)
14224{
14225    return(xmlCreateURLParserCtxt(filename, 0));
14226}
14227
14228#ifdef LIBXML_SAX1_ENABLED
14229/**
14230 * xmlSAXParseFileWithData:
14231 * @sax:  the SAX handler block
14232 * @filename:  the filename
14233 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14234 *             documents
14235 * @data:  the userdata
14236 *
14237 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14238 * compressed document is provided by default if found at compile-time.
14239 * It use the given SAX function block to handle the parsing callback.
14240 * If sax is NULL, fallback to the default DOM tree building routines.
14241 *
14242 * User data (void *) is stored within the parser context in the
14243 * context's _private member, so it is available nearly everywhere in libxml
14244 *
14245 * Returns the resulting document tree
14246 */
14247
14248xmlDocPtr
14249xmlSAXParseFileWithData(xmlSAXHandlerPtr sax, const char *filename,
14250                        int recovery, void *data) {
14251    xmlDocPtr ret;
14252    xmlParserCtxtPtr ctxt;
14253
14254    xmlInitParser();
14255
14256    ctxt = xmlCreateFileParserCtxt(filename);
14257    if (ctxt == NULL) {
14258	return(NULL);
14259    }
14260    if (sax != NULL) {
14261	if (ctxt->sax != NULL)
14262	    xmlFree(ctxt->sax);
14263        ctxt->sax = sax;
14264    }
14265    xmlDetectSAX2(ctxt);
14266    if (data!=NULL) {
14267	ctxt->_private = data;
14268    }
14269
14270    if (ctxt->directory == NULL)
14271        ctxt->directory = xmlParserGetDirectory(filename);
14272
14273    ctxt->recovery = recovery;
14274
14275    xmlParseDocument(ctxt);
14276
14277    if ((ctxt->wellFormed) || recovery) {
14278        ret = ctxt->myDoc;
14279	if (ret != NULL) {
14280	    if (ctxt->input->buf->compressed > 0)
14281		ret->compression = 9;
14282	    else
14283		ret->compression = ctxt->input->buf->compressed;
14284	}
14285    }
14286    else {
14287       ret = NULL;
14288       xmlFreeDoc(ctxt->myDoc);
14289       ctxt->myDoc = NULL;
14290    }
14291    if (sax != NULL)
14292        ctxt->sax = NULL;
14293    xmlFreeParserCtxt(ctxt);
14294
14295    return(ret);
14296}
14297
14298/**
14299 * xmlSAXParseFile:
14300 * @sax:  the SAX handler block
14301 * @filename:  the filename
14302 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14303 *             documents
14304 *
14305 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14306 * compressed document is provided by default if found at compile-time.
14307 * It use the given SAX function block to handle the parsing callback.
14308 * If sax is NULL, fallback to the default DOM tree building routines.
14309 *
14310 * Returns the resulting document tree
14311 */
14312
14313xmlDocPtr
14314xmlSAXParseFile(xmlSAXHandlerPtr sax, const char *filename,
14315                          int recovery) {
14316    return(xmlSAXParseFileWithData(sax,filename,recovery,NULL));
14317}
14318
14319/**
14320 * xmlRecoverDoc:
14321 * @cur:  a pointer to an array of xmlChar
14322 *
14323 * parse an XML in-memory document and build a tree.
14324 * In the case the document is not Well Formed, a attempt to build a
14325 * tree is tried anyway
14326 *
14327 * Returns the resulting document tree or NULL in case of failure
14328 */
14329
14330xmlDocPtr
14331xmlRecoverDoc(const xmlChar *cur) {
14332    return(xmlSAXParseDoc(NULL, cur, 1));
14333}
14334
14335/**
14336 * xmlParseFile:
14337 * @filename:  the filename
14338 *
14339 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14340 * compressed document is provided by default if found at compile-time.
14341 *
14342 * Returns the resulting document tree if the file was wellformed,
14343 * NULL otherwise.
14344 */
14345
14346xmlDocPtr
14347xmlParseFile(const char *filename) {
14348    return(xmlSAXParseFile(NULL, filename, 0));
14349}
14350
14351/**
14352 * xmlRecoverFile:
14353 * @filename:  the filename
14354 *
14355 * parse an XML file and build a tree. Automatic support for ZLIB/Compress
14356 * compressed document is provided by default if found at compile-time.
14357 * In the case the document is not Well Formed, it attempts to build
14358 * a tree anyway
14359 *
14360 * Returns the resulting document tree or NULL in case of failure
14361 */
14362
14363xmlDocPtr
14364xmlRecoverFile(const char *filename) {
14365    return(xmlSAXParseFile(NULL, filename, 1));
14366}
14367
14368
14369/**
14370 * xmlSetupParserForBuffer:
14371 * @ctxt:  an XML parser context
14372 * @buffer:  a xmlChar * buffer
14373 * @filename:  a file name
14374 *
14375 * Setup the parser context to parse a new buffer; Clears any prior
14376 * contents from the parser context. The buffer parameter must not be
14377 * NULL, but the filename parameter can be
14378 */
14379void
14380xmlSetupParserForBuffer(xmlParserCtxtPtr ctxt, const xmlChar* buffer,
14381                             const char* filename)
14382{
14383    xmlParserInputPtr input;
14384
14385    if ((ctxt == NULL) || (buffer == NULL))
14386        return;
14387
14388    input = xmlNewInputStream(ctxt);
14389    if (input == NULL) {
14390        xmlErrMemory(NULL, "parsing new buffer: out of memory\n");
14391        xmlClearParserCtxt(ctxt);
14392        return;
14393    }
14394
14395    xmlClearParserCtxt(ctxt);
14396    if (filename != NULL)
14397        input->filename = (char *) xmlCanonicPath((const xmlChar *)filename);
14398    input->base = buffer;
14399    input->cur = buffer;
14400    input->end = &buffer[xmlStrlen(buffer)];
14401    inputPush(ctxt, input);
14402}
14403
14404/**
14405 * xmlSAXUserParseFile:
14406 * @sax:  a SAX handler
14407 * @user_data:  The user data returned on SAX callbacks
14408 * @filename:  a file name
14409 *
14410 * parse an XML file and call the given SAX handler routines.
14411 * Automatic support for ZLIB/Compress compressed document is provided
14412 *
14413 * Returns 0 in case of success or a error number otherwise
14414 */
14415int
14416xmlSAXUserParseFile(xmlSAXHandlerPtr sax, void *user_data,
14417                    const char *filename) {
14418    int ret = 0;
14419    xmlParserCtxtPtr ctxt;
14420
14421    ctxt = xmlCreateFileParserCtxt(filename);
14422    if (ctxt == NULL) return -1;
14423    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
14424	xmlFree(ctxt->sax);
14425    ctxt->sax = sax;
14426    xmlDetectSAX2(ctxt);
14427
14428    if (user_data != NULL)
14429	ctxt->userData = user_data;
14430
14431    xmlParseDocument(ctxt);
14432
14433    if (ctxt->wellFormed)
14434	ret = 0;
14435    else {
14436        if (ctxt->errNo != 0)
14437	    ret = ctxt->errNo;
14438	else
14439	    ret = -1;
14440    }
14441    if (sax != NULL)
14442	ctxt->sax = NULL;
14443    if (ctxt->myDoc != NULL) {
14444        xmlFreeDoc(ctxt->myDoc);
14445	ctxt->myDoc = NULL;
14446    }
14447    xmlFreeParserCtxt(ctxt);
14448
14449    return ret;
14450}
14451#endif /* LIBXML_SAX1_ENABLED */
14452
14453/************************************************************************
14454 *									*
14455 *		Front ends when parsing from memory			*
14456 *									*
14457 ************************************************************************/
14458
14459/**
14460 * xmlCreateMemoryParserCtxt:
14461 * @buffer:  a pointer to a char array
14462 * @size:  the size of the array
14463 *
14464 * Create a parser context for an XML in-memory document.
14465 *
14466 * Returns the new parser context or NULL
14467 */
14468xmlParserCtxtPtr
14469xmlCreateMemoryParserCtxt(const char *buffer, int size) {
14470    xmlParserCtxtPtr ctxt;
14471    xmlParserInputPtr input;
14472    xmlParserInputBufferPtr buf;
14473
14474    if (buffer == NULL)
14475	return(NULL);
14476    if (size <= 0)
14477	return(NULL);
14478
14479    ctxt = xmlNewParserCtxt();
14480    if (ctxt == NULL)
14481	return(NULL);
14482
14483    /* TODO: xmlParserInputBufferCreateStatic, requires some serious changes */
14484    buf = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
14485    if (buf == NULL) {
14486	xmlFreeParserCtxt(ctxt);
14487	return(NULL);
14488    }
14489
14490    input = xmlNewInputStream(ctxt);
14491    if (input == NULL) {
14492	xmlFreeParserInputBuffer(buf);
14493	xmlFreeParserCtxt(ctxt);
14494	return(NULL);
14495    }
14496
14497    input->filename = NULL;
14498    input->buf = buf;
14499    xmlBufResetInput(input->buf->buffer, input);
14500
14501    inputPush(ctxt, input);
14502    return(ctxt);
14503}
14504
14505#ifdef LIBXML_SAX1_ENABLED
14506/**
14507 * xmlSAXParseMemoryWithData:
14508 * @sax:  the SAX handler block
14509 * @buffer:  an pointer to a char array
14510 * @size:  the size of the array
14511 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14512 *             documents
14513 * @data:  the userdata
14514 *
14515 * parse an XML in-memory block and use the given SAX function block
14516 * to handle the parsing callback. If sax is NULL, fallback to the default
14517 * DOM tree building routines.
14518 *
14519 * User data (void *) is stored within the parser context in the
14520 * context's _private member, so it is available nearly everywhere in libxml
14521 *
14522 * Returns the resulting document tree
14523 */
14524
14525xmlDocPtr
14526xmlSAXParseMemoryWithData(xmlSAXHandlerPtr sax, const char *buffer,
14527	          int size, int recovery, void *data) {
14528    xmlDocPtr ret;
14529    xmlParserCtxtPtr ctxt;
14530
14531    xmlInitParser();
14532
14533    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14534    if (ctxt == NULL) return(NULL);
14535    if (sax != NULL) {
14536	if (ctxt->sax != NULL)
14537	    xmlFree(ctxt->sax);
14538        ctxt->sax = sax;
14539    }
14540    xmlDetectSAX2(ctxt);
14541    if (data!=NULL) {
14542	ctxt->_private=data;
14543    }
14544
14545    ctxt->recovery = recovery;
14546
14547    xmlParseDocument(ctxt);
14548
14549    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14550    else {
14551       ret = NULL;
14552       xmlFreeDoc(ctxt->myDoc);
14553       ctxt->myDoc = NULL;
14554    }
14555    if (sax != NULL)
14556	ctxt->sax = NULL;
14557    xmlFreeParserCtxt(ctxt);
14558
14559    return(ret);
14560}
14561
14562/**
14563 * xmlSAXParseMemory:
14564 * @sax:  the SAX handler block
14565 * @buffer:  an pointer to a char array
14566 * @size:  the size of the array
14567 * @recovery:  work in recovery mode, i.e. tries to read not Well Formed
14568 *             documents
14569 *
14570 * parse an XML in-memory block and use the given SAX function block
14571 * to handle the parsing callback. If sax is NULL, fallback to the default
14572 * DOM tree building routines.
14573 *
14574 * Returns the resulting document tree
14575 */
14576xmlDocPtr
14577xmlSAXParseMemory(xmlSAXHandlerPtr sax, const char *buffer,
14578	          int size, int recovery) {
14579    return xmlSAXParseMemoryWithData(sax, buffer, size, recovery, NULL);
14580}
14581
14582/**
14583 * xmlParseMemory:
14584 * @buffer:  an pointer to a char array
14585 * @size:  the size of the array
14586 *
14587 * parse an XML in-memory block and build a tree.
14588 *
14589 * Returns the resulting document tree
14590 */
14591
14592xmlDocPtr xmlParseMemory(const char *buffer, int size) {
14593   return(xmlSAXParseMemory(NULL, buffer, size, 0));
14594}
14595
14596/**
14597 * xmlRecoverMemory:
14598 * @buffer:  an pointer to a char array
14599 * @size:  the size of the array
14600 *
14601 * parse an XML in-memory block and build a tree.
14602 * In the case the document is not Well Formed, an attempt to
14603 * build a tree is tried anyway
14604 *
14605 * Returns the resulting document tree or NULL in case of error
14606 */
14607
14608xmlDocPtr xmlRecoverMemory(const char *buffer, int size) {
14609   return(xmlSAXParseMemory(NULL, buffer, size, 1));
14610}
14611
14612/**
14613 * xmlSAXUserParseMemory:
14614 * @sax:  a SAX handler
14615 * @user_data:  The user data returned on SAX callbacks
14616 * @buffer:  an in-memory XML document input
14617 * @size:  the length of the XML document in bytes
14618 *
14619 * A better SAX parsing routine.
14620 * parse an XML in-memory buffer and call the given SAX handler routines.
14621 *
14622 * Returns 0 in case of success or a error number otherwise
14623 */
14624int xmlSAXUserParseMemory(xmlSAXHandlerPtr sax, void *user_data,
14625			  const char *buffer, int size) {
14626    int ret = 0;
14627    xmlParserCtxtPtr ctxt;
14628
14629    xmlInitParser();
14630
14631    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
14632    if (ctxt == NULL) return -1;
14633    if (ctxt->sax != (xmlSAXHandlerPtr) &xmlDefaultSAXHandler)
14634        xmlFree(ctxt->sax);
14635    ctxt->sax = sax;
14636    xmlDetectSAX2(ctxt);
14637
14638    if (user_data != NULL)
14639	ctxt->userData = user_data;
14640
14641    xmlParseDocument(ctxt);
14642
14643    if (ctxt->wellFormed)
14644	ret = 0;
14645    else {
14646        if (ctxt->errNo != 0)
14647	    ret = ctxt->errNo;
14648	else
14649	    ret = -1;
14650    }
14651    if (sax != NULL)
14652        ctxt->sax = NULL;
14653    if (ctxt->myDoc != NULL) {
14654        xmlFreeDoc(ctxt->myDoc);
14655	ctxt->myDoc = NULL;
14656    }
14657    xmlFreeParserCtxt(ctxt);
14658
14659    return ret;
14660}
14661#endif /* LIBXML_SAX1_ENABLED */
14662
14663/**
14664 * xmlCreateDocParserCtxt:
14665 * @cur:  a pointer to an array of xmlChar
14666 *
14667 * Creates a parser context for an XML in-memory document.
14668 *
14669 * Returns the new parser context or NULL
14670 */
14671xmlParserCtxtPtr
14672xmlCreateDocParserCtxt(const xmlChar *cur) {
14673    int len;
14674
14675    if (cur == NULL)
14676	return(NULL);
14677    len = xmlStrlen(cur);
14678    return(xmlCreateMemoryParserCtxt((const char *)cur, len));
14679}
14680
14681#ifdef LIBXML_SAX1_ENABLED
14682/**
14683 * xmlSAXParseDoc:
14684 * @sax:  the SAX handler block
14685 * @cur:  a pointer to an array of xmlChar
14686 * @recovery:  work in recovery mode, i.e. tries to read no Well Formed
14687 *             documents
14688 *
14689 * parse an XML in-memory document and build a tree.
14690 * It use the given SAX function block to handle the parsing callback.
14691 * If sax is NULL, fallback to the default DOM tree building routines.
14692 *
14693 * Returns the resulting document tree
14694 */
14695
14696xmlDocPtr
14697xmlSAXParseDoc(xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery) {
14698    xmlDocPtr ret;
14699    xmlParserCtxtPtr ctxt;
14700    xmlSAXHandlerPtr oldsax = NULL;
14701
14702    if (cur == NULL) return(NULL);
14703
14704
14705    ctxt = xmlCreateDocParserCtxt(cur);
14706    if (ctxt == NULL) return(NULL);
14707    if (sax != NULL) {
14708        oldsax = ctxt->sax;
14709        ctxt->sax = sax;
14710        ctxt->userData = NULL;
14711    }
14712    xmlDetectSAX2(ctxt);
14713
14714    xmlParseDocument(ctxt);
14715    if ((ctxt->wellFormed) || recovery) ret = ctxt->myDoc;
14716    else {
14717       ret = NULL;
14718       xmlFreeDoc(ctxt->myDoc);
14719       ctxt->myDoc = NULL;
14720    }
14721    if (sax != NULL)
14722	ctxt->sax = oldsax;
14723    xmlFreeParserCtxt(ctxt);
14724
14725    return(ret);
14726}
14727
14728/**
14729 * xmlParseDoc:
14730 * @cur:  a pointer to an array of xmlChar
14731 *
14732 * parse an XML in-memory document and build a tree.
14733 *
14734 * Returns the resulting document tree
14735 */
14736
14737xmlDocPtr
14738xmlParseDoc(const xmlChar *cur) {
14739    return(xmlSAXParseDoc(NULL, cur, 0));
14740}
14741#endif /* LIBXML_SAX1_ENABLED */
14742
14743#ifdef LIBXML_LEGACY_ENABLED
14744/************************************************************************
14745 *									*
14746 *	Specific function to keep track of entities references		*
14747 *	and used by the XSLT debugger					*
14748 *									*
14749 ************************************************************************/
14750
14751static xmlEntityReferenceFunc xmlEntityRefFunc = NULL;
14752
14753/**
14754 * xmlAddEntityReference:
14755 * @ent : A valid entity
14756 * @firstNode : A valid first node for children of entity
14757 * @lastNode : A valid last node of children entity
14758 *
14759 * Notify of a reference to an entity of type XML_EXTERNAL_GENERAL_PARSED_ENTITY
14760 */
14761static void
14762xmlAddEntityReference(xmlEntityPtr ent, xmlNodePtr firstNode,
14763                      xmlNodePtr lastNode)
14764{
14765    if (xmlEntityRefFunc != NULL) {
14766        (*xmlEntityRefFunc) (ent, firstNode, lastNode);
14767    }
14768}
14769
14770
14771/**
14772 * xmlSetEntityReferenceFunc:
14773 * @func: A valid function
14774 *
14775 * Set the function to call call back when a xml reference has been made
14776 */
14777void
14778xmlSetEntityReferenceFunc(xmlEntityReferenceFunc func)
14779{
14780    xmlEntityRefFunc = func;
14781}
14782#endif /* LIBXML_LEGACY_ENABLED */
14783
14784/************************************************************************
14785 *									*
14786 *				Miscellaneous				*
14787 *									*
14788 ************************************************************************/
14789
14790#ifdef LIBXML_XPATH_ENABLED
14791#include <libxml/xpath.h>
14792#endif
14793
14794extern void XMLCDECL xmlGenericErrorDefaultFunc(void *ctx, const char *msg, ...);
14795static int xmlParserInitialized = 0;
14796
14797/**
14798 * xmlInitParser:
14799 *
14800 * Initialization function for the XML parser.
14801 * This is not reentrant. Call once before processing in case of
14802 * use in multithreaded programs.
14803 */
14804
14805void
14806xmlInitParser(void) {
14807    if (xmlParserInitialized != 0)
14808	return;
14809
14810#ifdef LIBXML_THREAD_ENABLED
14811    __xmlGlobalInitMutexLock();
14812    if (xmlParserInitialized == 0) {
14813#endif
14814	xmlInitThreads();
14815	xmlInitGlobals();
14816	if ((xmlGenericError == xmlGenericErrorDefaultFunc) ||
14817	    (xmlGenericError == NULL))
14818	    initGenericErrorDefaultFunc(NULL);
14819	xmlInitMemory();
14820        xmlInitializeDict();
14821	xmlInitCharEncodingHandlers();
14822	xmlDefaultSAXHandlerInit();
14823	xmlRegisterDefaultInputCallbacks();
14824#ifdef LIBXML_OUTPUT_ENABLED
14825	xmlRegisterDefaultOutputCallbacks();
14826#endif /* LIBXML_OUTPUT_ENABLED */
14827#ifdef LIBXML_HTML_ENABLED
14828	htmlInitAutoClose();
14829	htmlDefaultSAXHandlerInit();
14830#endif
14831#ifdef LIBXML_XPATH_ENABLED
14832	xmlXPathInit();
14833#endif
14834	xmlParserInitialized = 1;
14835#ifdef LIBXML_THREAD_ENABLED
14836    }
14837    __xmlGlobalInitMutexUnlock();
14838#endif
14839}
14840
14841/**
14842 * xmlCleanupParser:
14843 *
14844 * This function name is somewhat misleading. It does not clean up
14845 * parser state, it cleans up memory allocated by the library itself.
14846 * It is a cleanup function for the XML library. It tries to reclaim all
14847 * related global memory allocated for the library processing.
14848 * It doesn't deallocate any document related memory. One should
14849 * call xmlCleanupParser() only when the process has finished using
14850 * the library and all XML/HTML documents built with it.
14851 * See also xmlInitParser() which has the opposite function of preparing
14852 * the library for operations.
14853 *
14854 * WARNING: if your application is multithreaded or has plugin support
14855 *          calling this may crash the application if another thread or
14856 *          a plugin is still using libxml2. It's sometimes very hard to
14857 *          guess if libxml2 is in use in the application, some libraries
14858 *          or plugins may use it without notice. In case of doubt abstain
14859 *          from calling this function or do it just before calling exit()
14860 *          to avoid leak reports from valgrind !
14861 */
14862
14863void
14864xmlCleanupParser(void) {
14865    if (!xmlParserInitialized)
14866	return;
14867
14868    xmlCleanupCharEncodingHandlers();
14869#ifdef LIBXML_CATALOG_ENABLED
14870    xmlCatalogCleanup();
14871#endif
14872    xmlDictCleanup();
14873    xmlCleanupInputCallbacks();
14874#ifdef LIBXML_OUTPUT_ENABLED
14875    xmlCleanupOutputCallbacks();
14876#endif
14877#ifdef LIBXML_SCHEMAS_ENABLED
14878    xmlSchemaCleanupTypes();
14879    xmlRelaxNGCleanupTypes();
14880#endif
14881    xmlResetLastError();
14882    xmlCleanupGlobals();
14883    xmlCleanupThreads(); /* must be last if called not from the main thread */
14884    xmlCleanupMemory();
14885    xmlParserInitialized = 0;
14886}
14887
14888/************************************************************************
14889 *									*
14890 *	New set (2.6.0) of simpler and more flexible APIs		*
14891 *									*
14892 ************************************************************************/
14893
14894/**
14895 * DICT_FREE:
14896 * @str:  a string
14897 *
14898 * Free a string if it is not owned by the "dict" dictionnary in the
14899 * current scope
14900 */
14901#define DICT_FREE(str)						\
14902	if ((str) && ((!dict) ||				\
14903	    (xmlDictOwns(dict, (const xmlChar *)(str)) == 0)))	\
14904	    xmlFree((char *)(str));
14905
14906/**
14907 * xmlCtxtReset:
14908 * @ctxt: an XML parser context
14909 *
14910 * Reset a parser context
14911 */
14912void
14913xmlCtxtReset(xmlParserCtxtPtr ctxt)
14914{
14915    xmlParserInputPtr input;
14916    xmlDictPtr dict;
14917
14918    if (ctxt == NULL)
14919        return;
14920
14921    dict = ctxt->dict;
14922
14923    while ((input = inputPop(ctxt)) != NULL) { /* Non consuming */
14924        xmlFreeInputStream(input);
14925    }
14926    ctxt->inputNr = 0;
14927    ctxt->input = NULL;
14928
14929    ctxt->spaceNr = 0;
14930    if (ctxt->spaceTab != NULL) {
14931	ctxt->spaceTab[0] = -1;
14932	ctxt->space = &ctxt->spaceTab[0];
14933    } else {
14934        ctxt->space = NULL;
14935    }
14936
14937
14938    ctxt->nodeNr = 0;
14939    ctxt->node = NULL;
14940
14941    ctxt->nameNr = 0;
14942    ctxt->name = NULL;
14943
14944    DICT_FREE(ctxt->version);
14945    ctxt->version = NULL;
14946    DICT_FREE(ctxt->encoding);
14947    ctxt->encoding = NULL;
14948    DICT_FREE(ctxt->directory);
14949    ctxt->directory = NULL;
14950    DICT_FREE(ctxt->extSubURI);
14951    ctxt->extSubURI = NULL;
14952    DICT_FREE(ctxt->extSubSystem);
14953    ctxt->extSubSystem = NULL;
14954    if (ctxt->myDoc != NULL)
14955        xmlFreeDoc(ctxt->myDoc);
14956    ctxt->myDoc = NULL;
14957
14958    ctxt->standalone = -1;
14959    ctxt->hasExternalSubset = 0;
14960    ctxt->hasPErefs = 0;
14961    ctxt->html = 0;
14962    ctxt->external = 0;
14963    ctxt->instate = XML_PARSER_START;
14964    ctxt->token = 0;
14965
14966    ctxt->wellFormed = 1;
14967    ctxt->nsWellFormed = 1;
14968    ctxt->disableSAX = 0;
14969    ctxt->valid = 1;
14970#if 0
14971    ctxt->vctxt.userData = ctxt;
14972    ctxt->vctxt.error = xmlParserValidityError;
14973    ctxt->vctxt.warning = xmlParserValidityWarning;
14974#endif
14975    ctxt->record_info = 0;
14976    ctxt->nbChars = 0;
14977    ctxt->checkIndex = 0;
14978    ctxt->inSubset = 0;
14979    ctxt->errNo = XML_ERR_OK;
14980    ctxt->depth = 0;
14981    ctxt->charset = XML_CHAR_ENCODING_UTF8;
14982    ctxt->catalogs = NULL;
14983    ctxt->nbentities = 0;
14984    ctxt->sizeentities = 0;
14985    ctxt->sizeentcopy = 0;
14986    xmlInitNodeInfoSeq(&ctxt->node_seq);
14987
14988    if (ctxt->attsDefault != NULL) {
14989        xmlHashFree(ctxt->attsDefault, (xmlHashDeallocator) xmlFree);
14990        ctxt->attsDefault = NULL;
14991    }
14992    if (ctxt->attsSpecial != NULL) {
14993        xmlHashFree(ctxt->attsSpecial, NULL);
14994        ctxt->attsSpecial = NULL;
14995    }
14996
14997#ifdef LIBXML_CATALOG_ENABLED
14998    if (ctxt->catalogs != NULL)
14999	xmlCatalogFreeLocal(ctxt->catalogs);
15000#endif
15001    if (ctxt->lastError.code != XML_ERR_OK)
15002        xmlResetError(&ctxt->lastError);
15003}
15004
15005/**
15006 * xmlCtxtResetPush:
15007 * @ctxt: an XML parser context
15008 * @chunk:  a pointer to an array of chars
15009 * @size:  number of chars in the array
15010 * @filename:  an optional file name or URI
15011 * @encoding:  the document encoding, or NULL
15012 *
15013 * Reset a push parser context
15014 *
15015 * Returns 0 in case of success and 1 in case of error
15016 */
15017int
15018xmlCtxtResetPush(xmlParserCtxtPtr ctxt, const char *chunk,
15019                 int size, const char *filename, const char *encoding)
15020{
15021    xmlParserInputPtr inputStream;
15022    xmlParserInputBufferPtr buf;
15023    xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
15024
15025    if (ctxt == NULL)
15026        return(1);
15027
15028    if ((encoding == NULL) && (chunk != NULL) && (size >= 4))
15029        enc = xmlDetectCharEncoding((const xmlChar *) chunk, size);
15030
15031    buf = xmlAllocParserInputBuffer(enc);
15032    if (buf == NULL)
15033        return(1);
15034
15035    if (ctxt == NULL) {
15036        xmlFreeParserInputBuffer(buf);
15037        return(1);
15038    }
15039
15040    xmlCtxtReset(ctxt);
15041
15042    if (ctxt->pushTab == NULL) {
15043        ctxt->pushTab = (void **) xmlMalloc(ctxt->nameMax * 3 *
15044	                                    sizeof(xmlChar *));
15045        if (ctxt->pushTab == NULL) {
15046	    xmlErrMemory(ctxt, NULL);
15047            xmlFreeParserInputBuffer(buf);
15048            return(1);
15049        }
15050    }
15051
15052    if (filename == NULL) {
15053        ctxt->directory = NULL;
15054    } else {
15055        ctxt->directory = xmlParserGetDirectory(filename);
15056    }
15057
15058    inputStream = xmlNewInputStream(ctxt);
15059    if (inputStream == NULL) {
15060        xmlFreeParserInputBuffer(buf);
15061        return(1);
15062    }
15063
15064    if (filename == NULL)
15065        inputStream->filename = NULL;
15066    else
15067        inputStream->filename = (char *)
15068            xmlCanonicPath((const xmlChar *) filename);
15069    inputStream->buf = buf;
15070    xmlBufResetInput(buf->buffer, inputStream);
15071
15072    inputPush(ctxt, inputStream);
15073
15074    if ((size > 0) && (chunk != NULL) && (ctxt->input != NULL) &&
15075        (ctxt->input->buf != NULL)) {
15076	size_t base = xmlBufGetInputBase(ctxt->input->buf->buffer, ctxt->input);
15077        size_t cur = ctxt->input->cur - ctxt->input->base;
15078
15079        xmlParserInputBufferPush(ctxt->input->buf, size, chunk);
15080
15081        xmlBufSetInputBaseCur(ctxt->input->buf->buffer, ctxt->input, base, cur);
15082#ifdef DEBUG_PUSH
15083        xmlGenericError(xmlGenericErrorContext, "PP: pushed %d\n", size);
15084#endif
15085    }
15086
15087    if (encoding != NULL) {
15088        xmlCharEncodingHandlerPtr hdlr;
15089
15090        if (ctxt->encoding != NULL)
15091	    xmlFree((xmlChar *) ctxt->encoding);
15092        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
15093
15094        hdlr = xmlFindCharEncodingHandler(encoding);
15095        if (hdlr != NULL) {
15096            xmlSwitchToEncoding(ctxt, hdlr);
15097	} else {
15098	    xmlFatalErrMsgStr(ctxt, XML_ERR_UNSUPPORTED_ENCODING,
15099			      "Unsupported encoding %s\n", BAD_CAST encoding);
15100        }
15101    } else if (enc != XML_CHAR_ENCODING_NONE) {
15102        xmlSwitchEncoding(ctxt, enc);
15103    }
15104
15105    return(0);
15106}
15107
15108
15109/**
15110 * xmlCtxtUseOptionsInternal:
15111 * @ctxt: an XML parser context
15112 * @options:  a combination of xmlParserOption
15113 * @encoding:  the user provided encoding to use
15114 *
15115 * Applies the options to the parser context
15116 *
15117 * Returns 0 in case of success, the set of unknown or unimplemented options
15118 *         in case of error.
15119 */
15120static int
15121xmlCtxtUseOptionsInternal(xmlParserCtxtPtr ctxt, int options, const char *encoding)
15122{
15123    if (ctxt == NULL)
15124        return(-1);
15125    if (encoding != NULL) {
15126        if (ctxt->encoding != NULL)
15127	    xmlFree((xmlChar *) ctxt->encoding);
15128        ctxt->encoding = xmlStrdup((const xmlChar *) encoding);
15129    }
15130    if (options & XML_PARSE_RECOVER) {
15131        ctxt->recovery = 1;
15132        options -= XML_PARSE_RECOVER;
15133	ctxt->options |= XML_PARSE_RECOVER;
15134    } else
15135        ctxt->recovery = 0;
15136    if (options & XML_PARSE_DTDLOAD) {
15137        ctxt->loadsubset = XML_DETECT_IDS;
15138        options -= XML_PARSE_DTDLOAD;
15139	ctxt->options |= XML_PARSE_DTDLOAD;
15140    } else
15141        ctxt->loadsubset = 0;
15142    if (options & XML_PARSE_DTDATTR) {
15143        ctxt->loadsubset |= XML_COMPLETE_ATTRS;
15144        options -= XML_PARSE_DTDATTR;
15145	ctxt->options |= XML_PARSE_DTDATTR;
15146    }
15147    if (options & XML_PARSE_NOENT) {
15148        ctxt->replaceEntities = 1;
15149        /* ctxt->loadsubset |= XML_DETECT_IDS; */
15150        options -= XML_PARSE_NOENT;
15151	ctxt->options |= XML_PARSE_NOENT;
15152    } else
15153        ctxt->replaceEntities = 0;
15154    if (options & XML_PARSE_PEDANTIC) {
15155        ctxt->pedantic = 1;
15156        options -= XML_PARSE_PEDANTIC;
15157	ctxt->options |= XML_PARSE_PEDANTIC;
15158    } else
15159        ctxt->pedantic = 0;
15160    if (options & XML_PARSE_NOBLANKS) {
15161        ctxt->keepBlanks = 0;
15162        ctxt->sax->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
15163        options -= XML_PARSE_NOBLANKS;
15164	ctxt->options |= XML_PARSE_NOBLANKS;
15165    } else
15166        ctxt->keepBlanks = 1;
15167    if (options & XML_PARSE_DTDVALID) {
15168        ctxt->validate = 1;
15169        if (options & XML_PARSE_NOWARNING)
15170            ctxt->vctxt.warning = NULL;
15171        if (options & XML_PARSE_NOERROR)
15172            ctxt->vctxt.error = NULL;
15173        options -= XML_PARSE_DTDVALID;
15174	ctxt->options |= XML_PARSE_DTDVALID;
15175    } else
15176        ctxt->validate = 0;
15177    if (options & XML_PARSE_NOWARNING) {
15178        ctxt->sax->warning = NULL;
15179        options -= XML_PARSE_NOWARNING;
15180    }
15181    if (options & XML_PARSE_NOERROR) {
15182        ctxt->sax->error = NULL;
15183        ctxt->sax->fatalError = NULL;
15184        options -= XML_PARSE_NOERROR;
15185    }
15186#ifdef LIBXML_SAX1_ENABLED
15187    if (options & XML_PARSE_SAX1) {
15188        ctxt->sax->startElement = xmlSAX2StartElement;
15189        ctxt->sax->endElement = xmlSAX2EndElement;
15190        ctxt->sax->startElementNs = NULL;
15191        ctxt->sax->endElementNs = NULL;
15192        ctxt->sax->initialized = 1;
15193        options -= XML_PARSE_SAX1;
15194	ctxt->options |= XML_PARSE_SAX1;
15195    }
15196#endif /* LIBXML_SAX1_ENABLED */
15197    if (options & XML_PARSE_NODICT) {
15198        ctxt->dictNames = 0;
15199        options -= XML_PARSE_NODICT;
15200	ctxt->options |= XML_PARSE_NODICT;
15201    } else {
15202        ctxt->dictNames = 1;
15203    }
15204    if (options & XML_PARSE_NOCDATA) {
15205        ctxt->sax->cdataBlock = NULL;
15206        options -= XML_PARSE_NOCDATA;
15207	ctxt->options |= XML_PARSE_NOCDATA;
15208    }
15209    if (options & XML_PARSE_NSCLEAN) {
15210	ctxt->options |= XML_PARSE_NSCLEAN;
15211        options -= XML_PARSE_NSCLEAN;
15212    }
15213    if (options & XML_PARSE_NONET) {
15214	ctxt->options |= XML_PARSE_NONET;
15215        options -= XML_PARSE_NONET;
15216    }
15217    if (options & XML_PARSE_COMPACT) {
15218	ctxt->options |= XML_PARSE_COMPACT;
15219        options -= XML_PARSE_COMPACT;
15220    }
15221    if (options & XML_PARSE_OLD10) {
15222	ctxt->options |= XML_PARSE_OLD10;
15223        options -= XML_PARSE_OLD10;
15224    }
15225    if (options & XML_PARSE_NOBASEFIX) {
15226	ctxt->options |= XML_PARSE_NOBASEFIX;
15227        options -= XML_PARSE_NOBASEFIX;
15228    }
15229    if (options & XML_PARSE_HUGE) {
15230	ctxt->options |= XML_PARSE_HUGE;
15231        options -= XML_PARSE_HUGE;
15232        if (ctxt->dict != NULL)
15233            xmlDictSetLimit(ctxt->dict, 0);
15234    }
15235    if (options & XML_PARSE_OLDSAX) {
15236	ctxt->options |= XML_PARSE_OLDSAX;
15237        options -= XML_PARSE_OLDSAX;
15238    }
15239    if (options & XML_PARSE_IGNORE_ENC) {
15240	ctxt->options |= XML_PARSE_IGNORE_ENC;
15241        options -= XML_PARSE_IGNORE_ENC;
15242    }
15243    if (options & XML_PARSE_BIG_LINES) {
15244	ctxt->options |= XML_PARSE_BIG_LINES;
15245        options -= XML_PARSE_BIG_LINES;
15246    }
15247    ctxt->linenumbers = 1;
15248    return (options);
15249}
15250
15251/**
15252 * xmlCtxtUseOptions:
15253 * @ctxt: an XML parser context
15254 * @options:  a combination of xmlParserOption
15255 *
15256 * Applies the options to the parser context
15257 *
15258 * Returns 0 in case of success, the set of unknown or unimplemented options
15259 *         in case of error.
15260 */
15261int
15262xmlCtxtUseOptions(xmlParserCtxtPtr ctxt, int options)
15263{
15264   return(xmlCtxtUseOptionsInternal(ctxt, options, NULL));
15265}
15266
15267/**
15268 * xmlDoRead:
15269 * @ctxt:  an XML parser context
15270 * @URL:  the base URL to use for the document
15271 * @encoding:  the document encoding, or NULL
15272 * @options:  a combination of xmlParserOption
15273 * @reuse:  keep the context for reuse
15274 *
15275 * Common front-end for the xmlRead functions
15276 *
15277 * Returns the resulting document tree or NULL
15278 */
15279static xmlDocPtr
15280xmlDoRead(xmlParserCtxtPtr ctxt, const char *URL, const char *encoding,
15281          int options, int reuse)
15282{
15283    xmlDocPtr ret;
15284
15285    xmlCtxtUseOptionsInternal(ctxt, options, encoding);
15286    if (encoding != NULL) {
15287        xmlCharEncodingHandlerPtr hdlr;
15288
15289	hdlr = xmlFindCharEncodingHandler(encoding);
15290	if (hdlr != NULL)
15291	    xmlSwitchToEncoding(ctxt, hdlr);
15292    }
15293    if ((URL != NULL) && (ctxt->input != NULL) &&
15294        (ctxt->input->filename == NULL))
15295        ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL);
15296    xmlParseDocument(ctxt);
15297    if ((ctxt->wellFormed) || ctxt->recovery)
15298        ret = ctxt->myDoc;
15299    else {
15300        ret = NULL;
15301	if (ctxt->myDoc != NULL) {
15302	    xmlFreeDoc(ctxt->myDoc);
15303	}
15304    }
15305    ctxt->myDoc = NULL;
15306    if (!reuse) {
15307	xmlFreeParserCtxt(ctxt);
15308    }
15309
15310    return (ret);
15311}
15312
15313/**
15314 * xmlReadDoc:
15315 * @cur:  a pointer to a zero terminated string
15316 * @URL:  the base URL to use for the document
15317 * @encoding:  the document encoding, or NULL
15318 * @options:  a combination of xmlParserOption
15319 *
15320 * parse an XML in-memory document and build a tree.
15321 *
15322 * Returns the resulting document tree
15323 */
15324xmlDocPtr
15325xmlReadDoc(const xmlChar * cur, const char *URL, const char *encoding, int options)
15326{
15327    xmlParserCtxtPtr ctxt;
15328
15329    if (cur == NULL)
15330        return (NULL);
15331    xmlInitParser();
15332
15333    ctxt = xmlCreateDocParserCtxt(cur);
15334    if (ctxt == NULL)
15335        return (NULL);
15336    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15337}
15338
15339/**
15340 * xmlReadFile:
15341 * @filename:  a file or URL
15342 * @encoding:  the document encoding, or NULL
15343 * @options:  a combination of xmlParserOption
15344 *
15345 * parse an XML file from the filesystem or the network.
15346 *
15347 * Returns the resulting document tree
15348 */
15349xmlDocPtr
15350xmlReadFile(const char *filename, const char *encoding, int options)
15351{
15352    xmlParserCtxtPtr ctxt;
15353
15354    xmlInitParser();
15355    ctxt = xmlCreateURLParserCtxt(filename, options);
15356    if (ctxt == NULL)
15357        return (NULL);
15358    return (xmlDoRead(ctxt, NULL, encoding, options, 0));
15359}
15360
15361/**
15362 * xmlReadMemory:
15363 * @buffer:  a pointer to a char array
15364 * @size:  the size of the array
15365 * @URL:  the base URL to use for the document
15366 * @encoding:  the document encoding, or NULL
15367 * @options:  a combination of xmlParserOption
15368 *
15369 * parse an XML in-memory document and build a tree.
15370 *
15371 * Returns the resulting document tree
15372 */
15373xmlDocPtr
15374xmlReadMemory(const char *buffer, int size, const char *URL, const char *encoding, int options)
15375{
15376    xmlParserCtxtPtr ctxt;
15377
15378    xmlInitParser();
15379    ctxt = xmlCreateMemoryParserCtxt(buffer, size);
15380    if (ctxt == NULL)
15381        return (NULL);
15382    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15383}
15384
15385/**
15386 * xmlReadFd:
15387 * @fd:  an open file descriptor
15388 * @URL:  the base URL to use for the document
15389 * @encoding:  the document encoding, or NULL
15390 * @options:  a combination of xmlParserOption
15391 *
15392 * parse an XML from a file descriptor and build a tree.
15393 * NOTE that the file descriptor will not be closed when the
15394 *      reader is closed or reset.
15395 *
15396 * Returns the resulting document tree
15397 */
15398xmlDocPtr
15399xmlReadFd(int fd, const char *URL, const char *encoding, int options)
15400{
15401    xmlParserCtxtPtr ctxt;
15402    xmlParserInputBufferPtr input;
15403    xmlParserInputPtr stream;
15404
15405    if (fd < 0)
15406        return (NULL);
15407    xmlInitParser();
15408
15409    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
15410    if (input == NULL)
15411        return (NULL);
15412    input->closecallback = NULL;
15413    ctxt = xmlNewParserCtxt();
15414    if (ctxt == NULL) {
15415        xmlFreeParserInputBuffer(input);
15416        return (NULL);
15417    }
15418    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15419    if (stream == NULL) {
15420        xmlFreeParserInputBuffer(input);
15421	xmlFreeParserCtxt(ctxt);
15422        return (NULL);
15423    }
15424    inputPush(ctxt, stream);
15425    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15426}
15427
15428/**
15429 * xmlReadIO:
15430 * @ioread:  an I/O read function
15431 * @ioclose:  an I/O close function
15432 * @ioctx:  an I/O handler
15433 * @URL:  the base URL to use for the document
15434 * @encoding:  the document encoding, or NULL
15435 * @options:  a combination of xmlParserOption
15436 *
15437 * parse an XML document from I/O functions and source and build a tree.
15438 *
15439 * Returns the resulting document tree
15440 */
15441xmlDocPtr
15442xmlReadIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose,
15443          void *ioctx, const char *URL, const char *encoding, int options)
15444{
15445    xmlParserCtxtPtr ctxt;
15446    xmlParserInputBufferPtr input;
15447    xmlParserInputPtr stream;
15448
15449    if (ioread == NULL)
15450        return (NULL);
15451    xmlInitParser();
15452
15453    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
15454                                         XML_CHAR_ENCODING_NONE);
15455    if (input == NULL) {
15456        if (ioclose != NULL)
15457            ioclose(ioctx);
15458        return (NULL);
15459    }
15460    ctxt = xmlNewParserCtxt();
15461    if (ctxt == NULL) {
15462        xmlFreeParserInputBuffer(input);
15463        return (NULL);
15464    }
15465    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15466    if (stream == NULL) {
15467        xmlFreeParserInputBuffer(input);
15468	xmlFreeParserCtxt(ctxt);
15469        return (NULL);
15470    }
15471    inputPush(ctxt, stream);
15472    return (xmlDoRead(ctxt, URL, encoding, options, 0));
15473}
15474
15475/**
15476 * xmlCtxtReadDoc:
15477 * @ctxt:  an XML parser context
15478 * @cur:  a pointer to a zero terminated string
15479 * @URL:  the base URL to use for the document
15480 * @encoding:  the document encoding, or NULL
15481 * @options:  a combination of xmlParserOption
15482 *
15483 * parse an XML in-memory document and build a tree.
15484 * This reuses the existing @ctxt parser context
15485 *
15486 * Returns the resulting document tree
15487 */
15488xmlDocPtr
15489xmlCtxtReadDoc(xmlParserCtxtPtr ctxt, const xmlChar * cur,
15490               const char *URL, const char *encoding, int options)
15491{
15492    xmlParserInputPtr stream;
15493
15494    if (cur == NULL)
15495        return (NULL);
15496    if (ctxt == NULL)
15497        return (NULL);
15498    xmlInitParser();
15499
15500    xmlCtxtReset(ctxt);
15501
15502    stream = xmlNewStringInputStream(ctxt, cur);
15503    if (stream == NULL) {
15504        return (NULL);
15505    }
15506    inputPush(ctxt, stream);
15507    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15508}
15509
15510/**
15511 * xmlCtxtReadFile:
15512 * @ctxt:  an XML parser context
15513 * @filename:  a file or URL
15514 * @encoding:  the document encoding, or NULL
15515 * @options:  a combination of xmlParserOption
15516 *
15517 * parse an XML file from the filesystem or the network.
15518 * This reuses the existing @ctxt parser context
15519 *
15520 * Returns the resulting document tree
15521 */
15522xmlDocPtr
15523xmlCtxtReadFile(xmlParserCtxtPtr ctxt, const char *filename,
15524                const char *encoding, int options)
15525{
15526    xmlParserInputPtr stream;
15527
15528    if (filename == NULL)
15529        return (NULL);
15530    if (ctxt == NULL)
15531        return (NULL);
15532    xmlInitParser();
15533
15534    xmlCtxtReset(ctxt);
15535
15536    stream = xmlLoadExternalEntity(filename, NULL, ctxt);
15537    if (stream == NULL) {
15538        return (NULL);
15539    }
15540    inputPush(ctxt, stream);
15541    return (xmlDoRead(ctxt, NULL, encoding, options, 1));
15542}
15543
15544/**
15545 * xmlCtxtReadMemory:
15546 * @ctxt:  an XML parser context
15547 * @buffer:  a pointer to a char array
15548 * @size:  the size of the array
15549 * @URL:  the base URL to use for the document
15550 * @encoding:  the document encoding, or NULL
15551 * @options:  a combination of xmlParserOption
15552 *
15553 * parse an XML in-memory document and build a tree.
15554 * This reuses the existing @ctxt parser context
15555 *
15556 * Returns the resulting document tree
15557 */
15558xmlDocPtr
15559xmlCtxtReadMemory(xmlParserCtxtPtr ctxt, const char *buffer, int size,
15560                  const char *URL, const char *encoding, int options)
15561{
15562    xmlParserInputBufferPtr input;
15563    xmlParserInputPtr stream;
15564
15565    if (ctxt == NULL)
15566        return (NULL);
15567    if (buffer == NULL)
15568        return (NULL);
15569    xmlInitParser();
15570
15571    xmlCtxtReset(ctxt);
15572
15573    input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE);
15574    if (input == NULL) {
15575	return(NULL);
15576    }
15577
15578    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15579    if (stream == NULL) {
15580	xmlFreeParserInputBuffer(input);
15581	return(NULL);
15582    }
15583
15584    inputPush(ctxt, stream);
15585    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15586}
15587
15588/**
15589 * xmlCtxtReadFd:
15590 * @ctxt:  an XML parser context
15591 * @fd:  an open file descriptor
15592 * @URL:  the base URL to use for the document
15593 * @encoding:  the document encoding, or NULL
15594 * @options:  a combination of xmlParserOption
15595 *
15596 * parse an XML from a file descriptor and build a tree.
15597 * This reuses the existing @ctxt parser context
15598 * NOTE that the file descriptor will not be closed when the
15599 *      reader is closed or reset.
15600 *
15601 * Returns the resulting document tree
15602 */
15603xmlDocPtr
15604xmlCtxtReadFd(xmlParserCtxtPtr ctxt, int fd,
15605              const char *URL, const char *encoding, int options)
15606{
15607    xmlParserInputBufferPtr input;
15608    xmlParserInputPtr stream;
15609
15610    if (fd < 0)
15611        return (NULL);
15612    if (ctxt == NULL)
15613        return (NULL);
15614    xmlInitParser();
15615
15616    xmlCtxtReset(ctxt);
15617
15618
15619    input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE);
15620    if (input == NULL)
15621        return (NULL);
15622    input->closecallback = NULL;
15623    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15624    if (stream == NULL) {
15625        xmlFreeParserInputBuffer(input);
15626        return (NULL);
15627    }
15628    inputPush(ctxt, stream);
15629    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15630}
15631
15632/**
15633 * xmlCtxtReadIO:
15634 * @ctxt:  an XML parser context
15635 * @ioread:  an I/O read function
15636 * @ioclose:  an I/O close function
15637 * @ioctx:  an I/O handler
15638 * @URL:  the base URL to use for the document
15639 * @encoding:  the document encoding, or NULL
15640 * @options:  a combination of xmlParserOption
15641 *
15642 * parse an XML document from I/O functions and source and build a tree.
15643 * This reuses the existing @ctxt parser context
15644 *
15645 * Returns the resulting document tree
15646 */
15647xmlDocPtr
15648xmlCtxtReadIO(xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread,
15649              xmlInputCloseCallback ioclose, void *ioctx,
15650	      const char *URL,
15651              const char *encoding, int options)
15652{
15653    xmlParserInputBufferPtr input;
15654    xmlParserInputPtr stream;
15655
15656    if (ioread == NULL)
15657        return (NULL);
15658    if (ctxt == NULL)
15659        return (NULL);
15660    xmlInitParser();
15661
15662    xmlCtxtReset(ctxt);
15663
15664    input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx,
15665                                         XML_CHAR_ENCODING_NONE);
15666    if (input == NULL) {
15667        if (ioclose != NULL)
15668            ioclose(ioctx);
15669        return (NULL);
15670    }
15671    stream = xmlNewIOInputStream(ctxt, input, XML_CHAR_ENCODING_NONE);
15672    if (stream == NULL) {
15673        xmlFreeParserInputBuffer(input);
15674        return (NULL);
15675    }
15676    inputPush(ctxt, stream);
15677    return (xmlDoRead(ctxt, URL, encoding, options, 1));
15678}
15679
15680#define bottom_parser
15681#include "elfgcchack.h"
15682